diff --git a/api.hyungi.net/config/middleware.js b/api.hyungi.net/config/middleware.js index 752761e..83b8eb6 100644 --- a/api.hyungi.net/config/middleware.js +++ b/api.hyungi.net/config/middleware.js @@ -57,14 +57,19 @@ function setupMiddlewares(app) { // 일반 API 요청 제한 const apiLimiter = rateLimit({ windowMs: 15 * 60 * 1000, // 15분 - max: 200, // IP당 최대 200 요청 + max: 1000, // IP당 최대 1000 요청 (일괄 처리 지원) message: { success: false, error: '너무 많은 요청입니다. 잠시 후 다시 시도해주세요.', code: 'RATE_LIMIT_EXCEEDED' }, standardHeaders: true, - legacyHeaders: false + legacyHeaders: false, + // 인증된 사용자는 더 많은 요청 허용 + skip: (req) => { + // Authorization 헤더가 있으면 Rate Limit 완화 + return req.headers.authorization && req.headers.authorization.startsWith('Bearer '); + } }); // 로그인 시도 제한 (브루트포스 방지) diff --git a/api.hyungi.net/config/routes.js b/api.hyungi.net/config/routes.js index 44200ef..f5cdb88 100644 --- a/api.hyungi.net/config/routes.js +++ b/api.hyungi.net/config/routes.js @@ -107,7 +107,10 @@ function setupRoutes(app) { '/api/setup/migrate-existing-data', '/api/setup/check-data-status', '/api/monthly-status/calendar', - '/api/monthly-status/daily-details' + '/api/monthly-status/daily-details', + '/api/migrate-work-type-id', // 임시 마이그레이션 - 실행 후 삭제! + '/api/diagnose-work-type-id', // 임시 진단 - 실행 후 삭제! + '/api/test-analysis' // 임시 분석 테스트 - 실행 후 삭제! ]; // 인증 미들웨어 - 공개 경로를 제외한 모든 API (rate limiter보다 먼저 실행) diff --git a/api.hyungi.net/controllers/attendanceController.js b/api.hyungi.net/controllers/attendanceController.js index 793fb97..124a4cd 100644 --- a/api.hyungi.net/controllers/attendanceController.js +++ b/api.hyungi.net/controllers/attendanceController.js @@ -38,6 +38,20 @@ const getDailyAttendanceRecords = asyncHandler(async (req, res) => { }); }); +/** + * 기간별 근태 기록 조회 (월별 조회용) + */ +const getAttendanceRecordsByRange = asyncHandler(async (req, res) => { + const { start_date, end_date, worker_id } = req.query; + const data = await attendanceService.getAttendanceRecordsByRangeService(start_date, end_date, worker_id); + + res.json({ + success: true, + data, + message: '근태 기록을 성공적으로 조회했습니다' + }); +}); + /** * 근태 기록 생성/업데이트 */ @@ -185,6 +199,7 @@ const saveCheckins = asyncHandler(async (req, res) => { module.exports = { getDailyAttendanceStatus, getDailyAttendanceRecords, + getAttendanceRecordsByRange, upsertAttendanceRecord, processVacation, approveOvertime, diff --git a/api.hyungi.net/controllers/patrolController.js b/api.hyungi.net/controllers/patrolController.js index 3a2c21f..e810a9c 100644 --- a/api.hyungi.net/controllers/patrolController.js +++ b/api.hyungi.net/controllers/patrolController.js @@ -289,6 +289,507 @@ const PatrolController = { console.error('작업장별 점검 현황 조회 오류:', error); res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); } + }, + + // ==================== 작업장 상세 정보 (통합) ==================== + + // 작업장 상세 정보 조회 (시설물, 안전신고, 부적합, 출입, TBM) + getWorkplaceDetail: async (req, res) => { + try { + const { workplaceId } = req.params; + const { date } = req.query; // 기본: 오늘 + const targetDate = date || new Date().toISOString().slice(0, 10); + const { getDb } = require('../dbPool'); + const db = await getDb(); + + // 1. 작업장 기본 정보 (카테고리 지도 이미지 포함) + const [workplaceInfo] = await db.query(` + SELECT w.*, wc.category_name, wc.layout_image as category_layout_image + FROM workplaces w + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + WHERE w.workplace_id = ? + `, [workplaceId]); + + if (!workplaceInfo.length) { + return res.status(404).json({ success: false, message: '작업장을 찾을 수 없습니다.' }); + } + + // 2. 설비 현황 (해당 작업장 - 원래 위치 또는 현재 위치) + let equipments = []; + try { + const [eqResult] = await db.query(` + SELECT e.equipment_id, e.equipment_name, e.equipment_code, e.equipment_type, + e.status, e.notes, e.workplace_id, + e.map_x_percent, e.map_y_percent, e.map_width_percent, e.map_height_percent, + e.is_temporarily_moved, e.current_workplace_id, + e.current_map_x_percent, e.current_map_y_percent, + e.current_map_width_percent, e.current_map_height_percent, + e.moved_at, + ow.workplace_name as original_workplace_name, + cw.workplace_name as current_workplace_name, + CASE + WHEN e.status IN ('maintenance', 'repair_needed', 'repair_external') THEN 1 + WHEN e.is_temporarily_moved = 1 THEN 1 + ELSE 0 + END as needs_attention + FROM equipments e + LEFT JOIN workplaces ow ON e.workplace_id = ow.workplace_id + LEFT JOIN workplaces cw ON e.current_workplace_id = cw.workplace_id + WHERE (e.workplace_id = ? OR e.current_workplace_id = ?) + AND e.status != 'inactive' + ORDER BY needs_attention DESC, e.equipment_name + `, [workplaceId, workplaceId]); + equipments = eqResult; + } catch (eqError) { + console.log('설비 조회 스킵 (테이블 없음 또는 오류):', eqError.message); + } + + // 3. 수리 요청 현황 (미완료) - 테이블 존재 여부 확인 후 조회 + let repairRequests = []; + try { + const [repairResult] = await db.query(` + SELECT er.request_id, er.request_date, er.repair_category, er.description, + er.priority, er.status, e.equipment_name, e.equipment_code + FROM equipment_repair_requests er + JOIN equipments e ON er.equipment_id = e.equipment_id + WHERE e.workplace_id = ? AND er.status NOT IN ('completed', 'cancelled') + ORDER BY + CASE er.priority WHEN 'emergency' THEN 1 WHEN 'high' THEN 2 WHEN 'normal' THEN 3 ELSE 4 END, + er.request_date DESC + LIMIT 10 + `, [workplaceId]); + repairRequests = repairResult; + } catch (repairError) { + console.log('수리요청 조회 스킵 (테이블 없음 또는 오류):', repairError.message); + } + + // 4. 안전 신고 및 부적합 사항 - 테이블 존재 여부 확인 후 조회 + let workIssues = []; + try { + const [issueResult] = await db.query(` + SELECT wi.report_id, wi.issue_type, wi.title, wi.description, + wi.status, wi.severity, wi.created_at, wi.resolved_at, + wic.category_name, wic.issue_type as category_type, + u.name as reporter_name + FROM work_issue_reports wi + LEFT JOIN issue_report_categories wic ON wi.category_id = wic.category_id + LEFT JOIN users u ON wi.reporter_id = u.user_id + WHERE wi.workplace_id = ? + AND wi.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY) + ORDER BY wi.created_at DESC + LIMIT 20 + `, [workplaceId]); + workIssues = issueResult; + } catch (issueError) { + console.log('신고 조회 스킵 (테이블 없음 또는 오류):', issueError.message); + } + + // 5. 오늘의 출입 기록 (해당 공장 카테고리) + const categoryId = workplaceInfo[0].category_id; + let visitRecords = []; + try { + const [visitResult] = await db.query(` + SELECT vr.request_id, vr.visitor_name, vr.visitor_company, vr.visit_purpose, + vr.visit_date, vr.visit_time_from, vr.visit_time_to, vr.status, + vr.vehicle_number, vr.companion_count, + vp.purpose_name, u.name as requester_name + FROM workplace_visit_requests vr + LEFT JOIN visit_purpose_types vp ON vr.purpose_id = vp.purpose_id + LEFT JOIN users u ON vr.requester_id = u.user_id + WHERE vr.category_id = ? AND vr.visit_date = ? AND vr.status = 'approved' + ORDER BY vr.visit_time_from + `, [categoryId, targetDate]); + visitRecords = visitResult; + } catch (visitError) { + console.log('출입기록 조회 스킵 (테이블 없음 또는 오류):', visitError.message); + } + + // 6. 오늘의 TBM 세션 (해당 공장 카테고리) + let tbmSessions = []; + try { + const [tbmResult] = await db.query(` + SELECT ts.session_id, ts.session_date, ts.work_location, ts.status, + ts.work_content, ts.safety_measures, ts.team_size, + t.task_name, wt.name as work_type_name, + u.name as leader_name, w.worker_name as leader_worker_name + FROM tbm_sessions ts + LEFT JOIN tasks t ON ts.task_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN users u ON ts.leader_id = u.user_id + LEFT JOIN workers w ON ts.leader_worker_id = w.worker_id + WHERE ts.category_id = ? AND ts.session_date = ? + ORDER BY ts.created_at DESC + `, [categoryId, targetDate]); + tbmSessions = tbmResult; + } catch (tbmError) { + console.log('TBM 조회 스킵 (테이블 없음 또는 오류):', tbmError.message); + } + + // 7. TBM 팀원 정보 (세션별) + let tbmWithTeams = []; + try { + tbmWithTeams = await Promise.all(tbmSessions.map(async (session) => { + const [team] = await db.query(` + SELECT tta.assignment_id, w.worker_name, w.occupation, + tta.attendance_status, tta.signature_image + FROM tbm_team_assignments tta + JOIN workers w ON tta.worker_id = w.worker_id + WHERE tta.session_id = ? + ORDER BY w.worker_name + `, [session.session_id]); + return { ...session, team }; + })); + } catch (teamError) { + console.log('TBM 팀원 조회 스킵:', teamError.message); + tbmWithTeams = tbmSessions.map(s => ({ ...s, team: [] })); + } + + // 8. 최근 순회점검 결과 (해당 작업장) + let recentPatrol = []; + try { + const [patrolResult] = await db.query(` + SELECT ps.session_id, ps.patrol_date, ps.patrol_time, ps.status, + ps.notes, u.name as inspector_name, + (SELECT COUNT(*) FROM patrol_check_records pcr + WHERE pcr.session_id = ps.session_id AND pcr.workplace_id = ?) as checked_count, + (SELECT COUNT(*) FROM patrol_check_records pcr + WHERE pcr.session_id = ps.session_id AND pcr.workplace_id = ? + AND pcr.check_result IN ('warning', 'bad')) as issue_count + FROM daily_patrol_sessions ps + LEFT JOIN users u ON ps.inspector_id = u.user_id + WHERE ps.category_id = ? AND ps.patrol_date >= DATE_SUB(NOW(), INTERVAL 7 DAY) + ORDER BY ps.patrol_date DESC, ps.patrol_time DESC + LIMIT 5 + `, [workplaceId, workplaceId, categoryId]); + recentPatrol = patrolResult; + } catch (patrolError) { + console.log('순회점검 조회 스킵 (테이블 없음 또는 오류):', patrolError.message); + } + + res.json({ + success: true, + data: { + workplace: workplaceInfo[0], + equipments: equipments, + repairRequests: repairRequests, + workIssues: { + safety: workIssues.filter(i => i.category_type === 'safety'), + nonconformity: workIssues.filter(i => i.category_type === 'nonconformity'), + all: workIssues + }, + visitRecords: visitRecords, + tbmSessions: tbmWithTeams, + recentPatrol: recentPatrol, + summary: { + equipmentCount: equipments.length, + needsAttention: equipments.filter(e => e.needs_attention).length, + pendingRepairs: repairRequests.length, + openIssues: workIssues.filter(i => i.status !== 'closed').length, + todayVisitors: visitRecords.reduce((sum, v) => sum + 1 + (v.companion_count || 0), 0), + todayTbmSessions: tbmSessions.length + } + } + }); + } catch (error) { + console.error('작업장 상세 정보 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // ==================== 구역 내 등록 물품/시설물 ==================== + + // 구역 내 물품/시설물 목록 조회 + getZoneItems: async (req, res) => { + try { + const { workplaceId } = req.params; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + // 테이블이 없으면 생성 + await db.query(` + CREATE TABLE IF NOT EXISTS workplace_zone_items ( + item_id INT AUTO_INCREMENT PRIMARY KEY, + workplace_id INT NOT NULL, + item_name VARCHAR(200) NOT NULL COMMENT '물품/시설물 명칭', + item_type VARCHAR(50) DEFAULT 'general' COMMENT '유형 (heavy_equipment, hazardous, storage, general 등)', + description TEXT COMMENT '상세 설명', + x_percent DECIMAL(5,2) NOT NULL COMMENT '영역 시작 X 좌표 (%)', + y_percent DECIMAL(5,2) NOT NULL COMMENT '영역 시작 Y 좌표 (%)', + width_percent DECIMAL(5,2) DEFAULT 10 COMMENT '영역 너비 (%)', + height_percent DECIMAL(5,2) DEFAULT 10 COMMENT '영역 높이 (%)', + color VARCHAR(20) DEFAULT '#3b82f6' COMMENT '표시 색상', + warning_level VARCHAR(20) DEFAULT 'normal' COMMENT '주의 수준 (normal, caution, danger)', + quantity INT DEFAULT 1 COMMENT '수량', + unit VARCHAR(20) DEFAULT '개' COMMENT '단위', + weight_kg DECIMAL(10,2) DEFAULT NULL COMMENT '중량 (kg)', + is_active BOOLEAN DEFAULT TRUE, + created_by INT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX idx_workplace (workplace_id), + INDEX idx_type (item_type) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='구역 내 등록 물품/시설물' + `); + + // 새 컬럼 추가 (없으면) + try { + await db.query(`ALTER TABLE workplace_zone_items ADD COLUMN project_type VARCHAR(20) DEFAULT 'non_project'`); + } catch (e) { /* 이미 존재 */ } + try { + await db.query(`ALTER TABLE workplace_zone_items ADD COLUMN project_id INT NULL`); + } catch (e) { /* 이미 존재 */ } + + const [items] = await db.query(` + SELECT zi.*, p.project_name + FROM workplace_zone_items zi + LEFT JOIN projects p ON zi.project_id = p.project_id + WHERE zi.workplace_id = ? AND zi.is_active = TRUE + ORDER BY zi.warning_level DESC, zi.item_name + `, [workplaceId]); + + // 사진 테이블 존재 확인 및 사진 조회 + try { + for (const item of items) { + const [photos] = await db.query(` + SELECT photo_id, photo_url, created_at + FROM zone_item_photos + WHERE item_id = ? + ORDER BY created_at DESC + `, [item.item_id]); + item.photos = photos || []; + } + } catch (e) { + // 사진 테이블이 없으면 무시 + items.forEach(item => item.photos = []); + } + + res.json({ success: true, data: items }); + } catch (error) { + console.error('구역 물품 목록 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 등록 + createZoneItem: async (req, res) => { + try { + const { workplaceId } = req.params; + const { item_name, item_type, description, x_percent, y_percent, width_percent, height_percent, + color, warning_level, project_type, project_id } = req.body; + const createdBy = req.user?.user_id; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + if (!item_name || x_percent === undefined || y_percent === undefined) { + return res.status(400).json({ success: false, message: '필수 정보가 누락되었습니다.' }); + } + + // 테이블에 새 컬럼 추가 (없으면) + try { + await db.query(`ALTER TABLE workplace_zone_items ADD COLUMN project_type VARCHAR(20) DEFAULT 'non_project'`); + } catch (e) { /* 이미 존재 */ } + try { + await db.query(`ALTER TABLE workplace_zone_items ADD COLUMN project_id INT NULL`); + } catch (e) { /* 이미 존재 */ } + + const [result] = await db.query(` + INSERT INTO workplace_zone_items + (workplace_id, item_name, item_type, description, x_percent, y_percent, width_percent, height_percent, + color, warning_level, project_type, project_id, created_by) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `, [workplaceId, item_name, item_type || 'working', description, x_percent, y_percent, + width_percent || 5, height_percent || 5, color || '#3b82f6', warning_level || 'good', + project_type || 'non_project', project_id || null, createdBy]); + + const newItemId = result.insertId; + + // 등록 이력 저장 + try { + await db.query(` + INSERT INTO zone_item_history (item_id, action_type, new_values, changed_by) + VALUES (?, 'created', ?, ?) + `, [newItemId, JSON.stringify({ item_name, item_type, warning_level, project_type }), createdBy]); + } catch (e) { /* 테이블 없으면 무시 */ } + + res.json({ + success: true, + data: { item_id: newItemId }, + message: '현황이 등록되었습니다.' + }); + } catch (error) { + console.error('구역 현황 등록 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 수정 + updateZoneItem: async (req, res) => { + try { + const { itemId } = req.params; + const { item_name, item_type, description, x_percent, y_percent, width_percent, height_percent, + color, warning_level, project_type, project_id } = req.body; + const userId = req.user?.user_id; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + // 이력 테이블 생성 (없으면) + await db.query(` + CREATE TABLE IF NOT EXISTS zone_item_history ( + history_id INT AUTO_INCREMENT PRIMARY KEY, + item_id INT NOT NULL, + action_type VARCHAR(20) NOT NULL COMMENT 'created, updated, deleted', + changed_fields TEXT COMMENT '변경된 필드 JSON', + old_values TEXT COMMENT '이전 값 JSON', + new_values TEXT COMMENT '새 값 JSON', + changed_by INT, + changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX idx_item (item_id), + INDEX idx_date (changed_at) + ) + `); + + // 기존 데이터 조회 (이력용) + const [oldData] = await db.query(`SELECT * FROM workplace_zone_items WHERE item_id = ?`, [itemId]); + const oldItem = oldData[0]; + + // 업데이트 + await db.query(` + UPDATE workplace_zone_items SET + item_name = COALESCE(?, item_name), + item_type = COALESCE(?, item_type), + description = ?, + x_percent = COALESCE(?, x_percent), + y_percent = COALESCE(?, y_percent), + width_percent = COALESCE(?, width_percent), + height_percent = COALESCE(?, height_percent), + color = COALESCE(?, color), + warning_level = COALESCE(?, warning_level), + project_type = COALESCE(?, project_type), + project_id = ? + WHERE item_id = ? + `, [item_name, item_type, description, x_percent, y_percent, width_percent, height_percent, + color, warning_level, project_type, project_id, itemId]); + + // 변경 이력 저장 + if (oldItem) { + const changedFields = []; + const oldValues = {}; + const newValues = {}; + + const fieldMap = { item_name, item_type, description, warning_level, project_type, project_id }; + for (const [key, newVal] of Object.entries(fieldMap)) { + if (newVal !== undefined && oldItem[key] !== newVal) { + changedFields.push(key); + oldValues[key] = oldItem[key]; + newValues[key] = newVal; + } + } + + if (changedFields.length > 0) { + await db.query(` + INSERT INTO zone_item_history (item_id, action_type, changed_fields, old_values, new_values, changed_by) + VALUES (?, 'updated', ?, ?, ?, ?) + `, [itemId, JSON.stringify(changedFields), JSON.stringify(oldValues), JSON.stringify(newValues), userId]); + } + } + + res.json({ success: true, message: '현황이 수정되었습니다.' }); + } catch (error) { + console.error('구역 현황 수정 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 사진 업로드 + uploadZoneItemPhoto: async (req, res) => { + try { + const { item_id } = req.body; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + if (!req.file) { + return res.status(400).json({ success: false, message: '파일이 없습니다.' }); + } + + // 사진 테이블 생성 (없으면) + await db.query(` + CREATE TABLE IF NOT EXISTS zone_item_photos ( + photo_id INT AUTO_INCREMENT PRIMARY KEY, + item_id INT NOT NULL, + photo_url VARCHAR(500) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX idx_item_id (item_id) + ) + `); + + const photoUrl = `/uploads/${req.file.filename}`; + const [result] = await db.query( + `INSERT INTO zone_item_photos (item_id, photo_url) VALUES (?, ?)`, + [item_id, photoUrl] + ); + + res.json({ + success: true, + data: { photo_id: result.insertId, photo_url: photoUrl }, + message: '사진이 업로드되었습니다.' + }); + } catch (error) { + console.error('사진 업로드 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 삭제 + deleteZoneItem: async (req, res) => { + try { + const { itemId } = req.params; + const userId = req.user?.user_id; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + // 기존 데이터 조회 (이력용) + const [oldData] = await db.query(`SELECT * FROM workplace_zone_items WHERE item_id = ?`, [itemId]); + const oldItem = oldData[0]; + + // 소프트 삭제 + await db.query(`UPDATE workplace_zone_items SET is_active = FALSE WHERE item_id = ?`, [itemId]); + + // 삭제 이력 저장 + if (oldItem) { + await db.query(` + INSERT INTO zone_item_history (item_id, action_type, old_values, changed_by) + VALUES (?, 'deleted', ?, ?) + `, [itemId, JSON.stringify({ item_name: oldItem.item_name, item_type: oldItem.item_type }), userId]); + } + + res.json({ success: true, message: '현황이 삭제되었습니다.' }); + } catch (error) { + console.error('구역 현황 삭제 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 이력 조회 + getZoneItemHistory: async (req, res) => { + try { + const { itemId } = req.params; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + const [history] = await db.query(` + SELECT h.*, u.full_name as changed_by_name + FROM zone_item_history h + LEFT JOIN users u ON h.changed_by = u.user_id + WHERE h.item_id = ? + ORDER BY h.changed_at DESC + LIMIT 50 + `, [itemId]); + + res.json({ success: true, data: history }); + } catch (error) { + console.error('현황 이력 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } } }; diff --git a/api.hyungi.net/controllers/taskController.js b/api.hyungi.net/controllers/taskController.js index fca45c3..d9cdc30 100644 --- a/api.hyungi.net/controllers/taskController.js +++ b/api.hyungi.net/controllers/taskController.js @@ -39,10 +39,18 @@ exports.createTask = asyncHandler(async (req, res) => { }); /** - * 전체 작업 조회 + * 전체 작업 조회 (work_type_id 필터 지원) */ exports.getAllTasks = asyncHandler(async (req, res) => { - const rows = await taskModel.getAllTasks(); + const { work_type_id } = req.query; + + let rows; + if (work_type_id) { + // 특정 공정의 활성 작업만 조회 + rows = await taskModel.getTasksByWorkType(work_type_id); + } else { + rows = await taskModel.getAllTasks(); + } res.json({ success: true, diff --git a/api.hyungi.net/controllers/vacationBalanceController.js b/api.hyungi.net/controllers/vacationBalanceController.js index 6983293..4eeaa3a 100644 --- a/api.hyungi.net/controllers/vacationBalanceController.js +++ b/api.hyungi.net/controllers/vacationBalanceController.js @@ -322,6 +322,70 @@ const vacationBalanceController = { } }, + /** + * 휴가 잔액 일괄 저장 (upsert) + * POST /api/vacation-balances/bulk-upsert + */ + async bulkUpsert(req, res) { + try { + const { balances } = req.body; + const created_by = req.user.user_id; + + if (!balances || !Array.isArray(balances) || balances.length === 0) { + return res.status(400).json({ + success: false, + message: '저장할 데이터가 없습니다' + }); + } + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + let successCount = 0; + let errorCount = 0; + + for (const balance of balances) { + const { worker_id, vacation_type_id, year, total_days, notes } = balance; + + if (!worker_id || !vacation_type_id || !year || total_days === undefined) { + errorCount++; + continue; + } + + try { + // Upsert 쿼리 + const query = ` + INSERT INTO vacation_balance_details + (worker_id, vacation_type_id, year, total_days, used_days, notes, created_by) + VALUES (?, ?, ?, ?, 0, ?, ?) + ON DUPLICATE KEY UPDATE + total_days = VALUES(total_days), + notes = VALUES(notes), + updated_at = NOW() + `; + + await db.query(query, [worker_id, vacation_type_id, year, total_days, notes || null, created_by]); + successCount++; + } catch (err) { + console.error('휴가 잔액 저장 오류:', err); + errorCount++; + } + } + + res.json({ + success: true, + message: `${successCount}건 저장 완료${errorCount > 0 ? `, ${errorCount}건 실패` : ''}`, + data: { successCount, errorCount } + }); + } catch (error) { + console.error('bulkUpsert 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + /** * 작업자의 사용 가능한 휴가 일수 조회 * GET /api/vacation-balances/worker/:workerId/year/:year/available diff --git a/api.hyungi.net/db/migrations/20260205_fix_work_type_id_data.js b/api.hyungi.net/db/migrations/20260205_fix_work_type_id_data.js new file mode 100644 index 0000000..53c520a --- /dev/null +++ b/api.hyungi.net/db/migrations/20260205_fix_work_type_id_data.js @@ -0,0 +1,105 @@ +/** + * 마이그레이션: TBM 기반 작업보고서의 work_type_id를 task_id로 수정 + * + * 문제: TBM에서 작업보고서 생성 시 work_type_id(공정 ID)가 저장됨 + * 해결: tbm_team_assignments 테이블의 task_id로 업데이트 + * + * 실행: node db/migrations/20260205_fix_work_type_id_data.js + */ + +const { getDb } = require('../../dbPool'); + +async function migrate() { + const db = await getDb(); + + console.log('🔄 TBM 기반 작업보고서 work_type_id 수정 시작...\n'); + + try { + // 1. 수정 대상 확인 (TBM 기반이면서 work_type_id가 task_id와 다른 경우) + const [checkResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id as current_work_type_id, + ta.task_id as correct_task_id, + ta.work_type_id as tbm_work_type_id, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + INNER JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + ORDER BY dwr.report_date DESC + `); + + console.log(`📊 수정 대상: ${checkResult.length}개 레코드\n`); + + if (checkResult.length === 0) { + console.log('✅ 수정할 데이터가 없습니다.'); + return; + } + + // 수정 대상 샘플 출력 + console.log('📋 수정 대상 샘플 (최대 10개):'); + console.log('─'.repeat(80)); + checkResult.slice(0, 10).forEach(row => { + console.log(` ID: ${row.id} | ${row.worker_name} | ${row.report_date}`); + console.log(` 현재 work_type_id: ${row.current_work_type_id} → 올바른 task_id: ${row.correct_task_id}`); + }); + if (checkResult.length > 10) { + console.log(` ... 외 ${checkResult.length - 10}개`); + } + console.log('─'.repeat(80)); + + // 2. 업데이트 실행 + const [updateResult] = await db.query(` + UPDATE daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + SET dwr.work_type_id = ta.task_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + `); + + console.log(`\n✅ 업데이트 완료: ${updateResult.affectedRows}개 레코드 수정됨`); + + // 3. 수정 결과 확인 + const [verifyResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id, + ta.task_id, + t.task_name, + wt.name as work_type_name + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + WHERE dwr.tbm_assignment_id IS NOT NULL + LIMIT 5 + `); + + console.log('\n📋 수정 후 샘플 확인:'); + console.log('─'.repeat(80)); + verifyResult.forEach(row => { + console.log(` ID: ${row.id} | work_type_id: ${row.work_type_id} | task: ${row.task_name || 'N/A'} | 공정: ${row.work_type_name || 'N/A'}`); + }); + console.log('─'.repeat(80)); + + } catch (error) { + console.error('❌ 마이그레이션 실패:', error.message); + throw error; + } +} + +// 실행 +migrate() + .then(() => { + console.log('\n🎉 마이그레이션 완료!'); + process.exit(0); + }) + .catch(err => { + console.error('\n💥 마이그레이션 실패:', err); + process.exit(1); + }); diff --git a/api.hyungi.net/db/migrations/20260206_migrate_error_types_final.sql b/api.hyungi.net/db/migrations/20260206_migrate_error_types_final.sql new file mode 100644 index 0000000..3082a30 --- /dev/null +++ b/api.hyungi.net/db/migrations/20260206_migrate_error_types_final.sql @@ -0,0 +1,56 @@ +-- ============================================ +-- error_types → issue_report_items 마이그레이션 +-- 실행 전 반드시 백업하세요! +-- ============================================ + +-- STEP 1: 현재 상태 확인 +-- ============================================ +SELECT 'Before Migration' as status; +SELECT error_type_id, COUNT(*) as cnt FROM daily_work_reports WHERE error_type_id IS NOT NULL GROUP BY error_type_id; + + +-- STEP 2: 매핑 업데이트 실행 +-- ============================================ +-- 주의: 순서가 중요! (충돌 방지를 위해 큰 숫자부터) + +-- 6 (검사불량) → 14 (치수 검사 누락) +UPDATE daily_work_reports SET error_type_id = 14 WHERE error_type_id = 6; + +-- 5 (설비고장) → 38 (기계 고장) +UPDATE daily_work_reports SET error_type_id = 38 WHERE error_type_id = 5; + +-- 4 (작업불량) → 43 (NDE 불합격) +UPDATE daily_work_reports SET error_type_id = 43 WHERE error_type_id = 4; + +-- 3 (입고지연) → 1 (배관 자재 미입고) - 이미 1이므로 충돌 가능, 임시값 사용 +UPDATE daily_work_reports SET error_type_id = 99991 WHERE error_type_id = 3; + +-- 2 (외주작업 불량) → 10 (외관 불량) +UPDATE daily_work_reports SET error_type_id = 10 WHERE error_type_id = 2; + +-- 1 (설계미스) → 6 (도면 치수 오류) - 6은 이미 업데이트됨 +UPDATE daily_work_reports SET error_type_id = 6 WHERE error_type_id = 1; + +-- 임시값 복원: 99991 → 1 +UPDATE daily_work_reports SET error_type_id = 1 WHERE error_type_id = 99991; + + +-- STEP 3: 마이그레이션 결과 확인 +-- ============================================ +SELECT 'After Migration' as status; +SELECT + dwr.error_type_id, + iri.item_name, + irc.category_name, + COUNT(*) as cnt +FROM daily_work_reports dwr +LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id +LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id +WHERE dwr.error_type_id IS NOT NULL +GROUP BY dwr.error_type_id, iri.item_name, irc.category_name; + + +-- STEP 4: error_types 테이블 삭제 (선택사항) +-- ============================================ +-- 마이그레이션 확인 후 주석 해제하여 실행 +-- DROP TABLE IF EXISTS error_types; diff --git a/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.js b/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.js new file mode 100644 index 0000000..18659f1 --- /dev/null +++ b/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.js @@ -0,0 +1,112 @@ +/** + * 마이그레이션: error_types에서 issue_report_items로 전환 + * + * 기존 daily_work_reports.error_type_id가 error_types.id를 참조하던 것을 + * issue_report_items.item_id를 참조하도록 변경 + * + * 기존 error_types 데이터: + * id=1: 설계미스 + * id=2: 외주작업 불량 + * id=3: 입고지연 + * + * 새 issue_report_categories 데이터: + * category_id=1: 자재누락 (nonconformity) + * category_id=2: 설계미스 (nonconformity) + * category_id=3: 입고불량 (nonconformity) + * + * 매핑 전략: + * - error_types.id=1 (설계미스) → issue_report_items에서 '설계미스' 카테고리의 첫 번째 항목 + * - error_types.id=2 (외주작업 불량) → issue_report_items에서 '입고불량' 카테고리의 '외관 불량' 항목 + * - error_types.id=3 (입고지연) → issue_report_items에서 '자재누락' 카테고리의 첫 번째 항목 + */ + +exports.up = async function(knex) { + console.log('=== error_type_id 마이그레이션 시작 ==='); + + // 1. 기존 error_types 데이터와 새 issue_report_items 매핑 테이블 조회 + const [categories] = await knex.raw(` + SELECT category_id, category_name + FROM issue_report_categories + WHERE category_type = 'nonconformity' + `); + console.log('부적합 카테고리:', categories); + + const [items] = await knex.raw(` + SELECT iri.item_id, iri.item_name, iri.category_id, irc.category_name + FROM issue_report_items iri + JOIN issue_report_categories irc ON iri.category_id = irc.category_id + WHERE irc.category_type = 'nonconformity' + ORDER BY iri.category_id, iri.display_order + `); + console.log('부적합 항목:', items); + + // 2. 매핑 정의 (기존 error_type_id → 새 issue_report_items.item_id) + // 설계미스 카테고리 찾기 + const designMissCategory = categories.find(c => c.category_name === '설계미스'); + const incomingDefectCategory = categories.find(c => c.category_name === '입고불량'); + const materialShortageCategory = categories.find(c => c.category_name === '자재누락'); + + // 각 카테고리의 첫 번째 항목 찾기 + const designMissItem = items.find(i => i.category_id === designMissCategory?.category_id); + const incomingDefectItem = items.find(i => i.category_id === incomingDefectCategory?.category_id); + const materialShortageItem = items.find(i => i.category_id === materialShortageCategory?.category_id); + + console.log('매핑 결과:'); + console.log(' - 설계미스(1) → item_id:', designMissItem?.item_id); + console.log(' - 외주작업불량(2) → item_id:', incomingDefectItem?.item_id); + console.log(' - 입고지연(3) → item_id:', materialShortageItem?.item_id); + + // 3. 기존 데이터 업데이트 + if (designMissItem) { + const [result1] = await knex.raw(` + UPDATE daily_work_reports + SET error_type_id = ? + WHERE error_type_id = 1 + `, [designMissItem.item_id]); + console.log('설계미스(1) 업데이트:', result1.affectedRows, '건'); + } + + if (incomingDefectItem) { + const [result2] = await knex.raw(` + UPDATE daily_work_reports + SET error_type_id = ? + WHERE error_type_id = 2 + `, [incomingDefectItem.item_id]); + console.log('외주작업불량(2) 업데이트:', result2.affectedRows, '건'); + } + + if (materialShortageItem) { + const [result3] = await knex.raw(` + UPDATE daily_work_reports + SET error_type_id = ? + WHERE error_type_id = 3 + `, [materialShortageItem.item_id]); + console.log('입고지연(3) 업데이트:', result3.affectedRows, '건'); + } + + // 4. 매핑 안된 나머지 데이터 확인 (4 이상의 error_type_id) + const [unmapped] = await knex.raw(` + SELECT DISTINCT error_type_id, COUNT(*) as cnt + FROM daily_work_reports + WHERE error_type_id IS NOT NULL + AND error_type_id NOT IN (?, ?, ?) + GROUP BY error_type_id + `, [ + designMissItem?.item_id || 0, + incomingDefectItem?.item_id || 0, + materialShortageItem?.item_id || 0 + ]); + + if (unmapped.length > 0) { + console.log('⚠️ 매핑되지 않은 error_type_id 발견:', unmapped); + console.log(' 이 데이터는 수동으로 확인 필요'); + } + + console.log('=== error_type_id 마이그레이션 완료 ==='); +}; + +exports.down = async function(knex) { + // 롤백은 복잡하므로 로그만 출력 + console.log('⚠️ 이 마이그레이션은 자동 롤백을 지원하지 않습니다.'); + console.log(' 데이터 복구가 필요한 경우 백업에서 복원해주세요.'); +}; diff --git a/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.sql b/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.sql new file mode 100644 index 0000000..4330533 --- /dev/null +++ b/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.sql @@ -0,0 +1,73 @@ +-- ============================================ +-- error_types → issue_report_items 마이그레이션 +-- ============================================ + +-- STEP 1: 현재 데이터 확인 +-- ============================================ + +-- 기존 error_types 확인 +SELECT * FROM error_types; + +-- 새 issue_report_categories 확인 (부적합만) +SELECT * FROM issue_report_categories WHERE category_type = 'nonconformity'; + +-- 새 issue_report_items 확인 (부적합만) +SELECT + iri.item_id, + iri.item_name, + iri.category_id, + irc.category_name +FROM issue_report_items iri +JOIN issue_report_categories irc ON iri.category_id = irc.category_id +WHERE irc.category_type = 'nonconformity' +ORDER BY irc.display_order, iri.display_order; + +-- 현재 daily_work_reports에서 사용 중인 error_type_id 확인 +SELECT + error_type_id, + COUNT(*) as cnt, + et.name as old_error_name +FROM daily_work_reports dwr +LEFT JOIN error_types et ON dwr.error_type_id = et.id +WHERE error_type_id IS NOT NULL +GROUP BY error_type_id +ORDER BY error_type_id; + + +-- STEP 2: 매핑 업데이트 (실제 item_id 확인 후 수정 필요!) +-- ============================================ + +-- 먼저 위 쿼리로 실제 item_id 값을 확인하세요! +-- 아래는 예시입니다. 실제 값으로 수정해서 사용하세요. + +-- 예시: 설계미스(error_type_id=1) → 설계미스 카테고리의 '도면 치수 오류' 항목 +-- UPDATE daily_work_reports SET error_type_id = 6 WHERE error_type_id = 1; + +-- 예시: 외주작업 불량(error_type_id=2) → 입고불량 카테고리의 '외관 불량' 항목 +-- UPDATE daily_work_reports SET error_type_id = 10 WHERE error_type_id = 2; + +-- 예시: 입고지연(error_type_id=3) → 자재누락 카테고리의 '배관 자재 미입고' 항목 +-- UPDATE daily_work_reports SET error_type_id = 1 WHERE error_type_id = 3; + + +-- STEP 3: 매핑 검증 +-- ============================================ + +-- 업데이트 후 확인 +SELECT + dwr.error_type_id, + iri.item_name, + irc.category_name, + COUNT(*) as cnt +FROM daily_work_reports dwr +LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id +LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id +WHERE dwr.error_type_id IS NOT NULL +GROUP BY dwr.error_type_id, iri.item_name, irc.category_name; + + +-- STEP 4: error_types 테이블 삭제 (매핑 완료 후) +-- ============================================ + +-- 주의: 반드시 STEP 2, 3 완료 후 실행! +-- DROP TABLE IF EXISTS error_types; diff --git a/api.hyungi.net/index.js b/api.hyungi.net/index.js index 7e7661d..fded5b8 100644 --- a/api.hyungi.net/index.js +++ b/api.hyungi.net/index.js @@ -22,6 +22,222 @@ const PORT = process.env.PORT || 20005; // Trust proxy for accurate IP addresses app.set('trust proxy', 1); +// JSON body parser 미리 적용 (마이그레이션용) +app.use(express.json()); + +// 임시 분석 테스트 엔드포인트 - 실행 후 삭제! +app.get('/api/test-analysis', async (req, res) => { + try { + const { getDb } = require('./dbPool'); + const db = await getDb(); + + // 수정된 COALESCE 로직 테스트 (tasks 우선) + const [results] = await db.query(` + SELECT + dwr.id, + w.worker_name, + dwr.report_date, + dwr.work_type_id as original_work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN t.work_type_id ELSE NULL END, + wt.id + ) as resolved_work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN wt2.name ELSE NULL END, + wt.name + ) as work_type_name, + t.task_name, + wt.name as direct_match_work_type, + wt2.name as task_work_type + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id + WHERE w.worker_name LIKE '%조승민%' OR w.worker_name LIKE '%최광욱%' + ORDER BY dwr.report_date DESC + LIMIT 20 + `); + + res.json({ + success: true, + message: 'tasks 테이블 우선 조회 결과', + data: results.map(r => ({ + id: r.id, + worker: r.worker_name, + date: r.report_date, + original_id: r.original_work_type_id, + resolved_work_type: r.work_type_name, + task: r.task_name, + note: `원래 ID ${r.original_work_type_id} → ${r.work_type_name}` + })) + }); + + } catch (error) { + console.error('테스트 실패:', error); + res.status(500).json({ success: false, error: error.message }); + } +}); + +// 임시 진단 엔드포인트 - 실행 후 삭제! +app.get('/api/diagnose-work-type-id', async (req, res) => { + try { + const { getDb } = require('./dbPool'); + const db = await getDb(); + + // 1. 전체 작업보고서 현황 + const [totalStats] = await db.query(` + SELECT + COUNT(*) as total_reports, + COUNT(tbm_assignment_id) as tbm_reports, + COUNT(CASE WHEN tbm_assignment_id IS NULL THEN 1 END) as non_tbm_reports + FROM daily_work_reports + `); + + // 2. work_type_id 값 분포 (상위 20개) + const [workTypeDistribution] = await db.query(` + SELECT + dwr.work_type_id, + COUNT(*) as count, + wt.name as if_work_type, + t.task_name as if_task, + wt2.name as task_work_type + FROM daily_work_reports dwr + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id + GROUP BY dwr.work_type_id + ORDER BY count DESC + LIMIT 20 + `); + + // 3. 특정 작업자 데이터 확인 (조승민, 최광욱) + const [workerSamples] = await db.query(` + SELECT + dwr.id, + w.worker_name, + dwr.work_type_id, + dwr.tbm_assignment_id, + wt.name as direct_work_type, + t.task_name, + wt2.name as task_work_type, + dwr.report_date + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id + WHERE w.worker_name LIKE '%조승민%' OR w.worker_name LIKE '%최광욱%' + ORDER BY dwr.report_date DESC + LIMIT 20 + `); + + res.json({ + success: true, + data: { + total_stats: totalStats[0], + work_type_distribution: workTypeDistribution, + worker_samples: workerSamples + } + }); + + } catch (error) { + console.error('진단 실패:', error); + res.status(500).json({ success: false, error: error.message }); + } +}); + +// 임시 마이그레이션 엔드포인트 (인증 없이 실행) - 실행 후 삭제! +app.post('/api/migrate-work-type-id', async (req, res) => { + try { + const { getDb } = require('./dbPool'); + const db = await getDb(); + + console.log('🔄 TBM 기반 작업보고서 work_type_id 수정 시작...'); + + // 1. 수정 대상 확인 + const [checkResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id as current_work_type_id, + ta.task_id as correct_task_id, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + INNER JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + ORDER BY dwr.report_date DESC + `); + + console.log('📊 수정 대상:', checkResult.length, '개 레코드'); + + if (checkResult.length === 0) { + return res.json({ + success: true, + message: '수정할 데이터가 없습니다.', + data: { affected_rows: 0 } + }); + } + + // 2. 업데이트 실행 + const [updateResult] = await db.query(` + UPDATE daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + SET dwr.work_type_id = ta.task_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + `); + + console.log('✅ 업데이트 완료:', updateResult.affectedRows, '개 레코드 수정됨'); + + // 3. 수정 후 확인 + const [samples] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id, + t.task_name, + wt.name as work_type_name, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + ORDER BY dwr.report_date DESC + LIMIT 10 + `); + + res.json({ + success: true, + message: updateResult.affectedRows + '개 레코드가 수정되었습니다.', + data: { + affected_rows: updateResult.affectedRows, + before_count: checkResult.length, + samples: samples.map(s => ({ + id: s.id, + worker: s.worker_name, + date: s.report_date, + task: s.task_name, + work_type: s.work_type_name + })) + } + }); + + } catch (error) { + console.error('마이그레이션 실패:', error); + res.status(500).json({ + success: false, + error: '마이그레이션 실패: ' + error.message + }); + } +}); + // 미들웨어 설정 setupMiddlewares(app); diff --git a/api.hyungi.net/models/WorkAnalysis.js b/api.hyungi.net/models/WorkAnalysis.js index f39e5b1..8513ace 100644 --- a/api.hyungi.net/models/WorkAnalysis.js +++ b/api.hyungi.net/models/WorkAnalysis.js @@ -182,8 +182,10 @@ class WorkAnalysis { // 최근 작업 현황 async getRecentWork(startDate, endDate, limit = 50) { - // work_type_id가 work_types에 있으면 직접 사용, - // 없으면 tasks 테이블을 통해 해당 task의 work_type_id로 공정(대분류) 조회 + // work_type_id 컬럼에는 task_id가 저장됨 (tasks 테이블 우선 조회) + // task_id로 매칭되면 해당 task의 work_type_id로 공정(대분류) 조회 + // 매칭 안 되면 직접 work_types 테이블 조회 (레거시 데이터 호환) + // error_type_id는 issue_report_items 테이블 참조 (issue-categories.html에서 관리) const query = ` SELECT dwr.id, @@ -194,13 +196,20 @@ class WorkAnalysis { p.project_name, p.job_no, dwr.work_type_id as original_work_type_id, - COALESCE(wt.id, t.work_type_id) as work_type_id, - COALESCE(wt.name, wt2.name) as work_type_name, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN t.work_type_id ELSE NULL END, + wt.id + ) as work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN wt2.name ELSE NULL END, + wt.name + ) as work_type_name, t.task_name as task_name, dwr.work_status_id, wst.name as work_status_name, dwr.error_type_id, - et.name as error_type_name, + iri.item_name as error_type_name, + irc.category_name as error_category_name, dwr.work_hours, dwr.created_by, u.name as created_by_name, @@ -212,7 +221,8 @@ class WorkAnalysis { LEFT JOIN tasks t ON dwr.work_type_id = t.task_id LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id LEFT JOIN work_status_types wst ON dwr.work_status_id = wst.id - LEFT JOIN error_types et ON dwr.error_type_id = et.id + LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id + LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id LEFT JOIN users u ON dwr.created_by = u.user_id WHERE dwr.report_date BETWEEN ? AND ? ORDER BY dwr.created_at DESC @@ -236,6 +246,7 @@ class WorkAnalysis { work_status_name: row.work_status_name || '정상', error_type_id: row.error_type_id, error_type_name: row.error_type_name || null, + error_category_name: row.error_category_name || null, work_hours: parseFloat(row.work_hours) || 0, created_by: row.created_by, created_by_name: row.created_by_name || '미지정', @@ -286,20 +297,23 @@ class WorkAnalysis { } // 에러 분석 + // error_type_id는 issue_report_items 테이블 참조 (issue-categories.html에서 관리) async getErrorAnalysis(startDate, endDate) { const query = ` - SELECT + SELECT dwr.error_type_id, - et.name as error_type_name, + iri.item_name as error_type_name, + irc.category_name as error_category_name, COUNT(*) as error_count, SUM(dwr.work_hours) as total_hours, COUNT(DISTINCT dwr.worker_id) as affected_workers, COUNT(DISTINCT dwr.project_id) as affected_projects FROM daily_work_reports dwr - LEFT JOIN error_types et ON dwr.error_type_id = et.id + LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id + LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id WHERE dwr.report_date BETWEEN ? AND ? AND dwr.work_status_id = 2 - GROUP BY dwr.error_type_id, et.name + GROUP BY dwr.error_type_id, iri.item_name, irc.category_name ORDER BY error_count DESC `; @@ -308,6 +322,7 @@ class WorkAnalysis { return results.map(row => ({ error_type_id: row.error_type_id, error_type_name: row.error_type_name || `에러유형 ${row.error_type_id}`, + error_category_name: row.error_category_name || null, errorCount: parseInt(row.error_count) || 0, totalHours: parseFloat(row.total_hours) || 0, affectedworkers: parseInt(row.affected_workers) || 0, @@ -436,14 +451,23 @@ class WorkAnalysis { } // 프로젝트별-작업별 시간 분석용 데이터 조회 (공정/대분류 기준) async getProjectWorkTypeRawData(startDate, endDate) { - // work_type_id가 실제로 task_id인 경우 해당 task의 work_type_id로 공정 조회 + // work_type_id 컬럼에는 task_id가 저장됨 (tasks 테이블 우선 조회) + // task_id로 매칭되면 해당 task의 work_type_id로 공정 조회 + // 매칭 안 되면 직접 work_types 조회 (레거시 데이터 호환) const query = ` SELECT COALESCE(p.project_id, dwr.project_id) as project_id, COALESCE(p.project_name, CONCAT('프로젝트 ', dwr.project_id)) as project_name, COALESCE(p.job_no, 'N/A') as job_no, - COALESCE(wt.id, t.work_type_id) as work_type_id, - COALESCE(wt.name, wt2.name, CONCAT('작업유형 ', dwr.work_type_id)) as work_type_name, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN t.work_type_id ELSE NULL END, + wt.id + ) as work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN wt2.name ELSE NULL END, + wt.name, + CONCAT('작업유형 ', dwr.work_type_id) + ) as work_type_name, -- 총 시간 SUM(dwr.work_hours) as total_hours, @@ -472,8 +496,14 @@ class WorkAnalysis { LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id WHERE dwr.report_date BETWEEN ? AND ? GROUP BY dwr.project_id, p.project_name, p.job_no, - COALESCE(wt.id, t.work_type_id), - COALESCE(wt.name, wt2.name) + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN t.work_type_id ELSE NULL END, + wt.id + ), + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN wt2.name ELSE NULL END, + wt.name + ) ORDER BY p.project_name, work_type_name `; diff --git a/api.hyungi.net/models/attendanceModel.js b/api.hyungi.net/models/attendanceModel.js index 3e6217b..a14c411 100644 --- a/api.hyungi.net/models/attendanceModel.js +++ b/api.hyungi.net/models/attendanceModel.js @@ -432,21 +432,23 @@ class AttendanceModel { static async getMonthlyAttendanceStats(year, month, workerId = null) { const db = await getDb(); + // work_attendance_types: 1=NORMAL, 2=LATE, 3=EARLY_LEAVE, 4=ABSENT, 5=VACATION + // vacation_types: 1=ANNUAL(연차), 2=HALF_ANNUAL(반차), 3=SICK(병가), 4=SPECIAL(경조사) let query = ` - SELECT + SELECT w.worker_id, w.worker_name, - COUNT(CASE WHEN dar.status = 'complete' THEN 1 END) as regular_days, - COUNT(CASE WHEN dar.status = 'overtime' THEN 1 END) as overtime_days, - COUNT(CASE WHEN dar.status = 'vacation' THEN 1 END) as vacation_days, - COUNT(CASE WHEN dar.status = 'partial' THEN 1 END) as partial_days, - COUNT(CASE WHEN dar.status = 'incomplete' THEN 1 END) as incomplete_days, - SUM(dar.total_work_hours) as total_work_hours, - AVG(dar.total_work_hours) as avg_work_hours + COUNT(CASE WHEN dar.attendance_type_id = 1 AND (dar.is_overtime_approved = 0 OR dar.is_overtime_approved IS NULL) THEN 1 END) as regular_days, + COUNT(CASE WHEN dar.is_overtime_approved = 1 OR dar.total_work_hours > 8 THEN 1 END) as overtime_days, + COUNT(CASE WHEN dar.attendance_type_id = 5 AND dar.vacation_type_id = 1 THEN 1 END) as vacation_days, + COUNT(CASE WHEN dar.vacation_type_id = 2 THEN 1 END) as partial_days, + COUNT(CASE WHEN dar.attendance_type_id = 4 THEN 1 END) as incomplete_days, + COALESCE(SUM(dar.total_work_hours), 0) as total_work_hours, + COALESCE(AVG(dar.total_work_hours), 0) as avg_work_hours FROM workers w LEFT JOIN daily_attendance_records dar ON w.worker_id = dar.worker_id AND YEAR(dar.record_date) = ? AND MONTH(dar.record_date) = ? - WHERE w.is_active = TRUE + WHERE w.employment_status = 'employed' `; const params = [year, month]; diff --git a/api.hyungi.net/models/dailyWorkReportModel.js b/api.hyungi.net/models/dailyWorkReportModel.js index e087153..8cf266a 100644 --- a/api.hyungi.net/models/dailyWorkReportModel.js +++ b/api.hyungi.net/models/dailyWorkReportModel.js @@ -29,7 +29,21 @@ const getAllWorkStatusTypes = async (callback) => { const getAllErrorTypes = async (callback) => { try { const db = await getDb(); - const [rows] = await db.query('SELECT id, name, description, severity, solution_guide, created_at, updated_at FROM error_types ORDER BY name ASC'); + // issue_report_items에서 부적합(nonconformity) 타입의 항목만 조회 + const [rows] = await db.query(` + SELECT + iri.item_id as id, + iri.item_name as name, + iri.description, + iri.severity, + irc.category_name as category, + iri.display_order, + iri.created_at + FROM issue_report_items iri + INNER JOIN issue_report_categories irc ON iri.category_id = irc.category_id + WHERE irc.category_type = 'nonconformity' AND iri.is_active = TRUE + ORDER BY irc.display_order, iri.display_order, iri.item_name ASC + `); callback(null, rows); } catch (err) { console.error('에러 유형 조회 오류:', err); @@ -301,9 +315,10 @@ const removeSpecificEntry = async (entry_id, deleted_by, callback) => { /** * 공통 SELECT 쿼리 부분 + * error_type_id는 issue_report_items 테이블 참조 (issue-categories.html에서 관리) */ const getSelectQuery = () => ` - SELECT + SELECT dwr.id, dwr.report_date, dwr.worker_id, @@ -317,7 +332,8 @@ const getSelectQuery = () => ` p.project_name, wt.name as work_type_name, wst.name as work_status_name, - et.name as error_type_name, + iri.item_name as error_type_name, + irc.category_name as error_category_name, u.name as created_by_name, dwr.created_at, dwr.updated_at @@ -326,7 +342,8 @@ const getSelectQuery = () => ` LEFT JOIN projects p ON dwr.project_id = p.project_id LEFT JOIN work_types wt ON dwr.work_type_id = wt.id LEFT JOIN work_status_types wst ON dwr.work_status_id = wst.id - LEFT JOIN error_types et ON dwr.error_type_id = et.id + LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id + LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id LEFT JOIN users u ON dwr.created_by = u.user_id `; @@ -873,9 +890,11 @@ const createReportEntries = async ({ report_date, worker_id, entries }) => { /** * [V2] 공통 SELECT 쿼리 (새로운 스키마 기준) + * 주의: work_type_id 컬럼에는 실제로 task_id가 저장됨 + * error_type_id는 issue_report_items 테이블 참조 (issue-categories.html에서 관리) */ const getSelectQueryV2 = () => ` - SELECT + SELECT dwr.id, dwr.report_date, dwr.worker_id, @@ -887,17 +906,21 @@ const getSelectQueryV2 = () => ` dwr.created_by, w.worker_name, p.project_name, + t.task_name, wt.name as work_type_name, wst.name as work_status_name, - et.name as error_type_name, + iri.item_name as error_type_name, + irc.category_name as error_category_name, u.name as created_by_name, dwr.created_at FROM daily_work_reports dwr LEFT JOIN workers w ON dwr.worker_id = w.worker_id LEFT JOIN projects p ON dwr.project_id = p.project_id - LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id LEFT JOIN work_status_types wst ON dwr.work_status_id = wst.id - LEFT JOIN error_types et ON dwr.error_type_id = et.id + LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id + LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id LEFT JOIN users u ON dwr.created_by = u.user_id `; @@ -967,9 +990,9 @@ const updateReportById = async (reportId, updateData) => { } } - // updated_by_user_id는 항상 업데이트 + // updated_by는 항상 업데이트 if (updateData.updated_by_user_id) { - setClauses.push('updated_by_user_id = ?'); + setClauses.push('updated_by = ?'); queryParams.push(updateData.updated_by_user_id); } diff --git a/api.hyungi.net/models/taskModel.js b/api.hyungi.net/models/taskModel.js index 45fd368..432d431 100644 --- a/api.hyungi.net/models/taskModel.js +++ b/api.hyungi.net/models/taskModel.js @@ -58,7 +58,7 @@ const getActiveTasks = async () => { }; /** - * 공정별 작업 목록 조회 + * 공정별 작업 목록 조회 (활성 작업만) */ const getTasksByWorkType = async (workTypeId) => { const db = await getDb(); @@ -68,8 +68,8 @@ const getTasksByWorkType = async (workTypeId) => { wt.name as work_type_name, wt.category FROM tasks t LEFT JOIN work_types wt ON t.work_type_id = wt.id - WHERE t.work_type_id = ? - ORDER BY t.task_id DESC`, + WHERE t.work_type_id = ? AND t.is_active = 1 + ORDER BY t.task_name ASC`, [workTypeId] ); return rows; diff --git a/api.hyungi.net/models/vacationBalanceModel.js b/api.hyungi.net/models/vacationBalanceModel.js index d2dc681..d342417 100644 --- a/api.hyungi.net/models/vacationBalanceModel.js +++ b/api.hyungi.net/models/vacationBalanceModel.js @@ -260,6 +260,118 @@ const vacationBalanceModel = { return Math.min(15 + additionalDays, 25); }, + /** + * 휴가 사용 시 우선순위에 따라 잔액에서 차감 (Promise 버전) + * - 일일 근태 기록 저장 시 호출 + * @param {number} workerId - 작업자 ID + * @param {number} year - 연도 + * @param {number} daysToDeduct - 차감할 일수 (1, 0.5, 0.25) + * @returns {Promise} - 차감 결과 + */ + async deductByPriority(workerId, year, daysToDeduct) { + const db = await getDb(); + + // 우선순위순으로 잔여 일수가 있는 잔액 조회 + const [balances] = await db.query(` + SELECT vbd.id, vbd.vacation_type_id, vbd.total_days, vbd.used_days, + (vbd.total_days - vbd.used_days) as remaining_days, + vt.type_code, vt.type_name, vt.priority + FROM vacation_balance_details vbd + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.worker_id = ? AND vbd.year = ? + AND (vbd.total_days - vbd.used_days) > 0 + ORDER BY vt.priority ASC + `, [workerId, year]); + + if (balances.length === 0) { + // 잔액이 없어도 일단 기록은 저장 (경고만) + console.warn(`[VacationBalance] 작업자 ${workerId}의 ${year}년 휴가 잔액이 없습니다`); + return { success: false, message: '휴가 잔액이 없습니다', deducted: 0 }; + } + + let remaining = daysToDeduct; + const deductions = []; + + for (const balance of balances) { + if (remaining <= 0) break; + + const available = parseFloat(balance.remaining_days); + const toDeduct = Math.min(remaining, available); + + if (toDeduct > 0) { + await db.query(` + UPDATE vacation_balance_details + SET used_days = used_days + ?, updated_at = NOW() + WHERE id = ? + `, [toDeduct, balance.id]); + + deductions.push({ + balance_id: balance.id, + type_code: balance.type_code, + type_name: balance.type_name, + deducted: toDeduct + }); + + remaining -= toDeduct; + } + } + + console.log(`[VacationBalance] 작업자 ${workerId}: ${daysToDeduct}일 차감 완료`, deductions); + return { success: true, deductions, totalDeducted: daysToDeduct - remaining }; + }, + + /** + * 휴가 취소 시 우선순위 역순으로 복구 (Promise 버전) + * @param {number} workerId - 작업자 ID + * @param {number} year - 연도 + * @param {number} daysToRestore - 복구할 일수 + * @returns {Promise} - 복구 결과 + */ + async restoreByPriority(workerId, year, daysToRestore) { + const db = await getDb(); + + // 우선순위 역순으로 사용 일수가 있는 잔액 조회 (나중에 차감된 것부터 복구) + const [balances] = await db.query(` + SELECT vbd.id, vbd.vacation_type_id, vbd.used_days, + vt.type_code, vt.type_name, vt.priority + FROM vacation_balance_details vbd + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.worker_id = ? AND vbd.year = ? + AND vbd.used_days > 0 + ORDER BY vt.priority DESC + `, [workerId, year]); + + let remaining = daysToRestore; + const restorations = []; + + for (const balance of balances) { + if (remaining <= 0) break; + + const usedDays = parseFloat(balance.used_days); + const toRestore = Math.min(remaining, usedDays); + + if (toRestore > 0) { + await db.query(` + UPDATE vacation_balance_details + SET used_days = used_days - ?, updated_at = NOW() + WHERE id = ? + `, [toRestore, balance.id]); + + restorations.push({ + balance_id: balance.id, + type_code: balance.type_code, + type_name: balance.type_name, + restored: toRestore + }); + + remaining -= toRestore; + } + } + + console.log(`[VacationBalance] 작업자 ${workerId}: ${daysToRestore}일 복구 완료`, restorations); + return { success: true, restorations, totalRestored: daysToRestore - remaining }; + }, + /** * 특정 ID로 휴가 잔액 조회 */ diff --git a/api.hyungi.net/routes/attendanceRoutes.js b/api.hyungi.net/routes/attendanceRoutes.js index a5c7393..b93a7e4 100644 --- a/api.hyungi.net/routes/attendanceRoutes.js +++ b/api.hyungi.net/routes/attendanceRoutes.js @@ -12,6 +12,9 @@ router.get('/daily-status', AttendanceController.getDailyAttendanceStatus); // 일일 근태 기록 조회 router.get('/daily-records', AttendanceController.getDailyAttendanceRecords); +// 기간별 근태 기록 조회 (월별 조회용) +router.get('/records', AttendanceController.getAttendanceRecordsByRange); + // 근태 기록 생성/업데이트 router.post('/records', AttendanceController.upsertAttendanceRecord); router.put('/records', AttendanceController.upsertAttendanceRecord); diff --git a/api.hyungi.net/routes/authRoutes.js b/api.hyungi.net/routes/authRoutes.js index 5b7c563..46d7f8c 100644 --- a/api.hyungi.net/routes/authRoutes.js +++ b/api.hyungi.net/routes/authRoutes.js @@ -147,7 +147,7 @@ router.post('/refresh-token', async (req, res) => { // 사용자 정보 조회 const [users] = await connection.execute( - 'SELECT * FROM Users WHERE user_id = ? AND is_active = TRUE', + 'SELECT * FROM users WHERE user_id = ? AND is_active = TRUE', [decoded.user_id] ); @@ -229,7 +229,7 @@ router.post('/change-password', verifyToken, async (req, res) => { // 현재 사용자의 비밀번호 조회 const [users] = await connection.execute( - 'SELECT password FROM Users WHERE user_id = ?', + 'SELECT password FROM users WHERE user_id = ?', [userId] ); @@ -339,7 +339,7 @@ router.post('/admin/change-password', verifyToken, async (req, res) => { // 대상 사용자 확인 const [users] = await connection.execute( - 'SELECT username, name FROM Users WHERE user_id = ?', + 'SELECT username, name FROM users WHERE user_id = ?', [userId] ); @@ -456,7 +456,7 @@ router.get('/me', verifyToken, async (req, res) => { connection = await mysql.createConnection(dbConfig); const [rows] = await connection.execute( - 'SELECT user_id, username, name, email, access_level, worker_id, last_login_at, created_at FROM Users WHERE user_id = ?', + 'SELECT user_id, username, name, email, access_level, worker_id, last_login_at, created_at FROM users WHERE user_id = ?', [userId] ); @@ -522,7 +522,7 @@ router.post('/register', verifyToken, async (req, res) => { // 사용자명 중복 체크 const [existing] = await connection.execute( - 'SELECT user_id FROM Users WHERE username = ?', + 'SELECT user_id FROM users WHERE username = ?', [username] ); @@ -536,7 +536,7 @@ router.post('/register', verifyToken, async (req, res) => { // 이메일 중복 체크 (이메일이 제공된 경우) if (email) { const [existingEmail] = await connection.execute( - 'SELECT user_id FROM Users WHERE email = ?', + 'SELECT user_id FROM users WHERE email = ?', [email] ); @@ -700,7 +700,7 @@ router.put('/users/:id', verifyToken, async (req, res) => { // 사용자 존재 확인 const [existing] = await connection.execute( - 'SELECT user_id, username FROM Users WHERE user_id = ?', + 'SELECT user_id, username FROM users WHERE user_id = ?', [userId] ); @@ -724,7 +724,7 @@ router.put('/users/:id', verifyToken, async (req, res) => { // 이메일 중복 체크 if (email) { const [emailCheck] = await connection.execute( - 'SELECT user_id FROM Users WHERE email = ? AND user_id != ?', + 'SELECT user_id FROM users WHERE email = ? AND user_id != ?', [email, userId] ); @@ -794,7 +794,7 @@ router.put('/users/:id', verifyToken, async (req, res) => { // 업데이트된 사용자 정보 조회 const [updated] = await connection.execute( - 'SELECT user_id, username, name, email, access_level, worker_id, is_active FROM Users WHERE user_id = ?', + 'SELECT user_id, username, name, email, access_level, worker_id, is_active FROM users WHERE user_id = ?', [userId] ); diff --git a/api.hyungi.net/routes/healthRoutes.js b/api.hyungi.net/routes/healthRoutes.js index 984d676..25f74b2 100644 --- a/api.hyungi.net/routes/healthRoutes.js +++ b/api.hyungi.net/routes/healthRoutes.js @@ -25,4 +25,99 @@ router.get('/detail', (req, res) => { }); }); +// 임시 마이그레이션 엔드포인트 - TBM work_type_id 수정 +// 실행 후 이 코드를 삭제하세요! +router.post('/migrate-work-type-id', async (req, res) => { + try { + const { getDb } = require('../dbPool'); + const db = await getDb(); + + console.log('🔄 TBM 기반 작업보고서 work_type_id 수정 시작...'); + + // 1. 수정 대상 확인 + const [checkResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id as current_work_type_id, + ta.task_id as correct_task_id, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + INNER JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + ORDER BY dwr.report_date DESC + `); + + console.log(`📊 수정 대상: ${checkResult.length}개 레코드`); + + if (checkResult.length === 0) { + return res.json({ + success: true, + message: '수정할 데이터가 없습니다.', + data: { affected_rows: 0 } + }); + } + + // 수정 전 샘플 로깅 + console.log('수정 전 샘플:', checkResult.slice(0, 5)); + + // 2. 업데이트 실행 + const [updateResult] = await db.query(` + UPDATE daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + SET dwr.work_type_id = ta.task_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + `); + + console.log(`✅ 업데이트 완료: ${updateResult.affectedRows}개 레코드 수정됨`); + + // 3. 수정 후 확인 + const [samples] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id, + t.task_name, + wt.name as work_type_name, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + ORDER BY dwr.report_date DESC + LIMIT 10 + `); + + res.json({ + success: true, + message: `${updateResult.affectedRows}개 레코드가 수정되었습니다.`, + data: { + affected_rows: updateResult.affectedRows, + before_count: checkResult.length, + samples: samples.map(s => ({ + id: s.id, + worker: s.worker_name, + date: s.report_date, + task: s.task_name, + work_type: s.work_type_name + })) + } + }); + + } catch (error) { + console.error('마이그레이션 실패:', error); + res.status(500).json({ + success: false, + error: '마이그레이션 실패: ' + error.message + }); + } +}); + module.exports = router; \ No newline at end of file diff --git a/api.hyungi.net/routes/patrolRoutes.js b/api.hyungi.net/routes/patrolRoutes.js index 9b5c0b5..4368f44 100644 --- a/api.hyungi.net/routes/patrolRoutes.js +++ b/api.hyungi.net/routes/patrolRoutes.js @@ -3,8 +3,35 @@ const express = require('express'); const router = express.Router(); +const multer = require('multer'); +const path = require('path'); const patrolController = require('../controllers/patrolController'); +// Multer 설정 - 구역 현황 사진 업로드 +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, path.join(__dirname, '../uploads')); + }, + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); + const ext = path.extname(file.originalname).toLowerCase(); + cb(null, `zone-item-${uniqueSuffix}${ext}`); + } +}); + +const upload = multer({ + storage, + limits: { fileSize: 10 * 1024 * 1024 }, // 10MB + fileFilter: (req, file, cb) => { + const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; + if (allowedTypes.includes(file.mimetype)) { + cb(null, true); + } else { + cb(new Error('이미지 파일만 업로드 가능합니다.'), false); + } + } +}); + // ==================== 순회점검 세션 ==================== // 세션 목록 조회 @@ -70,4 +97,30 @@ router.get('/item-types', patrolController.getItemTypes); // 오늘 순회점검 현황 router.get('/today-status', patrolController.getTodayStatus); +// ==================== 작업장 상세 정보 ==================== + +// 작업장 상세 정보 조회 (시설물, 안전신고, 부적합, 출입, TBM 통합) +// GET /patrol/workplaces/:workplaceId/detail?date=2026-02-05 +router.get('/workplaces/:workplaceId/detail', patrolController.getWorkplaceDetail); + +// ==================== 구역 내 등록 물품/시설물 ==================== + +// 구역 내 등록된 물품/시설물 목록 조회 +router.get('/workplaces/:workplaceId/zone-items', patrolController.getZoneItems); + +// 구역 내 물품/시설물 등록 +router.post('/workplaces/:workplaceId/zone-items', patrolController.createZoneItem); + +// 구역 내 물품/시설물 수정 +router.put('/zone-items/:itemId', patrolController.updateZoneItem); + +// 구역 내 물품/시설물 삭제 +router.delete('/zone-items/:itemId', patrolController.deleteZoneItem); + +// 구역 현황 사진 업로드 +router.post('/zone-items/photos', upload.single('photo'), patrolController.uploadZoneItemPhoto); + +// 구역 현황 이력 조회 +router.get('/zone-items/:itemId/history', patrolController.getZoneItemHistory); + module.exports = router; diff --git a/api.hyungi.net/routes/systemRoutes.js b/api.hyungi.net/routes/systemRoutes.js index 32cd528..ff5cd22 100644 --- a/api.hyungi.net/routes/systemRoutes.js +++ b/api.hyungi.net/routes/systemRoutes.js @@ -210,6 +210,98 @@ router.get('/logs/password-changes', async (req, res) => { } }); +/** + * POST /api/system/migrations/fix-work-type-id + * TBM 기반 작업보고서의 work_type_id를 task_id로 수정 + */ +router.post('/migrations/fix-work-type-id', async (req, res) => { + try { + const { getDb } = require('../dbPool'); + const db = await getDb(); + + console.log('🔄 TBM 기반 작업보고서 work_type_id 수정 시작...'); + + // 1. 수정 대상 확인 + const [checkResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id as current_work_type_id, + ta.task_id as correct_task_id, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + INNER JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + ORDER BY dwr.report_date DESC + `); + + if (checkResult.length === 0) { + return res.json({ + success: true, + message: '수정할 데이터가 없습니다.', + data: { affected_rows: 0, samples: [] } + }); + } + + // 2. 업데이트 실행 + const [updateResult] = await db.query(` + UPDATE daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + SET dwr.work_type_id = ta.task_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + `); + + console.log(`✅ 업데이트 완료: ${updateResult.affectedRows}개 레코드 수정됨`); + + // 3. 수정된 샘플 조회 + const [samples] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id, + t.task_name, + wt.name as work_type_name, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + ORDER BY dwr.report_date DESC + LIMIT 10 + `); + + res.json({ + success: true, + message: `${updateResult.affectedRows}개 레코드가 수정되었습니다.`, + data: { + affected_rows: updateResult.affectedRows, + before_count: checkResult.length, + samples: samples.map(s => ({ + id: s.id, + worker: s.worker_name, + date: s.report_date, + task: s.task_name, + work_type: s.work_type_name + })) + } + }); + + } catch (error) { + console.error('마이그레이션 실패:', error); + res.status(500).json({ + success: false, + error: '마이그레이션 실패: ' + error.message + }); + } +}); + /** * GET /api/system/logs/activity * 활동 로그 조회 (activity_logs 테이블이 있는 경우) diff --git a/api.hyungi.net/routes/vacationBalanceRoutes.js b/api.hyungi.net/routes/vacationBalanceRoutes.js index c2ab2b7..e44872f 100644 --- a/api.hyungi.net/routes/vacationBalanceRoutes.js +++ b/api.hyungi.net/routes/vacationBalanceRoutes.js @@ -22,6 +22,9 @@ router.post('/auto-calculate', vacationBalanceController.autoCalculateAndCreate) // 휴가 잔액 생성 (관리자만) router.post('/', vacationBalanceController.createBalance); +// 휴가 잔액 일괄 저장 (upsert) +router.post('/bulk-upsert', vacationBalanceController.bulkUpsert); + // 휴가 잔액 수정 (관리자만) router.put('/:id', vacationBalanceController.updateBalance); diff --git a/api.hyungi.net/services/attendanceService.js b/api.hyungi.net/services/attendanceService.js index 5422113..6d6a182 100644 --- a/api.hyungi.net/services/attendanceService.js +++ b/api.hyungi.net/services/attendanceService.js @@ -8,9 +8,19 @@ */ const AttendanceModel = require('../models/attendanceModel'); +const vacationBalanceModel = require('../models/vacationBalanceModel'); const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); const logger = require('../utils/logger'); +/** + * 휴가 사용 유형 ID를 차감 일수로 변환 + * vacation_type_id: 1=연차(1일), 2=반차(0.5일), 3=반반차(0.25일) + */ +const getVacationDays = (vacationTypeId) => { + const daysMap = { 1: 1, 2: 0.5, 3: 0.25 }; + return daysMap[vacationTypeId] || 0; +}; + /** * 일일 근태 현황 조회 */ @@ -63,8 +73,32 @@ const getDailyAttendanceRecordsService = async (date, workerId = null) => { } }; +/** + * 기간별 근태 기록 조회 (월별 조회용) + */ +const getAttendanceRecordsByRangeService = async (startDate, endDate, workerId = null) => { + if (!startDate || !endDate) { + throw new ValidationError('시작 날짜와 종료 날짜가 필요합니다', { + required: ['start_date', 'end_date'], + received: { startDate, endDate } + }); + } + + logger.info('기간별 근태 기록 조회 요청', { startDate, endDate, workerId }); + + try { + const records = await AttendanceModel.getDailyRecords(startDate, endDate, workerId); + logger.info('기간별 근태 기록 조회 성공', { startDate, endDate, count: records.length }); + return records; + } catch (error) { + logger.error('기간별 근태 기록 조회 실패', { startDate, endDate, error: error.message }); + throw new DatabaseError('근태 기록 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + /** * 근태 기록 생성/업데이트 + * - 휴가 기록 시 vacation_balance_details의 used_days 자동 연동 */ const upsertAttendanceRecordService = async (recordData) => { const { @@ -88,9 +122,15 @@ const upsertAttendanceRecordService = async (recordData) => { }); } - logger.info('근태 기록 저장 요청', { record_date, worker_id }); + logger.info('근태 기록 저장 요청', { record_date, worker_id, vacation_type_id }); try { + // 1. 기존 기록 조회 (휴가 연동을 위해) + const existingRecords = await AttendanceModel.getDailyAttendanceRecords(record_date, worker_id); + const existingRecord = existingRecords.find(r => r.worker_id === worker_id); + const previousVacationTypeId = existingRecord?.vacation_type_id || null; + + // 2. 근태 기록 저장 const result = await AttendanceModel.upsertAttendanceRecord({ record_date, worker_id, @@ -101,6 +141,26 @@ const upsertAttendanceRecordService = async (recordData) => { created_by }); + // 3. 휴가 잔액 연동 (vacation_balance_details.used_days 업데이트) + const year = new Date(record_date).getFullYear(); + const previousDays = getVacationDays(previousVacationTypeId); + const newDays = getVacationDays(vacation_type_id); + + // 이전 휴가가 있었고 변경된 경우 → 복구 후 차감 + if (previousDays !== newDays) { + // 이전 휴가 복구 + if (previousDays > 0) { + await vacationBalanceModel.restoreByPriority(worker_id, year, previousDays); + logger.info('휴가 잔액 복구', { worker_id, year, restored: previousDays }); + } + + // 새 휴가 차감 + if (newDays > 0) { + await vacationBalanceModel.deductByPriority(worker_id, year, newDays); + logger.info('휴가 잔액 차감', { worker_id, year, deducted: newDays }); + } + } + logger.info('근태 기록 저장 성공', { record_date, worker_id }); return result; } catch (error) { @@ -321,6 +381,7 @@ const saveCheckinsService = async (date, checkins) => { module.exports = { getDailyAttendanceStatusService, getDailyAttendanceRecordsService, + getAttendanceRecordsByRangeService, upsertAttendanceRecordService, processVacationService, approveOvertimeService, diff --git a/deploy/README.md b/deploy/README.md new file mode 100644 index 0000000..cbc692a --- /dev/null +++ b/deploy/README.md @@ -0,0 +1,137 @@ +# TK-FB-Project Synology NAS 배포 가이드 + +## 사전 준비 + +### 1. Synology NAS 요구사항 +- DSM 7.0 이상 +- Docker 패키지 설치 +- 최소 4GB RAM 권장 +- 10GB 이상 저장공간 + +### 2. Cloudflare Tunnel 설정 + +1. **Cloudflare 대시보드 접속** + - https://dash.cloudflare.com 로그인 + - Zero Trust > Access > Tunnels 이동 + +2. **터널 생성** + - "Create a tunnel" 클릭 + - 이름 입력 (예: tkfb-nas) + - 환경: Docker 선택 + - 표시되는 토큰을 `.env` 파일의 `CLOUDFLARE_TUNNEL_TOKEN`에 입력 + +3. **Public hostname 설정** + - 터널 설정에서 "Public Hostnames" 추가 + + | Subdomain | Domain | Service | + |-----------|--------|---------| + | tkfb | yourdomain.com | http://web:80 | + | api.tkfb | yourdomain.com | http://api:3005 | + +## 배포 순서 + +### 1. 파일 전송 +Synology NAS의 docker 폴더에 다음 파일들을 업로드: + +``` +/volume1/docker/tkfb/ +├── docker-compose.synology.yml (→ docker-compose.yml로 이름 변경) +├── .env (→ .env.synology 복사 후 수정) +├── backup_YYYYMMDD_HHMMSS.sql +├── api.hyungi.net/ +├── web-ui/ +└── fastapi-bridge/ +``` + +### 2. 환경 변수 설정 +```bash +cd /volume1/docker/tkfb +cp .env.synology .env +# .env 파일 편집하여 비밀번호, 토큰 등 수정 +``` + +### 3. Docker Compose 실행 +```bash +# SSH로 NAS 접속 후 +cd /volume1/docker/tkfb + +# 이미지 빌드 및 시작 +docker-compose up -d --build + +# 로그 확인 +docker-compose logs -f +``` + +### 4. 데이터베이스 복원 +```bash +# DB 컨테이너가 시작된 후 (약 30초 대기) +docker exec -i tkfb_db mysql -u root -p'비밀번호' < backup_YYYYMMDD_HHMMSS.sql +``` + +## 포트 설정 + +| 서비스 | 내부포트 | 외부포트 | 설명 | +|--------|----------|----------|------| +| web | 80 | 80 | Web UI | +| api | 3005 | 3005 | Node.js API | +| fastapi | 8000 | 8000 | FastAPI Bridge | +| db | 3306 | 3306 | MariaDB | +| phpmyadmin | 80 | 8080 | DB 관리도구 | + +## Cloudflare Tunnel 사용 시 + +Cloudflare Tunnel을 사용하면 포트 포워딩 없이 외부 접속이 가능합니다: +- 방화벽 포트 개방 불필요 +- 자동 HTTPS 인증서 +- DDoS 보호 + +### web-ui의 API 주소 변경 + +`web-ui/js/config.js` 또는 관련 설정 파일에서 API URL을 변경: + +```javascript +// 로컬 테스트 +const API_URL = 'http://localhost:3005'; + +// Cloudflare Tunnel 사용 시 +const API_URL = 'https://api.tkfb.yourdomain.com'; +``` + +## 문제 해결 + +### 1. 컨테이너 상태 확인 +```bash +docker-compose ps +docker-compose logs api # API 로그 +docker-compose logs db # DB 로그 +``` + +### 2. 데이터베이스 연결 오류 +```bash +# DB 컨테이너 재시작 +docker-compose restart db + +# DB 상태 확인 +docker exec tkfb_db mysqladmin -u root -p ping +``` + +### 3. 권한 오류 +```bash +# 볼륨 권한 설정 +chmod -R 755 /volume1/docker/tkfb +chown -R 1000:1000 /volume1/docker/tkfb/api.hyungi.net/uploads +``` + +## 업데이트 + +```bash +cd /volume1/docker/tkfb + +# 최신 코드 다운로드 후 +docker-compose down +docker-compose up -d --build + +# 캐시 포함 전체 재빌드 +docker-compose build --no-cache +docker-compose up -d +``` diff --git a/deploy/backup_20260206_085303.sql b/deploy/backup_20260206_085303.sql new file mode 100644 index 0000000..9e7094d --- /dev/null +++ b/deploy/backup_20260206_085303.sql @@ -0,0 +1,7407 @@ +-- MariaDB dump 10.19 Distrib 10.9.8-MariaDB, for debian-linux-gnu (aarch64) +-- +-- Host: localhost Database: hyungi +-- ------------------------------------------------------ +-- Server version 10.9.8-MariaDB-1:10.9.8+maria~ubu2204 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `hyungi` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `hyungi` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */; + +USE `hyungi`; + +-- +-- Table structure for table `CuttingPlan` +-- + +DROP TABLE IF EXISTS `CuttingPlan`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `CuttingPlan` ( + `cutting_plan_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int(11) NOT NULL, + `drawing_name` varchar(255) NOT NULL, + `area_number` varchar(100) DEFAULT NULL, + `spool_number` varchar(255) DEFAULT NULL, + `length` decimal(10,2) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `spec_id` int(11) NOT NULL, + PRIMARY KEY (`cutting_plan_id`), + KEY `project_id` (`project_id`), + KEY `fk_cuttingplan_spec` (`spec_id`), + CONSTRAINT `CuttingPlan_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`), + CONSTRAINT `fk_cuttingplan_spec` FOREIGN KEY (`spec_id`) REFERENCES `PipeSpecs` (`spec_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `CuttingPlan` +-- + +LOCK TABLES `CuttingPlan` WRITE; +/*!40000 ALTER TABLE `CuttingPlan` DISABLE KEYS */; +/*!40000 ALTER TABLE `CuttingPlan` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `DailyIssueReports` +-- + +DROP TABLE IF EXISTS `DailyIssueReports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `DailyIssueReports` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `issue_type_id` int(11) DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `start_time` time NOT NULL, + `end_time` time NOT NULL, + PRIMARY KEY (`id`), + KEY `worker_id` (`worker_id`), + KEY `fk_dird_project` (`project_id`), + KEY `fk_dird_issuetype` (`issue_type_id`), + CONSTRAINT `dailyissuereports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `fk_dird_issuetype` FOREIGN KEY (`issue_type_id`) REFERENCES `IssueTypes` (`issue_type_id`), + CONSTRAINT `fk_dird_project` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `DailyIssueReports` +-- + +LOCK TABLES `DailyIssueReports` WRITE; +/*!40000 ALTER TABLE `DailyIssueReports` DISABLE KEYS */; +INSERT INTO `DailyIssueReports` VALUES +(1,'2025-06-02',1,7,5,NULL,'2025-06-02 05:54:35','10:00:00','11:30:00'), +(2,'2025-06-02',9,7,5,NULL,'2025-06-02 05:54:35','10:00:00','11:30:00'), +(3,'2025-06-02',7,7,5,NULL,'2025-06-02 05:54:35','10:00:00','11:30:00'), +(4,'2025-06-04',10,7,3,NULL,'2025-06-04 01:54:03','10:00:00','11:30:00'), +(5,'2025-06-04',6,7,3,NULL,'2025-06-04 01:54:03','10:00:00','11:30:00'), +(6,'2025-06-04',3,7,3,NULL,'2025-06-04 01:54:03','10:00:00','11:30:00'), +(7,'2025-06-11',10,7,6,NULL,'2025-06-10 08:56:09','07:30:00','08:00:00'), +(8,'2025-06-11',6,7,6,NULL,'2025-06-10 08:56:09','07:30:00','08:00:00'), +(9,'2025-06-11',3,7,6,NULL,'2025-06-10 08:56:09','07:30:00','08:00:00'); +/*!40000 ALTER TABLE `DailyIssueReports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `FactoryInfo` +-- + +DROP TABLE IF EXISTS `FactoryInfo`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `FactoryInfo` ( + `factory_id` int(11) NOT NULL AUTO_INCREMENT, + `factory_name` varchar(255) NOT NULL, + `address` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `map_image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`factory_id`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `FactoryInfo` +-- + +LOCK TABLES `FactoryInfo` WRITE; +/*!40000 ALTER TABLE `FactoryInfo` DISABLE KEYS */; +INSERT INTO `FactoryInfo` VALUES +(3,'제1공장 휴게공간 및 작업자 사물함','현대기아로 771-9','개인 보관함, 컨테이너(휴게공간), 화장실, 흡연장','/uploads/map_image-1746593523450.png','2025-05-07 04:52:03','2025-05-07 04:52:03'), +(4,'제 1공장 공구 및 용접봉 보관 구역','현대기아로 771-9','소모품, 공구류, 용접봉 보관 구역','/uploads/map_image-1746593674259.png','2025-05-07 04:53:59','2025-05-07 04:53:59'), +(5,'ee','ee','ee',NULL,'2025-06-03 22:13:23','2025-06-03 22:13:23'); +/*!40000 ALTER TABLE `FactoryInfo` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `IssueTypes` +-- + +DROP TABLE IF EXISTS `IssueTypes`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `IssueTypes` ( + `issue_type_id` int(11) NOT NULL AUTO_INCREMENT, + `category` varchar(100) NOT NULL, + `subcategory` varchar(100) NOT NULL, + PRIMARY KEY (`issue_type_id`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `IssueTypes` +-- + +LOCK TABLES `IssueTypes` WRITE; +/*!40000 ALTER TABLE `IssueTypes` DISABLE KEYS */; +INSERT INTO `IssueTypes` VALUES +(1,'구매팀','자재입고지연'), +(2,'구매팀','자재전달 미흡'), +(3,'품질','검사 내용 전달 미흡'), +(4,'품질','검사오류'), +(5,'설계','설계미스(치수)'), +(6,'설계','설계미스(작업불가)'); +/*!40000 ALTER TABLE `IssueTypes` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `PipeSpecs` +-- + +DROP TABLE IF EXISTS `PipeSpecs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `PipeSpecs` ( + `spec_id` int(11) NOT NULL AUTO_INCREMENT, + `material` varchar(50) NOT NULL COMMENT '재질 (예: SS400, STS304)', + `diameter_in` varchar(10) NOT NULL COMMENT '직경 (inch, 예: 2")', + `schedule` varchar(50) NOT NULL COMMENT '스케줄 (예: STD, SCH10, SCH40)', + PRIMARY KEY (`spec_id`), + UNIQUE KEY `unique_spec` (`material`,`diameter_in`,`schedule`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `PipeSpecs` +-- + +LOCK TABLES `PipeSpecs` WRITE; +/*!40000 ALTER TABLE `PipeSpecs` DISABLE KEYS */; +INSERT INTO `PipeSpecs` VALUES +(2,'516-70N','1','SCH80'), +(1,'A106','3/4','SCH80'); +/*!40000 ALTER TABLE `PipeSpecs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `Processes` +-- + +DROP TABLE IF EXISTS `Processes`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `Processes` ( + `process_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int(11) NOT NULL, + `process_name` varchar(255) NOT NULL, + `process_start` date NOT NULL, + `process_end` date DEFAULT NULL, + `planned_worker_count` int(11) NOT NULL, + `process_description` text DEFAULT NULL, + `note` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`process_id`), + KEY `project_id` (`project_id`), + CONSTRAINT `Processes_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `Processes` +-- + +LOCK TABLES `Processes` WRITE; +/*!40000 ALTER TABLE `Processes` DISABLE KEYS */; +/*!40000 ALTER TABLE `Processes` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `WorkReports` +-- + +DROP TABLE IF EXISTS `WorkReports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `WorkReports` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `morning_task_id` int(11) DEFAULT NULL, + `afternoon_task_id` int(11) DEFAULT NULL, + `overtime_hours` decimal(4,1) DEFAULT 0.0, + `overtime_task_id` int(11) DEFAULT NULL, + `work_details` text DEFAULT NULL, + `note` text DEFAULT NULL, + `memo` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `morning_project_id` int(11) DEFAULT NULL, + `afternoon_project_id` int(11) DEFAULT NULL, + `overtime_project_id` int(11) DEFAULT NULL, + `task_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `worker_id` (`worker_id`), + KEY `project_id` (`project_id`), + KEY `morning_task_id` (`morning_task_id`), + KEY `afternoon_task_id` (`afternoon_task_id`), + KEY `overtime_task_id` (`overtime_task_id`), + CONSTRAINT `WorkReports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `WorkReports_ibfk_2` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`), + CONSTRAINT `WorkReports_ibfk_3` FOREIGN KEY (`morning_task_id`) REFERENCES `tasks_old_backup` (`task_id`), + CONSTRAINT `WorkReports_ibfk_4` FOREIGN KEY (`afternoon_task_id`) REFERENCES `tasks_old_backup` (`task_id`), + CONSTRAINT `WorkReports_ibfk_5` FOREIGN KEY (`overtime_task_id`) REFERENCES `tasks_old_backup` (`task_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1766 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `WorkReports` +-- + +LOCK TABLES `WorkReports` WRITE; +/*!40000 ALTER TABLE `WorkReports` DISABLE KEYS */; +INSERT INTO `WorkReports` VALUES +(176,'2025-01-02',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(177,'2025-01-02',2,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(178,'2025-01-02',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(179,'2025-01-02',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(180,'2025-01-02',8,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(181,'2025-01-02',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(182,'2025-01-02',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(183,'2025-01-02',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,15), +(194,'2025-01-03',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(195,'2025-01-03',2,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(196,'2025-01-03',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,15), +(197,'2025-01-03',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(198,'2025-01-03',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,15), +(199,'2025-01-03',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(200,'2025-01-03',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(201,'2025-01-03',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(202,'2025-01-03',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(203,'2025-01-04',7,12,NULL,NULL,NULL,NULL,'휴일근무',NULL,NULL,'2025-04-16 05:43:25','2025-04-16 05:43:25',NULL,NULL,NULL,12), +(204,'2025-01-06',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:03','2025-04-16 05:44:03',NULL,NULL,NULL,12), +(205,'2025-01-06',3,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:03','2025-04-16 05:44:03',NULL,NULL,NULL,12), +(206,'2025-01-06',2,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(207,'2025-01-06',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(208,'2025-01-06',8,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(209,'2025-01-06',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(210,'2025-01-06',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(211,'2025-01-06',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(212,'2025-01-06',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(213,'2025-01-07',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(214,'2025-01-07',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,1), +(215,'2025-01-07',3,12,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(216,'2025-01-07',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(217,'2025-01-07',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,1), +(218,'2025-01-07',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(219,'2025-01-07',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(220,'2025-01-07',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:25','2025-04-16 05:45:25',NULL,NULL,NULL,12), +(221,'2025-01-07',5,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:25','2025-04-16 05:45:25',NULL,NULL,NULL,1), +(222,'2025-01-08',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(223,'2025-01-08',2,2,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,1), +(224,'2025-01-08',3,12,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(225,'2025-01-08',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(226,'2025-01-08',8,2,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,1), +(227,'2025-01-08',9,12,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(228,'2025-01-08',6,12,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(229,'2025-01-08',4,2,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,1), +(230,'2025-01-08',5,12,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(231,'2025-01-09',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(232,'2025-01-09',2,2,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,1), +(233,'2025-01-09',3,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(234,'2025-01-09',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(235,'2025-01-09',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,1), +(236,'2025-01-09',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(237,'2025-01-09',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,1), +(238,'2025-01-09',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(239,'2025-01-09',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(240,'2025-01-10',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:16','2025-04-16 05:49:16',NULL,NULL,NULL,13), +(241,'2025-01-10',2,2,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,1), +(242,'2025-01-10',3,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,13), +(243,'2025-01-10',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,13), +(244,'2025-01-10',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,1), +(245,'2025-01-10',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,13), +(246,'2025-01-10',6,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,15), +(247,'2025-01-10',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,1), +(248,'2025-01-10',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,13), +(249,'2025-01-13',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,13), +(250,'2025-01-13',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,1), +(251,'2025-01-13',3,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,1), +(252,'2025-01-13',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,13), +(253,'2025-01-13',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,1), +(254,'2025-01-13',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,13), +(255,'2025-01-13',6,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,1), +(256,'2025-01-13',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,15), +(257,'2025-01-13',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,13), +(258,'2025-01-14',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(259,'2025-01-14',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,1), +(260,'2025-01-14',3,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,1), +(261,'2025-01-14',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(262,'2025-01-14',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,1), +(263,'2025-01-14',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(265,'2025-01-14',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(266,'2025-01-14',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(267,'2025-01-14',6,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,1), +(268,'2025-01-15',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,1), +(269,'2025-01-15',2,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,14), +(270,'2025-01-15',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,1), +(271,'2025-01-15',7,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,13), +(272,'2025-01-15',8,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,14), +(273,'2025-01-15',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,1), +(275,'2025-01-15',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,1), +(276,'2025-01-15',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:38','2025-04-16 05:52:38',NULL,NULL,NULL,1), +(277,'2025-01-15',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:38','2025-04-16 05:52:38',NULL,NULL,NULL,1), +(278,'2025-01-16',1,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,1), +(279,'2025-01-16',2,7,NULL,NULL,NULL,NULL,'근무',NULL,'볼트 보관함 제작','2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,14), +(280,'2025-01-16',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,1), +(281,'2025-01-16',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,1), +(282,'2025-01-16',8,7,NULL,NULL,NULL,NULL,'근무',NULL,'볼트 보관함 제작','2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,14), +(283,'2025-01-16',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:12','2025-04-16 05:54:12',NULL,NULL,NULL,1), +(285,'2025-01-16',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:12','2025-04-16 05:54:12',NULL,NULL,NULL,1), +(286,'2025-01-16',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:12','2025-04-16 05:54:12',NULL,NULL,NULL,1), +(287,'2025-01-16',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:12','2025-04-16 05:54:12',NULL,NULL,NULL,1), +(288,'2025-01-17',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(289,'2025-01-17',2,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(290,'2025-01-17',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(291,'2025-01-17',7,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(292,'2025-01-17',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(293,'2025-01-17',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(295,'2025-01-17',4,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(296,'2025-01-17',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(297,'2025-01-17',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(298,'2025-01-20',1,7,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,14), +(299,'2025-01-20',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,8), +(300,'2025-01-20',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,1), +(301,'2025-01-20',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,1), +(302,'2025-01-20',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,1), +(303,'2025-01-20',9,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,14), +(304,'2025-01-20',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,1), +(305,'2025-01-20',7,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,14), +(306,'2025-01-20',5,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,14), +(307,'2025-01-21',1,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,15), +(308,'2025-01-21',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,8), +(309,'2025-01-21',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,1), +(310,'2025-01-21',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,1), +(311,'2025-01-21',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,8), +(312,'2025-01-21',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,15), +(313,'2025-01-21',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,1), +(314,'2025-01-21',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,1), +(315,'2025-01-21',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:07','2025-04-16 05:59:07',NULL,NULL,NULL,1), +(316,'2025-01-22',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(317,'2025-01-22',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,8), +(318,'2025-01-22',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(319,'2025-01-22',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(320,'2025-01-22',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,8), +(321,'2025-01-22',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(322,'2025-01-22',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(323,'2025-01-22',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(324,'2025-01-22',5,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,8), +(325,'2025-01-23',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(326,'2025-01-23',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,8), +(327,'2025-01-23',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(328,'2025-01-23',7,1,NULL,NULL,NULL,NULL,'조퇴',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(329,'2025-01-23',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(330,'2025-01-23',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(331,'2025-01-23',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(332,'2025-01-23',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(333,'2025-01-23',5,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,8), +(334,'2025-01-24',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(335,'2025-01-24',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,8), +(336,'2025-01-24',3,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(337,'2025-01-24',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(338,'2025-01-24',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(339,'2025-01-24',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(340,'2025-01-24',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(341,'2025-01-24',5,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,8), +(342,'2025-01-24',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(343,'2025-02-03',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(344,'2025-02-03',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,8), +(345,'2025-02-03',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(346,'2025-02-03',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(347,'2025-02-03',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(348,'2025-02-03',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(349,'2025-02-03',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(350,'2025-02-03',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,8), +(351,'2025-02-03',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(352,'2025-02-04',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(353,'2025-02-04',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(354,'2025-02-04',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,8), +(355,'2025-02-04',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(356,'2025-02-04',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(357,'2025-02-04',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(358,'2025-02-04',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(359,'2025-02-04',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,8), +(360,'2025-02-04',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(361,'2025-02-05',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,8), +(362,'2025-02-05',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(363,'2025-02-05',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(364,'2025-02-05',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(365,'2025-02-05',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(366,'2025-02-05',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(367,'2025-02-05',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:03','2025-04-16 06:10:03',NULL,NULL,NULL,1), +(368,'2025-02-05',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:03','2025-04-16 06:10:03',NULL,NULL,NULL,8), +(369,'2025-02-05',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:03','2025-04-16 06:10:03',NULL,NULL,NULL,1), +(370,'2025-02-06',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(371,'2025-02-06',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,15), +(372,'2025-02-06',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(373,'2025-02-06',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(374,'2025-02-06',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(375,'2025-02-06',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(376,'2025-02-06',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(377,'2025-02-06',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(378,'2025-02-06',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(379,'2025-02-07',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(380,'2025-02-07',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,8), +(381,'2025-02-07',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(382,'2025-02-07',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,15), +(383,'2025-02-07',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(384,'2025-02-07',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(385,'2025-02-07',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(386,'2025-02-07',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,8), +(387,'2025-02-07',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(388,'2025-02-10',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(389,'2025-02-10',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,8), +(390,'2025-02-10',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(391,'2025-02-10',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(392,'2025-02-10',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(393,'2025-02-10',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(394,'2025-02-10',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(395,'2025-02-10',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,8), +(396,'2025-02-10',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(397,'2025-02-11',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(398,'2025-02-11',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,8), +(399,'2025-02-11',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(400,'2025-02-11',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(401,'2025-02-11',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(402,'2025-02-11',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(403,'2025-02-11',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(404,'2025-02-11',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,8), +(405,'2025-02-11',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(406,'2025-02-12',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(407,'2025-02-12',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,8), +(408,'2025-02-12',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(409,'2025-02-12',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(410,'2025-02-12',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(411,'2025-02-12',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(412,'2025-02-12',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,15), +(413,'2025-02-12',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(414,'2025-02-12',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(415,'2025-02-13',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(416,'2025-02-13',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,7), +(417,'2025-02-13',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(418,'2025-02-13',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(419,'2025-02-13',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(420,'2025-02-13',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(421,'2025-02-13',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(422,'2025-02-13',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,7), +(423,'2025-02-13',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(424,'2025-02-14',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(425,'2025-02-14',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,7), +(426,'2025-02-14',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(427,'2025-02-14',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(428,'2025-02-14',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(429,'2025-02-14',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(430,'2025-02-14',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(431,'2025-02-14',4,2,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,7), +(432,'2025-02-14',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(433,'2025-02-17',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:39','2025-04-16 06:18:39',NULL,NULL,NULL,1), +(434,'2025-02-17',2,2,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,8), +(435,'2025-02-17',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(436,'2025-02-17',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(437,'2025-02-17',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,15), +(438,'2025-02-17',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(439,'2025-02-17',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(440,'2025-02-17',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,8), +(441,'2025-02-17',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(442,'2025-02-18',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(443,'2025-02-18',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,15), +(444,'2025-02-18',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(445,'2025-02-18',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(446,'2025-02-18',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(447,'2025-02-18',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(448,'2025-02-18',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,7), +(449,'2025-02-18',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(450,'2025-02-18',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(451,'2025-02-19',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(452,'2025-02-19',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(453,'2025-02-19',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(454,'2025-02-19',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(455,'2025-02-19',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(456,'2025-02-19',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(457,'2025-02-19',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(458,'2025-02-19',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(459,'2025-02-19',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(460,'2025-02-20',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(461,'2025-02-20',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(462,'2025-02-20',3,1,NULL,NULL,NULL,NULL,'조퇴',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(463,'2025-02-20',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(464,'2025-02-20',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(465,'2025-02-20',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(466,'2025-02-20',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(467,'2025-02-20',7,1,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(468,'2025-02-20',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(469,'2025-02-21',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(470,'2025-02-21',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(471,'2025-02-21',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(472,'2025-02-21',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(473,'2025-02-21',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(474,'2025-02-21',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(475,'2025-02-21',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(476,'2025-02-21',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(477,'2025-02-21',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(478,'2025-02-24',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(479,'2025-02-24',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(480,'2025-02-24',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(481,'2025-02-24',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(482,'2025-02-24',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(483,'2025-02-24',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(484,'2025-02-24',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(485,'2025-02-24',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(486,'2025-02-24',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:33','2025-04-16 06:24:33',NULL,NULL,NULL,7), +(487,'2025-02-24',10,1,NULL,NULL,NULL,NULL,'근무',NULL,'근무시작','2025-04-16 06:25:07','2025-04-16 06:25:07',NULL,NULL,NULL,7), +(488,'2025-02-25',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(489,'2025-02-25',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(490,'2025-02-25',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(491,'2025-02-25',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(492,'2025-02-25',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(493,'2025-02-25',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(494,'2025-02-25',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(495,'2025-02-25',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(496,'2025-02-25',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(497,'2025-02-25',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(498,'2025-02-26',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'당진출장 건','2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,14), +(499,'2025-02-26',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(500,'2025-02-26',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(501,'2025-02-26',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'당진출장 건','2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,14), +(502,'2025-02-26',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(503,'2025-02-26',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(504,'2025-02-26',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(505,'2025-02-26',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,15), +(506,'2025-02-26',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(507,'2025-02-26',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(508,'2025-02-27',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(509,'2025-02-27',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(510,'2025-02-27',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(511,'2025-02-27',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(512,'2025-02-27',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(513,'2025-02-27',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(514,'2025-02-27',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(515,'2025-02-27',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(516,'2025-02-27',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(517,'2025-02-27',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(518,'2025-02-28',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,13), +(519,'2025-02-28',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(520,'2025-02-28',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(521,'2025-02-28',7,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,13), +(522,'2025-02-28',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(523,'2025-02-28',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(524,'2025-02-28',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(525,'2025-02-28',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(526,'2025-02-28',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,15), +(527,'2025-02-28',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(528,'2025-03-04',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(529,'2025-03-04',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(530,'2025-03-04',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,8), +(531,'2025-03-04',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,15), +(532,'2025-03-04',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(533,'2025-03-04',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(534,'2025-03-04',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(535,'2025-03-04',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(536,'2025-03-04',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(537,'2025-03-04',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,8), +(538,'2025-03-05',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(539,'2025-03-05',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(540,'2025-03-05',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,8), +(541,'2025-03-05',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(542,'2025-03-05',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(543,'2025-03-05',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(544,'2025-03-05',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(545,'2025-03-05',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,15), +(546,'2025-03-05',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(547,'2025-03-05',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,8), +(548,'2025-03-06',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(549,'2025-03-06',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(550,'2025-03-06',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,8), +(551,'2025-03-06',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,15), +(552,'2025-03-06',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(553,'2025-03-06',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(554,'2025-03-06',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(555,'2025-03-06',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(556,'2025-03-06',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(557,'2025-03-06',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,8), +(558,'2025-03-07',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(559,'2025-03-07',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,13), +(560,'2025-03-07',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,8), +(561,'2025-03-07',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,15), +(562,'2025-03-07',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(563,'2025-03-07',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(564,'2025-03-07',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(565,'2025-03-07',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,13), +(566,'2025-03-07',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(567,'2025-03-07',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,8), +(568,'2025-03-10',1,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,8), +(569,'2025-03-10',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,3), +(570,'2025-03-10',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,8), +(571,'2025-03-10',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,15), +(572,'2025-03-10',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,7), +(573,'2025-03-10',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,15), +(574,'2025-03-10',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,7), +(575,'2025-03-10',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,3), +(576,'2025-03-10',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,8), +(577,'2025-03-10',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,8), +(578,'2025-03-11',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:06','2025-04-16 06:39:06',NULL,NULL,NULL,8), +(579,'2025-03-11',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(580,'2025-03-11',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(581,'2025-03-11',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,7), +(582,'2025-03-11',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,7), +(583,'2025-03-11',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,15), +(584,'2025-03-11',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,7), +(585,'2025-03-11',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(586,'2025-03-11',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(587,'2025-03-11',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(588,'2025-03-12',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(589,'2025-03-12',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(590,'2025-03-12',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(591,'2025-03-12',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(592,'2025-03-12',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,7), +(593,'2025-03-12',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,15), +(594,'2025-03-12',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,7), +(595,'2025-03-12',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,7), +(596,'2025-03-12',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(597,'2025-03-12',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(598,'2025-03-13',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,8), +(599,'2025-03-13',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,8), +(600,'2025-03-13',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,8), +(601,'2025-03-13',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,7), +(602,'2025-03-13',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,7), +(603,'2025-03-13',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,15), +(604,'2025-03-13',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,7), +(605,'2025-03-13',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:08','2025-04-16 06:41:08',NULL,NULL,NULL,8), +(606,'2025-03-13',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:08','2025-04-16 06:41:08',NULL,NULL,NULL,8), +(607,'2025-03-13',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:08','2025-04-16 06:41:08',NULL,NULL,NULL,8), +(608,'2025-03-14',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,8), +(609,'2025-03-14',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,4), +(610,'2025-03-14',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,8), +(612,'2025-03-14',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,7), +(613,'2025-03-14',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,15), +(614,'2025-03-14',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,7), +(615,'2025-03-14',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,8), +(616,'2025-03-14',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,8), +(617,'2025-03-14',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,7), +(628,'2025-03-18',1,1,NULL,NULL,NULL,NULL,'조퇴',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(629,'2025-03-18',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,4), +(630,'2025-03-18',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(631,'2025-03-18',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,4), +(632,'2025-03-18',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(633,'2025-03-18',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,15), +(634,'2025-03-18',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(635,'2025-03-18',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,4), +(636,'2025-03-18',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(637,'2025-03-18',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(648,'2025-03-17',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,8), +(649,'2025-03-17',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,4), +(650,'2025-03-17',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,8), +(651,'2025-03-17',7,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,4), +(652,'2025-03-17',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,7), +(653,'2025-03-17',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,15), +(654,'2025-03-17',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,7), +(655,'2025-03-17',4,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,8), +(656,'2025-03-17',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,8), +(657,'2025-03-17',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,7), +(658,'2025-03-19',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,4), +(659,'2025-03-19',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,8), +(660,'2025-03-19',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,8), +(661,'2025-03-19',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,4), +(662,'2025-03-19',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,8), +(663,'2025-03-19',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,8), +(664,'2025-03-19',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,8), +(665,'2025-03-19',4,7,NULL,NULL,NULL,NULL,'근무',NULL,'용접기 보관함 제작','2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,14), +(666,'2025-03-19',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,4), +(667,'2025-03-19',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,8), +(668,'2025-03-20',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(669,'2025-03-20',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,4), +(670,'2025-03-20',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(671,'2025-03-20',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,4), +(672,'2025-03-20',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,4), +(673,'2025-03-20',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(674,'2025-03-20',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(675,'2025-03-20',4,7,NULL,NULL,2.0,NULL,'근무',NULL,'용접기 보관함 제작','2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,14), +(676,'2025-03-20',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,4), +(677,'2025-03-20',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(678,'2025-03-21',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:27','2025-04-16 21:34:27',NULL,NULL,NULL,8), +(679,'2025-03-21',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,4), +(680,'2025-03-21',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(681,'2025-03-21',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(682,'2025-03-21',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,4), +(683,'2025-03-21',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(684,'2025-03-21',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(685,'2025-03-21',4,7,NULL,NULL,NULL,NULL,'근무',NULL,'용기 보관함 제작','2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,14), +(686,'2025-03-21',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,4), +(687,'2025-03-21',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(688,'2025-03-24',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,8), +(689,'2025-03-24',2,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,5), +(690,'2025-03-24',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,8), +(691,'2025-03-24',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,5), +(692,'2025-03-24',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,5), +(693,'2025-03-24',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,8), +(694,'2025-03-24',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:48','2025-04-16 21:39:48',NULL,NULL,NULL,8), +(695,'2025-03-24',4,7,NULL,NULL,2.0,NULL,'근무',NULL,'용기 보관함 제작','2025-04-16 21:39:48','2025-04-16 21:39:48',NULL,NULL,NULL,14), +(696,'2025-03-24',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:48','2025-04-16 21:39:48',NULL,NULL,NULL,8), +(697,'2025-03-24',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:48','2025-04-16 21:39:48',NULL,NULL,NULL,8), +(698,'2025-03-25',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(699,'2025-03-25',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,5), +(700,'2025-03-25',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(701,'2025-03-25',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,5), +(702,'2025-03-25',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(703,'2025-03-25',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(704,'2025-03-25',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(705,'2025-03-25',4,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,14), +(706,'2025-03-25',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,5), +(707,'2025-03-25',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(708,'2025-03-26',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,13), +(709,'2025-03-26',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,15), +(710,'2025-03-26',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,5), +(711,'2025-03-26',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,5), +(712,'2025-03-26',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,8), +(713,'2025-03-26',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,8), +(714,'2025-03-26',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,8), +(715,'2025-03-26',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,13), +(716,'2025-03-26',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,5), +(717,'2025-03-26',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,8), +(718,'2025-03-27',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(719,'2025-03-27',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,5), +(720,'2025-03-27',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(721,'2025-03-27',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,5), +(722,'2025-03-27',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,5), +(723,'2025-03-27',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(724,'2025-03-27',10,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,15), +(725,'2025-03-27',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,5), +(726,'2025-03-27',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(727,'2025-03-27',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(728,'2025-03-28',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(729,'2025-03-28',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,5), +(730,'2025-03-28',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,15), +(731,'2025-03-28',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,15), +(732,'2025-03-28',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(733,'2025-03-28',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(734,'2025-03-28',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(735,'2025-03-28',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,5), +(736,'2025-03-28',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,5), +(737,'2025-03-28',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(738,'2025-03-31',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(739,'2025-03-31',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,5), +(740,'2025-03-31',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(741,'2025-03-31',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(742,'2025-03-31',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(743,'2025-03-31',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(744,'2025-03-31',10,13,NULL,NULL,NULL,NULL,'유급',NULL,'외조모상(2일)','2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,15), +(745,'2025-03-31',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,5), +(746,'2025-03-31',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(747,'2025-03-31',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(748,'2025-03-14',7,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-17 01:53:24','2025-04-17 01:53:24',NULL,NULL,NULL,4), +(749,'2025-04-01',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(750,'2025-04-01',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,5), +(751,'2025-04-01',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(752,'2025-04-01',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,5), +(753,'2025-04-01',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(754,'2025-04-01',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(755,'2025-04-01',10,13,NULL,NULL,NULL,NULL,'유급',NULL,'외조모상','2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,15), +(756,'2025-04-01',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,5), +(757,'2025-04-01',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(758,'2025-04-01',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:43','2025-04-17 04:22:43',NULL,NULL,NULL,9), +(769,'2025-04-02',1,1,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-17 04:25:55','2025-04-17 04:25:55',NULL,NULL,NULL,9), +(770,'2025-04-02',2,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(771,'2025-04-02',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(773,'2025-04-02',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(774,'2025-04-02',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(775,'2025-04-02',10,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,15), +(776,'2025-04-02',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,15), +(777,'2025-04-02',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(778,'2025-04-02',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(779,'2025-04-03',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(780,'2025-04-03',2,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(781,'2025-04-03',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(783,'2025-04-03',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(784,'2025-04-03',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(785,'2025-04-03',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(786,'2025-04-03',4,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(787,'2025-04-03',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(788,'2025-04-03',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(789,'2025-04-04',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(790,'2025-04-04',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(791,'2025-04-04',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,5), +(792,'2025-04-04',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(793,'2025-04-04',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,5), +(794,'2025-04-04',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(795,'2025-04-04',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(796,'2025-04-04',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(797,'2025-04-04',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(798,'2025-04-04',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,5), +(799,'2025-04-07',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(800,'2025-04-07',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(801,'2025-04-07',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,5), +(802,'2025-04-07',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(803,'2025-04-07',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,5), +(804,'2025-04-07',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(805,'2025-04-07',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(806,'2025-04-07',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(807,'2025-04-07',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(808,'2025-04-07',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,5), +(809,'2025-04-08',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(811,'2025-04-08',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,5), +(812,'2025-04-08',7,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(813,'2025-04-08',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,5), +(814,'2025-04-08',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(815,'2025-04-08',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(816,'2025-04-08',4,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(817,'2025-04-08',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(818,'2025-04-08',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,5), +(819,'2025-04-09',1,1,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-17 04:43:02','2025-04-17 04:43:02',NULL,NULL,NULL,9), +(820,'2025-04-09',2,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:02','2025-04-17 04:43:02',NULL,NULL,NULL,9), +(821,'2025-04-09',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,5), +(822,'2025-04-09',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(823,'2025-04-09',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,5), +(824,'2025-04-09',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(825,'2025-04-09',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(826,'2025-04-09',4,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(827,'2025-04-09',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(828,'2025-04-09',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,5), +(829,'2025-04-10',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(830,'2025-04-10',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(831,'2025-04-10',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,5), +(832,'2025-04-10',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(833,'2025-04-10',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,5), +(834,'2025-04-10',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(835,'2025-04-10',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(836,'2025-04-10',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(837,'2025-04-10',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(838,'2025-04-10',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,5), +(839,'2025-04-11',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:24','2025-04-17 04:46:24',NULL,NULL,NULL,9), +(840,'2025-04-11',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:24','2025-04-17 04:46:24',NULL,NULL,NULL,9), +(841,'2025-04-11',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:24','2025-04-17 04:46:24',NULL,NULL,NULL,5), +(842,'2025-04-11',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,9), +(843,'2025-04-11',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,5), +(844,'2025-04-11',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,15), +(845,'2025-04-11',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,5), +(846,'2025-04-11',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,9), +(847,'2025-04-11',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,15), +(848,'2025-04-11',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,9), +(849,'2025-04-14',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:37','2025-04-17 04:47:37',NULL,NULL,NULL,9), +(850,'2025-04-14',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:37','2025-04-17 04:47:37',NULL,NULL,NULL,9), +(851,'2025-04-14',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:37','2025-04-17 04:47:37',NULL,NULL,NULL,5), +(852,'2025-04-14',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:37','2025-04-17 04:47:37',NULL,NULL,NULL,9), +(853,'2025-04-14',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,5), +(854,'2025-04-14',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(855,'2025-04-14',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(856,'2025-04-14',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(857,'2025-04-14',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(858,'2025-04-14',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(859,'2025-04-17',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(860,'2025-04-17',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,5), +(861,'2025-04-17',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,5), +(862,'2025-04-17',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(863,'2025-04-17',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,5), +(864,'2025-04-17',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(865,'2025-04-17',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(866,'2025-04-17',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(867,'2025-04-17',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(868,'2025-04-17',6,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,5), +(879,'2025-04-21',1,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,14), +(880,'2025-04-21',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(881,'2025-04-21',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(882,'2025-04-21',7,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,14), +(883,'2025-04-21',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(884,'2025-04-21',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(885,'2025-04-21',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(886,'2025-04-21',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(887,'2025-04-21',5,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,14), +(888,'2025-04-21',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(889,'2025-04-22',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'ICK 크레인 공사','2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,14), +(890,'2025-04-22',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(891,'2025-04-22',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(892,'2025-04-22',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'ICK 크레인 공사','2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,14), +(893,'2025-04-22',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(894,'2025-04-22',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(895,'2025-04-22',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(896,'2025-04-22',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(897,'2025-04-22',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'ICK 크레인 공사','2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,14), +(898,'2025-04-22',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(899,'2025-04-23',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,14), +(900,'2025-04-23',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(901,'2025-04-23',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(902,'2025-04-23',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,14), +(903,'2025-04-23',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(904,'2025-04-23',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(905,'2025-04-23',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(906,'2025-04-23',4,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(907,'2025-04-23',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,14), +(908,'2025-04-23',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(909,'2025-04-24',1,1,NULL,NULL,NULL,NULL,'근무',NULL,'벨브 부적합 관련 작업 추가','2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(910,'2025-04-24',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(911,'2025-04-24',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(912,'2025-04-24',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(913,'2025-04-24',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(914,'2025-04-24',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(915,'2025-04-24',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(916,'2025-04-24',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(917,'2025-04-24',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(918,'2025-04-24',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(919,'2025-04-25',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(920,'2025-04-25',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(921,'2025-04-25',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,5), +(922,'2025-04-25',7,1,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(923,'2025-04-25',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(924,'2025-04-25',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(925,'2025-04-25',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(926,'2025-04-25',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'확관 작업','2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,5), +(927,'2025-04-25',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(928,'2025-04-25',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:39','2025-04-25 04:23:39',NULL,NULL,NULL,5), +(929,'2025-04-28',1,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:22','2025-04-28 23:20:22',NULL,NULL,NULL,9), +(930,'2025-04-28',2,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(931,'2025-04-28',3,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(932,'2025-04-28',7,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(934,'2025-04-28',9,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(935,'2025-04-28',10,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(936,'2025-04-28',4,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(937,'2025-04-28',5,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(938,'2025-04-28',6,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(939,'2025-04-29',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,9), +(940,'2025-04-29',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(941,'2025-04-29',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(942,'2025-04-29',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,9), +(943,'2025-04-29',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(944,'2025-04-29',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(945,'2025-04-29',10,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,14), +(946,'2025-04-29',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(947,'2025-04-29',8,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(948,'2025-04-29',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(949,'2025-04-30',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,14), +(950,'2025-04-30',2,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,16), +(951,'2025-04-30',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,16), +(953,'2025-04-30',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,15), +(954,'2025-04-30',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,16), +(955,'2025-04-30',10,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,14), +(956,'2025-04-30',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,14), +(957,'2025-04-30',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,15), +(958,'2025-04-30',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,16), +(959,'2025-04-30',4,7,NULL,NULL,NULL,NULL,'반반차',NULL,'제2공장 공사','2025-04-30 04:22:04','2025-04-30 04:22:04',NULL,NULL,NULL,14), +(1023,'2025-04-15',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1024,'2025-04-15',2,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1025,'2025-04-15',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1026,'2025-04-15',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1027,'2025-04-15',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1028,'2025-04-15',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1029,'2025-04-15',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1030,'2025-04-15',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1031,'2025-04-15',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1032,'2025-04-15',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1033,'2025-04-16',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1034,'2025-04-16',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,5), +(1035,'2025-04-16',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,5), +(1036,'2025-04-16',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1037,'2025-04-16',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1038,'2025-04-16',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,5), +(1039,'2025-04-16',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1040,'2025-04-16',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,15), +(1041,'2025-04-16',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,5), +(1042,'2025-04-16',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1043,'2025-04-18',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,9), +(1044,'2025-04-18',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1045,'2025-04-18',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1046,'2025-04-18',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,9), +(1047,'2025-04-18',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,15), +(1048,'2025-04-18',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1049,'2025-04-18',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,9), +(1050,'2025-04-18',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1051,'2025-04-18',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1052,'2025-04-18',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,9), +(1053,'2025-04-02',7,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-07 02:19:00','2025-05-07 02:19:00',NULL,NULL,NULL,9), +(1054,'2025-04-03',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 02:19:45','2025-05-07 02:19:45',NULL,NULL,NULL,9), +(1055,'2025-04-08',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 02:20:22','2025-05-07 02:20:22',NULL,NULL,NULL,9), +(1056,'2025-04-28',8,1,NULL,NULL,NULL,NULL,'반반차',NULL,'NCR 벨브라인 설치','2025-05-07 02:21:44','2025-05-07 02:21:44',NULL,NULL,NULL,9), +(1057,'2025-05-02',1,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1058,'2025-05-02',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1059,'2025-05-02',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1060,'2025-05-02',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1061,'2025-05-02',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1062,'2025-05-02',6,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1063,'2025-05-02',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1064,'2025-05-02',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1065,'2025-05-02',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1066,'2025-05-02',10,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1067,'2025-05-07',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,14), +(1068,'2025-05-07',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1069,'2025-05-07',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1070,'2025-05-07',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1071,'2025-05-07',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,14), +(1072,'2025-05-07',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1073,'2025-05-07',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,14), +(1074,'2025-05-07',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1075,'2025-05-07',9,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,14), +(1076,'2025-05-07',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1078,'2025-05-08',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1079,'2025-05-08',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1080,'2025-05-08',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1081,'2025-05-08',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,14), +(1082,'2025-05-08',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1083,'2025-05-08',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,14), +(1084,'2025-05-08',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1085,'2025-05-08',9,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,14), +(1086,'2025-05-08',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1087,'2025-05-08',1,7,NULL,NULL,NULL,NULL,'반반차',NULL,'작업장 구역 설치','2025-05-08 06:57:51','2025-05-08 06:57:51',NULL,NULL,NULL,14), +(1088,'2025-05-09',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,14), +(1089,'2025-05-09',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1090,'2025-05-09',3,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1091,'2025-05-09',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1092,'2025-05-09',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,14), +(1093,'2025-05-09',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1094,'2025-05-09',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,14), +(1095,'2025-05-09',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1096,'2025-05-09',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1097,'2025-05-09',10,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,14), +(1100,'2025-05-12',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-11 21:52:46','2025-05-11 21:52:46',NULL,NULL,NULL,15), +(1108,'2025-05-12',1,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1111,'2025-05-12',5,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1113,'2025-05-12',7,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1115,'2025-05-12',9,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1116,'2025-05-12',10,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1117,'2025-05-13',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,14), +(1118,'2025-05-13',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,3), +(1119,'2025-05-13',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,7), +(1120,'2025-05-13',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,3), +(1121,'2025-05-13',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,14), +(1122,'2025-05-13',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,7), +(1123,'2025-05-13',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,14), +(1124,'2025-05-13',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,7), +(1125,'2025-05-13',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,3), +(1126,'2025-05-13',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,7), +(1127,'2025-05-12',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:01:44','2025-05-13 00:01:44',NULL,NULL,NULL,3), +(1128,'2025-05-12',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:01:44','2025-05-13 00:01:44',NULL,NULL,NULL,3), +(1129,'2025-05-12',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:01:44','2025-05-13 00:01:44',NULL,NULL,NULL,3), +(1130,'2025-05-12',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:01:44','2025-05-13 00:01:44',NULL,NULL,NULL,3), +(1131,'2025-05-14',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,3), +(1132,'2025-05-14',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,3), +(1133,'2025-05-14',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1134,'2025-05-14',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1135,'2025-05-14',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1136,'2025-05-14',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,3), +(1137,'2025-05-14',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,3), +(1138,'2025-05-14',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1139,'2025-05-14',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1140,'2025-05-14',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1141,'2025-05-15',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,14), +(1142,'2025-05-15',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,3), +(1143,'2025-05-15',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1144,'2025-05-15',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1145,'2025-05-15',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1146,'2025-05-15',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1147,'2025-05-15',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,14), +(1148,'2025-05-15',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,3), +(1149,'2025-05-15',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,3), +(1150,'2025-05-15',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1151,'2025-05-16',1,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1152,'2025-05-16',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,3), +(1153,'2025-05-16',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1154,'2025-05-16',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1155,'2025-05-16',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1156,'2025-05-16',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1157,'2025-05-16',7,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1158,'2025-05-16',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,3), +(1159,'2025-05-16',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,3), +(1160,'2025-05-16',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1171,'2025-05-19',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1172,'2025-05-19',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,4), +(1173,'2025-05-19',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1174,'2025-05-19',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1175,'2025-05-19',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1176,'2025-05-19',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1177,'2025-05-19',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1179,'2025-05-19',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1180,'2025-05-19',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1181,'2025-05-21',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1183,'2025-05-21',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1184,'2025-05-21',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1185,'2025-05-21',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1186,'2025-05-21',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1187,'2025-05-21',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1188,'2025-05-21',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1189,'2025-05-21',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1190,'2025-05-21',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1191,'2025-05-20',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1192,'2025-05-20',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,3), +(1193,'2025-05-20',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1194,'2025-05-20',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1195,'2025-05-20',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1196,'2025-05-20',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1197,'2025-05-20',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1198,'2025-05-20',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1199,'2025-05-20',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1200,'2025-05-20',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1201,'2025-05-22',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1202,'2025-05-22',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,3), +(1203,'2025-05-22',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1204,'2025-05-22',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1205,'2025-05-22',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1206,'2025-05-22',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1207,'2025-05-22',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1208,'2025-05-22',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1209,'2025-05-22',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1210,'2025-05-22',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1211,'2025-05-21',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-22 04:54:12','2025-05-22 04:54:12',NULL,NULL,NULL,15), +(1215,'2025-05-26',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-26 06:58:00','2025-05-26 06:58:00',NULL,NULL,NULL,15), +(1222,'2025-05-19',8,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-01 22:34:36','2025-06-01 22:34:36',NULL,NULL,NULL,3), +(1223,'2025-05-26',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1224,'2025-05-26',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,5), +(1225,'2025-05-26',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1226,'2025-05-26',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,5), +(1227,'2025-05-26',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1228,'2025-05-26',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1229,'2025-05-26',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,5), +(1230,'2025-05-26',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1231,'2025-05-26',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1232,'2025-05-23',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1233,'2025-05-23',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,3), +(1234,'2025-05-23',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1235,'2025-05-23',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1236,'2025-05-23',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1237,'2025-05-23',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1238,'2025-05-23',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1239,'2025-05-23',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1240,'2025-05-23',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1241,'2025-05-23',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1242,'2025-05-27',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1243,'2025-05-27',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,5), +(1244,'2025-05-27',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1245,'2025-05-27',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1246,'2025-05-27',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,5), +(1247,'2025-05-27',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1248,'2025-05-27',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1249,'2025-05-27',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,5), +(1250,'2025-05-27',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1251,'2025-05-27',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1252,'2025-05-28',1,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-06-01 22:46:40','2025-06-01 22:46:40',NULL,NULL,NULL,8), +(1258,'2025-05-28',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:46:40','2025-06-01 22:46:40',NULL,NULL,NULL,8), +(1262,'2025-05-28',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,5), +(1263,'2025-05-28',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1264,'2025-05-28',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1265,'2025-05-28',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,5), +(1266,'2025-05-28',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1267,'2025-05-28',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,5), +(1268,'2025-05-28',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1269,'2025-05-28',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1270,'2025-05-29',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1271,'2025-05-29',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,5), +(1272,'2025-05-29',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1273,'2025-05-29',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1274,'2025-05-29',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,5), +(1275,'2025-05-29',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1276,'2025-05-29',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1277,'2025-05-29',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,5), +(1278,'2025-05-29',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1279,'2025-05-29',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1281,'2025-05-30',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,5), +(1282,'2025-05-30',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1283,'2025-05-30',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1284,'2025-05-30',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,5), +(1285,'2025-05-30',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1286,'2025-05-30',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1287,'2025-05-30',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,5), +(1288,'2025-05-30',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1289,'2025-05-30',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1290,'2025-06-02',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:18','2025-06-01 22:52:18',NULL,NULL,NULL,8), +(1291,'2025-06-02',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,5), +(1292,'2025-06-02',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1293,'2025-06-02',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1294,'2025-06-02',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,15), +(1295,'2025-06-02',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1296,'2025-06-02',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1297,'2025-06-02',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,15), +(1298,'2025-06-02',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1299,'2025-06-02',10,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,15), +(1300,'2025-05-30',1,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-01 23:17:51','2025-06-01 23:17:51',NULL,NULL,NULL,8), +(1301,'2025-01-02',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-01 23:31:26','2025-06-01 23:31:26',NULL,NULL,NULL,15), +(1302,'2025-06-04',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1303,'2025-06-04',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,5), +(1304,'2025-06-04',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1305,'2025-06-04',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,15), +(1306,'2025-06-04',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1307,'2025-06-04',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,5), +(1308,'2025-06-04',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1309,'2025-06-04',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,5), +(1310,'2025-06-04',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1311,'2025-06-04',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1312,'2025-06-09',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:28',NULL,NULL,NULL,8), +(1313,'2025-06-09',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,5), +(1314,'2025-06-09',3,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:30',NULL,NULL,NULL,8), +(1315,'2025-06-09',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,5), +(1316,'2025-06-09',5,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:31',NULL,NULL,NULL,8), +(1317,'2025-06-09',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,5), +(1318,'2025-06-09',7,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:32',NULL,NULL,NULL,8), +(1319,'2025-06-09',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,5), +(1320,'2025-06-09',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,15), +(1321,'2025-06-09',10,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:34',NULL,NULL,NULL,8), +(1322,'2025-06-10',1,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:03','2025-06-13 03:43:51',NULL,NULL,NULL,8), +(1323,'2025-06-10',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-10 08:47:03','2025-06-10 08:47:03',NULL,NULL,NULL,5), +(1324,'2025-06-10',3,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:03','2025-06-13 03:43:53',NULL,NULL,NULL,8), +(1325,'2025-06-10',4,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:04','2025-06-13 03:43:54',NULL,NULL,NULL,8), +(1326,'2025-06-10',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-10 08:47:04','2025-06-10 08:47:04',NULL,NULL,NULL,5), +(1327,'2025-06-10',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-10 08:47:04','2025-06-10 08:47:04',NULL,NULL,NULL,5), +(1328,'2025-06-10',7,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:04','2025-06-13 03:43:55',NULL,NULL,NULL,8), +(1329,'2025-06-10',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-10 08:47:04','2025-06-10 08:47:04',NULL,NULL,NULL,5), +(1330,'2025-06-10',9,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:04','2025-06-13 03:43:56',NULL,NULL,NULL,8), +(1331,'2025-06-10',10,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:04','2025-06-13 03:43:56',NULL,NULL,NULL,8), +(1332,'2025-06-11',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:18',NULL,NULL,NULL,8), +(1333,'2025-06-11',2,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-11 07:59:16','2025-06-11 07:59:16',NULL,NULL,NULL,5), +(1334,'2025-06-11',3,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:19',NULL,NULL,NULL,8), +(1335,'2025-06-11',4,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:20',NULL,NULL,NULL,8), +(1336,'2025-06-11',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-11 07:59:16','2025-06-11 07:59:16',NULL,NULL,NULL,5), +(1337,'2025-06-11',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-11 07:59:16','2025-06-11 07:59:16',NULL,NULL,NULL,5), +(1338,'2025-06-11',7,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:22',NULL,NULL,NULL,8), +(1339,'2025-06-11',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-11 07:59:16','2025-06-11 07:59:16',NULL,NULL,NULL,5), +(1340,'2025-06-11',9,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:23',NULL,NULL,NULL,8), +(1341,'2025-06-11',10,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:23',NULL,NULL,NULL,8), +(1342,'2025-06-13',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1343,'2025-06-13',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,5), +(1344,'2025-06-13',3,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1345,'2025-06-13',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1346,'2025-06-13',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,5), +(1347,'2025-06-13',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,5), +(1348,'2025-06-13',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,15), +(1349,'2025-06-13',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,5), +(1350,'2025-06-13',9,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1351,'2025-06-13',10,4,NULL,NULL,NULL,NULL,'반차',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1352,'2025-06-05',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1353,'2025-06-05',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,5), +(1354,'2025-06-05',3,4,NULL,NULL,NULL,NULL,'반차',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1355,'2025-06-05',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1356,'2025-06-05',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,5), +(1357,'2025-06-05',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,5), +(1358,'2025-06-05',7,4,NULL,NULL,NULL,NULL,'반반차',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1359,'2025-06-05',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,5), +(1360,'2025-06-05',9,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1361,'2025-06-05',10,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1362,'2025-06-12',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1363,'2025-06-12',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,5), +(1364,'2025-06-12',3,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1365,'2025-06-12',4,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1366,'2025-06-12',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,5), +(1367,'2025-06-12',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,5), +(1368,'2025-06-12',7,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1369,'2025-06-12',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,5), +(1370,'2025-06-12',9,4,NULL,NULL,NULL,NULL,'반차',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1371,'2025-06-12',10,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1372,'2025-06-16',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:26','2025-06-16 04:26:26',NULL,NULL,NULL,8), +(1373,'2025-06-16',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,5), +(1374,'2025-06-16',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,8), +(1375,'2025-06-16',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,8), +(1376,'2025-06-16',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,5), +(1377,'2025-06-16',6,3,NULL,NULL,NULL,NULL,'근무',NULL,'Vessel NDE 불량 수리','2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,5), +(1378,'2025-06-16',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,15), +(1379,'2025-06-16',8,3,NULL,NULL,NULL,NULL,'근무',NULL,'Vessel NDE 불량 수리','2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,5), +(1380,'2025-06-16',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,8), +(1381,'2025-06-16',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,8), +(1382,'2025-06-17',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1383,'2025-06-17',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,5), +(1384,'2025-06-17',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1385,'2025-06-17',4,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:36:28',NULL,NULL,NULL,5), +(1386,'2025-06-17',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,5), +(1387,'2025-06-17',6,3,NULL,NULL,2.0,NULL,'근무',NULL,'용기 비파괴 불량','2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,5), +(1388,'2025-06-17',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1389,'2025-06-17',8,3,NULL,NULL,2.0,NULL,'근무',NULL,'용기 비파괴 불량','2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,5), +(1390,'2025-06-17',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1391,'2025-06-17',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1392,'2025-06-18',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1393,'2025-06-18',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,5), +(1394,'2025-06-18',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1395,'2025-06-18',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1396,'2025-06-18',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,5), +(1397,'2025-06-18',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,5), +(1398,'2025-06-18',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1399,'2025-06-18',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,5), +(1400,'2025-06-18',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1401,'2025-06-18',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1402,'2025-06-24',1,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1403,'2025-06-24',2,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,5), +(1404,'2025-06-24',3,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1405,'2025-06-24',4,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1406,'2025-06-24',5,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1407,'2025-06-24',6,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1408,'2025-06-24',7,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1409,'2025-06-24',8,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,5), +(1410,'2025-06-24',9,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1411,'2025-06-24',10,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1412,'2025-06-25',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1413,'2025-06-25',2,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,5), +(1414,'2025-06-25',3,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1415,'2025-06-25',4,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1416,'2025-06-25',5,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1417,'2025-06-25',6,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1418,'2025-06-25',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1419,'2025-06-25',8,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,5), +(1420,'2025-06-25',9,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1421,'2025-06-25',10,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1422,'2025-06-26',1,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1423,'2025-06-26',2,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,5), +(1424,'2025-06-26',3,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,5), +(1425,'2025-06-26',4,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1426,'2025-06-26',5,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1427,'2025-06-26',6,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,5), +(1428,'2025-06-26',7,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1429,'2025-06-26',8,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,5), +(1430,'2025-06-26',9,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1431,'2025-06-26',10,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1432,'2025-06-27',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1433,'2025-06-27',2,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1434,'2025-06-27',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1435,'2025-06-27',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1436,'2025-06-27',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1437,'2025-06-27',6,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1438,'2025-06-27',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1439,'2025-06-27',8,3,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1440,'2025-06-27',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1441,'2025-06-27',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1442,'2025-06-19',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1443,'2025-06-19',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,5), +(1444,'2025-06-19',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1445,'2025-06-19',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1446,'2025-06-19',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,5), +(1447,'2025-06-19',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1448,'2025-06-19',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1449,'2025-06-19',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,5), +(1450,'2025-06-19',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1451,'2025-06-19',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1452,'2025-06-20',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1453,'2025-06-20',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,5), +(1454,'2025-06-20',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1455,'2025-06-20',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1456,'2025-06-20',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,5), +(1457,'2025-06-20',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1458,'2025-06-20',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1459,'2025-06-20',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,5), +(1460,'2025-06-20',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1461,'2025-06-20',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1462,'2025-06-23',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1463,'2025-06-23',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,5), +(1464,'2025-06-23',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1465,'2025-06-23',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1466,'2025-06-23',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,5), +(1467,'2025-06-23',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1468,'2025-06-23',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1469,'2025-06-23',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,5), +(1470,'2025-06-23',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1471,'2025-06-23',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1472,'2025-06-30',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1473,'2025-06-30',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,5), +(1474,'2025-06-30',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1475,'2025-06-30',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1476,'2025-06-30',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,5), +(1477,'2025-06-30',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,5), +(1478,'2025-06-30',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1479,'2025-06-30',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,5), +(1480,'2025-06-30',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1481,'2025-06-30',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1482,'2025-07-01',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,8), +(1483,'2025-07-01',2,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1484,'2025-07-01',3,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1485,'2025-07-01',4,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,8), +(1486,'2025-07-01',5,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,8), +(1487,'2025-07-01',6,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1488,'2025-07-01',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,8), +(1489,'2025-07-01',8,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1490,'2025-07-01',9,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1491,'2025-07-01',10,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1492,'2025-07-02',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,9), +(1493,'2025-07-02',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1494,'2025-07-02',3,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1495,'2025-07-02',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,9), +(1496,'2025-07-02',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,9), +(1497,'2025-07-02',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1498,'2025-07-02',7,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1499,'2025-07-02',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1500,'2025-07-02',9,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1501,'2025-07-02',10,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1502,'2025-07-03',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1503,'2025-07-03',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,5), +(1504,'2025-07-03',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1505,'2025-07-03',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1506,'2025-07-03',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1507,'2025-07-03',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,5), +(1508,'2025-07-03',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1509,'2025-07-03',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,5), +(1510,'2025-07-03',9,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,5), +(1511,'2025-07-03',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1512,'2025-07-04',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1513,'2025-07-04',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1514,'2025-07-04',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1515,'2025-07-04',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1516,'2025-07-04',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1517,'2025-07-04',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1518,'2025-07-04',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1519,'2025-07-04',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1520,'2025-07-04',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1521,'2025-07-04',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1522,'2025-07-05',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1523,'2025-07-05',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1524,'2025-07-05',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1525,'2025-07-05',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1526,'2025-07-05',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1527,'2025-07-05',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1528,'2025-07-06',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1529,'2025-07-06',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1530,'2025-07-06',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1531,'2025-07-06',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1532,'2025-07-06',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1533,'2025-07-06',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1534,'2025-07-06',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1535,'2025-07-06',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1536,'2025-07-07',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1537,'2025-07-07',2,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1538,'2025-07-07',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1539,'2025-07-07',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1540,'2025-07-07',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1541,'2025-07-07',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1542,'2025-07-07',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1543,'2025-07-07',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1544,'2025-07-07',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1545,'2025-07-07',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1546,'2025-07-08',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1547,'2025-07-08',2,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1548,'2025-07-08',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1549,'2025-07-08',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1550,'2025-07-08',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1551,'2025-07-08',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1552,'2025-07-08',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1553,'2025-07-08',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1554,'2025-07-08',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1555,'2025-07-08',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1556,'2025-07-09',1,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1557,'2025-07-09',2,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1558,'2025-07-09',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1559,'2025-07-09',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1560,'2025-07-09',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1561,'2025-07-09',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1562,'2025-07-09',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1563,'2025-07-09',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1564,'2025-07-09',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1565,'2025-07-09',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1566,'2025-07-10',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1567,'2025-07-10',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1568,'2025-07-10',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1569,'2025-07-10',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1570,'2025-07-10',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1571,'2025-07-10',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1572,'2025-07-10',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1573,'2025-07-10',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1574,'2025-07-10',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1575,'2025-07-10',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1576,'2025-07-14',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1577,'2025-07-14',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1578,'2025-07-14',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1579,'2025-07-14',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1580,'2025-07-14',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1581,'2025-07-14',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1582,'2025-07-14',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1583,'2025-07-14',8,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1584,'2025-07-14',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1585,'2025-07-14',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1586,'2025-07-15',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:41','2025-07-30 02:23:58',NULL,NULL,NULL,8), +(1587,'2025-07-15',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:41','2025-07-30 02:23:58',NULL,NULL,NULL,8), +(1588,'2025-07-15',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:41','2025-07-30 02:24:00',NULL,NULL,NULL,8), +(1589,'2025-07-15',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-07-30 02:08:41','2025-07-30 02:24:00',NULL,NULL,NULL,15), +(1590,'2025-07-15',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:01',NULL,NULL,NULL,5), +(1591,'2025-07-15',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:02',NULL,NULL,NULL,8), +(1592,'2025-07-15',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:02',NULL,NULL,NULL,8), +(1593,'2025-07-15',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:03',NULL,NULL,NULL,8), +(1594,'2025-07-15',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:03',NULL,NULL,NULL,5), +(1595,'2025-07-15',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:04',NULL,NULL,NULL,8), +(1596,'2025-07-16',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:17','2025-07-30 02:10:17',NULL,NULL,NULL,8), +(1597,'2025-07-16',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1598,'2025-07-16',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1599,'2025-07-16',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,8), +(1600,'2025-07-16',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1601,'2025-07-16',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1602,'2025-07-16',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,8), +(1603,'2025-07-16',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1604,'2025-07-16',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1605,'2025-07-16',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1606,'2025-07-17',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:24:31',NULL,NULL,NULL,7), +(1607,'2025-07-17',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1608,'2025-07-17',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1609,'2025-07-17',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1610,'2025-07-17',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1611,'2025-07-17',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1612,'2025-07-17',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1613,'2025-07-17',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1614,'2025-07-17',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1615,'2025-07-17',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1616,'2025-07-18',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,9), +(1617,'2025-07-18',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1618,'2025-07-18',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1619,'2025-07-18',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1620,'2025-07-18',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,9), +(1621,'2025-07-18',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1622,'2025-07-18',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,9), +(1623,'2025-07-18',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1624,'2025-07-18',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1625,'2025-07-18',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1626,'2025-07-21',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,7), +(1627,'2025-07-21',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1628,'2025-07-21',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1629,'2025-07-21',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,9), +(1630,'2025-07-21',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,9), +(1631,'2025-07-21',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1632,'2025-07-21',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1633,'2025-07-21',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1634,'2025-07-21',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1635,'2025-07-21',10,3,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1636,'2025-07-22',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,5), +(1637,'2025-07-22',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1638,'2025-07-22',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1639,'2025-07-22',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,7), +(1640,'2025-07-22',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,7), +(1641,'2025-07-22',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1642,'2025-07-22',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1643,'2025-07-22',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1644,'2025-07-22',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1645,'2025-07-22',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1646,'2025-07-23',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,7), +(1647,'2025-07-23',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1648,'2025-07-23',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1649,'2025-07-23',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,7), +(1650,'2025-07-23',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,7), +(1651,'2025-07-23',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1652,'2025-07-23',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1653,'2025-07-23',8,13,NULL,NULL,NULL,NULL,'유급',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 22:39:10',NULL,NULL,NULL,15), +(1654,'2025-07-23',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1655,'2025-07-23',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1656,'2025-07-24',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,7), +(1657,'2025-07-24',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1658,'2025-07-24',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1659,'2025-07-24',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,7), +(1660,'2025-07-24',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,7), +(1661,'2025-07-24',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1662,'2025-07-24',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1663,'2025-07-24',8,13,NULL,NULL,NULL,NULL,'유급',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,15), +(1664,'2025-07-24',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1665,'2025-07-24',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1666,'2025-07-25',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,13), +(1667,'2025-07-25',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1668,'2025-07-25',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1669,'2025-07-25',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1670,'2025-07-25',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,13), +(1671,'2025-07-25',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,13), +(1672,'2025-07-25',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,18), +(1673,'2025-07-25',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1674,'2025-07-25',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1675,'2025-07-25',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1676,'2025-07-28',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,7), +(1677,'2025-07-28',2,5,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,13), +(1678,'2025-07-28',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1679,'2025-07-28',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,7), +(1680,'2025-07-28',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,7), +(1681,'2025-07-28',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1682,'2025-07-28',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1683,'2025-07-28',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1684,'2025-07-28',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1685,'2025-07-28',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1686,'2025-07-11',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1687,'2025-07-11',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1688,'2025-07-11',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1689,'2025-07-11',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1690,'2025-07-11',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1691,'2025-07-11',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1692,'2025-07-11',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1693,'2025-07-11',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1694,'2025-07-11',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1695,'2025-07-11',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:31','2025-07-30 22:48:31',NULL,NULL,NULL,9), +(1696,'2025-07-12',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1697,'2025-07-12',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1698,'2025-07-12',3,13,NULL,NULL,NULL,NULL,'휴무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,15), +(1699,'2025-07-12',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1700,'2025-07-12',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1701,'2025-07-12',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1702,'2025-07-12',7,13,NULL,NULL,NULL,NULL,'휴무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,15), +(1703,'2025-07-12',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1704,'2025-07-12',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1705,'2025-07-12',10,13,NULL,NULL,NULL,NULL,'휴무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,15), +(1706,'2025-07-29',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,7), +(1707,'2025-07-29',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1708,'2025-07-29',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1709,'2025-07-29',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,7), +(1710,'2025-07-29',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,7), +(1711,'2025-07-29',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1712,'2025-07-29',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1713,'2025-07-29',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1714,'2025-07-29',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1715,'2025-07-29',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1716,'2025-07-30',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,7), +(1717,'2025-07-30',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1718,'2025-07-30',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1719,'2025-07-30',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,7), +(1720,'2025-07-30',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,7), +(1721,'2025-07-30',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1722,'2025-07-30',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1723,'2025-07-30',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1724,'2025-07-30',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1725,'2025-07-30',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1726,'2025-07-31',1,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,7), +(1727,'2025-07-31',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1728,'2025-07-31',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1729,'2025-07-31',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,7), +(1730,'2025-07-31',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,7), +(1731,'2025-07-31',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1732,'2025-07-31',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1733,'2025-07-31',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1734,'2025-07-31',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1735,'2025-07-31',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1736,'2025-09-18',1,3,NULL,NULL,NULL,NULL,'근무',NULL,'냉동기','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,18), +(1737,'2025-09-18',2,8,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,8), +(1738,'2025-09-18',3,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1739,'2025-09-18',4,8,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,8), +(1740,'2025-09-18',5,3,NULL,NULL,NULL,NULL,'근무',NULL,'냉동기','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,9), +(1741,'2025-09-18',6,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1742,'2025-09-18',7,3,NULL,NULL,NULL,NULL,'근무',NULL,'냉동기','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,18), +(1743,'2025-09-18',8,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1744,'2025-09-18',9,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1745,'2025-09-18',10,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1746,'2025-10-01',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,16), +(1747,'2025-10-01',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,16), +(1748,'2025-10-01',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1749,'2025-10-01',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,5), +(1750,'2025-10-01',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,16), +(1751,'2025-10-01',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1752,'2025-10-01',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1753,'2025-10-01',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1754,'2025-10-01',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1755,'2025-10-01',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1756,'2025-10-02',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1757,'2025-10-02',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1758,'2025-10-02',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,15), +(1759,'2025-10-02',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1760,'2025-10-02',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1761,'2025-10-02',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1762,'2025-10-02',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1763,'2025-10-02',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1764,'2025-10-02',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1765,'2025-10-02',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7); +/*!40000 ALTER TABLE `WorkReports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `activity_logs` +-- + +DROP TABLE IF EXISTS `activity_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `activity_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL, + `activity_type` varchar(100) DEFAULT NULL, + `table_name` varchar(50) DEFAULT NULL, + `record_id` int(11) DEFAULT NULL, + `action` enum('create','read','update','delete') DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + PRIMARY KEY (`log_id`), + KEY `idx_user_activity` (`user_id`,`activity_type`,`created_at`), + KEY `idx_table_record` (`table_name`,`record_id`), + CONSTRAINT `activity_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `activity_logs` +-- + +LOCK TABLES `activity_logs` WRITE; +/*!40000 ALTER TABLE `activity_logs` DISABLE KEYS */; +/*!40000 ALTER TABLE `activity_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `daily_attendance_records` +-- + +DROP TABLE IF EXISTS `daily_attendance_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_attendance_records` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `worker_id` int(10) unsigned NOT NULL COMMENT '작업자 ID', + `record_date` date NOT NULL COMMENT '기록 날짜', + `attendance_type_id` int(10) unsigned NOT NULL COMMENT '출근 유형 ID', + `vacation_type_id` int(10) unsigned DEFAULT NULL COMMENT '휴가 유형 ID', + `check_in_time` time DEFAULT NULL COMMENT '출근 시간', + `check_out_time` time DEFAULT NULL COMMENT '퇴근 시간', + `total_work_hours` decimal(4,2) DEFAULT 0.00 COMMENT '총 근무 시간', + `is_overtime_approved` tinyint(1) DEFAULT 0 COMMENT '초과근무 승인 여부', + `notes` text DEFAULT NULL COMMENT '비고', + `created_by` int(10) unsigned NOT NULL COMMENT '등록자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `is_present` tinyint(1) DEFAULT 1 COMMENT '출근 여부', + PRIMARY KEY (`id`), + UNIQUE KEY `daily_attendance_records_worker_id_record_date_unique` (`worker_id`,`record_date`) +) ENGINE=InnoDB AUTO_INCREMENT=231 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_attendance_records` +-- + +LOCK TABLES `daily_attendance_records` WRITE; +/*!40000 ALTER TABLE `daily_attendance_records` DISABLE KEYS */; +INSERT INTO `daily_attendance_records` VALUES +(1,11,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(2,10,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(3,9,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(4,8,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(5,6,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(6,5,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(7,4,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(8,3,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(9,2,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(10,1,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(11,11,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(12,10,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(13,9,'2026-01-05',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',0), +(14,8,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(15,6,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(16,5,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(17,4,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(18,3,'2026-01-05',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',0), +(19,2,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(20,1,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(21,11,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(22,10,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(23,9,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(24,8,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(25,6,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(26,5,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(27,4,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(28,3,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(29,2,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(30,1,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(31,11,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(32,10,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(33,9,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(34,8,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(35,6,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(36,5,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(37,4,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(38,3,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(39,2,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(40,1,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(41,11,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(42,10,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(43,9,'2026-01-06',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',0), +(44,8,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(45,6,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(46,5,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(47,4,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(48,3,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(49,2,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(50,1,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(51,11,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(52,10,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(53,9,'2026-01-07',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(54,8,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(55,6,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(56,5,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(57,4,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(58,3,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(59,2,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(60,1,'2026-01-07',4,3,NULL,NULL,6.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(61,11,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(62,10,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(63,9,'2026-01-08',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(64,8,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(65,6,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(66,5,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(67,4,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(68,3,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(69,2,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(70,1,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(71,11,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(72,10,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(73,9,'2026-01-09',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(74,8,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(75,6,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(76,5,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(77,4,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(78,3,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(79,2,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(80,1,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(81,11,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:37',1), +(82,10,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:37',1), +(83,9,'2026-01-12',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:37',1), +(84,8,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:37',1), +(85,6,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(86,5,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(87,4,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(88,3,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(89,2,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(90,1,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(91,11,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(92,10,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(93,9,'2026-01-13',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(94,8,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(95,6,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(96,5,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(97,4,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(98,3,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(99,2,'2026-01-13',4,2,NULL,NULL,4.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(100,1,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(101,11,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(102,10,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(103,9,'2026-01-14',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',0), +(104,8,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(105,6,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(106,5,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(107,4,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(108,3,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(109,2,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(110,1,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(111,11,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(112,10,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(113,9,'2026-01-15',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',0), +(114,8,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(115,6,'2026-01-15',3,NULL,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(116,5,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(117,4,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(118,3,'2026-01-15',5,2,NULL,NULL,4.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(119,2,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(120,1,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(121,11,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(122,10,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(123,9,'2026-01-16',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',0), +(124,8,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(125,6,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(126,5,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(127,4,'2026-01-16',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',0), +(128,3,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(129,2,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(130,1,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(131,11,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(132,10,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(133,9,'2026-01-19',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',0), +(134,8,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(135,6,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(136,5,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(137,4,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(138,3,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(139,2,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(140,1,'2026-01-19',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',0), +(141,11,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(142,10,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(143,9,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(144,8,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(145,6,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(146,5,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(147,4,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(148,3,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(149,2,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(150,1,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(151,11,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(152,10,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(153,9,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(154,8,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(155,6,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(156,5,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(157,4,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(158,3,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(159,2,'2026-01-21',5,2,NULL,NULL,4.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(160,1,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(161,11,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(162,10,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(163,9,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(164,8,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(165,6,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(166,5,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(167,4,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(168,3,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(169,2,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(170,1,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(171,11,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(172,10,'2026-01-23',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',0), +(173,9,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(174,8,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(175,6,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(176,5,'2026-01-23',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',0), +(177,4,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(178,3,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(179,2,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(180,1,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(181,11,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(182,10,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(183,9,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(184,8,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(185,6,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(186,5,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(187,4,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(188,3,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(189,2,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(190,1,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(191,11,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(192,10,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(193,9,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(194,8,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(195,6,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(196,5,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(197,4,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(198,3,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(199,2,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(200,1,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(201,11,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(202,10,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(203,9,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(204,8,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(205,6,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(206,5,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(207,4,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(208,3,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(209,2,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(210,1,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(211,11,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(212,10,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(213,9,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(214,8,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(215,6,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(216,5,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(217,4,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(218,3,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(219,2,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(220,1,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(221,11,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(222,10,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(223,9,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(224,8,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(225,6,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(226,5,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(227,4,'2026-01-30',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',0), +(228,3,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(229,2,'2026-01-30',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',0), +(230,1,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1); +/*!40000 ALTER TABLE `daily_attendance_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `daily_patrol_sessions` +-- + +DROP TABLE IF EXISTS `daily_patrol_sessions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_patrol_sessions` ( + `session_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `patrol_date` date NOT NULL COMMENT '점검 날짜', + `patrol_time` enum('morning','afternoon') NOT NULL COMMENT '점검 시간대', + `inspector_id` int(11) NOT NULL COMMENT '순찰자 user_id', + `category_id` int(10) unsigned DEFAULT NULL COMMENT '공장 ID', + `status` enum('in_progress','completed') DEFAULT 'in_progress' COMMENT '상태', + `notes` text DEFAULT NULL COMMENT '특이사항', + `started_at` time DEFAULT NULL COMMENT '점검 시작 시간', + `completed_at` time DEFAULT NULL COMMENT '점검 완료 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`session_id`), + UNIQUE KEY `daily_patrol_sessions_patrol_date_patrol_time_category_id_unique` (`patrol_date`,`patrol_time`,`category_id`), + KEY `daily_patrol_sessions_patrol_date_patrol_time_index` (`patrol_date`,`patrol_time`), + KEY `daily_patrol_sessions_inspector_id_index` (`inspector_id`), + KEY `daily_patrol_sessions_category_id_foreign` (`category_id`), + CONSTRAINT `daily_patrol_sessions_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE SET NULL, + CONSTRAINT `daily_patrol_sessions_inspector_id_foreign` FOREIGN KEY (`inspector_id`) REFERENCES `users` (`user_id`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_patrol_sessions` +-- + +LOCK TABLES `daily_patrol_sessions` WRITE; +/*!40000 ALTER TABLE `daily_patrol_sessions` DISABLE KEYS */; +INSERT INTO `daily_patrol_sessions` VALUES +(1,'2026-02-04','morning',1,1,'in_progress',NULL,'02:20:32',NULL,'2026-02-04 02:20:32','2026-02-04 02:20:32'), +(2,'2026-02-04','afternoon',1,1,'in_progress',NULL,'07:36:23',NULL,'2026-02-04 07:36:23','2026-02-04 07:36:23'), +(3,'2026-02-05','afternoon',1,1,'in_progress',NULL,'04:30:44',NULL,'2026-02-05 04:30:44','2026-02-05 04:30:44'); +/*!40000 ALTER TABLE `daily_patrol_sessions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `daily_work_reports` +-- + +DROP TABLE IF EXISTS `daily_work_reports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_work_reports` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `report_date` date NOT NULL COMMENT '작업 날짜', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `project_id` int(11) NOT NULL COMMENT '프로젝트 ID', + `work_type_id` int(11) NOT NULL COMMENT '작업 유형 ID', + `work_status_id` int(11) DEFAULT 1 COMMENT '업무 상태 ID (1:정규, 2:에러)', + `error_type_id` int(11) DEFAULT NULL COMMENT '에러 유형 ID (에러일 때만)', + `work_hours` decimal(4,2) NOT NULL COMMENT '작업 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `created_by` int(11) NOT NULL DEFAULT 1 COMMENT '작성자 user_id', + `updated_by` int(11) DEFAULT NULL COMMENT '수정자 user_id', + `tbm_session_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 TBM 세션 ID', + `tbm_assignment_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 TBM 팀 배정 ID', + `start_time` time DEFAULT NULL COMMENT '작업 시작 시간', + `end_time` time DEFAULT NULL COMMENT '작업 종료 시간', + `total_hours` decimal(5,2) DEFAULT NULL COMMENT '총 작업 시간', + `regular_hours` decimal(5,2) DEFAULT NULL COMMENT '정규 작업 시간 (총 시간 - 오류 시간)', + `error_hours` decimal(5,2) DEFAULT NULL COMMENT '부적합 사항 처리 시간', + PRIMARY KEY (`id`), + KEY `idx_report_date` (`report_date`), + KEY `idx_worker_date` (`worker_id`,`report_date`), + KEY `idx_project_date` (`project_id`,`report_date`), + KEY `idx_work_type` (`work_type_id`), + KEY `idx_work_status` (`work_status_id`), + KEY `idx_error_type` (`error_type_id`), + KEY `idx_created_by` (`created_by`), + KEY `idx_date_worker_creator` (`report_date`,`worker_id`,`created_by`), + KEY `daily_work_reports_tbm_session_id_foreign` (`tbm_session_id`), + KEY `daily_work_reports_tbm_assignment_id_foreign` (`tbm_assignment_id`), + CONSTRAINT `daily_work_reports_tbm_assignment_id_foreign` FOREIGN KEY (`tbm_assignment_id`) REFERENCES `tbm_team_assignments` (`assignment_id`) ON DELETE SET NULL, + CONSTRAINT `daily_work_reports_tbm_session_id_foreign` FOREIGN KEY (`tbm_session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=1858 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_work_reports` +-- + +LOCK TABLES `daily_work_reports` WRITE; +/*!40000 ALTER TABLE `daily_work_reports` DISABLE KEYS */; +INSERT INTO `daily_work_reports` VALUES +(14,'2025-06-02',1,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(15,'2025-06-02',3,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(16,'2025-06-02',4,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(17,'2025-06-02',6,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(18,'2025-06-02',7,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(19,'2025-06-02',9,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(20,'2025-06-02',2,3,2,1,NULL,8.00,'2025-06-16 05:10:47','2025-06-16 05:10:47',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(21,'2025-06-04',1,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(22,'2025-06-04',3,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(23,'2025-06-04',5,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(24,'2025-06-04',7,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(25,'2025-06-04',9,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(26,'2025-06-04',10,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(27,'2025-06-04',2,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(28,'2025-06-04',6,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(29,'2025-06-04',8,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(30,'2025-06-05',1,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(31,'2025-06-05',3,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(32,'2025-06-05',4,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(33,'2025-06-05',7,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(34,'2025-06-05',10,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(35,'2025-06-05',9,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(36,'2025-06-05',2,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(37,'2025-06-05',5,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(38,'2025-06-05',6,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(39,'2025-06-05',8,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(40,'2025-06-16',5,3,2,1,NULL,8.00,'2025-06-16 06:12:01','2025-06-16 06:12:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(43,'2025-06-16',2,3,2,1,NULL,8.00,'2025-06-16 06:12:01','2025-06-16 06:12:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(44,'2025-06-16',6,3,2,2,43,4.00,'2025-06-16 06:13:02','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(45,'2025-06-16',6,3,2,1,NULL,4.00,'2025-06-16 06:13:50','2025-06-16 06:13:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(46,'2025-06-16',8,3,2,2,43,4.00,'2025-06-16 06:15:22','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(47,'2025-06-16',8,3,2,1,NULL,4.00,'2025-06-16 06:15:22','2025-06-16 06:15:22',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(48,'2025-06-16',4,4,3,2,6,8.00,'2025-06-16 06:46:44','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(50,'2025-06-16',1,4,3,2,6,8.00,'2025-06-16 06:46:44','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(51,'2025-06-16',9,4,3,1,NULL,8.00,'2025-06-16 06:48:29','2025-06-16 06:48:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(52,'2025-06-16',10,4,3,1,NULL,6.00,'2025-06-16 06:50:09','2025-06-16 06:50:09',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(53,'2025-06-16',10,4,3,2,6,2.00,'2025-06-16 06:50:09','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(54,'2025-06-16',3,4,3,1,NULL,6.00,'2025-06-16 06:50:09','2025-06-16 06:50:09',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(55,'2025-06-16',3,4,3,2,6,2.00,'2025-06-16 06:50:09','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(56,'2025-06-17',2,3,2,1,NULL,8.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(57,'2025-06-17',2,3,2,1,NULL,2.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(58,'2025-06-17',5,3,2,1,NULL,8.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(59,'2025-06-17',5,3,2,1,NULL,2.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(60,'2025-06-17',6,3,2,1,NULL,8.00,'2025-06-17 08:24:33','2025-06-17 08:24:33',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(61,'2025-06-17',6,3,2,2,43,2.00,'2025-06-17 08:24:33','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(62,'2025-06-17',8,3,2,1,NULL,8.00,'2025-06-17 08:24:33','2025-06-17 08:24:33',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(63,'2025-06-17',8,3,2,2,43,2.00,'2025-06-17 08:24:33','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(65,'2025-06-17',9,4,3,2,6,4.00,'2025-06-17 08:25:24','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(66,'2025-06-17',1,4,3,2,6,4.00,'2025-06-17 08:27:06','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(67,'2025-06-17',4,4,3,2,6,4.00,'2025-06-17 08:27:06','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(68,'2025-06-17',1,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(69,'2025-06-17',9,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(70,'2025-06-17',4,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(71,'2025-06-17',9,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(72,'2025-06-17',4,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(73,'2025-06-17',1,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(74,'2025-06-17',10,4,3,1,NULL,8.00,'2025-06-17 08:34:11','2025-06-17 08:34:11',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(75,'2025-06-17',10,4,3,2,6,2.00,'2025-06-17 08:34:11','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(76,'2025-06-17',3,4,3,1,NULL,8.00,'2025-06-17 08:34:11','2025-06-17 08:34:11',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(77,'2025-06-17',3,4,3,2,6,2.00,'2025-06-17 08:34:11','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(78,'2025-06-18',6,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(79,'2025-06-18',2,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(80,'2025-06-18',8,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(81,'2025-06-18',2,3,2,1,NULL,2.00,'2025-06-18 08:41:02','2025-06-18 08:41:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(82,'2025-06-18',6,3,2,1,NULL,2.00,'2025-06-18 08:41:03','2025-06-18 08:41:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(83,'2025-06-18',8,3,2,1,NULL,2.00,'2025-06-18 08:41:03','2025-06-18 08:41:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(84,'2025-06-18',5,4,3,1,NULL,8.00,'2025-06-18 08:41:45','2025-06-18 08:41:45',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(85,'2025-06-18',5,4,3,1,NULL,2.00,'2025-06-18 08:41:45','2025-06-18 08:41:45',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(86,'2025-06-18',10,4,3,1,NULL,9.00,'2025-06-18 08:47:55','2025-06-18 08:47:55',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(87,'2025-06-18',10,4,3,2,6,1.00,'2025-06-18 08:47:55','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(88,'2025-06-18',3,4,3,1,NULL,9.00,'2025-06-18 08:47:55','2025-06-18 08:47:55',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(89,'2025-06-18',3,4,3,2,6,1.00,'2025-06-18 08:47:55','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(90,'2025-06-18',4,4,3,2,6,4.00,'2025-06-18 08:50:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(91,'2025-06-18',4,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(92,'2025-06-18',9,4,3,2,6,4.00,'2025-06-18 08:50:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(93,'2025-06-18',9,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(94,'2025-06-18',1,4,3,2,6,4.00,'2025-06-18 08:50:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(95,'2025-06-18',1,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(96,'2025-06-18',7,4,3,2,6,4.00,'2025-06-18 09:00:17','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(97,'2025-06-18',7,4,3,1,NULL,6.00,'2025-06-18 09:00:17','2025-06-18 09:00:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(98,'2025-06-19',8,3,2,1,NULL,8.00,'2025-06-19 06:37:59','2025-06-19 06:37:59',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(99,'2025-06-19',2,3,2,1,NULL,8.00,'2025-06-19 06:37:59','2025-06-19 06:37:59',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(100,'2025-06-19',10,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(101,'2025-06-19',3,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(102,'2025-06-19',5,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(103,'2025-06-19',9,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(104,'2025-06-19',9,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(105,'2025-06-19',4,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(106,'2025-06-19',4,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(107,'2025-06-19',1,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(108,'2025-06-19',1,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(109,'2025-06-19',7,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(110,'2025-06-19',7,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(111,'2025-06-19',6,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(112,'2025-06-19',6,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(113,'2025-06-20',9,4,3,2,6,2.00,'2025-06-20 06:44:01','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(114,'2025-06-20',9,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(115,'2025-06-20',4,4,3,2,6,2.00,'2025-06-20 06:44:01','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(116,'2025-06-20',4,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(117,'2025-06-20',7,4,3,2,6,2.00,'2025-06-20 06:44:01','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(118,'2025-06-20',7,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(119,'2025-06-20',6,4,3,2,6,2.00,'2025-06-20 06:44:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(120,'2025-06-20',6,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(121,'2025-06-20',1,4,3,2,6,2.00,'2025-06-20 06:44:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(122,'2025-06-20',1,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(123,'2025-06-20',5,4,3,2,6,2.00,'2025-06-20 06:44:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(124,'2025-06-20',5,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(125,'2025-06-20',10,4,3,1,NULL,8.00,'2025-06-20 06:45:30','2025-06-20 06:45:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(126,'2025-06-20',3,4,3,1,NULL,8.00,'2025-06-20 06:45:31','2025-06-20 06:45:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(127,'2025-06-23',10,4,3,1,NULL,8.00,'2025-06-23 06:42:58','2025-06-23 06:42:58',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(128,'2025-06-23',3,4,3,1,NULL,8.00,'2025-06-23 06:42:58','2025-06-23 06:42:58',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(129,'2025-06-23',5,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(130,'2025-06-23',5,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(131,'2025-06-23',1,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(132,'2025-06-23',1,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(133,'2025-06-23',9,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(134,'2025-06-23',9,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(135,'2025-06-23',4,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(136,'2025-06-23',4,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(137,'2025-06-23',7,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(138,'2025-06-23',7,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(139,'2025-06-23',6,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(140,'2025-06-23',6,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(141,'2025-06-24',10,4,3,1,NULL,12.00,'2025-06-24 11:10:32','2025-06-24 11:10:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(142,'2025-06-24',3,4,3,1,NULL,12.00,'2025-06-24 11:10:32','2025-06-24 11:10:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(143,'2025-06-24',9,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(144,'2025-06-24',9,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(145,'2025-06-24',5,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(146,'2025-06-24',5,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(147,'2025-06-24',4,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(148,'2025-06-24',4,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(149,'2025-06-24',7,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(150,'2025-06-24',7,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(151,'2025-06-24',6,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(152,'2025-06-24',6,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(153,'2025-06-24',1,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(154,'2025-06-24',1,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(155,'2025-06-24',8,3,2,1,NULL,8.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(156,'2025-06-24',8,3,2,1,NULL,4.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(157,'2025-06-24',2,3,2,1,NULL,8.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(158,'2025-06-24',2,3,2,1,NULL,4.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(159,'2025-06-25',2,3,2,1,NULL,8.00,'2025-06-25 11:08:04','2025-06-25 11:08:04',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(160,'2025-06-25',2,3,2,1,NULL,4.00,'2025-06-25 11:08:04','2025-06-25 11:08:04',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(161,'2025-06-25',8,3,2,1,NULL,8.00,'2025-06-25 11:08:05','2025-06-25 11:08:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(162,'2025-06-25',8,3,2,1,NULL,4.00,'2025-06-25 11:08:05','2025-06-25 11:08:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(163,'2025-06-25',10,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(164,'2025-06-25',9,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(165,'2025-06-25',3,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(166,'2025-06-25',6,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(167,'2025-06-26',10,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(168,'2025-06-26',5,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(169,'2025-06-26',7,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(170,'2025-06-26',1,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(171,'2025-06-26',4,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(172,'2025-06-26',8,3,2,1,NULL,8.00,'2025-06-26 11:11:31','2025-06-26 11:11:31',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(173,'2025-06-26',8,3,2,1,NULL,4.00,'2025-06-26 11:11:31','2025-06-26 11:11:31',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(174,'2025-06-26',2,3,2,1,NULL,8.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(175,'2025-06-26',2,3,2,1,NULL,4.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(176,'2025-06-26',9,3,2,1,NULL,8.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(177,'2025-06-26',9,3,2,1,NULL,4.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(178,'2025-06-26',3,3,2,1,NULL,12.00,'2025-06-26 11:19:34','2025-06-26 11:19:34',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(179,'2025-06-26',6,3,2,1,NULL,12.00,'2025-06-26 11:19:34','2025-06-26 11:19:34',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(182,'2025-06-27',2,3,2,1,NULL,4.00,'2025-06-27 01:54:40','2025-06-27 01:54:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(183,'2025-06-27',9,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(184,'2025-06-27',10,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(185,'2025-06-27',7,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(186,'2025-06-27',5,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(187,'2025-06-27',4,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(188,'2025-06-27',1,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(189,'2025-06-27',3,3,2,1,NULL,8.00,'2025-06-27 06:49:08','2025-06-27 06:49:08',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(191,'2025-06-27',6,3,2,1,NULL,4.00,'2025-06-27 06:58:46','2025-06-27 06:58:46',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(192,'2025-06-27',8,3,2,1,NULL,6.00,'2025-06-27 07:00:10','2025-06-27 07:00:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(193,'2025-06-30',6,3,2,2,43,2.00,'2025-07-05 01:37:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(194,'2025-06-30',6,3,2,1,NULL,2.00,'2025-07-05 01:37:29','2025-07-07 04:15:25',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(195,'2025-06-30',2,3,2,1,NULL,4.00,'2025-07-05 01:38:19','2025-07-07 04:15:40',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(196,'2025-06-30',3,3,2,1,NULL,8.00,'2025-07-05 01:38:19','2025-07-05 01:38:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(197,'2025-06-30',8,3,2,1,NULL,6.00,'2025-07-05 01:38:19','2025-07-07 04:15:02',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(198,'2025-07-01',3,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(199,'2025-07-01',2,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(200,'2025-07-01',6,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(201,'2025-07-01',8,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(202,'2025-07-01',10,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(203,'2025-07-01',9,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(204,'2025-07-01',2,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:42:08',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(205,'2025-07-01',3,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:42:02',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(206,'2025-07-01',6,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:41:56',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(207,'2025-07-01',8,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:41:48',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(208,'2025-07-01',9,3,2,2,43,2.00,'2025-07-05 01:40:10','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(209,'2025-07-01',10,3,2,2,43,2.00,'2025-07-05 01:40:10','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(210,'2025-07-01',7,4,3,1,NULL,5.00,'2025-07-05 01:42:57','2025-07-05 01:42:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(211,'2025-07-01',7,4,3,2,10,3.00,'2025-07-05 01:42:57','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(212,'2025-07-01',5,4,3,1,NULL,8.00,'2025-07-05 01:42:57','2025-07-07 04:21:24',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(213,'2025-07-01',5,4,3,2,10,4.00,'2025-07-05 01:42:57','2026-02-05 22:24:28',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(214,'2025-07-01',4,4,3,1,NULL,8.00,'2025-07-05 01:42:57','2025-07-07 04:21:41',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(215,'2025-07-01',4,4,3,2,10,4.00,'2025-07-05 01:42:57','2026-02-05 22:24:28',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(216,'2025-07-01',1,4,3,1,NULL,5.00,'2025-07-05 01:42:57','2025-07-05 01:42:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(217,'2025-07-01',1,4,3,2,10,3.00,'2025-07-05 01:42:57','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(218,'2025-07-02',2,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(219,'2025-07-02',3,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(220,'2025-07-02',10,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(221,'2025-07-02',9,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(222,'2025-07-02',8,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(223,'2025-07-02',6,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(224,'2025-07-02',7,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(225,'2025-07-02',5,4,3,2,10,4.00,'2025-07-05 01:44:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(226,'2025-07-02',5,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:44:54',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(227,'2025-07-02',4,4,3,2,10,4.00,'2025-07-05 01:44:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(228,'2025-07-02',4,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:44:59',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(229,'2025-07-02',1,4,3,2,10,4.00,'2025-07-05 01:44:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(230,'2025-07-02',1,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:45:05',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(231,'2025-07-03',2,3,2,1,NULL,10.00,'2025-07-05 01:45:44','2025-07-05 01:45:44',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(232,'2025-07-03',6,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(233,'2025-07-03',9,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(234,'2025-07-03',8,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(235,'2025-07-03',7,4,3,1,NULL,10.00,'2025-07-05 01:46:07','2025-07-05 01:46:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(236,'2025-07-03',1,4,3,1,NULL,10.00,'2025-07-05 01:46:07','2025-07-05 01:46:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(237,'2025-07-03',3,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(238,'2025-07-03',4,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(239,'2025-07-03',5,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(240,'2025-07-03',10,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(241,'2025-07-04',10,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(242,'2025-07-04',10,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(243,'2025-07-04',5,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(244,'2025-07-04',5,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(245,'2025-07-04',4,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(246,'2025-07-04',4,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(247,'2025-07-04',9,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(248,'2025-07-04',9,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(249,'2025-07-04',8,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(250,'2025-07-04',8,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(251,'2025-07-04',3,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(252,'2025-07-04',3,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(253,'2025-07-04',2,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(254,'2025-07-04',2,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(255,'2025-07-04',7,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(256,'2025-07-04',7,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(257,'2025-07-04',6,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(258,'2025-07-04',6,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(259,'2025-07-04',1,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(260,'2025-07-04',1,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(261,'2025-07-05',8,4,2,1,NULL,8.00,'2025-07-05 05:36:38','2025-07-05 05:36:38',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(262,'2025-07-05',5,4,2,1,NULL,8.00,'2025-07-05 05:36:38','2025-07-05 05:36:38',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(263,'2025-07-05',4,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(264,'2025-07-05',3,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(265,'2025-07-05',2,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(266,'2025-07-05',1,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(267,'2025-07-06',10,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:08',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(268,'2025-07-06',9,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:16',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(269,'2025-07-06',7,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:22',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(270,'2025-07-06',6,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:27',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(271,'2025-07-06',4,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:33',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(272,'2025-07-06',3,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:39',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(273,'2025-07-06',2,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:44',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(274,'2025-07-06',1,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:49',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(275,'2025-07-07',10,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(276,'2025-07-07',9,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(277,'2025-07-07',8,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(278,'2025-07-07',7,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(279,'2025-07-07',3,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(280,'2025-07-07',4,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(281,'2025-07-07',5,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(282,'2025-07-07',6,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(283,'2025-07-07',2,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(284,'2025-07-07',1,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(285,'2025-07-08',10,4,3,1,NULL,8.00,'2025-07-08 06:36:57','2025-07-08 06:36:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(286,'2025-07-08',9,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(287,'2025-07-08',8,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(288,'2025-07-08',7,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(289,'2025-07-08',6,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(290,'2025-07-08',1,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(291,'2025-07-08',2,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(292,'2025-07-08',3,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(293,'2025-07-08',5,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(294,'2025-07-08',4,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(295,'2025-07-09',10,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(296,'2025-07-09',9,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(297,'2025-07-09',8,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(298,'2025-07-09',7,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(299,'2025-07-09',6,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(300,'2025-07-09',2,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(301,'2025-07-09',3,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(302,'2025-07-09',4,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(303,'2025-07-09',5,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(304,'2025-07-09',1,4,3,1,NULL,4.00,'2025-07-09 22:09:10','2025-07-09 22:09:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(305,'2025-07-10',9,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(306,'2025-07-10',8,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(307,'2025-07-10',5,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(308,'2025-07-10',6,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(309,'2025-07-10',2,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(310,'2025-07-10',3,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(311,'2025-07-10',4,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(312,'2025-07-10',1,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(313,'2025-07-10',7,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(314,'2025-07-10',10,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(315,'2025-07-12',9,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(316,'2025-07-12',8,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(317,'2025-07-12',6,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(318,'2025-07-12',5,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(319,'2025-07-12',4,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(320,'2025-07-12',2,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(321,'2025-07-12',1,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(322,'2025-07-14',8,4,3,1,NULL,6.00,'2025-07-14 06:46:30','2025-07-14 06:46:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(323,'2025-07-14',10,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(324,'2025-07-14',9,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(325,'2025-07-14',7,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(326,'2025-07-14',6,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(327,'2025-07-14',1,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(328,'2025-07-14',2,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(329,'2025-07-14',3,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(330,'2025-07-14',4,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(331,'2025-07-15',3,3,2,1,NULL,8.00,'2025-07-15 05:57:06','2025-07-15 05:57:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(332,'2025-07-15',9,3,2,1,NULL,8.00,'2025-07-15 05:57:06','2025-07-15 05:57:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(333,'2025-07-15',5,3,2,2,43,4.00,'2025-07-15 05:57:47','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(334,'2025-07-15',5,4,3,1,NULL,4.00,'2025-07-15 05:57:47','2025-07-15 05:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(335,'2025-07-15',10,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(336,'2025-07-15',8,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(337,'2025-07-15',7,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(338,'2025-07-15',6,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(339,'2025-07-15',2,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(340,'2025-07-15',1,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(341,'2025-07-14',5,4,3,1,NULL,8.00,'2025-07-15 06:57:26','2025-07-15 06:57:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(342,'2025-07-16',4,4,3,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(343,'2025-07-16',4,3,2,1,NULL,4.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(344,'2025-07-16',4,3,2,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(345,'2025-07-16',5,4,3,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(346,'2025-07-16',5,3,2,1,NULL,4.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(347,'2025-07-16',5,3,2,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(348,'2025-07-16',10,4,3,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(349,'2025-07-16',10,3,2,1,NULL,4.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(350,'2025-07-16',10,3,2,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(351,'2025-07-16',6,4,3,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(352,'2025-07-16',6,3,2,1,NULL,4.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(353,'2025-07-16',6,3,2,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(354,'2025-07-16',9,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(355,'2025-07-16',8,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(356,'2025-07-16',3,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(357,'2025-07-16',2,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(358,'2025-07-16',1,4,3,1,NULL,8.00,'2025-07-16 06:51:31','2025-07-16 06:51:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(359,'2025-07-16',7,4,3,1,NULL,8.00,'2025-07-16 06:51:31','2025-07-16 06:51:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(360,'2025-07-17',1,3,3,1,NULL,8.00,'2025-07-17 06:45:22','2025-07-17 06:45:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(361,'2025-07-17',5,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(362,'2025-07-17',5,3,2,2,43,4.00,'2025-07-17 06:46:48','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(363,'2025-07-17',4,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(364,'2025-07-17',4,3,2,2,43,4.00,'2025-07-17 06:46:48','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(365,'2025-07-17',2,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(366,'2025-07-17',2,3,2,2,43,4.00,'2025-07-17 06:46:48','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(367,'2025-07-17',10,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(368,'2025-07-17',9,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(369,'2025-07-17',8,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(370,'2025-07-17',7,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(371,'2025-07-17',6,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(372,'2025-07-17',3,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(373,'2025-07-18',7,4,3,2,6,2.00,'2025-07-18 05:54:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(374,'2025-07-18',1,4,3,2,6,2.00,'2025-07-18 05:54:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(376,'2025-07-18',5,4,3,1,NULL,2.00,'2025-07-18 05:58:33','2025-07-18 05:58:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(377,'2025-07-18',5,3,2,1,NULL,6.00,'2025-07-18 05:58:33','2025-07-18 05:58:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(378,'2025-07-18',7,3,2,1,NULL,6.00,'2025-07-18 05:59:42','2025-07-18 05:59:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(379,'2025-07-18',1,3,3,1,NULL,6.00,'2025-07-18 06:00:15','2025-07-18 06:00:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(380,'2025-07-18',10,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(381,'2025-07-18',9,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(382,'2025-07-18',8,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(383,'2025-07-18',6,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(384,'2025-07-18',4,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(385,'2025-07-18',3,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(386,'2025-07-18',2,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(387,'2025-07-21',5,4,3,2,6,4.00,'2025-07-21 06:40:08','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(388,'2025-07-21',5,3,2,1,NULL,4.00,'2025-07-21 06:40:08','2025-07-21 06:40:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(389,'2025-07-21',4,4,3,2,6,4.00,'2025-07-21 06:40:08','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(390,'2025-07-21',4,3,2,1,NULL,4.00,'2025-07-21 06:40:08','2025-07-21 06:40:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(391,'2025-07-21',10,3,2,1,NULL,6.00,'2025-07-21 06:40:32','2025-07-22 06:58:42',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(392,'2025-07-21',9,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(393,'2025-07-21',8,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(394,'2025-07-21',7,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(395,'2025-07-21',6,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(396,'2025-07-21',3,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(397,'2025-07-21',2,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(398,'2025-07-21',1,3,3,1,NULL,8.00,'2025-07-21 06:53:37','2025-07-21 06:53:37',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(399,'2025-07-22',10,3,2,1,NULL,8.00,'2025-07-22 06:45:47','2025-07-22 06:45:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(400,'2025-07-22',9,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(401,'2025-07-22',8,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(402,'2025-07-22',7,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(403,'2025-07-22',6,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(404,'2025-07-22',4,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(405,'2025-07-22',3,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(406,'2025-07-22',2,4,3,2,6,8.00,'2025-07-22 06:46:11','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(407,'2025-07-22',5,3,3,1,NULL,8.00,'2025-07-22 06:46:11','2025-07-22 06:46:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(408,'2025-07-22',1,3,3,1,NULL,8.00,'2025-07-22 06:46:11','2025-07-22 06:46:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(409,'2025-07-23',4,3,3,1,NULL,8.00,'2025-07-23 06:45:06','2025-07-23 06:45:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(410,'2025-07-23',5,3,3,1,NULL,8.00,'2025-07-23 06:45:28','2025-07-23 06:45:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(411,'2025-07-23',1,3,3,1,NULL,8.00,'2025-07-23 06:45:28','2025-07-23 06:45:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(412,'2025-07-23',10,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(413,'2025-07-23',9,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(414,'2025-07-23',7,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(415,'2025-07-23',6,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(416,'2025-07-23',3,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(417,'2025-07-23',2,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(418,'2025-07-24',4,3,3,1,NULL,8.00,'2025-07-24 06:36:55','2025-07-24 06:36:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(419,'2025-07-24',10,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(420,'2025-07-24',9,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(421,'2025-07-24',7,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(422,'2025-07-24',6,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(423,'2025-07-24',3,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(424,'2025-07-24',2,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(425,'2025-07-24',5,3,3,1,NULL,8.00,'2025-07-24 06:47:04','2025-07-24 06:47:04',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(426,'2025-07-24',1,3,3,1,NULL,8.00,'2025-07-24 06:47:04','2025-07-24 06:47:04',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(427,'2025-07-25',4,3,3,1,NULL,8.00,'2025-07-25 06:44:23','2025-07-25 06:44:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(428,'2025-07-25',10,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(429,'2025-07-25',9,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(430,'2025-07-25',8,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(431,'2025-07-25',6,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(432,'2025-07-25',3,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(433,'2025-07-25',2,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(434,'2025-07-25',5,4,3,1,NULL,8.00,'2025-07-25 06:45:18','2025-07-25 06:45:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(435,'2025-07-25',7,4,3,1,NULL,8.00,'2025-07-25 06:45:19','2025-07-25 06:45:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(436,'2025-07-25',1,4,3,1,NULL,8.00,'2025-07-25 06:45:19','2025-07-25 06:45:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(437,'2025-07-28',5,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(438,'2025-07-28',4,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(439,'2025-07-28',1,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(440,'2025-07-28',2,5,2,1,NULL,4.00,'2025-07-28 06:33:08','2025-07-28 06:33:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(441,'2025-07-28',2,3,2,1,NULL,4.00,'2025-07-28 06:33:08','2025-07-28 06:33:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(442,'2025-07-28',10,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(443,'2025-07-28',9,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(444,'2025-07-28',8,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(445,'2025-07-28',7,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(446,'2025-07-28',6,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(447,'2025-07-28',3,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(448,'2025-07-29',5,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(449,'2025-07-29',4,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(450,'2025-07-29',1,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(451,'2025-07-30',5,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(452,'2025-07-30',4,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(453,'2025-07-30',1,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(454,'2025-07-30',10,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(455,'2025-07-30',9,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(456,'2025-07-30',8,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(457,'2025-07-30',7,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(458,'2025-07-30',6,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(459,'2025-07-30',3,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(460,'2025-07-30',2,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(461,'2025-07-31',1,3,3,1,NULL,4.00,'2025-07-31 06:42:56','2025-07-31 06:42:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(462,'2025-07-31',4,3,3,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(463,'2025-07-31',4,3,2,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(464,'2025-07-31',5,3,3,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(465,'2025-07-31',5,3,2,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(466,'2025-07-31',10,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(467,'2025-07-31',9,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(468,'2025-07-31',8,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(469,'2025-07-31',7,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(470,'2025-07-31',6,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(471,'2025-07-31',3,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(472,'2025-07-31',2,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(473,'2025-07-11',10,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(474,'2025-07-11',5,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(475,'2025-07-11',4,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(476,'2025-07-11',9,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(477,'2025-07-11',8,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(478,'2025-07-11',3,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(479,'2025-07-11',2,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(480,'2025-07-11',7,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(481,'2025-07-11',6,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(482,'2025-07-11',1,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(483,'2025-08-01',10,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(484,'2025-08-01',9,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(485,'2025-08-01',8,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(486,'2025-08-01',7,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(487,'2025-08-01',6,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(488,'2025-08-01',3,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(489,'2025-08-01',2,3,2,1,NULL,8.00,'2025-08-01 04:57:48','2025-08-01 04:57:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(490,'2025-08-01',4,3,3,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(491,'2025-08-01',4,5,1,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(492,'2025-08-01',5,3,3,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(493,'2025-08-01',5,5,1,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(494,'2025-08-07',9,3,2,2,43,4.00,'2025-08-07 06:42:39','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(495,'2025-08-07',9,3,2,1,NULL,4.00,'2025-08-07 06:42:39','2025-08-07 06:42:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(496,'2025-08-07',7,3,2,2,43,4.00,'2025-08-07 06:42:39','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(497,'2025-08-07',7,3,2,1,NULL,4.00,'2025-08-07 06:42:39','2025-08-07 06:42:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(498,'2025-08-07',10,5,2,1,NULL,8.00,'2025-08-07 06:43:14','2025-08-07 06:43:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(499,'2025-08-07',4,5,2,1,NULL,8.00,'2025-08-07 06:43:15','2025-08-07 06:43:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(500,'2025-08-07',2,5,2,1,NULL,8.00,'2025-08-07 06:43:15','2025-08-07 06:43:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(501,'2025-08-07',6,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(502,'2025-08-07',3,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(503,'2025-08-07',8,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(504,'2025-08-07',1,3,3,1,NULL,8.00,'2025-08-07 06:43:52','2025-08-07 06:43:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(505,'2025-08-08',1,3,3,1,NULL,8.00,'2025-08-08 06:45:20','2025-08-08 06:45:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(506,'2025-08-08',10,5,2,1,NULL,8.00,'2025-08-08 06:58:42','2025-08-08 06:58:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(507,'2025-08-08',2,5,2,1,NULL,8.00,'2025-08-08 06:58:42','2025-08-08 06:58:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(508,'2025-08-08',9,3,2,1,NULL,8.00,'2025-08-08 06:59:18','2025-08-08 06:59:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(509,'2025-08-08',8,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(510,'2025-08-08',3,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(511,'2025-08-08',4,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(512,'2025-08-08',6,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(513,'2025-08-11',1,3,3,1,NULL,8.00,'2025-08-11 06:27:37','2025-08-11 06:27:37',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(514,'2025-08-11',1,3,3,1,NULL,8.00,'2025-08-11 06:27:37','2025-08-11 06:27:37',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(515,'2025-08-11',10,5,2,1,NULL,8.00,'2025-08-11 06:46:23','2025-08-11 06:46:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(516,'2025-08-11',2,5,2,1,NULL,8.00,'2025-08-11 06:46:23','2025-08-11 06:46:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(517,'2025-08-11',8,3,2,1,NULL,8.00,'2025-08-11 06:46:49','2025-08-11 06:46:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(518,'2025-08-11',7,3,2,1,NULL,8.00,'2025-08-11 06:46:49','2025-08-11 06:46:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(519,'2025-08-11',6,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(520,'2025-08-11',5,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(521,'2025-08-11',4,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(522,'2025-08-11',3,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(523,'2025-08-12',10,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(524,'2025-08-12',9,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(525,'2025-08-12',8,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(526,'2025-08-12',7,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(527,'2025-08-12',5,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(528,'2025-08-12',4,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(529,'2025-08-12',3,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(530,'2025-08-12',1,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(531,'2025-08-13',1,3,3,1,NULL,8.00,'2025-08-13 06:31:32','2025-08-13 06:31:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(532,'2025-08-13',2,3,2,1,NULL,4.00,'2025-08-13 06:36:13','2025-08-13 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(533,'2025-08-13',2,5,2,1,NULL,4.00,'2025-08-13 06:36:13','2025-08-13 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(534,'2025-08-13',9,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(535,'2025-08-13',8,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(536,'2025-08-13',7,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(537,'2025-08-13',6,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(538,'2025-08-13',5,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(539,'2025-08-13',4,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(540,'2025-08-13',3,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(541,'2025-08-13',10,5,2,1,NULL,8.00,'2025-08-13 06:37:19','2025-08-13 06:37:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(542,'2025-08-14',1,3,3,2,6,4.00,'2025-08-14 06:35:27','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(543,'2025-08-14',1,3,3,1,NULL,4.00,'2025-08-14 06:35:27','2025-08-14 06:35:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(544,'2025-08-14',10,5,2,1,NULL,4.00,'2025-08-14 06:39:03','2025-08-14 06:39:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(545,'2025-08-14',10,5,3,1,NULL,4.00,'2025-08-14 06:39:03','2025-08-14 06:39:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(546,'2025-08-14',2,5,2,1,NULL,2.00,'2025-08-14 06:39:44','2025-08-14 06:39:44',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(547,'2025-08-14',2,3,2,1,NULL,6.00,'2025-08-14 06:39:44','2025-08-14 06:39:44',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(548,'2025-08-14',9,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(549,'2025-08-14',8,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(550,'2025-08-14',7,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(551,'2025-08-14',6,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(552,'2025-08-14',5,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(553,'2025-08-14',4,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(554,'2025-08-18',2,3,2,1,NULL,8.00,'2025-08-18 06:21:36','2025-08-18 06:21:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(555,'2025-08-18',8,3,2,1,NULL,8.00,'2025-08-18 06:21:36','2025-08-18 06:21:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(556,'2025-08-18',4,3,2,1,NULL,8.00,'2025-08-18 06:22:01','2025-08-18 06:22:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(557,'2025-08-18',10,5,3,1,NULL,6.00,'2025-08-18 06:22:53','2025-08-18 06:22:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(558,'2025-08-18',10,3,2,1,NULL,2.00,'2025-08-18 06:22:53','2025-08-18 06:22:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(559,'2025-08-18',9,3,2,1,NULL,4.00,'2025-08-18 06:23:34','2025-08-18 06:23:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(560,'2025-08-18',9,3,3,1,NULL,4.00,'2025-08-18 06:23:34','2025-08-18 06:23:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(561,'2025-08-18',5,3,3,2,6,4.00,'2025-08-18 06:41:24','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(562,'2025-08-18',1,3,3,2,6,4.00,'2025-08-18 06:41:24','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(563,'2025-08-18',7,3,3,2,6,4.00,'2025-08-18 06:41:24','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(564,'2025-08-18',7,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(565,'2025-08-18',5,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(566,'2025-08-18',1,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(567,'2025-08-18',6,3,3,1,NULL,8.00,'2025-08-18 06:43:35','2025-08-18 06:43:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(568,'2025-08-18',3,3,3,1,NULL,8.00,'2025-08-18 06:43:35','2025-08-18 06:43:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(569,'2025-08-19',1,3,3,1,NULL,6.00,'2025-08-19 08:02:49','2025-08-19 08:02:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(573,'2025-08-19',9,3,3,1,NULL,10.00,'2025-08-19 08:03:30','2025-08-19 08:03:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(574,'2025-08-19',10,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(575,'2025-08-19',8,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(576,'2025-08-19',5,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(577,'2025-08-19',4,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(578,'2025-08-19',2,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(579,'2025-08-19',3,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(580,'2025-08-19',7,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(581,'2025-08-19',6,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(582,'2025-08-20',2,3,2,1,NULL,8.00,'2025-08-20 06:19:36','2025-08-20 06:19:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(583,'2025-08-20',5,3,1,1,NULL,2.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(584,'2025-08-20',5,3,2,1,NULL,6.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(585,'2025-08-20',4,3,1,1,NULL,2.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(586,'2025-08-20',4,3,2,1,NULL,6.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(587,'2025-08-20',6,3,3,1,NULL,4.00,'2025-08-20 06:43:46','2025-08-20 06:43:46',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(589,'2025-08-20',9,3,3,1,NULL,8.00,'2025-08-20 06:44:23','2025-08-20 06:44:23',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(590,'2025-08-20',8,3,3,1,NULL,8.00,'2025-08-20 06:44:23','2025-08-20 06:44:23',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(591,'2025-08-20',7,3,3,1,NULL,8.00,'2025-08-20 06:44:24','2025-08-20 06:44:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(593,'2025-08-20',1,3,3,1,NULL,8.00,'2025-08-20 06:44:24','2025-08-20 06:44:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(594,'2025-08-20',10,3,3,1,NULL,8.00,'2025-08-20 06:44:26','2025-08-20 06:44:26',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(595,'2025-08-20',3,3,3,1,NULL,8.00,'2025-08-20 06:44:26','2025-08-20 06:44:26',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(596,'2025-08-21',7,3,3,1,NULL,8.00,'2025-08-21 06:30:36','2025-08-21 06:30:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(597,'2025-08-21',1,3,3,1,NULL,8.00,'2025-08-21 06:30:36','2025-08-21 06:30:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(600,'2025-08-21',10,3,3,1,NULL,8.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(601,'2025-08-21',10,3,3,1,NULL,2.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(602,'2025-08-21',9,3,3,1,NULL,8.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(603,'2025-08-21',9,3,3,1,NULL,2.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(608,'2025-08-21',2,3,2,1,NULL,8.00,'2025-08-21 07:54:46','2025-08-21 07:54:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(609,'2025-08-21',2,5,2,1,NULL,2.00,'2025-08-21 07:54:46','2025-08-21 07:54:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(610,'2025-08-21',8,3,3,1,NULL,4.00,'2025-08-21 07:55:25','2025-08-21 07:55:25',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(611,'2025-08-21',8,3,2,1,NULL,6.00,'2025-08-21 07:55:25','2025-08-21 07:55:25',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(612,'2025-08-21',6,3,3,1,NULL,10.00,'2025-08-21 08:24:50','2025-08-21 08:24:50',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(613,'2025-08-21',3,3,3,1,NULL,10.00,'2025-08-21 08:24:50','2025-08-21 08:24:50',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(614,'2025-08-22',2,3,2,1,NULL,8.00,'2025-08-22 06:21:15','2025-08-22 06:21:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(615,'2025-08-22',8,3,2,1,NULL,4.00,'2025-08-22 06:23:12','2025-08-22 06:23:12',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(616,'2025-08-22',8,3,3,1,NULL,4.00,'2025-08-22 06:23:12','2025-08-22 06:23:12',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(617,'2025-08-22',5,3,3,1,NULL,8.00,'2025-08-22 06:23:55','2025-08-22 06:23:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(618,'2025-08-22',6,3,2,1,NULL,4.00,'2025-08-22 06:27:43','2025-08-22 06:27:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(619,'2025-08-22',10,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(620,'2025-08-22',9,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(621,'2025-08-22',7,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(622,'2025-08-22',4,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(623,'2025-08-22',3,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(624,'2025-08-22',1,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(625,'2025-08-23',4,3,2,1,NULL,2.00,'2025-08-23 04:57:02','2025-08-23 04:57:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(626,'2025-08-23',4,3,3,1,NULL,6.00,'2025-08-23 04:57:02','2025-08-23 04:57:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(627,'2025-08-23',2,3,2,1,NULL,8.00,'2025-08-23 04:57:25','2025-08-23 04:57:25',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(628,'2025-08-23',10,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(629,'2025-08-23',9,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(630,'2025-08-23',8,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(631,'2025-08-23',6,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(632,'2025-08-23',5,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(633,'2025-08-23',3,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(634,'2025-08-23',1,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(635,'2025-08-25',10,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(636,'2025-08-25',9,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(637,'2025-08-25',8,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(638,'2025-08-25',7,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(640,'2025-08-25',5,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(641,'2025-08-25',4,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(643,'2025-08-25',2,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(644,'2025-08-25',1,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(645,'2025-08-25',6,3,3,1,NULL,8.00,'2025-08-25 06:49:16','2025-08-25 06:49:16',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(646,'2025-08-25',3,3,3,1,NULL,8.00,'2025-08-25 06:49:17','2025-08-25 06:49:17',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(647,'2025-08-26',4,8,3,1,NULL,8.00,'2025-08-26 07:28:03','2025-08-26 07:28:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(648,'2025-08-26',4,3,3,1,NULL,2.00,'2025-08-26 07:28:03','2025-08-26 07:28:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(649,'2025-08-26',2,8,3,1,NULL,10.00,'2025-08-26 07:28:35','2025-08-26 07:28:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(651,'2025-08-26',9,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(652,'2025-08-26',8,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(653,'2025-08-26',7,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(655,'2025-08-26',5,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(657,'2025-08-26',1,3,3,1,NULL,10.00,'2025-08-26 07:29:03','2025-08-26 07:29:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(658,'2025-08-26',6,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(659,'2025-08-26',10,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(660,'2025-08-26',3,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(661,'2025-08-27',10,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(662,'2025-08-27',9,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(663,'2025-08-27',7,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(664,'2025-08-27',6,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(665,'2025-08-27',5,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(666,'2025-08-27',4,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(667,'2025-08-27',3,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(668,'2025-08-27',1,3,3,2,38,8.00,'2025-08-27 06:44:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(669,'2025-08-27',2,3,3,2,6,2.00,'2025-08-27 06:45:32','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(670,'2025-08-27',2,8,2,1,NULL,6.00,'2025-08-27 06:45:32','2025-08-27 06:45:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(671,'2025-08-27',8,3,3,2,6,2.00,'2025-08-27 06:45:32','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(672,'2025-08-27',8,8,2,1,NULL,6.00,'2025-08-27 06:45:32','2025-08-27 06:45:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(673,'2025-08-28',10,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(674,'2025-08-28',10,3,3,2,6,4.00,'2025-08-28 08:31:42','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(675,'2025-08-28',5,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(676,'2025-08-28',5,3,3,2,6,4.00,'2025-08-28 08:31:42','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(677,'2025-08-28',6,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(678,'2025-08-28',6,3,3,2,6,4.00,'2025-08-28 08:31:42','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(679,'2025-08-28',3,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(680,'2025-08-28',3,3,3,2,6,4.00,'2025-08-28 08:31:42','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(681,'2025-08-28',4,3,3,1,NULL,4.00,'2025-08-28 08:37:46','2025-08-28 08:37:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(682,'2025-08-28',4,5,3,1,NULL,4.00,'2025-08-28 08:37:46','2025-08-28 08:37:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(683,'2025-08-28',8,8,2,1,NULL,4.00,'2025-08-28 08:38:15','2025-08-28 08:38:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(684,'2025-08-28',8,5,3,1,NULL,4.00,'2025-08-28 08:38:15','2025-08-28 08:38:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(685,'2025-08-28',2,3,3,2,6,2.00,'2025-08-28 08:38:50','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(686,'2025-08-28',2,5,3,1,NULL,6.00,'2025-08-28 08:38:50','2025-08-28 08:38:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(687,'2025-08-28',1,3,3,2,6,8.00,'2025-08-28 08:39:24','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(689,'2025-08-28',9,3,3,2,43,8.00,'2025-08-28 08:40:00','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(690,'2025-08-28',7,3,3,2,43,8.00,'2025-08-28 08:40:00','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(694,'2025-08-28',4,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(695,'2025-08-28',8,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(696,'2025-08-28',2,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(698,'2025-08-28',9,3,3,1,NULL,2.00,'2025-08-28 08:45:19','2025-08-28 08:45:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(699,'2025-08-28',7,3,3,1,NULL,2.00,'2025-08-28 08:45:19','2025-08-28 08:45:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(703,'2025-08-29',10,3,3,2,38,8.00,'2025-08-29 06:47:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(704,'2025-08-29',9,3,3,2,38,8.00,'2025-08-29 06:47:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(706,'2025-08-29',7,3,3,2,38,8.00,'2025-08-29 06:47:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(710,'2025-08-29',1,3,3,2,38,8.00,'2025-08-29 06:47:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(713,'2025-08-29',5,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(714,'2025-08-29',5,3,3,2,6,2.00,'2025-08-29 06:47:35','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(715,'2025-08-29',3,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(716,'2025-08-29',3,3,3,2,6,2.00,'2025-08-29 06:47:35','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(717,'2025-08-29',6,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(718,'2025-08-29',6,3,3,2,6,2.00,'2025-08-29 06:47:35','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(719,'2025-08-29',8,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(720,'2025-08-29',4,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(721,'2025-08-29',2,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(722,'2025-08-30',2,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(723,'2025-08-30',8,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(724,'2025-08-30',4,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(725,'2025-08-30',10,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(726,'2025-08-30',9,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(727,'2025-08-30',7,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(728,'2025-08-30',6,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(729,'2025-08-30',5,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(730,'2025-08-30',3,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(731,'2025-08-30',1,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(732,'2025-09-01',7,3,3,1,NULL,8.00,'2025-09-01 06:18:28','2025-09-01 06:18:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(733,'2025-09-01',9,3,3,1,NULL,8.00,'2025-09-01 06:18:28','2025-09-01 06:18:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(734,'2025-09-01',10,3,3,2,38,4.00,'2025-09-01 06:19:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(735,'2025-09-01',3,3,3,2,38,4.00,'2025-09-01 06:19:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(736,'2025-09-01',1,3,3,2,38,4.00,'2025-09-01 06:19:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(737,'2025-09-01',10,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(738,'2025-09-01',3,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(739,'2025-09-01',1,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(740,'2025-09-01',5,3,3,2,6,8.00,'2025-09-01 06:20:03','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(741,'2025-08-21',4,3,3,1,NULL,10.00,'2025-09-01 23:18:03','2025-09-01 23:18:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(742,'2025-08-21',5,3,3,1,NULL,10.00,'2025-09-01 23:18:03','2025-09-01 23:18:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(745,'2025-09-02',10,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(746,'2025-09-02',9,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(747,'2025-09-02',6,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(748,'2025-09-02',5,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(749,'2025-09-02',3,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(750,'2025-09-02',1,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(751,'2025-09-02',10,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(752,'2025-09-02',9,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(753,'2025-09-02',6,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(754,'2025-09-02',5,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(755,'2025-09-02',3,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(756,'2025-09-02',1,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(757,'2025-09-02',8,3,3,1,NULL,10.00,'2025-09-02 07:37:19','2025-09-02 07:37:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(758,'2025-09-02',7,3,3,1,NULL,10.00,'2025-09-02 07:37:19','2025-09-02 07:37:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(759,'2025-09-02',2,5,3,1,NULL,8.00,'2025-09-02 08:16:14','2025-09-02 08:16:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(760,'2025-09-02',2,5,3,1,NULL,2.00,'2025-09-02 08:16:14','2025-09-02 08:16:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(761,'2025-09-02',4,5,3,1,NULL,8.00,'2025-09-02 08:16:14','2025-09-02 08:16:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(762,'2025-09-02',4,5,3,1,NULL,2.00,'2025-09-02 08:16:14','2025-09-02 08:16:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(763,'2025-09-03',10,3,3,1,NULL,8.00,'2025-09-03 06:34:47','2025-09-03 06:34:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(764,'2025-09-03',9,3,3,1,NULL,8.00,'2025-09-03 06:34:47','2025-09-03 06:34:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(765,'2025-09-03',8,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(766,'2025-09-03',7,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(767,'2025-09-03',6,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(768,'2025-09-03',5,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(769,'2025-09-03',3,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(770,'2025-09-03',1,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(771,'2025-09-03',2,5,3,1,NULL,8.00,'2025-09-03 06:44:18','2025-09-03 06:44:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(772,'2025-09-04',10,3,3,1,NULL,8.00,'2025-09-04 06:41:32','2025-09-04 06:41:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(773,'2025-09-04',5,3,3,1,NULL,8.00,'2025-09-04 06:41:32','2025-09-04 06:41:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(774,'2025-09-04',9,3,3,1,NULL,8.00,'2025-09-04 06:41:32','2025-09-04 06:41:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(775,'2025-09-04',8,3,3,1,NULL,8.00,'2025-09-04 06:41:32','2025-09-04 06:41:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(776,'2025-09-04',3,3,3,1,NULL,8.00,'2025-09-04 06:41:33','2025-09-04 06:41:33',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(777,'2025-09-04',7,3,3,1,NULL,8.00,'2025-09-04 06:41:33','2025-09-04 06:41:33',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(778,'2025-09-04',1,3,3,1,NULL,8.00,'2025-09-04 06:41:33','2025-09-04 06:41:33',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(779,'2025-09-04',6,3,3,1,NULL,8.00,'2025-09-04 06:41:33','2025-09-04 06:41:33',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(780,'2025-09-04',2,5,3,1,NULL,8.00,'2025-09-04 06:48:34','2025-09-04 06:48:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(781,'2025-09-04',4,5,3,1,NULL,8.00,'2025-09-04 06:48:34','2025-09-04 06:48:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(782,'2025-09-05',10,3,3,1,NULL,8.00,'2025-09-05 06:39:30','2025-09-05 06:39:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(783,'2025-09-05',9,3,3,1,NULL,8.00,'2025-09-05 06:39:30','2025-09-05 06:39:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(784,'2025-09-05',7,3,3,1,NULL,8.00,'2025-09-05 06:39:30','2025-09-05 06:39:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(785,'2025-09-05',6,3,3,1,NULL,8.00,'2025-09-05 06:39:31','2025-09-05 06:39:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(786,'2025-09-05',5,3,3,1,NULL,8.00,'2025-09-05 06:39:31','2025-09-05 06:39:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(787,'2025-09-05',3,3,3,1,NULL,8.00,'2025-09-05 06:39:31','2025-09-05 06:39:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(788,'2025-09-05',1,3,3,1,NULL,8.00,'2025-09-05 06:39:31','2025-09-05 06:39:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(789,'2025-09-05',2,5,3,1,NULL,8.00,'2025-09-05 22:09:55','2025-09-05 22:09:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(790,'2025-09-05',8,5,3,1,NULL,8.00,'2025-09-05 22:09:55','2025-09-05 22:09:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(791,'2025-09-05',4,5,3,1,NULL,8.00,'2025-09-05 22:09:55','2025-09-05 22:09:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(792,'2025-09-06',8,10,3,1,NULL,8.00,'2025-09-06 04:21:10','2025-09-06 04:21:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(793,'2025-09-06',4,10,3,1,NULL,8.00,'2025-09-06 04:21:10','2025-09-06 04:21:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(794,'2025-09-06',2,10,3,1,NULL,8.00,'2025-09-06 04:21:10','2025-09-06 04:21:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(795,'2025-09-06',10,3,3,1,NULL,8.00,'2025-09-06 05:28:18','2025-09-06 05:28:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(796,'2025-09-06',9,3,3,1,NULL,8.00,'2025-09-06 05:28:18','2025-09-06 05:28:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(797,'2025-09-06',7,3,3,1,NULL,8.00,'2025-09-06 05:28:18','2025-09-06 05:28:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(798,'2025-09-06',6,3,3,1,NULL,8.00,'2025-09-06 05:28:19','2025-09-06 05:28:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(799,'2025-09-06',5,3,3,1,NULL,8.00,'2025-09-06 05:28:19','2025-09-06 05:28:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(800,'2025-09-06',3,3,3,1,NULL,8.00,'2025-09-06 05:28:19','2025-09-06 05:28:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(801,'2025-09-06',1,3,3,1,NULL,8.00,'2025-09-06 05:28:19','2025-09-06 05:28:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(802,'2025-09-08',10,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(803,'2025-09-08',9,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(804,'2025-09-08',7,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(805,'2025-09-08',6,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(806,'2025-09-08',5,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(807,'2025-09-08',3,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(808,'2025-09-08',1,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(809,'2025-09-08',8,5,3,1,NULL,8.00,'2025-09-08 06:47:37','2025-09-08 06:47:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(810,'2025-09-08',4,5,3,1,NULL,8.00,'2025-09-08 06:47:37','2025-09-08 06:47:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(811,'2025-09-08',2,5,3,1,NULL,8.00,'2025-09-08 06:47:37','2025-09-08 06:47:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(812,'2025-09-09',10,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(813,'2025-09-09',9,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(814,'2025-09-09',7,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(815,'2025-09-09',6,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(816,'2025-09-09',5,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(817,'2025-09-09',3,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(818,'2025-09-09',1,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(819,'2025-09-09',8,5,3,1,NULL,8.00,'2025-09-09 06:44:29','2025-09-09 06:44:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(820,'2025-09-09',4,5,3,1,NULL,8.00,'2025-09-09 06:44:29','2025-09-09 06:44:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(821,'2025-09-09',2,5,3,1,NULL,8.00,'2025-09-09 06:44:29','2025-09-09 06:44:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(822,'2025-09-10',10,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(823,'2025-09-10',9,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(824,'2025-09-10',7,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(825,'2025-09-10',6,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(826,'2025-09-10',5,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(827,'2025-09-10',3,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(828,'2025-09-10',1,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(829,'2025-09-10',8,5,3,1,NULL,8.00,'2025-09-10 06:48:43','2025-09-10 06:48:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(830,'2025-09-10',4,5,3,1,NULL,8.00,'2025-09-10 06:48:43','2025-09-10 06:48:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(831,'2025-09-10',2,5,3,1,NULL,8.00,'2025-09-10 06:48:43','2025-09-10 06:48:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(832,'2025-09-11',2,5,3,1,NULL,2.00,'2025-09-11 06:37:11','2025-09-11 06:37:11',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(833,'2025-09-11',2,8,3,1,NULL,6.00,'2025-09-11 06:37:11','2025-09-11 06:37:11',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(834,'2025-09-11',4,5,3,1,NULL,2.00,'2025-09-11 06:38:24','2025-09-11 06:38:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(835,'2025-09-11',4,8,3,1,NULL,2.00,'2025-09-11 06:38:24','2025-09-11 06:38:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(836,'2025-09-11',4,3,3,1,NULL,4.00,'2025-09-11 06:38:24','2025-09-11 06:38:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(838,'2025-09-11',1,3,1,1,NULL,4.00,'2025-09-11 06:40:48','2025-09-11 06:40:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(840,'2025-09-11',5,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(841,'2025-09-11',8,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(842,'2025-09-11',3,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(843,'2025-09-11',7,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(844,'2025-09-11',6,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(845,'2025-09-11',10,3,2,1,NULL,4.00,'2025-09-11 06:41:51','2025-09-11 06:41:51',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(846,'2025-09-11',10,3,3,1,NULL,4.00,'2025-09-11 06:41:51','2025-09-11 06:41:51',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(847,'2025-09-11',9,3,2,1,NULL,4.00,'2025-09-11 06:41:51','2025-09-11 06:41:51',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(848,'2025-09-11',9,3,3,1,NULL,4.00,'2025-09-11 06:41:51','2025-09-11 06:41:51',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(851,'2025-09-12',10,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(852,'2025-09-12',9,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(853,'2025-09-12',8,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(854,'2025-09-12',6,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(855,'2025-09-12',5,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(856,'2025-09-12',4,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(857,'2025-09-12',3,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(858,'2025-09-12',2,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(859,'2025-09-12',1,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(860,'2025-09-12',7,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(861,'2025-09-13',10,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(862,'2025-09-13',8,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(863,'2025-09-13',7,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(864,'2025-09-13',6,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(865,'2025-09-13',5,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(866,'2025-09-13',4,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(867,'2025-09-13',3,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(868,'2025-09-13',2,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(869,'2025-09-13',1,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(870,'2025-09-14',9,3,3,1,NULL,8.00,'2025-09-14 04:47:40','2025-09-14 04:47:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(871,'2025-09-14',8,3,3,1,NULL,8.00,'2025-09-14 04:47:40','2025-09-14 04:47:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(872,'2025-09-14',7,3,3,1,NULL,8.00,'2025-09-14 04:47:40','2025-09-14 04:47:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(873,'2025-09-14',6,3,3,1,NULL,8.00,'2025-09-14 04:47:40','2025-09-14 04:47:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(874,'2025-09-14',5,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(875,'2025-09-14',4,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(876,'2025-09-14',3,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(877,'2025-09-14',2,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(878,'2025-09-14',1,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(879,'2025-09-15',5,3,3,1,NULL,8.00,'2025-09-15 06:50:00','2025-09-15 06:50:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(880,'2025-09-15',10,3,3,1,NULL,8.00,'2025-09-15 06:50:00','2025-09-15 06:50:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(881,'2025-09-15',9,3,3,1,NULL,8.00,'2025-09-15 06:50:00','2025-09-15 06:50:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(882,'2025-09-15',8,3,3,1,NULL,8.00,'2025-09-15 06:50:00','2025-09-15 06:50:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(883,'2025-09-15',7,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(884,'2025-09-15',6,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(885,'2025-09-15',4,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(886,'2025-09-15',3,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(887,'2025-09-15',2,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(888,'2025-09-15',1,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(889,'2025-09-16',2,8,3,1,NULL,8.00,'2025-09-16 06:51:19','2025-09-16 06:51:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(890,'2025-09-16',4,8,3,1,NULL,8.00,'2025-09-16 06:51:19','2025-09-16 06:51:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(891,'2025-09-16',8,8,2,1,NULL,2.00,'2025-09-16 06:52:12','2025-09-16 06:52:12',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(892,'2025-09-16',8,3,2,1,NULL,6.00,'2025-09-16 06:52:12','2025-09-16 06:52:12',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(893,'2025-09-17',4,8,3,1,NULL,8.00,'2025-09-17 06:43:08','2025-09-17 06:43:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(894,'2025-09-17',2,8,3,1,NULL,8.00,'2025-09-17 06:43:08','2025-09-17 06:43:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(895,'2025-09-17',10,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(896,'2025-09-17',9,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(897,'2025-09-17',8,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(898,'2025-09-17',7,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(899,'2025-09-17',6,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(900,'2025-09-17',5,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(901,'2025-09-17',3,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(902,'2025-09-17',1,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(903,'2025-09-18',7,3,3,1,NULL,8.00,'2025-09-18 06:43:40','2025-09-18 06:43:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(904,'2025-09-18',1,3,3,1,NULL,8.00,'2025-09-18 06:43:40','2025-09-18 06:43:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(905,'2025-09-18',10,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(906,'2025-09-18',9,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(907,'2025-09-18',8,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(908,'2025-09-18',6,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(909,'2025-09-18',3,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(910,'2025-09-18',5,3,2,1,NULL,6.00,'2025-09-18 06:46:39','2025-09-18 06:46:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(911,'2025-09-18',2,8,3,1,NULL,8.00,'2025-09-18 06:54:48','2025-09-18 06:54:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(912,'2025-09-18',4,8,3,1,NULL,8.00,'2025-09-18 06:54:48','2025-09-18 06:54:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(913,'2025-09-19',4,8,3,1,NULL,8.00,'2025-09-19 06:51:40','2025-09-19 06:51:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(914,'2025-09-19',2,8,3,1,NULL,8.00,'2025-09-19 06:51:40','2025-09-19 06:51:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(915,'2025-09-19',10,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(916,'2025-09-19',8,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(917,'2025-09-19',7,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(918,'2025-09-19',6,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(919,'2025-09-19',5,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(920,'2025-09-19',3,3,2,1,NULL,4.00,'2025-09-19 06:52:23','2025-09-19 06:52:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(921,'2025-09-20',4,8,3,1,NULL,8.00,'2025-09-20 05:30:19','2025-09-20 05:30:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(922,'2025-09-20',2,8,3,1,NULL,8.00,'2025-09-20 05:30:19','2025-09-20 05:30:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(923,'2025-09-22',10,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(924,'2025-09-22',9,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(925,'2025-09-22',8,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(926,'2025-09-22',7,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(927,'2025-09-22',5,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(928,'2025-09-22',1,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(929,'2025-09-22',4,8,3,1,NULL,8.00,'2025-09-22 06:50:29','2025-09-22 06:50:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(930,'2025-09-22',2,8,3,1,NULL,8.00,'2025-09-22 06:50:29','2025-09-22 06:50:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(931,'2025-09-23',4,8,3,1,NULL,8.00,'2025-09-23 05:46:40','2025-09-23 05:46:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(932,'2025-09-23',2,8,3,1,NULL,8.00,'2025-09-23 05:46:40','2025-09-23 05:46:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(933,'2025-09-24',4,8,3,1,NULL,8.00,'2025-09-25 01:14:58','2025-09-25 01:14:58',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(934,'2025-09-24',2,8,3,1,NULL,8.00,'2025-09-25 01:14:58','2025-09-25 01:14:58',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(935,'2025-09-29',7,14,1,1,NULL,8.00,'2025-09-29 06:36:07','2025-09-29 06:36:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(936,'2025-09-29',1,14,1,1,NULL,8.00,'2025-09-29 06:36:07','2025-09-29 06:36:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(937,'2025-09-29',10,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(938,'2025-09-29',8,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(939,'2025-09-29',6,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(940,'2025-09-29',9,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(941,'2025-09-29',5,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(942,'2025-09-29',4,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(943,'2025-09-29',3,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(944,'2025-09-29',2,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(945,'2025-09-30',10,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(946,'2025-09-30',9,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(947,'2025-09-30',8,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(948,'2025-09-30',6,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(949,'2025-09-30',5,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(950,'2025-09-30',4,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(951,'2025-09-30',3,3,2,1,NULL,8.00,'2025-09-30 06:52:27','2025-09-30 06:52:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(953,'2025-09-30',1,3,2,1,NULL,8.00,'2025-09-30 06:52:27','2025-09-30 06:52:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(954,'2025-09-30',2,8,3,1,NULL,8.00,'2025-09-30 06:56:55','2025-09-30 06:56:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(955,'2025-10-02',5,3,2,1,NULL,6.00,'2025-10-02 05:25:58','2025-10-02 05:25:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(956,'2025-10-02',8,3,2,1,NULL,6.00,'2025-10-02 05:25:59','2025-10-02 05:25:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(957,'2025-10-02',10,3,2,1,NULL,8.00,'2025-10-02 06:22:32','2025-10-02 06:22:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(958,'2025-10-02',9,3,2,1,NULL,8.00,'2025-10-02 06:22:32','2025-10-02 06:22:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(959,'2025-10-02',7,3,2,1,NULL,8.00,'2025-10-02 06:22:32','2025-10-02 06:22:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(960,'2025-10-02',6,3,2,1,NULL,8.00,'2025-10-02 06:22:32','2025-10-02 06:22:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(961,'2025-10-02',4,3,2,1,NULL,8.00,'2025-10-02 06:22:33','2025-10-02 06:22:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(962,'2025-10-02',2,3,2,1,NULL,8.00,'2025-10-02 06:22:33','2025-10-02 06:22:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(963,'2025-10-02',1,3,2,1,NULL,8.00,'2025-10-02 06:22:33','2025-10-02 06:22:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(964,'2025-09-01',8,5,3,1,NULL,8.00,'2025-10-10 23:35:07','2025-10-10 23:35:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(965,'2025-09-01',4,5,3,1,NULL,8.00,'2025-10-10 23:35:07','2025-10-10 23:35:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(966,'2025-09-01',2,5,3,1,NULL,8.00,'2025-10-10 23:35:07','2025-10-10 23:35:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(967,'2025-10-13',10,10,3,1,NULL,8.00,'2025-10-13 06:53:05','2025-10-13 06:53:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(968,'2025-10-13',7,10,3,1,NULL,8.00,'2025-10-13 06:53:05','2025-10-13 06:53:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(969,'2025-10-13',2,10,3,1,NULL,8.00,'2025-10-13 06:53:05','2025-10-13 06:53:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(970,'2025-10-13',8,3,2,1,NULL,8.00,'2025-10-13 06:53:30','2025-10-13 06:53:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(971,'2025-10-13',6,3,2,1,NULL,8.00,'2025-10-13 06:53:30','2025-10-13 06:53:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(972,'2025-10-13',3,3,2,1,NULL,8.00,'2025-10-13 06:53:30','2025-10-13 06:53:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(973,'2025-10-13',5,3,3,1,NULL,8.00,'2025-10-13 06:53:53','2025-10-13 06:53:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(974,'2025-10-13',4,3,3,1,NULL,8.00,'2025-10-13 06:53:53','2025-10-13 06:53:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(975,'2025-10-13',9,3,2,1,NULL,4.00,'2025-10-13 06:54:19','2025-10-13 06:54:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(976,'2025-10-13',9,10,3,1,NULL,4.00,'2025-10-13 06:54:19','2025-10-13 06:54:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(977,'2025-10-13',1,3,1,1,NULL,8.00,'2025-10-13 06:54:41','2025-10-13 06:54:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(978,'2025-10-14',10,10,3,1,NULL,8.00,'2025-10-14 06:55:49','2025-10-14 06:55:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(979,'2025-10-14',2,10,3,1,NULL,8.00,'2025-10-14 06:55:49','2025-10-14 06:55:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(980,'2025-10-14',9,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(981,'2025-10-14',8,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(982,'2025-10-14',7,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(983,'2025-10-14',6,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(984,'2025-10-14',5,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(985,'2025-10-14',4,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(986,'2025-10-14',3,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(987,'2025-10-14',1,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(988,'2025-10-15',8,3,2,1,NULL,8.00,'2025-10-15 06:58:52','2025-10-15 06:58:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(989,'2025-10-15',7,3,2,1,NULL,8.00,'2025-10-15 06:58:52','2025-10-15 06:58:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(990,'2025-10-15',6,3,2,1,NULL,8.00,'2025-10-15 06:58:52','2025-10-15 06:58:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(991,'2025-10-15',5,3,2,1,NULL,8.00,'2025-10-15 06:58:52','2025-10-15 06:58:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(992,'2025-10-15',4,3,2,1,NULL,8.00,'2025-10-15 06:58:53','2025-10-15 06:58:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(993,'2025-10-15',3,3,2,1,NULL,8.00,'2025-10-15 06:58:53','2025-10-15 06:58:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(994,'2025-10-15',1,3,2,1,NULL,8.00,'2025-10-15 06:58:53','2025-10-15 06:58:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(995,'2025-10-15',10,10,3,1,6,8.00,'2025-10-15 06:59:41','2026-02-05 22:40:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(996,'2025-10-15',9,10,3,1,NULL,8.00,'2025-10-15 06:59:41','2025-10-15 06:59:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(997,'2025-10-15',2,10,3,1,NULL,4.00,'2025-10-15 07:00:06','2025-10-15 07:00:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(998,'2025-10-16',9,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(999,'2025-10-16',8,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1000,'2025-10-16',7,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1001,'2025-10-16',6,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1002,'2025-10-16',5,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1003,'2025-10-16',4,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1004,'2025-10-16',3,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1005,'2025-10-16',1,3,2,1,NULL,8.00,'2025-10-16 06:52:00','2025-10-16 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1006,'2025-10-20',9,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1007,'2025-10-20',8,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1008,'2025-10-20',7,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1009,'2025-10-20',6,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1010,'2025-10-20',5,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1011,'2025-10-20',4,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1012,'2025-10-20',3,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1013,'2025-10-20',1,3,2,1,NULL,8.00,'2025-10-20 06:49:46','2025-10-20 06:49:46',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1014,'2025-10-20',2,10,3,1,NULL,8.00,'2025-10-20 06:50:55','2025-10-20 06:50:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1015,'2025-10-20',10,10,3,1,NULL,8.00,'2025-10-20 06:50:55','2025-10-20 06:50:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1017,'2025-10-21',10,3,3,1,NULL,4.00,'2025-10-21 08:42:41','2025-10-21 08:42:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1019,'2025-10-21',2,3,3,1,NULL,4.00,'2025-10-21 08:42:41','2025-10-21 08:42:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1020,'2025-10-21',8,3,2,1,NULL,10.00,'2025-10-21 08:43:34','2025-10-21 08:43:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1021,'2025-10-21',6,3,2,1,NULL,10.00,'2025-10-21 08:43:34','2025-10-21 08:43:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1022,'2025-10-21',3,3,2,1,NULL,10.00,'2025-10-21 08:43:34','2025-10-21 08:43:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1023,'2025-10-21',10,10,3,1,NULL,6.00,'2025-10-21 08:44:26','2025-10-21 08:44:26',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1024,'2025-10-21',2,10,3,1,NULL,6.00,'2025-10-21 08:44:27','2025-10-21 08:44:27',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1025,'2025-10-21',5,3,3,1,NULL,10.00,'2025-10-21 08:45:01','2025-10-21 08:45:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1026,'2025-10-21',4,3,3,1,NULL,10.00,'2025-10-21 08:45:01','2025-10-21 08:45:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1027,'2025-10-21',9,3,3,1,NULL,10.00,'2025-10-21 08:45:28','2025-10-21 08:45:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1028,'2025-10-21',1,3,3,1,NULL,10.00,'2025-10-21 08:45:28','2025-10-21 08:45:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1029,'2025-10-21',7,3,3,1,NULL,10.00,'2025-10-21 08:45:28','2025-10-21 08:45:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1030,'2025-10-22',2,11,2,1,NULL,4.00,'2025-10-22 06:47:36','2025-10-22 06:47:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1031,'2025-10-22',2,10,1,1,NULL,4.00,'2025-10-22 06:47:36','2025-10-22 06:47:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1032,'2025-10-22',10,11,2,1,NULL,4.00,'2025-10-22 06:47:36','2025-10-22 06:47:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1033,'2025-10-22',10,10,1,1,NULL,4.00,'2025-10-22 06:47:36','2025-10-22 06:47:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1034,'2025-10-22',9,3,3,1,NULL,8.00,'2025-10-22 06:48:06','2025-10-22 06:48:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1035,'2025-10-22',8,3,3,1,NULL,8.00,'2025-10-22 06:48:06','2025-10-22 06:48:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1036,'2025-10-22',6,3,3,1,NULL,8.00,'2025-10-22 06:48:06','2025-10-22 06:48:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1039,'2025-10-22',7,3,3,1,NULL,8.00,'2025-10-22 06:48:11','2025-10-22 06:48:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1043,'2025-10-22',3,3,3,1,NULL,8.00,'2025-10-22 06:48:11','2025-10-22 06:48:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1044,'2025-10-22',1,3,3,1,NULL,8.00,'2025-10-22 06:48:11','2025-10-22 06:48:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1047,'2025-10-22',5,11,3,1,NULL,8.00,'2025-10-22 06:48:50','2025-10-22 06:48:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1048,'2025-10-22',4,11,3,1,NULL,8.00,'2025-10-22 06:48:50','2025-10-22 06:48:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1051,'2025-10-24',9,3,3,1,NULL,8.00,'2025-10-24 06:47:05','2025-10-24 06:47:05',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1052,'2025-10-24',8,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1053,'2025-10-24',7,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1054,'2025-10-24',6,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1055,'2025-10-24',5,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1056,'2025-10-24',3,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1057,'2025-10-24',1,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1058,'2025-10-24',4,3,3,1,NULL,4.00,'2025-10-24 06:48:13','2025-10-24 06:48:13',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1059,'2025-10-25',10,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1060,'2025-10-25',8,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1061,'2025-10-25',6,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1062,'2025-10-25',5,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1063,'2025-10-25',4,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1064,'2025-10-25',3,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1065,'2025-10-25',1,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1066,'2025-10-27',9,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1067,'2025-10-27',8,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1070,'2025-10-27',5,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1071,'2025-10-27',4,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1072,'2025-10-27',3,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1074,'2025-10-27',6,3,3,1,NULL,4.00,'2025-10-27 06:43:11','2025-10-27 06:43:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1075,'2025-10-27',10,10,3,1,NULL,8.00,'2025-10-28 08:44:41','2025-10-28 08:44:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1076,'2025-10-27',2,10,3,1,NULL,8.00,'2025-10-28 08:44:41','2025-10-28 08:44:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1077,'2025-10-28',10,10,3,1,NULL,10.00,'2025-10-28 08:45:05','2025-10-28 08:45:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1078,'2025-10-28',2,10,3,1,NULL,10.00,'2025-10-28 08:45:05','2025-10-28 08:45:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1079,'2025-10-28',7,3,1,2,6,10.00,'2025-10-28 08:47:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1080,'2025-10-28',1,3,1,2,6,10.00,'2025-10-28 08:47:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1081,'2025-10-28',9,3,3,1,NULL,10.00,'2025-10-28 08:48:02','2025-10-28 08:48:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1082,'2025-10-28',8,3,3,1,NULL,10.00,'2025-10-28 08:48:02','2025-10-28 08:48:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1083,'2025-10-28',6,3,3,1,NULL,10.00,'2025-10-28 08:48:02','2025-10-28 08:48:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1084,'2025-10-28',5,3,3,1,NULL,10.00,'2025-10-28 08:48:02','2025-10-28 08:48:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1085,'2025-10-28',4,3,3,1,NULL,10.00,'2025-10-28 08:48:03','2025-10-28 08:48:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1086,'2025-10-28',3,3,3,1,NULL,10.00,'2025-10-28 08:48:03','2025-10-28 08:48:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1087,'2025-10-29',8,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1089,'2025-10-29',6,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1090,'2025-10-29',5,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1091,'2025-10-29',4,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1092,'2025-10-29',3,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1094,'2025-10-29',10,10,3,1,NULL,8.00,'2025-10-29 06:51:44','2025-10-29 06:51:44',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1095,'2025-10-29',2,10,3,1,NULL,8.00,'2025-10-29 06:51:44','2025-10-29 06:51:44',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1097,'2025-10-30',8,3,3,1,NULL,8.00,'2025-10-30 08:49:06','2025-10-30 08:49:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1098,'2025-10-30',8,10,3,1,NULL,2.00,'2025-10-30 08:49:06','2025-10-30 08:49:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1099,'2025-10-30',9,13,4,1,NULL,0.00,'2025-10-30 08:49:47','2025-10-30 08:49:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1100,'2025-10-30',7,3,3,1,NULL,10.00,'2025-10-30 08:50:19','2025-10-30 08:50:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1101,'2025-10-30',5,11,3,1,NULL,10.00,'2025-10-30 08:50:43','2025-10-30 08:50:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1102,'2025-10-30',4,11,3,1,NULL,10.00,'2025-10-30 08:50:43','2025-10-30 08:50:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1104,'2025-10-30',2,10,3,1,NULL,10.00,'2025-10-30 08:51:30','2025-10-30 08:51:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1105,'2025-10-30',6,3,3,1,NULL,10.00,'2025-10-30 08:52:04','2025-10-30 08:52:04',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1106,'2025-10-30',3,3,3,1,NULL,10.00,'2025-10-30 08:52:04','2025-10-30 08:52:04',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1107,'2025-10-31',9,10,3,2,6,8.00,'2025-10-31 06:53:09','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1108,'2025-10-31',2,10,3,2,6,8.00,'2025-10-31 06:53:09','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1110,'2025-11-01',10,10,3,1,NULL,8.00,'2025-11-01 05:55:09','2025-11-01 05:55:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1111,'2025-11-01',9,10,3,1,NULL,8.00,'2025-11-01 05:55:09','2025-11-01 05:55:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1112,'2025-11-01',2,10,3,1,NULL,8.00,'2025-11-01 05:55:09','2025-11-01 05:55:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1113,'2025-10-30',1,13,1,1,NULL,2.00,'2025-11-03 21:48:30','2025-11-03 21:48:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1114,'2025-10-30',9,13,1,1,NULL,8.00,'2025-11-03 21:56:32','2025-11-03 21:56:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1115,'2025-10-01',10,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1116,'2025-10-01',4,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1117,'2025-10-01',3,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1118,'2025-10-01',9,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1119,'2025-10-01',8,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1120,'2025-10-01',2,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1121,'2025-10-01',1,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1122,'2025-10-01',7,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1123,'2025-10-01',6,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1124,'2025-10-01',5,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1125,'2025-10-02',5,13,1,1,NULL,2.00,'2025-11-04 05:30:23','2025-11-04 05:30:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1126,'2025-10-02',8,13,1,1,NULL,2.00,'2025-11-04 05:31:11','2025-11-04 05:31:11',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1127,'2025-10-02',3,13,11,1,NULL,8.00,'2025-11-04 06:09:53','2025-11-04 06:09:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1128,'2025-10-15',2,13,11,1,NULL,4.00,'2025-11-04 06:10:29','2025-11-04 06:10:29',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1130,'2025-10-16',2,10,3,2,6,8.00,'2025-11-04 06:11:29','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1131,'2025-10-16',10,10,3,2,6,8.00,'2025-11-04 06:11:47','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1132,'2025-10-24',10,10,3,2,6,8.00,'2025-11-04 06:12:35','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1133,'2025-10-24',2,10,3,2,6,8.00,'2025-11-04 06:12:51','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1134,'2025-10-24',4,13,11,1,NULL,4.00,'2025-11-04 06:13:01','2025-11-04 06:13:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1135,'2025-10-27',6,13,11,1,NULL,4.00,'2025-11-04 06:13:24','2025-11-04 06:13:24',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1136,'2025-10-30',10,10,3,1,NULL,8.00,'2025-11-04 06:15:07','2025-11-04 06:15:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1137,'2025-10-29',9,3,3,1,NULL,8.00,'2025-11-04 06:15:43','2025-11-04 06:15:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1138,'2025-10-25',9,13,11,1,NULL,8.00,'2025-11-04 06:17:02','2025-11-04 06:17:02',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1139,'2025-10-25',7,13,11,1,NULL,8.00,'2025-11-04 06:17:15','2025-11-04 06:17:15',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1140,'2025-10-25',2,13,11,1,NULL,8.00,'2025-11-04 06:17:29','2025-11-04 06:17:29',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1141,'2025-10-17',10,10,3,2,6,8.00,'2025-11-04 06:31:47','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1142,'2025-10-17',2,10,3,2,6,8.00,'2025-11-04 06:31:47','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1143,'2025-10-17',9,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1144,'2025-10-17',8,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1145,'2025-10-17',7,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1146,'2025-10-17',6,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1147,'2025-10-17',5,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1148,'2025-10-17',4,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1149,'2025-10-17',3,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1150,'2025-10-17',1,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1151,'2025-10-23',2,10,3,2,6,10.00,'2025-11-04 06:37:19','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1152,'2025-10-23',10,10,3,2,6,10.00,'2025-11-04 06:37:19','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1153,'2025-10-23',9,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1154,'2025-10-23',8,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1155,'2025-10-23',7,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1156,'2025-10-23',6,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1157,'2025-10-23',5,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1159,'2025-10-23',3,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1160,'2025-10-23',4,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1161,'2025-10-31',10,10,3,2,6,8.00,'2025-11-04 06:38:35','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1164,'2025-10-31',3,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1165,'2025-10-31',4,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1166,'2025-10-31',1,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1167,'2025-10-31',7,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1168,'2025-10-31',5,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1169,'2025-10-31',8,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1170,'2025-10-31',6,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1171,'2025-10-23',1,3,3,2,6,8.00,'2025-11-04 06:43:18','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1172,'2025-10-30',1,3,3,1,NULL,5.00,'2025-11-04 22:27:07','2025-11-04 22:27:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1173,'2025-10-30',1,14,1,1,NULL,1.00,'2025-11-04 22:27:22','2025-11-04 22:27:22',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1174,'2025-10-29',1,3,3,1,NULL,7.00,'2025-11-04 22:27:49','2025-11-04 22:27:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1175,'2025-10-29',1,14,1,1,NULL,1.00,'2025-11-04 22:28:03','2025-11-04 22:28:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1176,'2025-10-29',7,14,1,1,NULL,1.00,'2025-11-04 22:28:22','2025-11-04 22:28:22',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1177,'2025-10-29',7,3,3,1,NULL,7.00,'2025-11-04 22:28:32','2025-11-04 22:28:32',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1178,'2025-10-27',1,3,3,1,NULL,6.00,'2025-11-04 22:29:03','2025-11-04 22:29:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1179,'2025-10-27',1,14,1,1,NULL,2.00,'2025-11-04 22:29:13','2025-11-04 22:29:13',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1180,'2025-10-27',7,14,1,1,NULL,2.00,'2025-11-04 22:29:34','2025-11-04 22:29:34',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1181,'2025-10-27',7,3,3,1,NULL,6.00,'2025-11-04 22:29:45','2025-11-04 22:29:45',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1192,'2025-11-03',2,10,3,2,6,8.00,'2025-11-05 02:54:31','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1193,'2025-11-03',10,10,3,2,6,8.00,'2025-11-05 02:54:31','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1194,'2025-11-03',9,10,3,2,6,6.00,'2025-11-05 02:55:16','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1195,'2025-11-03',9,3,3,1,NULL,2.00,'2025-11-05 02:55:16','2025-11-05 02:55:16',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1196,'2025-11-03',6,10,3,2,6,6.00,'2025-11-05 02:55:16','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1197,'2025-11-03',6,3,3,1,NULL,2.00,'2025-11-05 02:55:16','2025-11-05 02:55:16',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1199,'2025-11-05',10,10,3,1,NULL,8.00,'2025-11-05 06:54:26','2025-11-05 06:54:26',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1200,'2025-11-05',2,10,3,1,NULL,8.00,'2025-11-05 06:54:26','2025-11-05 06:54:26',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1201,'2025-11-05',9,10,3,1,NULL,4.00,'2025-11-05 06:54:40','2025-11-05 06:54:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1202,'2025-11-06',10,10,3,2,6,4.00,'2025-11-06 08:44:42','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1203,'2025-11-06',10,11,3,1,NULL,6.00,'2025-11-06 08:44:42','2025-11-06 08:44:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1204,'2025-11-06',4,11,1,1,NULL,10.00,'2025-11-06 08:45:59','2025-11-06 08:45:59',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1205,'2025-11-06',5,11,1,1,NULL,10.00,'2025-11-06 08:45:59','2025-11-06 08:45:59',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1206,'2025-11-06',2,10,3,2,6,1.00,'2025-11-06 08:46:46','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1207,'2025-11-06',2,11,3,1,NULL,9.00,'2025-11-06 08:46:46','2025-11-06 08:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1208,'2025-11-06',9,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1209,'2025-11-06',8,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1210,'2025-11-06',7,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1211,'2025-11-06',6,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1212,'2025-11-06',3,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1213,'2025-11-06',1,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1214,'2025-11-07',7,3,3,1,NULL,4.00,'2025-11-07 06:48:19','2025-11-07 06:48:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1217,'2025-11-07',9,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1218,'2025-11-07',8,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1219,'2025-11-07',6,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1222,'2025-11-07',3,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1223,'2025-11-07',1,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1224,'2025-11-07',4,10,3,1,NULL,2.00,'2025-11-07 06:49:20','2025-11-07 06:49:20',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1225,'2025-11-07',4,3,3,1,NULL,6.00,'2025-11-07 06:49:20','2025-11-07 06:49:20',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1226,'2025-11-07',5,10,3,1,NULL,2.00,'2025-11-07 06:49:20','2025-11-07 06:49:20',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1227,'2025-11-07',5,3,3,1,NULL,6.00,'2025-11-07 06:49:20','2025-11-07 06:49:20',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1228,'2025-11-07',2,11,3,1,NULL,8.00,'2025-11-07 06:50:15','2025-11-07 06:50:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1229,'2025-11-07',10,11,3,1,NULL,8.00,'2025-11-07 06:50:55','2025-11-07 06:50:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1230,'2025-11-08',10,11,3,1,NULL,8.00,'2025-11-08 05:53:23','2025-11-08 05:53:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1231,'2025-11-08',2,11,3,1,NULL,8.00,'2025-11-08 05:53:24','2025-11-08 05:53:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1232,'2025-11-09',10,10,3,1,NULL,8.00,'2025-11-09 05:39:09','2025-11-09 05:39:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1233,'2025-11-09',2,10,3,1,NULL,8.00,'2025-11-09 05:39:09','2025-11-09 05:39:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1234,'2025-11-09',9,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1235,'2025-11-09',8,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1236,'2025-11-09',7,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1237,'2025-11-09',6,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1238,'2025-11-09',3,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1239,'2025-11-10',10,10,3,1,NULL,8.00,'2025-11-11 08:28:29','2025-11-11 08:28:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1240,'2025-11-10',4,10,3,1,NULL,8.00,'2025-11-11 08:28:29','2025-11-11 08:28:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1241,'2025-11-10',2,10,3,1,NULL,8.00,'2025-11-11 08:28:29','2025-11-11 08:28:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1242,'2025-11-11',10,11,3,1,NULL,8.00,'2025-11-11 08:29:03','2025-11-11 08:29:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1243,'2025-11-11',9,11,3,1,NULL,8.00,'2025-11-11 08:29:03','2025-11-11 08:29:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1244,'2025-11-11',4,10,3,1,NULL,4.00,'2025-11-11 08:29:45','2025-11-11 08:29:45',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1245,'2025-11-11',4,11,3,1,NULL,6.00,'2025-11-11 08:29:45','2025-11-11 08:29:45',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1246,'2025-11-11',2,10,3,1,NULL,10.00,'2025-11-11 08:30:08','2025-11-11 08:30:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1247,'2025-11-11',10,11,3,1,NULL,2.00,'2025-11-11 08:30:35','2025-11-11 08:30:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1248,'2025-11-11',9,11,3,1,NULL,2.00,'2025-11-11 08:30:35','2025-11-11 08:30:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1249,'2025-11-11',7,3,3,1,NULL,8.00,'2025-11-11 08:45:23','2025-11-11 08:45:23',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1251,'2025-11-11',8,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1252,'2025-11-11',6,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1253,'2025-11-11',5,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1254,'2025-11-11',3,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1255,'2025-11-11',1,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1256,'2025-11-12',10,11,3,1,NULL,8.00,'2025-11-12 06:47:21','2025-11-12 06:47:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1257,'2025-11-12',2,11,3,1,NULL,8.00,'2025-11-12 06:47:21','2025-11-12 06:47:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1258,'2025-11-12',9,11,3,1,NULL,8.00,'2025-11-12 06:47:21','2025-11-12 06:47:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1259,'2025-11-12',8,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1260,'2025-11-12',7,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1261,'2025-11-12',6,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1262,'2025-11-12',5,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1263,'2025-11-12',3,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1264,'2025-11-12',1,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1265,'2025-11-13',10,11,3,1,NULL,10.00,'2025-11-13 08:46:09','2025-11-13 08:46:09',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1266,'2025-11-13',4,11,3,1,NULL,10.00,'2025-11-13 08:46:09','2025-11-13 08:46:09',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1267,'2025-11-13',2,11,3,1,NULL,4.00,'2025-11-13 08:46:32','2025-11-13 08:46:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1268,'2025-11-13',9,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1269,'2025-11-13',8,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1270,'2025-11-13',7,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1271,'2025-11-13',6,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1272,'2025-11-13',5,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1273,'2025-11-13',3,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1274,'2025-11-13',1,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1275,'2025-11-14',10,11,3,1,NULL,6.00,'2025-11-14 07:00:16','2025-11-14 07:00:16',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1276,'2025-11-14',10,11,3,2,6,2.00,'2025-11-14 07:00:16','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1277,'2025-11-14',9,11,3,1,NULL,6.00,'2025-11-14 07:00:16','2025-11-14 07:00:16',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1278,'2025-11-14',9,11,3,2,6,2.00,'2025-11-14 07:00:16','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1279,'2025-11-14',2,11,3,1,NULL,6.00,'2025-11-14 07:00:17','2025-11-14 07:00:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1280,'2025-11-14',2,11,3,2,6,2.00,'2025-11-14 07:00:17','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1281,'2025-11-14',8,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1282,'2025-11-14',8,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1283,'2025-11-14',7,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1284,'2025-11-14',7,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1285,'2025-11-14',5,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1286,'2025-11-14',5,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1287,'2025-11-14',6,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1288,'2025-11-14',6,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1289,'2025-11-14',4,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1290,'2025-11-14',4,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1291,'2025-11-14',3,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1292,'2025-11-14',3,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1293,'2025-11-14',1,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1294,'2025-11-14',1,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1295,'2025-11-15',10,11,3,1,NULL,8.00,'2025-11-15 05:46:53','2025-11-15 05:46:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1296,'2025-11-15',9,11,3,1,NULL,8.00,'2025-11-15 05:46:53','2025-11-15 05:46:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1297,'2025-11-15',2,11,3,1,NULL,8.00,'2025-11-15 05:46:53','2025-11-15 05:46:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1298,'2025-11-17',10,11,3,1,NULL,8.00,'2025-11-18 08:45:07','2025-11-18 08:45:07',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1300,'2025-11-17',2,11,3,1,NULL,8.00,'2025-11-18 08:45:08','2025-11-18 08:45:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1301,'2025-11-18',4,11,3,1,NULL,6.00,'2025-11-18 08:46:01','2025-11-18 08:46:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1302,'2025-11-18',4,10,3,1,NULL,4.00,'2025-11-18 08:46:01','2025-11-18 08:46:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1303,'2025-11-18',2,11,3,1,NULL,6.00,'2025-11-18 08:46:01','2025-11-18 08:46:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1304,'2025-11-18',2,10,3,1,NULL,4.00,'2025-11-18 08:46:01','2025-11-18 08:46:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1305,'2025-11-18',10,11,3,1,NULL,10.00,'2025-11-18 08:46:23','2025-11-18 08:46:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1306,'2025-11-24',2,11,3,1,NULL,8.00,'2025-11-25 08:47:55','2025-11-25 08:47:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1307,'2025-11-24',4,11,3,1,NULL,8.00,'2025-11-25 08:47:55','2025-11-25 08:47:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1308,'2025-11-22',4,11,3,1,NULL,8.00,'2025-11-25 08:48:18','2025-11-25 08:48:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1309,'2025-11-22',2,11,3,1,NULL,8.00,'2025-11-25 08:48:18','2025-11-25 08:48:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1310,'2025-11-21',4,11,3,1,NULL,8.00,'2025-11-25 08:48:39','2025-11-25 08:48:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1311,'2025-11-21',2,11,3,1,NULL,8.00,'2025-11-25 08:48:39','2025-11-25 08:48:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1312,'2025-11-25',4,11,3,1,NULL,10.00,'2025-11-25 08:49:02','2025-11-25 08:49:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1313,'2025-11-25',2,11,3,1,NULL,10.00,'2025-11-25 08:49:02','2025-11-25 08:49:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1314,'2025-11-26',10,11,3,1,NULL,8.00,'2025-11-26 06:51:13','2025-11-26 06:51:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1315,'2025-11-26',4,11,3,1,NULL,8.00,'2025-11-26 06:51:13','2025-11-26 06:51:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1316,'2025-11-26',2,11,3,1,NULL,8.00,'2025-11-26 06:51:13','2025-11-26 06:51:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1317,'2025-11-27',10,11,3,1,NULL,10.00,'2025-11-27 07:34:37','2025-11-27 07:34:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1318,'2025-11-27',4,11,3,1,NULL,10.00,'2025-11-27 07:34:37','2025-11-27 07:34:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1319,'2025-11-27',2,11,3,1,NULL,10.00,'2025-11-27 07:34:37','2025-11-27 07:34:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1320,'2025-11-27',9,11,3,1,NULL,6.00,'2025-11-27 07:35:24','2025-11-27 07:35:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1321,'2025-11-27',9,3,3,1,NULL,4.00,'2025-11-27 07:35:24','2025-11-27 07:35:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1322,'2025-11-28',10,11,3,1,NULL,8.00,'2025-11-28 06:47:35','2025-11-28 06:47:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1323,'2025-11-28',9,11,3,1,NULL,8.00,'2025-11-28 06:47:35','2025-11-28 06:47:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1324,'2025-11-28',2,11,3,1,NULL,8.00,'2025-11-28 06:47:35','2025-11-28 06:47:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1325,'2025-11-28',4,13,11,1,NULL,1.00,'2025-11-28 06:48:24','2025-11-28 06:48:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1326,'2025-11-29',10,11,3,1,NULL,8.00,'2025-11-29 05:12:39','2025-11-29 05:12:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1327,'2025-11-29',4,11,3,1,NULL,8.00,'2025-11-29 05:12:39','2025-11-29 05:12:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1328,'2025-11-29',2,11,3,1,NULL,8.00,'2025-11-29 05:12:39','2025-11-29 05:12:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1329,'2025-11-29',1,3,3,1,NULL,4.00,'2025-11-29 05:17:02','2025-11-29 05:17:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1331,'2025-11-29',8,3,3,1,NULL,8.00,'2025-11-29 05:17:46','2025-11-29 05:17:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1332,'2025-11-29',6,3,3,1,NULL,8.00,'2025-11-29 05:17:46','2025-11-29 05:17:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1333,'2025-11-29',5,3,3,1,NULL,8.00,'2025-11-29 05:17:46','2025-11-29 05:17:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1334,'2025-11-29',3,3,3,1,NULL,8.00,'2025-11-29 05:17:46','2025-11-29 05:17:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1335,'2025-12-01',10,11,3,1,NULL,8.00,'2025-12-01 06:55:15','2025-12-01 06:55:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1336,'2025-12-01',9,11,3,1,NULL,8.00,'2025-12-01 06:55:15','2025-12-01 06:55:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1337,'2025-12-01',4,11,3,1,NULL,8.00,'2025-12-01 06:55:15','2025-12-01 06:55:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1338,'2025-12-01',2,11,3,1,NULL,8.00,'2025-12-01 06:55:15','2025-12-01 06:55:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1339,'2025-11-01',8,3,3,1,NULL,4.00,'2025-12-02 02:07:51','2025-12-02 02:07:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1340,'2025-11-01',8,3,3,2,6,4.00,'2025-12-02 02:07:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1341,'2025-11-01',7,3,3,1,NULL,4.00,'2025-12-02 02:07:52','2025-12-02 02:07:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1342,'2025-11-01',7,3,3,2,6,4.00,'2025-12-02 02:07:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1345,'2025-11-01',5,3,3,1,NULL,4.00,'2025-12-02 02:07:52','2025-12-02 02:07:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1346,'2025-11-01',5,3,3,2,6,4.00,'2025-12-02 02:07:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1347,'2025-11-01',4,3,3,1,NULL,4.00,'2025-12-02 02:07:52','2025-12-02 02:07:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1348,'2025-11-01',4,3,3,2,6,4.00,'2025-12-02 02:07:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1349,'2025-11-01',3,3,3,1,NULL,4.00,'2025-12-02 02:07:52','2025-12-02 02:07:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1350,'2025-11-01',3,3,3,2,6,4.00,'2025-12-02 02:07:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1353,'2025-11-03',8,3,3,1,NULL,4.00,'2025-12-02 02:09:19','2025-12-02 02:09:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1354,'2025-11-03',8,3,3,2,6,4.00,'2025-12-02 02:09:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1356,'2025-11-03',5,3,3,1,NULL,4.00,'2025-12-02 02:09:19','2025-12-02 02:09:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1357,'2025-11-03',5,3,3,2,6,4.00,'2025-12-02 02:09:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1359,'2025-11-03',4,3,3,1,NULL,4.00,'2025-12-02 02:09:19','2025-12-02 02:09:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1360,'2025-11-03',4,3,3,2,6,4.00,'2025-12-02 02:09:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1362,'2025-11-03',3,3,3,1,NULL,4.00,'2025-12-02 02:09:19','2025-12-02 02:09:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1363,'2025-11-03',3,3,3,2,6,4.00,'2025-12-02 02:09:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1369,'2025-11-03',7,13,1,1,NULL,8.00,'2025-12-02 02:11:57','2025-12-02 02:11:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1370,'2025-11-04',10,10,3,1,NULL,6.00,'2025-12-02 02:17:03','2025-12-02 02:17:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1371,'2025-11-04',10,10,3,2,6,4.00,'2025-12-02 02:17:03','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1372,'2025-11-04',9,10,3,1,NULL,6.00,'2025-12-02 02:17:03','2025-12-02 02:17:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1373,'2025-11-04',9,10,3,2,6,4.00,'2025-12-02 02:17:03','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1374,'2025-11-04',2,10,3,1,NULL,6.00,'2025-12-02 02:17:03','2025-12-02 02:17:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1375,'2025-11-04',2,10,3,2,6,4.00,'2025-12-02 02:17:03','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1376,'2025-11-04',8,3,3,1,NULL,8.00,'2025-12-02 02:19:20','2025-12-02 02:19:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1377,'2025-11-04',6,3,3,2,6,4.00,'2025-12-02 02:19:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1378,'2025-11-04',6,3,3,1,NULL,4.00,'2025-12-02 02:19:51','2025-12-02 02:19:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1379,'2025-11-24',1,3,3,1,NULL,4.00,'2025-12-02 02:43:58','2025-12-02 02:43:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1380,'2025-11-24',1,3,3,2,6,4.00,'2025-12-02 02:43:58','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1381,'2025-11-24',7,3,3,1,NULL,4.00,'2025-12-02 02:43:58','2025-12-02 02:43:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1382,'2025-11-24',7,3,3,2,6,4.00,'2025-12-02 02:43:58','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1383,'2025-11-25',3,3,3,1,NULL,8.00,'2025-12-02 04:17:39','2025-12-02 04:17:39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1384,'2025-11-25',3,3,3,2,6,1.00,'2025-12-02 04:17:39','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1385,'2025-11-25',3,3,3,2,14,1.00,'2025-12-02 04:17:39','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1386,'2025-11-25',6,3,3,1,NULL,8.00,'2025-12-02 04:17:39','2025-12-02 04:17:39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1387,'2025-11-25',6,3,3,2,6,1.00,'2025-12-02 04:17:39','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1388,'2025-11-25',6,3,3,2,14,1.00,'2025-12-02 04:17:39','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1389,'2025-12-03',10,11,3,1,NULL,8.00,'2025-12-03 06:52:28','2025-12-03 06:52:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1390,'2025-12-03',9,11,3,1,NULL,8.00,'2025-12-03 06:52:28','2025-12-03 06:52:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1391,'2025-12-03',4,11,3,1,NULL,8.00,'2025-12-03 06:52:28','2025-12-03 06:52:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1392,'2025-12-03',2,11,3,1,NULL,8.00,'2025-12-03 06:52:28','2025-12-03 06:52:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1393,'2025-12-04',10,11,3,1,NULL,8.00,'2025-12-04 06:45:00','2025-12-04 06:45:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1394,'2025-12-04',9,11,3,1,NULL,8.00,'2025-12-04 06:45:00','2025-12-04 06:45:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1395,'2025-12-04',4,11,3,1,NULL,8.00,'2025-12-04 06:45:00','2025-12-04 06:45:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1396,'2025-12-04',2,11,3,1,NULL,8.00,'2025-12-04 06:45:00','2025-12-04 06:45:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1397,'2025-11-01',6,3,3,1,NULL,4.00,'2025-12-05 00:34:20','2025-12-05 00:34:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1398,'2025-11-01',6,3,3,2,6,4.00,'2025-12-05 00:34:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1399,'2025-11-01',1,3,3,1,NULL,4.00,'2025-12-05 00:34:20','2025-12-05 00:34:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1400,'2025-11-01',1,3,3,2,6,4.00,'2025-12-05 00:34:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1401,'2025-11-03',1,3,3,1,NULL,8.00,'2025-12-05 00:35:16','2025-12-05 00:35:16',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1402,'2025-11-04',6,3,3,1,NULL,2.00,'2025-12-05 01:02:21','2025-12-05 01:02:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1403,'2025-11-04',8,3,3,1,NULL,2.00,'2025-12-05 01:02:21','2025-12-05 01:02:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1404,'2025-11-04',7,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1405,'2025-11-04',7,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1406,'2025-11-04',5,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1407,'2025-11-04',5,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1408,'2025-11-04',4,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1409,'2025-11-04',4,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1410,'2025-11-04',3,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1411,'2025-11-04',3,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1412,'2025-11-04',1,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1413,'2025-11-04',1,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1414,'2025-11-05',8,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1415,'2025-11-05',8,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1416,'2025-11-05',8,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1417,'2025-11-05',7,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1418,'2025-11-05',7,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1419,'2025-11-05',7,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1420,'2025-11-05',6,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1421,'2025-11-05',6,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1422,'2025-11-05',6,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1423,'2025-11-05',4,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1424,'2025-11-05',4,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1425,'2025-11-05',4,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1426,'2025-11-05',3,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1427,'2025-11-05',3,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1428,'2025-11-05',3,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1429,'2025-11-05',1,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1430,'2025-11-05',1,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1431,'2025-11-05',1,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1434,'2025-11-08',9,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1435,'2025-11-08',9,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1436,'2025-11-08',8,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1437,'2025-11-08',8,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1438,'2025-11-08',7,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1439,'2025-11-08',7,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1440,'2025-11-08',6,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1441,'2025-11-08',6,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1442,'2025-11-08',5,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1443,'2025-11-08',5,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1444,'2025-11-08',3,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1445,'2025-11-08',3,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1446,'2025-11-08',1,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1447,'2025-11-08',1,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1448,'2025-11-10',8,3,3,1,NULL,4.00,'2025-12-05 01:06:58','2025-12-05 01:06:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1449,'2025-11-10',8,13,11,1,NULL,4.00,'2025-12-05 01:06:58','2025-12-05 01:06:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1450,'2025-11-10',9,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1451,'2025-11-10',9,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1452,'2025-11-10',7,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1453,'2025-11-10',7,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1454,'2025-11-10',6,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1455,'2025-11-10',6,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1456,'2025-11-10',5,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1457,'2025-11-10',5,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1458,'2025-11-10',3,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1459,'2025-11-10',3,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1460,'2025-11-10',1,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1461,'2025-11-10',1,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1462,'2025-11-12',4,3,3,1,NULL,8.00,'2025-12-05 01:08:07','2025-12-05 01:08:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1463,'2025-11-15',8,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1464,'2025-11-15',8,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1465,'2025-11-15',7,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1466,'2025-11-15',7,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1467,'2025-11-15',6,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1468,'2025-11-15',6,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1469,'2025-11-15',5,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1470,'2025-11-15',5,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1471,'2025-11-15',4,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1472,'2025-11-15',4,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1473,'2025-11-15',3,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1474,'2025-11-15',3,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1475,'2025-11-15',1,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1476,'2025-11-15',1,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1477,'2025-11-17',9,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1478,'2025-11-17',9,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1479,'2025-11-17',8,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1480,'2025-11-17',8,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1481,'2025-11-17',6,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1482,'2025-11-17',6,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1483,'2025-11-17',5,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1484,'2025-11-17',5,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1485,'2025-11-17',3,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1486,'2025-11-17',3,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1487,'2025-11-17',1,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1488,'2025-11-17',1,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1489,'2025-11-18',8,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1490,'2025-11-18',8,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1491,'2025-11-18',9,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1492,'2025-11-18',9,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1493,'2025-11-18',7,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1494,'2025-11-18',7,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1495,'2025-11-18',6,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1496,'2025-11-18',6,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1497,'2025-11-18',5,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1498,'2025-11-18',5,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1499,'2025-11-18',3,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1500,'2025-11-18',3,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1501,'2025-11-18',1,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1502,'2025-11-18',1,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1503,'2025-11-19',2,11,3,1,NULL,4.00,'2025-12-05 01:12:15','2025-12-05 01:12:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1504,'2025-11-19',2,11,3,2,6,4.00,'2025-12-05 01:12:15','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1505,'2025-11-19',10,11,3,1,NULL,4.00,'2025-12-05 01:12:15','2025-12-05 01:12:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1506,'2025-11-19',10,11,3,2,6,4.00,'2025-12-05 01:12:15','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1507,'2025-11-19',9,11,3,1,NULL,4.00,'2025-12-05 01:12:15','2025-12-05 01:12:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1508,'2025-11-19',9,11,3,2,6,4.00,'2025-12-05 01:12:15','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1509,'2025-11-19',8,3,3,1,NULL,5.00,'2025-12-05 01:12:48','2025-12-05 01:12:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1510,'2025-11-19',8,3,3,2,6,3.00,'2025-12-05 01:12:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1511,'2025-11-19',7,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1512,'2025-11-19',7,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1513,'2025-11-19',6,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1514,'2025-11-19',6,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1515,'2025-11-19',5,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1516,'2025-11-19',5,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1517,'2025-11-19',4,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1518,'2025-11-19',4,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1519,'2025-11-19',3,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1520,'2025-11-19',3,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1521,'2025-11-19',1,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1522,'2025-11-19',1,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1523,'2025-11-20',10,11,3,1,NULL,5.00,'2025-12-05 01:13:18','2025-12-05 01:13:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1524,'2025-11-20',10,11,3,2,6,3.00,'2025-12-05 01:13:18','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1525,'2025-11-20',9,11,3,1,NULL,5.00,'2025-12-05 01:13:18','2025-12-05 01:13:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1526,'2025-11-20',9,11,3,2,6,3.00,'2025-12-05 01:13:18','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1527,'2025-11-20',2,11,3,1,NULL,5.00,'2025-12-05 01:13:18','2025-12-05 01:13:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1528,'2025-11-20',2,11,3,2,6,3.00,'2025-12-05 01:13:18','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1529,'2025-11-20',4,11,3,1,NULL,5.00,'2025-12-05 01:13:18','2025-12-05 01:13:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1530,'2025-11-20',4,11,3,2,6,3.00,'2025-12-05 01:13:18','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1531,'2025-11-20',8,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1532,'2025-11-20',8,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1533,'2025-11-20',7,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1534,'2025-11-20',7,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1535,'2025-11-20',6,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1536,'2025-11-20',6,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1537,'2025-11-20',5,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1538,'2025-11-20',5,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1539,'2025-11-20',3,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1540,'2025-11-20',3,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1541,'2025-11-20',1,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1542,'2025-11-20',1,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1543,'2025-11-21',9,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1544,'2025-11-21',9,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1545,'2025-11-21',8,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1546,'2025-11-21',8,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1547,'2025-11-21',6,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1548,'2025-11-21',6,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1549,'2025-11-21',7,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1550,'2025-11-21',7,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1551,'2025-11-21',5,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1552,'2025-11-21',5,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1553,'2025-11-21',3,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1554,'2025-11-21',3,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1555,'2025-11-21',1,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1556,'2025-11-21',1,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1557,'2025-11-22',9,3,3,1,NULL,8.00,'2025-12-05 01:15:21','2025-12-05 01:15:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1558,'2025-11-22',8,3,3,1,NULL,8.00,'2025-12-05 01:15:22','2025-12-05 01:15:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1559,'2025-11-22',6,3,3,1,NULL,8.00,'2025-12-05 01:15:22','2025-12-05 01:15:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1560,'2025-11-22',3,3,3,1,NULL,8.00,'2025-12-05 01:15:22','2025-12-05 01:15:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1561,'2025-11-22',1,3,3,1,NULL,8.00,'2025-12-05 01:15:22','2025-12-05 01:15:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1562,'2025-11-24',9,11,3,1,NULL,4.00,'2025-12-05 01:21:20','2025-12-05 01:21:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1563,'2025-11-24',9,11,3,2,6,4.00,'2025-12-05 01:21:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1564,'2025-11-24',8,11,3,1,NULL,4.00,'2025-12-05 01:21:20','2025-12-05 01:21:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1565,'2025-11-24',8,11,3,2,6,4.00,'2025-12-05 01:21:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1566,'2025-11-24',6,11,3,1,NULL,4.00,'2025-12-05 01:21:20','2025-12-05 01:21:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1567,'2025-11-24',6,11,3,2,6,4.00,'2025-12-05 01:21:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1568,'2025-11-24',5,11,3,1,NULL,4.00,'2025-12-05 01:21:20','2025-12-05 01:21:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1569,'2025-11-24',5,11,3,2,6,4.00,'2025-12-05 01:21:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1570,'2025-11-25',1,13,11,1,NULL,2.00,'2025-12-05 01:21:59','2025-12-05 01:21:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1571,'2025-11-25',1,3,3,1,NULL,6.00,'2025-12-05 01:21:59','2025-12-05 01:21:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1572,'2025-11-25',9,3,3,1,NULL,4.00,'2025-12-05 01:22:49','2025-12-05 01:22:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1573,'2025-11-25',9,3,3,2,14,2.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1574,'2025-11-25',9,3,3,2,6,4.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1575,'2025-11-25',8,3,3,1,NULL,4.00,'2025-12-05 01:22:49','2025-12-05 01:22:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1576,'2025-11-25',8,3,3,2,14,2.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1577,'2025-11-25',8,3,3,2,6,4.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1578,'2025-11-25',5,3,3,1,NULL,4.00,'2025-12-05 01:22:49','2025-12-05 01:22:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1579,'2025-11-25',5,3,3,2,14,2.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1580,'2025-11-25',5,3,3,2,6,4.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1581,'2025-11-26',9,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1582,'2025-11-26',9,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1583,'2025-11-26',8,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1584,'2025-11-26',8,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1585,'2025-11-26',6,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1586,'2025-11-26',6,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1587,'2025-11-26',5,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1588,'2025-11-26',5,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1589,'2025-11-26',3,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1590,'2025-11-26',3,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1591,'2025-11-26',1,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1592,'2025-11-26',1,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1593,'2025-11-27',1,3,3,1,NULL,8.00,'2025-12-05 01:24:00','2025-12-05 01:24:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1594,'2025-11-27',8,3,3,1,NULL,10.00,'2025-12-05 01:24:26','2025-12-05 01:24:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1595,'2025-11-27',6,3,3,1,NULL,10.00,'2025-12-05 01:24:26','2025-12-05 01:24:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1596,'2025-11-27',5,3,3,1,NULL,10.00,'2025-12-05 01:24:26','2025-12-05 01:24:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1597,'2025-11-27',3,3,3,1,NULL,10.00,'2025-12-05 01:24:26','2025-12-05 01:24:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1598,'2025-11-28',4,13,11,1,NULL,8.00,'2025-12-05 01:24:50','2025-12-05 01:24:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1599,'2025-11-28',6,13,11,1,NULL,8.00,'2025-12-05 01:24:50','2025-12-05 01:24:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1600,'2025-11-28',8,3,3,1,NULL,8.00,'2025-12-05 01:25:17','2025-12-05 01:25:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1601,'2025-11-28',5,3,3,1,NULL,8.00,'2025-12-05 01:25:17','2025-12-05 01:25:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1602,'2025-11-28',3,3,3,1,NULL,8.00,'2025-12-05 01:25:17','2025-12-05 01:25:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1603,'2025-11-28',1,3,3,1,NULL,8.00,'2025-12-05 01:25:17','2025-12-05 01:25:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1604,'2025-11-05',5,3,3,1,NULL,8.00,'2025-12-05 01:26:26','2025-12-05 01:26:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1605,'2025-11-13',2,13,1,1,NULL,4.00,'2025-12-05 01:28:08','2025-12-05 01:28:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1606,'2025-11-17',7,13,1,1,NULL,8.00,'2025-12-05 01:28:40','2025-12-05 01:28:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1607,'2025-11-17',4,11,3,1,NULL,6.00,'2025-12-05 01:30:38','2025-12-05 01:30:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1608,'2025-11-17',4,13,11,1,NULL,2.00,'2025-12-05 01:30:38','2025-12-05 01:30:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1609,'2025-11-21',10,13,1,1,NULL,8.00,'2025-12-05 01:31:07','2025-12-05 01:31:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1610,'2025-11-24',10,13,1,1,NULL,8.00,'2025-12-05 01:31:34','2025-12-05 01:31:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1611,'2025-11-24',3,13,1,1,NULL,8.00,'2025-12-05 01:31:40','2025-12-05 01:31:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1612,'2025-11-25',10,13,1,1,NULL,8.00,'2025-12-05 01:31:53','2025-12-05 01:31:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1613,'2025-12-05',10,11,3,1,NULL,8.00,'2025-12-05 06:53:42','2025-12-05 06:53:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1614,'2025-12-05',9,11,3,1,NULL,8.00,'2025-12-05 06:53:42','2025-12-05 06:53:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1615,'2025-12-05',4,11,3,1,NULL,8.00,'2025-12-05 06:53:43','2025-12-05 06:53:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1616,'2025-12-05',2,11,3,1,NULL,8.00,'2025-12-05 06:53:43','2025-12-05 06:53:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1617,'2025-12-06',10,11,3,1,NULL,8.00,'2025-12-06 05:46:14','2025-12-06 05:46:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1618,'2025-12-06',9,11,3,1,NULL,8.00,'2025-12-06 05:46:14','2025-12-06 05:46:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1619,'2025-12-06',4,11,3,1,NULL,8.00,'2025-12-06 05:46:14','2025-12-06 05:46:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1620,'2025-12-06',2,11,3,1,NULL,8.00,'2025-12-06 05:46:14','2025-12-06 05:46:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1621,'2025-12-08',1,11,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1622,'2025-12-08',1,3,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1623,'2025-12-08',5,11,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1624,'2025-12-08',5,3,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1625,'2025-12-08',3,11,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1626,'2025-12-08',3,3,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1627,'2025-12-08',10,11,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1628,'2025-12-08',10,3,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1629,'2025-12-08',9,3,3,1,NULL,8.00,'2025-12-09 07:34:05','2025-12-09 07:34:05',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1630,'2025-12-08',8,3,3,1,NULL,8.00,'2025-12-09 07:34:05','2025-12-09 07:34:05',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1631,'2025-12-08',2,3,3,1,NULL,8.00,'2025-12-09 07:34:05','2025-12-09 07:34:05',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1632,'2025-12-08',4,3,3,1,NULL,8.00,'2025-12-09 07:34:06','2025-12-09 07:34:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1634,'2025-12-08',6,3,3,1,NULL,8.00,'2025-12-09 07:34:38','2025-12-09 07:34:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1635,'2025-12-10',4,3,3,1,NULL,8.00,'2025-12-10 06:56:21','2025-12-10 06:56:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1636,'2025-12-10',2,3,3,1,NULL,8.00,'2025-12-10 06:56:21','2025-12-10 06:56:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1637,'2025-12-10',8,3,3,1,NULL,8.00,'2025-12-10 06:56:21','2025-12-10 06:56:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1638,'2025-12-10',6,3,3,1,NULL,8.00,'2025-12-10 06:56:21','2025-12-10 06:56:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1642,'2026-01-02',10,13,21,1,NULL,8.00,'2026-02-04 22:47:59','2026-02-04 22:47:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1643,'2026-01-02',9,13,20,1,NULL,8.00,'2026-02-04 22:50:13','2026-02-04 22:50:13',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1644,'2026-01-05',11,15,3,1,42,8.00,'2026-02-04 22:52:41','2026-02-05 22:40:21',1,1,NULL,NULL,NULL,NULL,NULL,NULL,4.00), +(1645,'2026-01-06',11,15,3,1,NULL,8.00,'2026-02-04 22:53:13','2026-02-04 22:53:13',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1646,'2026-01-07',11,15,3,1,NULL,8.00,'2026-02-04 22:53:35','2026-02-04 22:53:35',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1647,'2026-01-08',11,15,3,1,NULL,8.00,'2026-02-04 22:54:03','2026-02-04 22:54:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1648,'2026-01-09',11,15,3,1,NULL,8.00,'2026-02-04 22:54:24','2026-02-04 22:54:24',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1649,'2026-01-12',11,15,3,1,NULL,8.00,'2026-02-04 22:55:52','2026-02-04 22:55:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1650,'2026-01-13',11,15,3,1,NULL,8.00,'2026-02-04 22:56:20','2026-02-04 22:56:20',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1651,'2026-01-14',11,15,3,1,NULL,8.00,'2026-02-04 22:56:50','2026-02-04 22:56:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1652,'2026-01-15',11,15,3,1,NULL,8.00,'2026-02-04 22:57:09','2026-02-04 22:57:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1653,'2026-01-16',11,15,3,1,NULL,8.00,'2026-02-04 22:57:29','2026-02-04 22:57:29',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1654,'2026-01-19',11,15,14,1,NULL,8.00,'2026-02-04 22:58:20','2026-02-04 22:58:20',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1655,'2026-01-20',11,15,14,1,NULL,8.00,'2026-02-04 22:58:49','2026-02-04 22:58:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1656,'2026-01-21',11,15,14,1,NULL,8.00,'2026-02-04 23:00:27','2026-02-04 23:00:27',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1657,'2026-01-22',11,15,3,1,NULL,8.00,'2026-02-04 23:00:50','2026-02-04 23:00:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1658,'2026-01-23',11,15,15,1,NULL,8.00,'2026-02-04 23:01:12','2026-02-04 23:01:12',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1659,'2026-01-26',11,15,15,1,NULL,8.00,'2026-02-04 23:01:35','2026-02-04 23:01:35',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1660,'2026-01-27',11,15,15,1,NULL,8.00,'2026-02-04 23:02:09','2026-02-04 23:02:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1661,'2026-01-29',11,15,15,1,NULL,8.00,'2026-02-04 23:02:29','2026-02-04 23:02:29',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1662,'2026-01-28',11,15,15,1,NULL,8.00,'2026-02-04 23:02:58','2026-02-04 23:02:58',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1663,'2026-01-30',11,15,15,1,NULL,8.00,'2026-02-04 23:03:16','2026-02-04 23:03:16',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1664,'2026-01-02',6,13,21,1,NULL,8.00,'2026-02-04 23:03:55','2026-02-04 23:03:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1665,'2026-01-05',6,15,16,1,NULL,8.00,'2026-02-04 23:04:43','2026-02-04 23:04:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1666,'2026-01-06',6,15,16,1,NULL,8.00,'2026-02-04 23:05:15','2026-02-04 23:05:15',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1667,'2026-01-07',6,15,16,1,NULL,8.00,'2026-02-04 23:05:59','2026-02-04 23:05:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1668,'2026-01-08',6,15,16,1,NULL,8.00,'2026-02-04 23:06:37','2026-02-04 23:06:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1669,'2026-01-09',6,15,16,1,NULL,8.00,'2026-02-04 23:06:56','2026-02-04 23:06:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1670,'2026-01-12',6,17,8,1,NULL,8.00,'2026-02-04 23:07:38','2026-02-04 23:07:38',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1671,'2026-01-13',6,17,8,1,NULL,8.00,'2026-02-04 23:08:01','2026-02-04 23:08:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1672,'2026-01-14',6,17,8,1,NULL,8.00,'2026-02-04 23:08:22','2026-02-04 23:08:22',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1673,'2026-01-15',6,17,8,1,NULL,8.00,'2026-02-04 23:08:56','2026-02-04 23:08:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1674,'2026-01-16',6,15,8,1,NULL,2.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1675,'2026-01-16',6,13,24,1,NULL,6.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1676,'2026-01-19',6,17,8,2,43,2.00,'2026-02-04 23:22:54','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,2.00), +(1677,'2026-01-19',6,17,10,1,NULL,6.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1678,'2026-01-20',6,17,10,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1679,'2026-01-21',6,17,8,2,44,8.00,'2026-02-04 23:22:54','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1680,'2026-01-22',6,17,10,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1681,'2026-01-23',6,17,10,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1682,'2026-01-26',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1683,'2026-01-27',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1684,'2026-01-28',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1685,'2026-01-29',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1686,'2026-01-30',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1687,'2026-01-02',3,13,21,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1688,'2026-01-05',3,13,21,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1689,'2026-01-06',3,15,2,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1690,'2026-01-07',3,15,2,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1691,'2026-01-08',3,15,2,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1692,'2026-01-09',3,15,2,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1693,'2026-01-12',3,15,16,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1694,'2026-01-13',3,15,16,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1695,'2026-01-14',3,15,16,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1696,'2026-01-15',3,15,16,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1697,'2026-01-16',3,15,16,1,NULL,6.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1698,'2026-01-16',3,13,23,1,NULL,2.00,'2026-02-04 23:34:05','2026-02-05 02:05:51',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1699,'2026-01-19',3,17,10,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1700,'2026-01-20',3,17,10,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1701,'2026-01-21',3,17,10,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1702,'2026-01-22',3,17,10,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1703,'2026-01-23',3,17,10,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1704,'2026-01-26',3,15,17,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1705,'2026-01-27',3,15,17,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1706,'2026-01-28',3,15,17,2,15,8.00,'2026-02-04 23:36:37','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,4.00), +(1707,'2026-01-29',3,15,17,2,15,8.00,'2026-02-04 23:36:37','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1708,'2026-01-30',3,15,17,2,15,8.00,'2026-02-04 23:36:37','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1709,'2026-01-05',10,15,2,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1710,'2026-01-06',10,15,2,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1711,'2026-01-07',10,15,2,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1712,'2026-01-08',10,15,2,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1713,'2026-01-09',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1714,'2026-01-12',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1715,'2026-01-13',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1716,'2026-01-14',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1717,'2026-01-15',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1718,'2026-01-16',10,17,8,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1719,'2026-01-19',10,17,8,2,43,8.00,'2026-02-04 23:44:26','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1720,'2026-01-20',10,17,10,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1721,'2026-01-21',10,17,10,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1722,'2026-01-22',10,17,10,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1723,'2026-01-22',10,17,10,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1724,'2026-01-23',10,13,21,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1725,'2026-01-26',10,16,25,1,NULL,8.00,'2026-02-04 23:47:27','2026-02-04 23:47:27',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1726,'2026-01-27',10,16,25,1,NULL,8.00,'2026-02-04 23:47:27','2026-02-04 23:47:27',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1727,'2026-01-28',10,16,25,1,NULL,8.00,'2026-02-04 23:50:51','2026-02-04 23:50:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1728,'2026-01-29',10,16,25,1,NULL,8.00,'2026-02-04 23:50:51','2026-02-04 23:50:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1729,'2026-01-30',10,16,25,1,NULL,8.00,'2026-02-04 23:50:51','2026-02-04 23:50:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1730,'2026-01-05',9,13,20,1,NULL,8.00,'2026-02-04 23:54:55','2026-02-04 23:54:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1731,'2026-01-06',9,13,20,1,NULL,8.00,'2026-02-04 23:54:56','2026-02-04 23:54:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1732,'2026-01-07',9,13,20,1,NULL,8.00,'2026-02-04 23:54:57','2026-02-04 23:54:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1733,'2026-01-08',9,13,20,1,NULL,8.00,'2026-02-04 23:54:58','2026-02-04 23:54:58',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1734,'2026-01-09',9,13,20,1,NULL,8.00,'2026-02-04 23:54:59','2026-02-04 23:54:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1735,'2026-01-12',9,13,20,1,NULL,8.00,'2026-02-04 23:55:00','2026-02-04 23:55:00',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1736,'2026-01-13',9,13,20,1,NULL,8.00,'2026-02-04 23:55:01','2026-02-04 23:55:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1737,'2026-01-14',9,13,20,1,NULL,8.00,'2026-02-04 23:55:02','2026-02-04 23:55:02',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1738,'2026-01-15',9,13,20,1,NULL,8.00,'2026-02-04 23:55:03','2026-02-04 23:55:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1739,'2026-01-16',9,13,20,1,NULL,8.00,'2026-02-04 23:55:04','2026-02-04 23:55:04',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1740,'2026-01-19',9,13,20,1,NULL,8.00,'2026-02-04 23:55:05','2026-02-04 23:55:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1741,'2026-01-20',9,15,15,1,NULL,8.00,'2026-02-04 23:56:33','2026-02-04 23:56:33',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1742,'2026-01-21',9,15,15,1,NULL,8.00,'2026-02-04 23:56:34','2026-02-04 23:56:34',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1743,'2026-01-22',9,15,15,1,NULL,8.00,'2026-02-04 23:56:35','2026-02-04 23:56:35',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1744,'2026-01-23',9,15,15,1,NULL,8.00,'2026-02-04 23:56:36','2026-02-04 23:56:36',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1745,'2026-01-26',9,16,25,1,NULL,8.00,'2026-02-04 23:59:49','2026-02-04 23:59:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1746,'2026-01-27',9,16,25,1,NULL,8.00,'2026-02-04 23:59:50','2026-02-04 23:59:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1747,'2026-01-28',9,16,25,1,NULL,8.00,'2026-02-04 23:59:51','2026-02-04 23:59:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1748,'2026-01-29',9,16,25,1,NULL,8.00,'2026-02-04 23:59:52','2026-02-04 23:59:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1749,'2026-01-30',9,16,25,1,NULL,8.00,'2026-02-04 23:59:53','2026-02-04 23:59:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1750,'2026-01-02',1,13,21,1,NULL,8.00,'2026-02-05 00:26:36','2026-02-05 00:26:36',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1751,'2026-01-05',1,15,2,1,NULL,8.00,'2026-02-05 00:26:37','2026-02-05 00:26:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1752,'2026-01-06',1,15,2,1,NULL,8.00,'2026-02-05 00:26:38','2026-02-05 00:26:38',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1753,'2026-01-07',1,15,2,1,NULL,6.00,'2026-02-05 00:26:39','2026-02-05 00:26:39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1754,'2026-01-07',1,13,23,1,NULL,2.00,'2026-02-05 00:26:40','2026-02-05 00:26:40',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1755,'2026-01-08',1,15,2,1,NULL,8.00,'2026-02-05 00:26:41','2026-02-05 00:26:41',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1756,'2026-01-09',1,15,2,1,NULL,8.00,'2026-02-05 00:26:42','2026-02-05 00:26:42',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1757,'2026-01-12',1,15,2,1,NULL,8.00,'2026-02-05 00:26:43','2026-02-05 00:26:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1758,'2026-01-13',1,15,2,1,NULL,8.00,'2026-02-05 00:26:44','2026-02-05 00:26:44',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1759,'2026-01-14',1,15,2,1,NULL,8.00,'2026-02-05 00:26:45','2026-02-05 00:26:45',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1760,'2026-01-15',1,16,25,1,NULL,8.00,'2026-02-05 00:26:46','2026-02-05 00:26:46',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1761,'2026-01-16',1,16,25,1,NULL,8.00,'2026-02-05 00:26:47','2026-02-05 00:26:47',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1762,'2026-01-19',1,13,21,1,NULL,8.00,'2026-02-05 00:26:48','2026-02-05 00:26:48',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1763,'2026-01-20',1,17,10,1,NULL,8.00,'2026-02-05 00:26:49','2026-02-05 00:26:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1764,'2026-01-21',1,17,10,1,NULL,8.00,'2026-02-05 00:26:50','2026-02-05 00:26:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1765,'2026-01-22',1,15,17,1,NULL,8.00,'2026-02-05 00:26:51','2026-02-05 00:26:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1766,'2026-01-23',1,15,17,1,NULL,8.00,'2026-02-05 00:26:52','2026-02-05 00:26:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1767,'2026-01-26',1,16,25,1,NULL,8.00,'2026-02-05 00:26:53','2026-02-05 00:26:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1768,'2026-01-27',1,16,25,1,NULL,8.00,'2026-02-05 00:26:54','2026-02-05 00:26:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1769,'2026-01-28',1,16,25,1,NULL,8.00,'2026-02-05 00:26:55','2026-02-05 00:26:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1770,'2026-01-29',1,16,25,1,NULL,8.00,'2026-02-05 00:26:56','2026-02-05 00:26:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1771,'2026-01-30',1,16,25,1,NULL,8.00,'2026-02-05 00:26:57','2026-02-05 00:26:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1772,'2026-01-02',2,13,21,1,NULL,8.00,'2026-02-05 00:36:41','2026-02-05 00:36:41',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1773,'2026-01-05',2,15,2,1,NULL,8.00,'2026-02-05 00:36:42','2026-02-05 00:36:42',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1774,'2026-01-06',2,15,2,1,NULL,8.00,'2026-02-05 00:36:43','2026-02-05 00:36:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1775,'2026-01-07',2,15,2,1,NULL,8.00,'2026-02-05 00:36:44','2026-02-05 00:36:44',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1776,'2026-01-08',2,14,19,1,NULL,8.00,'2026-02-05 00:36:45','2026-02-05 00:36:45',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1777,'2026-01-09',2,14,19,1,NULL,8.00,'2026-02-05 00:36:46','2026-02-05 00:36:46',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1778,'2026-01-12',2,14,19,1,NULL,8.00,'2026-02-05 00:36:47','2026-02-05 00:36:47',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1779,'2026-01-13',2,14,19,1,NULL,4.00,'2026-02-05 00:36:48','2026-02-05 00:36:48',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1780,'2026-01-13',2,13,22,1,NULL,4.00,'2026-02-05 00:36:49','2026-02-05 00:36:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1781,'2026-01-14',2,15,16,1,NULL,8.00,'2026-02-05 00:36:50','2026-02-05 00:36:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1782,'2026-01-15',2,15,16,1,NULL,8.00,'2026-02-05 00:36:51','2026-02-05 00:36:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1783,'2026-01-16',2,15,16,1,NULL,8.00,'2026-02-05 00:36:52','2026-02-05 00:36:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1784,'2026-01-19',2,15,16,1,NULL,8.00,'2026-02-05 00:36:53','2026-02-05 00:46:20',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1785,'2026-01-20',2,15,14,1,NULL,8.00,'2026-02-05 00:36:54','2026-02-05 00:36:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1786,'2026-01-21',2,15,14,1,NULL,4.00,'2026-02-05 00:36:55','2026-02-05 00:46:43',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1787,'2026-01-22',2,15,14,1,NULL,8.00,'2026-02-05 00:36:56','2026-02-05 00:36:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1788,'2026-01-23',2,15,14,1,NULL,8.00,'2026-02-05 00:36:57','2026-02-05 00:36:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1789,'2026-01-26',2,15,14,1,NULL,8.00,'2026-02-05 00:36:58','2026-02-05 00:36:58',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1790,'2026-01-27',2,15,17,1,NULL,8.00,'2026-02-05 00:36:59','2026-02-05 00:36:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1791,'2026-01-28',2,15,17,1,NULL,8.00,'2026-02-05 00:37:00','2026-02-05 00:37:00',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1792,'2026-01-29',2,15,17,2,15,8.00,'2026-02-05 00:37:01','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1793,'2026-01-30',2,13,21,1,15,8.00,'2026-02-05 00:37:02','2026-02-05 22:40:21',1,1,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1794,'2026-01-21',2,13,22,1,NULL,4.00,'2026-02-05 00:47:10','2026-02-05 00:47:10',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1795,'2026-01-02',4,13,21,1,NULL,8.00,'2026-02-05 00:53:38','2026-02-05 00:53:38',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1796,'2026-01-05',4,15,1,1,NULL,8.00,'2026-02-05 00:53:39','2026-02-05 00:53:39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1797,'2026-01-06',4,15,1,1,NULL,8.00,'2026-02-05 00:53:40','2026-02-05 00:53:40',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1798,'2026-01-07',4,15,1,1,NULL,8.00,'2026-02-05 00:53:41','2026-02-05 00:53:41',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1799,'2026-01-08',4,15,1,1,NULL,8.00,'2026-02-05 00:53:42','2026-02-05 00:53:42',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1800,'2026-01-09',4,15,2,1,NULL,8.00,'2026-02-05 00:53:43','2026-02-05 00:53:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1801,'2026-01-12',4,15,13,1,NULL,8.00,'2026-02-05 00:53:44','2026-02-05 00:53:44',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1802,'2026-01-13',4,15,13,1,NULL,8.00,'2026-02-05 00:53:45','2026-02-05 00:53:45',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1803,'2026-01-14',4,15,13,1,NULL,8.00,'2026-02-05 00:53:46','2026-02-05 00:53:46',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1804,'2026-01-15',4,15,13,1,NULL,8.00,'2026-02-05 00:53:47','2026-02-05 00:53:47',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1805,'2026-01-16',4,13,21,1,NULL,8.00,'2026-02-05 00:53:48','2026-02-05 00:53:48',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1806,'2026-01-19',4,14,19,1,NULL,8.00,'2026-02-05 00:53:49','2026-02-05 00:53:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1807,'2026-01-20',4,14,19,1,NULL,8.00,'2026-02-05 00:53:50','2026-02-05 00:53:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1808,'2026-01-21',4,14,19,1,NULL,8.00,'2026-02-05 00:53:51','2026-02-05 00:53:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1809,'2026-01-22',4,15,16,1,NULL,8.00,'2026-02-05 00:53:52','2026-02-05 00:53:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1810,'2026-01-23',4,15,16,1,NULL,8.00,'2026-02-05 00:53:53','2026-02-05 00:53:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1811,'2026-01-26',4,14,10,1,NULL,8.00,'2026-02-05 00:56:53','2026-02-05 00:56:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1812,'2026-01-27',4,14,10,1,NULL,8.00,'2026-02-05 00:56:54','2026-02-05 00:56:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1813,'2026-01-28',4,14,10,1,NULL,8.00,'2026-02-05 00:56:55','2026-02-05 00:56:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1814,'2026-01-29',4,14,10,1,NULL,8.00,'2026-02-05 00:56:56','2026-02-05 00:56:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1815,'2026-01-30',4,13,21,1,NULL,8.00,'2026-02-05 00:56:57','2026-02-05 00:56:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1816,'2026-01-02',5,13,21,1,NULL,8.00,'2026-02-05 01:05:46','2026-02-05 01:05:46',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1817,'2026-01-23',5,13,21,1,NULL,8.00,'2026-02-05 01:06:01','2026-02-05 01:06:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1818,'2026-01-05',5,15,1,1,NULL,8.00,'2026-02-05 01:07:09','2026-02-05 01:07:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1819,'2026-01-06',5,15,1,1,NULL,8.00,'2026-02-05 01:07:11','2026-02-05 01:07:11',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1820,'2026-01-07',5,15,2,1,NULL,8.00,'2026-02-05 01:07:12','2026-02-05 01:07:12',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1821,'2026-01-08',5,15,2,1,NULL,8.00,'2026-02-05 01:07:13','2026-02-05 01:07:13',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1822,'2026-01-09',5,15,2,1,NULL,8.00,'2026-02-05 01:07:14','2026-02-05 01:07:14',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1823,'2026-01-12',5,17,26,1,NULL,8.00,'2026-02-05 01:07:15','2026-02-05 01:07:15',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1824,'2026-01-13',5,17,26,1,NULL,8.00,'2026-02-05 01:07:16','2026-02-05 01:07:16',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1825,'2026-01-14',5,17,26,1,NULL,8.00,'2026-02-05 01:07:17','2026-02-05 01:07:17',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1826,'2026-01-15',5,17,26,1,NULL,8.00,'2026-02-05 01:07:18','2026-02-05 01:07:18',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1827,'2026-01-16',5,17,26,1,NULL,8.00,'2026-02-05 01:07:19','2026-02-05 01:07:19',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1828,'2026-01-19',5,15,16,1,NULL,8.00,'2026-02-05 01:07:20','2026-02-05 01:07:20',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1829,'2026-01-20',5,15,16,1,NULL,8.00,'2026-02-05 01:07:21','2026-02-05 01:07:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1830,'2026-01-21',5,15,16,1,NULL,8.00,'2026-02-05 01:07:22','2026-02-05 01:07:22',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1831,'2026-01-22',5,15,16,1,NULL,8.00,'2026-02-05 01:07:23','2026-02-05 01:07:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1832,'2026-01-26',5,16,25,1,NULL,8.00,'2026-02-05 01:07:24','2026-02-05 01:07:24',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1833,'2026-01-27',5,16,25,1,NULL,8.00,'2026-02-05 01:07:25','2026-02-05 01:07:25',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1834,'2026-01-28',5,16,25,1,NULL,8.00,'2026-02-05 01:07:26','2026-02-05 01:07:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1835,'2026-01-29',5,16,25,1,NULL,8.00,'2026-02-05 01:07:27','2026-02-05 01:07:27',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1836,'2026-01-30',5,16,25,1,NULL,8.00,'2026-02-05 01:07:28','2026-02-05 01:07:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1837,'2026-01-02',8,13,21,1,NULL,8.00,'2026-02-05 01:14:48','2026-02-05 01:14:48',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1838,'2026-01-05',8,15,3,1,NULL,8.00,'2026-02-05 01:14:49','2026-02-05 01:14:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1839,'2026-01-06',8,15,3,1,NULL,8.00,'2026-02-05 01:14:50','2026-02-05 01:14:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1840,'2026-01-07',8,15,3,1,NULL,8.00,'2026-02-05 01:14:51','2026-02-05 01:14:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1841,'2026-01-08',8,15,3,1,NULL,8.00,'2026-02-05 01:14:52','2026-02-05 01:14:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1842,'2026-01-09',8,15,3,1,NULL,8.00,'2026-02-05 01:14:53','2026-02-05 01:14:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1843,'2026-01-12',8,15,4,1,NULL,8.00,'2026-02-05 01:14:54','2026-02-05 01:14:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1844,'2026-01-13',8,15,4,1,NULL,8.00,'2026-02-05 01:14:55','2026-02-05 01:14:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1845,'2026-01-14',8,15,4,1,NULL,8.00,'2026-02-05 01:14:56','2026-02-05 01:14:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1846,'2026-01-15',8,15,4,1,NULL,8.00,'2026-02-05 01:14:57','2026-02-05 01:14:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1847,'2026-01-16',8,15,4,1,NULL,8.00,'2026-02-05 01:14:58','2026-02-05 01:14:58',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1848,'2026-01-19',8,15,4,1,NULL,8.00,'2026-02-05 01:14:59','2026-02-05 01:14:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1849,'2026-01-20',8,15,4,1,NULL,8.00,'2026-02-05 01:15:00','2026-02-05 01:15:00',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1850,'2026-01-21',8,14,10,1,NULL,8.00,'2026-02-05 01:15:01','2026-02-05 01:15:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1851,'2026-01-22',8,14,10,1,NULL,8.00,'2026-02-05 01:15:02','2026-02-05 01:15:02',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1852,'2026-01-23',8,14,10,1,NULL,8.00,'2026-02-05 01:15:03','2026-02-05 01:15:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1853,'2026-01-26',8,15,14,1,NULL,8.00,'2026-02-05 01:15:04','2026-02-05 01:15:04',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1854,'2026-01-27',8,15,14,1,NULL,8.00,'2026-02-05 01:15:05','2026-02-05 01:15:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1855,'2026-01-28',8,15,14,1,NULL,8.00,'2026-02-05 01:15:06','2026-02-05 01:15:06',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1856,'2026-01-29',8,15,14,1,NULL,8.00,'2026-02-05 01:15:07','2026-02-05 01:15:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1857,'2026-01-30',8,15,14,1,NULL,8.00,'2026-02-05 01:15:09','2026-02-05 01:15:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +/*!40000 ALTER TABLE `daily_work_reports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `daily_worker_summary` +-- + +DROP TABLE IF EXISTS `daily_worker_summary`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_worker_summary` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `report_date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `total_hours` decimal(4,2) NOT NULL DEFAULT 8.00 COMMENT '총 근무시간', + `work_status` enum('normal','annual_leave','half_leave','overtime') DEFAULT 'normal' COMMENT '근무 상태', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `unique_worker_date` (`worker_id`,`report_date`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_worker_summary` +-- + +LOCK TABLES `daily_worker_summary` WRITE; +/*!40000 ALTER TABLE `daily_worker_summary` DISABLE KEYS */; +/*!40000 ALTER TABLE `daily_worker_summary` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `departments` +-- + +DROP TABLE IF EXISTS `departments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `departments` ( + `department_id` int(11) NOT NULL AUTO_INCREMENT, + `department_name` varchar(100) NOT NULL, + `parent_id` int(11) DEFAULT NULL, + `description` text DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `display_order` int(11) DEFAULT 0, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`department_id`), + KEY `parent_id` (`parent_id`), + CONSTRAINT `departments_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `departments` (`department_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `departments` +-- + +LOCK TABLES `departments` WRITE; +/*!40000 ALTER TABLE `departments` DISABLE KEYS */; +INSERT INTO `departments` VALUES +(1,'생산팀',NULL,'현장 생산 작업 담당',1,1,'2026-02-03 05:03:37','2026-02-03 05:03:37'); +/*!40000 ALTER TABLE `departments` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `equipment_external_logs` +-- + +DROP TABLE IF EXISTS `equipment_external_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `equipment_external_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `equipment_id` int(10) unsigned NOT NULL COMMENT '설비 ID', + `log_type` enum('export','return') NOT NULL COMMENT '반출/반입', + `export_date` date DEFAULT NULL COMMENT '반출일', + `expected_return_date` date DEFAULT NULL COMMENT '반입 예정일', + `actual_return_date` date DEFAULT NULL COMMENT '실제 반입일', + `destination` varchar(200) DEFAULT NULL COMMENT '반출처 (수리업체명 등)', + `reason` text DEFAULT NULL COMMENT '반출 사유', + `notes` text DEFAULT NULL COMMENT '비고', + `exported_by` int(11) DEFAULT NULL COMMENT '반출 담당자', + `returned_by` int(11) DEFAULT NULL COMMENT '반입 담당자', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`log_id`), + KEY `fk_eel_exported_by` (`exported_by`), + KEY `fk_eel_returned_by` (`returned_by`), + KEY `idx_eel_equipment_id` (`equipment_id`), + KEY `idx_eel_log_type` (`log_type`), + KEY `idx_eel_export_date` (`export_date`), + CONSTRAINT `fk_eel_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipments` (`equipment_id`) ON DELETE CASCADE, + CONSTRAINT `fk_eel_exported_by` FOREIGN KEY (`exported_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, + CONSTRAINT `fk_eel_returned_by` FOREIGN KEY (`returned_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `equipment_external_logs` +-- + +LOCK TABLES `equipment_external_logs` WRITE; +/*!40000 ALTER TABLE `equipment_external_logs` DISABLE KEYS */; +/*!40000 ALTER TABLE `equipment_external_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `equipment_move_logs` +-- + +DROP TABLE IF EXISTS `equipment_move_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `equipment_move_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `equipment_id` int(10) unsigned NOT NULL COMMENT '설비 ID', + `move_type` enum('temporary','return') NOT NULL COMMENT '임시이동/복귀', + `from_workplace_id` int(10) unsigned DEFAULT NULL COMMENT '이전 작업장', + `to_workplace_id` int(10) unsigned DEFAULT NULL COMMENT '이동 작업장', + `from_x_percent` decimal(5,2) DEFAULT NULL COMMENT '이전 X좌표', + `from_y_percent` decimal(5,2) DEFAULT NULL COMMENT '이전 Y좌표', + `to_x_percent` decimal(5,2) DEFAULT NULL COMMENT '이동 X좌표', + `to_y_percent` decimal(5,2) DEFAULT NULL COMMENT '이동 Y좌표', + `reason` text DEFAULT NULL COMMENT '이동 사유', + `moved_by` int(11) DEFAULT NULL COMMENT '이동 처리자', + `moved_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`log_id`), + KEY `fk_eml_from_workplace` (`from_workplace_id`), + KEY `fk_eml_to_workplace` (`to_workplace_id`), + KEY `fk_eml_moved_by` (`moved_by`), + KEY `idx_eml_equipment_id` (`equipment_id`), + KEY `idx_eml_move_type` (`move_type`), + CONSTRAINT `fk_eml_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipments` (`equipment_id`) ON DELETE CASCADE, + CONSTRAINT `fk_eml_from_workplace` FOREIGN KEY (`from_workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL, + CONSTRAINT `fk_eml_moved_by` FOREIGN KEY (`moved_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, + CONSTRAINT `fk_eml_to_workplace` FOREIGN KEY (`to_workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `equipment_move_logs` +-- + +LOCK TABLES `equipment_move_logs` WRITE; +/*!40000 ALTER TABLE `equipment_move_logs` DISABLE KEYS */; +INSERT INTO `equipment_move_logs` VALUES +(1,68,'temporary',2,10,7.82,8.53,NULL,NULL,NULL,1,'2026-02-04 04:34:45'), +(2,68,'temporary',2,10,7.82,8.53,NULL,NULL,NULL,1,'2026-02-04 04:44:36'); +/*!40000 ALTER TABLE `equipment_move_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `equipment_photos` +-- + +DROP TABLE IF EXISTS `equipment_photos`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `equipment_photos` ( + `photo_id` int(11) NOT NULL AUTO_INCREMENT, + `equipment_id` int(10) unsigned NOT NULL, + `photo_path` varchar(255) NOT NULL COMMENT '이미지 경로', + `description` varchar(200) DEFAULT NULL COMMENT '사진 설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `uploaded_by` int(11) DEFAULT NULL COMMENT '업로드한 사용자 ID', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`photo_id`), + KEY `fk_eq_photos_user` (`uploaded_by`), + KEY `idx_eq_photos_equipment_id` (`equipment_id`), + CONSTRAINT `fk_eq_photos_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipments` (`equipment_id`) ON DELETE CASCADE, + CONSTRAINT `fk_eq_photos_user` FOREIGN KEY (`uploaded_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `equipment_photos` +-- + +LOCK TABLES `equipment_photos` WRITE; +/*!40000 ALTER TABLE `equipment_photos` DISABLE KEYS */; +/*!40000 ALTER TABLE `equipment_photos` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `equipments` +-- + +DROP TABLE IF EXISTS `equipments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `equipments` ( + `equipment_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '설비 ID', + `equipment_code` varchar(50) NOT NULL COMMENT '설비 코드 (예: CNC-01, LATHE-A)', + `equipment_name` varchar(100) NOT NULL COMMENT '설비명', + `equipment_type` varchar(50) DEFAULT NULL COMMENT '설비 유형 (예: CNC, 선반, 밀링 등)', + `model_name` varchar(100) DEFAULT NULL COMMENT '모델명', + `manufacturer` varchar(100) DEFAULT NULL COMMENT '제조사', + `supplier` varchar(100) DEFAULT NULL COMMENT '구입처', + `purchase_price` decimal(15,0) DEFAULT NULL COMMENT '구입가격', + `installation_date` date DEFAULT NULL COMMENT '설치일', + `serial_number` varchar(100) DEFAULT NULL COMMENT '시리얼 번호', + `specifications` text DEFAULT NULL COMMENT '사양 정보 (JSON 형태로 저장 가능)', + `status` enum('active','maintenance','repair_needed','inactive','external','repair_external') DEFAULT 'active' COMMENT '설비 상태', + `notes` text DEFAULT NULL COMMENT '비고', + `workplace_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 작업장 ID', + `map_x_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 X 위치 (%)', + `map_y_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 Y 위치 (%)', + `map_width_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 영역 너비 (%)', + `map_height_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 영역 높이 (%)', + `current_workplace_id` int(10) unsigned DEFAULT NULL COMMENT '현재 임시 위치 - 작업장 ID', + `current_map_x_percent` decimal(5,2) DEFAULT NULL COMMENT '현재 위치 X%', + `current_map_y_percent` decimal(5,2) DEFAULT NULL COMMENT '현재 위치 Y%', + `current_map_width_percent` decimal(5,2) DEFAULT NULL COMMENT '현재 위치 너비%', + `current_map_height_percent` decimal(5,2) DEFAULT NULL COMMENT '현재 위치 높이%', + `is_temporarily_moved` tinyint(1) DEFAULT 0 COMMENT '임시 이동 상태', + `moved_at` datetime DEFAULT NULL COMMENT '이동 일시', + `moved_by` int(11) DEFAULT NULL COMMENT '이동 처리자', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '생성일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정일시', + PRIMARY KEY (`equipment_id`), + UNIQUE KEY `equipments_equipment_code_unique` (`equipment_code`), + KEY `equipments_workplace_id_index` (`workplace_id`), + KEY `equipments_equipment_type_index` (`equipment_type`), + KEY `equipments_status_index` (`status`), + KEY `fk_eq_current_workplace` (`current_workplace_id`), + CONSTRAINT `equipments_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL, + CONSTRAINT `fk_eq_current_workplace` FOREIGN KEY (`current_workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `equipments` +-- + +LOCK TABLES `equipments` WRITE; +/*!40000 ALTER TABLE `equipments` DISABLE KEYS */; +INSERT INTO `equipments` VALUES +(1,'TKP-001','AIR COMPRESSOR',NULL,'AR10E','경원','지티씨',NULL,'2016-06-01','K603023Y','7.5KW(10HP)','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(2,'TKP-002','TURN TABLE',NULL,'YCT-200T','유체기계','형진종합공구',3600000,'2016-05-30',NULL,'220V','active',NULL,2,9.93,79.22,3.41,7.29,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:57:25'), +(3,'TKP-003','BAND SAW(中)',NULL,'CY300W','유림싸이겐','형진종합공구',4800000,'2016-05-30','20150943','1500W*380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(4,'TKP-004','BAND SAW(小)',NULL,'XB-180WA','렉스','형진종합공구',2700000,'2016-05-30',NULL,'180(VICE)','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(5,'TKP-005','BAND SAW(小)',NULL,'XB-180WA','렉스',NULL,NULL,'2019-05-30',NULL,'180(VICE)','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(6,'TKP-006','TIG용접기',NULL,'DAESUNG-500DT','대성용접기','형진종합공구',2200000,'2016-05-30','TEAG0168-001','500A','active',NULL,2,0.35,42.33,3.90,3.88,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-04 00:23:29'), +(7,'TKP-007','TIG용접기',NULL,'DAESUNG-500DT','대성용접기','형진종합공구',2200000,'2016-05-30','TEAG0168-002','500A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(8,'TKP-008','TIG용접기',NULL,'DAESUNG-500DT','대성용접기','형진종합공구',2200000,'2016-05-30','TEAG0168-003','500A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(9,'TKP-009','CO2용접기',NULL,'COD-500A','대성용접기','형진종합공구',2000000,'2016-05-30','10880','500A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(10,'TKP-010','O2용접기',NULL,'GSORK','재현오토닉스','형진종합공구',620000,'2016-05-30',NULL,'220V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(11,'TKP-011','PIPE BEVELLING MACHINE',NULL,'S-200LT_MT(테이블포함)','DCS ENG','DCS ENG',12000000,'2017-03-29','KR-17030007','2\" ~ 8\"','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(12,'TKP-012','CO2용접기',NULL,'500MX','현대용접기','현대용접기',1800000,'2017-08-02',NULL,'220/380V,500A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(13,'TKP-013','프라즈마',NULL,'Perfect-150AP','퍼펙트대대','현대용접기',1900000,'2017-08-02',NULL,'220/380/440V,140A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(14,'TKP-014','터닝로라',NULL,'JK-5-TR','정일기공','정일기공',5700000,'2017-09-08',NULL,'5TON/380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(15,'TKP-015','터닝로라',NULL,'JK-5-TR','정일기공','정일기공',5700000,'2017-09-08',NULL,'5TON/380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(16,'TKP-016','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1600000,'2017-10-18','TJAD017B-005','500A/350A','active',NULL,2,0.02,46.36,4.87,4.34,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-04 00:22:53'), +(17,'TKP-017','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1600000,'2017-10-18','TJAD017B-006','500A/350A','active',NULL,2,0.35,20.93,4.06,4.03,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-04 00:23:46'), +(18,'TKP-018','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1600000,'2017-10-18','TJAD017B-007','500A/350A','repair_needed',NULL,2,0.35,17.05,4.06,3.57,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-04 05:35:54'), +(19,'TKP-019','전해연마기',NULL,'ONB-8000VP','메탈브라이트(오토기전)','오토기전',1450000,'2018-03-13','8022701','220V/MAX1200W','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(20,'TKP-020','지게차',NULL,'50DA-9F','현대지게차','현대지게차',45000000,'2018-05-10','HHKHFV36JJ0000061','5000KGS','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(21,'TKP-021','조방',NULL,NULL,'테크니컬코리아','천우기계공업/삼덕금속',14200000,'2018-05-11',NULL,'3658*12190','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(22,'TKP-022','BAND SAW(大)',NULL,'WBS-RC500AN','원공사','원공사',36000000,'2018-05-31','BC50A18-005F001','3,300kgs / 7.88kw','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(23,'TKP-023','AIR COMPRESSOR',NULL,'AR20E','경원기계','경원기계',NULL,'2018-06-05','AR020FE358','0.95Mpa','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(24,'TKP-024','TURN TABLE',NULL,'YCT-200TA','유체기계','청운종합공구',3245000,'2018-06-12',NULL,'220V','active',NULL,2,9.76,69.92,4.06,7.60,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:57:40'), +(25,'TKP-025','TIG용접기',NULL,'Perfect-500WT','퍼펙트대대','현대용접기',2400000,'2018-06-12','ADKAC017B-006','500A/AC DC','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(26,'TKP-026','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1900000,'2018-06-12','TAAI018B-002','500A/DC','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(27,'TKP-027','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1900000,'2018-06-12','TAAA018B-009','500A/DC','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(28,'TKP-028','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1900000,'2018-06-12','TAAA018B-001','500A/DC','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(29,'TKP-029','ELECTRIC CHAIN HOIST',NULL,'DSM-2S','대산','청운종합공구',2300000,'2018-07-06','K1806077','3Ph-60Hz-380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(30,'TKP-030','ELECTRIC CHAIN HOIST',NULL,'DSM-2S','대산','청운종합공구',2300000,'2018-07-10','K1807028','3Ph-60Hz-380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(31,'TKP-031','ELECTRIC CHAIN HOIST',NULL,'DSM-2S','대산','청운종합공구',2300000,'2018-07-10','K1807029','3Ph-60Hz-380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(32,'TKP-032','만능탭 드릴링머신',NULL,'SF-TDM32','㈜애스앤에프','㈜애스앤애프',2927000,'2018-11-09',NULL,'1.5KW','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(33,'TKP-033','지게차',NULL,'30D-9B','현대지게차','현대지게차',29400000,'2019-03-06','HHKHHN51KK0000864','2850KGS','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(34,'TKP-034','갠츄리크레인',NULL,'CRANE - DHG','반도호이스트','유진산업기계',249000000,'2019-05-09',NULL,'50/10Ton x SP20M x T/L50M x H15M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(35,'TKP-035','OVER HEAD CRANE',NULL,'CRANE - DHO','반도호이스트','유진산업기계',58000000,'2019-05-09',NULL,'20Ton x SP24.0M x T/L67M x H11M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(36,'TKP-036','OVER HEAD CRANE',NULL,'CRANE - DHO','반도호이스트','유진산업기계',58000000,'2019-05-09',NULL,'20Ton x SP24.0M x T/L67M x H11M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(37,'TKP-037','OVER HEAD CRANE',NULL,'CRANE - DHO','반도호이스트','유진산업기계',29000000,'2019-05-09',NULL,'5Ton x SP24.0M x T/L67M x H11M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(38,'TKP-038','OVER HEAD CRANE',NULL,'CRANE - DHO','반도호이스트','유진산업기계',29000000,'2019-05-09',NULL,'5Ton x SP24.0M x T/L67M x H11M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(39,'TKP-039','고소작업대',NULL,NULL,'㈜쓰리제이테크',NULL,NULL,'2019-01-01',NULL,'250 Kg','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(40,'TKP-040','고소작업대',NULL,NULL,'㈜쓰리제이테크',NULL,NULL,'2019-01-01',NULL,'250 Kg','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(41,'TKP-041','AIR CONDITIONER',NULL,'코끼리 냉장고','㈜에스엔에프',NULL,NULL,'2019-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(42,'TKP-042','AIR CONDITIONER',NULL,NULL,'㈜에스엔에프',NULL,NULL,'2019-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(43,'TKP-043','AIR CONDITIONER',NULL,NULL,'㈜에스엔에프',NULL,NULL,'2019-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(44,'TKP-044','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(45,'TKP-045','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(46,'TKP-046','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(47,'TKP-047','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(48,'TKP-048','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(49,'TKP-049','자동용접기',NULL,NULL,'Swage-Lok','Swage-Lok',50000000,'2019-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(50,'TKP-050','Magnetic Drill',NULL,NULL,'NITTO','청운종합공구',NULL,'2020-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(51,'TKP-051','Magnetic Drill',NULL,NULL,'Key-Yang','청운종합공구',NULL,'2020-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(52,'TKP-052','Tube Bending M/C',NULL,NULL,'REMS',NULL,NULL,'2020-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(53,'TKP-053','Unit Test Panel',NULL,NULL,NULL,NULL,NULL,'2021-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(54,'TKP-054','고소작업대',NULL,NULL,'㈜쓰리제이테크',NULL,NULL,'2021-01-01',NULL,'500 Kg','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(55,'TKP-055','용접봉 건조기',NULL,'주문제작','진원하이텍','진원하이텍',2300000,'2022-05-04',NULL,'박스형','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(56,'TKP-056','C&T 가공기',NULL,'MS-CTK469','Swage-Lok','Swage-Lok',7347600,'2022-07-20',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(57,'TKP-057','테이블형 튜브 벤딩기',NULL,'MS-BTT-K','Swage-Lok','Swage-Lok',20000000,'2022-06-03',NULL,'1/2\", 1/4\"','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(58,'TKP-058','자동용접기 헤드',NULL,'SWS-10H-D-15','Swage-Lok','Swage-Lok',20000000,'2022-06-03',NULL,'1/2\"','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(59,'TKP-059','천장주행크레인',NULL,'HC-75D-13105','에이치앤씨','에이치앤씨',22800000,'2023-06-09',NULL,'7.5ton','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(60,'TKP-060','AED',NULL,'CU-SP1 Plus','제이메디','제이메디',1600000,'2023-11-09',NULL,'저출력심장충격기','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(61,'TKP-061','베벨머신',NULL,'S-150','DCSENG','DCSENG',16000000,'2023-12-12',NULL,'O.D 20mm ~ 170mm','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(62,'TKP-062','피막제거기',NULL,'CM4_OD_GC','DCSENG','DCSENG',2000000,'2023-12-12',NULL,'최대 폭 48mm, 최대 깊이 15mm, 6\"이상','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(63,'TKP-063','피막제거기',NULL,'S-CM4_OD','DCSENG','DCSENG',1200000,'2023-12-12',NULL,'최대 폭 48mm, 최대 깊이 15mm, 1\" 이상','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(64,'TKP-064','텅스텐 가공기',NULL,'S-TGR','DCSENG','DCSENG',800000,'2023-12-12',NULL,'0.89kg, 0.25~3.2','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(65,'TKP-065','전동대차',NULL,'LPM15','두산산업차량','두산산업차량',2800000,'2023-12-20',NULL,'2.0 ton','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(66,'TKP-066','TURN TABLE',NULL,'YCT-200T','유체기계','청운종합공구',3000000,NULL,NULL,'220V','active',NULL,2,9.76,60.78,6.17,3.10,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-04 00:17:49','2026-02-04 00:19:51'), +(67,'TKP-067','TURN TABLE',NULL,'YCT-200T','유체기계','청운종합공구',3000000,NULL,NULL,'220V','active',NULL,2,9.60,55.66,6.33,2.95,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-04 00:18:26','2026-02-04 00:19:57'), +(68,'TKP-068','TURN TABLE',NULL,'YCT-200TA','유체기계','청운종합공구',3000000,NULL,NULL,'220V','active',NULL,2,7.82,8.53,5.68,3.10,10,NULL,NULL,NULL,NULL,1,'2026-02-04 04:44:36',1,'2026-02-04 00:18:59','2026-02-04 04:44:36'); +/*!40000 ALTER TABLE `equipments` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `issue_report_categories` +-- + +DROP TABLE IF EXISTS `issue_report_categories`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `issue_report_categories` ( + `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '카테고리 ID', + `category_type` enum('nonconformity','safety') NOT NULL COMMENT '카테고리 유형 (부적합/안전)', + `category_name` varchar(100) NOT NULL COMMENT '카테고리명', + `description` text DEFAULT NULL COMMENT '카테고리 설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`category_id`), + KEY `idx_irc_category_type` (`category_type`), + KEY `idx_irc_is_active` (`is_active`) +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `issue_report_categories` +-- + +LOCK TABLES `issue_report_categories` WRITE; +/*!40000 ALTER TABLE `issue_report_categories` DISABLE KEYS */; +INSERT INTO `issue_report_categories` VALUES +(1,'nonconformity','자재누락',NULL,1,1,'2026-02-02 00:23:42'), +(2,'nonconformity','설계미스',NULL,2,1,'2026-02-02 00:23:42'), +(3,'nonconformity','입고불량',NULL,3,1,'2026-02-02 00:23:42'), +(4,'nonconformity','검사미스',NULL,4,1,'2026-02-02 00:23:42'), +(5,'nonconformity','기타 부적합',NULL,99,1,'2026-02-02 00:23:42'), +(6,'safety','보호구 미착용',NULL,1,1,'2026-02-02 00:23:42'), +(7,'safety','위험구역 출입',NULL,2,1,'2026-02-02 00:23:42'), +(8,'safety','안전시설 파손',NULL,3,1,'2026-02-02 00:23:42'), +(9,'safety','안전수칙 위반',NULL,4,1,'2026-02-02 00:23:42'), +(10,'safety','기타 안전',NULL,99,1,'2026-02-02 00:23:42'), +(11,'nonconformity','설비 수리','설비 고장 및 수리 요청',10,1,'2026-02-04 03:22:27'), +(12,'nonconformity','NDE 불합격',NULL,0,1,'2026-02-04 23:15:15'), +(13,'nonconformity','작업 부적합',NULL,0,1,'2026-02-04 23:15:37'); +/*!40000 ALTER TABLE `issue_report_categories` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `issue_report_items` +-- + +DROP TABLE IF EXISTS `issue_report_items`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `issue_report_items` ( + `item_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '항목 ID', + `category_id` int(10) unsigned NOT NULL COMMENT '소속 카테고리 ID', + `item_name` varchar(200) NOT NULL COMMENT '신고 항목명', + `description` text DEFAULT NULL COMMENT '항목 설명', + `severity` enum('low','medium','high','critical') DEFAULT 'medium' COMMENT '심각도', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`item_id`), + KEY `idx_iri_category_id` (`category_id`), + KEY `idx_iri_is_active` (`is_active`), + CONSTRAINT `issue_report_items_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `issue_report_categories` (`category_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `issue_report_items` +-- + +LOCK TABLES `issue_report_items` WRITE; +/*!40000 ALTER TABLE `issue_report_items` DISABLE KEYS */; +INSERT INTO `issue_report_items` VALUES +(1,1,'배관 자재 미입고',NULL,'high',1,1,'2026-02-02 00:23:42'), +(2,1,'피팅류 부족',NULL,'medium',2,1,'2026-02-02 00:23:42'), +(3,1,'밸브류 미입고',NULL,'high',3,1,'2026-02-02 00:23:42'), +(4,1,'가스켓/볼트류 부족',NULL,'low',4,1,'2026-02-02 00:23:42'), +(5,1,'서포트 자재 부족',NULL,'medium',5,1,'2026-02-02 00:23:42'), +(6,2,'도면 치수 오류',NULL,'high',1,1,'2026-02-02 00:23:42'), +(7,2,'스펙 불일치',NULL,'high',2,1,'2026-02-02 00:23:42'), +(8,2,'누락된 상세도',NULL,'medium',3,1,'2026-02-02 00:23:42'), +(9,2,'간섭 발생',NULL,'critical',4,1,'2026-02-02 00:23:42'), +(10,3,'외관 불량',NULL,'medium',1,1,'2026-02-02 00:23:42'), +(11,3,'치수 불량',NULL,'high',2,1,'2026-02-02 00:23:42'), +(12,3,'수량 부족',NULL,'medium',3,1,'2026-02-02 00:23:42'), +(13,3,'재질 불일치',NULL,'critical',4,1,'2026-02-02 00:23:42'), +(14,4,'치수 검사 누락',NULL,'high',1,1,'2026-02-02 00:23:42'), +(15,4,'외관 검사 누락',NULL,'medium',2,1,'2026-02-02 00:23:42'), +(16,4,'용접 검사 누락',NULL,'critical',3,1,'2026-02-02 00:23:42'), +(17,4,'도장 검사 누락',NULL,'medium',4,1,'2026-02-02 00:23:42'), +(18,6,'안전모 미착용',NULL,'high',1,1,'2026-02-02 00:23:42'), +(19,6,'안전화 미착용',NULL,'high',2,1,'2026-02-02 00:23:42'), +(20,6,'보안경 미착용',NULL,'medium',3,1,'2026-02-02 00:23:42'), +(21,6,'안전대 미착용',NULL,'critical',4,1,'2026-02-02 00:23:42'), +(22,6,'귀마개 미착용',NULL,'low',5,1,'2026-02-02 00:23:42'), +(23,6,'안전장갑 미착용',NULL,'medium',6,1,'2026-02-02 00:23:42'), +(24,7,'통제구역 무단 출입',NULL,'critical',1,1,'2026-02-02 00:23:42'), +(25,7,'고소 작업 구역 무단 출입',NULL,'critical',2,1,'2026-02-02 00:23:42'), +(26,7,'밀폐공간 무단 진입',NULL,'critical',3,1,'2026-02-02 00:23:42'), +(27,7,'장비 가동 구역 무단 접근',NULL,'high',4,1,'2026-02-02 00:23:42'), +(28,8,'안전난간 파손',NULL,'high',1,1,'2026-02-02 00:23:42'), +(29,8,'경고 표지판 훼손',NULL,'medium',2,1,'2026-02-02 00:23:42'), +(30,8,'안전망 파손',NULL,'high',3,1,'2026-02-02 00:23:42'), +(31,8,'비상조명 고장',NULL,'medium',4,1,'2026-02-02 00:23:42'), +(32,8,'소화설비 파손',NULL,'critical',5,1,'2026-02-02 00:23:42'), +(33,9,'지정 통로 미사용',NULL,'medium',1,1,'2026-02-02 00:23:42'), +(34,9,'고소 작업 안전 미준수',NULL,'critical',2,1,'2026-02-02 00:23:42'), +(35,9,'화기 작업 절차 미준수',NULL,'critical',3,1,'2026-02-02 00:23:42'), +(36,9,'정리정돈 미흡',NULL,'low',4,1,'2026-02-02 00:23:42'), +(37,9,'장비 조작 절차 미준수',NULL,'high',5,1,'2026-02-02 00:23:42'), +(38,11,'기계 고장','기계 작동 불가 또는 이상','high',1,1,'2026-02-04 03:22:27'), +(39,11,'부품 교체 필요','소모품 또는 부품 교체 필요','medium',2,1,'2026-02-04 03:22:27'), +(40,11,'정기 점검 필요','예방 정비 또는 정기 점검','low',3,1,'2026-02-04 03:22:27'), +(41,11,'외부 수리 필요','전문 업체 수리가 필요한 경우','high',4,1,'2026-02-04 03:22:27'), +(42,5,'작업대기',NULL,'medium',0,1,'2026-02-04 22:52:31'), +(43,13,'NDE 불합격',NULL,'medium',0,1,'2026-02-04 23:15:46'), +(44,4,'결과 전달 부적합',NULL,'medium',0,1,'2026-02-04 23:19:05'); +/*!40000 ALTER TABLE `issue_report_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `item_types` +-- + +DROP TABLE IF EXISTS `item_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `item_types` ( + `type_code` varchar(20) NOT NULL, + `type_name` varchar(50) NOT NULL COMMENT '유형명', + `icon` varchar(10) DEFAULT NULL COMMENT '아이콘 이모지', + `color` varchar(20) DEFAULT NULL COMMENT '표시 색상', + `display_order` int(11) DEFAULT 0, + `is_active` tinyint(1) DEFAULT 1, + PRIMARY KEY (`type_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `item_types` +-- + +LOCK TABLES `item_types` WRITE; +/*!40000 ALTER TABLE `item_types` DISABLE KEYS */; +INSERT INTO `item_types` VALUES +('container','용기','📦','#3b82f6',1,1), +('material','자재','🧱','#f59e0b',3,1), +('other','기타','📍','#6b7280',5,1), +('plate','플레이트','🔲','#10b981',2,1), +('tool','공구/장비','🔧','#8b5cf6',4,1); +/*!40000 ALTER TABLE `item_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `knex_migrations` +-- + +DROP TABLE IF EXISTS `knex_migrations`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `knex_migrations` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `batch` int(11) DEFAULT NULL, + `migration_time` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `knex_migrations` +-- + +LOCK TABLES `knex_migrations` WRITE; +/*!40000 ALTER TABLE `knex_migrations` DISABLE KEYS */; +INSERT INTO `knex_migrations` VALUES +(1,'20251219003210_20251219_initial_schema.js',1,'2026-01-19 00:47:40'), +(2,'20251219010000_add_columns_to_projects.js',1,'2026-01-19 00:47:40'), +(3,'20260106083251_create_permissions_tables.js',2,'2026-01-19 00:49:25'), +(4,'20260106083318_populate_permissions_data.js',3,'2026-01-19 00:49:29'), +(5,'20260107140000_update_worker_schema.js',3,'2026-01-19 00:49:29'), +(6,'20260119000000_simplify_permissions_and_add_page_access.js',3,'2026-01-19 00:49:29'), +(7,'20260119120000_add_worker_fields.js',3,'2026-01-19 00:49:46'), +(9,'20260119120001_create_attendance_tables.js',3,'2026-01-19 01:34:26'), +(11,'20260119120002_create_accounts_for_existing_workers.js',5,'2026-01-19 10:40:56'), +(12,'20260119120003_add_guest_role.js',5,'2026-01-19 10:40:56'), +(13,'20260119095549_add_worker_display_fields.js',6,'2026-01-19 01:46:21'), +(14,'20260120000000_create_tbm_system.js',7,'2026-01-20 15:30:51'), +(15,'20260120000001_add_tbm_page.js',8,'2026-01-20 15:34:53'), +(16,'20260126000001_create_workplace_categories.js',9,'2026-01-26 14:27:40'), +(17,'20260126000002_create_workplaces.js',9,'2026-01-26 14:27:40'), +(18,'20260126010002_create_tasks.js',10,'2026-01-26 15:05:01'), +(20,'20260126010003_add_work_type_task_to_tbm.js',11,'2026-01-27 06:30:46'), +(21,'20260126010004_add_work_details_to_team_assignments.js',11,'2026-01-27 06:30:46'), +(22,'20260127000001_remove_unused_tbm_fields.js',12,'2026-01-27 07:03:06'), +(23,'20260127000002_add_workplace_map_images.js',13,'2026-01-27 07:30:47'), +(24,'20260127010000_add_workplace_purpose_fields.js',14,'2026-01-27 08:15:49'), +(25,'20260127020000_make_leader_id_nullable.js',15,'2026-01-27 08:48:02'), +(26,'20260127030000_add_tbm_fields_to_work_reports.js',16,'2026-01-27 10:38:52'), +(27,'20260127040000_update_pages_for_current_system.js',17,'2026-01-27 14:59:17'), +(28,'20260128000000_add_layout_image_to_workplaces.js',18,'2026-01-28 08:24:33'), +(29,'20260128010000_create_equipments_table.js',19,'2026-01-28 09:01:32'), +(30,'20260129000000_create_vacation_requests.js',20,'2026-01-28 14:54:20'), +(31,'20260129000001_register_attendance_pages.js',21,'2026-01-28 14:55:06'), +(32,'20260129000003_update_vacation_pages.js',22,'2026-01-29 12:49:41'), +(33,'20260129000002_add_attendance_is_present.js',23,'2026-01-29 13:09:34'), +(37,'20260129000004_extend_vacation_types.js',24,'2026-01-29 13:33:11'), +(38,'20260129000005_create_vacation_balance_details.js',24,'2026-01-29 13:33:11'), +(39,'20260129000006_register_vacation_pages.js',24,'2026-01-29 13:33:11'), +(40,'20260129010000_create_visit_request_system.js',25,'2026-01-29 14:26:17'), +(41,'20260129010001_register_visit_pages.js',25,'2026-01-29 14:26:17'), +(42,'20260130000001_create_work_issue_system.js',26,'2026-02-02 00:23:42'), +(44,'20260130000002_register_issue_pages.js',27,'2026-02-02 01:19:22'), +(45,'20260202000001_create_work_report_defects.js',28,'2026-02-02 01:19:31'), +(46,'20260202100000_expand_safety_checklist.js',29,'2026-02-02 01:44:54'), +(48,'20260202200000_reorganize_pages.js',30,'2026-02-02 23:15:51'), +(49,'20260203100000_link_defects_to_issues.js',31,'2026-02-02 23:16:00'), +(50,'20260203090000_add_category_to_defects.js',32,'2026-02-02 23:55:34'), +(51,'20260204100000_add_equipment_purchase_fields.js',33,'2026-02-04 01:44:41'), +(52,'20260204100000_create_daily_patrol_system.js',34,'2026-02-04 01:47:33'); +/*!40000 ALTER TABLE `knex_migrations` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `knex_migrations_lock` +-- + +DROP TABLE IF EXISTS `knex_migrations_lock`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `knex_migrations_lock` ( + `index` int(10) unsigned NOT NULL AUTO_INCREMENT, + `is_locked` int(11) DEFAULT NULL, + PRIMARY KEY (`index`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `knex_migrations_lock` +-- + +LOCK TABLES `knex_migrations_lock` WRITE; +/*!40000 ALTER TABLE `knex_migrations_lock` DISABLE KEYS */; +INSERT INTO `knex_migrations_lock` VALUES +(1,0); +/*!40000 ALTER TABLE `knex_migrations_lock` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `login_logs` +-- + +DROP TABLE IF EXISTS `login_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `login_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL, + `login_time` datetime DEFAULT current_timestamp(), + `logout_time` datetime DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `login_status` enum('success','failed','locked') DEFAULT 'success', + `failure_reason` varchar(100) DEFAULT NULL, + PRIMARY KEY (`log_id`), + KEY `idx_user_login` (`user_id`,`login_time`), + CONSTRAINT `login_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=224 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `login_logs` +-- + +LOCK TABLES `login_logs` WRITE; +/*!40000 ALTER TABLE `login_logs` DISABLE KEYS */; +INSERT INTO `login_logs` VALUES +(146,3,'2025-11-02 23:53:02',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(147,3,'2025-11-03 02:10:26',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(148,3,'2025-11-03 02:10:33',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(149,1,'2025-11-03 02:11:06',NULL,'::ffff:185.199.111.133','curl/8.7.1','failed','invalid_password'), +(150,1,'2025-11-03 02:11:06',NULL,'::ffff:185.199.111.133','curl/8.7.1','failed','invalid_password'), +(151,3,'2025-11-03 02:11:43',NULL,'::ffff:185.199.111.133','curl/8.7.1','success',NULL), +(152,3,'2025-11-03 02:11:49',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(153,3,'2025-11-03 02:12:44',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(154,3,'2025-11-03 02:12:58',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(155,3,'2025-11-03 02:12:58',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(156,3,'2025-11-03 02:13:02',NULL,'::ffff:185.199.111.133','curl/8.7.1','success',NULL), +(157,3,'2025-11-03 02:13:43',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(158,3,'2025-11-03 02:15:28',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(159,3,'2025-11-03 03:07:23',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(160,3,'2025-11-03 03:27:50',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(161,3,'2025-11-03 03:44:52',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(162,3,'2025-11-03 04:02:14',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(163,3,'2025-11-03 04:36:14',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(164,3,'2025-11-03 06:21:57',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(165,3,'2025-11-03 06:50:04',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(166,3,'2025-11-03 22:39:38',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(167,1,'2025-11-04 01:38:28',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(168,1,'2025-11-04 01:58:20',NULL,'::ffff:192.168.65.1','curl/8.7.1','failed','invalid_password'), +(169,1,'2025-11-04 21:34:47',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(170,1,'2025-11-04 23:55:43',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(171,1,'2025-11-04 23:56:47',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','failed','invalid_password'), +(172,1,'2025-11-04 23:56:59',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(173,1,'2025-11-05 01:35:01',NULL,'::ffff:185.199.109.133','curl/8.7.1','failed','invalid_password'), +(174,1,'2025-11-05 01:36:09',NULL,'::ffff:185.199.109.133','curl/8.7.1','failed','invalid_password'), +(175,1,'2025-11-05 01:37:45',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(176,1,'2025-11-05 01:44:59',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(177,6,'2025-11-05 01:46:07',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(178,3,'2025-11-05 01:46:14',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(179,5,'2025-11-05 01:47:15',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(180,3,'2025-11-05 01:49:12',NULL,'::ffff:185.199.109.133','curl/8.7.1','failed','invalid_password'), +(181,3,'2025-11-05 01:49:27',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(182,6,'2025-11-05 01:49:37',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(183,5,'2025-11-05 01:49:44',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(184,5,'2025-11-05 01:50:08',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(185,5,'2025-11-05 01:55:59',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(186,6,'2025-11-05 01:56:13',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(187,3,'2025-11-05 01:56:20',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(188,1,'2025-11-05 01:56:35',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(189,1,'2025-11-05 02:01:27',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(190,3,'2025-11-05 02:01:53',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(191,5,'2025-11-05 02:02:02',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(192,1,'2025-11-05 02:03:10',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','failed','invalid_password'), +(193,1,'2025-11-05 02:03:20',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(194,5,'2025-11-05 02:18:31',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(195,7,'2025-11-05 02:20:22',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(196,1,'2025-11-05 02:20:37',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(197,7,'2025-11-05 02:23:43',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(198,1,'2025-11-05 02:25:08',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(199,3,'2025-11-05 02:25:45',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(200,7,'2025-11-05 02:25:54',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(201,7,'2025-11-05 02:26:31',NULL,'::ffff:185.199.110.133','curl/8.7.1','failed','invalid_password'), +(202,7,'2025-11-05 02:27:52',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(205,1,'2025-11-05 02:52:20',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(206,3,'2026-02-03 04:54:17',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(207,1,'2026-02-03 04:56:05',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(208,3,'2026-02-03 05:43:08',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36','success',NULL), +(209,1,'2026-02-03 05:43:42',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36','success',NULL), +(210,1,'2026-02-03 06:14:57',NULL,'::ffff:185.199.108.133','curl/8.7.1','failed','invalid_password'), +(211,1,'2026-02-03 06:25:29',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(212,1,'2026-02-03 06:26:54',NULL,'::ffff:185.199.108.133','curl/8.7.1','failed','invalid_password'), +(213,1,'2026-02-03 06:55:48',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(214,1,'2026-02-03 21:24:20',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(215,1,'2026-02-03 22:53:39',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(216,1,'2026-02-04 05:31:13',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(217,1,'2026-02-04 07:25:57',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(218,1,'2026-02-04 23:46:38',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(219,1,'2026-02-05 01:01:31',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(220,1,'2026-02-05 03:56:31',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(221,1,'2026-02-05 05:22:15',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(222,1,'2026-02-05 21:37:09',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36','success',NULL), +(223,1,'2026-02-05 22:40:53',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36','success',NULL); +/*!40000 ALTER TABLE `login_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `notification_recipients` +-- + +DROP TABLE IF EXISTS `notification_recipients`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `notification_recipients` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `notification_type` enum('repair','safety','nonconformity','equipment','maintenance','system') NOT NULL, + `user_id` int(11) NOT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `created_by` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unique_type_user` (`notification_type`,`user_id`), + KEY `user_id` (`user_id`), + KEY `idx_nr_type` (`notification_type`), + KEY `idx_nr_active` (`is_active`), + CONSTRAINT `notification_recipients_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `notification_recipients` +-- + +LOCK TABLES `notification_recipients` WRITE; +/*!40000 ALTER TABLE `notification_recipients` DISABLE KEYS */; +/*!40000 ALTER TABLE `notification_recipients` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `notifications` +-- + +DROP TABLE IF EXISTS `notifications`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `notifications` ( + `notification_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL COMMENT '특정 사용자에게만 표시 (NULL이면 전체)', + `type` enum('repair','safety','system','equipment','maintenance') NOT NULL DEFAULT 'system', + `title` varchar(200) NOT NULL, + `message` text DEFAULT NULL, + `link_url` varchar(500) DEFAULT NULL COMMENT '클릭시 이동할 URL', + `reference_type` varchar(50) DEFAULT NULL COMMENT '연관 테이블', + `reference_id` int(11) DEFAULT NULL COMMENT '연관 레코드 ID', + `is_read` tinyint(1) DEFAULT 0, + `read_at` datetime DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `created_by` int(11) DEFAULT NULL, + PRIMARY KEY (`notification_id`), + KEY `idx_notifications_user` (`user_id`), + KEY `idx_notifications_type` (`type`), + KEY `idx_notifications_is_read` (`is_read`), + KEY `idx_notifications_created` (`created_at` DESC) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `notifications` +-- + +LOCK TABLES `notifications` WRITE; +/*!40000 ALTER TABLE `notifications` DISABLE KEYS */; +INSERT INTO `notifications` VALUES +(1,NULL,'repair','수리 신청: TIG용접기','기계 고장 수리가 신청되었습니다.','/pages/admin/equipment-detail.html?id=18','work_issue_reports',7,1,'2026-02-04 06:08:30','2026-02-04 05:35:54',NULL), +(2,NULL,'repair','수리 신청: TIG용접기','기계 고장 수리가 신청되었습니다.','/pages/admin/repair-management.html','work_issue_reports',7,0,NULL,'2026-02-04 05:35:54',NULL); +/*!40000 ALTER TABLE `notifications` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pages` +-- + +DROP TABLE IF EXISTS `pages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pages` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `page_key` varchar(100) NOT NULL, + `page_name` varchar(100) NOT NULL, + `page_path` varchar(255) NOT NULL, + `category` varchar(50) DEFAULT NULL, + `description` varchar(255) DEFAULT NULL, + `is_admin_only` tinyint(1) DEFAULT 0, + `display_order` int(11) DEFAULT 0, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `is_default_accessible` tinyint(1) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `pages_page_key_unique` (`page_key`) +) ENGINE=InnoDB AUTO_INCREMENT=55 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `pages` +-- + +LOCK TABLES `pages` WRITE; +/*!40000 ALTER TABLE `pages` DISABLE KEYS */; +INSERT INTO `pages` VALUES +(11,'dashboard','대시보드','/pages/dashboard.html','common','전체 현황 대시보드',0,1,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(12,'work.tbm','TBM','/pages/work/tbm.html','work','TBM (Tool Box Meeting) 관리',0,10,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(13,'work.report-create','작업보고서 작성','/pages/work/report-create.html','work','일일 작업보고서 작성',0,11,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(14,'work.report-view','작업보고서 조회','/pages/work/report-view.html','work','작업보고서 조회 및 검색',0,12,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(15,'work.analysis','작업 분석','/pages/work/analysis.html','work','작업 통계 및 분석',0,13,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(16,'admin.accounts','계정 관리','/pages/admin/accounts.html','admin','사용자 계정 관리',1,20,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(18,'admin.workers','작업자 관리','/pages/admin/workers.html','admin','작업자 정보 관리',1,22,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(19,'admin.projects','프로젝트 관리','/pages/admin/projects.html','admin','프로젝트 관리',1,23,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(20,'admin.workplaces','작업장 관리','/pages/admin/workplaces.html','admin','작업장소 관리',1,24,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(21,'admin.codes','코드 관리','/pages/admin/codes.html','admin','시스템 코드 관리',1,25,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(22,'admin.tasks','작업 관리','/pages/admin/tasks.html','admin','작업 유형 관리',1,26,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(23,'profile.info','내 정보','/pages/profile/info.html','profile','내 프로필 정보',0,30,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(24,'profile.password','비밀번호 변경','/pages/profile/password.html','profile','비밀번호 변경',0,31,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(25,'admin.equipments','설비 관리','/pages/admin/equipments.html','admin','작업장별 설비 정보를 등록하고 관리합니다',1,35,'2026-01-28 00:17:01','2026-01-28 00:17:01',0), +(26,'common.daily-attendance','일일 출퇴근 입력','/pages/common/daily-attendance.html','common','일일 출퇴근 기록 입력 페이지 (관리자/조장)',0,50,'2026-01-28 05:55:06','2026-01-28 05:55:06',1), +(27,'common.monthly-attendance','월별 출퇴근 현황','/pages/common/monthly-attendance.html','common','월별 출퇴근 현황 조회 페이지',0,51,'2026-01-28 05:55:06','2026-01-28 05:55:06',1), +(29,'admin.attendance-report-comparison','출퇴근-작업보고서 대조','/pages/admin/attendance-report-comparison.html','admin','출퇴근 기록과 작업보고서 대조 페이지 (관리자)',1,120,'2026-01-28 05:55:06','2026-01-28 05:55:06',0), +(34,'common.vacation-request','휴가 신청','/pages/common/vacation-request.html','common','작업자가 휴가를 신청하고 본인의 신청 내역을 확인하는 페이지',0,51,'2026-01-29 04:10:29','2026-01-29 04:10:29',1), +(35,'common.vacation-management','휴가 관리','/pages/common/vacation-management.html','common','관리자가 휴가 승인, 직접 입력, 전체 내역을 관리하는 페이지',1,52,'2026-01-29 04:10:29','2026-01-29 04:10:29',0), +(36,'common.annual-vacation-overview','연간 연차 현황','/pages/common/annual-vacation-overview.html','common','모든 작업자의 연간 연차 현황을 차트로 시각화',1,54,'2026-01-29 04:33:11','2026-01-29 04:33:11',0), +(37,'common.vacation-allocation','휴가 발생 입력','/pages/common/vacation-allocation.html','common','작업자별 휴가 발생 입력 및 특별 휴가 관리',1,55,'2026-01-29 04:33:11','2026-01-29 04:33:11',0), +(38,'work.visit-request','출입 신청','/pages/work/visit-request.html','work','작업장 출입 신청 및 안전교육 신청',0,15,'2026-01-29 05:26:17','2026-01-29 05:26:17',1), +(39,'admin.safety-management','안전관리','/pages/admin/safety-management.html','admin','출입 신청 승인 및 안전교육 관리',0,60,'2026-01-29 05:26:17','2026-01-29 05:26:17',0), +(40,'admin.safety-training-conduct','안전교육 진행','/pages/admin/safety-training-conduct.html','admin','안전교육 실시 및 서명 관리',0,61,'2026-01-29 05:26:17','2026-01-29 05:26:17',0), +(41,'work.issue-report','문제 신고','/pages/work/issue-report.html','work','작업 중 문제(부적합/안전) 신고 등록',0,16,'2026-02-02 00:24:55','2026-02-02 00:24:55',1), +(42,'work.issue-list','신고 목록','/pages/work/issue-list.html','work','문제 신고 목록 조회 및 관리',0,17,'2026-02-02 00:24:55','2026-02-02 00:24:55',1), +(43,'work.issue-detail','신고 상세','/pages/work/issue-detail.html','work','문제 신고 상세 조회',0,18,'2026-02-02 00:24:55','2026-02-02 00:24:55',1), +(44,'safety.issue_report','이슈 신고','/pages/safety/issue-report.html','safety','작업 중 문제(부적합/안전) 신고 등록',0,16,'2026-02-02 01:19:22','2026-02-02 01:19:22',0), +(45,'safety.issue_list','이슈 목록','/pages/safety/issue-list.html','safety','문제 신고 목록 조회 및 관리',0,17,'2026-02-02 01:19:22','2026-02-02 01:19:22',0), +(46,'safety.issue_detail','이슈 상세','/pages/safety/issue-detail.html','safety','문제 신고 상세 조회',0,18,'2026-02-02 01:19:22','2026-02-02 01:19:22',0), +(50,'safety.checklist_manage','안전 체크리스트 관리','/pages/safety/checklist-manage.html','safety','안전 체크리스트 항목 관리',1,50,'2026-02-02 23:15:51','2026-02-02 23:15:51',0), +(51,'attendance.vacation_approval','휴가 승인 관리','/pages/attendance/vacation-approval.html','attendance','휴가 신청 승인/거부',1,65,'2026-02-02 23:15:51','2026-02-02 23:15:51',0), +(52,'attendance.vacation_input','휴가 직접 입력','/pages/attendance/vacation-input.html','attendance','관리자 휴가 직접 입력',1,66,'2026-02-02 23:15:51','2026-02-02 23:15:51',0), +(53,'admin.departments','부서 관리','/pages/admin/departments.html','admin',NULL,1,3,'2026-02-03 05:06:48','2026-02-03 05:06:48',0), +(54,'inspection.daily_patrol','일일순회점검','/pages/inspection/daily-patrol.html','inspection','작업장 일일순회점검 페이지',0,1,'2026-02-04 02:17:23','2026-02-04 02:17:23',1); +/*!40000 ALTER TABLE `pages` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `password_change_logs` +-- + +DROP TABLE IF EXISTS `password_change_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `password_change_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `changed_by_user_id` int(11) DEFAULT NULL, + `changed_at` datetime DEFAULT current_timestamp(), + `change_type` enum('self','admin','reset','initial') DEFAULT 'self', + `ip_address` varchar(45) DEFAULT NULL, + PRIMARY KEY (`log_id`), + KEY `changed_by_user_id` (`changed_by_user_id`), + KEY `idx_user_changes` (`user_id`,`changed_at`), + CONSTRAINT `password_change_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE, + CONSTRAINT `password_change_logs_ibfk_2` FOREIGN KEY (`changed_by_user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `password_change_logs` +-- + +LOCK TABLES `password_change_logs` WRITE; +/*!40000 ALTER TABLE `password_change_logs` DISABLE KEYS */; +/*!40000 ALTER TABLE `password_change_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `patrol_check_records` +-- + +DROP TABLE IF EXISTS `patrol_check_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `patrol_check_records` ( + `record_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL COMMENT '순회점검 세션 ID', + `workplace_id` int(10) unsigned NOT NULL COMMENT '작업장 ID', + `check_item_id` int(10) unsigned NOT NULL COMMENT '체크항목 ID', + `is_checked` tinyint(1) DEFAULT 0 COMMENT '체크 여부', + `check_result` enum('good','warning','bad') DEFAULT NULL COMMENT '점검 결과', + `note` text DEFAULT NULL COMMENT '비고', + `checked_at` timestamp NULL DEFAULT NULL COMMENT '체크 시간', + PRIMARY KEY (`record_id`), + UNIQUE KEY `pcr_session_wp_item_unique` (`session_id`,`workplace_id`,`check_item_id`), + KEY `pcr_session_wp_idx` (`session_id`,`workplace_id`), + KEY `patrol_check_records_workplace_id_foreign` (`workplace_id`), + KEY `patrol_check_records_check_item_id_foreign` (`check_item_id`), + CONSTRAINT `patrol_check_records_check_item_id_foreign` FOREIGN KEY (`check_item_id`) REFERENCES `patrol_checklist_items` (`item_id`) ON DELETE CASCADE, + CONSTRAINT `patrol_check_records_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `daily_patrol_sessions` (`session_id`) ON DELETE CASCADE, + CONSTRAINT `patrol_check_records_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `patrol_check_records` +-- + +LOCK TABLES `patrol_check_records` WRITE; +/*!40000 ALTER TABLE `patrol_check_records` DISABLE KEYS */; +/*!40000 ALTER TABLE `patrol_check_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `patrol_checklist_items` +-- + +DROP TABLE IF EXISTS `patrol_checklist_items`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `patrol_checklist_items` ( + `item_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `workplace_id` int(10) unsigned DEFAULT NULL COMMENT '특정 작업장 전용 (NULL=공통)', + `category_id` int(10) unsigned DEFAULT NULL COMMENT '특정 공장 전용 (NULL=공통)', + `check_category` varchar(50) NOT NULL COMMENT '분류 (안전, 정리정돈, 설비 등)', + `check_item` varchar(200) NOT NULL COMMENT '점검 항목', + `description` text DEFAULT NULL COMMENT '설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_required` tinyint(1) DEFAULT 1 COMMENT '필수 체크 여부', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`item_id`), + KEY `patrol_checklist_items_workplace_id_index` (`workplace_id`), + KEY `patrol_checklist_items_category_id_index` (`category_id`), + KEY `patrol_checklist_items_check_category_index` (`check_category`), + CONSTRAINT `patrol_checklist_items_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE CASCADE, + CONSTRAINT `patrol_checklist_items_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `patrol_checklist_items` +-- + +LOCK TABLES `patrol_checklist_items` WRITE; +/*!40000 ALTER TABLE `patrol_checklist_items` DISABLE KEYS */; +INSERT INTO `patrol_checklist_items` VALUES +(1,NULL,NULL,'SAFETY','소화기 상태 확인',NULL,1,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(2,NULL,NULL,'SAFETY','비상구 통로 확보 확인',NULL,2,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(3,NULL,NULL,'SAFETY','안전표지판 부착 상태',NULL,3,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(4,NULL,NULL,'SAFETY','위험물 관리 상태',NULL,4,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(5,NULL,NULL,'ORGANIZATION','작업장 정리정돈 상태',NULL,10,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(6,NULL,NULL,'ORGANIZATION','통로 장애물 여부',NULL,11,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(7,NULL,NULL,'ORGANIZATION','폐기물 처리 상태',NULL,12,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(8,NULL,NULL,'ORGANIZATION','자재 적재 상태',NULL,13,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(9,NULL,NULL,'EQUIPMENT','설비 외관 이상 여부',NULL,20,0,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(10,NULL,NULL,'EQUIPMENT','설비 작동 상태',NULL,21,0,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(11,NULL,NULL,'EQUIPMENT','설비 청결 상태',NULL,22,0,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(12,NULL,NULL,'ENVIRONMENT','조명 상태',NULL,30,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(13,NULL,NULL,'ENVIRONMENT','환기 상태',NULL,31,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(14,NULL,NULL,'ENVIRONMENT','누수/누유 여부',NULL,32,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'); +/*!40000 ALTER TABLE `patrol_checklist_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permissions` +-- + +DROP TABLE IF EXISTS `permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `permissions` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `description` varchar(255) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `permissions_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permissions` +-- + +LOCK TABLES `permissions` WRITE; +/*!40000 ALTER TABLE `permissions` DISABLE KEYS */; +INSERT INTO `permissions` VALUES +(1,'user:create','사용자 생성','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(2,'user:read','사용자 정보 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(3,'user:update','사용자 정보 수정','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(4,'user:delete','사용자 삭제','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(5,'project:create','프로젝트 생성','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(6,'project:read','프로젝트 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(7,'project:update','프로젝트 수정','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(8,'project:delete','프로젝트 삭제','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(9,'work-report:create','작업 보고서 생성','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(10,'work-report:read-own','자신의 작업 보고서 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(11,'work-report:read-team','팀의 작업 보고서 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(12,'work-report:read-all','모든 작업 보고서 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(13,'work-report:update','작업 보고서 수정','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(14,'work-report:delete','작업 보고서 삭제','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(15,'system:read-logs','시스템 로그 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(16,'system:manage-settings','시스템 설정 관리','2026-01-19 00:49:29','2026-01-19 00:49:29'); +/*!40000 ALTER TABLE `permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `projects` +-- + +DROP TABLE IF EXISTS `projects`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `projects` ( + `project_id` int(11) NOT NULL AUTO_INCREMENT, + `job_no` varchar(50) NOT NULL, + `project_name` varchar(255) NOT NULL, + `contract_date` date DEFAULT NULL, + `due_date` date DEFAULT NULL, + `delivery_method` varchar(100) DEFAULT NULL, + `site` varchar(100) DEFAULT NULL, + `pm` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `is_active` tinyint(1) DEFAULT 1, + `project_status` varchar(50) DEFAULT 'active', + `completed_date` date DEFAULT NULL, + PRIMARY KEY (`project_id`) +) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `projects` +-- + +LOCK TABLES `projects` WRITE; +/*!40000 ALTER TABLE `projects` DISABLE KEYS */; +INSERT INTO `projects` VALUES +(1,'TKO-24008P','YHP Project',NULL,NULL,NULL,'Quang Ninh(Vietnam)','장형태','2025-04-15 22:40:28','2025-04-15 22:40:28',0,'active',NULL), +(2,'TKG-24009P','한화에어로스페이스 순천',NULL,NULL,NULL,'순천','장형태','2025-04-15 22:42:41','2025-04-15 22:42:41',0,'active',NULL), +(3,'TKG-24011P','효성화학 에틸렌 탱크 건설공사',NULL,NULL,NULL,'울산','김길종','2025-04-15 22:43:53','2025-04-15 22:43:53',0,'active',NULL), +(4,'TKG-24013P','김천 솔라 파워 그린 수소 Project',NULL,NULL,NULL,'김천','김길종','2025-04-15 22:44:57','2025-04-15 22:44:57',0,'active',NULL), +(5,'TKG-24016P','LG Chem P3RE Project',NULL,NULL,NULL,'.','장형태','2025-04-15 22:46:36','2025-04-15 22:46:36',0,'active',NULL), +(7,'TKO-25003F','25년 안전보건시설설비',NULL,NULL,NULL,'.','.','2025-04-15 22:47:32','2025-04-15 22:47:32',0,'active',NULL), +(8,'TKG-25007P','P Project',NULL,NULL,NULL,'오창읍','장형태','2025-04-15 22:48:50','2025-04-15 22:48:50',0,'active',NULL), +(10,'TKR-25008P','DIG Airgas LG CHEM',NULL,NULL,NULL,'여수','서태원','2025-04-15 22:50:05','2025-04-15 22:50:05',0,'active',NULL), +(11,'TKR-25010P','FK FISCHER Project',NULL,NULL,NULL,'울산','전상신','2025-04-15 22:51:12','2025-04-15 22:51:12',0,'active',NULL), +(12,'TKO-24007P','MP7 Project',NULL,NULL,NULL,'.','윤지민','2025-04-15 23:56:26','2025-04-15 23:56:26',0,'active',NULL), +(13,'연차/휴무','연차/휴무','2025-01-01','2025-12-31','.','.','.','2025-04-16 01:58:23','2025-04-16 01:58:23',1,'active',NULL), +(14,'TKO-25009R','M Project',NULL,NULL,NULL,NULL,'이민후','2025-09-28 22:13:33','2025-09-28 22:13:33',1,'active',NULL), +(15,'TKR-25013P','HAS MCS Plnat',NULL,'2026-03-31',NULL,NULL,NULL,'2026-01-06 06:16:37','2026-01-06 06:16:37',1,'active',NULL), +(16,'TKO-26003F','안전보건시설설비','2026-01-01','2026-12-31',NULL,NULL,NULL,'2026-01-06 06:17:33','2026-01-06 06:17:33',1,'active',NULL), +(17,'TKO-25014P','OT1-MPR-002',NULL,NULL,NULL,'말레이시아','윤지민','2026-02-04 21:35:22','2026-02-04 21:35:22',1,'active',NULL), +(18,'TKO025024P','H2 Gas Scrubber',NULL,'2026-07-31',NULL,NULL,'윤지민','2026-02-04 21:36:50','2026-02-04 21:36:50',1,'active',NULL); +/*!40000 ALTER TABLE `projects` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `role_default_pages` +-- + +DROP TABLE IF EXISTS `role_default_pages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `role_default_pages` ( + `role_id` int(10) unsigned NOT NULL, + `page_id` int(10) unsigned NOT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`role_id`,`page_id`), + KEY `role_default_pages_page_id_foreign` (`page_id`), + CONSTRAINT `role_default_pages_page_id_foreign` FOREIGN KEY (`page_id`) REFERENCES `pages` (`id`) ON DELETE CASCADE, + CONSTRAINT `role_default_pages_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `role_default_pages` +-- + +LOCK TABLES `role_default_pages` WRITE; +/*!40000 ALTER TABLE `role_default_pages` DISABLE KEYS */; +/*!40000 ALTER TABLE `role_default_pages` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `role_permissions` +-- + +DROP TABLE IF EXISTS `role_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `role_permissions` ( + `role_id` int(10) unsigned NOT NULL, + `permission_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`role_id`,`permission_id`), + KEY `role_permissions_permission_id_foreign` (`permission_id`), + CONSTRAINT `role_permissions_permission_id_foreign` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE, + CONSTRAINT `role_permissions_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `role_permissions` +-- + +LOCK TABLES `role_permissions` WRITE; +/*!40000 ALTER TABLE `role_permissions` DISABLE KEYS */; +INSERT INTO `role_permissions` VALUES +(1,1), +(1,2), +(1,3), +(1,4), +(1,5), +(1,6), +(1,7), +(1,8), +(1,9), +(1,10), +(1,11), +(1,12), +(1,13), +(1,14), +(1,15), +(1,16), +(2,1), +(2,2), +(2,3), +(2,4), +(2,5), +(2,6), +(2,7), +(2,8), +(2,12), +(2,13), +(2,14), +(4,2), +(4,5), +(4,6), +(4,7), +(4,9), +(4,10), +(4,11), +(4,12), +(4,13), +(4,14); +/*!40000 ALTER TABLE `role_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles` +-- + +DROP TABLE IF EXISTS `roles`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(255) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `roles_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles` +-- + +LOCK TABLES `roles` WRITE; +/*!40000 ALTER TABLE `roles` DISABLE KEYS */; +INSERT INTO `roles` VALUES +(1,'System Admin','시스템 전체 관리자. 모든 권한을 가짐.','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(2,'Admin','관리자. 사용자 및 프로젝트 관리 등 대부분의 권한을 가짐.','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(4,'User','일반 사용자. 작업 보고서 및 프로젝트 관리 등 모든 일반 기능을 사용할 수 있음.','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(5,'Guest','게스트 (계정 없이 특정 기능 접근 가능)','2026-01-19 01:40:56','2026-01-19 01:40:56'); +/*!40000 ALTER TABLE `roles` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `safety_training_records` +-- + +DROP TABLE IF EXISTS `safety_training_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `safety_training_records` ( + `training_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '교육 기록 ID', + `request_id` int(10) unsigned NOT NULL COMMENT '출입 신청 ID', + `trainer_id` int(11) NOT NULL COMMENT '교육 진행자 user_id', + `training_date` date NOT NULL COMMENT '교육 날짜', + `training_start_time` time NOT NULL COMMENT '교육 시작 시간', + `training_end_time` time DEFAULT NULL COMMENT '교육 종료 시간', + `training_topics` text DEFAULT NULL COMMENT '교육 내용 (JSON 배열)', + `signature_data` longtext DEFAULT NULL COMMENT '교육 이수자 서명 (Base64 PNG)', + `completed_at` timestamp NULL DEFAULT NULL COMMENT '교육 완료 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`training_id`), + KEY `safety_training_records_trainer_id_foreign` (`trainer_id`), + KEY `idx_training_date` (`training_date`), + KEY `idx_request_id` (`request_id`), + CONSTRAINT `safety_training_records_request_id_foreign` FOREIGN KEY (`request_id`) REFERENCES `workplace_visit_requests` (`request_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `safety_training_records_trainer_id_foreign` FOREIGN KEY (`trainer_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `safety_training_records` +-- + +LOCK TABLES `safety_training_records` WRITE; +/*!40000 ALTER TABLE `safety_training_records` DISABLE KEYS */; +INSERT INTO `safety_training_records` VALUES +(1,1,1,'2026-01-29','15:04:41','15:04:41',NULL,NULL,NULL,'2026-01-29 06:04:41','2026-01-29 06:04:41'), +(2,1,1,'2026-01-29','15:04:41','15:04:41',NULL,NULL,NULL,'2026-01-29 06:04:41','2026-01-29 06:04:41'), +(3,1,1,'2026-01-29','15:08:41','15:08:41',NULL,NULL,NULL,'2026-01-29 06:08:41','2026-01-29 06:08:41'), +(4,1,1,'2026-01-29','15:08:41','15:08:41',NULL,NULL,NULL,'2026-01-29 06:08:41','2026-01-29 06:08:41'), +(5,2,1,'2026-01-29','15:12:11','15:12:11',NULL,NULL,NULL,'2026-01-29 06:12:11','2026-01-29 06:12:11'), +(6,2,1,'2026-01-29','15:12:11','15:12:11',NULL,NULL,NULL,'2026-01-29 06:12:11','2026-01-29 06:12:11'); +/*!40000 ALTER TABLE `safety_training_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tasks` +-- + +DROP TABLE IF EXISTS `tasks`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tasks` ( + `task_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '작업 ID', + `work_type_id` int(11) DEFAULT NULL COMMENT '공정 ID (work_types 참조)', + `task_name` varchar(255) NOT NULL COMMENT '작업명', + `description` text DEFAULT NULL COMMENT '작업 설명', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성화 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '생성일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정일시', + PRIMARY KEY (`task_id`), + KEY `tasks_work_type_id_index` (`work_type_id`), + KEY `tasks_is_active_index` (`is_active`), + CONSTRAINT `tasks_work_type_id_foreign` FOREIGN KEY (`work_type_id`) REFERENCES `work_types` (`id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tasks` +-- + +LOCK TABLES `tasks` WRITE; +/*!40000 ALTER TABLE `tasks` DISABLE KEYS */; +INSERT INTO `tasks` VALUES +(1,1,'H빔 절단',NULL,1,'2026-01-26 21:54:17','2026-01-26 21:54:17'), +(2,1,'H빔 가공','끝단 가공 등 전부 포함',1,'2026-02-04 21:47:35','2026-02-04 21:47:35'), +(3,1,'용접',NULL,1,'2026-02-04 21:47:53','2026-02-04 21:47:53'), +(4,1,'서포트 제작(홀 가공 포함)',NULL,1,'2026-02-04 21:48:15','2026-02-04 21:48:15'), +(5,2,'Plate 하차',NULL,1,'2026-02-04 21:48:30','2026-02-04 21:48:30'), +(6,2,'Plate 마킹',NULL,1,'2026-02-04 21:48:38','2026-02-04 21:48:38'), +(7,2,'Plate 가공 출하',NULL,1,'2026-02-04 21:48:59','2026-02-04 21:48:59'), +(8,2,'동체 L심 용접',NULL,1,'2026-02-04 21:49:19','2026-02-04 21:49:19'), +(9,2,'C심 용접',NULL,1,'2026-02-04 21:49:29','2026-02-04 21:49:29'), +(10,2,'노즐 용접',NULL,1,'2026-02-04 21:49:36','2026-02-04 21:49:48'), +(11,2,'자재 절단',NULL,1,'2026-02-04 21:49:55','2026-02-04 21:49:55'), +(12,2,'검사 지원',NULL,1,'2026-02-04 21:50:16','2026-02-04 21:50:16'), +(13,3,'pipe 절단',NULL,1,'2026-02-04 21:50:31','2026-02-04 21:50:31'), +(14,3,'배관 취부',NULL,1,'2026-02-04 21:50:39','2026-02-04 21:50:39'), +(15,3,'용접',NULL,1,'2026-02-04 21:50:43','2026-02-04 21:50:43'), +(16,3,'선 작업(용접전 작업 준비)','갭링, 면취 등 모든 선 작업',1,'2026-02-04 21:51:22','2026-02-04 21:51:22'), +(17,3,'1차 조립',NULL,1,'2026-02-04 21:51:31','2026-02-04 21:51:31'), +(18,3,'검사 지원',NULL,1,'2026-02-04 21:51:36','2026-02-04 21:51:36'), +(19,3,'2차 조립',NULL,1,'2026-02-04 21:51:41','2026-02-04 21:51:41'), +(20,11,'배우자출산휴가',NULL,1,'2026-02-04 22:41:40','2026-02-04 22:41:40'), +(21,11,'연차',NULL,1,'2026-02-04 22:41:46','2026-02-04 22:41:46'), +(22,11,'반차',NULL,1,'2026-02-04 22:41:51','2026-02-04 22:41:51'), +(23,11,'반반차',NULL,1,'2026-02-04 22:41:57','2026-02-04 22:41:57'), +(24,11,'조퇴',NULL,1,'2026-02-04 22:42:05','2026-02-04 22:42:05'), +(25,12,'설비제작',NULL,1,'2026-02-04 23:47:01','2026-02-04 23:47:01'), +(26,2,'자재 가공',NULL,1,'2026-02-05 01:01:48','2026-02-05 01:01:48'); +/*!40000 ALTER TABLE `tasks` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tasks_old_backup` +-- + +DROP TABLE IF EXISTS `tasks_old_backup`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tasks_old_backup` ( + `task_id` int(11) NOT NULL AUTO_INCREMENT, + `category` varchar(255) NOT NULL, + `subcategory` varchar(255) DEFAULT NULL, + `task_name` varchar(255) NOT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`task_id`) +) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tasks_old_backup` +-- + +LOCK TABLES `tasks_old_backup` WRITE; +/*!40000 ALTER TABLE `tasks_old_backup` DISABLE KEYS */; +INSERT INTO `tasks_old_backup` VALUES +(1,'Base','Fabrication','용접','...','2025-04-15 10:41:43','2025-04-15 10:41:43'), +(3,'Vessel','MI and Marking','Marking','..','2025-04-15 22:25:58','2025-04-15 22:25:58'), +(4,'Vessel','Cutting','자재 커팅','..','2025-04-15 22:26:17','2025-04-15 22:26:17'), +(5,'Vessel','Fabrication','용접','..','2025-04-15 22:26:43','2025-04-15 22:26:43'), +(7,'PKG','Pipe Pre-Fabrication','취부&용접','배관사 1명\n용접사 1명','2025-04-15 22:37:14','2025-04-15 22:37:14'), +(8,'PKG','1st Piping Assembly','1차 조립','.','2025-04-15 22:38:49','2025-04-15 22:38:49'), +(9,'PKG','Re-Assembly','재조립','.','2025-04-15 22:39:18','2025-04-15 22:39:18'), +(13,'작업지원','구매팀','.','.','2025-04-16 03:03:40','2025-04-16 03:03:40'), +(14,'기타','시설설비제작','.','.','2025-04-16 03:30:53','2025-04-16 03:30:53'), +(15,'기타','휴가/연차/휴무','.','.','2025-04-16 05:18:13','2025-04-16 05:18:13'), +(16,'PKG','제품설치','설치작업','Skid, 용기 등 설치','2025-04-29 04:39:36','2025-04-29 04:39:36'), +(18,'작업지원','품질팀','test지원','.','2025-06-25 07:07:08','2025-06-25 07:07:08'); +/*!40000 ALTER TABLE `tasks_old_backup` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_safety_checks` +-- + +DROP TABLE IF EXISTS `tbm_safety_checks`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_safety_checks` ( + `check_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `check_category` varchar(50) NOT NULL COMMENT '카테고리 (장비, PPE, 환경 등)', + `check_type` enum('basic','weather','task') DEFAULT 'basic', + `weather_condition` varchar(50) DEFAULT NULL, + `task_id` int(10) unsigned DEFAULT NULL, + `check_item` varchar(200) NOT NULL COMMENT '체크 항목', + `description` text DEFAULT NULL COMMENT '설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_required` tinyint(1) DEFAULT 1 COMMENT '필수 체크 여부', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`check_id`), + KEY `tbm_safety_checks_check_category_index` (`check_category`), + KEY `tbm_safety_checks_check_type_index` (`check_type`), + KEY `tbm_safety_checks_weather_condition_index` (`weather_condition`), + KEY `tbm_safety_checks_task_id_index` (`task_id`) +) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_safety_checks` +-- + +LOCK TABLES `tbm_safety_checks` WRITE; +/*!40000 ALTER TABLE `tbm_safety_checks` DISABLE KEYS */; +INSERT INTO `tbm_safety_checks` VALUES +(1,'PPE','basic',NULL,NULL,'안전모 착용 확인',NULL,1,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(2,'PPE','basic',NULL,NULL,'안전화 착용 확인',NULL,2,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(3,'PPE','basic',NULL,NULL,'안전조끼 착용 확인',NULL,3,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(4,'PPE','basic',NULL,NULL,'안전벨트 착용 확인 (고소작업 시)',NULL,4,0,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(5,'PPE','basic',NULL,NULL,'보안경/마스크 착용 확인',NULL,5,0,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(6,'EQUIPMENT','basic',NULL,NULL,'작업 도구 점검 완료',NULL,10,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(7,'EQUIPMENT','basic',NULL,NULL,'전동공구 안전 점검',NULL,11,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(8,'EQUIPMENT','basic',NULL,NULL,'사다리/비계 안전 확인',NULL,12,0,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(9,'EQUIPMENT','basic',NULL,NULL,'차량/중장비 점검 완료',NULL,13,0,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(10,'ENVIRONMENT','basic',NULL,NULL,'작업 장소 정리정돈 확인',NULL,20,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(11,'ENVIRONMENT','basic',NULL,NULL,'위험 구역 표시 확인',NULL,21,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(12,'ENVIRONMENT','basic',NULL,NULL,'기상 상태 확인 (우천, 강풍 등)',NULL,22,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(13,'ENVIRONMENT','basic',NULL,NULL,'작업 동선 안전 확인',NULL,23,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(14,'EMERGENCY','basic',NULL,NULL,'비상연락망 공유 완료',NULL,30,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(15,'EMERGENCY','basic',NULL,NULL,'소화기 위치 확인',NULL,31,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(16,'EMERGENCY','basic',NULL,NULL,'응급처치 키트 위치 확인',NULL,32,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(17,'WEATHER','weather','rain',NULL,'우의/우산 준비 확인','비 오는 날 우의 또는 우산 준비 여부',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(18,'WEATHER','weather','rain',NULL,'미끄럼 방지 조치 확인','빗물로 인한 미끄러움 방지 조치',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(19,'WEATHER','weather','rain',NULL,'전기 작업 중단 여부 확인','우천 시 전기 작업 중단 필요성 확인',3,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(20,'WEATHER','weather','rain',NULL,'배수 상태 확인','작업장 배수 상태 점검',4,0,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(21,'WEATHER','weather','snow',NULL,'제설 작업 완료 확인','작업장 주변 제설 작업 완료 여부',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(22,'WEATHER','weather','snow',NULL,'동파 방지 조치 확인','배관 및 설비 동파 방지 조치',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(23,'WEATHER','weather','snow',NULL,'미끄럼 방지 모래/염화칼슘 비치','미끄럼 방지를 위한 모래 또는 염화칼슘 비치',3,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(24,'WEATHER','weather','heat',NULL,'그늘막/휴게소 확보','무더위 휴식을 위한 그늘막 또는 휴게소 확보',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(25,'WEATHER','weather','heat',NULL,'음료수/식염 포도당 비치','열사병 예방을 위한 음료수 및 염분 보충제 비치',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(26,'WEATHER','weather','heat',NULL,'무더위 휴식 시간 확보','10~15시 사이 충분한 휴식 시간 확보',3,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(27,'WEATHER','weather','heat',NULL,'작업자 건강 상태 확인','열사병 증상 체크 및 건강 상태 확인',4,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(28,'WEATHER','weather','cold',NULL,'방한복/방한장갑 착용 확인','동상 방지를 위한 방한복 및 방한장갑 착용',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(29,'WEATHER','weather','cold',NULL,'난방시설 가동 확인','휴게 공간 난방시설 가동 상태 확인',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(30,'WEATHER','weather','cold',NULL,'온열 음료 비치','체온 유지를 위한 따뜻한 음료 비치',3,0,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(31,'WEATHER','weather','wind',NULL,'고소 작업 중단 여부 확인','강풍 시 고소 작업 중단 필요성 확인',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(32,'WEATHER','weather','wind',NULL,'자재/장비 결박 확인','바람에 날릴 수 있는 자재 및 장비 고정',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(33,'WEATHER','weather','wind',NULL,'가설물 안전 점검','가설 구조물 및 비계 안전 상태 점검',3,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(34,'WEATHER','weather','wind',NULL,'크레인 작업 중단 여부 확인','강풍 시 크레인 작업 중단 필요성 확인',4,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(35,'WEATHER','weather','fog',NULL,'경광등/조명 확보','시정 확보를 위한 경광등 및 조명 설치',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(36,'WEATHER','weather','fog',NULL,'차량 운행 주의 안내','안개로 인한 차량 운행 주의 안내',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(37,'WEATHER','weather','fog',NULL,'작업 구역 표시 강화','시인성 확보를 위한 작업 구역 표시 강화',3,0,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(38,'WEATHER','weather','dust',NULL,'보호 마스크 착용 확인','KF94 이상 마스크 착용 여부 확인',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(39,'WEATHER','weather','dust',NULL,'실외 작업 시간 조정','미세먼지 농도에 따른 실외 작업 시간 조정',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(40,'WEATHER','weather','dust',NULL,'호흡기 질환자 실내 배치','호흡기 질환 작업자 실내 작업 배치',3,0,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'); +/*!40000 ALTER TABLE `tbm_safety_checks` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_safety_records` +-- + +DROP TABLE IF EXISTS `tbm_safety_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_safety_records` ( + `record_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL COMMENT 'TBM 세션 ID', + `check_id` int(10) unsigned NOT NULL COMMENT '체크 항목 ID', + `is_checked` tinyint(1) DEFAULT 0 COMMENT '체크 여부', + `notes` text DEFAULT NULL COMMENT '비고/특이사항', + `checked_by` int(11) DEFAULT NULL COMMENT '체크한 user_id', + `checked_at` timestamp NULL DEFAULT NULL COMMENT '체크 시간', + PRIMARY KEY (`record_id`), + UNIQUE KEY `tbm_safety_records_session_id_check_id_unique` (`session_id`,`check_id`), + KEY `tbm_safety_records_check_id_foreign` (`check_id`), + KEY `tbm_safety_records_checked_by_foreign` (`checked_by`), + CONSTRAINT `tbm_safety_records_check_id_foreign` FOREIGN KEY (`check_id`) REFERENCES `tbm_safety_checks` (`check_id`), + CONSTRAINT `tbm_safety_records_checked_by_foreign` FOREIGN KEY (`checked_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `tbm_safety_records_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_safety_records` +-- + +LOCK TABLES `tbm_safety_records` WRITE; +/*!40000 ALTER TABLE `tbm_safety_records` DISABLE KEYS */; +/*!40000 ALTER TABLE `tbm_safety_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_sessions` +-- + +DROP TABLE IF EXISTS `tbm_sessions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_sessions` ( + `session_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_date` date NOT NULL COMMENT 'TBM 날짜', + `leader_id` int(11) DEFAULT NULL, + `project_id` int(11) DEFAULT NULL COMMENT '프로젝트 ID', + `work_location` varchar(200) DEFAULT NULL COMMENT '작업 장소', + `status` enum('draft','completed','cancelled') DEFAULT 'draft' COMMENT '상태', + `end_time` time DEFAULT NULL COMMENT 'TBM 종료 시간', + `created_by` int(11) NOT NULL COMMENT '생성자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `work_type_id` int(11) DEFAULT NULL COMMENT '공정 ID (work_types 참조)', + `task_id` int(10) unsigned DEFAULT NULL COMMENT '작업 ID (tasks 참조)', + PRIMARY KEY (`session_id`), + KEY `tbm_sessions_session_date_leader_id_index` (`session_date`,`leader_id`), + KEY `tbm_sessions_project_id_foreign` (`project_id`), + KEY `tbm_sessions_created_by_foreign` (`created_by`), + KEY `tbm_sessions_work_type_id_index` (`work_type_id`), + KEY `tbm_sessions_task_id_index` (`task_id`), + KEY `tbm_sessions_leader_id_foreign` (`leader_id`), + CONSTRAINT `tbm_sessions_created_by_foreign` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `tbm_sessions_leader_id_foreign` FOREIGN KEY (`leader_id`) REFERENCES `workers` (`worker_id`) ON DELETE SET NULL, + CONSTRAINT `tbm_sessions_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE SET NULL, + CONSTRAINT `tbm_sessions_task_id_foreign` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`task_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_sessions_work_type_id_foreign` FOREIGN KEY (`work_type_id`) REFERENCES `work_types` (`id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_sessions` +-- + +LOCK TABLES `tbm_sessions` WRITE; +/*!40000 ALTER TABLE `tbm_sessions` DISABLE KEYS */; +/*!40000 ALTER TABLE `tbm_sessions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_team_assignments` +-- + +DROP TABLE IF EXISTS `tbm_team_assignments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_team_assignments` ( + `assignment_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL COMMENT 'TBM 세션 ID', + `worker_id` int(11) NOT NULL COMMENT '팀원 worker_id', + `assigned_role` varchar(100) DEFAULT NULL COMMENT '역할/담당', + `work_detail` text DEFAULT NULL COMMENT '세부 작업 내용', + `is_present` tinyint(1) DEFAULT 1 COMMENT '출석 여부', + `absence_reason` text DEFAULT NULL COMMENT '결석 사유', + `assigned_at` timestamp NOT NULL DEFAULT current_timestamp(), + `project_id` int(11) DEFAULT NULL COMMENT '작업자별 프로젝트 ID', + `work_type_id` int(11) DEFAULT NULL COMMENT '작업자별 공정 ID', + `task_id` int(10) unsigned DEFAULT NULL COMMENT '작업자별 작업 ID', + `workplace_category_id` int(10) unsigned DEFAULT NULL COMMENT '작업자별 작업장 대분류 (공장)', + `workplace_id` int(10) unsigned DEFAULT NULL COMMENT '작업자별 작업장 ID', + PRIMARY KEY (`assignment_id`), + UNIQUE KEY `tbm_team_assignments_session_id_worker_id_unique` (`session_id`,`worker_id`), + KEY `tbm_team_assignments_worker_id_foreign` (`worker_id`), + KEY `tbm_team_assignments_project_id_foreign` (`project_id`), + KEY `tbm_team_assignments_work_type_id_foreign` (`work_type_id`), + KEY `tbm_team_assignments_task_id_foreign` (`task_id`), + KEY `tbm_team_assignments_workplace_category_id_foreign` (`workplace_category_id`), + KEY `tbm_team_assignments_workplace_id_foreign` (`workplace_id`), + CONSTRAINT `tbm_team_assignments_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_team_assignments_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE, + CONSTRAINT `tbm_team_assignments_task_id_foreign` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`task_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_team_assignments_work_type_id_foreign` FOREIGN KEY (`work_type_id`) REFERENCES `work_types` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_team_assignments_worker_id_foreign` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `tbm_team_assignments_workplace_category_id_foreign` FOREIGN KEY (`workplace_category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_team_assignments_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_team_assignments` +-- + +LOCK TABLES `tbm_team_assignments` WRITE; +/*!40000 ALTER TABLE `tbm_team_assignments` DISABLE KEYS */; +/*!40000 ALTER TABLE `tbm_team_assignments` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_weather_records` +-- + +DROP TABLE IF EXISTS `tbm_weather_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_weather_records` ( + `record_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL, + `weather_date` date NOT NULL, + `temperature` decimal(4,1) DEFAULT NULL, + `humidity` int(11) DEFAULT NULL, + `wind_speed` decimal(4,1) DEFAULT NULL, + `precipitation` decimal(5,1) DEFAULT NULL, + `sky_condition` varchar(50) DEFAULT NULL, + `weather_condition` varchar(50) DEFAULT NULL, + `weather_conditions` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`weather_conditions`)), + `data_source` varchar(50) DEFAULT 'api', + `fetched_at` timestamp NULL DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`record_id`), + UNIQUE KEY `tbm_weather_records_session_id_unique` (`session_id`), + KEY `tbm_weather_records_weather_date_index` (`weather_date`), + CONSTRAINT `tbm_weather_records_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_weather_records` +-- + +LOCK TABLES `tbm_weather_records` WRITE; +/*!40000 ALTER TABLE `tbm_weather_records` DISABLE KEYS */; +INSERT INTO `tbm_weather_records` VALUES +(1,12,'2026-02-02',20.0,50,2.0,0.0,NULL,'clear','[\"clear\"]','api','2026-02-02 04:00:40','2026-02-02 04:00:40'); +/*!40000 ALTER TABLE `tbm_weather_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `team_handovers` +-- + +DROP TABLE IF EXISTS `team_handovers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `team_handovers` ( + `handover_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL COMMENT 'TBM 세션 ID', + `from_leader_id` int(11) NOT NULL COMMENT '인계자 worker_id', + `to_leader_id` int(11) NOT NULL COMMENT '인수자 worker_id', + `handover_date` date NOT NULL COMMENT '인계 날짜', + `handover_time` time DEFAULT NULL COMMENT '인계 시간', + `reason` enum('half_day','early_leave','emergency','other') NOT NULL COMMENT '인계 사유', + `handover_notes` text DEFAULT NULL COMMENT '인계 내용', + `worker_ids` text DEFAULT NULL COMMENT '인계하는 작업자 IDs (JSON array)', + `is_confirmed` tinyint(1) DEFAULT 0 COMMENT '인수 확인 여부', + `confirmed_at` timestamp NULL DEFAULT NULL COMMENT '인수 확인 시간', + `confirmed_by` int(11) DEFAULT NULL COMMENT '인수 확인자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`handover_id`), + KEY `team_handovers_session_id_handover_date_index` (`session_id`,`handover_date`), + KEY `team_handovers_from_leader_id_foreign` (`from_leader_id`), + KEY `team_handovers_to_leader_id_foreign` (`to_leader_id`), + KEY `team_handovers_confirmed_by_foreign` (`confirmed_by`), + CONSTRAINT `team_handovers_confirmed_by_foreign` FOREIGN KEY (`confirmed_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `team_handovers_from_leader_id_foreign` FOREIGN KEY (`from_leader_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `team_handovers_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE, + CONSTRAINT `team_handovers_to_leader_id_foreign` FOREIGN KEY (`to_leader_id`) REFERENCES `workers` (`worker_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `team_handovers` +-- + +LOCK TABLES `team_handovers` WRITE; +/*!40000 ALTER TABLE `team_handovers` DISABLE KEYS */; +/*!40000 ALTER TABLE `team_handovers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `uploaded_documents` +-- + +DROP TABLE IF EXISTS `uploaded_documents`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `uploaded_documents` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `title` varchar(255) NOT NULL, + `tags` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `original_name` varchar(255) DEFAULT NULL, + `stored_name` varchar(255) NOT NULL, + `file_path` varchar(500) DEFAULT NULL, + `file_type` varchar(50) DEFAULT NULL, + `file_size` int(11) DEFAULT NULL, + `submitted_by` varchar(100) DEFAULT NULL, + `dt_imported` tinyint(1) DEFAULT 0, + `dt_uuid` varchar(100) DEFAULT NULL, + `of_task_created` tinyint(1) DEFAULT 0, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `uploaded_documents` +-- + +LOCK TABLES `uploaded_documents` WRITE; +/*!40000 ALTER TABLE `uploaded_documents` DISABLE KEYS */; +/*!40000 ALTER TABLE `uploaded_documents` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user_page_access` +-- + +DROP TABLE IF EXISTS `user_page_access`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user_page_access` ( + `user_id` int(11) NOT NULL, + `page_id` int(10) unsigned NOT NULL, + `can_access` tinyint(1) DEFAULT 1, + `granted_at` timestamp NOT NULL DEFAULT current_timestamp(), + `granted_by` int(11) DEFAULT NULL, + PRIMARY KEY (`user_id`,`page_id`), + KEY `user_page_access_page_id_foreign` (`page_id`), + KEY `user_page_access_granted_by_foreign` (`granted_by`), + CONSTRAINT `user_page_access_granted_by_foreign` FOREIGN KEY (`granted_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, + CONSTRAINT `user_page_access_page_id_foreign` FOREIGN KEY (`page_id`) REFERENCES `pages` (`id`) ON DELETE CASCADE, + CONSTRAINT `user_page_access_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user_page_access` +-- + +LOCK TABLES `user_page_access` WRITE; +/*!40000 ALTER TABLE `user_page_access` DISABLE KEYS */; +INSERT INTO `user_page_access` VALUES +(1,26,1,'2026-01-28 05:55:06',1), +(1,27,1,'2026-01-28 05:55:06',1), +(1,29,1,'2026-01-28 05:55:06',1), +(27,12,1,'2026-02-02 01:01:57',NULL), +(27,13,1,'2026-02-02 01:01:57',NULL), +(27,14,0,'2026-02-02 01:01:57',NULL), +(27,15,0,'2026-02-02 01:01:57',NULL), +(27,16,0,'2026-02-02 01:01:57',NULL), +(27,18,0,'2026-02-02 01:01:57',NULL), +(27,19,0,'2026-02-02 01:01:57',NULL), +(27,20,0,'2026-02-02 01:01:57',NULL), +(27,21,0,'2026-02-02 01:01:57',NULL), +(27,22,1,'2026-02-02 01:01:57',NULL), +(27,25,0,'2026-02-02 01:01:57',NULL), +(27,26,0,'2026-02-02 01:01:57',NULL), +(27,27,0,'2026-02-02 01:01:57',NULL), +(27,29,0,'2026-02-02 01:01:57',NULL), +(27,34,0,'2026-02-02 01:01:57',NULL), +(27,35,0,'2026-02-02 01:01:57',NULL), +(27,36,0,'2026-02-02 01:01:57',NULL), +(27,37,0,'2026-02-02 01:01:57',NULL), +(27,38,0,'2026-02-02 01:01:57',NULL), +(27,39,0,'2026-02-02 01:01:57',NULL), +(27,40,0,'2026-02-02 01:01:57',NULL), +(27,41,0,'2026-02-02 01:01:57',NULL), +(27,42,0,'2026-02-02 01:01:57',NULL), +(27,43,0,'2026-02-02 01:01:57',NULL); +/*!40000 ALTER TABLE `user_page_access` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user_permissions` +-- + +DROP TABLE IF EXISTS `user_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user_permissions` ( + `user_id` int(10) unsigned NOT NULL, + `permission_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`user_id`,`permission_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user_permissions` +-- + +LOCK TABLES `user_permissions` WRITE; +/*!40000 ALTER TABLE `user_permissions` DISABLE KEYS */; +/*!40000 ALTER TABLE `user_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `users` +-- + +DROP TABLE IF EXISTS `users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `users` ( + `user_id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(100) NOT NULL, + `password` varchar(255) NOT NULL, + `_role_old` varchar(30) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `_access_level_old` varchar(30) DEFAULT NULL, + `worker_id` int(11) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `last_login_at` datetime DEFAULT NULL, + `password_changed_at` datetime DEFAULT NULL, + `failed_login_attempts` int(11) DEFAULT 0, + `locked_until` datetime DEFAULT NULL, + `name` varchar(50) DEFAULT NULL, + `email` varchar(255) DEFAULT NULL, + `role_id` int(10) unsigned DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`user_id`), + UNIQUE KEY `username` (`username`), + UNIQUE KEY `email` (`email`), + KEY `fk_worker` (`worker_id`), + KEY `idx_username` (`username`), + KEY `idx_active_users` (`is_active`,`_access_level_old`), + KEY `users_role_id_foreign` (`role_id`), + CONSTRAINT `fk_worker` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `users_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `users` +-- + +LOCK TABLES `users` WRITE; +/*!40000 ALTER TABLE `users` DISABLE KEYS */; +INSERT INTO `users` VALUES +(1,'hyungi','$2b$10$lwSfKipx0fQ.9nfMUBmzt.WXzerdxuT5MVX4b3YhFeHxyYlUjM7bi',NULL,'2025-05-06 05:03:02','system',NULL,1,'2026-02-05 22:40:53','2025-05-06 05:03:02',0,NULL,'안현기',NULL,2,'2026-02-05 22:40:53'), +(3,'김두수','$2a$10$z3i2EVOotRFBj.KHzx5LQOKlXD0QHLNFEvJcd6FlO6/1TCYGk6SSu',NULL,'2025-06-07 23:48:35',NULL,1,1,'2026-02-03 05:43:08','2025-06-15 07:40:39',0,NULL,'김두수',NULL,4,'2026-02-03 21:44:25'), +(5,'임영규','$2a$10$66ps/MEEi4BVABfJc5P0y.yCap09NhTMyd1A/7rFVxESytQGlB3wC',NULL,'2025-06-15 07:41:02',NULL,2,1,'2025-12-10 15:55:48','2025-06-15 07:41:02',0,NULL,'임영규',NULL,4,'2026-02-03 21:44:32'), +(6,'반치원','$2a$10$jcn6f7flRLZlr5yKQcXDIePodRK0rsM4deNnNGjuOlredeTVsRYZ6',NULL,'2025-06-15 07:41:32',NULL,3,1,'2025-11-05 01:56:13','2025-06-15 07:41:32',5,'2025-11-25 16:22:46','반치원',NULL,4,'2026-02-03 21:44:36'), +(7,'khahn','$2a$10$vQcJ3C37TPGweYF8rok2quzN2DK9lgxiqDAXV38vvPVjRdz3l6M8y',NULL,'2025-11-05 02:18:15',NULL,NULL,1,'2025-11-05 15:56:23',NULL,0,NULL,'khahn',NULL,2,'2025-11-05 06:56:23'); +/*!40000 ALTER TABLE `users` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vacation_balance_details` +-- + +DROP TABLE IF EXISTS `vacation_balance_details`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vacation_balance_details` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `vacation_type_id` int(10) unsigned NOT NULL COMMENT '휴가 유형 ID', + `year` int(11) NOT NULL COMMENT '연도', + `total_days` decimal(4,1) DEFAULT 0.0 COMMENT '총 발생 일수', + `used_days` decimal(4,1) DEFAULT 0.0 COMMENT '사용 일수', + `notes` text DEFAULT NULL COMMENT '비고', + `created_by` int(11) NOT NULL COMMENT '생성자 ID', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `remaining_days` decimal(4,1) GENERATED ALWAYS AS (`total_days` - `used_days`) STORED COMMENT '잔여 일수', + PRIMARY KEY (`id`), + UNIQUE KEY `unique_worker_vacation_year` (`worker_id`,`vacation_type_id`,`year`), + KEY `idx_worker_year` (`worker_id`,`year`), + KEY `idx_vacation_type` (`vacation_type_id`), + KEY `vacation_balance_details_created_by_foreign` (`created_by`), + CONSTRAINT `vacation_balance_details_created_by_foreign` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `vacation_balance_details_vacation_type_id_foreign` FOREIGN KEY (`vacation_type_id`) REFERENCES `vacation_types` (`id`), + CONSTRAINT `vacation_balance_details_worker_id_foreign` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vacation_balance_details` +-- + +LOCK TABLES `vacation_balance_details` WRITE; +/*!40000 ALTER TABLE `vacation_balance_details` DISABLE KEYS */; +INSERT INTO `vacation_balance_details` VALUES +(1,1,1,2026,17.0,0.0,NULL,1,'2026-01-19 01:40:31','2026-02-05 06:17:09',17.0), +(2,2,1,2026,17.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',17.0), +(3,4,1,2026,17.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',17.0), +(4,5,1,2026,16.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',16.0), +(5,6,1,2026,17.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',17.0), +(6,7,1,2026,15.0,0.0,'Migrated from worker_vacation_balance',1,'2026-01-19 01:40:56','2026-01-19 01:40:56',15.0), +(7,8,1,2026,16.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',16.0), +(8,9,1,2026,15.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',15.0), +(9,10,1,2026,15.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',15.0), +(10,12,1,2026,15.0,0.0,'Migrated from worker_vacation_balance',1,'2026-01-19 01:40:56','2026-01-19 01:40:56',15.0), +(14,3,1,2026,16.0,0.0,NULL,1,'2026-02-05 06:12:39','2026-02-05 06:17:09',16.0), +(16,11,1,2026,11.0,0.0,NULL,1,'2026-02-05 06:12:39','2026-02-05 06:17:09',11.0), +(31,1,6,2026,2.3,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',2.3), +(33,1,7,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0), +(34,6,6,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0), +(36,6,7,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0), +(37,9,6,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(39,9,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(40,3,6,2026,1.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',1.0), +(42,3,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(43,2,6,2026,1.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',1.0), +(45,2,7,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0), +(46,11,6,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(48,11,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(49,10,6,2026,-0.8,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',-0.8), +(51,10,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(52,8,6,2026,2.3,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',2.3), +(54,8,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(55,5,6,2026,2.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',2.0), +(57,5,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(58,4,6,2026,0.8,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.8), +(60,4,7,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0); +/*!40000 ALTER TABLE `vacation_balance_details` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vacation_requests` +-- + +DROP TABLE IF EXISTS `vacation_requests`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vacation_requests` ( + `request_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '휴가 신청 ID', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `vacation_type_id` int(10) unsigned NOT NULL COMMENT '휴가 유형 ID', + `start_date` date NOT NULL COMMENT '휴가 시작일', + `end_date` date NOT NULL COMMENT '휴가 종료일', + `days_used` decimal(4,1) NOT NULL COMMENT '사용 일수 (0.5일 단위)', + `reason` text DEFAULT NULL COMMENT '휴가 사유', + `status` enum('pending','approved','rejected') NOT NULL DEFAULT 'pending' COMMENT '승인 상태: pending(대기), approved(승인), rejected(거부)', + `requested_by` int(11) NOT NULL COMMENT '신청자 user_id', + `reviewed_by` int(11) DEFAULT NULL COMMENT '승인/거부자 user_id', + `reviewed_at` timestamp NULL DEFAULT NULL COMMENT '승인/거부 일시', + `review_note` text DEFAULT NULL COMMENT '승인/거부 메모', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '신청 일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정 일시', + PRIMARY KEY (`request_id`), + KEY `vacation_requests_vacation_type_id_foreign` (`vacation_type_id`), + KEY `vacation_requests_requested_by_foreign` (`requested_by`), + KEY `vacation_requests_reviewed_by_foreign` (`reviewed_by`), + KEY `idx_vacation_requests_worker` (`worker_id`), + KEY `idx_vacation_requests_status` (`status`), + KEY `idx_vacation_requests_dates` (`start_date`,`end_date`), + CONSTRAINT `vacation_requests_requested_by_foreign` FOREIGN KEY (`requested_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `vacation_requests_reviewed_by_foreign` FOREIGN KEY (`reviewed_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, + CONSTRAINT `vacation_requests_vacation_type_id_foreign` FOREIGN KEY (`vacation_type_id`) REFERENCES `vacation_types` (`id`), + CONSTRAINT `vacation_requests_worker_id_foreign` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vacation_requests` +-- + +LOCK TABLES `vacation_requests` WRITE; +/*!40000 ALTER TABLE `vacation_requests` DISABLE KEYS */; +/*!40000 ALTER TABLE `vacation_requests` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vacation_types` +-- + +DROP TABLE IF EXISTS `vacation_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vacation_types` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `type_code` varchar(20) NOT NULL COMMENT '휴가 코드', + `type_name` varchar(50) NOT NULL COMMENT '휴가 이름', + `deduct_days` decimal(3,1) DEFAULT 1.0 COMMENT '차감 일수', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `is_special` tinyint(1) DEFAULT 0 COMMENT '특별 휴가 여부 (장기근속, 출산 등)', + `priority` int(11) DEFAULT 99 COMMENT '차감 우선순위 (낮을수록 먼저 차감)', + `description` text DEFAULT NULL COMMENT '휴가 설명', + `is_system` tinyint(1) DEFAULT 1 COMMENT '시스템 기본 휴가 (삭제 불가)', + PRIMARY KEY (`id`), + UNIQUE KEY `vacation_types_type_code_unique` (`type_code`) +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vacation_types` +-- + +LOCK TABLES `vacation_types` WRITE; +/*!40000 ALTER TABLE `vacation_types` DISABLE KEYS */; +INSERT INTO `vacation_types` VALUES +(1,'ANNUAL_FULL','연차',1.0,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,1,'하루 전체 연차',1), +(2,'ANNUAL_HALF','반차',0.5,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,2,'반일 연차',1), +(3,'ANNUAL_QUARTER','반반차',0.3,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,3,'1/4일 연차',1), +(4,'SICK_FULL','병가',1.0,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,4,'하루 전체 병가',1), +(5,'SICK_HALF','반일병가',0.5,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,5,'반일 병가',1), +(6,'CARRYOVER','이월',1.0,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',1,1,NULL,0), +(7,'LONG_SERVICE','장기근속',1.0,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',1,3,NULL,0); +/*!40000 ALTER TABLE `vacation_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `visit_purpose_types` +-- + +DROP TABLE IF EXISTS `visit_purpose_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `visit_purpose_types` ( + `purpose_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '방문 목적 ID', + `purpose_name` varchar(100) NOT NULL COMMENT '방문 목적명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`purpose_id`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `visit_purpose_types` +-- + +LOCK TABLES `visit_purpose_types` WRITE; +/*!40000 ALTER TABLE `visit_purpose_types` DISABLE KEYS */; +INSERT INTO `visit_purpose_types` VALUES +(1,'외주작업',1,1,'2026-01-29 05:26:17'), +(2,'검사',2,1,'2026-01-29 05:26:17'), +(3,'견학',3,1,'2026-01-29 05:26:17'), +(4,'기타',99,1,'2026-01-29 05:26:17'); +/*!40000 ALTER TABLE `visit_purpose_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `weather_conditions` +-- + +DROP TABLE IF EXISTS `weather_conditions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `weather_conditions` ( + `condition_code` varchar(50) NOT NULL, + `condition_name` varchar(100) NOT NULL, + `description` text DEFAULT NULL, + `icon` varchar(50) DEFAULT NULL, + `temp_threshold_min` decimal(4,1) DEFAULT NULL, + `temp_threshold_max` decimal(4,1) DEFAULT NULL, + `wind_threshold` decimal(4,1) DEFAULT NULL, + `precip_threshold` decimal(5,1) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `display_order` int(11) DEFAULT 0, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`condition_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `weather_conditions` +-- + +LOCK TABLES `weather_conditions` WRITE; +/*!40000 ALTER TABLE `weather_conditions` DISABLE KEYS */; +INSERT INTO `weather_conditions` VALUES +('clear','맑음','맑은 날씨','sunny',NULL,NULL,NULL,NULL,1,1,'2026-02-02 01:44:54'), +('cold','한파','기온 영하 10도 이하','cold',NULL,-10.0,NULL,NULL,1,5,'2026-02-02 01:44:54'), +('dust','미세먼지','미세먼지 나쁨 이상','dusty',NULL,NULL,NULL,NULL,1,8,'2026-02-02 01:44:54'), +('fog','안개','시정 1km 미만','foggy',NULL,NULL,NULL,NULL,1,7,'2026-02-02 01:44:54'), +('heat','폭염','기온 35도 이상','hot',35.0,NULL,NULL,NULL,1,4,'2026-02-02 01:44:54'), +('rain','비','비 오는 날씨','rainy',NULL,NULL,NULL,0.1,1,2,'2026-02-02 01:44:54'), +('snow','눈','눈 오는 날씨','snowy',NULL,NULL,NULL,NULL,1,3,'2026-02-02 01:44:54'), +('wind','강풍','풍속 10m/s 이상','windy',NULL,NULL,10.0,NULL,1,6,'2026-02-02 01:44:54'); +/*!40000 ALTER TABLE `weather_conditions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_attendance_types` +-- + +DROP TABLE IF EXISTS `work_attendance_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_attendance_types` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `type_code` varchar(20) NOT NULL COMMENT '유형 코드', + `type_name` varchar(50) NOT NULL COMMENT '유형 이름', + `description` text DEFAULT NULL COMMENT '설명', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `work_attendance_types_type_code_unique` (`type_code`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_attendance_types` +-- + +LOCK TABLES `work_attendance_types` WRITE; +/*!40000 ALTER TABLE `work_attendance_types` DISABLE KEYS */; +INSERT INTO `work_attendance_types` VALUES +(1,'REGULAR','정시근로','8시간 정규 근무',1,'2025-11-03 06:48:45','2025-11-03 06:48:45'), +(2,'OVERTIME','연장근로','8시간 초과 근무',1,'2025-11-03 06:48:45','2025-11-03 06:48:45'), +(3,'PARTIAL','부분근로','8시간 미만 근무',1,'2025-11-03 06:48:45','2025-11-03 06:48:45'), +(4,'VACATION','휴가근로','휴가와 함께하는 부분 근무',1,'2025-11-03 06:48:45','2025-11-03 06:48:45'); +/*!40000 ALTER TABLE `work_attendance_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_issue_reports` +-- + +DROP TABLE IF EXISTS `work_issue_reports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_issue_reports` ( + `report_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '신고 ID', + `reporter_id` int(11) NOT NULL COMMENT '신고자 user_id', + `report_date` datetime DEFAULT current_timestamp() COMMENT '신고 일시', + `factory_category_id` int(10) unsigned DEFAULT NULL COMMENT '공장 카테고리 ID (지도 외 위치 시 null)', + `workplace_id` int(10) unsigned DEFAULT NULL COMMENT '작업장 ID (지도 외 위치 시 null)', + `custom_location` varchar(200) DEFAULT NULL COMMENT '기타 위치 (지도 외 선택 시)', + `tbm_session_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 TBM 세션', + `visit_request_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 출입 신청', + `equipment_id` int(10) unsigned DEFAULT NULL COMMENT '관련 설비 ID', + `issue_category_id` int(10) unsigned NOT NULL COMMENT '신고 카테고리 ID', + `issue_item_id` int(10) unsigned DEFAULT NULL COMMENT '사전 정의 신고 항목 ID', + `additional_description` text DEFAULT NULL COMMENT '추가 설명', + `photo_path1` varchar(255) DEFAULT NULL COMMENT '사진 1', + `photo_path2` varchar(255) DEFAULT NULL COMMENT '사진 2', + `photo_path3` varchar(255) DEFAULT NULL COMMENT '사진 3', + `photo_path4` varchar(255) DEFAULT NULL COMMENT '사진 4', + `photo_path5` varchar(255) DEFAULT NULL COMMENT '사진 5', + `status` enum('reported','received','in_progress','completed','closed') DEFAULT 'reported' COMMENT '상태: 신고→접수→처리중→완료→종료', + `assigned_department` varchar(100) DEFAULT NULL COMMENT '담당 부서', + `assigned_user_id` int(11) DEFAULT NULL COMMENT '담당자 user_id', + `assigned_at` datetime DEFAULT NULL COMMENT '배정 일시', + `assigned_by` int(11) DEFAULT NULL COMMENT '배정자 user_id', + `resolution_notes` text DEFAULT NULL COMMENT '처리 내용', + `resolution_photo_path1` varchar(255) DEFAULT NULL COMMENT '처리 완료 사진 1', + `resolution_photo_path2` varchar(255) DEFAULT NULL COMMENT '처리 완료 사진 2', + `resolved_at` datetime DEFAULT NULL COMMENT '처리 완료 일시', + `resolved_by` int(11) DEFAULT NULL COMMENT '처리 완료자 user_id', + `modification_history` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '수정 이력 추적' CHECK (json_valid(`modification_history`)), + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`report_id`), + KEY `work_issue_reports_workplace_id_foreign` (`workplace_id`), + KEY `work_issue_reports_issue_item_id_foreign` (`issue_item_id`), + KEY `work_issue_reports_assigned_by_foreign` (`assigned_by`), + KEY `work_issue_reports_resolved_by_foreign` (`resolved_by`), + KEY `idx_wir_reporter_id` (`reporter_id`), + KEY `idx_wir_status` (`status`), + KEY `idx_wir_report_date` (`report_date`), + KEY `idx_wir_workplace` (`factory_category_id`,`workplace_id`), + KEY `idx_wir_issue_category` (`issue_category_id`), + KEY `idx_wir_assigned_user` (`assigned_user_id`), + KEY `idx_wir_equipment_id` (`equipment_id`), + CONSTRAINT `fk_wir_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipments` (`equipment_id`) ON DELETE SET NULL, + CONSTRAINT `work_issue_reports_assigned_by_foreign` FOREIGN KEY (`assigned_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_assigned_user_id_foreign` FOREIGN KEY (`assigned_user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_factory_category_id_foreign` FOREIGN KEY (`factory_category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_issue_category_id_foreign` FOREIGN KEY (`issue_category_id`) REFERENCES `issue_report_categories` (`category_id`) ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_issue_item_id_foreign` FOREIGN KEY (`issue_item_id`) REFERENCES `issue_report_items` (`item_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_reporter_id_foreign` FOREIGN KEY (`reporter_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_resolved_by_foreign` FOREIGN KEY (`resolved_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_issue_reports` +-- + +LOCK TABLES `work_issue_reports` WRITE; +/*!40000 ALTER TABLE `work_issue_reports` DISABLE KEYS */; +INSERT INTO `work_issue_reports` VALUES +(7,1,'2026-02-04 05:35:54',NULL,2,NULL,NULL,NULL,18,11,38,'전원인 안들어옴(Test)',NULL,NULL,NULL,NULL,NULL,'reported',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'2026-02-04 05:35:54','2026-02-04 05:35:54'); +/*!40000 ALTER TABLE `work_issue_reports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_issue_status_logs` +-- + +DROP TABLE IF EXISTS `work_issue_status_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_issue_status_logs` ( + `log_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '로그 ID', + `report_id` int(10) unsigned NOT NULL COMMENT '신고 ID', + `previous_status` varchar(50) DEFAULT NULL COMMENT '이전 상태', + `new_status` varchar(50) NOT NULL COMMENT '새 상태', + `changed_by` int(11) NOT NULL COMMENT '변경자 user_id', + `change_reason` text DEFAULT NULL COMMENT '변경 사유', + `changed_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`log_id`), + KEY `work_issue_status_logs_changed_by_foreign` (`changed_by`), + KEY `idx_wisl_report_id` (`report_id`), + KEY `idx_wisl_changed_at` (`changed_at`), + CONSTRAINT `work_issue_status_logs_changed_by_foreign` FOREIGN KEY (`changed_by`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE, + CONSTRAINT `work_issue_status_logs_report_id_foreign` FOREIGN KEY (`report_id`) REFERENCES `work_issue_reports` (`report_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_issue_status_logs` +-- + +LOCK TABLES `work_issue_status_logs` WRITE; +/*!40000 ALTER TABLE `work_issue_status_logs` DISABLE KEYS */; +INSERT INTO `work_issue_status_logs` VALUES +(1,1,NULL,'reported',1,NULL,'2026-02-02 22:16:33'), +(2,2,NULL,'reported',1,NULL,'2026-02-02 22:44:48'), +(3,3,NULL,'reported',1,NULL,'2026-02-02 23:39:13'), +(4,4,NULL,'reported',1,NULL,'2026-02-03 00:10:10'), +(5,5,NULL,'reported',1,NULL,'2026-02-03 00:10:39'), +(6,6,NULL,'reported',1,NULL,'2026-02-03 00:11:29'); +/*!40000 ALTER TABLE `work_issue_status_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_report_audit_log` +-- + +DROP TABLE IF EXISTS `work_report_audit_log`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_report_audit_log` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `action` enum('ADD_ACCUMULATE','DELETE_SINGLE','UPDATE','DELETE','CREATE','DELETE_BATCH') NOT NULL COMMENT '작업 유형', + `report_id` int(11) DEFAULT NULL COMMENT '관련 보고서 ID', + `old_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 전 값' CHECK (json_valid(`old_values`)), + `new_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 후 값' CHECK (json_valid(`new_values`)), + `changed_by` int(11) NOT NULL COMMENT '변경자 ID', + `change_reason` varchar(500) DEFAULT NULL COMMENT '변경 사유', + `ip_address` varchar(45) DEFAULT NULL COMMENT 'IP 주소', + `user_agent` text DEFAULT NULL COMMENT '사용자 에이전트', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '변경 시간', + PRIMARY KEY (`log_id`), + KEY `idx_action_date` (`action`,`created_at`), + KEY `idx_changed_by` (`changed_by`), + KEY `idx_report_id` (`report_id`) +) ENGINE=InnoDB AUTO_INCREMENT=880 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_report_audit_log` +-- + +LOCK TABLES `work_report_audit_log` WRITE; +/*!40000 ALTER TABLE `work_report_audit_log` DISABLE KEYS */; +INSERT INTO `work_report_audit_log` VALUES +(1,'ADD_ACCUMULATE',12,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 02:56:12'), +(2,'DELETE_SINGLE',12,'{\"worker_name\":\"김두수\",\"project_name\":\"MP7 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-16 03:17:36'), +(3,'DELETE_SINGLE',11,'{\"worker_name\":\"김두수\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-16 03:17:39'), +(4,'DELETE_SINGLE',7,'{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-16 03:17:41'), +(5,'ADD_ACCUMULATE',13,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":1,\"my_total\":\"1.00\",\"grand_total\":1,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"1.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 03:18:37'), +(6,'DELETE_SINGLE',13,'{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-16 03:19:23'), +(7,'ADD_ACCUMULATE',14,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(8,'ADD_ACCUMULATE',15,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(9,'ADD_ACCUMULATE',16,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(10,'ADD_ACCUMULATE',17,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(11,'ADD_ACCUMULATE',18,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(12,'ADD_ACCUMULATE',19,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(13,'ADD_ACCUMULATE',20,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:47'), +(14,'ADD_ACCUMULATE',21,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(15,'ADD_ACCUMULATE',22,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(16,'ADD_ACCUMULATE',23,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(17,'ADD_ACCUMULATE',24,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(18,'ADD_ACCUMULATE',25,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(19,'ADD_ACCUMULATE',26,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(20,'ADD_ACCUMULATE',27,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:07'), +(21,'ADD_ACCUMULATE',28,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:07'), +(22,'ADD_ACCUMULATE',29,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:07'), +(23,'ADD_ACCUMULATE',30,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(24,'ADD_ACCUMULATE',31,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(25,'ADD_ACCUMULATE',32,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(26,'ADD_ACCUMULATE',33,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(27,'ADD_ACCUMULATE',34,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(28,'ADD_ACCUMULATE',35,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(29,'ADD_ACCUMULATE',36,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:13:56'), +(30,'ADD_ACCUMULATE',37,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:13:56'), +(31,'ADD_ACCUMULATE',38,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:13:56'), +(32,'ADD_ACCUMULATE',39,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:13:56'), +(33,'ADD_ACCUMULATE',40,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:12:01'), +(34,'ADD_ACCUMULATE',41,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:12:01'), +(35,'ADD_ACCUMULATE',42,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:12:01'), +(36,'ADD_ACCUMULATE',43,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:12:01'), +(37,'DELETE_SINGLE',42,'{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-16 06:12:33'), +(38,'ADD_ACCUMULATE',44,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:13:02'), +(39,'ADD_ACCUMULATE',45,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:13:50'), +(40,'DELETE_SINGLE',41,'{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-16 06:14:48'), +(41,'ADD_ACCUMULATE',46,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:15:22'), +(42,'DELETE_SINGLE',1,'{\"worker_name\":\"김두수\",\"project_name\":\"25년 안전보건시설설비\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-01T00:00:00.000Z\"}',NULL,1,'개별 항목 삭제',NULL,NULL,'2025-06-16 06:20:38'), +(43,'ADD_ACCUMULATE',48,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 06:46:44'), +(44,'ADD_ACCUMULATE',49,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 06:46:44'), +(45,'ADD_ACCUMULATE',50,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 06:46:44'), +(46,'DELETE_SINGLE',49,'{\"worker_name\":\"박현수\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-16 06:47:54'), +(47,'ADD_ACCUMULATE',51,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 06:48:29'), +(48,'ADD_ACCUMULATE',52,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-16 06:50:09'), +(49,'ADD_ACCUMULATE',54,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-16 06:50:09'), +(50,'ADD_ACCUMULATE',56,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-17 08:23:41'), +(51,'ADD_ACCUMULATE',58,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-17 08:23:41'), +(52,'ADD_ACCUMULATE',60,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-17 08:24:33'), +(53,'ADD_ACCUMULATE',62,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-17 08:24:33'), +(54,'ADD_ACCUMULATE',64,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:24:44'), +(55,'ADD_ACCUMULATE',65,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:25:24'), +(56,'DELETE_SINGLE',64,'{\"worker_name\":\"황인용\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-17T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-17 08:26:17'), +(57,'ADD_ACCUMULATE',66,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:27:06'), +(58,'ADD_ACCUMULATE',67,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:27:06'), +(59,'ADD_ACCUMULATE',68,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:31:06'), +(60,'ADD_ACCUMULATE',69,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:31:06'), +(61,'ADD_ACCUMULATE',70,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:31:06'), +(62,'ADD_ACCUMULATE',71,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:33:06'), +(63,'ADD_ACCUMULATE',72,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:33:06'), +(64,'ADD_ACCUMULATE',73,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:33:06'), +(65,'ADD_ACCUMULATE',74,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-17 08:34:11'), +(66,'ADD_ACCUMULATE',76,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-17 08:34:11'), +(67,'ADD_ACCUMULATE',78,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:40:27'), +(68,'ADD_ACCUMULATE',79,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:40:27'), +(69,'ADD_ACCUMULATE',80,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:40:27'), +(70,'ADD_ACCUMULATE',81,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:41:02'), +(71,'ADD_ACCUMULATE',82,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:41:03'), +(72,'ADD_ACCUMULATE',83,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:41:03'), +(73,'ADD_ACCUMULATE',84,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:41:45'), +(74,'ADD_ACCUMULATE',86,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-18 08:47:55'), +(75,'ADD_ACCUMULATE',88,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-18 08:47:55'), +(76,'ADD_ACCUMULATE',90,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-18 08:50:19'), +(77,'ADD_ACCUMULATE',92,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-18 08:50:19'), +(78,'ADD_ACCUMULATE',94,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-18 08:50:19'), +(79,'ADD_ACCUMULATE',96,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-18 09:00:17'), +(80,'ADD_ACCUMULATE',98,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-19 06:37:59'), +(81,'ADD_ACCUMULATE',99,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-19 06:37:59'), +(82,'ADD_ACCUMULATE',100,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-19 06:59:36'), +(83,'ADD_ACCUMULATE',101,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-19 06:59:36'), +(84,'ADD_ACCUMULATE',102,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-19 06:59:36'), +(85,'ADD_ACCUMULATE',103,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(86,'ADD_ACCUMULATE',105,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(87,'ADD_ACCUMULATE',107,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(88,'ADD_ACCUMULATE',109,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(89,'ADD_ACCUMULATE',111,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(90,'ADD_ACCUMULATE',113,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:01'), +(91,'ADD_ACCUMULATE',115,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:01'), +(92,'ADD_ACCUMULATE',117,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:01'), +(93,'ADD_ACCUMULATE',119,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:02'), +(94,'ADD_ACCUMULATE',121,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:02'), +(95,'ADD_ACCUMULATE',123,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:02'), +(96,'ADD_ACCUMULATE',125,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-20 06:45:30'), +(97,'ADD_ACCUMULATE',126,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-20 06:45:31'), +(98,'ADD_ACCUMULATE',127,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-23 06:42:58'), +(99,'ADD_ACCUMULATE',128,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-23 06:42:58'), +(100,'ADD_ACCUMULATE',129,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(101,'ADD_ACCUMULATE',131,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(102,'ADD_ACCUMULATE',133,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(103,'ADD_ACCUMULATE',135,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(104,'ADD_ACCUMULATE',137,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(105,'ADD_ACCUMULATE',139,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(106,'ADD_ACCUMULATE',141,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-24 11:10:32'), +(107,'ADD_ACCUMULATE',142,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-24 11:10:32'), +(108,'ADD_ACCUMULATE',143,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(109,'ADD_ACCUMULATE',145,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(110,'ADD_ACCUMULATE',147,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(111,'ADD_ACCUMULATE',149,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(112,'ADD_ACCUMULATE',151,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(113,'ADD_ACCUMULATE',153,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(114,'ADD_ACCUMULATE',155,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:05'), +(115,'ADD_ACCUMULATE',157,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:05'), +(116,'ADD_ACCUMULATE',159,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-25 11:08:04'), +(117,'ADD_ACCUMULATE',161,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-25 11:08:05'), +(118,'ADD_ACCUMULATE',163,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-25 11:11:30'), +(119,'ADD_ACCUMULATE',164,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-25 11:11:30'), +(120,'ADD_ACCUMULATE',165,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-25 11:11:30'), +(121,'ADD_ACCUMULATE',166,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-25 11:11:30'), +(122,'ADD_ACCUMULATE',167,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(123,'ADD_ACCUMULATE',168,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(124,'ADD_ACCUMULATE',169,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(125,'ADD_ACCUMULATE',170,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(126,'ADD_ACCUMULATE',171,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(127,'ADD_ACCUMULATE',172,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-26 11:11:31'), +(128,'ADD_ACCUMULATE',174,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-26 11:11:32'), +(129,'ADD_ACCUMULATE',176,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-26 11:11:32'), +(130,'ADD_ACCUMULATE',178,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-26 11:19:34'), +(131,'ADD_ACCUMULATE',179,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-26 11:19:34'), +(132,'ADD_ACCUMULATE',180,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-27 01:54:21'), +(133,'ADD_ACCUMULATE',181,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-27 01:54:21'), +(134,'ADD_ACCUMULATE',182,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-27 01:54:40'), +(135,'ADD_ACCUMULATE',183,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(136,'ADD_ACCUMULATE',184,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(137,'ADD_ACCUMULATE',185,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(138,'ADD_ACCUMULATE',186,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(139,'ADD_ACCUMULATE',187,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(140,'ADD_ACCUMULATE',188,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(141,'ADD_ACCUMULATE',189,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-27 06:49:08'), +(142,'ADD_ACCUMULATE',190,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-27 06:49:08'), +(143,'DELETE_SINGLE',190,'{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}',NULL,6,'개별 항목 삭제',NULL,NULL,'2025-06-27 06:58:25'), +(144,'ADD_ACCUMULATE',191,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"4.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-27 06:58:46'), +(145,'DELETE_SINGLE',181,'{\"worker_name\":\"박현수\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-27 06:59:37'), +(146,'DELETE_SINGLE',180,'{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-27 06:59:42'), +(147,'ADD_ACCUMULATE',192,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-27 07:00:10'), +(148,'ADD_ACCUMULATE',193,NULL,'{\"report_date\":\"2025-06-30\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:37:29'), +(149,'ADD_ACCUMULATE',195,NULL,'{\"report_date\":\"2025-06-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:38:19'), +(150,'ADD_ACCUMULATE',196,NULL,'{\"report_date\":\"2025-06-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:38:19'), +(151,'ADD_ACCUMULATE',197,NULL,'{\"report_date\":\"2025-06-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:38:19'), +(152,'ADD_ACCUMULATE',198,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(153,'ADD_ACCUMULATE',199,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(154,'ADD_ACCUMULATE',200,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(155,'ADD_ACCUMULATE',201,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(156,'ADD_ACCUMULATE',202,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(157,'ADD_ACCUMULATE',203,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(158,'ADD_ACCUMULATE',204,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:48'), +(159,'ADD_ACCUMULATE',205,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:48'), +(160,'ADD_ACCUMULATE',206,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:48'), +(161,'ADD_ACCUMULATE',207,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:48'), +(162,'ADD_ACCUMULATE',208,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:40:10'), +(163,'ADD_ACCUMULATE',209,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:40:10'), +(164,'ADD_ACCUMULATE',210,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:42:57'), +(165,'ADD_ACCUMULATE',212,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:42:57'), +(166,'ADD_ACCUMULATE',214,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:42:57'), +(167,'ADD_ACCUMULATE',216,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:42:57'), +(168,'ADD_ACCUMULATE',218,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(169,'ADD_ACCUMULATE',219,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(170,'ADD_ACCUMULATE',220,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(171,'ADD_ACCUMULATE',221,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(172,'ADD_ACCUMULATE',222,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(173,'ADD_ACCUMULATE',223,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(174,'ADD_ACCUMULATE',224,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(175,'ADD_ACCUMULATE',225,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:44:11'), +(176,'ADD_ACCUMULATE',227,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:44:11'), +(177,'ADD_ACCUMULATE',229,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:44:11'), +(178,'ADD_ACCUMULATE',231,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:45:44'), +(179,'ADD_ACCUMULATE',232,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:45:45'), +(180,'ADD_ACCUMULATE',233,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:45:45'), +(181,'ADD_ACCUMULATE',234,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:45:45'), +(182,'ADD_ACCUMULATE',235,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:07'), +(183,'ADD_ACCUMULATE',236,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:07'), +(184,'ADD_ACCUMULATE',237,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:08'), +(185,'ADD_ACCUMULATE',238,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:08'), +(186,'ADD_ACCUMULATE',239,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:08'), +(187,'ADD_ACCUMULATE',240,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:08'), +(188,'ADD_ACCUMULATE',241,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(189,'ADD_ACCUMULATE',243,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(190,'ADD_ACCUMULATE',245,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(191,'ADD_ACCUMULATE',247,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(192,'ADD_ACCUMULATE',249,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(193,'ADD_ACCUMULATE',251,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(194,'ADD_ACCUMULATE',253,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(195,'ADD_ACCUMULATE',255,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(196,'ADD_ACCUMULATE',257,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(197,'ADD_ACCUMULATE',259,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(198,'ADD_ACCUMULATE',261,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:38'), +(199,'ADD_ACCUMULATE',262,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:38'), +(200,'ADD_ACCUMULATE',263,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:39'), +(201,'ADD_ACCUMULATE',264,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:39'), +(202,'ADD_ACCUMULATE',265,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:39'), +(203,'ADD_ACCUMULATE',266,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:39'), +(204,'ADD_ACCUMULATE',267,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(205,'ADD_ACCUMULATE',268,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(206,'ADD_ACCUMULATE',269,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(207,'ADD_ACCUMULATE',270,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(208,'ADD_ACCUMULATE',271,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(209,'ADD_ACCUMULATE',272,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(210,'ADD_ACCUMULATE',273,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(211,'ADD_ACCUMULATE',274,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(212,'ADD_ACCUMULATE',275,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(213,'ADD_ACCUMULATE',276,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(214,'ADD_ACCUMULATE',277,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(215,'ADD_ACCUMULATE',278,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(216,'ADD_ACCUMULATE',279,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(217,'ADD_ACCUMULATE',280,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(218,'ADD_ACCUMULATE',281,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(219,'ADD_ACCUMULATE',282,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(220,'ADD_ACCUMULATE',283,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(221,'ADD_ACCUMULATE',284,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(222,'ADD_ACCUMULATE',285,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:57'), +(223,'ADD_ACCUMULATE',286,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(224,'ADD_ACCUMULATE',287,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(225,'ADD_ACCUMULATE',288,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(226,'ADD_ACCUMULATE',289,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(227,'ADD_ACCUMULATE',290,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(228,'ADD_ACCUMULATE',291,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(229,'ADD_ACCUMULATE',292,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(230,'ADD_ACCUMULATE',293,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(231,'ADD_ACCUMULATE',294,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(232,'ADD_ACCUMULATE',295,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:40'), +(233,'ADD_ACCUMULATE',296,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:40'), +(234,'ADD_ACCUMULATE',297,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:40'), +(235,'ADD_ACCUMULATE',298,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:41'), +(236,'ADD_ACCUMULATE',299,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:41'), +(237,'ADD_ACCUMULATE',300,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:41'), +(238,'ADD_ACCUMULATE',301,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:42'), +(239,'ADD_ACCUMULATE',302,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:42'), +(240,'ADD_ACCUMULATE',303,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:42'), +(241,'ADD_ACCUMULATE',304,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:09:10'), +(242,'ADD_ACCUMULATE',305,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:58'), +(243,'ADD_ACCUMULATE',306,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:58'), +(244,'ADD_ACCUMULATE',307,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:58'), +(245,'ADD_ACCUMULATE',308,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(246,'ADD_ACCUMULATE',309,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(247,'ADD_ACCUMULATE',310,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(248,'ADD_ACCUMULATE',311,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(249,'ADD_ACCUMULATE',312,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(250,'ADD_ACCUMULATE',313,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(251,'ADD_ACCUMULATE',314,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(252,'ADD_ACCUMULATE',315,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(253,'ADD_ACCUMULATE',316,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(254,'ADD_ACCUMULATE',317,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(255,'ADD_ACCUMULATE',318,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(256,'ADD_ACCUMULATE',319,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(257,'ADD_ACCUMULATE',320,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(258,'ADD_ACCUMULATE',321,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(259,'ADD_ACCUMULATE',322,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:30'), +(260,'ADD_ACCUMULATE',323,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(261,'ADD_ACCUMULATE',324,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(262,'ADD_ACCUMULATE',325,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(263,'ADD_ACCUMULATE',326,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(264,'ADD_ACCUMULATE',327,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(265,'ADD_ACCUMULATE',328,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(266,'ADD_ACCUMULATE',329,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(267,'ADD_ACCUMULATE',330,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(268,'ADD_ACCUMULATE',331,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:57:06'), +(269,'ADD_ACCUMULATE',332,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:57:06'), +(270,'ADD_ACCUMULATE',333,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:57:47'), +(271,'ADD_ACCUMULATE',335,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(272,'ADD_ACCUMULATE',336,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(273,'ADD_ACCUMULATE',337,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(274,'ADD_ACCUMULATE',338,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(275,'ADD_ACCUMULATE',339,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(276,'ADD_ACCUMULATE',340,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(277,'ADD_ACCUMULATE',341,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-15 06:57:26'), +(278,'ADD_ACCUMULATE',342,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":4,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:46:46'), +(279,'ADD_ACCUMULATE',345,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":5,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:46:46'), +(280,'ADD_ACCUMULATE',348,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":10,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:47:53'), +(281,'ADD_ACCUMULATE',351,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":6,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:47:53'), +(282,'ADD_ACCUMULATE',354,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:48:32'), +(283,'ADD_ACCUMULATE',355,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:48:32'), +(284,'ADD_ACCUMULATE',356,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:48:32'), +(285,'ADD_ACCUMULATE',357,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:48:32'), +(286,'ADD_ACCUMULATE',358,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-16 06:51:31'), +(287,'ADD_ACCUMULATE',359,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-16 06:51:31'), +(288,'ADD_ACCUMULATE',360,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-17 06:45:22'), +(289,'ADD_ACCUMULATE',361,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:46:48'), +(290,'ADD_ACCUMULATE',363,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:46:48'), +(291,'ADD_ACCUMULATE',365,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:46:48'), +(292,'ADD_ACCUMULATE',367,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(293,'ADD_ACCUMULATE',368,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(294,'ADD_ACCUMULATE',369,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(295,'ADD_ACCUMULATE',370,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(296,'ADD_ACCUMULATE',371,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(297,'ADD_ACCUMULATE',372,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(298,'ADD_ACCUMULATE',373,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"2.00\",\"grand_total\":2,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"2.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 05:54:47'), +(299,'ADD_ACCUMULATE',374,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"2.00\",\"grand_total\":2,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"2.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 05:54:48'), +(300,'ADD_ACCUMULATE',375,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":5,\"work_entries_count\":3,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 05:58:33'), +(301,'DELETE_SINGLE',375,'{\"worker_name\":\"표영진\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"2.00\",\"report_date\":\"2025-07-18T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-07-18 05:58:49'), +(302,'ADD_ACCUMULATE',378,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 05:59:42'), +(303,'ADD_ACCUMULATE',379,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 06:00:15'), +(304,'ADD_ACCUMULATE',380,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(305,'ADD_ACCUMULATE',381,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(306,'ADD_ACCUMULATE',382,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(307,'ADD_ACCUMULATE',383,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(308,'ADD_ACCUMULATE',384,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(309,'ADD_ACCUMULATE',385,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(310,'ADD_ACCUMULATE',386,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(311,'ADD_ACCUMULATE',387,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:08'), +(312,'ADD_ACCUMULATE',389,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:08'), +(313,'ADD_ACCUMULATE',391,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(314,'ADD_ACCUMULATE',392,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(315,'ADD_ACCUMULATE',393,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(316,'ADD_ACCUMULATE',394,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(317,'ADD_ACCUMULATE',395,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(318,'ADD_ACCUMULATE',396,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(319,'ADD_ACCUMULATE',397,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(320,'ADD_ACCUMULATE',398,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-21 06:53:37'), +(321,'ADD_ACCUMULATE',399,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:47'), +(322,'ADD_ACCUMULATE',400,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(323,'ADD_ACCUMULATE',401,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(324,'ADD_ACCUMULATE',402,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(325,'ADD_ACCUMULATE',403,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(326,'ADD_ACCUMULATE',404,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(327,'ADD_ACCUMULATE',405,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(328,'ADD_ACCUMULATE',406,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:46:11'), +(329,'ADD_ACCUMULATE',407,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-22 06:46:11'), +(330,'ADD_ACCUMULATE',408,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-22 06:46:11'), +(331,'ADD_ACCUMULATE',409,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:06'), +(332,'ADD_ACCUMULATE',410,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:28'), +(333,'ADD_ACCUMULATE',411,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:28'), +(334,'ADD_ACCUMULATE',412,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(335,'ADD_ACCUMULATE',413,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(336,'ADD_ACCUMULATE',414,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(337,'ADD_ACCUMULATE',415,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(338,'ADD_ACCUMULATE',416,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(339,'ADD_ACCUMULATE',417,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(340,'ADD_ACCUMULATE',418,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:36:55'), +(341,'ADD_ACCUMULATE',419,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(342,'ADD_ACCUMULATE',420,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(343,'ADD_ACCUMULATE',421,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(344,'ADD_ACCUMULATE',422,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(345,'ADD_ACCUMULATE',423,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(346,'ADD_ACCUMULATE',424,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(347,'ADD_ACCUMULATE',425,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-24 06:47:04'), +(348,'ADD_ACCUMULATE',426,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-24 06:47:04'), +(349,'ADD_ACCUMULATE',427,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:44:23'), +(350,'ADD_ACCUMULATE',428,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(351,'ADD_ACCUMULATE',429,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(352,'ADD_ACCUMULATE',430,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(353,'ADD_ACCUMULATE',431,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(354,'ADD_ACCUMULATE',432,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(355,'ADD_ACCUMULATE',433,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(356,'ADD_ACCUMULATE',434,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:18'), +(357,'ADD_ACCUMULATE',435,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:19'), +(358,'ADD_ACCUMULATE',436,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:19'), +(359,'ADD_ACCUMULATE',437,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-28 06:30:39'), +(360,'ADD_ACCUMULATE',438,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-28 06:30:39'), +(361,'ADD_ACCUMULATE',439,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-28 06:30:39'), +(362,'ADD_ACCUMULATE',440,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:08'), +(363,'ADD_ACCUMULATE',442,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(364,'ADD_ACCUMULATE',443,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(365,'ADD_ACCUMULATE',444,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(366,'ADD_ACCUMULATE',445,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(367,'ADD_ACCUMULATE',446,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(368,'ADD_ACCUMULATE',447,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(369,'ADD_ACCUMULATE',448,NULL,'{\"report_date\":\"2025-07-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-29 06:39:13'), +(370,'ADD_ACCUMULATE',449,NULL,'{\"report_date\":\"2025-07-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-29 06:39:13'), +(371,'ADD_ACCUMULATE',450,NULL,'{\"report_date\":\"2025-07-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-29 06:39:13'), +(372,'ADD_ACCUMULATE',451,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-30 06:50:30'), +(373,'ADD_ACCUMULATE',452,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-30 06:50:30'), +(374,'ADD_ACCUMULATE',453,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-30 06:50:30'), +(375,'ADD_ACCUMULATE',454,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(376,'ADD_ACCUMULATE',455,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(377,'ADD_ACCUMULATE',456,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(378,'ADD_ACCUMULATE',457,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(379,'ADD_ACCUMULATE',458,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(380,'ADD_ACCUMULATE',459,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(381,'ADD_ACCUMULATE',460,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(382,'ADD_ACCUMULATE',461,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:42:56'), +(383,'ADD_ACCUMULATE',462,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:43:32'), +(384,'ADD_ACCUMULATE',464,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:43:32'), +(385,'ADD_ACCUMULATE',466,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(386,'ADD_ACCUMULATE',467,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(387,'ADD_ACCUMULATE',468,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(388,'ADD_ACCUMULATE',469,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(389,'ADD_ACCUMULATE',470,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(390,'ADD_ACCUMULATE',471,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(391,'ADD_ACCUMULATE',472,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(392,'ADD_ACCUMULATE',473,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(393,'ADD_ACCUMULATE',474,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(394,'ADD_ACCUMULATE',475,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(395,'ADD_ACCUMULATE',476,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(396,'ADD_ACCUMULATE',477,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(397,'ADD_ACCUMULATE',478,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(398,'ADD_ACCUMULATE',479,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(399,'ADD_ACCUMULATE',480,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(400,'ADD_ACCUMULATE',481,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(401,'ADD_ACCUMULATE',482,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(402,'ADD_ACCUMULATE',483,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(403,'ADD_ACCUMULATE',484,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(404,'ADD_ACCUMULATE',485,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(405,'ADD_ACCUMULATE',486,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(406,'ADD_ACCUMULATE',487,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(407,'ADD_ACCUMULATE',488,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(408,'ADD_ACCUMULATE',489,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:48'), +(409,'ADD_ACCUMULATE',490,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-01 05:02:28'), +(410,'ADD_ACCUMULATE',492,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-01 05:02:28'), +(411,'ADD_ACCUMULATE',494,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:42:39'), +(412,'ADD_ACCUMULATE',496,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:42:39'), +(413,'ADD_ACCUMULATE',498,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:14'), +(414,'ADD_ACCUMULATE',499,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:15'), +(415,'ADD_ACCUMULATE',500,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:15'), +(416,'ADD_ACCUMULATE',501,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:39'), +(417,'ADD_ACCUMULATE',502,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:39'), +(418,'ADD_ACCUMULATE',503,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:39'), +(419,'ADD_ACCUMULATE',504,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:52'), +(420,'ADD_ACCUMULATE',505,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-08 06:45:20'), +(421,'ADD_ACCUMULATE',506,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:58:42'), +(422,'ADD_ACCUMULATE',507,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:58:42'), +(423,'ADD_ACCUMULATE',508,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:18'), +(424,'ADD_ACCUMULATE',509,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:19'), +(425,'ADD_ACCUMULATE',510,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:19'), +(426,'ADD_ACCUMULATE',511,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:19'), +(427,'ADD_ACCUMULATE',512,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:19'), +(428,'ADD_ACCUMULATE',513,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-11 06:27:37'), +(429,'ADD_ACCUMULATE',514,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"16.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"16.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-11 06:27:37'), +(430,'ADD_ACCUMULATE',515,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:23'), +(431,'ADD_ACCUMULATE',516,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:23'), +(432,'ADD_ACCUMULATE',517,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:49'), +(433,'ADD_ACCUMULATE',518,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:49'), +(434,'ADD_ACCUMULATE',519,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:50'), +(435,'ADD_ACCUMULATE',520,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:50'), +(436,'ADD_ACCUMULATE',521,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:50'), +(437,'ADD_ACCUMULATE',522,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:50'), +(438,'ADD_ACCUMULATE',523,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(439,'ADD_ACCUMULATE',524,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(440,'ADD_ACCUMULATE',525,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(441,'ADD_ACCUMULATE',526,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(442,'ADD_ACCUMULATE',527,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(443,'ADD_ACCUMULATE',528,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(444,'ADD_ACCUMULATE',529,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(445,'ADD_ACCUMULATE',530,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(446,'ADD_ACCUMULATE',531,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-13 06:31:32'), +(447,'ADD_ACCUMULATE',532,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:13'), +(448,'ADD_ACCUMULATE',534,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(449,'ADD_ACCUMULATE',535,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(450,'ADD_ACCUMULATE',536,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(451,'ADD_ACCUMULATE',537,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(452,'ADD_ACCUMULATE',538,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(453,'ADD_ACCUMULATE',539,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(454,'ADD_ACCUMULATE',540,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(455,'ADD_ACCUMULATE',541,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:37:19'), +(456,'ADD_ACCUMULATE',542,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-14 06:35:27'), +(457,'ADD_ACCUMULATE',544,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:39:03'), +(458,'ADD_ACCUMULATE',546,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:39:44'), +(459,'ADD_ACCUMULATE',548,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(460,'ADD_ACCUMULATE',549,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(461,'ADD_ACCUMULATE',550,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(462,'ADD_ACCUMULATE',551,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(463,'ADD_ACCUMULATE',552,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(464,'ADD_ACCUMULATE',553,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(465,'ADD_ACCUMULATE',554,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:21:36'), +(466,'ADD_ACCUMULATE',555,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:21:36'), +(467,'ADD_ACCUMULATE',556,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:22:01'), +(468,'ADD_ACCUMULATE',557,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:22:53'), +(469,'ADD_ACCUMULATE',559,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:23:34'), +(470,'ADD_ACCUMULATE',561,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:41:24'), +(471,'ADD_ACCUMULATE',562,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:41:24'), +(472,'ADD_ACCUMULATE',563,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:41:24'), +(473,'ADD_ACCUMULATE',564,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:10'), +(474,'ADD_ACCUMULATE',565,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:10'), +(475,'ADD_ACCUMULATE',566,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:10'), +(476,'ADD_ACCUMULATE',567,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:35'), +(477,'ADD_ACCUMULATE',568,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:35'), +(478,'ADD_ACCUMULATE',569,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:02:49'), +(479,'ADD_ACCUMULATE',570,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:03:30'), +(480,'ADD_ACCUMULATE',571,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:03:30'), +(481,'ADD_ACCUMULATE',572,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:03:30'), +(482,'ADD_ACCUMULATE',573,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:03:30'), +(483,'ADD_ACCUMULATE',574,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(484,'ADD_ACCUMULATE',575,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(485,'ADD_ACCUMULATE',576,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(486,'ADD_ACCUMULATE',577,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(487,'ADD_ACCUMULATE',578,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(488,'ADD_ACCUMULATE',579,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-19 08:36:51'), +(489,'ADD_ACCUMULATE',580,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-19 08:36:51'), +(490,'ADD_ACCUMULATE',581,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-19 08:36:51'), +(491,'ADD_ACCUMULATE',582,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-20 06:19:36'), +(492,'ADD_ACCUMULATE',583,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-20 06:21:28'), +(493,'ADD_ACCUMULATE',585,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-20 06:21:28'), +(494,'ADD_ACCUMULATE',587,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:43:46'), +(495,'ADD_ACCUMULATE',588,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:23'), +(496,'ADD_ACCUMULATE',589,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:23'), +(497,'ADD_ACCUMULATE',590,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:23'), +(498,'ADD_ACCUMULATE',591,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:24'), +(499,'ADD_ACCUMULATE',592,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:24'), +(500,'ADD_ACCUMULATE',593,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:24'), +(501,'ADD_ACCUMULATE',594,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:26'), +(502,'ADD_ACCUMULATE',595,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:26'), +(503,'ADD_ACCUMULATE',596,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-21 06:30:36'), +(504,'ADD_ACCUMULATE',597,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-21 06:30:36'), +(505,'ADD_ACCUMULATE',598,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:50:38'), +(506,'ADD_ACCUMULATE',599,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:50:38'), +(507,'ADD_ACCUMULATE',600,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:51:23'), +(508,'ADD_ACCUMULATE',602,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:51:23'), +(509,'ADD_ACCUMULATE',604,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:51:23'), +(510,'ADD_ACCUMULATE',606,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:51:23'), +(511,'ADD_ACCUMULATE',608,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:54:46'), +(512,'ADD_ACCUMULATE',610,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:55:25'), +(513,'ADD_ACCUMULATE',612,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-21 08:24:50'), +(514,'ADD_ACCUMULATE',613,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-21 08:24:50'), +(515,'ADD_ACCUMULATE',614,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-22 06:21:15'), +(516,'ADD_ACCUMULATE',615,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-22 06:23:12'), +(517,'ADD_ACCUMULATE',617,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-22 06:23:55'), +(518,'ADD_ACCUMULATE',618,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:27:43'), +(519,'ADD_ACCUMULATE',619,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(520,'ADD_ACCUMULATE',620,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(521,'ADD_ACCUMULATE',621,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(522,'ADD_ACCUMULATE',622,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(523,'ADD_ACCUMULATE',623,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(524,'ADD_ACCUMULATE',624,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(525,'ADD_ACCUMULATE',625,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:02'), +(526,'ADD_ACCUMULATE',627,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:25'), +(527,'ADD_ACCUMULATE',628,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(528,'ADD_ACCUMULATE',629,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(529,'ADD_ACCUMULATE',630,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(530,'ADD_ACCUMULATE',631,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(531,'ADD_ACCUMULATE',632,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(532,'ADD_ACCUMULATE',633,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(533,'ADD_ACCUMULATE',634,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(534,'ADD_ACCUMULATE',635,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(535,'ADD_ACCUMULATE',636,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(536,'ADD_ACCUMULATE',637,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(537,'ADD_ACCUMULATE',638,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(538,'ADD_ACCUMULATE',639,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(539,'ADD_ACCUMULATE',640,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(540,'ADD_ACCUMULATE',641,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(541,'ADD_ACCUMULATE',642,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(542,'ADD_ACCUMULATE',643,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(543,'ADD_ACCUMULATE',644,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(544,'ADD_ACCUMULATE',645,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-25 06:49:16'), +(545,'ADD_ACCUMULATE',646,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-25 06:49:17'), +(546,'ADD_ACCUMULATE',647,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:28:03'), +(547,'ADD_ACCUMULATE',649,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:28:35'), +(548,'ADD_ACCUMULATE',650,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(549,'ADD_ACCUMULATE',651,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(550,'ADD_ACCUMULATE',652,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(551,'ADD_ACCUMULATE',653,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(552,'ADD_ACCUMULATE',654,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(553,'ADD_ACCUMULATE',655,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(554,'ADD_ACCUMULATE',656,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(555,'ADD_ACCUMULATE',657,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:03'), +(556,'ADD_ACCUMULATE',658,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-26 08:22:12'), +(557,'ADD_ACCUMULATE',659,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-26 08:22:12'), +(558,'ADD_ACCUMULATE',660,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-26 08:22:12'), +(559,'ADD_ACCUMULATE',661,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(560,'ADD_ACCUMULATE',662,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(561,'ADD_ACCUMULATE',663,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(562,'ADD_ACCUMULATE',664,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(563,'ADD_ACCUMULATE',665,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(564,'ADD_ACCUMULATE',666,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(565,'ADD_ACCUMULATE',667,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(566,'ADD_ACCUMULATE',668,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:48'), +(567,'ADD_ACCUMULATE',669,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-27 06:45:32'), +(568,'ADD_ACCUMULATE',671,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-27 06:45:32'), +(569,'ADD_ACCUMULATE',673,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-28 08:31:42'), +(570,'ADD_ACCUMULATE',675,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-28 08:31:42'), +(571,'ADD_ACCUMULATE',677,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-28 08:31:42'), +(572,'ADD_ACCUMULATE',679,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-28 08:31:42'), +(573,'ADD_ACCUMULATE',681,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:37:46'), +(574,'ADD_ACCUMULATE',683,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:38:15'), +(575,'ADD_ACCUMULATE',685,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:38:50'), +(576,'ADD_ACCUMULATE',687,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:39:24'), +(577,'ADD_ACCUMULATE',688,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(578,'ADD_ACCUMULATE',689,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(579,'ADD_ACCUMULATE',690,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(580,'ADD_ACCUMULATE',691,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(581,'ADD_ACCUMULATE',692,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(582,'ADD_ACCUMULATE',693,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(583,'ADD_ACCUMULATE',694,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:44:56'), +(584,'ADD_ACCUMULATE',695,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:44:56'), +(585,'ADD_ACCUMULATE',696,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:44:56'), +(586,'ADD_ACCUMULATE',697,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(587,'ADD_ACCUMULATE',698,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(588,'ADD_ACCUMULATE',699,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(589,'ADD_ACCUMULATE',700,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(590,'ADD_ACCUMULATE',701,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(591,'ADD_ACCUMULATE',702,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(592,'DELETE',693,'{\"id\":693,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:05'), +(593,'DELETE',702,'{\"id\":702,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:16'), +(594,'DELETE',697,'{\"id\":697,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:26'), +(595,'DELETE',688,'{\"id\":688,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:32'), +(596,'DELETE',691,'{\"id\":691,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:41'), +(597,'DELETE',700,'{\"id\":700,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:48'), +(598,'DELETE',692,'{\"id\":692,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:56'), +(599,'DELETE',701,'{\"id\":701,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:47:01'), +(600,'ADD_ACCUMULATE',703,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(601,'ADD_ACCUMULATE',704,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(602,'ADD_ACCUMULATE',705,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(603,'ADD_ACCUMULATE',706,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(604,'ADD_ACCUMULATE',707,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(605,'ADD_ACCUMULATE',708,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(606,'ADD_ACCUMULATE',709,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(607,'ADD_ACCUMULATE',710,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(608,'ADD_ACCUMULATE',711,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:35'), +(609,'ADD_ACCUMULATE',713,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:35'), +(610,'ADD_ACCUMULATE',715,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:35'), +(611,'ADD_ACCUMULATE',717,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:35'), +(612,'DELETE',705,'{\"id\":705,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":8,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:55:28'), +(613,'ADD_ACCUMULATE',719,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-29 21:55:56'), +(614,'ADD_ACCUMULATE',720,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-29 21:55:56'), +(615,'ADD_ACCUMULATE',721,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-29 21:55:56'), +(616,'DELETE',711,'{\"id\":711,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"6.00\",\"created_at\":\"2025-08-29T06:47:35.000Z\",\"updated_at\":\"2025-08-29T06:47:35.000Z\",\"created_by\":6,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:56:26'), +(617,'DELETE',712,'{\"id\":712,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":1,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-29T06:47:35.000Z\",\"updated_at\":\"2025-08-29T06:47:35.000Z\",\"created_by\":6,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:56:43'), +(618,'DELETE',707,'{\"id\":707,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:57:03'), +(619,'DELETE',708,'{\"id\":708,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:57:16'), +(620,'DELETE',709,'{\"id\":709,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:57:26'), +(621,'ADD_ACCUMULATE',722,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-30 05:12:03'), +(622,'ADD_ACCUMULATE',723,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-30 05:12:03'), +(623,'ADD_ACCUMULATE',724,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-30 05:12:03'), +(624,'ADD_ACCUMULATE',725,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(625,'ADD_ACCUMULATE',726,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(626,'ADD_ACCUMULATE',727,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(627,'ADD_ACCUMULATE',728,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(628,'ADD_ACCUMULATE',729,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(629,'ADD_ACCUMULATE',730,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(630,'ADD_ACCUMULATE',731,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(631,'ADD_ACCUMULATE',732,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:18:28'), +(632,'ADD_ACCUMULATE',733,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:18:28'), +(633,'ADD_ACCUMULATE',734,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:11'), +(634,'ADD_ACCUMULATE',735,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:11'), +(635,'ADD_ACCUMULATE',736,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:11'), +(636,'ADD_ACCUMULATE',737,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:35'), +(637,'ADD_ACCUMULATE',738,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:35'), +(638,'ADD_ACCUMULATE',739,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:35'), +(639,'ADD_ACCUMULATE',740,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:20:03'), +(640,'DELETE',650,'{\"id\":650,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:13:55'), +(641,'DELETE',654,'{\"id\":654,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:14:02'), +(642,'DELETE',656,'{\"id\":656,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:14:11'), +(643,'DELETE',572,'{\"id\":572,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":7,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:15:09'), +(644,'DELETE',571,'{\"id\":571,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:15:17'), +(645,'DELETE',570,'{\"id\":570,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:15:27'), +(646,'DELETE',599,'{\"id\":599,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":7,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:50:38.000Z\",\"updated_at\":\"2025-08-21T07:50:38.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:15:59'), +(647,'DELETE',604,'{\"id\":604,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:14'), +(648,'DELETE',605,'{\"id\":605,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:19'), +(649,'DELETE',606,'{\"id\":606,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:28'), +(650,'DELETE',607,'{\"id\":607,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:33'), +(651,'DELETE',598,'{\"id\":598,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":1,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:50:38.000Z\",\"updated_at\":\"2025-08-21T07:50:38.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:54'), +(652,'ADD_ACCUMULATE',741,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 23:18:03'), +(653,'ADD_ACCUMULATE',742,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 23:18:03'), +(654,'DELETE',588,'{\"id\":588,\"report_date\":\"2025-08-20T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-20T06:44:23.000Z\",\"updated_at\":\"2025-08-20T06:44:23.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:26:52'), +(655,'DELETE',592,'{\"id\":592,\"report_date\":\"2025-08-20T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-20T06:44:24.000Z\",\"updated_at\":\"2025-08-20T06:44:24.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:26:58'), +(656,'DELETE',639,'{\"id\":639,\"report_date\":\"2025-08-25T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-25T06:48:34.000Z\",\"updated_at\":\"2025-08-25T06:48:34.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:27:26'), +(657,'DELETE',642,'{\"id\":642,\"report_date\":\"2025-08-25T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-25T06:48:34.000Z\",\"updated_at\":\"2025-08-25T06:48:34.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:27:31'), +(658,'ADD_ACCUMULATE',743,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:34:20'), +(659,'ADD_ACCUMULATE',744,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:34:20'), +(660,'DELETE_SINGLE',744,'{\"worker_name\":\"이창호\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-09-02T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-09-02 07:35:18'), +(661,'DELETE_SINGLE',743,'{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-09-02T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-09-02 07:35:21'), +(662,'ADD_ACCUMULATE',745,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(663,'ADD_ACCUMULATE',746,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(664,'ADD_ACCUMULATE',747,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(665,'ADD_ACCUMULATE',748,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(666,'ADD_ACCUMULATE',749,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(667,'ADD_ACCUMULATE',750,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(668,'ADD_ACCUMULATE',751,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(669,'ADD_ACCUMULATE',752,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(670,'ADD_ACCUMULATE',753,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(671,'ADD_ACCUMULATE',754,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(672,'ADD_ACCUMULATE',755,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(673,'ADD_ACCUMULATE',756,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(674,'ADD_ACCUMULATE',757,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:37:19'), +(675,'ADD_ACCUMULATE',758,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:37:19'), +(676,'ADD_ACCUMULATE',759,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-02 08:16:14'), +(677,'ADD_ACCUMULATE',761,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-02 08:16:14'), +(678,'ADD_ACCUMULATE',763,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:47'), +(679,'ADD_ACCUMULATE',764,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:47'), +(680,'ADD_ACCUMULATE',765,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(681,'ADD_ACCUMULATE',766,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(682,'ADD_ACCUMULATE',767,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(683,'ADD_ACCUMULATE',768,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(684,'ADD_ACCUMULATE',769,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(685,'ADD_ACCUMULATE',770,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(686,'ADD_ACCUMULATE',771,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-03 06:44:18'), +(687,'ADD_ACCUMULATE',772,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:32'), +(688,'ADD_ACCUMULATE',773,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:32'), +(689,'ADD_ACCUMULATE',774,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:32'), +(690,'ADD_ACCUMULATE',775,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:32'), +(691,'ADD_ACCUMULATE',776,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:33'), +(692,'ADD_ACCUMULATE',777,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:33'), +(693,'ADD_ACCUMULATE',778,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:33'), +(694,'ADD_ACCUMULATE',779,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:33'), +(695,'ADD_ACCUMULATE',780,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-04 06:48:34'), +(696,'ADD_ACCUMULATE',781,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-04 06:48:34'), +(697,'ADD_ACCUMULATE',782,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:30'), +(698,'ADD_ACCUMULATE',783,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:30'), +(699,'ADD_ACCUMULATE',784,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:30'), +(700,'ADD_ACCUMULATE',785,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:31'), +(701,'ADD_ACCUMULATE',786,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:31'), +(702,'ADD_ACCUMULATE',787,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:31'), +(703,'ADD_ACCUMULATE',788,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:31'), +(704,'ADD_ACCUMULATE',789,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-05 22:09:55'), +(705,'ADD_ACCUMULATE',790,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-05 22:09:55'), +(706,'ADD_ACCUMULATE',791,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-05 22:09:55'), +(707,'ADD_ACCUMULATE',792,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-06 04:21:10'), +(708,'ADD_ACCUMULATE',793,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-06 04:21:10'), +(709,'ADD_ACCUMULATE',794,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-06 04:21:10'), +(710,'ADD_ACCUMULATE',795,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:18'), +(711,'ADD_ACCUMULATE',796,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:18'), +(712,'ADD_ACCUMULATE',797,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:18'), +(713,'ADD_ACCUMULATE',798,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:19'), +(714,'ADD_ACCUMULATE',799,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:19'), +(715,'ADD_ACCUMULATE',800,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:19'), +(716,'ADD_ACCUMULATE',801,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:19'), +(717,'ADD_ACCUMULATE',802,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(718,'ADD_ACCUMULATE',803,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(719,'ADD_ACCUMULATE',804,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(720,'ADD_ACCUMULATE',805,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(721,'ADD_ACCUMULATE',806,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(722,'ADD_ACCUMULATE',807,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(723,'ADD_ACCUMULATE',808,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(724,'ADD_ACCUMULATE',809,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-08 06:47:37'), +(725,'ADD_ACCUMULATE',810,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-08 06:47:37'), +(726,'ADD_ACCUMULATE',811,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-08 06:47:37'), +(727,'ADD_ACCUMULATE',812,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(728,'ADD_ACCUMULATE',813,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(729,'ADD_ACCUMULATE',814,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(730,'ADD_ACCUMULATE',815,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(731,'ADD_ACCUMULATE',816,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(732,'ADD_ACCUMULATE',817,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(733,'ADD_ACCUMULATE',818,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(734,'ADD_ACCUMULATE',819,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-09 06:44:29'), +(735,'ADD_ACCUMULATE',820,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-09 06:44:29'), +(736,'ADD_ACCUMULATE',821,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-09 06:44:29'), +(737,'ADD_ACCUMULATE',822,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(738,'ADD_ACCUMULATE',823,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(739,'ADD_ACCUMULATE',824,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(740,'ADD_ACCUMULATE',825,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(741,'ADD_ACCUMULATE',826,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(742,'ADD_ACCUMULATE',827,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(743,'ADD_ACCUMULATE',828,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(744,'ADD_ACCUMULATE',829,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-10 06:48:43'), +(745,'ADD_ACCUMULATE',830,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-10 06:48:43'), +(746,'ADD_ACCUMULATE',831,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-10 06:48:43'), +(747,'ADD_ACCUMULATE',832,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:37:11'), +(748,'ADD_ACCUMULATE',834,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":4,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:38:24'), +(749,'ADD_ACCUMULATE',837,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:39:38'), +(750,'ADD_ACCUMULATE',838,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:40:48'), +(751,'ADD_ACCUMULATE',839,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:46'), +(752,'ADD_ACCUMULATE',840,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(753,'ADD_ACCUMULATE',841,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(754,'ADD_ACCUMULATE',842,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(755,'ADD_ACCUMULATE',843,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(756,'ADD_ACCUMULATE',844,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(757,'ADD_ACCUMULATE',845,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:51'), +(758,'ADD_ACCUMULATE',847,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:51'), +(759,'ADD_ACCUMULATE',849,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:51'), +(760,'DELETE',849,'{\"id\":849,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"4.00\",\"created_at\":\"2025-09-11T06:41:51.000Z\",\"updated_at\":\"2025-09-11T06:41:51.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-11 06:42:40'), +(761,'DELETE',850,'{\"id\":850,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"4.00\",\"created_at\":\"2025-09-11T06:41:51.000Z\",\"updated_at\":\"2025-09-11T06:41:51.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-11 06:42:49'), +(762,'DELETE',839,'{\"id\":839,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-11T06:41:46.000Z\",\"updated_at\":\"2025-09-11T06:41:46.000Z\",\"created_by\":6,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-11 06:43:07'), +(763,'DELETE',837,'{\"id\":837,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":8,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-11T06:39:38.000Z\",\"updated_at\":\"2025-09-11T06:39:38.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-11 06:43:16'), +(764,'ADD_ACCUMULATE',851,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(765,'ADD_ACCUMULATE',852,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(766,'ADD_ACCUMULATE',853,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(767,'ADD_ACCUMULATE',854,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(768,'ADD_ACCUMULATE',855,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(769,'ADD_ACCUMULATE',856,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(770,'ADD_ACCUMULATE',857,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(771,'ADD_ACCUMULATE',858,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(772,'ADD_ACCUMULATE',859,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(773,'ADD_ACCUMULATE',860,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(774,'ADD_ACCUMULATE',861,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(775,'ADD_ACCUMULATE',862,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(776,'ADD_ACCUMULATE',863,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(777,'ADD_ACCUMULATE',864,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(778,'ADD_ACCUMULATE',865,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(779,'ADD_ACCUMULATE',866,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(780,'ADD_ACCUMULATE',867,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(781,'ADD_ACCUMULATE',868,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(782,'ADD_ACCUMULATE',869,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(783,'ADD_ACCUMULATE',870,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:40'), +(784,'ADD_ACCUMULATE',871,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:40'), +(785,'ADD_ACCUMULATE',872,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:40'), +(786,'ADD_ACCUMULATE',873,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:40'), +(787,'ADD_ACCUMULATE',874,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(788,'ADD_ACCUMULATE',875,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(789,'ADD_ACCUMULATE',876,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(790,'ADD_ACCUMULATE',877,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(791,'ADD_ACCUMULATE',878,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(792,'ADD_ACCUMULATE',879,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:00'), +(793,'ADD_ACCUMULATE',880,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:00'), +(794,'ADD_ACCUMULATE',881,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:00'), +(795,'ADD_ACCUMULATE',882,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:00'), +(796,'ADD_ACCUMULATE',883,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(797,'ADD_ACCUMULATE',884,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(798,'ADD_ACCUMULATE',885,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(799,'ADD_ACCUMULATE',886,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(800,'ADD_ACCUMULATE',887,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(801,'ADD_ACCUMULATE',888,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(802,'ADD_ACCUMULATE',889,NULL,'{\"report_date\":\"2025-09-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-16 06:51:19'), +(803,'ADD_ACCUMULATE',890,NULL,'{\"report_date\":\"2025-09-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-16 06:51:19'), +(804,'ADD_ACCUMULATE',891,NULL,'{\"report_date\":\"2025-09-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-16 06:52:12'), +(805,'ADD_ACCUMULATE',893,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-17 06:43:08'), +(806,'ADD_ACCUMULATE',894,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-17 06:43:08'), +(807,'ADD_ACCUMULATE',895,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(808,'ADD_ACCUMULATE',896,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(809,'ADD_ACCUMULATE',897,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(810,'ADD_ACCUMULATE',898,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(811,'ADD_ACCUMULATE',899,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(812,'ADD_ACCUMULATE',900,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(813,'ADD_ACCUMULATE',901,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(814,'ADD_ACCUMULATE',902,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(815,'ADD_ACCUMULATE',903,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:43:40'), +(816,'ADD_ACCUMULATE',904,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:43:40'), +(817,'ADD_ACCUMULATE',905,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(818,'ADD_ACCUMULATE',906,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(819,'ADD_ACCUMULATE',907,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(820,'ADD_ACCUMULATE',908,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(821,'ADD_ACCUMULATE',909,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(822,'ADD_ACCUMULATE',910,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:46:39'), +(823,'ADD_ACCUMULATE',911,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-18 06:54:48'), +(824,'ADD_ACCUMULATE',912,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-18 06:54:48'), +(825,'ADD_ACCUMULATE',913,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:51:40'), +(826,'ADD_ACCUMULATE',914,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:51:40'), +(827,'ADD_ACCUMULATE',915,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(828,'ADD_ACCUMULATE',916,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(829,'ADD_ACCUMULATE',917,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(830,'ADD_ACCUMULATE',918,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(831,'ADD_ACCUMULATE',919,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(832,'ADD_ACCUMULATE',920,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:23'), +(833,'ADD_ACCUMULATE',921,NULL,'{\"report_date\":\"2025-09-20\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-20 05:30:19'), +(834,'ADD_ACCUMULATE',922,NULL,'{\"report_date\":\"2025-09-20\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-20 05:30:19'), +(835,'ADD_ACCUMULATE',923,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(836,'ADD_ACCUMULATE',924,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(837,'ADD_ACCUMULATE',925,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(838,'ADD_ACCUMULATE',926,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(839,'ADD_ACCUMULATE',927,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(840,'ADD_ACCUMULATE',928,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(841,'ADD_ACCUMULATE',929,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-22 06:50:29'), +(842,'ADD_ACCUMULATE',930,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-22 06:50:29'), +(843,'ADD_ACCUMULATE',931,NULL,'{\"report_date\":\"2025-09-23\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-23 05:46:40'), +(844,'ADD_ACCUMULATE',932,NULL,'{\"report_date\":\"2025-09-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-23 05:46:40'), +(845,'ADD_ACCUMULATE',933,NULL,'{\"report_date\":\"2025-09-24\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-25 01:14:58'), +(846,'ADD_ACCUMULATE',934,NULL,'{\"report_date\":\"2025-09-24\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-25 01:14:58'), +(847,'ADD_ACCUMULATE',935,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:07'), +(848,'ADD_ACCUMULATE',936,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:07'), +(849,'ADD_ACCUMULATE',937,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(850,'ADD_ACCUMULATE',938,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(851,'ADD_ACCUMULATE',939,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(852,'ADD_ACCUMULATE',940,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(853,'ADD_ACCUMULATE',941,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(854,'ADD_ACCUMULATE',942,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(855,'ADD_ACCUMULATE',943,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(856,'ADD_ACCUMULATE',944,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(857,'ADD_ACCUMULATE',945,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(858,'ADD_ACCUMULATE',946,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(859,'ADD_ACCUMULATE',947,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(860,'ADD_ACCUMULATE',948,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(861,'ADD_ACCUMULATE',949,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(862,'ADD_ACCUMULATE',950,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(863,'ADD_ACCUMULATE',951,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:27'), +(864,'ADD_ACCUMULATE',952,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:27'), +(865,'ADD_ACCUMULATE',953,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:27'), +(866,'DELETE',952,'{\"id\":952,\"report_date\":\"2025-09-30T00:00:00.000Z\",\"worker_id\":2,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-30T06:52:27.000Z\",\"updated_at\":\"2025-09-30T06:52:27.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-30 06:56:36'), +(867,'ADD_ACCUMULATE',954,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-30 06:56:55'), +(868,'ADD_ACCUMULATE',955,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 05:25:58'), +(869,'ADD_ACCUMULATE',956,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 05:25:59'), +(870,'ADD_ACCUMULATE',957,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:32'), +(871,'ADD_ACCUMULATE',958,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:32'), +(872,'ADD_ACCUMULATE',959,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:32'), +(873,'ADD_ACCUMULATE',960,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:32'), +(874,'ADD_ACCUMULATE',961,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:33'), +(875,'ADD_ACCUMULATE',962,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:33'), +(876,'ADD_ACCUMULATE',963,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:33'), +(877,'ADD_ACCUMULATE',964,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-10 23:35:07'), +(878,'ADD_ACCUMULATE',965,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-10 23:35:07'), +(879,'ADD_ACCUMULATE',966,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-10 23:35:07'); +/*!40000 ALTER TABLE `work_report_audit_log` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_report_defects` +-- + +DROP TABLE IF EXISTS `work_report_defects`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_report_defects` ( + `defect_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `report_id` int(11) NOT NULL COMMENT 'daily_work_reports의 id', + `error_type_id` int(11) DEFAULT NULL COMMENT 'error_types의 id (부적합 원인) - 레거시, issue_report_id 사용 권장', + `issue_report_id` int(10) unsigned DEFAULT NULL COMMENT 'work_issue_reports의 report_id (신고된 이슈 연결)', + `category_id` int(10) unsigned DEFAULT NULL COMMENT 'issue_report_categories의 category_id (직접 입력 시)', + `item_id` int(10) unsigned DEFAULT NULL COMMENT 'issue_report_items의 item_id (직접 입력 시)', + `defect_hours` decimal(4,1) NOT NULL DEFAULT 0.0 COMMENT '해당 원인의 부적합 시간', + `note` text DEFAULT NULL COMMENT '추가 메모', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`defect_id`), + UNIQUE KEY `work_report_defects_report_issue_unique` (`report_id`,`issue_report_id`), + KEY `work_report_defects_report_id_index` (`report_id`), + KEY `work_report_defects_error_type_id_index` (`error_type_id`), + KEY `work_report_defects_issue_report_id_index` (`issue_report_id`), + KEY `work_report_defects_category_id_foreign` (`category_id`), + KEY `work_report_defects_item_id_foreign` (`item_id`), + CONSTRAINT `work_report_defects_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `issue_report_categories` (`category_id`) ON DELETE SET NULL, + CONSTRAINT `work_report_defects_issue_report_id_foreign` FOREIGN KEY (`issue_report_id`) REFERENCES `work_issue_reports` (`report_id`) ON DELETE SET NULL, + CONSTRAINT `work_report_defects_item_id_foreign` FOREIGN KEY (`item_id`) REFERENCES `issue_report_items` (`item_id`) ON DELETE SET NULL, + CONSTRAINT `work_report_defects_report_id_foreign` FOREIGN KEY (`report_id`) REFERENCES `daily_work_reports` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_report_defects` +-- + +LOCK TABLES `work_report_defects` WRITE; +/*!40000 ALTER TABLE `work_report_defects` DISABLE KEYS */; +INSERT INTO `work_report_defects` VALUES +(1,970,1,NULL,NULL,NULL,2.0,NULL,'2026-01-27 05:00:13'), +(2,972,1,NULL,NULL,NULL,4.0,NULL,'2026-01-27 05:09:53'), +(3,991,1,NULL,NULL,NULL,2.0,NULL,'2026-01-30 00:13:02'), +(4,973,5,NULL,NULL,NULL,4.0,NULL,'2026-01-27 05:11:47'), +(5,987,5,NULL,NULL,NULL,2.0,NULL,'2026-01-29 22:16:36'), +(6,990,5,NULL,NULL,NULL,2.0,NULL,'2026-01-29 22:16:36'), +(8,995,NULL,NULL,2,6,2.0,'치수가 nmm 안맞음(포인트 많이 고침)','2026-02-03 00:29:52'), +(9,995,NULL,3,NULL,NULL,1.0,NULL,'2026-02-03 00:29:52'), +(10,1639,NULL,3,NULL,NULL,1.0,NULL,'2026-02-03 04:28:40'), +(11,1639,NULL,NULL,1,2,2.0,NULL,'2026-02-03 04:28:40'), +(12,1644,NULL,NULL,5,42,4.0,NULL,'2026-02-04 22:52:41'), +(13,1676,NULL,NULL,13,43,2.0,NULL,'2026-02-04 23:22:54'), +(14,1679,NULL,NULL,4,44,8.0,'잘못된 정보를 전달함','2026-02-04 23:22:54'), +(15,1706,NULL,NULL,4,15,4.0,NULL,'2026-02-04 23:36:37'), +(16,1707,NULL,NULL,4,15,8.0,'설치 지연','2026-02-04 23:36:37'), +(17,1708,NULL,NULL,4,15,8.0,'설치 지연','2026-02-04 23:36:37'), +(18,1719,NULL,NULL,13,43,8.0,NULL,'2026-02-04 23:44:26'), +(19,1792,NULL,NULL,4,15,8.0,NULL,'2026-02-05 00:37:01'), +(20,1793,NULL,NULL,4,15,8.0,NULL,'2026-02-05 00:37:02'); +/*!40000 ALTER TABLE `work_report_defects` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_status_types` +-- + +DROP TABLE IF EXISTS `work_status_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_status_types` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL COMMENT '상태명', + `description` text DEFAULT NULL COMMENT '상태 설명', + `is_error` tinyint(1) DEFAULT 0 COMMENT '에러 상태 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_status_types` +-- + +LOCK TABLES `work_status_types` WRITE; +/*!40000 ALTER TABLE `work_status_types` DISABLE KEYS */; +INSERT INTO `work_status_types` VALUES +(1,'정규','정상적으로 완료된 작업',0,'2025-06-16 02:21:16'), +(2,'에러','오류가 발생한 작업',1,'2025-06-16 02:21:16'); +/*!40000 ALTER TABLE `work_status_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_types` +-- + +DROP TABLE IF EXISTS `work_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_types` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL COMMENT '작업 유형명', + `description` text DEFAULT NULL COMMENT '작업 유형 설명', + `category` varchar(50) DEFAULT NULL COMMENT '작업 카테고리', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_types` +-- + +LOCK TABLES `work_types` WRITE; +/*!40000 ALTER TABLE `work_types` DISABLE KEYS */; +INSERT INTO `work_types` VALUES +(1,'Base(구조물)',NULL,NULL,'2025-06-16 02:21:32','2025-06-16 03:03:42'), +(2,'Vessel(용기)',NULL,NULL,'2025-06-16 02:21:32','2025-06-16 03:03:47'), +(3,'Piping Assembly(배관)',NULL,NULL,'2025-06-16 02:21:32','2025-06-16 03:03:50'), +(4,'작업대기',NULL,NULL,'2025-06-16 02:21:32','2025-06-16 03:03:56'), +(11,'휴무','연차사용 등',NULL,'2025-11-04 05:53:46','2025-11-04 05:53:46'), +(12,'시설설비',NULL,NULL,'2026-02-04 21:52:07','2026-02-04 21:52:07'); +/*!40000 ALTER TABLE `work_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `worker_groups` +-- + +DROP TABLE IF EXISTS `worker_groups`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `worker_groups` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `group_leader_id` int(11) NOT NULL, + `worker_id` int(11) NOT NULL, + `group_name` varchar(100) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `uk_leader_worker` (`group_leader_id`,`worker_id`), + KEY `idx_group_leader` (`group_leader_id`), + KEY `idx_worker` (`worker_id`), + KEY `idx_is_active` (`is_active`), + CONSTRAINT `fk_group_leader` FOREIGN KEY (`group_leader_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE, + CONSTRAINT `fk_group_worker` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `worker_groups` +-- + +LOCK TABLES `worker_groups` WRITE; +/*!40000 ALTER TABLE `worker_groups` DISABLE KEYS */; +/*!40000 ALTER TABLE `worker_groups` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `worker_vacation_balance` +-- + +DROP TABLE IF EXISTS `worker_vacation_balance`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `worker_vacation_balance` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `worker_id` int(11) NOT NULL, + `year` int(11) NOT NULL, + `total_annual_leave` decimal(4,1) DEFAULT 15.0, + `used_annual_leave` decimal(4,1) DEFAULT 0.0, + `notes` text DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `unique_worker_year` (`worker_id`,`year`), + CONSTRAINT `worker_vacation_balance_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `worker_vacation_balance` +-- + +LOCK TABLES `worker_vacation_balance` WRITE; +/*!40000 ALTER TABLE `worker_vacation_balance` DISABLE KEYS */; +INSERT INTO `worker_vacation_balance` VALUES +(1,1,2026,15.0,0.0,NULL,'2026-01-19 01:40:31','2026-01-19 01:40:31'), +(11,2,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(12,4,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(13,5,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(14,6,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(15,7,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(16,8,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(17,9,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(18,10,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(19,12,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'); +/*!40000 ALTER TABLE `worker_vacation_balance` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workers` +-- + +DROP TABLE IF EXISTS `workers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workers` ( + `worker_id` int(11) NOT NULL AUTO_INCREMENT, + `worker_name` varchar(100) NOT NULL, + `join_date` date DEFAULT NULL, + `job_type` varchar(100) DEFAULT NULL, + `salary` decimal(10,2) DEFAULT NULL, + `annual_leave` int(11) DEFAULT NULL, + `status` enum('active','inactive') DEFAULT 'active' COMMENT '작업자 상태 (active: 활성, inactive: 비활성)', + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `phone_number` varchar(20) DEFAULT NULL COMMENT '전화번호', + `email` varchar(100) DEFAULT NULL COMMENT '이메일', + `hire_date` date DEFAULT NULL COMMENT '입사일', + `department` varchar(100) DEFAULT NULL COMMENT '부서', + `department_id` int(11) DEFAULT NULL, + `notes` text DEFAULT NULL COMMENT '비고', + `employment_status` enum('employed','resigned') NOT NULL DEFAULT 'employed' COMMENT '재직 상태 (employed: 재직, resigned: 퇴사)', + PRIMARY KEY (`worker_id`), + KEY `idx_workers_status` (`status`), + KEY `idx_workers_hire_date` (`hire_date`), + KEY `department_id` (`department_id`), + CONSTRAINT `workers_ibfk_1` FOREIGN KEY (`department_id`) REFERENCES `departments` (`department_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workers` +-- + +LOCK TABLES `workers` WRITE; +/*!40000 ALTER TABLE `workers` DISABLE KEYS */; +INSERT INTO `workers` VALUES +(1,'김두수',NULL,'leader',NULL,NULL,'active','2025-04-15 13:23:17','2025-04-15 13:23:17',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(2,'임영규',NULL,'leader',NULL,NULL,'active','2025-04-15 13:23:17','2025-04-15 13:23:17',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(3,'반치원',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:22','2025-04-15 13:23:22',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(4,'황인용',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:33','2025-04-15 13:23:33',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(5,'표영진',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:38','2025-04-15 13:23:38',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(6,'김윤섭',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:46','2025-04-15 13:23:46',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(7,'이창호',NULL,'worker',NULL,NULL,'inactive','2025-04-15 13:23:51','2025-04-15 13:23:51',NULL,NULL,NULL,NULL,1,NULL,'resigned'), +(8,'최광욱',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:57','2025-04-15 13:23:57',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(9,'박현수',NULL,'worker',NULL,NULL,'active','2025-04-15 13:24:01','2025-04-15 13:24:01',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(10,'조윤호',NULL,'worker',NULL,NULL,'active','2025-04-15 13:24:07','2025-04-15 13:24:07',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(11,'조승민',NULL,'worker',NULL,NULL,'active','2026-01-06 06:18:27','2026-01-06 06:18:27',NULL,NULL,'2026-01-05','생산팀',1,'용접사','employed'); +/*!40000 ALTER TABLE `workers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_categories` +-- + +DROP TABLE IF EXISTS `workplace_categories`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_categories` ( + `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '카테고리 ID', + `category_name` varchar(100) NOT NULL COMMENT '카테고리명 (예: 제 1공장)', + `description` text DEFAULT NULL COMMENT '설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성화 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '생성일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정일시', + `layout_image` varchar(500) DEFAULT NULL COMMENT '공장 배치도 이미지 경로', + PRIMARY KEY (`category_id`), + KEY `workplace_categories_is_active_index` (`is_active`), + KEY `workplace_categories_display_order_index` (`display_order`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_categories` +-- + +LOCK TABLES `workplace_categories` WRITE; +/*!40000 ALTER TABLE `workplace_categories` DISABLE KEYS */; +INSERT INTO `workplace_categories` VALUES +(1,'제 1공장',NULL,1,1,'2026-01-26 05:28:52','2026-01-27 03:52:45','/uploads/workplace-layout-1769485965188-143426330.jpg'), +(2,'제 2공장',NULL,2,1,'2026-01-26 05:28:59','2026-01-26 05:28:59',NULL); +/*!40000 ALTER TABLE `workplace_categories` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_items` +-- + +DROP TABLE IF EXISTS `workplace_items`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_items` ( + `item_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `workplace_id` int(10) unsigned NOT NULL COMMENT '작업장 ID', + `patrol_session_id` int(10) unsigned DEFAULT NULL COMMENT '등록한 순회점검 세션', + `project_id` int(11) DEFAULT NULL COMMENT '관련 프로젝트', + `item_type` enum('container','plate','material','tool','other') NOT NULL COMMENT '물품 유형', + `item_name` varchar(100) DEFAULT NULL COMMENT '물품명/설명', + `quantity` int(11) DEFAULT 1 COMMENT '수량', + `x_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 X 위치 (%)', + `y_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 Y 위치 (%)', + `width_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 너비 (%)', + `height_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 높이 (%)', + `is_active` tinyint(1) DEFAULT 1 COMMENT '현재 존재 여부', + `created_by` int(11) NOT NULL COMMENT '등록자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_by` int(11) DEFAULT NULL COMMENT '최종 수정자 user_id', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`item_id`), + KEY `workplace_items_workplace_id_is_active_index` (`workplace_id`,`is_active`), + KEY `workplace_items_project_id_index` (`project_id`), + KEY `workplace_items_patrol_session_id_foreign` (`patrol_session_id`), + KEY `workplace_items_created_by_foreign` (`created_by`), + KEY `workplace_items_updated_by_foreign` (`updated_by`), + CONSTRAINT `workplace_items_created_by_foreign` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `workplace_items_patrol_session_id_foreign` FOREIGN KEY (`patrol_session_id`) REFERENCES `daily_patrol_sessions` (`session_id`) ON DELETE SET NULL, + CONSTRAINT `workplace_items_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE SET NULL, + CONSTRAINT `workplace_items_updated_by_foreign` FOREIGN KEY (`updated_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `workplace_items_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_items` +-- + +LOCK TABLES `workplace_items` WRITE; +/*!40000 ALTER TABLE `workplace_items` DISABLE KEYS */; +/*!40000 ALTER TABLE `workplace_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_map_regions` +-- + +DROP TABLE IF EXISTS `workplace_map_regions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_map_regions` ( + `region_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '영역 ID', + `workplace_id` int(10) unsigned NOT NULL COMMENT '작업장 ID', + `category_id` int(10) unsigned NOT NULL COMMENT '공장 카테고리 ID', + `x_start` decimal(5,2) NOT NULL COMMENT '시작 X 좌표 (%)', + `y_start` decimal(5,2) NOT NULL COMMENT '시작 Y 좌표 (%)', + `x_end` decimal(5,2) NOT NULL COMMENT '끝 X 좌표 (%)', + `y_end` decimal(5,2) NOT NULL COMMENT '끝 Y 좌표 (%)', + `shape` varchar(20) DEFAULT 'rect' COMMENT '영역 모양 (rect, circle, polygon)', + `polygon_points` text DEFAULT NULL COMMENT '다각형인 경우 좌표 배열 (JSON)', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`region_id`), + KEY `workplace_map_regions_workplace_id_foreign` (`workplace_id`), + KEY `workplace_map_regions_category_id_foreign` (`category_id`), + CONSTRAINT `workplace_map_regions_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `workplace_map_regions_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_map_regions` +-- + +LOCK TABLES `workplace_map_regions` WRITE; +/*!40000 ALTER TABLE `workplace_map_regions` DISABLE KEYS */; +INSERT INTO `workplace_map_regions` VALUES +(1,12,1,29.43,57.36,34.43,66.06,'rect',NULL,'2026-01-26 23:05:13','2026-01-26 23:05:13'), +(2,11,1,46.05,7.85,51.68,24.75,'rect',NULL,'2026-01-26 23:05:23','2026-01-26 23:05:23'), +(3,4,1,35.18,0.12,46.05,23.79,'rect',NULL,'2026-01-26 23:05:53','2026-01-26 23:05:53'), +(4,9,1,50.68,29.10,54.93,38.52,'rect',NULL,'2026-01-26 23:06:03','2026-01-26 23:06:03'), +(5,10,1,50.80,43.35,55.05,52.05,'rect',NULL,'2026-01-26 23:06:08','2026-01-26 23:06:08'), +(6,5,1,55.30,8.33,58.55,24.27,'rect',NULL,'2026-01-26 23:06:15','2026-01-26 23:06:15'), +(7,3,1,59.30,8.09,80.93,55.67,'rect',NULL,'2026-01-26 23:06:29','2026-01-26 23:06:29'), +(8,1,1,58.93,62.92,72.93,74.03,'rect',NULL,'2026-01-26 23:06:37','2026-01-26 23:06:37'), +(9,8,1,56.43,28.38,58.55,39.25,'rect',NULL,'2026-01-26 23:06:46','2026-01-26 23:06:46'), +(10,7,1,0.18,1.32,25.68,21.37,'rect',NULL,'2026-01-26 23:06:51','2026-01-26 23:06:51'), +(11,2,1,34.93,29.10,47.93,61.95,'rect',NULL,'2026-01-26 23:06:59','2026-01-26 23:06:59'); +/*!40000 ALTER TABLE `workplace_map_regions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_visit_requests` +-- + +DROP TABLE IF EXISTS `workplace_visit_requests`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_visit_requests` ( + `request_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '신청 ID', + `requester_id` int(11) NOT NULL COMMENT '신청자 user_id', + `visitor_company` varchar(200) NOT NULL COMMENT '방문자 소속 (회사명 또는 "일용직")', + `visitor_count` int(11) DEFAULT 1 COMMENT '방문 인원', + `category_id` int(10) unsigned NOT NULL COMMENT '방문 구역 (공장)', + `workplace_id` int(10) unsigned NOT NULL COMMENT '방문 작업장', + `visit_date` date NOT NULL COMMENT '방문 날짜', + `visit_time` time NOT NULL COMMENT '방문 시간', + `purpose_id` int(10) unsigned NOT NULL COMMENT '방문 목적 ID', + `notes` text DEFAULT NULL COMMENT '비고', + `status` enum('pending','approved','rejected','training_completed') DEFAULT 'pending' COMMENT '신청 상태', + `approved_by` int(11) DEFAULT NULL COMMENT '승인자 user_id', + `approved_at` timestamp NULL DEFAULT NULL COMMENT '승인 시간', + `rejection_reason` text DEFAULT NULL COMMENT '반려 사유', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`request_id`), + KEY `workplace_visit_requests_requester_id_foreign` (`requester_id`), + KEY `workplace_visit_requests_category_id_foreign` (`category_id`), + KEY `workplace_visit_requests_workplace_id_foreign` (`workplace_id`), + KEY `workplace_visit_requests_purpose_id_foreign` (`purpose_id`), + KEY `workplace_visit_requests_approved_by_foreign` (`approved_by`), + KEY `idx_visit_date` (`visit_date`), + KEY `idx_status` (`status`), + KEY `idx_visit_date_status` (`visit_date`,`status`), + CONSTRAINT `workplace_visit_requests_approved_by_foreign` FOREIGN KEY (`approved_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `workplace_visit_requests_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON UPDATE CASCADE, + CONSTRAINT `workplace_visit_requests_purpose_id_foreign` FOREIGN KEY (`purpose_id`) REFERENCES `visit_purpose_types` (`purpose_id`) ON UPDATE CASCADE, + CONSTRAINT `workplace_visit_requests_requester_id_foreign` FOREIGN KEY (`requester_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE, + CONSTRAINT `workplace_visit_requests_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_visit_requests` +-- + +LOCK TABLES `workplace_visit_requests` WRITE; +/*!40000 ALTER TABLE `workplace_visit_requests` DISABLE KEYS */; +INSERT INTO `workplace_visit_requests` VALUES +(1,1,'test',1,1,2,'2026-01-29','15:48:00',3,NULL,'approved',1,'2026-01-29 05:54:04',NULL,'2026-01-29 05:48:54','2026-01-29 05:54:04'), +(2,1,'테스트',2,1,1,'2026-01-29','16:11:00',2,NULL,'training_completed',1,'2026-01-29 06:11:38',NULL,'2026-01-29 06:11:23','2026-01-29 06:12:11'), +(3,1,'test',2,1,2,'2026-01-30','10:13:00',1,NULL,'approved',1,'2026-01-30 00:13:57',NULL,'2026-01-30 00:13:49','2026-01-30 00:13:57'); +/*!40000 ALTER TABLE `workplace_visit_requests` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_zone_items` +-- + +DROP TABLE IF EXISTS `workplace_zone_items`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_zone_items` ( + `item_id` int(11) NOT NULL AUTO_INCREMENT, + `workplace_id` int(11) NOT NULL, + `item_name` varchar(200) NOT NULL COMMENT '물품/시설물 명칭', + `item_type` varchar(50) DEFAULT 'general' COMMENT '유형 (heavy_equipment, hazardous, storage, general 등)', + `description` text DEFAULT NULL COMMENT '상세 설명', + `x_percent` decimal(5,2) NOT NULL COMMENT '영역 시작 X 좌표 (%)', + `y_percent` decimal(5,2) NOT NULL COMMENT '영역 시작 Y 좌표 (%)', + `width_percent` decimal(5,2) DEFAULT 10.00 COMMENT '영역 너비 (%)', + `height_percent` decimal(5,2) DEFAULT 10.00 COMMENT '영역 높이 (%)', + `color` varchar(20) DEFAULT '#3b82f6' COMMENT '표시 색상', + `warning_level` varchar(20) DEFAULT 'normal' COMMENT '주의 수준 (normal, caution, danger)', + `quantity` int(11) DEFAULT 1 COMMENT '수량', + `unit` varchar(20) DEFAULT '개' COMMENT '단위', + `weight_kg` decimal(10,2) DEFAULT NULL COMMENT '중량 (kg)', + `is_active` tinyint(1) DEFAULT 1, + `created_by` int(11) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`item_id`), + KEY `idx_workplace` (`workplace_id`), + KEY `idx_type` (`item_type`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='구역 내 등록 물품/시설물'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_zone_items` +-- + +LOCK TABLES `workplace_zone_items` WRITE; +/*!40000 ALTER TABLE `workplace_zone_items` DISABLE KEYS */; +INSERT INTO `workplace_zone_items` VALUES +(1,2,'용기 동체(대기중)','temp_storage','',21.28,1.37,77.27,29.64,'#3b82f6','good',1,'개',NULL,1,1,'2026-02-05 06:28:36','2026-02-05 06:28:36'); +/*!40000 ALTER TABLE `workplace_zone_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplaces` +-- + +DROP TABLE IF EXISTS `workplaces`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplaces` ( + `workplace_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '작업장 ID', + `category_id` int(10) unsigned DEFAULT NULL COMMENT '카테고리 ID (공장)', + `workplace_name` varchar(255) NOT NULL COMMENT '작업장명', + `description` text DEFAULT NULL COMMENT '설명', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성화 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '생성일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정일시', + `workplace_purpose` varchar(50) DEFAULT NULL COMMENT '작업장 용도 (작업구역, 설비, 휴게시설, 회의실 등)', + `display_priority` int(11) DEFAULT 0 COMMENT '표시 우선순위 (숫자가 작을수록 먼저 표시)', + `layout_image` varchar(500) DEFAULT NULL COMMENT '작업장 레이아웃 이미지 경로', + PRIMARY KEY (`workplace_id`), + KEY `workplaces_category_id_index` (`category_id`), + KEY `workplaces_is_active_index` (`is_active`), + CONSTRAINT `workplaces_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplaces` +-- + +LOCK TABLES `workplaces` WRITE; +/*!40000 ALTER TABLE `workplaces` DISABLE KEYS */; +INSERT INTO `workplaces` VALUES +(1,1,'서스작업장',NULL,1,'2026-01-26 05:29:18','2026-01-26 23:28:46','작업구역',1,NULL), +(2,1,'조립구역',NULL,1,'2026-01-26 05:29:30','2026-02-04 00:26:04','작업구역',0,'/uploads/workplace-layout-1770162560033-681774067.jpg'), +(3,1,'외부작업장',NULL,1,'2026-01-26 05:29:36','2026-01-26 23:28:35','작업구역',2,NULL), +(4,1,'입고장',NULL,1,'2026-01-26 05:29:41','2026-01-26 23:28:30','작업구역',2,NULL), +(5,1,'생산팀 창고',NULL,1,'2026-01-26 05:29:48','2026-01-26 23:28:16','창고',3,NULL), +(6,1,'검사장비 창고',NULL,1,'2026-01-26 05:29:57','2026-01-26 23:28:21','창고',3,NULL), +(7,1,'2층 가공장',NULL,1,'2026-01-26 05:30:04','2026-01-26 23:28:08','작업구역',2,NULL), +(8,1,'1층 가공장',NULL,1,'2026-01-26 05:30:09','2026-01-26 23:25:00','작업구역',2,NULL), +(9,1,'조방A',NULL,1,'2026-01-26 05:30:17','2026-01-26 23:24:56','작업구역',1,NULL), +(10,1,'조방B',NULL,1,'2026-01-26 05:30:26','2026-01-26 23:24:51','작업구역',1,NULL), +(11,1,'NDE룸',NULL,1,'2026-01-26 05:30:36','2026-01-26 23:24:45','설비',2,NULL), +(12,1,'휴게실',NULL,1,'2026-01-26 05:30:44','2026-01-26 23:24:38','휴게시설',3,NULL), +(13,NULL,'테스트 구역',NULL,1,'2026-02-05 06:48:37','2026-02-05 06:48:37','설비',0,NULL); +/*!40000 ALTER TABLE `workplaces` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping routines for database 'hyungi' +-- +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-02-05 23:53:06 diff --git a/deploy/deploy.sh b/deploy/deploy.sh new file mode 100755 index 0000000..1157b20 --- /dev/null +++ b/deploy/deploy.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# ============================================================================= +# TK-FB-Project Synology NAS 배포 스크립트 +# ============================================================================= + +set -e + +echo "==========================================" +echo "TK-FB-Project 배포 시작" +echo "==========================================" + +# 1. 환경 변수 파일 확인 +if [ ! -f .env ]; then + echo "❌ .env 파일이 없습니다." + echo " .env.synology 파일을 복사하고 값을 수정하세요:" + echo " cp .env.synology .env" + exit 1 +fi + +# 2. Cloudflare Tunnel 토큰 확인 +if grep -q "여기에_터널_토큰_입력" .env; then + echo "⚠️ Cloudflare Tunnel 토큰이 설정되지 않았습니다." + echo " .env 파일에서 CLOUDFLARE_TUNNEL_TOKEN을 설정하세요." +fi + +# 3. Docker 이미지 빌드 +echo "" +echo "🔨 Docker 이미지 빌드 중..." +docker-compose -f docker-compose.synology.yml build --no-cache + +# 4. 기존 컨테이너 중지 +echo "" +echo "🛑 기존 컨테이너 중지 중..." +docker-compose -f docker-compose.synology.yml down 2>/dev/null || true + +# 5. 컨테이너 시작 +echo "" +echo "🚀 컨테이너 시작 중..." +docker-compose -f docker-compose.synology.yml up -d + +# 6. DB 초기화 대기 +echo "" +echo "⏳ 데이터베이스 초기화 대기 중 (30초)..." +sleep 30 + +# 7. 데이터베이스 복원 (백업 파일이 있는 경우) +BACKUP_FILE=$(ls -t backup_*.sql 2>/dev/null | head -1) +if [ -n "$BACKUP_FILE" ]; then + echo "" + echo "📦 데이터베이스 복원 중: $BACKUP_FILE" + docker exec -i tkfb_db mysql -u root -p"$MYSQL_ROOT_PASSWORD" < "$BACKUP_FILE" + echo "✅ 데이터베이스 복원 완료" +fi + +# 8. 상태 확인 +echo "" +echo "==========================================" +echo "📊 컨테이너 상태" +echo "==========================================" +docker-compose -f docker-compose.synology.yml ps + +echo "" +echo "==========================================" +echo "✅ 배포 완료!" +echo "==========================================" +echo "" +echo "접속 URL:" +echo " - Web UI: http://localhost:80" +echo " - API: http://localhost:3005" +echo " - phpMyAdmin: http://localhost:8080" +echo "" +echo "Cloudflare Tunnel 설정 시:" +echo " - 외부 접속: https://your-domain.com" +echo "" diff --git a/deploy/docker-compose.synology.yml b/deploy/docker-compose.synology.yml new file mode 100644 index 0000000..6adf764 --- /dev/null +++ b/deploy/docker-compose.synology.yml @@ -0,0 +1,150 @@ +version: "3.8" + +services: + # MariaDB 데이터베이스 + db: + image: mariadb:10.9 + container_name: tkfb_db + restart: unless-stopped + environment: + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} + - MYSQL_DATABASE=${MYSQL_DATABASE:-hyungi} + - MYSQL_USER=${MYSQL_USER:-hyungi_user} + - MYSQL_PASSWORD=${MYSQL_PASSWORD} + volumes: + - db_data:/var/lib/mysql + - ./init-db:/docker-entrypoint-initdb.d + ports: + - "3306:3306" + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + timeout: 20s + retries: 10 + networks: + - tkfb_network + + # Node.js API 서버 + api: + build: + context: ./api.hyungi.net + dockerfile: Dockerfile + container_name: tkfb_api + env_file: + - ./.env + depends_on: + db: + condition: service_healthy + redis: + condition: service_started + restart: unless-stopped + ports: + - "3005:3005" + environment: + - NODE_ENV=production + - PORT=3005 + - DB_HOST=db + - DB_PORT=3306 + - DB_USER=${MYSQL_USER:-hyungi_user} + - DB_PASSWORD=${MYSQL_PASSWORD} + - DB_NAME=${MYSQL_DATABASE:-hyungi} + - DB_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} + - JWT_SECRET=${JWT_SECRET} + - JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-7d} + - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET} + - JWT_REFRESH_EXPIRES_IN=${JWT_REFRESH_EXPIRES_IN:-30d} + - REDIS_HOST=redis + - REDIS_PORT=6379 + - WEATHER_API_URL=${WEATHER_API_URL:-} + - WEATHER_API_KEY=${WEATHER_API_KEY:-} + volumes: + - ./api.hyungi.net/uploads:/usr/src/app/uploads + - ./api.hyungi.net/logs:/usr/src/app/logs + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + networks: + - tkfb_network + + # Web UI (Nginx) + web: + build: + context: ./web-ui + dockerfile: Dockerfile + container_name: tkfb_web + restart: unless-stopped + ports: + - "80:80" + volumes: + - ./web-ui:/usr/share/nginx/html:ro + depends_on: + - api + networks: + - tkfb_network + + # FastAPI Bridge + fastapi: + build: + context: ./fastapi-bridge + dockerfile: Dockerfile + container_name: tkfb_fastapi + restart: unless-stopped + ports: + - "8000:8000" + environment: + - API_BASE_URL=http://api:3005 + depends_on: + - api + networks: + - tkfb_network + + # Redis Cache + redis: + image: redis:6-alpine + container_name: tkfb_redis + restart: unless-stopped + expose: + - "6379" + networks: + - tkfb_network + + # Cloudflare Tunnel + cloudflared: + image: cloudflare/cloudflared:latest + container_name: tkfb_cloudflared + restart: unless-stopped + command: tunnel --no-autoupdate run + environment: + - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN} + depends_on: + - web + - api + networks: + - tkfb_network + + # phpMyAdmin (선택사항 - 보안상 제거 권장) + phpmyadmin: + image: phpmyadmin/phpmyadmin:latest + container_name: tkfb_phpmyadmin + depends_on: + - db + restart: unless-stopped + ports: + - "8080:80" + environment: + - PMA_HOST=db + - PMA_USER=root + - PMA_PASSWORD=${MYSQL_ROOT_PASSWORD} + - UPLOAD_LIMIT=50M + networks: + - tkfb_network + +volumes: + db_data: + driver: local + +networks: + tkfb_network: + driver: bridge + name: tkfb_network diff --git a/deploy/package.sh b/deploy/package.sh new file mode 100755 index 0000000..bb53dd9 --- /dev/null +++ b/deploy/package.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# ============================================================================= +# 배포 패키지 생성 스크립트 +# ============================================================================= + +set -e +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(dirname "$SCRIPT_DIR")" +DEPLOY_DIR="$SCRIPT_DIR" +PACKAGE_DIR="$DEPLOY_DIR/tkfb-package" + +echo "==========================================" +echo "배포 패키지 생성" +echo "==========================================" + +# 기존 패키지 삭제 +rm -rf "$PACKAGE_DIR" +mkdir -p "$PACKAGE_DIR" + +# 1. Docker 설정 파일 +echo "📦 Docker 설정 복사..." +cp "$DEPLOY_DIR/docker-compose.synology.yml" "$PACKAGE_DIR/docker-compose.yml" +cp "$DEPLOY_DIR/.env.synology" "$PACKAGE_DIR/.env.example" +cp "$DEPLOY_DIR/deploy.sh" "$PACKAGE_DIR/" +cp "$DEPLOY_DIR/README.md" "$PACKAGE_DIR/" + +# 2. 데이터베이스 백업 +echo "📦 DB 백업 복사..." +cp "$DEPLOY_DIR"/backup_*.sql "$PACKAGE_DIR/" 2>/dev/null || echo "⚠️ DB 백업 파일 없음" + +# 3. 소스 코드 +echo "📦 소스 코드 복사..." + +# API +mkdir -p "$PACKAGE_DIR/api.hyungi.net" +rsync -a --exclude='node_modules' --exclude='logs/*' --exclude='.git' \ + "$PROJECT_DIR/api.hyungi.net/" "$PACKAGE_DIR/api.hyungi.net/" + +# Web UI +mkdir -p "$PACKAGE_DIR/web-ui" +rsync -a --exclude='.git' \ + "$PROJECT_DIR/web-ui/" "$PACKAGE_DIR/web-ui/" +# 프로덕션 config 복사 +cp "$DEPLOY_DIR/web-ui-config.js" "$PACKAGE_DIR/web-ui/js/config.js" + +# FastAPI +mkdir -p "$PACKAGE_DIR/fastapi-bridge" +rsync -a --exclude='__pycache__' --exclude='.git' --exclude='venv' \ + "$PROJECT_DIR/fastapi-bridge/" "$PACKAGE_DIR/fastapi-bridge/" + +# 4. init-db 폴더 생성 (초기 스키마용) +mkdir -p "$PACKAGE_DIR/init-db" +echo "-- 초기 데이터베이스 생성 완료 시 실행됨" > "$PACKAGE_DIR/init-db/README.txt" + +# 5. 압축 +echo "📦 압축 중..." +cd "$DEPLOY_DIR" +TIMESTAMP=$(date +%Y%m%d_%H%M%S) +tar -czf "tkfb-deploy-$TIMESTAMP.tar.gz" -C "$DEPLOY_DIR" tkfb-package + +# 크기 확인 +echo "" +echo "==========================================" +echo "✅ 패키지 생성 완료!" +echo "==========================================" +ls -lh "$DEPLOY_DIR/tkfb-deploy-$TIMESTAMP.tar.gz" +echo "" +echo "파일: $DEPLOY_DIR/tkfb-deploy-$TIMESTAMP.tar.gz" +echo "" +echo "Synology NAS로 전송:" +echo " scp $DEPLOY_DIR/tkfb-deploy-$TIMESTAMP.tar.gz admin@nas:/volume1/docker/" diff --git a/deploy/tkfb-package/.env.example b/deploy/tkfb-package/.env.example new file mode 100644 index 0000000..b1cd8fb --- /dev/null +++ b/deploy/tkfb-package/.env.example @@ -0,0 +1,34 @@ +# ============================================================================= +# Synology NAS 배포용 환경 변수 +# ============================================================================= + +# 데이터베이스 설정 +MYSQL_ROOT_PASSWORD=변경필수_강력한비밀번호 +MYSQL_DATABASE=hyungi +MYSQL_USER=hyungi_user +MYSQL_PASSWORD=변경필수_강력한비밀번호 + +# API 서버 설정 +NODE_ENV=production +PORT=3005 +DB_HOST=db +DB_PORT=3306 +DB_USER=hyungi_user +DB_PASSWORD=변경필수_강력한비밀번호 +DB_NAME=hyungi + +# JWT 인증 설정 (새로 생성 권장: openssl rand -base64 32) +JWT_SECRET=변경필수_최소32자이상_랜덤문자열 +JWT_EXPIRES_IN=7d +JWT_REFRESH_SECRET=변경필수_최소32자이상_랜덤문자열 +JWT_REFRESH_EXPIRES_IN=30d + +# FastAPI 설정 +API_BASE_URL=http://api:3005 + +# Cloudflare Tunnel 토큰 (Cloudflare 대시보드에서 발급) +CLOUDFLARE_TUNNEL_TOKEN=여기에_터널_토큰_입력 + +# 기상청 API (선택사항) +WEATHER_API_URL=https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0 +WEATHER_API_KEY= diff --git a/deploy/tkfb-package/README.md b/deploy/tkfb-package/README.md new file mode 100644 index 0000000..cbc692a --- /dev/null +++ b/deploy/tkfb-package/README.md @@ -0,0 +1,137 @@ +# TK-FB-Project Synology NAS 배포 가이드 + +## 사전 준비 + +### 1. Synology NAS 요구사항 +- DSM 7.0 이상 +- Docker 패키지 설치 +- 최소 4GB RAM 권장 +- 10GB 이상 저장공간 + +### 2. Cloudflare Tunnel 설정 + +1. **Cloudflare 대시보드 접속** + - https://dash.cloudflare.com 로그인 + - Zero Trust > Access > Tunnels 이동 + +2. **터널 생성** + - "Create a tunnel" 클릭 + - 이름 입력 (예: tkfb-nas) + - 환경: Docker 선택 + - 표시되는 토큰을 `.env` 파일의 `CLOUDFLARE_TUNNEL_TOKEN`에 입력 + +3. **Public hostname 설정** + - 터널 설정에서 "Public Hostnames" 추가 + + | Subdomain | Domain | Service | + |-----------|--------|---------| + | tkfb | yourdomain.com | http://web:80 | + | api.tkfb | yourdomain.com | http://api:3005 | + +## 배포 순서 + +### 1. 파일 전송 +Synology NAS의 docker 폴더에 다음 파일들을 업로드: + +``` +/volume1/docker/tkfb/ +├── docker-compose.synology.yml (→ docker-compose.yml로 이름 변경) +├── .env (→ .env.synology 복사 후 수정) +├── backup_YYYYMMDD_HHMMSS.sql +├── api.hyungi.net/ +├── web-ui/ +└── fastapi-bridge/ +``` + +### 2. 환경 변수 설정 +```bash +cd /volume1/docker/tkfb +cp .env.synology .env +# .env 파일 편집하여 비밀번호, 토큰 등 수정 +``` + +### 3. Docker Compose 실행 +```bash +# SSH로 NAS 접속 후 +cd /volume1/docker/tkfb + +# 이미지 빌드 및 시작 +docker-compose up -d --build + +# 로그 확인 +docker-compose logs -f +``` + +### 4. 데이터베이스 복원 +```bash +# DB 컨테이너가 시작된 후 (약 30초 대기) +docker exec -i tkfb_db mysql -u root -p'비밀번호' < backup_YYYYMMDD_HHMMSS.sql +``` + +## 포트 설정 + +| 서비스 | 내부포트 | 외부포트 | 설명 | +|--------|----------|----------|------| +| web | 80 | 80 | Web UI | +| api | 3005 | 3005 | Node.js API | +| fastapi | 8000 | 8000 | FastAPI Bridge | +| db | 3306 | 3306 | MariaDB | +| phpmyadmin | 80 | 8080 | DB 관리도구 | + +## Cloudflare Tunnel 사용 시 + +Cloudflare Tunnel을 사용하면 포트 포워딩 없이 외부 접속이 가능합니다: +- 방화벽 포트 개방 불필요 +- 자동 HTTPS 인증서 +- DDoS 보호 + +### web-ui의 API 주소 변경 + +`web-ui/js/config.js` 또는 관련 설정 파일에서 API URL을 변경: + +```javascript +// 로컬 테스트 +const API_URL = 'http://localhost:3005'; + +// Cloudflare Tunnel 사용 시 +const API_URL = 'https://api.tkfb.yourdomain.com'; +``` + +## 문제 해결 + +### 1. 컨테이너 상태 확인 +```bash +docker-compose ps +docker-compose logs api # API 로그 +docker-compose logs db # DB 로그 +``` + +### 2. 데이터베이스 연결 오류 +```bash +# DB 컨테이너 재시작 +docker-compose restart db + +# DB 상태 확인 +docker exec tkfb_db mysqladmin -u root -p ping +``` + +### 3. 권한 오류 +```bash +# 볼륨 권한 설정 +chmod -R 755 /volume1/docker/tkfb +chown -R 1000:1000 /volume1/docker/tkfb/api.hyungi.net/uploads +``` + +## 업데이트 + +```bash +cd /volume1/docker/tkfb + +# 최신 코드 다운로드 후 +docker-compose down +docker-compose up -d --build + +# 캐시 포함 전체 재빌드 +docker-compose build --no-cache +docker-compose up -d +``` diff --git a/deploy/tkfb-package/api.hyungi.net/.dockerignore b/deploy/tkfb-package/api.hyungi.net/.dockerignore new file mode 100644 index 0000000..edd83c0 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/.dockerignore @@ -0,0 +1,4 @@ +node_modules +npm-debug.log +Dockerfile +.dockerignore \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/DEPLOY.md b/deploy/tkfb-package/api.hyungi.net/DEPLOY.md new file mode 100644 index 0000000..9f8a4b0 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/DEPLOY.md @@ -0,0 +1,199 @@ +# API 서버 배포 가이드 + +## 자동 배포 (권장) + +### 1. 배포 스크립트 실행 + +```bash +cd api.hyungi.net + +# 처음 한 번만: 실행 권한 부여 +chmod +x deploy.sh + +# 배포 실행 +./deploy.sh +``` + +배포 스크립트는 다음을 자동으로 처리합니다: +1. ✅ Git Pull +2. ✅ NPM Install (package.json 변경 시) +3. ✅ 데이터베이스 마이그레이션 (확인 후 실행) +4. ✅ PM2 서버 재시작 +5. ✅ 상태 확인 + +--- + +## 수동 배포 + +### 1. Git Pull +```bash +cd api.hyungi.net +git pull +``` + +### 2. 의존성 설치 (package.json 변경 시) +```bash +npm install +``` + +### 3. 데이터베이스 마이그레이션 + +⚠️ **중요**: 마이그레이션 전 데이터베이스 백업을 권장합니다! + +```bash +# 마이그레이션 실행 +npm run db:migrate + +# 마이그레이션 롤백 (문제 발생 시) +npm run db:rollback +``` + +### 4. PM2 서버 재시작 + +```bash +# 무중단 재시작 (권장) +pm2 reload ecosystem.config.js --env production + +# 또는 일반 재시작 +pm2 restart hyungi-api + +# 서버 중지 후 시작 +pm2 stop hyungi-api +pm2 start ecosystem.config.js --env production +``` + +--- + +## 배포 후 확인사항 + +### 1. 서버 상태 확인 +```bash +# PM2 프로세스 목록 +pm2 list + +# 실시간 로그 확인 +pm2 logs hyungi-api + +# 에러 로그만 확인 +pm2 logs hyungi-api --err +``` + +### 2. API 응답 확인 +```bash +# Health Check +curl http://localhost:20005/health + +# 또는 +curl http://api.hyungi.net/health +``` + +### 3. 마이그레이션 상태 확인 +```bash +# 현재 마이그레이션 버전 확인 +npx knex migrate:currentVersion --knexfile knexfile.js + +# 적용된 마이그레이션 목록 +npx knex migrate:list --knexfile knexfile.js +``` + +--- + +## 문제 해결 + +### 마이그레이션 실패 시 + +1. **에러 로그 확인** + ```bash + pm2 logs hyungi-api --err + ``` + +2. **마이그레이션 롤백** + ```bash + npm run db:rollback + ``` + +3. **특정 마이그레이션만 실행** + ```bash + npx knex migrate:up 20260119095549_add_worker_display_fields.js --knexfile knexfile.js + ``` + +### 서버 시작 실패 시 + +1. **포트 충돌 확인** + ```bash + lsof -i :20005 + ``` + +2. **PM2 프로세스 완전 삭제 후 재시작** + ```bash + pm2 delete hyungi-api + pm2 start ecosystem.config.js --env production + ``` + +3. **환경변수 확인** + ```bash + cat .env + ``` + +--- + +## 환경별 배포 + +### Development (개발) +```bash +NODE_ENV=development npm run db:migrate +pm2 reload ecosystem.config.js --env development +``` + +### Production (운영) +```bash +NODE_ENV=production npm run db:migrate +pm2 reload ecosystem.config.js --env production +``` + +--- + +## 데이터베이스 백업 + +### 백업 생성 +```bash +# MySQL 백업 +mysqldump -h DB_HOST -u DB_USER -p DB_NAME > backup_$(date +%Y%m%d_%H%M%S).sql +``` + +### 백업 복구 +```bash +mysql -h DB_HOST -u DB_USER -p DB_NAME < backup_20260119_120000.sql +``` + +--- + +## CI/CD 자동화 (향후 개선안) + +GitHub Actions 또는 GitLab CI/CD를 사용한 자동 배포: + +```yaml +# .github/workflows/deploy.yml 예시 +name: Deploy to Production + +on: + push: + branches: [ master ] + +jobs: + deploy: + runs-on: ubuntu-latest + steps: + - name: SSH and Deploy + run: | + ssh user@server 'cd /path/to/api.hyungi.net && ./deploy.sh' +``` + +--- + +## 참고사항 + +- **마이그레이션은 한 방향으로만 진행** (forward-only) +- **rollback은 개발 환경에서만 사용 권장** +- **운영 환경에서는 반드시 백업 후 마이그레이션** +- **PM2 reload는 무중단 재시작** (downtime 없음) diff --git a/deploy/tkfb-package/api.hyungi.net/Dockerfile b/deploy/tkfb-package/api.hyungi.net/Dockerfile new file mode 100644 index 0000000..5ce8317 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/Dockerfile @@ -0,0 +1,33 @@ +# Node.js 공식 이미지 사용 +FROM node:18-alpine + +# 작업 디렉토리 설정 +WORKDIR /usr/src/app + +# 패키지 파일 복사 (캐싱 최적화) +COPY package*.json ./ + +# 프로덕션 의존성만 설치 +RUN npm ci --only=production + +# 앱 소스 복사 +COPY . . + +# 로그 디렉토리 생성 +RUN mkdir -p logs uploads + +# 실행 권한 설정 +RUN chown -R node:node /usr/src/app + +# 보안을 위해 non-root 사용자로 실행 +USER node + +# 포트 노출 +EXPOSE 3005 + +# 헬스체크 추가 +HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \ + CMD node -e "require('http').get('http://localhost:3005/api/health', (res) => { process.exit(res.statusCode === 200 ? 0 : 1); })" + +# 앱 시작 +CMD ["node", "index.js"] \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/config/cors.js b/deploy/tkfb-package/api.hyungi.net/config/cors.js new file mode 100644 index 0000000..a6ba58f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/config/cors.js @@ -0,0 +1,89 @@ +/** + * CORS 설정 + * + * Cross-Origin Resource Sharing 설정 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const logger = require('../utils/logger'); + +/** + * 허용된 Origin 목록 + */ +const allowedOrigins = [ + 'http://localhost:20000', // 웹 UI + 'http://localhost:3005', // API 서버 + 'http://localhost:3000', // 개발 포트 + 'http://127.0.0.1:20000', // 로컬호스트 대체 + 'http://127.0.0.1:3005', + 'http://127.0.0.1:3000' +]; + +/** + * CORS 설정 옵션 + */ +const corsOptions = { + /** + * Origin 검증 함수 + */ + origin: function (origin, callback) { + // Origin이 없는 경우 (직접 접근, Postman 등) + if (!origin) { + logger.debug('CORS: Origin 없음 - 허용'); + return callback(null, true); + } + + // 허용된 Origin 확인 + if (allowedOrigins.includes(origin)) { + logger.debug('CORS: 허용된 Origin', { origin }); + return callback(null, true); + } + + // 개발 환경에서는 모든 localhost 허용 + if (process.env.NODE_ENV === 'development') { + if (origin.includes('localhost') || origin.includes('127.0.0.1')) { + logger.debug('CORS: 로컬호스트 허용 (개발 모드)', { origin }); + return callback(null, true); + } + } + + // 로컬 네트워크 IP 자동 허용 (192.168.x.x) + if (origin.match(/^http:\/\/192\.168\.\d+\.\d+(:\d+)?$/)) { + logger.debug('CORS: 로컬 네트워크 IP 허용', { origin }); + return callback(null, true); + } + + // 차단 + logger.warn('CORS: 차단된 Origin', { origin }); + callback(new Error(`CORS 정책에 의해 차단됨: ${origin}`)); + }, + + /** + * 인증 정보 포함 허용 + */ + credentials: true, + + /** + * 허용된 HTTP 메소드 + */ + methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'], + + /** + * 허용된 헤더 + */ + allowedHeaders: ['Content-Type', 'Authorization', 'X-Requested-With'], + + /** + * 노출할 헤더 + */ + exposedHeaders: ['Content-Range', 'X-Content-Range'], + + /** + * Preflight 요청 캐시 시간 (초) + */ + maxAge: 86400 // 24시간 +}; + +module.exports = corsOptions; diff --git a/deploy/tkfb-package/api.hyungi.net/config/database.js b/deploy/tkfb-package/api.hyungi.net/config/database.js new file mode 100644 index 0000000..f7200ac --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/config/database.js @@ -0,0 +1,79 @@ +/** + * 데이터베이스 연결 설정 + * + * MySQL/MariaDB 커넥션 풀 관리 + * - 환경 변수 기반 설정 + * - 자동 재연결 (최대 5회 재시도) + * - UTF-8MB4 문자셋 지원 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +require('dotenv').config(); +const mysql = require('mysql2/promise'); +const retry = require('async-retry'); +const logger = require('../utils/logger'); + +let pool = null; + +async function initPool() { + if (pool) return pool; + + const { + DB_HOST, DB_PORT, DB_USER, + DB_PASSWORD, DB_NAME, + DB_SOCKET, DB_CONN_LIMIT = '10' + } = process.env; + + if (!DB_USER || !DB_PASSWORD || !DB_NAME) { + throw new Error('필수 환경변수(DB_USER, DB_PASSWORD, DB_NAME)가 없습니다.'); + } + if (!DB_SOCKET && !DB_HOST) { + throw new Error('DB_SOCKET이 없으면 DB_HOST가 반드시 필요합니다.'); + } + + await retry(async () => { + const config = { + user: DB_USER, + password: DB_PASSWORD, + database: DB_NAME, + waitForConnections: true, + connectionLimit: parseInt(DB_CONN_LIMIT, 10), + queueLimit: 0, + charset: 'utf8mb4' + }; + if (DB_SOCKET) { + config.socketPath = DB_SOCKET; + } else { + config.host = DB_HOST; + config.port = parseInt(DB_PORT, 10); + } + + pool = mysql.createPool(config); + + // 첫 연결 검증 + const conn = await pool.getConnection(); + await conn.query('SET NAMES utf8mb4'); + conn.release(); + + const connectionInfo = DB_SOCKET ? `socket=${DB_SOCKET}` : `${DB_HOST}:${DB_PORT}`; + logger.info('MariaDB 연결 성공', { + connection: connectionInfo, + database: DB_NAME, + connectionLimit: parseInt(DB_CONN_LIMIT, 10) + }); + }, { + retries: 5, + factor: 2, + minTimeout: 1000 + }); + + return pool; +} + +async function getDb() { + return initPool(); +} + +module.exports = { getDb }; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/config/middleware.js b/deploy/tkfb-package/api.hyungi.net/config/middleware.js new file mode 100644 index 0000000..83b8eb6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/config/middleware.js @@ -0,0 +1,115 @@ +/** + * 미들웨어 설정 + * + * Express 애플리케이션의 모든 미들웨어를 등록하는 중앙화된 설정 파일 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const express = require('express'); +const cors = require('cors'); +const helmet = require('helmet'); +const compression = require('compression'); +const path = require('path'); +const helmetOptions = require('./security'); +const corsOptions = require('./cors'); +const { responseMiddleware } = require('../utils/responseFormatter'); +const logger = require('../utils/logger'); + +/** + * 모든 미들웨어를 Express 앱에 등록 + * @param {Express.Application} app - Express 애플리케이션 인스턴스 + */ +function setupMiddlewares(app) { + // 보안 헤더 설정 (Helmet) + app.use(helmet(helmetOptions)); + + // 성능 최적화 - Compression + app.use(compression({ + filter: (req, res) => { + if (req.headers['x-no-compression']) { + return false; + } + return compression.filter(req, res); + }, + level: 6, // 압축 레벨 (1-9, 6이 기본값) + threshold: 1024 // 1KB 이상만 압축 + })); + + // 요청 바디 파싱 - 용량 제한 확장 + app.use(express.urlencoded({ extended: true, limit: '50mb' })); + app.use(express.json({ limit: '50mb' })); + + // 응답 포맷터 미들웨어 + app.use(responseMiddleware); + + // CORS 설정 + app.use(cors(corsOptions)); + + // 정적 파일 서빙 + app.use(express.static(path.join(__dirname, '../public'))); + app.use('/uploads', express.static(path.join(__dirname, '../uploads'))); + + // Rate Limiting - API 요청 제한 + const rateLimit = require('express-rate-limit'); + + // 일반 API 요청 제한 + const apiLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15분 + max: 1000, // IP당 최대 1000 요청 (일괄 처리 지원) + message: { + success: false, + error: '너무 많은 요청입니다. 잠시 후 다시 시도해주세요.', + code: 'RATE_LIMIT_EXCEEDED' + }, + standardHeaders: true, + legacyHeaders: false, + // 인증된 사용자는 더 많은 요청 허용 + skip: (req) => { + // Authorization 헤더가 있으면 Rate Limit 완화 + return req.headers.authorization && req.headers.authorization.startsWith('Bearer '); + } + }); + + // 로그인 시도 제한 (브루트포스 방지) + const loginLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15분 + max: 10, // IP당 최대 10회 로그인 시도 + message: { + success: false, + error: '로그인 시도 횟수를 초과했습니다. 15분 후 다시 시도해주세요.', + code: 'LOGIN_RATE_LIMIT_EXCEEDED' + }, + standardHeaders: true, + legacyHeaders: false + }); + + // Rate limiter 적용 + app.use('/api/', apiLimiter); + app.use('/api/auth/login', loginLimiter); + + logger.info('Rate Limiting 설정 완료'); + + // CSRF Protection (선택적 - 필요 시 주석 해제) + // const { verifyCsrfToken, getCsrfToken } = require('../middlewares/csrf'); + // + // CSRF 토큰 발급 엔드포인트 + // app.get('/api/csrf-token', getCsrfToken); + // + // CSRF 검증 미들웨어 (로그인 등 일부 경로 제외) + // app.use('/api/', verifyCsrfToken({ + // ignorePaths: [ + // '/api/auth/login', + // '/api/auth/register', + // '/api/health', + // '/api/csrf-token' + // ] + // })); + // + // logger.info('CSRF Protection 설정 완료'); + + logger.info('미들웨어 설정 완료'); +} + +module.exports = setupMiddlewares; diff --git a/deploy/tkfb-package/api.hyungi.net/config/routes.js b/deploy/tkfb-package/api.hyungi.net/config/routes.js new file mode 100644 index 0000000..f5cdb88 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/config/routes.js @@ -0,0 +1,192 @@ +/** + * 라우트 설정 + * + * 애플리케이션의 모든 라우트를 등록하는 중앙화된 설정 파일 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const swaggerUi = require('swagger-ui-express'); +const swaggerSpec = require('./swagger'); +const { verifyToken } = require('../middlewares/authMiddleware'); +const { activityLogger } = require('../middlewares/activityLogger'); +const logger = require('../utils/logger'); + +/** + * 모든 라우트를 Express 앱에 등록 + * @param {Express.Application} app - Express 애플리케이션 인스턴스 + */ +function setupRoutes(app) { + // 라우터 가져오기 + const authRoutes = require('../routes/authRoutes'); + const projectRoutes = require('../routes/projectRoutes'); + const workerRoutes = require('../routes/workerRoutes'); + const workReportRoutes = require('../routes/workReportRoutes'); + const toolsRoute = require('../routes/toolsRoute'); + const uploadRoutes = require('../routes/uploadRoutes'); + const uploadBgRoutes = require('../routes/uploadBgRoutes'); + const dailyIssueReportRoutes = require('../routes/dailyIssueReportRoutes'); + const issueTypeRoutes = require('../routes/issueTypeRoutes'); + const healthRoutes = require('../routes/healthRoutes'); + const dailyWorkReportRoutes = require('../routes/dailyWorkReportRoutes'); + const workAnalysisRoutes = require('../routes/workAnalysisRoutes'); + const analysisRoutes = require('../routes/analysisRoutes'); + const systemRoutes = require('../routes/systemRoutes'); + const performanceRoutes = require('../routes/performanceRoutes'); + const userRoutes = require('../routes/userRoutes'); + const setupRoutes = require('../routes/setupRoutes'); + const workReportAnalysisRoutes = require('../routes/workReportAnalysisRoutes'); + const attendanceRoutes = require('../routes/attendanceRoutes'); + const monthlyStatusRoutes = require('../routes/monthlyStatusRoutes'); + const pageAccessRoutes = require('../routes/pageAccessRoutes'); + const workplaceRoutes = require('../routes/workplaceRoutes'); + const equipmentRoutes = require('../routes/equipmentRoutes'); + const taskRoutes = require('../routes/taskRoutes'); + const tbmRoutes = require('../routes/tbmRoutes'); + const vacationRequestRoutes = require('../routes/vacationRequestRoutes'); + const vacationTypeRoutes = require('../routes/vacationTypeRoutes'); + const vacationBalanceRoutes = require('../routes/vacationBalanceRoutes'); + const visitRequestRoutes = require('../routes/visitRequestRoutes'); + const workIssueRoutes = require('../routes/workIssueRoutes'); + const departmentRoutes = require('../routes/departmentRoutes'); + const patrolRoutes = require('../routes/patrolRoutes'); + const notificationRoutes = require('../routes/notificationRoutes'); + const notificationRecipientRoutes = require('../routes/notificationRecipientRoutes'); + + // Rate Limiters 설정 + const rateLimit = require('express-rate-limit'); + + const loginLimiter = rateLimit({ + windowMs: 15 * 60 * 1000, // 15분 + max: 5, // 최대 5회 + message: '너무 많은 로그인 시도가 있었습니다. 잠시 후 다시 시도해주세요.', + standardHeaders: true, + legacyHeaders: false + }); + + const apiLimiter = rateLimit({ + windowMs: 1 * 60 * 1000, // 1분 + max: 1000, // 최대 1000회 (기존 100회에서 대폭 증가) + message: 'API 요청 한도를 초과했습니다. 잠시 후 다시 시도해주세요.', + standardHeaders: true, + legacyHeaders: false, + // 관리자 및 시스템 계정은 rate limit 제외 + skip: (req) => { + // 인증된 사용자 정보 확인 + if (req.user && (req.user.access_level === 'system' || req.user.access_level === 'admin')) { + return true; // rate limit 건너뛰기 + } + return false; + } + }); + + // 모든 API 요청에 활동 로거 적용 + app.use('/api/*', activityLogger); + + // 인증 불필요 경로 - 로그인 + app.use('/api/auth', loginLimiter, authRoutes); + + // DB 설정 라우트 (개발용) + app.use('/api/setup', setupRoutes); + + // Health check + app.use('/api/health', healthRoutes); + + // 인증이 필요 없는 공개 경로 목록 + const publicPaths = [ + '/api/auth/login', + '/api/auth/refresh-token', + '/api/auth/check-password-strength', + '/api/health', + '/api/ping', + '/api/status', + '/api/setup/setup-attendance-db', + '/api/setup/setup-monthly-status', + '/api/setup/add-overtime-warning', + '/api/setup/migrate-existing-data', + '/api/setup/check-data-status', + '/api/monthly-status/calendar', + '/api/monthly-status/daily-details', + '/api/migrate-work-type-id', // 임시 마이그레이션 - 실행 후 삭제! + '/api/diagnose-work-type-id', // 임시 진단 - 실행 후 삭제! + '/api/test-analysis' // 임시 분석 테스트 - 실행 후 삭제! + ]; + + // 인증 미들웨어 - 공개 경로를 제외한 모든 API (rate limiter보다 먼저 실행) + app.use('/api/*', (req, res, next) => { + const isPublicPath = publicPaths.some(path => { + return req.originalUrl === path || + req.originalUrl.startsWith(path + '?') || + req.originalUrl.startsWith(path + '/'); + }); + + if (isPublicPath) { + logger.debug('공개 경로 허용', { url: req.originalUrl }); + return next(); + } + + logger.debug('인증 필요 경로', { url: req.originalUrl }); + verifyToken(req, res, next); + }); + + // 인증 후 일반 API에 속도 제한 적용 (인증된 사용자 정보로 skip 판단) + app.use('/api/', apiLimiter); + + // 인증된 사용자만 접근 가능한 라우트들 + app.use('/api/issue-reports', dailyIssueReportRoutes); + app.use('/api/issue-types', issueTypeRoutes); + app.use('/api/workers', workerRoutes); + app.use('/api/daily-work-reports', dailyWorkReportRoutes); + app.use('/api/work-analysis', workAnalysisRoutes); + app.use('/api/analysis', analysisRoutes); + app.use('/api/daily-work-reports-analysis', workReportAnalysisRoutes); + app.use('/api/attendance', attendanceRoutes); + app.use('/api/monthly-status', monthlyStatusRoutes); + app.use('/api/workreports', workReportRoutes); + app.use('/api/system', systemRoutes); + app.use('/api/uploads', uploadRoutes); + app.use('/api/performance', performanceRoutes); + app.use('/api/projects', projectRoutes); + app.use('/api/tools', toolsRoute); + app.use('/api/users', userRoutes); + app.use('/api/workplaces', workplaceRoutes); + app.use('/api/equipments', equipmentRoutes); + app.use('/api/tasks', taskRoutes); + app.use('/api/vacation-requests', vacationRequestRoutes); // 휴가 신청 관리 + app.use('/api/vacation-types', vacationTypeRoutes); // 휴가 유형 관리 + app.use('/api/vacation-balances', vacationBalanceRoutes); // 휴가 잔액 관리 + app.use('/api/workplace-visits', visitRequestRoutes); // 출입 신청 및 안전교육 관리 + app.use('/api', pageAccessRoutes); // 페이지 접근 권한 관리 + app.use('/api/tbm', tbmRoutes); // TBM 시스템 + app.use('/api/work-issues', workIssueRoutes); // 문제 신고 시스템 + app.use('/api/departments', departmentRoutes); // 부서 관리 + app.use('/api/patrol', patrolRoutes); // 일일순회점검 시스템 + app.use('/api/notifications', notificationRoutes); // 알림 시스템 + app.use('/api/notification-recipients', notificationRecipientRoutes); // 알림 수신자 설정 + app.use('/api', uploadBgRoutes); + + // Swagger API 문서 + app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpec, { + explorer: true, + customCss: '.swagger-ui .topbar { display: none }', + customSiteTitle: 'TK Work Management API', + swaggerOptions: { + persistAuthorization: true, + displayRequestDuration: true, + docExpansion: 'none', + filter: true, + showExtensions: true, + showCommonExtensions: true + } + })); + + app.get('/api-docs.json', (req, res) => { + res.setHeader('Content-Type', 'application/json'); + res.send(swaggerSpec); + }); + + logger.info('라우트 설정 완료'); +} + +module.exports = setupRoutes; diff --git a/deploy/tkfb-package/api.hyungi.net/config/security.js b/deploy/tkfb-package/api.hyungi.net/config/security.js new file mode 100644 index 0000000..e58037e --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/config/security.js @@ -0,0 +1,101 @@ +/** + * 보안 설정 (Helmet) + * + * HTTP 헤더 보안 설정 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +/** + * Helmet 보안 설정 옵션 + */ +const helmetOptions = { + /** + * Content Security Policy + * XSS 공격 방지 + */ + contentSecurityPolicy: { + directives: { + defaultSrc: ["'self'"], + styleSrc: ["'self'", "'unsafe-inline'", "https://fonts.googleapis.com"], + scriptSrc: ["'self'", "'unsafe-inline'", "'unsafe-eval'"], // 개발 중 unsafe-eval 허용 + imgSrc: ["'self'", "data:", "https:", "blob:"], + fontSrc: ["'self'", "https://fonts.gstatic.com"], + connectSrc: ["'self'", "https://api.technicalkorea.com"], + frameSrc: ["'none'"], + objectSrc: ["'none'"] + } + }, + + /** + * HTTP Strict Transport Security (HSTS) + * HTTPS 강제 사용 + */ + hsts: { + maxAge: 31536000, // 1년 + includeSubDomains: true, + preload: true + }, + + /** + * X-Frame-Options + * 클릭재킹 공격 방지 + */ + frameguard: { + action: 'deny' + }, + + /** + * X-Content-Type-Options + * MIME 타입 스니핑 방지 + */ + noSniff: true, + + /** + * X-XSS-Protection + * XSS 필터 활성화 + */ + xssFilter: true, + + /** + * Referrer-Policy + * 리퍼러 정보 제어 + */ + referrerPolicy: { + policy: 'strict-origin-when-cross-origin' + }, + + /** + * X-DNS-Prefetch-Control + * DNS prefetching 제어 + */ + dnsPrefetchControl: { + allow: false + }, + + /** + * X-Download-Options + * IE8+ 다운로드 옵션 + */ + ieNoOpen: true, + + /** + * X-Permitted-Cross-Domain-Policies + * Adobe 제품의 크로스 도메인 정책 + */ + permittedCrossDomainPolicies: { + permittedPolicies: 'none' + }, + + /** + * Cross-Origin-Resource-Policy + * 크로스 오리진 리소스 공유 설정 + * 이미지 등 정적 파일을 다른 포트에서 로드할 수 있도록 허용 + */ + crossOriginResourcePolicy: { + policy: 'cross-origin' + } +}; + +module.exports = helmetOptions; diff --git a/deploy/tkfb-package/api.hyungi.net/config/swagger.js b/deploy/tkfb-package/api.hyungi.net/config/swagger.js new file mode 100644 index 0000000..ce2621a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/config/swagger.js @@ -0,0 +1,497 @@ +// config/swagger.js - Swagger/OpenAPI 설정 + +const swaggerJSDoc = require('swagger-jsdoc'); + +const swaggerDefinition = { + openapi: '3.0.0', + info: { + title: 'Technical Korea Work Management API', + version: '2.1.0', + description: '보안이 강화된 생산관리 시스템 API - 작업자, 프로젝트, 일일 작업 보고서 관리', + contact: { + name: 'Technical Korea', + email: 'admin@technicalkorea.com' + }, + license: { + name: 'MIT', + url: 'https://opensource.org/licenses/MIT' + } + }, + servers: [ + { + url: 'http://localhost:20005', + description: '개발 서버 (Docker)' + }, + { + url: 'http://localhost:3005', + description: '로컬 개발 서버' + } + ], + components: { + securitySchemes: { + bearerAuth: { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT', + description: 'JWT 토큰을 사용한 인증. 로그인 후 받은 토큰을 "Bearer {token}" 형식으로 입력하세요.' + } + }, + schemas: { + // 공통 응답 스키마 + SuccessResponse: { + type: 'object', + properties: { + success: { + type: 'boolean', + example: true + }, + message: { + type: 'string', + example: '요청이 성공적으로 처리되었습니다.' + }, + data: { + type: 'object', + description: '응답 데이터' + }, + timestamp: { + type: 'string', + format: 'date-time', + example: '2024-01-01T00:00:00.000Z' + } + } + }, + ErrorResponse: { + type: 'object', + properties: { + success: { + type: 'boolean', + example: false + }, + error: { + type: 'string', + example: '오류 메시지' + }, + timestamp: { + type: 'string', + format: 'date-time', + example: '2024-01-01T00:00:00.000Z' + } + } + }, + PaginatedResponse: { + type: 'object', + properties: { + success: { + type: 'boolean', + example: true + }, + message: { + type: 'string', + example: '데이터 조회 성공' + }, + data: { + type: 'array', + items: { + type: 'object' + } + }, + meta: { + type: 'object', + properties: { + pagination: { + type: 'object', + properties: { + currentPage: { type: 'integer', example: 1 }, + totalPages: { type: 'integer', example: 10 }, + totalCount: { type: 'integer', example: 100 }, + limit: { type: 'integer', example: 10 }, + hasNextPage: { type: 'boolean', example: true }, + hasPrevPage: { type: 'boolean', example: false } + } + } + } + }, + timestamp: { + type: 'string', + format: 'date-time' + } + } + }, + + // 사용자 관련 스키마 + User: { + type: 'object', + properties: { + user_id: { + type: 'integer', + example: 1, + description: '사용자 ID' + }, + username: { + type: 'string', + example: 'admin', + description: '사용자명' + }, + name: { + type: 'string', + example: '관리자', + description: '실명' + }, + email: { + type: 'string', + format: 'email', + example: 'admin@technicalkorea.com', + description: '이메일 주소' + }, + role: { + type: 'string', + example: 'admin', + description: '역할' + }, + access_level: { + type: 'string', + enum: ['user', 'admin', 'system'], + example: 'admin', + description: '접근 권한 레벨' + }, + worker_id: { + type: 'integer', + example: 1, + description: '연결된 작업자 ID' + }, + is_active: { + type: 'boolean', + example: true, + description: '활성 상태' + }, + last_login_at: { + type: 'string', + format: 'date-time', + description: '마지막 로그인 시간' + }, + created_at: { + type: 'string', + format: 'date-time', + description: '생성 시간' + }, + updated_at: { + type: 'string', + format: 'date-time', + description: '수정 시간' + } + } + }, + + // 작업자 관련 스키마 + Worker: { + type: 'object', + properties: { + worker_id: { + type: 'integer', + example: 1, + description: '작업자 ID' + }, + worker_name: { + type: 'string', + example: '김철수', + description: '작업자 이름' + }, + position: { + type: 'string', + example: '용접공', + description: '직책' + }, + department: { + type: 'string', + example: '생산부', + description: '부서' + }, + phone: { + type: 'string', + example: '010-1234-5678', + description: '전화번호' + }, + email: { + type: 'string', + format: 'email', + example: 'worker@technicalkorea.com', + description: '이메일' + }, + hire_date: { + type: 'string', + format: 'date', + example: '2024-01-01', + description: '입사일' + }, + is_active: { + type: 'boolean', + example: true, + description: '활성 상태' + }, + created_at: { + type: 'string', + format: 'date-time', + description: '생성 시간' + }, + updated_at: { + type: 'string', + format: 'date-time', + description: '수정 시간' + } + } + }, + + // 프로젝트 관련 스키마 + Project: { + type: 'object', + properties: { + project_id: { + type: 'integer', + example: 1, + description: '프로젝트 ID' + }, + project_name: { + type: 'string', + example: '신규 플랜트 건설', + description: '프로젝트 이름' + }, + description: { + type: 'string', + example: '대형 화학 플랜트 건설 프로젝트', + description: '프로젝트 설명' + }, + start_date: { + type: 'string', + format: 'date', + example: '2024-01-01', + description: '시작일' + }, + end_date: { + type: 'string', + format: 'date', + example: '2024-12-31', + description: '종료일' + }, + status: { + type: 'string', + example: 'active', + description: '프로젝트 상태' + }, + created_at: { + type: 'string', + format: 'date-time', + description: '생성 시간' + }, + updated_at: { + type: 'string', + format: 'date-time', + description: '수정 시간' + } + } + }, + + // 작업 관련 스키마 + Task: { + type: 'object', + properties: { + task_id: { + type: 'integer', + example: 1, + description: '작업 ID' + }, + task_name: { + type: 'string', + example: '용접 작업', + description: '작업 이름' + }, + description: { + type: 'string', + example: '파이프 용접 작업', + description: '작업 설명' + }, + category: { + type: 'string', + example: '용접', + description: '작업 카테고리' + }, + is_active: { + type: 'boolean', + example: true, + description: '활성 상태' + }, + created_at: { + type: 'string', + format: 'date-time', + description: '생성 시간' + }, + updated_at: { + type: 'string', + format: 'date-time', + description: '수정 시간' + } + } + }, + + // 일일 작업 보고서 관련 스키마 + DailyWorkReport: { + type: 'object', + properties: { + id: { + type: 'integer', + example: 1, + description: '보고서 ID' + }, + report_date: { + type: 'string', + format: 'date', + example: '2024-01-01', + description: '작업 날짜' + }, + worker_id: { + type: 'integer', + example: 1, + description: '작업자 ID' + }, + project_id: { + type: 'integer', + example: 1, + description: '프로젝트 ID' + }, + work_type_id: { + type: 'integer', + example: 1, + description: '작업 유형 ID' + }, + work_status_id: { + type: 'integer', + example: 1, + description: '작업 상태 ID (1:정규, 2:에러)' + }, + error_type_id: { + type: 'integer', + example: null, + description: '에러 유형 ID (에러일 때만)' + }, + work_hours: { + type: 'number', + format: 'decimal', + example: 8.5, + description: '작업 시간' + }, + created_by: { + type: 'integer', + example: 1, + description: '작성자 user_id' + }, + created_at: { + type: 'string', + format: 'date-time', + description: '생성 시간' + }, + updated_at: { + type: 'string', + format: 'date-time', + description: '수정 시간' + }, + // 조인된 데이터 + worker_name: { + type: 'string', + example: '김철수', + description: '작업자 이름' + }, + project_name: { + type: 'string', + example: '신규 플랜트 건설', + description: '프로젝트 이름' + }, + work_type_name: { + type: 'string', + example: '용접', + description: '작업 유형 이름' + }, + work_status_name: { + type: 'string', + example: '정규', + description: '작업 상태 이름' + }, + error_type_name: { + type: 'string', + example: null, + description: '에러 유형 이름' + } + } + }, + + // 로그인 관련 스키마 + LoginRequest: { + type: 'object', + required: ['username', 'password'], + properties: { + username: { + type: 'string', + example: 'admin', + description: '사용자명' + }, + password: { + type: 'string', + example: 'password123', + description: '비밀번호' + } + } + }, + LoginResponse: { + type: 'object', + properties: { + success: { + type: 'boolean', + example: true + }, + message: { + type: 'string', + example: '로그인 성공' + }, + data: { + type: 'object', + properties: { + user: { + $ref: '#/components/schemas/User' + }, + token: { + type: 'string', + example: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...', + description: 'JWT 토큰' + }, + redirectUrl: { + type: 'string', + example: '/pages/dashboard/group-leader.html', + description: '리다이렉트 URL' + } + } + }, + timestamp: { + type: 'string', + format: 'date-time' + } + } + } + } + }, + security: [ + { + bearerAuth: [] + } + ] +}; + +const options = { + definition: swaggerDefinition, + apis: [ + './routes/*.js', + './controllers/*.js', + './index.js' + ] +}; + +const swaggerSpec = swaggerJSDoc(options); + +module.exports = swaggerSpec; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/analysisController.js b/deploy/tkfb-package/api.hyungi.net/controllers/analysisController.js new file mode 100644 index 0000000..7d8bdf4 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/analysisController.js @@ -0,0 +1,29 @@ +/** + * 프로젝트 분석 컨트롤러 + * + * 기간별 프로젝트 분석 API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const analysisService = require('../services/analysisService'); +const { asyncHandler } = require('../middlewares/errorHandler'); + +/** + * 프로젝트 분석 데이터 조회 + */ +const getAnalysisData = asyncHandler(async (req, res) => { + const { startDate, endDate } = req.query; + const data = await analysisService.getAnalysisService(startDate, endDate); + + res.json({ + success: true, + data, + message: '분석 데이터 조회 성공' + }); +}); + +module.exports = { + getAnalysisData +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/attendanceController.js b/deploy/tkfb-package/api.hyungi.net/controllers/attendanceController.js new file mode 100644 index 0000000..124a4cd --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/attendanceController.js @@ -0,0 +1,212 @@ +/** + * 근태 관리 컨트롤러 + * + * 근태 기록 API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const attendanceService = require('../services/attendanceService'); +const { asyncHandler } = require('../middlewares/errorHandler'); + +/** + * 일일 근태 현황 조회 (대시보드용) + */ +const getDailyAttendanceStatus = asyncHandler(async (req, res) => { + const { date } = req.query; + const data = await attendanceService.getDailyAttendanceStatusService(date); + + res.json({ + success: true, + data, + message: '근태 현황을 성공적으로 조회했습니다' + }); +}); + +/** + * 일일 근태 기록 조회 + */ +const getDailyAttendanceRecords = asyncHandler(async (req, res) => { + const { date, worker_id } = req.query; + const data = await attendanceService.getDailyAttendanceRecordsService(date, worker_id); + + res.json({ + success: true, + data, + message: '근태 기록을 성공적으로 조회했습니다' + }); +}); + +/** + * 기간별 근태 기록 조회 (월별 조회용) + */ +const getAttendanceRecordsByRange = asyncHandler(async (req, res) => { + const { start_date, end_date, worker_id } = req.query; + const data = await attendanceService.getAttendanceRecordsByRangeService(start_date, end_date, worker_id); + + res.json({ + success: true, + data, + message: '근태 기록을 성공적으로 조회했습니다' + }); +}); + +/** + * 근태 기록 생성/업데이트 + */ +const upsertAttendanceRecord = asyncHandler(async (req, res) => { + const recordData = { + ...req.body, + created_by: req.user?.user_id || req.user?.id + }; + + const result = await attendanceService.upsertAttendanceRecordService(recordData); + + res.json({ + success: true, + data: result, + message: '근태 기록이 성공적으로 저장되었습니다' + }); +}); + +/** + * 휴가 처리 + */ +const processVacation = asyncHandler(async (req, res) => { + const vacationData = { + record_date: req.body.date, + worker_id: req.body.worker_id, + vacation_type_id: req.body.vacation_type, + created_by: req.user?.user_id || req.user?.id + }; + + const result = await attendanceService.processVacationService(vacationData); + + res.json({ + success: true, + data: result, + message: '휴가 처리가 성공적으로 완료되었습니다' + }); +}); + +/** + * 초과근무 승인 + */ +const approveOvertime = asyncHandler(async (req, res) => { + const overtimeData = { + record_date: req.body.date, + worker_id: req.body.worker_id, + overtime_approved: true, + approved_by: req.user?.user_id || req.user?.id + }; + + const result = await attendanceService.approveOvertimeService(overtimeData); + + res.json({ + success: true, + data: result, + message: '초과근무가 성공적으로 승인되었습니다' + }); +}); + +/** + * 근로 유형 목록 조회 + */ +const getAttendanceTypes = asyncHandler(async (req, res) => { + const data = await attendanceService.getAttendanceTypesService(); + + res.json({ + success: true, + data, + message: '근로 유형 목록을 성공적으로 조회했습니다' + }); +}); + +/** + * 휴가 유형 목록 조회 + */ +const getVacationTypes = asyncHandler(async (req, res) => { + const data = await attendanceService.getVacationTypesService(); + + res.json({ + success: true, + data, + message: '휴가 유형 목록을 성공적으로 조회했습니다' + }); +}); + +/** + * 작업자 휴가 잔여 조회 + */ +const getWorkerVacationBalance = asyncHandler(async (req, res) => { + const { worker_id } = req.params; + const data = await attendanceService.getWorkerVacationBalanceService(parseInt(worker_id)); + + res.json({ + success: true, + data, + message: '휴가 잔여 정보를 성공적으로 조회했습니다' + }); +}); + +/** + * 월별 근태 통계 + */ +const getMonthlyAttendanceStats = asyncHandler(async (req, res) => { + const { year, month, worker_id } = req.query; + const data = await attendanceService.getMonthlyAttendanceStatsService( + parseInt(year), + parseInt(month), + worker_id ? parseInt(worker_id) : null + ); + + res.json({ + success: true, + data, + message: '월별 근태 통계를 성공적으로 조회했습니다' + }); +}); + +/** + * 출근 체크 목록 조회 (아침용, 휴가 정보 포함) + */ +const getCheckinList = asyncHandler(async (req, res) => { + const { date } = req.query; + const data = await attendanceService.getCheckinListService(date); + + res.json({ + success: true, + data, + message: '출근 체크 목록을 성공적으로 조회했습니다' + }); +}); + +/** + * 출근 체크 저장 (일괄 처리) + */ +const saveCheckins = asyncHandler(async (req, res) => { + const { date, checkins } = req.body; // checkins: [{worker_id, is_present}, ...] + const result = await attendanceService.saveCheckinsService(date, checkins); + + res.json({ + success: true, + data: result, + message: '출근 체크가 성공적으로 저장되었습니다' + }); +}); + +module.exports = { + getDailyAttendanceStatus, + getDailyAttendanceRecords, + getAttendanceRecordsByRange, + upsertAttendanceRecord, + processVacation, + approveOvertime, + getAttendanceTypes, + getVacationTypes, + getWorkerVacationBalance, + getMonthlyAttendanceStats, + getCheckinList, + saveCheckins +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/authController.js b/deploy/tkfb-package/api.hyungi.net/controllers/authController.js new file mode 100644 index 0000000..adb2047 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/authController.js @@ -0,0 +1,161 @@ +const { getDb } = require('../dbPool'); +const bcrypt = require('bcryptjs'); +const jwt = require('jsonwebtoken'); +const authService = require('../services/auth.service'); +const { asyncHandler } = require('../utils/errorHandler'); +const { AuthenticationError, ValidationError } = require('../utils/errors'); +const { validateSchema, schemas } = require('../utils/validator'); + +const login = asyncHandler(async (req, res) => { + const { username, password } = req.body; + const ipAddress = req.ip || req.connection.remoteAddress; + const userAgent = req.headers['user-agent']; + + // 유효성 검사 + if (!username || !password) { + throw new ValidationError('사용자명과 비밀번호를 입력해주세요.'); + } + + const result = await authService.loginService(username, password, ipAddress, userAgent); + + if (!result.success) { + throw new AuthenticationError(result.error); + } + + // 로그인 성공 후, 메인 대시보드로 리다이렉트 + const user = result.data.user; + const redirectUrl = '/pages/dashboard.html'; // 메인 대시보드로 리다이렉트 + + // 새로운 응답 포맷터 사용 + res.auth(user, result.data.token, redirectUrl, '로그인 성공'); +}); + +// ✅ 사용자 등록 기능 추가 +const register = async (req, res) => { + try { + const { username, password, name, access_level, worker_id } = req.body; + const db = await getDb(); + + // 필수 필드 검증 + if (!username || !password || !name || !access_level) { + return res.status(400).json({ + success: false, + error: '필수 정보가 누락되었습니다.' + }); + } + + // 중복 아이디 확인 + const [existing] = await db.query( + 'SELECT user_id FROM users WHERE username = ?', + [username] + ); + + if (existing.length > 0) { + return res.status(409).json({ + success: false, + error: '이미 존재하는 아이디입니다.' + }); + } + + // 비밀번호 해시화 + const hashedPassword = await bcrypt.hash(password, 10); + + // role 설정 (access_level에 따라) + const roleMap = { + 'admin': 'admin', + 'system': 'system', // 시스템 계정은 system role로 설정 + 'group_leader': 'leader', + 'support_team': 'support', + 'worker': 'user' + }; + const role = roleMap[access_level] || 'user'; + + // 사용자 등록 + const [result] = await db.query( + `INSERT INTO users (username, password, name, role, access_level, worker_id) + VALUES (?, ?, ?, ?, ?, ?)`, + [username, hashedPassword, name, role, access_level, worker_id] + ); + + console.log('[사용자 등록 성공]', username); + + return res.status(201).json({ + success: true, + message: '사용자 등록이 완료되었습니다.', + user_id: result.insertId + }); + + } catch (err) { + console.error('[사용자 등록 오류]', err); + return res.status(500).json({ + success: false, + error: '서버 오류가 발생했습니다.', + detail: err.message + }); + } +}; + +// ✅ 사용자 삭제 기능 추가 +const deleteUser = async (req, res) => { + try { + const { id } = req.params; + const db = await getDb(); + + // 사용자 존재 확인 + const [user] = await db.query( + 'SELECT user_id FROM users WHERE user_id = ?', + [id] + ); + + if (user.length === 0) { + return res.status(404).json({ + success: false, + error: '해당 사용자를 찾을 수 없습니다.' + }); + } + + // 사용자 삭제 + await db.query('DELETE FROM users WHERE user_id = ?', [id]); + + console.log('[사용자 삭제 성공] ID:', id); + + return res.status(200).json({ + success: true, + message: '사용자가 삭제되었습니다.' + }); + + } catch (err) { + console.error('[사용자 삭제 오류]', err); + return res.status(500).json({ + success: false, + error: '서버 오류가 발생했습니다.', + detail: err.message + }); + } +}; + +// 모든 사용자 목록 조회 +const getAllUsers = async (req, res) => { + try { + const db = await getDb(); + + // 비밀번호 제외하고 조회 + const [rows] = await db.query( + `SELECT user_id, username, name, role, access_level, worker_id, created_at + FROM users + ORDER BY created_at DESC` + ); + + res.status(200).json(rows); + } catch (err) { + console.error('[사용자 목록 조회 실패]', err); + res.status(500).json({ error: '서버 오류' }); + } +}; + +module.exports = { + login, + register, + deleteUser, + getAllUsers +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/dailyIssueReportController.js b/deploy/tkfb-package/api.hyungi.net/controllers/dailyIssueReportController.js new file mode 100644 index 0000000..6dca260 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/dailyIssueReportController.js @@ -0,0 +1,64 @@ +/** + * 일일 이슈 보고서 관리 컨트롤러 + * + * 일일 이슈 보고서 CRUD API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const dailyIssueReportService = require('../services/dailyIssueReportService'); +const { asyncHandler } = require('../middlewares/errorHandler'); + +/** + * 일일 이슈 보고서 생성 + */ +const createDailyIssueReport = asyncHandler(async (req, res) => { + // 프론트엔드에서 worker_ids 또는 worker_id로 보낼 수 있음 + const issueData = { + ...req.body, + worker_ids: req.body.worker_ids || req.body.worker_id + }; + + const result = await dailyIssueReportService.createDailyIssueReportService(issueData); + + res.status(201).json({ + success: true, + data: result, + message: result.message + }); +}); + +/** + * 날짜별 이슈 조회 + */ +const getDailyIssuesByDate = asyncHandler(async (req, res) => { + const { date } = req.query; + const issues = await dailyIssueReportService.getDailyIssuesByDateService(date); + + res.json({ + success: true, + data: issues, + message: '이슈 보고서 조회 성공' + }); +}); + +/** + * 이슈 보고서 삭제 + */ +const removeDailyIssue = asyncHandler(async (req, res) => { + const { id } = req.params; + const result = await dailyIssueReportService.removeDailyIssueService(id); + + res.json({ + success: true, + data: result, + message: result.message + }); +}); + +module.exports = { + createDailyIssueReport, + getDailyIssuesByDate, + removeDailyIssue +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/dailyWorkReportController.js b/deploy/tkfb-package/api.hyungi.net/controllers/dailyWorkReportController.js new file mode 100644 index 0000000..9c79629 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/dailyWorkReportController.js @@ -0,0 +1,934 @@ +/** + * 일일 작업 보고서 컨트롤러 + * + * 작업 보고서 API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const dailyWorkReportModel = require('../models/dailyWorkReportModel'); +const dailyWorkReportService = require('../services/dailyWorkReportService'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); + +/** + * 📝 작업보고서 생성 (V2 - Service Layer 사용) + */ +const createDailyWorkReport = asyncHandler(async (req, res) => { + const reportData = { + ...req.body, + created_by: req.user?.user_id || req.user?.id, + created_by_name: req.user?.name || req.user?.username || '알 수 없는 사용자' + }; + + const result = await dailyWorkReportService.createDailyWorkReportService(reportData); + + res.status(201).json({ + success: true, + data: result, + message: '작업보고서가 성공적으로 생성되었습니다' + }); +}); + +/** + * 📊 기여자별 요약 조회 (새로운 기능) + */ +const getContributorsSummary = asyncHandler(async (req, res) => { + const { date, worker_id } = req.query; + + if (!date || !worker_id) { + throw new ApiError('date와 worker_id가 필요합니다.', 400); + } + + console.log(`📊 기여자별 요약 조회: date=${date}, worker_id=${worker_id}`); + + try { + const data = await new Promise((resolve, reject) => { + dailyWorkReportModel.getContributorsByDate(date, worker_id, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + const totalHours = data.reduce((sum, contributor) => sum + parseFloat(contributor.total_hours || 0), 0); + + console.log(`📊 기여자별 요약: ${data.length}명, 총 ${totalHours}시간`); + + const result = { + date, + worker_id, + contributors: data, + total_contributors: data.length, + grand_total_hours: totalHours + }; + + res.success(result, '기여자별 요약 조회 성공'); + } catch (err) { + handleDatabaseError(err, '기여자별 요약 조회'); + } +}); + +/** + * 📊 개인 누적 현황 조회 (새로운 기능) + */ +const getMyAccumulatedData = (req, res) => { + const { date, worker_id } = req.query; + const created_by = req.user?.user_id || req.user?.id; + + if (!date || !worker_id) { + return res.status(400).json({ + error: 'date와 worker_id가 필요합니다.', + example: 'date=2024-06-16&worker_id=1' + }); + } + + if (!created_by) { + return res.status(401).json({ + error: '사용자 인증 정보가 없습니다.' + }); + } + + console.log(`📊 개인 누적 현황 조회: date=${date}, worker_id=${worker_id}, created_by=${created_by}`); + + dailyWorkReportModel.getMyAccumulatedHours(date, worker_id, created_by, (err, data) => { + if (err) { + console.error('개인 누적 현황 조회 오류:', err); + return res.status(500).json({ + error: '개인 누적 현황 조회 중 오류가 발생했습니다.', + details: err.message + }); + } + + console.log(`📊 개인 누적: ${data.my_entry_count}개 항목, ${data.my_total_hours}시간`); + res.json({ + date, + worker_id, + created_by, + my_data: data, + timestamp: new Date().toISOString() + }); + }); +}; + +/** + * 🗑️ 개별 항목 삭제 (본인 작성분만 - 새로운 기능) + */ +const removeMyEntry = (req, res) => { + const { id } = req.params; + const deleted_by = req.user?.user_id || req.user?.id; + + if (!deleted_by) { + return res.status(401).json({ + error: '사용자 인증 정보가 없습니다.' + }); + } + + console.log(`🗑️ 개별 항목 삭제 요청: id=${id}, 삭제자=${deleted_by}`); + + dailyWorkReportModel.removeSpecificEntry(id, deleted_by, (err, result) => { + if (err) { + console.error('개별 항목 삭제 오류:', err); + return res.status(500).json({ + error: '항목 삭제 중 오류가 발생했습니다.', + details: err.message + }); + } + + console.log(`✅ 개별 항목 삭제 완료: id=${id}`); + res.json({ + message: '항목이 성공적으로 삭제되었습니다.', + id: id, + deleted_by, + timestamp: new Date().toISOString(), + ...result + }); + }); +}; + +/** + * 📊 작업보고서 조회 (V2 - Service Layer 사용) + */ +const getDailyWorkReports = async (req, res) => { + try { + const userInfo = { + user_id: req.user?.user_id || req.user?.id, + role: req.user?.role || 'user' // 기본값을 'user'로 설정하여 안전하게 처리 + }; + + if (!userInfo.user_id) { + return res.status(401).json({ error: '사용자 인증 정보가 없습니다.' }); + } + + const reports = await dailyWorkReportService.getDailyWorkReportsService(req.query, userInfo); + + res.json(reports); + + } catch (error) { + console.error('💥 작업보고서 조회 컨트롤러 오류:', error.message); + res.status(400).json({ + success: false, + error: '작업보고서 조회에 실패했습니다.', + details: error.message + }); + } +}; + +/** + * 📊 날짜별 작업보고서 조회 (경로 파라미터 - 권한별 전체 조회 지원) + */ +const getDailyWorkReportsByDate = (req, res) => { + const { date } = req.params; + const current_user_id = req.user?.user_id || req.user?.id; + const user_access_level = req.user?.access_level; + const user_job_type = req.user?.job_type; + + if (!current_user_id) { + return res.status(401).json({ + error: '사용자 인증 정보가 없습니다.' + }); + } + + const isAdmin = user_access_level === 'system' || user_access_level === 'admin' || user_access_level === 'leader' || user_job_type === 'leader'; + + console.log(`📊 날짜별 조회 (경로): date=${date}, user=${current_user_id}, 권한=${user_access_level}, 직책=${user_job_type}, 관리자=${isAdmin}`); + console.log(`🔍 사용자 정보 상세:`, req.user); + + dailyWorkReportModel.getByDate(date, (err, data) => { + if (err) { + console.error('날짜별 작업보고서 조회 오류:', err); + return res.status(500).json({ + error: '작업보고서 조회 중 오류가 발생했습니다.', + details: err.message + }); + } + + // 🎯 권한별 필터링 (임시로 비활성화) + let finalData = data; + console.log(`📊 임시로 모든 사용자에게 전체 조회 허용: ${data.length}개`); + console.log(`📊 권한 정보: access_level=${user_access_level}, job_type=${user_job_type}, isAdmin=${isAdmin}`); + + // if (!isAdmin) { + // finalData = data.filter(report => report.created_by === current_user_id); + // console.log(`📊 권한 필터링: 전체 ${data.length}개 → ${finalData.length}개`); + // } else { + // console.log(`📊 관리자 권한으로 전체 조회: ${data.length}개`); + // } + + res.json(finalData); + }); +}; + +/** + * 🔍 작업보고서 검색 (페이지네이션 포함) + */ +const searchWorkReports = (req, res) => { + const { start_date, end_date, worker_id, project_id, work_status_id, page = 1, limit = 20 } = req.query; + const created_by = req.user?.user_id || req.user?.id; + + if (!start_date || !end_date) { + return res.status(400).json({ + error: 'start_date와 end_date가 필요합니다.', + example: 'start_date=2024-01-01&end_date=2024-01-31', + optional: ['worker_id', 'project_id', 'work_status_id', 'page', 'limit'] + }); + } + + if (!created_by) { + return res.status(401).json({ + error: '사용자 인증 정보가 없습니다.' + }); + } + + const searchParams = { + start_date, + end_date, + worker_id: worker_id ? parseInt(worker_id) : null, + project_id: project_id ? parseInt(project_id) : null, + work_status_id: work_status_id ? parseInt(work_status_id) : null, + created_by, // 작성자 필터링 추가 + page: parseInt(page), + limit: parseInt(limit) + }; + + console.log('🔍 작업보고서 검색 요청:', searchParams); + + dailyWorkReportModel.searchWithDetails(searchParams, (err, data) => { + if (err) { + console.error('작업보고서 검색 오류:', err); + return res.status(500).json({ + error: '작업보고서 검색 중 오류가 발생했습니다.', + details: err.message + }); + } + + console.log(`🔍 검색 결과: ${data.reports?.length || 0}개 (전체: ${data.total || 0}개)`); + res.json(data); + }); +}; + +/** + * 📈 통계 조회 (V2 - Service Layer 사용) + */ +const getWorkReportStats = async (req, res) => { + try { + const statsData = await dailyWorkReportService.getStatisticsService(req.query); + res.json(statsData); + } catch (error) { + console.error('💥 통계 조회 컨트롤러 오류:', error.message); + res.status(400).json({ + success: false, + error: '통계 조회에 실패했습니다.', + details: error.message + }); + } +}; + +/** + * 📊 일일 근무 요약 조회 (V2 - Service Layer 사용) + */ +const getDailySummary = async (req, res) => { + try { + const summaryData = await dailyWorkReportService.getSummaryService(req.query); + res.json(summaryData); + } catch (error) { + console.error('💥 일일 요약 조회 컨트롤러 오류:', error.message); + res.status(400).json({ + success: false, + error: '일일 요약 조회에 실패했습니다.', + details: error.message + }); + } +}; + +/** + * 📅 월간 요약 조회 + */ +const getMonthlySummary = (req, res) => { + const { year, month } = req.query; + + if (!year || !month) { + return res.status(400).json({ + error: 'year와 month가 필요합니다.', + example: 'year=2024&month=01', + note: 'month는 01, 02, ..., 12 형식으로 입력하세요.' + }); + } + + console.log(`📅 월간 요약 조회: ${year}-${month}`); + + dailyWorkReportModel.getMonthlySummary(year, month, (err, data) => { + if (err) { + console.error('월간 요약 조회 오류:', err); + return res.status(500).json({ + error: '월간 요약 조회 중 오류가 발생했습니다.', + details: err.message + }); + } + + res.json({ + year: parseInt(year), + month: parseInt(month), + summary: data, + total_entries: data.length, + timestamp: new Date().toISOString() + }); + }); +}; + +/** + * ✏️ 작업보고서 수정 (V2 - Service Layer 사용) + */ +const updateWorkReport = async (req, res) => { + try { + const { id: reportId } = req.params; + const updateData = req.body; + const userInfo = { + user_id: req.user?.user_id || req.user?.id, + role: req.user?.role || 'user' + }; + + if (!userInfo.user_id) { + return res.status(401).json({ error: '사용자 인증 정보가 없습니다.' }); + } + + const result = await dailyWorkReportService.updateWorkReportService(reportId, updateData, userInfo); + + res.json({ + success: true, + timestamp: new Date().toISOString(), + ...result + }); + + } catch (error) { + console.error(`💥 작업보고서 수정 컨트롤러 오류 (id: ${req.params.id}):`, error.message); + const statusCode = error.statusCode || 400; + res.status(statusCode).json({ + success: false, + error: '작업보고서 수정에 실패했습니다.', + details: error.message + }); + } +}; + +/** + * 🗑️ 특정 작업보고서 삭제 (V2 - Service Layer 사용) + * 권한: 그룹장(group_leader), 시스템(system), 관리자(admin)만 가능 + */ +const removeDailyWorkReport = async (req, res) => { + try { + const { id: reportId } = req.params; + const userInfo = { + user_id: req.user?.user_id || req.user?.id, + access_level: req.user?.access_level || req.user?.role, + }; + + if (!userInfo.user_id) { + return res.status(401).json({ error: '사용자 인증 정보가 없습니다.' }); + } + + // 권한 체크: 그룹장, 시스템, 관리자만 삭제 가능 + const allowedRoles = ['admin', 'system', 'group_leader']; + if (!allowedRoles.includes(userInfo.access_level)) { + return res.status(403).json({ + error: '작업보고서 삭제 권한이 없습니다.', + details: '그룹장 이상의 권한이 필요합니다.' + }); + } + + const result = await dailyWorkReportService.removeDailyWorkReportService(reportId, userInfo); + + res.json({ + success: true, + timestamp: new Date().toISOString(), + ...result + }); + + } catch (error) { + console.error(`💥 작업보고서 삭제 컨트롤러 오류 (id: ${req.params.id}):`, error.message); + const statusCode = error.statusCode || 400; + res.status(statusCode).json({ + success: false, + error: '작업보고서 삭제에 실패했습니다.', + details: error.message + }); + } +}; + +/** + * ��️ 작업자의 특정 날짜 전체 삭제 + */ +const removeDailyWorkReportByDateAndWorker = (req, res) => { + const { date, worker_id } = req.params; + const deleted_by = req.user?.user_id || req.user?.id; + const access_level = req.user?.access_level || req.user?.role; + + if (!deleted_by) { + return res.status(401).json({ + error: '사용자 인증 정보가 없습니다.' + }); + } + + // 권한 체크: 그룹장, 시스템, 관리자만 삭제 가능 + const allowedRoles = ['admin', 'system', 'group_leader']; + if (!allowedRoles.includes(access_level)) { + return res.status(403).json({ + error: '작업보고서 삭제 권한이 없습니다.', + details: '그룹장 이상의 권한이 필요합니다.' + }); + } + + console.log(`🗑️ 날짜+작업자별 전체 삭제 요청: date=${date}, worker_id=${worker_id}, 삭제자=${deleted_by}`); + + dailyWorkReportModel.removeByDateAndWorker(date, worker_id, deleted_by, (err, affectedRows) => { + if (err) { + console.error('작업보고서 전체 삭제 오류:', err); + return res.status(500).json({ + error: '작업보고서 삭제 중 오류가 발생했습니다.', + details: err.message + }); + } + + if (affectedRows === 0) { + return res.status(404).json({ + error: '삭제할 작업보고서를 찾을 수 없습니다.', + date: date, + worker_id: worker_id + }); + } + + console.log(`✅ 날짜+작업자별 전체 삭제 완료: ${affectedRows}개`); + res.json({ + message: `${date} 날짜의 작업자 ${worker_id} 작업보고서 ${affectedRows}개가 삭제되었습니다.`, + date, + worker_id, + affected_rows: affectedRows, + deleted_by, + timestamp: new Date().toISOString() + }); + }); +}; + +/** + * 📋 마스터 데이터 조회 함수들 + */ +const getWorkTypes = (req, res) => { + console.log('📋 작업 유형 조회 요청'); + dailyWorkReportModel.getAllWorkTypes((err, data) => { + if (err) { + console.error('작업 유형 조회 오류:', err); + return res.status(500).json({ + success: false, + error: { + message: '작업 유형 조회 중 오류가 발생했습니다.', + code: 'DATABASE_ERROR' + } + }); + } + console.log(`📋 작업 유형 조회 결과: ${data.length}개`); + res.json({ + success: true, + data: data, + message: '작업 유형 조회 성공' + }); + }); +}; + +const getWorkStatusTypes = (req, res) => { + console.log('📋 업무 상태 유형 조회 요청'); + dailyWorkReportModel.getAllWorkStatusTypes((err, data) => { + if (err) { + console.error('업무 상태 유형 조회 오류:', err); + return res.status(500).json({ + error: '업무 상태 유형 조회 중 오류가 발생했습니다.', + details: err.message + }); + } + console.log(`📋 업무 상태 유형 조회 결과: ${data.length}개`); + res.json(data); + }); +}; + +const getErrorTypes = (req, res) => { + console.log('📋 에러 유형 조회 요청'); + dailyWorkReportModel.getAllErrorTypes((err, data) => { + if (err) { + console.error('에러 유형 조회 오류:', err); + return res.status(500).json({ + error: '에러 유형 조회 중 오류가 발생했습니다.', + details: err.message + }); + } + console.log(`📋 에러 유형 조회 결과: ${data.length}개`); + res.json(data); + }); +}; + +// ========== 작업 유형 CRUD ========== + +/** + * 📝 작업 유형 생성 + */ +const createWorkType = asyncHandler(async (req, res) => { + const { name, description, category } = req.body; + + if (!name) { + throw new ApiError('작업 유형 이름이 필요합니다.', 400); + } + + console.log('📝 작업 유형 생성:', { name, description, category }); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.createWorkType({ name, description, category }, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + res.created(result, '작업 유형이 성공적으로 생성되었습니다.'); + } catch (err) { + handleDatabaseError(err, '작업 유형 생성'); + } +}); + +/** + * ✏️ 작업 유형 수정 + */ +const updateWorkType = asyncHandler(async (req, res) => { + const { id } = req.params; + const { name, description, category } = req.body; + + if (!id) { + throw new ApiError('작업 유형 ID가 필요합니다.', 400); + } + + console.log('✏️ 작업 유형 수정:', { id, name, description, category }); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.updateWorkType(id, { name, description, category }, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + if (result.affectedRows === 0) { + throw new ApiError('수정할 작업 유형을 찾을 수 없습니다.', 404); + } + + res.success(result, '작업 유형이 성공적으로 수정되었습니다.'); + } catch (err) { + handleDatabaseError(err, '작업 유형 수정'); + } +}); + +/** + * 🗑️ 작업 유형 삭제 + */ +const deleteWorkType = asyncHandler(async (req, res) => { + const { id } = req.params; + + if (!id) { + throw new ApiError('작업 유형 ID가 필요합니다.', 400); + } + + console.log('🗑️ 작업 유형 삭제:', id); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.deleteWorkType(id, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + if (result.affectedRows === 0) { + throw new ApiError('삭제할 작업 유형을 찾을 수 없습니다.', 404); + } + + res.success(result, '작업 유형이 성공적으로 삭제되었습니다.'); + } catch (err) { + handleDatabaseError(err, '작업 유형 삭제'); + } +}); + +// ========== 작업 상태 CRUD ========== + +/** + * 📝 작업 상태 생성 + */ +const createWorkStatus = asyncHandler(async (req, res) => { + const { name, description, is_error } = req.body; + + if (!name) { + throw new ApiError('작업 상태 이름이 필요합니다.', 400); + } + + console.log('📝 작업 상태 생성:', { name, description, is_error }); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.createWorkStatus({ name, description, is_error }, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + res.created(result, '작업 상태가 성공적으로 생성되었습니다.'); + } catch (err) { + handleDatabaseError(err, '작업 상태 생성'); + } +}); + +/** + * ✏️ 작업 상태 수정 + */ +const updateWorkStatus = asyncHandler(async (req, res) => { + const { id } = req.params; + const { name, description, is_error } = req.body; + + if (!id) { + throw new ApiError('작업 상태 ID가 필요합니다.', 400); + } + + console.log('✏️ 작업 상태 수정:', { id, name, description, is_error }); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.updateWorkStatus(id, { name, description, is_error }, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + if (result.affectedRows === 0) { + throw new ApiError('수정할 작업 상태를 찾을 수 없습니다.', 404); + } + + res.success(result, '작업 상태가 성공적으로 수정되었습니다.'); + } catch (err) { + handleDatabaseError(err, '작업 상태 수정'); + } +}); + +/** + * 🗑️ 작업 상태 삭제 + */ +const deleteWorkStatus = asyncHandler(async (req, res) => { + const { id } = req.params; + + if (!id) { + throw new ApiError('작업 상태 ID가 필요합니다.', 400); + } + + console.log('🗑️ 작업 상태 삭제:', id); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.deleteWorkStatus(id, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + if (result.affectedRows === 0) { + throw new ApiError('삭제할 작업 상태를 찾을 수 없습니다.', 404); + } + + res.success(result, '작업 상태가 성공적으로 삭제되었습니다.'); + } catch (err) { + handleDatabaseError(err, '작업 상태 삭제'); + } +}); + +// ========== 오류 유형 CRUD ========== + +/** + * 📝 오류 유형 생성 + */ +const createErrorType = asyncHandler(async (req, res) => { + const { name, description, severity } = req.body; + + if (!name) { + throw new ApiError('오류 유형 이름이 필요합니다.', 400); + } + + console.log('📝 오류 유형 생성:', { name, description, severity }); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.createErrorType({ name, description, severity }, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + res.created(result, '오류 유형이 성공적으로 생성되었습니다.'); + } catch (err) { + handleDatabaseError(err, '오류 유형 생성'); + } +}); + +/** + * ✏️ 오류 유형 수정 + */ +const updateErrorType = asyncHandler(async (req, res) => { + const { id } = req.params; + const { name, description, severity } = req.body; + + if (!id) { + throw new ApiError('오류 유형 ID가 필요합니다.', 400); + } + + console.log('✏️ 오류 유형 수정:', { id, name, description, severity }); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.updateErrorType(id, { name, description, severity }, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + if (result.affectedRows === 0) { + throw new ApiError('수정할 오류 유형을 찾을 수 없습니다.', 404); + } + + res.success(result, '오류 유형이 성공적으로 수정되었습니다.'); + } catch (err) { + handleDatabaseError(err, '오류 유형 수정'); + } +}); + +/** + * 🗑️ 오류 유형 삭제 + */ +const deleteErrorType = asyncHandler(async (req, res) => { + const { id } = req.params; + + if (!id) { + throw new ApiError('오류 유형 ID가 필요합니다.', 400); + } + + console.log('🗑️ 오류 유형 삭제:', id); + + try { + const result = await new Promise((resolve, reject) => { + dailyWorkReportModel.deleteErrorType(id, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + if (result.affectedRows === 0) { + throw new ApiError('삭제할 오류 유형을 찾을 수 없습니다.', 404); + } + + res.success(result, '오류 유형이 성공적으로 삭제되었습니다.'); + } catch (err) { + handleDatabaseError(err, '오류 유형 삭제'); + } +}); + +/** + * 📊 누적 현황 조회 + */ +const getAccumulatedReports = (req, res) => { + const { date, worker_id } = req.query; + + if (!date || !worker_id) { + return res.status(400).json({ + error: 'date와 worker_id가 필요합니다.', + example: 'date=2024-06-16&worker_id=1' + }); + } + + console.log(`📊 누적 현황 조회: date=${date}, worker_id=${worker_id}`); + + dailyWorkReportModel.getAccumulatedReportsByDate(date, worker_id, (err, data) => { + if (err) { + console.error('누적 현황 조회 오류:', err); + return res.status(500).json({ + error: '누적 현황 조회 중 오류가 발생했습니다.', + details: err.message + }); + } + + console.log(`📊 누적 현황 조회 결과: ${data.length}개`); + res.json({ + date, + worker_id, + total_entries: data.length, + accumulated_data: data, + timestamp: new Date().toISOString() + }); + }); +}; + +/** + * TBM 배정 기반 작업보고서 생성 + */ +const createFromTbm = async (req, res) => { + try { + const { + tbm_assignment_id, + tbm_session_id, + worker_id, + project_id, + work_type_id, + report_date, + start_time, + end_time, + total_hours, + error_hours, + error_type_id, + work_status_id + } = req.body; + + // 필수 필드 검증 + if (!tbm_assignment_id || !tbm_session_id || !worker_id || !report_date || !total_hours) { + return res.status(400).json({ + success: false, + message: '필수 필드가 누락되었습니다. (assignment_id, session_id, worker_id, report_date, total_hours)' + }); + } + + // regular_hours 계산 + const regular_hours = total_hours - (error_hours || 0); + + const reportData = { + tbm_assignment_id, + tbm_session_id, + worker_id, + project_id, + work_type_id, + report_date, + start_time, + end_time, + total_hours, + error_hours: error_hours || 0, + regular_hours, + work_status_id: work_status_id || (error_hours > 0 ? 2 : 1), // error_hours가 있으면 상태 2 (부적합) + error_type_id, + created_by: req.user.user_id + }; + + const result = await dailyWorkReportModel.createFromTbmAssignment(reportData); + + res.status(201).json({ + success: true, + message: '작업보고서가 생성되었습니다.', + data: result + }); + + } catch (err) { + console.error('TBM 작업보고서 생성 오류:', err); + console.error('Error stack:', err.stack); + res.status(500).json({ + success: false, + message: 'TBM 작업보고서 생성 중 오류가 발생했습니다.', + error: err.message, + stack: process.env.NODE_ENV === 'development' ? err.stack : undefined + }); + } +}; + +// 모든 컨트롤러 함수 내보내기 (리팩토링된 함수 위주로 재구성) +module.exports = { + // 📝 V2 핵심 CRUD 함수 + createDailyWorkReport, + getDailyWorkReports, + updateWorkReport, + removeDailyWorkReport, + createFromTbm, + + // 📊 V2 통계 및 요약 함수 + getWorkReportStats, + getDailySummary, + + // 🔽 아직 리팩토링되지 않은 레거시 함수들 + getAccumulatedReports, + getContributorsSummary, + getMyAccumulatedData, + removeMyEntry, + getDailyWorkReportsByDate, + searchWorkReports, + getMonthlySummary, + removeDailyWorkReportByDateAndWorker, + getWorkTypes, + getWorkStatusTypes, + getErrorTypes, + + // 🔽 마스터 데이터 CRUD + createWorkType, + updateWorkType, + deleteWorkType, + createWorkStatus, + updateWorkStatus, + deleteWorkStatus, + createErrorType, + updateErrorType, + deleteErrorType +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/departmentController.js b/deploy/tkfb-package/api.hyungi.net/controllers/departmentController.js new file mode 100644 index 0000000..e44574b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/departmentController.js @@ -0,0 +1,241 @@ +// controllers/departmentController.js +const departmentModel = require('../models/departmentModel'); + +const departmentController = { + // 모든 부서 조회 + async getAll(req, res) { + try { + const { active_only } = req.query; + const departments = active_only === 'true' + ? await departmentModel.getActive() + : await departmentModel.getAll(); + + res.json({ + success: true, + data: departments + }); + } catch (error) { + console.error('부서 목록 조회 오류:', error); + res.status(500).json({ + success: false, + error: '부서 목록을 불러오는데 실패했습니다.' + }); + } + }, + + // 부서 상세 조회 + async getById(req, res) { + try { + const { id } = req.params; + const department = await departmentModel.getById(id); + + if (!department) { + return res.status(404).json({ + success: false, + error: '부서를 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + data: department + }); + } catch (error) { + console.error('부서 조회 오류:', error); + res.status(500).json({ + success: false, + error: '부서 정보를 불러오는데 실패했습니다.' + }); + } + }, + + // 부서 생성 + async create(req, res) { + try { + const { department_name, parent_id, description, is_active, display_order } = req.body; + + if (!department_name) { + return res.status(400).json({ + success: false, + error: '부서명은 필수입니다.' + }); + } + + const departmentId = await departmentModel.create({ + department_name, + parent_id, + description, + is_active, + display_order + }); + + const newDepartment = await departmentModel.getById(departmentId); + + res.status(201).json({ + success: true, + message: '부서가 생성되었습니다.', + data: newDepartment + }); + } catch (error) { + console.error('부서 생성 오류:', error); + res.status(500).json({ + success: false, + error: '부서 생성에 실패했습니다.' + }); + } + }, + + // 부서 수정 + async update(req, res) { + try { + const { id } = req.params; + const { department_name, parent_id, description, is_active, display_order } = req.body; + + if (!department_name) { + return res.status(400).json({ + success: false, + error: '부서명은 필수입니다.' + }); + } + + // 자기 자신을 상위 부서로 지정하는 것 방지 + if (parent_id && parseInt(parent_id) === parseInt(id)) { + return res.status(400).json({ + success: false, + error: '자기 자신을 상위 부서로 지정할 수 없습니다.' + }); + } + + const updated = await departmentModel.update(id, { + department_name, + parent_id, + description, + is_active, + display_order + }); + + if (!updated) { + return res.status(404).json({ + success: false, + error: '부서를 찾을 수 없습니다.' + }); + } + + const updatedDepartment = await departmentModel.getById(id); + + res.json({ + success: true, + message: '부서 정보가 수정되었습니다.', + data: updatedDepartment + }); + } catch (error) { + console.error('부서 수정 오류:', error); + res.status(500).json({ + success: false, + error: '부서 수정에 실패했습니다.' + }); + } + }, + + // 부서 삭제 + async delete(req, res) { + try { + const { id } = req.params; + + await departmentModel.delete(id); + + res.json({ + success: true, + message: '부서가 삭제되었습니다.' + }); + } catch (error) { + console.error('부서 삭제 오류:', error); + res.status(400).json({ + success: false, + error: error.message || '부서 삭제에 실패했습니다.' + }); + } + }, + + // 부서별 작업자 조회 + async getWorkers(req, res) { + try { + const { id } = req.params; + const workers = await departmentModel.getWorkersByDepartment(id); + + res.json({ + success: true, + data: workers + }); + } catch (error) { + console.error('부서 작업자 조회 오류:', error); + res.status(500).json({ + success: false, + error: '작업자 목록을 불러오는데 실패했습니다.' + }); + } + }, + + // 작업자 부서 이동 + async moveWorker(req, res) { + try { + const { workerId, departmentId } = req.body; + + if (!workerId || !departmentId) { + return res.status(400).json({ + success: false, + error: '작업자 ID와 부서 ID가 필요합니다.' + }); + } + + await departmentModel.moveWorker(workerId, departmentId); + + res.json({ + success: true, + message: '작업자 부서가 변경되었습니다.' + }); + } catch (error) { + console.error('작업자 부서 이동 오류:', error); + res.status(500).json({ + success: false, + error: '작업자 부서 변경에 실패했습니다.' + }); + } + }, + + // 여러 작업자 부서 일괄 이동 + async moveWorkers(req, res) { + try { + const { workerIds, departmentId } = req.body; + + if (!workerIds || !Array.isArray(workerIds) || workerIds.length === 0) { + return res.status(400).json({ + success: false, + error: '이동할 작업자를 선택하세요.' + }); + } + + if (!departmentId) { + return res.status(400).json({ + success: false, + error: '대상 부서를 선택하세요.' + }); + } + + const count = await departmentModel.moveWorkers(workerIds, departmentId); + + res.json({ + success: true, + message: `${count}명의 작업자 부서가 변경되었습니다.` + }); + } catch (error) { + console.error('작업자 일괄 이동 오류:', error); + res.status(500).json({ + success: false, + error: '작업자 부서 변경에 실패했습니다.' + }); + } + } +}; + +module.exports = departmentController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/equipmentController.js b/deploy/tkfb-package/api.hyungi.net/controllers/equipmentController.js new file mode 100644 index 0000000..896eb75 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/equipmentController.js @@ -0,0 +1,945 @@ +// controllers/equipmentController.js +const EquipmentModel = require('../models/equipmentModel'); +const imageUploadService = require('../services/imageUploadService'); + +const EquipmentController = { + // CREATE - 설비 생성 + createEquipment: async (req, res) => { + try { + const equipmentData = req.body; + + // 필수 필드 검증 + if (!equipmentData.equipment_code || !equipmentData.equipment_name) { + return res.status(400).json({ + success: false, + message: '설비 코드와 설비명은 필수입니다.' + }); + } + + // 설비 코드 중복 확인 + EquipmentModel.checkDuplicateCode(equipmentData.equipment_code, null, (error, isDuplicate) => { + if (error) { + console.error('설비 코드 중복 확인 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 코드 중복 확인 중 오류가 발생했습니다.' + }); + } + + if (isDuplicate) { + return res.status(409).json({ + success: false, + message: '이미 사용 중인 설비 코드입니다.' + }); + } + + // 설비 생성 + EquipmentModel.create(equipmentData, (error, result) => { + if (error) { + console.error('설비 생성 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 생성 중 오류가 발생했습니다.' + }); + } + + res.status(201).json({ + success: true, + message: '설비가 성공적으로 생성되었습니다.', + data: result + }); + }); + }); + } catch (error) { + console.error('설비 생성 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // READ ALL - 모든 설비 조회 (필터링 가능) + getAllEquipments: (req, res) => { + try { + const filters = { + workplace_id: req.query.workplace_id, + equipment_type: req.query.equipment_type, + status: req.query.status, + search: req.query.search + }; + + EquipmentModel.getAll(filters, (error, results) => { + if (error) { + console.error('설비 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('설비 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // READ ONE - 특정 설비 조회 + getEquipmentById: (req, res) => { + try { + const equipmentId = req.params.id; + + EquipmentModel.getById(equipmentId, (error, result) => { + if (error) { + console.error('설비 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 조회 중 오류가 발생했습니다.' + }); + } + + if (!result) { + return res.status(404).json({ + success: false, + message: '설비를 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + data: result + }); + }); + } catch (error) { + console.error('설비 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // READ BY WORKPLACE - 특정 작업장의 설비 조회 + getEquipmentsByWorkplace: (req, res) => { + try { + const workplaceId = req.params.workplaceId; + + EquipmentModel.getByWorkplace(workplaceId, (error, results) => { + if (error) { + console.error('작업장 설비 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '작업장 설비 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('작업장 설비 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // READ ACTIVE - 활성 설비만 조회 + getActiveEquipments: (req, res) => { + try { + EquipmentModel.getActive((error, results) => { + if (error) { + console.error('활성 설비 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '활성 설비 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('활성 설비 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // UPDATE - 설비 수정 + updateEquipment: async (req, res) => { + try { + const equipmentId = req.params.id; + const equipmentData = req.body; + + // 필수 필드 검증 + if (!equipmentData.equipment_code || !equipmentData.equipment_name) { + return res.status(400).json({ + success: false, + message: '설비 코드와 설비명은 필수입니다.' + }); + } + + // 설비 존재 확인 + EquipmentModel.getById(equipmentId, (error, existingEquipment) => { + if (error) { + console.error('설비 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 조회 중 오류가 발생했습니다.' + }); + } + + if (!existingEquipment) { + return res.status(404).json({ + success: false, + message: '설비를 찾을 수 없습니다.' + }); + } + + // 설비 코드 중복 확인 (자신 제외) + EquipmentModel.checkDuplicateCode(equipmentData.equipment_code, equipmentId, (error, isDuplicate) => { + if (error) { + console.error('설비 코드 중복 확인 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 코드 중복 확인 중 오류가 발생했습니다.' + }); + } + + if (isDuplicate) { + return res.status(409).json({ + success: false, + message: '이미 사용 중인 설비 코드입니다.' + }); + } + + // 설비 수정 + EquipmentModel.update(equipmentId, equipmentData, (error, result) => { + if (error) { + console.error('설비 수정 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 수정 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + message: '설비가 성공적으로 수정되었습니다.', + data: result + }); + }); + }); + }); + } catch (error) { + console.error('설비 수정 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // UPDATE MAP POSITION - 지도상 위치 업데이트 + updateMapPosition: (req, res) => { + try { + const equipmentId = 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 + }; + + // workplace_id가 있으면 포함 (설비를 다른 작업장으로 이동 가능) + if (req.body.workplace_id !== undefined) { + positionData.workplace_id = req.body.workplace_id; + } + + EquipmentModel.updateMapPosition(equipmentId, positionData, (error, result) => { + if (error) { + console.error('설비 위치 업데이트 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 위치 업데이트 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + message: '설비 위치가 성공적으로 업데이트되었습니다.', + data: result + }); + }); + } catch (error) { + console.error('설비 위치 업데이트 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // DELETE - 설비 삭제 + deleteEquipment: (req, res) => { + try { + const equipmentId = req.params.id; + + EquipmentModel.delete(equipmentId, (error, result) => { + if (error) { + console.error('설비 삭제 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 삭제 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + message: '설비가 성공적으로 삭제되었습니다.', + data: result + }); + }); + } catch (error) { + console.error('설비 삭제 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET EQUIPMENT TYPES - 사용 중인 설비 유형 목록 조회 + getEquipmentTypes: (req, res) => { + try { + EquipmentModel.getEquipmentTypes((error, results) => { + if (error) { + console.error('설비 유형 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 유형 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('설비 유형 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET NEXT EQUIPMENT CODE - 다음 관리번호 자동 생성 + getNextEquipmentCode: (req, res) => { + try { + const prefix = req.query.prefix || 'TKP'; + + EquipmentModel.getNextEquipmentCode(prefix, (error, nextCode) => { + if (error) { + console.error('다음 관리번호 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '다음 관리번호 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: { + next_code: nextCode, + prefix: prefix + } + }); + }); + } catch (error) { + console.error('다음 관리번호 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // ========================================== + // 설비 사진 관리 + // ========================================== + + // ADD PHOTO - 설비 사진 추가 + addPhoto: async (req, res) => { + try { + const equipmentId = req.params.id; + const { photo_base64, description, display_order } = req.body; + + if (!photo_base64) { + return res.status(400).json({ + success: false, + message: '사진 데이터가 필요합니다.' + }); + } + + // Base64 이미지를 파일로 저장 + const photoPath = await imageUploadService.saveBase64Image( + photo_base64, + 'equipment', + 'equipments' + ); + + if (!photoPath) { + return res.status(500).json({ + success: false, + message: '사진 저장에 실패했습니다.' + }); + } + + // DB에 사진 정보 저장 + const photoData = { + photo_path: photoPath, + description: description || null, + display_order: display_order || 0, + uploaded_by: req.user?.user_id || null + }; + + EquipmentModel.addPhoto(equipmentId, photoData, (error, result) => { + if (error) { + console.error('사진 정보 저장 오류:', error); + return res.status(500).json({ + success: false, + message: '사진 정보 저장 중 오류가 발생했습니다.' + }); + } + + res.status(201).json({ + success: true, + message: '사진이 성공적으로 추가되었습니다.', + data: result + }); + }); + } catch (error) { + console.error('사진 추가 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET PHOTOS - 설비 사진 조회 + getPhotos: (req, res) => { + try { + const equipmentId = req.params.id; + + EquipmentModel.getPhotos(equipmentId, (error, results) => { + if (error) { + console.error('사진 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '사진 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('사진 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // DELETE PHOTO - 설비 사진 삭제 + deletePhoto: async (req, res) => { + try { + const photoId = req.params.photoId; + + EquipmentModel.deletePhoto(photoId, async (error, result) => { + if (error) { + if (error.message === 'Photo not found') { + return res.status(404).json({ + success: false, + message: '사진을 찾을 수 없습니다.' + }); + } + console.error('사진 삭제 오류:', error); + return res.status(500).json({ + success: false, + message: '사진 삭제 중 오류가 발생했습니다.' + }); + } + + // 파일 시스템에서 사진 삭제 + if (result.photo_path) { + await imageUploadService.deleteFile(result.photo_path); + } + + res.json({ + success: true, + message: '사진이 성공적으로 삭제되었습니다.', + data: { photo_id: photoId } + }); + }); + } catch (error) { + console.error('사진 삭제 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // ========================================== + // 설비 임시 이동 + // ========================================== + + // MOVE TEMPORARILY - 설비 임시 이동 + moveTemporarily: (req, res) => { + try { + const equipmentId = req.params.id; + const moveData = { + target_workplace_id: req.body.target_workplace_id, + target_x_percent: req.body.target_x_percent, + target_y_percent: req.body.target_y_percent, + target_width_percent: req.body.target_width_percent, + target_height_percent: req.body.target_height_percent, + from_workplace_id: req.body.from_workplace_id, + from_x_percent: req.body.from_x_percent, + from_y_percent: req.body.from_y_percent, + reason: req.body.reason, + moved_by: req.user?.user_id || null + }; + + if (!moveData.target_workplace_id || moveData.target_x_percent === undefined || moveData.target_y_percent === undefined) { + return res.status(400).json({ + success: false, + message: '이동할 작업장과 위치가 필요합니다.' + }); + } + + EquipmentModel.moveTemporarily(equipmentId, moveData, (error, result) => { + if (error) { + console.error('설비 이동 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 이동 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + message: '설비가 임시 이동되었습니다.', + data: result + }); + }); + } catch (error) { + console.error('설비 이동 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // RETURN TO ORIGINAL - 설비 원위치 복귀 + returnToOriginal: (req, res) => { + try { + const equipmentId = req.params.id; + const userId = req.user?.user_id || null; + + EquipmentModel.returnToOriginal(equipmentId, userId, (error, result) => { + if (error) { + if (error.message === 'Equipment not found') { + return res.status(404).json({ + success: false, + message: '설비를 찾을 수 없습니다.' + }); + } + console.error('설비 복귀 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 복귀 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + message: '설비가 원위치로 복귀되었습니다.', + data: result + }); + }); + } catch (error) { + console.error('설비 복귀 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET TEMPORARILY MOVED - 임시 이동된 설비 목록 + getTemporarilyMoved: (req, res) => { + try { + EquipmentModel.getTemporarilyMoved((error, results) => { + if (error) { + console.error('임시 이동 설비 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '임시 이동 설비 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('임시 이동 설비 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET MOVE LOGS - 설비 이동 이력 조회 + getMoveLogs: (req, res) => { + try { + const equipmentId = req.params.id; + + EquipmentModel.getMoveLogs(equipmentId, (error, results) => { + if (error) { + console.error('이동 이력 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '이동 이력 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('이동 이력 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // ========================================== + // 설비 외부 반출/반입 + // ========================================== + + // EXPORT EQUIPMENT - 설비 외부 반출 + exportEquipment: (req, res) => { + try { + const equipmentId = req.params.id; + const exportData = { + equipment_id: equipmentId, + export_date: req.body.export_date, + expected_return_date: req.body.expected_return_date, + destination: req.body.destination, + reason: req.body.reason, + notes: req.body.notes, + is_repair: req.body.is_repair || false, + exported_by: req.user?.user_id || null + }; + + EquipmentModel.exportEquipment(exportData, (error, result) => { + if (error) { + console.error('설비 반출 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 반출 중 오류가 발생했습니다.' + }); + } + + res.status(201).json({ + success: true, + message: '설비가 외부로 반출되었습니다.', + data: result + }); + }); + } catch (error) { + console.error('설비 반출 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // RETURN EQUIPMENT - 설비 반입 (외부에서 복귀) + returnEquipment: (req, res) => { + try { + const logId = req.params.logId; + const returnData = { + return_date: req.body.return_date, + new_status: req.body.new_status || 'active', + notes: req.body.notes, + returned_by: req.user?.user_id || null + }; + + EquipmentModel.returnEquipment(logId, returnData, (error, result) => { + if (error) { + if (error.message === 'Export log not found') { + return res.status(404).json({ + success: false, + message: '반출 기록을 찾을 수 없습니다.' + }); + } + console.error('설비 반입 오류:', error); + return res.status(500).json({ + success: false, + message: '설비 반입 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + message: '설비가 반입되었습니다.', + data: result + }); + }); + } catch (error) { + console.error('설비 반입 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET EXTERNAL LOGS - 설비 외부 반출 이력 조회 + getExternalLogs: (req, res) => { + try { + const equipmentId = req.params.id; + + EquipmentModel.getExternalLogs(equipmentId, (error, results) => { + if (error) { + console.error('반출 이력 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '반출 이력 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('반출 이력 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET EXPORTED EQUIPMENTS - 현재 외부 반출 중인 설비 목록 + getExportedEquipments: (req, res) => { + try { + EquipmentModel.getExportedEquipments((error, results) => { + if (error) { + console.error('반출 중 설비 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '반출 중 설비 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('반출 중 설비 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // ========================================== + // 설비 수리 신청 + // ========================================== + + // CREATE REPAIR REQUEST - 수리 신청 + createRepairRequest: async (req, res) => { + try { + const equipmentId = req.params.id; + const { photo_base64_list, description, item_id, workplace_id } = req.body; + + // 사진 저장 (있는 경우) + let photoPaths = []; + if (photo_base64_list && photo_base64_list.length > 0) { + for (const base64 of photo_base64_list) { + const path = await imageUploadService.saveBase64Image(base64, 'repair', 'issues'); + if (path) photoPaths.push(path); + } + } + + const requestData = { + equipment_id: equipmentId, + item_id: item_id || null, + workplace_id: workplace_id || null, + description: description || null, + photo_paths: photoPaths.length > 0 ? photoPaths : null, + reported_by: req.user?.user_id || null + }; + + EquipmentModel.createRepairRequest(requestData, (error, result) => { + if (error) { + if (error.message === '설비 수리 카테고리가 없습니다') { + return res.status(400).json({ + success: false, + message: error.message + }); + } + console.error('수리 신청 오류:', error); + return res.status(500).json({ + success: false, + message: '수리 신청 중 오류가 발생했습니다.' + }); + } + + res.status(201).json({ + success: true, + message: '수리 신청이 접수되었습니다.', + data: result + }); + }); + } catch (error) { + console.error('수리 신청 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET REPAIR HISTORY - 설비 수리 이력 조회 + getRepairHistory: (req, res) => { + try { + const equipmentId = req.params.id; + + EquipmentModel.getRepairHistory(equipmentId, (error, results) => { + if (error) { + console.error('수리 이력 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '수리 이력 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('수리 이력 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // GET REPAIR CATEGORIES - 설비 수리 항목 목록 조회 + getRepairCategories: (req, res) => { + try { + EquipmentModel.getRepairCategories((error, results) => { + if (error) { + console.error('수리 항목 조회 오류:', error); + return res.status(500).json({ + success: false, + message: '수리 항목 조회 중 오류가 발생했습니다.' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('수리 항목 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + }, + + // ADD REPAIR CATEGORY - 새 수리 항목 추가 + addRepairCategory: (req, res) => { + try { + const { item_name } = req.body; + + if (!item_name || !item_name.trim()) { + return res.status(400).json({ + success: false, + message: '수리 유형 이름을 입력하세요.' + }); + } + + EquipmentModel.addRepairCategory(item_name.trim(), (error, result) => { + if (error) { + console.error('수리 항목 추가 오류:', error); + return res.status(500).json({ + success: false, + message: '수리 항목 추가 중 오류가 발생했습니다.' + }); + } + + res.status(201).json({ + success: true, + message: result.isNew ? '새 수리 유형이 추가되었습니다.' : '기존 수리 유형을 사용합니다.', + data: result + }); + }); + } catch (error) { + console.error('수리 항목 추가 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다.' + }); + } + } +}; + +module.exports = EquipmentController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/issueTypeController.js b/deploy/tkfb-package/api.hyungi.net/controllers/issueTypeController.js new file mode 100644 index 0000000..96cb434 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/issueTypeController.js @@ -0,0 +1,65 @@ +/** + * 이슈 유형 관리 컨트롤러 + * + * 이슈 유형(카테고리/서브카테고리) CRUD API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const issueTypeService = require('../services/issueTypeService'); +const { asyncHandler } = require('../middlewares/errorHandler'); + +/** + * 이슈 유형 생성 + */ +exports.createIssueType = asyncHandler(async (req, res) => { + const result = await issueTypeService.createIssueTypeService(req.body); + + res.status(201).json({ + success: true, + data: result, + message: '이슈 유형이 성공적으로 생성되었습니다' + }); +}); + +/** + * 전체 이슈 유형 조회 + */ +exports.getAllIssueTypes = asyncHandler(async (req, res) => { + const rows = await issueTypeService.getAllIssueTypesService(); + + res.json({ + success: true, + data: rows, + message: '이슈 유형 목록 조회 성공' + }); +}); + +/** + * 이슈 유형 수정 + */ +exports.updateIssueType = asyncHandler(async (req, res) => { + const id = parseInt(req.params.id, 10); + const result = await issueTypeService.updateIssueTypeService(id, req.body); + + res.json({ + success: true, + data: result, + message: '이슈 유형이 성공적으로 수정되었습니다' + }); +}); + +/** + * 이슈 유형 삭제 + */ +exports.removeIssueType = asyncHandler(async (req, res) => { + const id = parseInt(req.params.id, 10); + const result = await issueTypeService.removeIssueTypeService(id); + + res.json({ + success: true, + data: result, + message: '이슈 유형이 성공적으로 삭제되었습니다' + }); +}); diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/monthlyStatusController.js b/deploy/tkfb-package/api.hyungi.net/controllers/monthlyStatusController.js new file mode 100644 index 0000000..c34c5df --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/monthlyStatusController.js @@ -0,0 +1,231 @@ +/** + * 월별 작업자 상태 집계 컨트롤러 + * + * 월별 캘린더 및 작업자 상태 집계 API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const MonthlyStatusModel = require('../models/monthlyStatusModel'); +const { ValidationError, ForbiddenError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); + +/** + * 월별 캘린더 데이터 조회 + */ +const getMonthlyCalendarData = asyncHandler(async (req, res) => { + const { year, month } = req.query; + + if (!year || !month) { + throw new ValidationError('연도(year)와 월(month)이 필요합니다', { + required: ['year', 'month'], + received: { year, month } + }); + } + + const yearNum = parseInt(year); + const monthNum = parseInt(month); + + if (yearNum < 2020 || yearNum > 2030 || monthNum < 1 || monthNum > 12) { + throw new ValidationError('유효하지 않은 연도 또는 월입니다', { + received: { year: yearNum, month: monthNum } + }); + } + + logger.info('월별 캘린더 데이터 조회 요청', { year: yearNum, month: monthNum }); + + try { + const summaryData = await MonthlyStatusModel.getMonthlySummary(yearNum, monthNum); + + // 날짜별 객체로 변환 + const calendarData = {}; + summaryData.forEach(day => { + const dateKey = day.date.toISOString().split('T')[0]; + calendarData[dateKey] = { + totalWorkers: day.total_workers, + workingWorkers: day.working_workers, + hasIssues: day.has_issues, + hasErrors: day.has_errors, + hasOvertimeWarning: day.has_overtime_warning, + incompleteWorkers: day.incomplete_workers, + partialWorkers: day.partial_workers, + errorWorkers: day.error_workers, + overtimeWarningWorkers: day.overtime_warning_workers, + totalHours: parseFloat(day.total_work_hours || 0), + totalTasks: day.total_work_count, + errorCount: day.total_error_count, + lastUpdated: day.last_updated + }; + }); + + logger.info('월별 캘린더 데이터 조회 성공', { + year: yearNum, + month: monthNum, + dayCount: Object.keys(calendarData).length + }); + + res.json({ + success: true, + data: calendarData, + message: `${year}년 ${month}월 캘린더 데이터를 성공적으로 조회했습니다` + }); + } catch (error) { + logger.error('월별 캘린더 데이터 조회 실패', { + year: yearNum, + month: monthNum, + error: error.message + }); + throw new DatabaseError('월별 캘린더 데이터 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 특정 날짜의 작업자별 상세 상태 조회 + */ +const getDailyWorkerDetails = asyncHandler(async (req, res) => { + const { date } = req.query; + + if (!date) { + throw new ValidationError('날짜(date)가 필요합니다', { + required: ['date'], + received: { date } + }); + } + + logger.info('일별 작업자 상세 조회 요청', { date }); + + try { + const workerDetails = await MonthlyStatusModel.getDailyWorkerStatus(date); + + // 데이터 변환 + const formattedData = workerDetails.map(worker => ({ + workerId: worker.worker_id, + workerName: worker.worker_name, + jobType: worker.job_type, + totalHours: parseFloat(worker.total_work_hours || 0), + actualWorkHours: parseFloat(worker.actual_work_hours || 0), + vacationHours: parseFloat(worker.vacation_hours || 0), + totalWorkCount: worker.total_work_count, + regularWorkCount: worker.regular_work_count, + errorWorkCount: worker.error_work_count, + status: worker.work_status, + hasVacation: worker.has_vacation, + hasError: worker.has_error, + hasIssues: worker.has_issues, + lastUpdated: worker.last_updated + })); + + // 요약 정보 계산 + const summary = { + totalWorkers: formattedData.length, + totalHours: formattedData.reduce((sum, w) => sum + w.totalHours, 0), + totalTasks: formattedData.reduce((sum, w) => sum + w.totalWorkCount, 0), + errorCount: formattedData.reduce((sum, w) => sum + w.errorWorkCount, 0) + }; + + logger.info('일별 작업자 상세 조회 성공', { + date, + workerCount: formattedData.length, + totalHours: summary.totalHours + }); + + res.json({ + success: true, + data: { + workers: formattedData, + summary + }, + message: `${date} 작업자 상세 정보를 성공적으로 조회했습니다` + }); + } catch (error) { + logger.error('일별 작업자 상세 조회 실패', { + date, + error: error.message + }); + throw new DatabaseError('일별 작업자 상세 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 월별 집계 재계산 (관리자용) + */ +const recalculateMonth = asyncHandler(async (req, res) => { + const { year, month } = req.body; + + if (!year || !month) { + throw new ValidationError('연도(year)와 월(month)이 필요합니다', { + required: ['year', 'month'], + received: { year, month } + }); + } + + // 관리자 권한 확인 + if (req.user.role !== 'admin' && req.user.role !== 'system') { + throw new ForbiddenError('관리자 권한이 필요합니다'); + } + + logger.info('월별 집계 재계산 시작', { + year, + month, + requestedBy: req.user.username + }); + + try { + const result = await MonthlyStatusModel.recalculateMonth(parseInt(year), parseInt(month)); + + logger.info('월별 집계 재계산 성공', { year, month, result }); + + res.json({ + success: true, + data: result, + message: `${year}년 ${month}월 집계 재계산이 완료되었습니다` + }); + } catch (error) { + logger.error('월별 집계 재계산 실패', { + year, + month, + error: error.message + }); + throw new DatabaseError('월별 집계 재계산 중 오류가 발생했습니다'); + } +}); + +/** + * 집계 테이블 상태 확인 (관리자용) + */ +const getStatusInfo = asyncHandler(async (req, res) => { + // 관리자 권한 확인 + if (req.user.role !== 'admin' && req.user.role !== 'system') { + throw new ForbiddenError('관리자 권한이 필요합니다'); + } + + logger.info('집계 테이블 상태 확인 요청', { + requestedBy: req.user.username + }); + + try { + const statusInfo = await MonthlyStatusModel.getStatusInfo(); + + logger.info('집계 테이블 상태 확인 성공'); + + res.json({ + success: true, + data: statusInfo, + message: '집계 테이블 상태 정보를 성공적으로 조회했습니다' + }); + } catch (error) { + logger.error('집계 테이블 상태 확인 실패', { + error: error.message + }); + throw new DatabaseError('집계 테이블 상태 확인 중 오류가 발생했습니다'); + } +}); + +module.exports = { + getMonthlyCalendarData, + getDailyWorkerDetails, + recalculateMonth, + getStatusInfo +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/notificationController.js b/deploy/tkfb-package/api.hyungi.net/controllers/notificationController.js new file mode 100644 index 0000000..2863a19 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/notificationController.js @@ -0,0 +1,165 @@ +// controllers/notificationController.js +const notificationModel = require('../models/notificationModel'); + +const notificationController = { + // 읽지 않은 알림 조회 + async getUnread(req, res) { + try { + const userId = req.user?.id || null; + const notifications = await notificationModel.getUnread(userId); + + res.json({ + success: true, + data: notifications + }); + } catch (error) { + console.error('읽지 않은 알림 조회 오류:', error); + res.status(500).json({ + success: false, + message: '알림 조회 중 오류가 발생했습니다.' + }); + } + }, + + // 전체 알림 조회 + async getAll(req, res) { + try { + const userId = req.user?.id || null; + const page = parseInt(req.query.page) || 1; + const limit = parseInt(req.query.limit) || 20; + + const result = await notificationModel.getAll(userId, page, limit); + + res.json({ + success: true, + data: result.notifications, + pagination: { + total: result.total, + page: result.page, + limit: result.limit, + totalPages: Math.ceil(result.total / result.limit) + } + }); + } catch (error) { + console.error('알림 목록 조회 오류:', error); + res.status(500).json({ + success: false, + message: '알림 조회 중 오류가 발생했습니다.' + }); + } + }, + + // 읽지 않은 알림 개수 + async getUnreadCount(req, res) { + try { + const userId = req.user?.id || null; + const count = await notificationModel.getUnreadCount(userId); + + res.json({ + success: true, + data: { count } + }); + } catch (error) { + console.error('알림 개수 조회 오류:', error); + res.status(500).json({ + success: false, + message: '알림 개수 조회 중 오류가 발생했습니다.' + }); + } + }, + + // 알림 읽음 처리 + async markAsRead(req, res) { + try { + const { id } = req.params; + const success = await notificationModel.markAsRead(id); + + res.json({ + success, + message: success ? '알림을 읽음 처리했습니다.' : '알림을 찾을 수 없습니다.' + }); + } catch (error) { + console.error('알림 읽음 처리 오류:', error); + res.status(500).json({ + success: false, + message: '알림 처리 중 오류가 발생했습니다.' + }); + } + }, + + // 모든 알림 읽음 처리 + async markAllAsRead(req, res) { + try { + const userId = req.user?.id || null; + const count = await notificationModel.markAllAsRead(userId); + + res.json({ + success: true, + message: `${count}개의 알림을 읽음 처리했습니다.`, + data: { count } + }); + } catch (error) { + console.error('전체 읽음 처리 오류:', error); + res.status(500).json({ + success: false, + message: '알림 처리 중 오류가 발생했습니다.' + }); + } + }, + + // 알림 삭제 + async delete(req, res) { + try { + const { id } = req.params; + const success = await notificationModel.delete(id); + + res.json({ + success, + message: success ? '알림을 삭제했습니다.' : '알림을 찾을 수 없습니다.' + }); + } catch (error) { + console.error('알림 삭제 오류:', error); + res.status(500).json({ + success: false, + message: '알림 삭제 중 오류가 발생했습니다.' + }); + } + }, + + // 알림 생성 (시스템용) + async create(req, res) { + try { + const { type, title, message, link_url, user_id } = req.body; + + if (!title) { + return res.status(400).json({ + success: false, + message: '알림 제목은 필수입니다.' + }); + } + + const notificationId = await notificationModel.create({ + user_id, + type, + title, + message, + link_url, + created_by: req.user?.id + }); + + res.json({ + success: true, + message: '알림이 생성되었습니다.', + data: { notification_id: notificationId } + }); + } catch (error) { + console.error('알림 생성 오류:', error); + res.status(500).json({ + success: false, + message: '알림 생성 중 오류가 발생했습니다.' + }); + } + } +}; + +module.exports = notificationController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/notificationRecipientController.js b/deploy/tkfb-package/api.hyungi.net/controllers/notificationRecipientController.js new file mode 100644 index 0000000..e3b4a00 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/notificationRecipientController.js @@ -0,0 +1,91 @@ +// controllers/notificationRecipientController.js +const notificationRecipientModel = require('../models/notificationRecipientModel'); + +const notificationRecipientController = { + // 알림 유형 목록 + getTypes: async (req, res) => { + try { + const types = notificationRecipientModel.getTypes(); + res.json({ success: true, data: types }); + } catch (error) { + console.error('알림 유형 조회 오류:', error); + res.status(500).json({ success: false, error: '알림 유형 조회 실패' }); + } + }, + + // 전체 수신자 목록 (유형별 그룹화) + getAll: async (req, res) => { + try { + console.log('🔔 알림 수신자 목록 조회 시작'); + const recipients = await notificationRecipientModel.getAll(); + console.log('✅ 알림 수신자 목록 조회 완료:', recipients); + res.json({ success: true, data: recipients }); + } catch (error) { + console.error('❌ 수신자 목록 조회 오류:', error.message); + console.error('❌ 스택:', error.stack); + res.status(500).json({ success: false, error: '수신자 목록 조회 실패', detail: error.message }); + } + }, + + // 유형별 수신자 조회 + getByType: async (req, res) => { + try { + const { type } = req.params; + const recipients = await notificationRecipientModel.getByType(type); + res.json({ success: true, data: recipients }); + } catch (error) { + console.error('수신자 조회 오류:', error); + res.status(500).json({ success: false, error: '수신자 조회 실패' }); + } + }, + + // 수신자 추가 + add: async (req, res) => { + try { + const { notification_type, user_id } = req.body; + + if (!notification_type || !user_id) { + return res.status(400).json({ success: false, error: '알림 유형과 사용자 ID가 필요합니다.' }); + } + + await notificationRecipientModel.add(notification_type, user_id, req.user?.user_id); + res.json({ success: true, message: '수신자가 추가되었습니다.' }); + } catch (error) { + console.error('수신자 추가 오류:', error); + res.status(500).json({ success: false, error: '수신자 추가 실패' }); + } + }, + + // 수신자 제거 + remove: async (req, res) => { + try { + const { type, userId } = req.params; + + await notificationRecipientModel.remove(type, userId); + res.json({ success: true, message: '수신자가 제거되었습니다.' }); + } catch (error) { + console.error('수신자 제거 오류:', error); + res.status(500).json({ success: false, error: '수신자 제거 실패' }); + } + }, + + // 유형별 수신자 일괄 설정 + setRecipients: async (req, res) => { + try { + const { type } = req.params; + const { user_ids } = req.body; + + if (!Array.isArray(user_ids)) { + return res.status(400).json({ success: false, error: 'user_ids 배열이 필요합니다.' }); + } + + await notificationRecipientModel.setRecipients(type, user_ids, req.user?.user_id); + res.json({ success: true, message: '수신자가 설정되었습니다.' }); + } catch (error) { + console.error('수신자 설정 오류:', error); + res.status(500).json({ success: false, error: '수신자 설정 실패' }); + } + } +}; + +module.exports = notificationRecipientController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/pageAccessController.js b/deploy/tkfb-package/api.hyungi.net/controllers/pageAccessController.js new file mode 100644 index 0000000..0448e39 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/pageAccessController.js @@ -0,0 +1,200 @@ +// controllers/pageAccessController.js +const PageAccessModel = require('../models/pageAccessModel'); + +const PageAccessController = { + // 사용자의 페이지 권한 조회 + getUserPageAccess: (req, res) => { + const userId = parseInt(req.params.userId); + + if (isNaN(userId)) { + return res.status(400).json({ + success: false, + message: '유효하지 않은 사용자 ID입니다.' + }); + } + + PageAccessModel.getUserPageAccess(userId, (err, results) => { + if (err) { + console.error('페이지 권한 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '페이지 권한 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + // 모든 페이지 목록 조회 + getAllPages: (req, res) => { + PageAccessModel.getAllPages((err, results) => { + if (err) { + console.error('페이지 목록 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '페이지 목록 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + // 페이지 권한 부여 + grantPageAccess: (req, res) => { + const userId = parseInt(req.params.userId); + const { pageId } = req.body; + const grantedBy = req.user.user_id; + + if (isNaN(userId) || !pageId) { + return res.status(400).json({ + success: false, + message: '필수 파라미터가 누락되었습니다.' + }); + } + + PageAccessModel.grantPageAccess(userId, pageId, grantedBy, (err, result) => { + if (err) { + console.error('페이지 권한 부여 오류:', err); + return res.status(500).json({ + success: false, + message: '페이지 권한 부여 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + message: '페이지 권한이 부여되었습니다.', + data: result + }); + }); + }, + + // 페이지 권한 회수 + revokePageAccess: (req, res) => { + const userId = parseInt(req.params.userId); + const pageId = parseInt(req.params.pageId); + + if (isNaN(userId) || isNaN(pageId)) { + return res.status(400).json({ + success: false, + message: '유효하지 않은 파라미터입니다.' + }); + } + + PageAccessModel.revokePageAccess(userId, pageId, (err, result) => { + if (err) { + console.error('페이지 권한 회수 오류:', err); + return res.status(500).json({ + success: false, + message: '페이지 권한 회수 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + message: '페이지 권한이 회수되었습니다.', + data: result + }); + }); + }, + + // 사용자 페이지 권한 일괄 설정 + setUserPageAccess: (req, res) => { + const userId = parseInt(req.params.userId); + const { pageIds } = req.body; + const grantedBy = req.user.user_id; + + if (isNaN(userId)) { + return res.status(400).json({ + success: false, + message: '유효하지 않은 사용자 ID입니다.' + }); + } + + if (!Array.isArray(pageIds)) { + return res.status(400).json({ + success: false, + message: 'pageIds는 배열이어야 합니다.' + }); + } + + PageAccessModel.setUserPageAccess(userId, pageIds, grantedBy, (err, result) => { + if (err) { + console.error('페이지 권한 설정 오류:', err); + return res.status(500).json({ + success: false, + message: '페이지 권한 설정 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + message: '페이지 권한이 설정되었습니다.', + data: result + }); + }); + }, + + // 특정 페이지 접근 권한 확인 + checkPageAccess: (req, res) => { + const userId = req.user.user_id; + const { pageKey } = req.params; + + if (!pageKey) { + return res.status(400).json({ + success: false, + message: '페이지 키가 필요합니다.' + }); + } + + PageAccessModel.checkPageAccess(userId, pageKey, (err, result) => { + if (err) { + console.error('페이지 접근 권한 확인 오류:', err); + return res.status(500).json({ + success: false, + message: '페이지 접근 권한 확인 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: result + }); + }); + }, + + // 계정이 있는 사용자 목록 조회 (권한 관리용) + getUsersWithAccounts: (req, res) => { + PageAccessModel.getUsersWithAccounts((err, results) => { + if (err) { + console.error('사용자 목록 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '사용자 목록 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + } +}; + +module.exports = PageAccessController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/patrolController.js b/deploy/tkfb-package/api.hyungi.net/controllers/patrolController.js new file mode 100644 index 0000000..daff992 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/patrolController.js @@ -0,0 +1,796 @@ +// 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: '서버 오류가 발생했습니다.' }); + } + }, + + // ==================== 작업장 상세 정보 (통합) ==================== + + // 작업장 상세 정보 조회 (시설물, 안전신고, 부적합, 출입, TBM) + getWorkplaceDetail: async (req, res) => { + try { + const { workplaceId } = req.params; + const { date } = req.query; // 기본: 오늘 + const targetDate = date || new Date().toISOString().slice(0, 10); + const { getDb } = require('../dbPool'); + const db = await getDb(); + + // 1. 작업장 기본 정보 (카테고리 지도 이미지 포함) + const [workplaceInfo] = await db.query(` + SELECT w.*, wc.category_name, wc.layout_image as category_layout_image + FROM workplaces w + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + WHERE w.workplace_id = ? + `, [workplaceId]); + + if (!workplaceInfo.length) { + return res.status(404).json({ success: false, message: '작업장을 찾을 수 없습니다.' }); + } + + // 2. 설비 현황 (해당 작업장 - 원래 위치 또는 현재 위치) + let equipments = []; + try { + const [eqResult] = await db.query(` + SELECT e.equipment_id, e.equipment_name, e.equipment_code, e.equipment_type, + e.status, e.notes, e.workplace_id, + e.map_x_percent, e.map_y_percent, e.map_width_percent, e.map_height_percent, + e.is_temporarily_moved, e.current_workplace_id, + e.current_map_x_percent, e.current_map_y_percent, + e.current_map_width_percent, e.current_map_height_percent, + e.moved_at, + ow.workplace_name as original_workplace_name, + cw.workplace_name as current_workplace_name, + CASE + WHEN e.status IN ('maintenance', 'repair_needed', 'repair_external') THEN 1 + WHEN e.is_temporarily_moved = 1 THEN 1 + ELSE 0 + END as needs_attention + FROM equipments e + LEFT JOIN workplaces ow ON e.workplace_id = ow.workplace_id + LEFT JOIN workplaces cw ON e.current_workplace_id = cw.workplace_id + WHERE (e.workplace_id = ? OR e.current_workplace_id = ?) + AND e.status != 'inactive' + ORDER BY needs_attention DESC, e.equipment_name + `, [workplaceId, workplaceId]); + equipments = eqResult; + } catch (eqError) { + console.log('설비 조회 스킵 (테이블 없음 또는 오류):', eqError.message); + } + + // 3. 수리 요청 현황 (미완료) - 테이블 존재 여부 확인 후 조회 + let repairRequests = []; + try { + const [repairResult] = await db.query(` + SELECT er.request_id, er.request_date, er.repair_category, er.description, + er.priority, er.status, e.equipment_name, e.equipment_code + FROM equipment_repair_requests er + JOIN equipments e ON er.equipment_id = e.equipment_id + WHERE e.workplace_id = ? AND er.status NOT IN ('completed', 'cancelled') + ORDER BY + CASE er.priority WHEN 'emergency' THEN 1 WHEN 'high' THEN 2 WHEN 'normal' THEN 3 ELSE 4 END, + er.request_date DESC + LIMIT 10 + `, [workplaceId]); + repairRequests = repairResult; + } catch (repairError) { + console.log('수리요청 조회 스킵 (테이블 없음 또는 오류):', repairError.message); + } + + // 4. 안전 신고 및 부적합 사항 - 테이블 존재 여부 확인 후 조회 + let workIssues = []; + try { + const [issueResult] = await db.query(` + SELECT wi.report_id, wi.issue_type, wi.title, wi.description, + wi.status, wi.severity, wi.created_at, wi.resolved_at, + wic.category_name, wic.issue_type as category_type, + u.name as reporter_name + FROM work_issue_reports wi + LEFT JOIN work_issue_categories wic ON wi.category_id = wic.category_id + LEFT JOIN Users u ON wi.reporter_id = u.user_id + WHERE wi.workplace_id = ? + AND wi.created_at >= DATE_SUB(NOW(), INTERVAL 30 DAY) + ORDER BY wi.created_at DESC + LIMIT 20 + `, [workplaceId]); + workIssues = issueResult; + } catch (issueError) { + console.log('신고 조회 스킵 (테이블 없음 또는 오류):', issueError.message); + } + + // 5. 오늘의 출입 기록 (해당 공장 카테고리) + const categoryId = workplaceInfo[0].category_id; + let visitRecords = []; + try { + const [visitResult] = await db.query(` + SELECT vr.request_id, vr.visitor_name, vr.visitor_company, vr.visit_purpose, + vr.visit_date, vr.visit_time_from, vr.visit_time_to, vr.status, + vr.vehicle_number, vr.companion_count, + vp.purpose_name, u.name as requester_name + FROM visit_requests vr + LEFT JOIN visit_purposes vp ON vr.purpose_id = vp.purpose_id + LEFT JOIN Users u ON vr.requester_id = u.user_id + WHERE vr.category_id = ? AND vr.visit_date = ? AND vr.status = 'approved' + ORDER BY vr.visit_time_from + `, [categoryId, targetDate]); + visitRecords = visitResult; + } catch (visitError) { + console.log('출입기록 조회 스킵 (테이블 없음 또는 오류):', visitError.message); + } + + // 6. 오늘의 TBM 세션 (해당 공장 카테고리) + let tbmSessions = []; + try { + const [tbmResult] = await db.query(` + SELECT ts.session_id, ts.session_date, ts.work_location, ts.status, + ts.work_content, ts.safety_measures, ts.team_size, + t.task_name, wt.name as work_type_name, + u.name as leader_name, w.worker_name as leader_worker_name + FROM tbm_sessions ts + LEFT JOIN tasks t ON ts.task_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN Users u ON ts.leader_id = u.user_id + LEFT JOIN workers w ON ts.leader_worker_id = w.worker_id + WHERE ts.category_id = ? AND ts.session_date = ? + ORDER BY ts.created_at DESC + `, [categoryId, targetDate]); + tbmSessions = tbmResult; + } catch (tbmError) { + console.log('TBM 조회 스킵 (테이블 없음 또는 오류):', tbmError.message); + } + + // 7. TBM 팀원 정보 (세션별) + let tbmWithTeams = []; + try { + tbmWithTeams = await Promise.all(tbmSessions.map(async (session) => { + const [team] = await db.query(` + SELECT tta.assignment_id, w.worker_name, w.occupation, + tta.attendance_status, tta.signature_image + FROM tbm_team_assignments tta + JOIN workers w ON tta.worker_id = w.worker_id + WHERE tta.session_id = ? + ORDER BY w.worker_name + `, [session.session_id]); + return { ...session, team }; + })); + } catch (teamError) { + console.log('TBM 팀원 조회 스킵:', teamError.message); + tbmWithTeams = tbmSessions.map(s => ({ ...s, team: [] })); + } + + // 8. 최근 순회점검 결과 (해당 작업장) + let recentPatrol = []; + try { + const [patrolResult] = await db.query(` + SELECT ps.session_id, ps.patrol_date, ps.patrol_time, ps.status, + ps.notes, u.name as inspector_name, + (SELECT COUNT(*) FROM patrol_check_records pcr + WHERE pcr.session_id = ps.session_id AND pcr.workplace_id = ?) as checked_count, + (SELECT COUNT(*) FROM patrol_check_records pcr + WHERE pcr.session_id = ps.session_id AND pcr.workplace_id = ? + AND pcr.check_result IN ('warning', 'bad')) as issue_count + FROM patrol_sessions ps + LEFT JOIN Users u ON ps.inspector_id = u.user_id + WHERE ps.category_id = ? AND ps.patrol_date >= DATE_SUB(NOW(), INTERVAL 7 DAY) + ORDER BY ps.patrol_date DESC, ps.patrol_time DESC + LIMIT 5 + `, [workplaceId, workplaceId, categoryId]); + recentPatrol = patrolResult; + } catch (patrolError) { + console.log('순회점검 조회 스킵 (테이블 없음 또는 오류):', patrolError.message); + } + + res.json({ + success: true, + data: { + workplace: workplaceInfo[0], + equipments: equipments, + repairRequests: repairRequests, + workIssues: { + safety: workIssues.filter(i => i.category_type === 'safety'), + nonconformity: workIssues.filter(i => i.category_type === 'nonconformity'), + all: workIssues + }, + visitRecords: visitRecords, + tbmSessions: tbmWithTeams, + recentPatrol: recentPatrol, + summary: { + equipmentCount: equipments.length, + needsAttention: equipments.filter(e => e.needs_attention).length, + pendingRepairs: repairRequests.length, + openIssues: workIssues.filter(i => i.status !== 'closed').length, + todayVisitors: visitRecords.reduce((sum, v) => sum + 1 + (v.companion_count || 0), 0), + todayTbmSessions: tbmSessions.length + } + } + }); + } catch (error) { + console.error('작업장 상세 정보 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // ==================== 구역 내 등록 물품/시설물 ==================== + + // 구역 내 물품/시설물 목록 조회 + getZoneItems: async (req, res) => { + try { + const { workplaceId } = req.params; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + // 테이블이 없으면 생성 + await db.query(` + CREATE TABLE IF NOT EXISTS workplace_zone_items ( + item_id INT AUTO_INCREMENT PRIMARY KEY, + workplace_id INT NOT NULL, + item_name VARCHAR(200) NOT NULL COMMENT '물품/시설물 명칭', + item_type VARCHAR(50) DEFAULT 'general' COMMENT '유형 (heavy_equipment, hazardous, storage, general 등)', + description TEXT COMMENT '상세 설명', + x_percent DECIMAL(5,2) NOT NULL COMMENT '영역 시작 X 좌표 (%)', + y_percent DECIMAL(5,2) NOT NULL COMMENT '영역 시작 Y 좌표 (%)', + width_percent DECIMAL(5,2) DEFAULT 10 COMMENT '영역 너비 (%)', + height_percent DECIMAL(5,2) DEFAULT 10 COMMENT '영역 높이 (%)', + color VARCHAR(20) DEFAULT '#3b82f6' COMMENT '표시 색상', + warning_level VARCHAR(20) DEFAULT 'normal' COMMENT '주의 수준 (normal, caution, danger)', + quantity INT DEFAULT 1 COMMENT '수량', + unit VARCHAR(20) DEFAULT '개' COMMENT '단위', + weight_kg DECIMAL(10,2) DEFAULT NULL COMMENT '중량 (kg)', + is_active BOOLEAN DEFAULT TRUE, + created_by INT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + INDEX idx_workplace (workplace_id), + INDEX idx_type (item_type) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='구역 내 등록 물품/시설물' + `); + + // 새 컬럼 추가 (없으면) + try { + await db.query(`ALTER TABLE workplace_zone_items ADD COLUMN project_type VARCHAR(20) DEFAULT 'non_project'`); + } catch (e) { /* 이미 존재 */ } + try { + await db.query(`ALTER TABLE workplace_zone_items ADD COLUMN project_id INT NULL`); + } catch (e) { /* 이미 존재 */ } + + const [items] = await db.query(` + SELECT zi.*, p.project_name + FROM workplace_zone_items zi + LEFT JOIN projects p ON zi.project_id = p.project_id + WHERE zi.workplace_id = ? AND zi.is_active = TRUE + ORDER BY zi.warning_level DESC, zi.item_name + `, [workplaceId]); + + // 사진 테이블 존재 확인 및 사진 조회 + try { + for (const item of items) { + const [photos] = await db.query(` + SELECT photo_id, photo_url, created_at + FROM zone_item_photos + WHERE item_id = ? + ORDER BY created_at DESC + `, [item.item_id]); + item.photos = photos || []; + } + } catch (e) { + // 사진 테이블이 없으면 무시 + items.forEach(item => item.photos = []); + } + + res.json({ success: true, data: items }); + } catch (error) { + console.error('구역 물품 목록 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 등록 + createZoneItem: async (req, res) => { + try { + const { workplaceId } = req.params; + const { item_name, item_type, description, x_percent, y_percent, width_percent, height_percent, + color, warning_level, project_type, project_id } = req.body; + const createdBy = req.user?.user_id; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + if (!item_name || x_percent === undefined || y_percent === undefined) { + return res.status(400).json({ success: false, message: '필수 정보가 누락되었습니다.' }); + } + + // 테이블에 새 컬럼 추가 (없으면) + try { + await db.query(`ALTER TABLE workplace_zone_items ADD COLUMN project_type VARCHAR(20) DEFAULT 'non_project'`); + } catch (e) { /* 이미 존재 */ } + try { + await db.query(`ALTER TABLE workplace_zone_items ADD COLUMN project_id INT NULL`); + } catch (e) { /* 이미 존재 */ } + + const [result] = await db.query(` + INSERT INTO workplace_zone_items + (workplace_id, item_name, item_type, description, x_percent, y_percent, width_percent, height_percent, + color, warning_level, project_type, project_id, created_by) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `, [workplaceId, item_name, item_type || 'working', description, x_percent, y_percent, + width_percent || 5, height_percent || 5, color || '#3b82f6', warning_level || 'good', + project_type || 'non_project', project_id || null, createdBy]); + + const newItemId = result.insertId; + + // 등록 이력 저장 + try { + await db.query(` + INSERT INTO zone_item_history (item_id, action_type, new_values, changed_by) + VALUES (?, 'created', ?, ?) + `, [newItemId, JSON.stringify({ item_name, item_type, warning_level, project_type }), createdBy]); + } catch (e) { /* 테이블 없으면 무시 */ } + + res.json({ + success: true, + data: { item_id: newItemId }, + message: '현황이 등록되었습니다.' + }); + } catch (error) { + console.error('구역 현황 등록 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 수정 + updateZoneItem: async (req, res) => { + try { + const { itemId } = req.params; + const { item_name, item_type, description, x_percent, y_percent, width_percent, height_percent, + color, warning_level, project_type, project_id } = req.body; + const userId = req.user?.user_id; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + // 이력 테이블 생성 (없으면) + await db.query(` + CREATE TABLE IF NOT EXISTS zone_item_history ( + history_id INT AUTO_INCREMENT PRIMARY KEY, + item_id INT NOT NULL, + action_type VARCHAR(20) NOT NULL COMMENT 'created, updated, deleted', + changed_fields TEXT COMMENT '변경된 필드 JSON', + old_values TEXT COMMENT '이전 값 JSON', + new_values TEXT COMMENT '새 값 JSON', + changed_by INT, + changed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX idx_item (item_id), + INDEX idx_date (changed_at) + ) + `); + + // 기존 데이터 조회 (이력용) + const [oldData] = await db.query(`SELECT * FROM workplace_zone_items WHERE item_id = ?`, [itemId]); + const oldItem = oldData[0]; + + // 업데이트 + await db.query(` + UPDATE workplace_zone_items SET + item_name = COALESCE(?, item_name), + item_type = COALESCE(?, item_type), + description = ?, + x_percent = COALESCE(?, x_percent), + y_percent = COALESCE(?, y_percent), + width_percent = COALESCE(?, width_percent), + height_percent = COALESCE(?, height_percent), + color = COALESCE(?, color), + warning_level = COALESCE(?, warning_level), + project_type = COALESCE(?, project_type), + project_id = ? + WHERE item_id = ? + `, [item_name, item_type, description, x_percent, y_percent, width_percent, height_percent, + color, warning_level, project_type, project_id, itemId]); + + // 변경 이력 저장 + if (oldItem) { + const changedFields = []; + const oldValues = {}; + const newValues = {}; + + const fieldMap = { item_name, item_type, description, warning_level, project_type, project_id }; + for (const [key, newVal] of Object.entries(fieldMap)) { + if (newVal !== undefined && oldItem[key] !== newVal) { + changedFields.push(key); + oldValues[key] = oldItem[key]; + newValues[key] = newVal; + } + } + + if (changedFields.length > 0) { + await db.query(` + INSERT INTO zone_item_history (item_id, action_type, changed_fields, old_values, new_values, changed_by) + VALUES (?, 'updated', ?, ?, ?, ?) + `, [itemId, JSON.stringify(changedFields), JSON.stringify(oldValues), JSON.stringify(newValues), userId]); + } + } + + res.json({ success: true, message: '현황이 수정되었습니다.' }); + } catch (error) { + console.error('구역 현황 수정 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 사진 업로드 + uploadZoneItemPhoto: async (req, res) => { + try { + const { item_id } = req.body; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + if (!req.file) { + return res.status(400).json({ success: false, message: '파일이 없습니다.' }); + } + + // 사진 테이블 생성 (없으면) + await db.query(` + CREATE TABLE IF NOT EXISTS zone_item_photos ( + photo_id INT AUTO_INCREMENT PRIMARY KEY, + item_id INT NOT NULL, + photo_url VARCHAR(500) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + INDEX idx_item_id (item_id) + ) + `); + + const photoUrl = `/uploads/${req.file.filename}`; + const [result] = await db.query( + `INSERT INTO zone_item_photos (item_id, photo_url) VALUES (?, ?)`, + [item_id, photoUrl] + ); + + res.json({ + success: true, + data: { photo_id: result.insertId, photo_url: photoUrl }, + message: '사진이 업로드되었습니다.' + }); + } catch (error) { + console.error('사진 업로드 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 삭제 + deleteZoneItem: async (req, res) => { + try { + const { itemId } = req.params; + const userId = req.user?.user_id; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + // 기존 데이터 조회 (이력용) + const [oldData] = await db.query(`SELECT * FROM workplace_zone_items WHERE item_id = ?`, [itemId]); + const oldItem = oldData[0]; + + // 소프트 삭제 + await db.query(`UPDATE workplace_zone_items SET is_active = FALSE WHERE item_id = ?`, [itemId]); + + // 삭제 이력 저장 + if (oldItem) { + await db.query(` + INSERT INTO zone_item_history (item_id, action_type, old_values, changed_by) + VALUES (?, 'deleted', ?, ?) + `, [itemId, JSON.stringify({ item_name: oldItem.item_name, item_type: oldItem.item_type }), userId]); + } + + res.json({ success: true, message: '현황이 삭제되었습니다.' }); + } catch (error) { + console.error('구역 현황 삭제 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + }, + + // 구역 현황 이력 조회 + getZoneItemHistory: async (req, res) => { + try { + const { itemId } = req.params; + const { getDb } = require('../dbPool'); + const db = await getDb(); + + const [history] = await db.query(` + SELECT h.*, u.full_name as changed_by_name + FROM zone_item_history h + LEFT JOIN users u ON h.changed_by = u.user_id + WHERE h.item_id = ? + ORDER BY h.changed_at DESC + LIMIT 50 + `, [itemId]); + + res.json({ success: true, data: history }); + } catch (error) { + console.error('현황 이력 조회 오류:', error); + res.status(500).json({ success: false, message: '서버 오류가 발생했습니다.' }); + } + } +}; + +module.exports = PatrolController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/projectController.js b/deploy/tkfb-package/api.hyungi.net/controllers/projectController.js new file mode 100644 index 0000000..0eccedb --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/projectController.js @@ -0,0 +1,142 @@ +/** + * 프로젝트 관리 컨트롤러 + * + * 프로젝트 CRUD API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const projectModel = require('../models/projectModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); +const cache = require('../utils/cache'); + +/** + * 프로젝트 생성 + */ +exports.createProject = asyncHandler(async (req, res) => { + const projectData = req.body; + + logger.info('프로젝트 생성 요청', { name: projectData.name }); + + const id = await projectModel.create(projectData); + + // 프로젝트 캐시 무효화 + await cache.invalidateCache.project(); + + logger.info('프로젝트 생성 성공', { project_id: id }); + + res.status(201).json({ + success: true, + data: { project_id: id }, + message: '프로젝트가 성공적으로 생성되었습니다' + }); +}); + +/** + * 전체 프로젝트 조회 + */ +exports.getAllProjects = asyncHandler(async (req, res) => { + const rows = await projectModel.getAll(); + + res.json({ + success: true, + data: rows, + message: '프로젝트 목록 조회 성공' + }); +}); + +/** + * 활성 프로젝트만 조회 (작업보고서용) + */ +exports.getActiveProjects = asyncHandler(async (req, res) => { + const rows = await projectModel.getActiveProjects(); + + res.json({ + success: true, + data: rows, + message: '활성 프로젝트 목록 조회 성공' + }); +}); + +/** + * 단일 프로젝트 조회 + */ +exports.getProjectById = asyncHandler(async (req, res) => { + const id = parseInt(req.params.project_id, 10); + + if (isNaN(id)) { + throw new ValidationError('유효하지 않은 프로젝트 ID입니다'); + } + + const row = await projectModel.getById(id); + + if (!row) { + throw new NotFoundError('프로젝트를 찾을 수 없습니다'); + } + + res.json({ + success: true, + data: row, + message: '프로젝트 조회 성공' + }); +}); + +/** + * 프로젝트 수정 + */ +exports.updateProject = asyncHandler(async (req, res) => { + const id = parseInt(req.params.project_id, 10); + + if (isNaN(id)) { + throw new ValidationError('유효하지 않은 프로젝트 ID입니다'); + } + + const data = { ...req.body, project_id: id }; + + const changes = await projectModel.update(data); + + if (changes === 0) { + throw new NotFoundError('프로젝트를 찾을 수 없습니다'); + } + + // 프로젝트 캐시 무효화 + await cache.invalidateCache.project(); + + logger.info('프로젝트 수정 성공', { project_id: id }); + + res.json({ + success: true, + data: { changes }, + message: '프로젝트 정보가 성공적으로 수정되었습니다' + }); +}); + +/** + * 프로젝트 삭제 + */ +exports.removeProject = asyncHandler(async (req, res) => { + const id = parseInt(req.params.project_id, 10); + + if (isNaN(id)) { + throw new ValidationError('유효하지 않은 프로젝트 ID입니다'); + } + + const changes = await projectModel.remove(id); + + if (changes === 0) { + throw new NotFoundError('프로젝트를 찾을 수 없습니다'); + } + + // 프로젝트 캐시 무효화 + await cache.invalidateCache.project(); + + logger.info('프로젝트 삭제 성공', { project_id: id }); + + res.json({ + success: true, + message: '프로젝트가 성공적으로 삭제되었습니다' + }); +}); diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/systemController.js b/deploy/tkfb-package/api.hyungi.net/controllers/systemController.js new file mode 100644 index 0000000..d03da90 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/systemController.js @@ -0,0 +1,467 @@ +// 시스템 관리 컨트롤러 +const { getDb } = require('../dbPool'); +const bcrypt = require('bcryptjs'); +const { ApiError, asyncHandler, handleDatabaseError } = require('../utils/errorHandler'); +const { validateSchema, schemas } = require('../utils/validator'); + +/** + * 시스템 상태 확인 + */ +exports.getSystemStatus = asyncHandler(async (req, res) => { + try { + const db = await getDb(); + + // 데이터베이스 연결 상태 확인 + const [dbStatus] = await db.query('SELECT 1 as status'); + + // 시스템 상태 정보 + const systemStatus = { + server: 'online', + database: dbStatus.length > 0 ? 'online' : 'offline' + }; + + res.health('healthy', systemStatus); + + } catch (error) { + handleDatabaseError(error, '시스템 상태 확인'); + } +}); + +/** + * 데이터베이스 상태 확인 + */ +exports.getDatabaseStatus = asyncHandler(async (req, res) => { + try { + const db = await getDb(); + + // 데이터베이스 연결 수 확인 + const [connections] = await db.query('SHOW STATUS LIKE "Threads_connected"'); + const [maxConnections] = await db.query('SHOW VARIABLES LIKE "max_connections"'); + + // 데이터베이스 크기 확인 + const [dbSize] = await db.query(` + SELECT + ROUND(SUM(data_length + index_length) / 1024 / 1024, 2) AS size_mb + FROM information_schema.tables + WHERE table_schema = DATABASE() + `); + + const dbStatus = { + status: 'online', + connections: parseInt(connections[0]?.Value || 0), + max_connections: parseInt(maxConnections[0]?.Value || 0), + size_mb: dbSize[0]?.size_mb || 0 + }; + + res.success(dbStatus, '데이터베이스 상태 조회 성공'); + + } catch (error) { + handleDatabaseError(error, '데이터베이스 상태 확인'); + } +}); + +/** + * 시스템 알림 조회 + */ +exports.getSystemAlerts = async (req, res) => { + try { + const db = await getDb(); + + // 최근 실패한 로그인 시도 + const [failedLogins] = await db.query(` + SELECT COUNT(*) as count + FROM login_logs + WHERE login_status = 'failed' + AND login_time > DATE_SUB(NOW(), INTERVAL 1 HOUR) + `); + + // 비활성 사용자 수 + const [inactiveusers] = await db.query(` + SELECT COUNT(*) as count + FROM users + WHERE is_active = 0 + `); + + const alerts = []; + + if (failedLogins[0]?.count > 5) { + alerts.push({ + type: 'security', + level: 'warning', + message: `최근 1시간 동안 ${failedLogins[0].count}회의 로그인 실패가 발생했습니다.`, + timestamp: new Date().toISOString() + }); + } + + if (inactiveusers[0]?.count > 0) { + alerts.push({ + type: 'user', + level: 'info', + message: `${inactiveusers[0].count}명의 비활성 사용자가 있습니다.`, + timestamp: new Date().toISOString() + }); + } + + res.json({ + success: true, + alerts: alerts + }); + + } catch (error) { + console.error('시스템 알림 조회 오류:', error); + res.status(500).json({ + success: false, + error: '시스템 알림을 조회할 수 없습니다.' + }); + } +}; + +/** + * 최근 시스템 활동 조회 + */ +exports.getRecentActivities = async (req, res) => { + try { + const db = await getDb(); + + // 최근 로그인 활동 + const [loginActivities] = await db.query(` + SELECT + ll.login_time as created_at, + u.name as user_name, + ll.login_status, + ll.ip_address, + 'login' as activity_type + FROM login_logs ll + LEFT JOIN users u ON ll.user_id = u.user_id + ORDER BY ll.login_time DESC + LIMIT 10 + `); + + // 비밀번호 변경 활동 + const [passwordActivities] = await db.query(` + SELECT + pcl.changed_at as created_at, + u.name as user_name, + pcl.change_type, + 'password_change' as activity_type + FROM password_change_logs pcl + LEFT JOIN users u ON pcl.user_id = u.user_id + ORDER BY pcl.changed_at DESC + LIMIT 5 + `); + + // 활동 통합 및 정렬 + const activities = [ + ...loginActivities.map(activity => ({ + type: activity.login_status === 'success' ? 'login' : 'login_failed', + title: activity.login_status === 'success' + ? `${activity.user_name || '알 수 없는 사용자'} 로그인` + : `로그인 실패 (${activity.ip_address})`, + description: activity.login_status === 'success' + ? `IP: ${activity.ip_address}` + : `사용자: ${activity.user_name || '알 수 없음'}`, + created_at: activity.created_at + })), + ...passwordActivities.map(activity => ({ + type: 'password_change', + title: `${activity.user_name || '알 수 없는 사용자'} 비밀번호 변경`, + description: `변경 유형: ${activity.change_type}`, + created_at: activity.created_at + })) + ]; + + // 시간순 정렬 + activities.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); + + res.json({ + success: true, + data: activities.slice(0, 15) + }); + + } catch (error) { + console.error('최근 활동 조회 오류:', error); + res.status(500).json({ + success: false, + error: '최근 활동을 조회할 수 없습니다.' + }); + } +}; + +/** + * 사용자 통계 조회 + */ +exports.getUserStats = async (req, res) => { + try { + const db = await getDb(); + + // 전체 사용자 수 + const [totalusers] = await db.query('SELECT COUNT(*) as count FROM users'); + + // 활성 사용자 수 + const [activeusers] = await db.query('SELECT COUNT(*) as count FROM users WHERE is_active = 1'); + + // 최근 24시간 로그인 사용자 수 + const [recentLogins] = await db.query(` + SELECT COUNT(DISTINCT user_id) as count + FROM login_logs + WHERE login_status = 'success' + AND login_time > DATE_SUB(NOW(), INTERVAL 24 HOUR) + `); + + // 권한별 사용자 수 + const [roleStats] = await db.query(` + SELECT role, COUNT(*) as count + FROM users + WHERE is_active = 1 + GROUP BY role + `); + + res.json({ + success: true, + data: { + total: totalusers[0]?.count || 0, + active: activeusers[0]?.count || 0, + recent_logins: recentLogins[0]?.count || 0, + by_role: roleStats + } + }); + + } catch (error) { + console.error('사용자 통계 조회 오류:', error); + res.status(500).json({ + success: false, + error: '사용자 통계를 조회할 수 없습니다.' + }); + } +}; + +/** + * 모든 사용자 목록 조회 (시스템 관리자용) + */ +exports.getAllUsers = asyncHandler(async (req, res) => { + try { + const db = await getDb(); + + const [users] = await db.query(` + SELECT + user_id, + username, + name, + email, + role, + access_level, + worker_id, + is_active, + last_login_at, + failed_login_attempts, + locked_until, + created_at, + updated_at + FROM users + ORDER BY created_at DESC + `); + + res.list(users, '사용자 목록 조회 성공'); + + } catch (error) { + handleDatabaseError(error, '사용자 목록 조회'); + } +}); + +/** + * 사용자 생성 + */ +exports.createUser = asyncHandler(async (req, res) => { + const { username, password, name, email, role, access_level, worker_id } = req.body; + + // 스키마 기반 유효성 검사 + validateSchema(req.body, schemas.createUser); + + try { + const db = await getDb(); + + // 사용자명 중복 확인 + const [existing] = await db.query('SELECT user_id FROM users WHERE username = ?', [username]); + if (existing.length > 0) { + throw new ApiError('이미 존재하는 사용자명입니다.', 409); + } + + // 이메일 중복 확인 (이메일이 제공된 경우) + if (email) { + const [existingEmail] = await db.query('SELECT user_id FROM users WHERE email = ?', [email]); + if (existingEmail.length > 0) { + throw new ApiError('이미 사용 중인 이메일입니다.', 409); + } + } + + // 비밀번호 해시화 + const hashedPassword = await bcrypt.hash(password, 10); + + // 사용자 생성 + const [result] = await db.query(` + INSERT INTO users (username, password, name, email, role, access_level, worker_id, is_active, created_at, password_changed_at) + VALUES (?, ?, ?, ?, ?, ?, ?, 1, NOW(), NOW()) + `, [username, hashedPassword, name, email || null, role, access_level || role, worker_id || null]); + + // 비밀번호 변경 로그 기록 + await db.query(` + INSERT INTO password_change_logs (user_id, changed_by_user_id, changed_at, change_type) + VALUES (?, ?, NOW(), 'initial') + `, [result.insertId, req.user.user_id]); + + res.created({ user_id: result.insertId }, '사용자가 성공적으로 생성되었습니다.'); + + } catch (error) { + handleDatabaseError(error, '사용자 생성'); + } +}); + +/** + * 사용자 수정 + */ +exports.updateUser = async (req, res) => { + try { + const { id } = req.params; + const { name, email, role, access_level, is_active, worker_id } = req.body; + const db = await getDb(); + + // 사용자 존재 확인 + const [user] = await db.query('SELECT user_id FROM users WHERE user_id = ?', [id]); + if (user.length === 0) { + return res.status(404).json({ + success: false, + error: '해당 사용자를 찾을 수 없습니다.' + }); + } + + // 이메일 중복 확인 (다른 사용자가 사용 중인지) + if (email) { + const [existingEmail] = await db.query( + 'SELECT user_id FROM users WHERE email = ? AND user_id != ?', + [email, id] + ); + if (existingEmail.length > 0) { + return res.status(409).json({ + success: false, + error: '이미 사용 중인 이메일입니다.' + }); + } + } + + // 사용자 정보 업데이트 + await db.query(` + UPDATE users + SET name = ?, email = ?, role = ?, access_level = ?, is_active = ?, worker_id = ?, updated_at = NOW() + WHERE user_id = ? + `, [name, email || null, role, access_level || role, is_active ? 1 : 0, worker_id || null, id]); + + res.json({ + success: true, + message: '사용자 정보가 성공적으로 업데이트되었습니다.' + }); + + } catch (error) { + console.error('사용자 수정 오류:', error); + res.status(500).json({ + success: false, + error: '사용자 수정 중 오류가 발생했습니다.' + }); + } +}; + +/** + * 사용자 삭제 + */ +exports.deleteUser = async (req, res) => { + try { + const { id } = req.params; + const db = await getDb(); + + // 자기 자신 삭제 방지 + if (parseInt(id) === req.user.user_id) { + return res.status(400).json({ + success: false, + error: '자기 자신은 삭제할 수 없습니다.' + }); + } + + // 사용자 존재 확인 + const [user] = await db.query('SELECT user_id, username FROM users WHERE user_id = ?', [id]); + if (user.length === 0) { + return res.status(404).json({ + success: false, + error: '해당 사용자를 찾을 수 없습니다.' + }); + } + + // 사용자 삭제 (관련 로그는 유지) + await db.query('DELETE FROM users WHERE user_id = ?', [id]); + + res.json({ + success: true, + message: `사용자 '${user[0].username}'가 성공적으로 삭제되었습니다.` + }); + + } catch (error) { + console.error('사용자 삭제 오류:', error); + res.status(500).json({ + success: false, + error: '사용자 삭제 중 오류가 발생했습니다.' + }); + } +}; + +/** + * 사용자 비밀번호 재설정 + */ +exports.resetUserPassword = async (req, res) => { + try { + const { id } = req.params; + const { new_password } = req.body; + const db = await getDb(); + + if (!new_password || new_password.length < 6) { + return res.status(400).json({ + success: false, + error: '비밀번호는 최소 6자 이상이어야 합니다.' + }); + } + + // 사용자 존재 확인 + const [user] = await db.query('SELECT user_id, username FROM users WHERE user_id = ?', [id]); + if (user.length === 0) { + return res.status(404).json({ + success: false, + error: '해당 사용자를 찾을 수 없습니다.' + }); + } + + // 비밀번호 해시화 + const hashedPassword = await bcrypt.hash(new_password, 10); + + // 비밀번호 업데이트 + await db.query(` + UPDATE users + SET password = ?, password_changed_at = NOW(), failed_login_attempts = 0, locked_until = NULL + WHERE user_id = ? + `, [hashedPassword, id]); + + // 비밀번호 변경 로그 기록 + await db.query(` + INSERT INTO password_change_logs (user_id, changed_by_user_id, changed_at, change_type) + VALUES (?, ?, NOW(), 'admin') + `, [id, req.user.user_id]); + + res.json({ + success: true, + message: `사용자 '${user[0].username}'의 비밀번호가 재설정되었습니다.` + }); + + } catch (error) { + console.error('비밀번호 재설정 오류:', error); + res.status(500).json({ + success: false, + error: '비밀번호 재설정 중 오류가 발생했습니다.' + }); + } +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/taskController.js b/deploy/tkfb-package/api.hyungi.net/controllers/taskController.js new file mode 100644 index 0000000..d9cdc30 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/taskController.js @@ -0,0 +1,152 @@ +/** + * 작업 관리 컨트롤러 + * + * 작업 CRUD API 엔드포인트 핸들러 + * (공정=work_types에 속하는 세부 작업) + * + * @author TK-FB-Project + * @since 2026-01-26 + */ + +const taskModel = require('../models/taskModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); + +// ==================== 작업 CRUD ==================== + +/** + * 작업 생성 + */ +exports.createTask = asyncHandler(async (req, res) => { + const taskData = req.body; + + if (!taskData.task_name) { + throw new ValidationError('작업명은 필수 입력 항목입니다'); + } + + logger.info('작업 생성 요청', { name: taskData.task_name }); + + const id = await taskModel.createTask(taskData); + + logger.info('작업 생성 성공', { task_id: id }); + + res.status(201).json({ + success: true, + data: { task_id: id }, + message: '작업이 성공적으로 생성되었습니다' + }); +}); + +/** + * 전체 작업 조회 (work_type_id 필터 지원) + */ +exports.getAllTasks = asyncHandler(async (req, res) => { + const { work_type_id } = req.query; + + let rows; + if (work_type_id) { + // 특정 공정의 활성 작업만 조회 + rows = await taskModel.getTasksByWorkType(work_type_id); + } else { + rows = await taskModel.getAllTasks(); + } + + res.json({ + success: true, + data: rows, + message: '작업 목록 조회 성공' + }); +}); + +/** + * 활성 작업만 조회 + */ +exports.getActiveTasks = asyncHandler(async (req, res) => { + const rows = await taskModel.getActiveTasks(); + + res.json({ + success: true, + data: rows, + message: '활성 작업 목록 조회 성공' + }); +}); + +/** + * 공정별 작업 조회 + */ +exports.getTasksByWorkType = asyncHandler(async (req, res) => { + const workTypeId = req.params.work_type_id || req.query.work_type_id; + + if (!workTypeId) { + throw new ValidationError('공정 ID가 필요합니다'); + } + + const rows = await taskModel.getTasksByWorkType(workTypeId); + + res.json({ + success: true, + data: rows, + message: '공정별 작업 목록 조회 성공' + }); +}); + +/** + * 단일 작업 조회 + */ +exports.getTaskById = asyncHandler(async (req, res) => { + const taskId = req.params.id; + + const task = await taskModel.getTaskById(taskId); + + if (!task) { + throw new NotFoundError('작업을 찾을 수 없습니다'); + } + + res.json({ + success: true, + data: task, + message: '작업 조회 성공' + }); +}); + +/** + * 작업 수정 + */ +exports.updateTask = asyncHandler(async (req, res) => { + const taskId = req.params.id; + const taskData = req.body; + + if (!taskData.task_name) { + throw new ValidationError('작업명은 필수 입력 항목입니다'); + } + + logger.info('작업 수정 요청', { task_id: taskId }); + + await taskModel.updateTask(taskId, taskData); + + logger.info('작업 수정 성공', { task_id: taskId }); + + res.json({ + success: true, + message: '작업이 성공적으로 수정되었습니다' + }); +}); + +/** + * 작업 삭제 + */ +exports.deleteTask = asyncHandler(async (req, res) => { + const taskId = req.params.id; + + logger.info('작업 삭제 요청', { task_id: taskId }); + + await taskModel.deleteTask(taskId); + + logger.info('작업 삭제 성공', { task_id: taskId }); + + res.json({ + success: true, + message: '작업이 성공적으로 삭제되었습니다' + }); +}); diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/tbmController.js b/deploy/tkfb-package/api.hyungi.net/controllers/tbmController.js new file mode 100644 index 0000000..dd6fd39 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/tbmController.js @@ -0,0 +1,893 @@ +// controllers/tbmController.js - TBM 시스템 컨트롤러 +const TbmModel = require('../models/tbmModel'); + +const TbmController = { + // ==================== TBM 세션 관련 ==================== + + /** + * TBM 세션 생성 + */ + createSession: (req, res) => { + const sessionData = { + session_date: req.body.session_date, + leader_id: req.body.leader_id || null, + project_id: req.body.project_id || null, + work_location: req.body.work_location || null, + work_description: req.body.work_description || null, + safety_notes: req.body.safety_notes || null, + start_time: req.body.start_time || null, + created_by: req.user.user_id + }; + + // 필수 필드 검증 (날짜만 필수, leader_id는 관리자의 경우 null 허용) + if (!sessionData.session_date) { + return res.status(400).json({ + success: false, + message: 'TBM 날짜는 필수입니다.' + }); + } + + TbmModel.createSession(sessionData, (err, result) => { + if (err) { + console.error('TBM 세션 생성 오류:', err); + return res.status(500).json({ + success: false, + message: 'TBM 세션 생성 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.status(201).json({ + success: true, + message: 'TBM 세션이 생성되었습니다.', + data: { + session_id: result.insertId, + ...sessionData + } + }); + }); + }, + + /** + * 특정 날짜의 TBM 세션 목록 조회 + */ + getSessionsByDate: (req, res) => { + const { date } = req.params; + + if (!date) { + return res.status(400).json({ + success: false, + message: '날짜 정보가 필요합니다.' + }); + } + + TbmModel.getSessionsByDate(date, (err, results) => { + if (err) { + console.error('TBM 세션 조회 오류:', err); + return res.status(500).json({ + success: false, + message: 'TBM 세션 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + /** + * TBM 세션 상세 조회 + */ + getSessionById: (req, res) => { + const { sessionId } = req.params; + + TbmModel.getSessionById(sessionId, (err, results) => { + if (err) { + console.error('TBM 세션 상세 조회 오류:', err); + return res.status(500).json({ + success: false, + message: 'TBM 세션 상세 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (results.length === 0) { + return res.status(404).json({ + success: false, + message: 'TBM 세션을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + data: results[0] + }); + }); + }, + + /** + * TBM 세션 수정 + */ + updateSession: (req, res) => { + const { sessionId } = req.params; + const sessionData = { + project_id: req.body.project_id, + work_location: req.body.work_location, + work_description: req.body.work_description, + safety_notes: req.body.safety_notes, + status: req.body.status || 'draft' + }; + + TbmModel.updateSession(sessionId, sessionData, (err, result) => { + if (err) { + console.error('TBM 세션 수정 오류:', err); + return res.status(500).json({ + success: false, + message: 'TBM 세션 수정 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: 'TBM 세션을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: 'TBM 세션이 수정되었습니다.' + }); + }); + }, + + /** + * TBM 세션 완료 처리 + */ + completeSession: (req, res) => { + const { sessionId } = req.params; + const endTime = req.body.end_time || new Date().toTimeString().slice(0, 8); + + TbmModel.completeSession(sessionId, endTime, (err, result) => { + if (err) { + console.error('TBM 세션 완료 처리 오류:', err); + return res.status(500).json({ + success: false, + message: 'TBM 세션 완료 처리 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: 'TBM 세션을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: 'TBM 세션이 완료되었습니다.' + }); + }); + }, + + // ==================== 팀 구성 관련 ==================== + + /** + * 팀원 추가 (작업자별 상세 정보 포함) + */ + addTeamMember: (req, res) => { + const assignmentData = { + session_id: req.params.sessionId, + worker_id: req.body.worker_id, + assigned_role: req.body.assigned_role || null, + work_detail: req.body.work_detail || null, + is_present: req.body.is_present, + absence_reason: req.body.absence_reason || null, + project_id: req.body.project_id || null, + work_type_id: req.body.work_type_id || null, + task_id: req.body.task_id || null, + workplace_category_id: req.body.workplace_category_id || null, + workplace_id: req.body.workplace_id || null + }; + + if (!assignmentData.worker_id) { + return res.status(400).json({ + success: false, + message: '작업자 ID가 필요합니다.' + }); + } + + TbmModel.addTeamMember(assignmentData, (err, result) => { + if (err) { + console.error('팀원 추가 오류:', err); + return res.status(500).json({ + success: false, + message: '팀원 추가 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + message: '팀원이 추가되었습니다.' + }); + }); + }, + + /** + * 팀 구성 일괄 추가 + */ + addTeamMembers: (req, res) => { + const { sessionId } = req.params; + const { members } = req.body; + + if (!Array.isArray(members) || members.length === 0) { + return res.status(400).json({ + success: false, + message: '팀원 목록이 필요합니다.' + }); + } + + TbmModel.addTeamMembers(sessionId, members, (err, result) => { + if (err) { + console.error('팀 구성 일괄 추가 오류:', err); + return res.status(500).json({ + success: false, + message: '팀 구성 추가 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + message: `${members.length}명의 팀원이 추가되었습니다.`, + data: { count: members.length } + }); + }); + }, + + /** + * TBM 세션의 팀 구성 조회 + */ + getTeamMembers: (req, res) => { + const { sessionId } = req.params; + + TbmModel.getTeamMembers(sessionId, (err, results) => { + if (err) { + console.error('팀 구성 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '팀 구성 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + /** + * 팀원 제거 + */ + removeTeamMember: (req, res) => { + const { sessionId, workerId } = req.params; + + TbmModel.removeTeamMember(sessionId, workerId, (err, result) => { + if (err) { + console.error('팀원 제거 오류:', err); + return res.status(500).json({ + success: false, + message: '팀원 제거 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '팀원을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '팀원이 제거되었습니다.' + }); + }); + }, + + /** + * 세션의 모든 팀원 삭제 (수정 시 사용) + */ + clearAllTeamMembers: (req, res) => { + const { sessionId } = req.params; + + TbmModel.clearAllTeamMembers(sessionId, (err, result) => { + if (err) { + console.error('팀원 전체 삭제 오류:', err); + return res.status(500).json({ + success: false, + message: '팀원 전체 삭제 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + message: '모든 팀원이 삭제되었습니다.', + data: { deletedCount: result.affectedRows } + }); + }); + }, + + // ==================== 안전 체크리스트 관련 ==================== + + /** + * 모든 안전 체크 항목 조회 + */ + getAllSafetyChecks: (req, res) => { + TbmModel.getAllSafetyChecks((err, results) => { + if (err) { + console.error('안전 체크 항목 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '안전 체크 항목 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + /** + * TBM 세션의 안전 체크 기록 조회 + */ + getSafetyRecords: (req, res) => { + const { sessionId } = req.params; + + TbmModel.getSafetyRecords(sessionId, (err, results) => { + if (err) { + console.error('안전 체크 기록 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '안전 체크 기록 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + /** + * 안전 체크 일괄 저장 + */ + saveSafetyRecords: (req, res) => { + const { sessionId } = req.params; + const { records } = req.body; + + if (!Array.isArray(records) || records.length === 0) { + return res.status(400).json({ + success: false, + message: '안전 체크 기록이 필요합니다.' + }); + } + + const checkedBy = req.user.user_id; + + TbmModel.saveSafetyRecords(sessionId, records, checkedBy, (err, result) => { + if (err) { + console.error('안전 체크 저장 오류:', err); + return res.status(500).json({ + success: false, + message: '안전 체크 저장 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + message: '안전 체크가 저장되었습니다.', + data: { count: records.length } + }); + }); + }, + + // ==================== 필터링된 안전 체크리스트 (확장) ==================== + + /** + * 세션에 맞는 필터링된 안전 체크 항목 조회 + * 기본 + 날씨 + 작업별 체크항목 통합 + */ + getFilteredSafetyChecks: async (req, res) => { + const { sessionId } = req.params; + + try { + // 날씨 정보 확인 (이미 저장된 경우 사용, 없으면 새로 조회) + const weatherService = require('../services/weatherService'); + let weatherRecord = await weatherService.getWeatherRecord(sessionId); + let weatherConditions = []; + + if (weatherRecord && weatherRecord.weather_conditions) { + weatherConditions = weatherRecord.weather_conditions; + } else { + // 날씨 정보가 없으면 현재 날씨 조회 + const currentWeather = await weatherService.getCurrentWeather(); + weatherConditions = await weatherService.determineWeatherConditions(currentWeather); + // 날씨 기록 저장 + await weatherService.saveWeatherRecord(sessionId, currentWeather, weatherConditions); + } + + TbmModel.getFilteredSafetyChecks(sessionId, weatherConditions, (err, results) => { + if (err) { + console.error('필터링된 안전 체크 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '안전 체크리스트 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('필터링된 안전 체크 조회 오류:', error); + res.status(500).json({ + success: false, + message: '안전 체크리스트 조회 중 오류가 발생했습니다.', + error: error.message + }); + } + }, + + /** + * 현재 날씨 조회 + */ + getCurrentWeather: async (req, res) => { + try { + const weatherService = require('../services/weatherService'); + const { nx, ny } = req.query; + + const weatherData = await weatherService.getCurrentWeather(nx, ny); + const conditions = await weatherService.determineWeatherConditions(weatherData); + const conditionList = await weatherService.getWeatherConditionList(); + + // 현재 조건의 상세 정보 매핑 + const activeConditions = conditionList.filter(c => conditions.includes(c.condition_code)); + + res.json({ + success: true, + data: { + ...weatherData, + conditions, + conditionDetails: activeConditions + } + }); + } catch (error) { + console.error('날씨 조회 오류:', error); + res.status(500).json({ + success: false, + message: '날씨 조회 중 오류가 발생했습니다.', + error: error.message + }); + } + }, + + /** + * 세션 날씨 정보 저장 + */ + saveSessionWeather: async (req, res) => { + const { sessionId } = req.params; + const { weatherConditions } = req.body; + + try { + const weatherService = require('../services/weatherService'); + + // 현재 날씨 조회 + const weatherData = await weatherService.getCurrentWeather(); + const conditions = weatherConditions || await weatherService.determineWeatherConditions(weatherData); + + // 저장 + await weatherService.saveWeatherRecord(sessionId, weatherData, conditions); + + res.json({ + success: true, + message: '날씨 정보가 저장되었습니다.', + data: { conditions } + }); + } catch (error) { + console.error('날씨 저장 오류:', error); + res.status(500).json({ + success: false, + message: '날씨 저장 중 오류가 발생했습니다.', + error: error.message + }); + } + }, + + /** + * 세션 날씨 정보 조회 + */ + getSessionWeather: async (req, res) => { + const { sessionId } = req.params; + + try { + const weatherService = require('../services/weatherService'); + const weatherRecord = await weatherService.getWeatherRecord(sessionId); + + if (!weatherRecord) { + return res.status(404).json({ + success: false, + message: '날씨 기록이 없습니다.' + }); + } + + res.json({ + success: true, + data: weatherRecord + }); + } catch (error) { + console.error('날씨 조회 오류:', error); + res.status(500).json({ + success: false, + message: '날씨 조회 중 오류가 발생했습니다.', + error: error.message + }); + } + }, + + /** + * 날씨 조건 목록 조회 + */ + getWeatherConditions: async (req, res) => { + try { + const weatherService = require('../services/weatherService'); + const conditions = await weatherService.getWeatherConditionList(); + + res.json({ + success: true, + data: conditions + }); + } catch (error) { + console.error('날씨 조건 조회 오류:', error); + res.status(500).json({ + success: false, + message: '날씨 조건 조회 중 오류가 발생했습니다.', + error: error.message + }); + } + }, + + // ==================== 안전 체크항목 관리 (관리자용) ==================== + + /** + * 안전 체크 항목 생성 + */ + createSafetyCheck: (req, res) => { + const checkData = req.body; + + if (!checkData.check_category || !checkData.check_item) { + return res.status(400).json({ + success: false, + message: '카테고리와 체크 항목은 필수입니다.' + }); + } + + TbmModel.createSafetyCheck(checkData, (err, result) => { + if (err) { + console.error('안전 체크 항목 생성 오류:', err); + return res.status(500).json({ + success: false, + message: '안전 체크 항목 생성 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.status(201).json({ + success: true, + message: '안전 체크 항목이 생성되었습니다.', + data: { check_id: result.insertId } + }); + }); + }, + + /** + * 안전 체크 항목 수정 + */ + updateSafetyCheck: (req, res) => { + const { checkId } = req.params; + const checkData = req.body; + + TbmModel.updateSafetyCheck(checkId, checkData, (err, result) => { + if (err) { + console.error('안전 체크 항목 수정 오류:', err); + return res.status(500).json({ + success: false, + message: '안전 체크 항목 수정 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '안전 체크 항목을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '안전 체크 항목이 수정되었습니다.' + }); + }); + }, + + /** + * 안전 체크 항목 삭제 (비활성화) + */ + deleteSafetyCheck: (req, res) => { + const { checkId } = req.params; + + TbmModel.deleteSafetyCheck(checkId, (err, result) => { + if (err) { + console.error('안전 체크 항목 삭제 오류:', err); + return res.status(500).json({ + success: false, + message: '안전 체크 항목 삭제 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '안전 체크 항목을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '안전 체크 항목이 삭제되었습니다.' + }); + }); + }, + + // ==================== 작업 인계 관련 ==================== + + /** + * 작업 인계 생성 + */ + createHandover: (req, res) => { + const handoverData = { + session_id: req.body.session_id, + from_leader_id: req.body.from_leader_id, + to_leader_id: req.body.to_leader_id, + handover_date: req.body.handover_date, + handover_time: req.body.handover_time || null, + reason: req.body.reason, + handover_notes: req.body.handover_notes || null, + worker_ids: req.body.worker_ids || [] + }; + + // 필수 필드 검증 + if (!handoverData.session_id || !handoverData.from_leader_id || + !handoverData.to_leader_id || !handoverData.handover_date || !handoverData.reason) { + return res.status(400).json({ + success: false, + message: '필수 정보가 누락되었습니다.' + }); + } + + TbmModel.createHandover(handoverData, (err, result) => { + if (err) { + console.error('작업 인계 생성 오류:', err); + return res.status(500).json({ + success: false, + message: '작업 인계 생성 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.status(201).json({ + success: true, + message: '작업 인계가 생성되었습니다.', + data: { handover_id: result.insertId } + }); + }); + }, + + /** + * 작업 인계 확인 + */ + confirmHandover: (req, res) => { + const { handoverId } = req.params; + const confirmedBy = req.user.user_id; + + TbmModel.confirmHandover(handoverId, confirmedBy, (err, result) => { + if (err) { + console.error('작업 인계 확인 오류:', err); + return res.status(500).json({ + success: false, + message: '작업 인계 확인 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '작업 인계 건을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '작업 인계가 확인되었습니다.' + }); + }); + }, + + /** + * 특정 날짜의 작업 인계 목록 조회 + */ + getHandoversByDate: (req, res) => { + const { date } = req.params; + + TbmModel.getHandoversByDate(date, (err, results) => { + if (err) { + console.error('작업 인계 목록 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '작업 인계 목록 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + /** + * 나에게 온 미확인 인계 건 조회 + */ + getMyPendingHandovers: (req, res) => { + // worker_id는 req.user에서 가져옴 + const toLeaderId = req.user.worker_id; + + if (!toLeaderId) { + return res.status(400).json({ + success: false, + message: '작업자 정보를 찾을 수 없습니다.' + }); + } + + TbmModel.getPendingHandovers(toLeaderId, (err, results) => { + if (err) { + console.error('미확인 인계 건 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '미확인 인계 건 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + // ==================== 통계 및 리포트 ==================== + + /** + * TBM 통계 조회 + */ + getTbmStatistics: (req, res) => { + const { startDate, endDate } = req.query; + + if (!startDate || !endDate) { + return res.status(400).json({ + success: false, + message: '시작일과 종료일이 필요합니다.' + }); + } + + TbmModel.getTbmStatistics(startDate, endDate, (err, results) => { + if (err) { + console.error('TBM 통계 조회 오류:', err); + return res.status(500).json({ + success: false, + message: 'TBM 통계 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + /** + * 리더별 TBM 진행 현황 조회 + */ + getLeaderStatistics: (req, res) => { + const { startDate, endDate } = req.query; + + if (!startDate || !endDate) { + return res.status(400).json({ + success: false, + message: '시작일과 종료일이 필요합니다.' + }); + } + + TbmModel.getLeaderStatistics(startDate, endDate, (err, results) => { + if (err) { + console.error('리더 통계 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '리더 통계 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + }, + + /** + * 작업보고서가 작성되지 않은 TBM 팀 배정 조회 + */ + getIncompleteWorkReports: (req, res) => { + const userId = req.user.user_id; + const accessLevel = req.user.access_level; + + // 관리자는 모든 TBM 조회, 일반 사용자는 본인이 작성한 것만 조회 + const filterUserId = (accessLevel === 'system' || accessLevel === 'admin') ? null : userId; + + TbmModel.getIncompleteWorkReports(filterUserId, (err, results) => { + if (err) { + console.error('미완료 작업보고서 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '미완료 작업보고서 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: results + }); + }); + } +}; + +module.exports = TbmController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/toolsController.js b/deploy/tkfb-package/api.hyungi.net/controllers/toolsController.js new file mode 100644 index 0000000..3480886 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/toolsController.js @@ -0,0 +1,75 @@ +/** + * 도구 관리 컨트롤러 + * + * 도구(공구) 재고 및 위치 관리 API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const toolsService = require('../services/toolsService'); +const { asyncHandler } = require('../middlewares/errorHandler'); + +/** + * 전체 도구 조회 + */ +exports.getAll = asyncHandler(async (req, res) => { + const rows = await toolsService.getAllToolsService(); + + res.json({ + success: true, + data: rows, + message: '도구 목록 조회 성공' + }); +}); + +/** + * 단일 도구 조회 + */ +exports.getById = asyncHandler(async (req, res) => { + const id = parseInt(req.params.id, 10); + const row = await toolsService.getToolByIdService(id); + + res.json({ + success: true, + data: row, + message: '도구 조회 성공' + }); +}); + +/** + * 도구 생성 + */ +exports.create = asyncHandler(async (req, res) => { + const result = await toolsService.createToolService(req.body); + + res.status(201).json({ + success: true, + data: result, + message: '도구가 성공적으로 생성되었습니다' + }); +}); + +/** + * 도구 수정 + */ +exports.update = asyncHandler(async (req, res) => { + const id = parseInt(req.params.id, 10); + const result = await toolsService.updateToolService(id, req.body); + + res.json({ + success: true, + data: result, + message: '도구 정보가 성공적으로 수정되었습니다' + }); +}); + +/** + * 도구 삭제 + */ +exports.delete = asyncHandler(async (req, res) => { + const id = parseInt(req.params.id, 10); + await toolsService.deleteToolService(id); + + res.status(204).send(); +}); diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/uploadController.js b/deploy/tkfb-package/api.hyungi.net/controllers/uploadController.js new file mode 100644 index 0000000..8d2b75c --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/uploadController.js @@ -0,0 +1,38 @@ +/** + * 문서 업로드 관리 컨트롤러 + * + * 파일 업로드 및 문서 메타데이터 CRUD API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const uploadService = require('../services/uploadService'); +const { asyncHandler } = require('../middlewares/errorHandler'); + +/** + * 문서 업로드 + */ +exports.createUpload = asyncHandler(async (req, res) => { + const doc = req.body; + const result = await uploadService.createUploadService(doc); + + res.status(201).json({ + success: true, + data: result, + message: '문서가 성공적으로 업로드되었습니다' + }); +}); + +/** + * 전체 업로드 문서 조회 + */ +exports.getUploads = asyncHandler(async (req, res) => { + const rows = await uploadService.getAllUploadsService(); + + res.json({ + success: true, + data: rows, + message: '업로드 문서 목록 조회 성공' + }); +}); diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/userController.js b/deploy/tkfb-package/api.hyungi.net/controllers/userController.js new file mode 100644 index 0000000..3873f90 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/userController.js @@ -0,0 +1,739 @@ +/** + * 사용자 관리 컨트롤러 + * + * 사용자 CRUD 및 상태 관리 기능을 제공하는 컨트롤러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const bcrypt = require('bcrypt'); +const { ValidationError, ForbiddenError, NotFoundError, ConflictError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); + +/** + * 관리자 권한 확인 헬퍼 함수 + */ +const checkAdminPermission = (user) => { + if (!user || !['admin', 'system'].includes(user.access_level)) { + throw new ForbiddenError('관리자 권한이 필요합니다'); + } +}; + +/** + * 모든 사용자 조회 + */ +const getAllUsers = asyncHandler(async (req, res) => { + checkAdminPermission(req.user); + + logger.info('사용자 목록 조회 요청', { requestedBy: req.user?.username }); + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + const query = ` + SELECT + u.user_id, + u.username, + u.name, + u.email, + u.role_id, + r.name as role, + u._access_level_old as access_level, + u.is_active, + u.worker_id, + w.worker_name, + w.department_id, + d.department_name, + u.created_at, + u.updated_at, + u.last_login_at as last_login + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + LEFT JOIN workers w ON u.worker_id = w.worker_id + LEFT JOIN departments d ON w.department_id = d.department_id + ORDER BY u.created_at DESC + `; + + const [users] = await db.execute(query); + + logger.info('사용자 목록 조회 성공', { count: users.length }); + + res.json({ + success: true, + data: users, + message: '사용자 목록 조회 성공' + }); + } catch (error) { + logger.error('사용자 목록 조회 실패', { error: error.message }); + throw new DatabaseError('사용자 목록을 조회하는데 실패했습니다'); + } +}); + +/** + * 특정 사용자 조회 + */ +const getUserById = asyncHandler(async (req, res) => { + const { id } = req.params; + + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 사용자 ID입니다'); + } + + logger.info('사용자 조회 요청', { userId: id }); + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + const query = ` + SELECT + user_id, + username, + name, + email, + phone, + role, + access_level, + is_active, + created_at, + updated_at, + last_login + FROM users + WHERE user_id = ? + `; + + const [users] = await db.execute(query, [id]); + + if (users.length === 0) { + throw new NotFoundError('사용자를 찾을 수 없습니다'); + } + + logger.info('사용자 조회 성공', { userId: id, username: users[0].username }); + + res.json({ + success: true, + data: users[0], + message: '사용자 조회 성공' + }); + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + logger.error('사용자 조회 실패', { userId: id, error: error.message }); + throw new DatabaseError('사용자를 조회하는데 실패했습니다'); + } +}); + +/** + * 새 사용자 생성 + */ +const createUser = asyncHandler(async (req, res) => { + checkAdminPermission(req.user); + + const { username, name, email, phone, role, password } = req.body; + + logger.info('사용자 생성 요청', { username, name, role }); + + // 필수 필드 검증 + if (!username || !name || !role || !password) { + throw new ValidationError('필수 필드가 누락되었습니다', { + required: ['username', 'name', 'role', 'password'], + received: { username, name, role, password: '***' } + }); + } + + // 사용자명 유효성 검증 + if (username.length < 3 || username.length > 20) { + throw new ValidationError('사용자명은 3-20자 사이여야 합니다'); + } + + // 비밀번호 유효성 검증 + if (password.length < 6) { + throw new ValidationError('비밀번호는 최소 6자 이상이어야 합니다'); + } + + // 권한 레벨 검증 + const validRoles = ['admin', 'group_leader', 'worker']; + if (!validRoles.includes(role)) { + throw new ValidationError('유효하지 않은 권한입니다', { + valid: validRoles, + received: role + }); + } + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + // 사용자명 중복 확인 + const checkQuery = 'SELECT user_id FROM users WHERE username = ?'; + const [existing] = await db.execute(checkQuery, [username]); + + if (existing.length > 0) { + throw new ConflictError('이미 존재하는 사용자명입니다'); + } + + // 비밀번호 해시화 + const hashedPassword = await bcrypt.hash(password, 10); + + // 사용자 생성 + const insertQuery = ` + INSERT INTO users (username, name, email, phone, role, access_level, password_hash, is_active, created_at) + VALUES (?, ?, ?, ?, ?, ?, ?, 1, NOW()) + `; + + const [result] = await db.execute(insertQuery, [ + username, + name, + email || null, + phone || null, + role, + role, // access_level을 role과 동일하게 설정 + hashedPassword + ]); + + logger.info('사용자 생성 성공', { + userId: result.insertId, + username, + name, + role, + createdBy: req.user.username + }); + + res.status(201).json({ + success: true, + data: { user_id: result.insertId }, + message: '사용자가 성공적으로 생성되었습니다' + }); + } catch (error) { + if (error instanceof ConflictError) { + throw error; + } + logger.error('사용자 생성 실패', { username, error: error.message }); + throw new DatabaseError('사용자를 생성하는데 실패했습니다'); + } +}); + +/** + * 사용자 정보 수정 + */ +const updateUser = asyncHandler(async (req, res) => { + checkAdminPermission(req.user); + + const { id } = req.params; + const { username, name, email, role, role_id, password, worker_id } = req.body; + + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 사용자 ID입니다'); + } + + logger.info('사용자 수정 요청', { userId: id, body: req.body }); + + // 최소 하나의 수정 필드가 필요 + if (!username && !name && email === undefined && !role && !role_id && !password && worker_id === undefined) { + throw new ValidationError('수정할 필드가 없습니다'); + } + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + // 사용자 존재 확인 + const checkQuery = 'SELECT user_id, username, is_active FROM users WHERE user_id = ?'; + const [existing] = await db.execute(checkQuery, [id]); + + if (existing.length === 0) { + throw new NotFoundError('사용자를 찾을 수 없습니다'); + } + + if (existing[0].is_active === 0) { + throw new ValidationError('비활성화된 사용자는 수정할 수 없습니다'); + } + + // 업데이트할 필드들 + const updates = []; + const values = []; + + if (username) { + if (username.length < 3 || username.length > 20) { + throw new ValidationError('사용자명은 3-20자 사이여야 합니다'); + } + + // 사용자명 중복 확인 (자신 제외) + const dupQuery = 'SELECT user_id FROM users WHERE username = ? AND user_id != ?'; + const [duplicate] = await db.execute(dupQuery, [username, id]); + + if (duplicate.length > 0) { + throw new ConflictError('이미 존재하는 사용자명입니다'); + } + + updates.push('username = ?'); + values.push(username); + } + + if (name) { + updates.push('name = ?'); + values.push(name); + } + + if (email !== undefined) { + updates.push('email = ?'); + values.push(email || null); + } + + // role_id 또는 role 문자열 처리 + if (role_id) { + // role_id가 유효한지 확인 + const [roleCheck] = await db.execute('SELECT id, name FROM roles WHERE id = ?', [role_id]); + if (roleCheck.length === 0) { + throw new ValidationError('유효하지 않은 역할 ID입니다'); + } + updates.push('role_id = ?'); + values.push(role_id); + logger.info('role_id로 역할 변경', { userId: id, role_id, role_name: roleCheck[0].name }); + } else if (role) { + // role 문자열을 role_id로 변환 (하위 호환성) + const roleNameMap = { + 'admin': 'Admin', + 'system': 'System Admin', + 'user': 'User', + 'guest': 'Guest', + 'group_leader': 'User', // 임시 매핑 + 'worker': 'User' // 임시 매핑 + }; + const roleName = roleNameMap[role.toLowerCase()] || role; + const [roleCheck] = await db.execute('SELECT id FROM roles WHERE name = ?', [roleName]); + + if (roleCheck.length === 0) { + throw new ValidationError(`유효하지 않은 권한입니다: ${role}`); + } + updates.push('role_id = ?'); + values.push(roleCheck[0].id); + logger.info('role 문자열로 역할 변경', { userId: id, role, role_id: roleCheck[0].id }); + } + + if (password) { + if (password.length < 6) { + throw new ValidationError('비밀번호는 최소 6자 이상이어야 합니다'); + } + const hashedPassword = await bcrypt.hash(password, 10); + updates.push('password = ?'); + values.push(hashedPassword); + } + + // worker_id 업데이트 (null도 허용 - 연결 해제) + if (worker_id !== undefined) { + if (worker_id !== null) { + // worker_id가 유효한지 확인 + const [workerCheck] = await db.execute('SELECT worker_id, worker_name FROM workers WHERE worker_id = ?', [worker_id]); + if (workerCheck.length === 0) { + throw new ValidationError('유효하지 않은 작업자 ID입니다'); + } + logger.info('작업자 연결', { userId: id, worker_id, worker_name: workerCheck[0].worker_name }); + } else { + logger.info('작업자 연결 해제', { userId: id }); + } + updates.push('worker_id = ?'); + values.push(worker_id); + } + + updates.push('updated_at = NOW()'); + values.push(id); + + const updateQuery = `UPDATE users SET ${updates.join(', ')} WHERE user_id = ?`; + + logger.info('실행할 UPDATE 쿼리', { query: updateQuery, values }); + await db.execute(updateQuery, values); + + logger.info('사용자 수정 성공', { + userId: id, + username: existing[0].username, + updatedFields: Object.keys(req.body), + updatedBy: req.user.username + }); + + res.json({ + success: true, + data: { user_id: id }, + message: '사용자 정보가 성공적으로 수정되었습니다' + }); + } catch (error) { + if (error instanceof NotFoundError || error instanceof ValidationError || error instanceof ConflictError) { + throw error; + } + logger.error('사용자 수정 실패', { userId: id, error: error.message, stack: error.stack }); + throw new DatabaseError('사용자 정보를 수정하는데 실패했습니다'); + } +}); + +/** + * 사용자 상태 변경 (활성화/비활성화) + */ +const updateUserStatus = asyncHandler(async (req, res) => { + checkAdminPermission(req.user); + + const { id } = req.params; + const { is_active } = req.body; + + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 사용자 ID입니다'); + } + + if (is_active === undefined || ![0, 1, true, false].includes(is_active)) { + throw new ValidationError('유효하지 않은 활성 상태 값입니다'); + } + + const activeValue = is_active === true || is_active === 1 ? 1 : 0; + + // 자기 자신 비활성화 방지 + if (parseInt(id) === req.user.user_id && activeValue === 0) { + throw new ValidationError('자기 자신을 비활성화할 수 없습니다'); + } + + logger.info('사용자 상태 변경 요청', { userId: id, is_active: activeValue }); + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + // 사용자 존재 확인 + const checkQuery = 'SELECT user_id, username, is_active FROM users WHERE user_id = ?'; + const [users] = await db.execute(checkQuery, [id]); + + if (users.length === 0) { + throw new NotFoundError('사용자를 찾을 수 없습니다'); + } + + // 상태 변경이 필요한지 확인 + if (users[0].is_active === activeValue) { + const status = activeValue === 1 ? '활성' : '비활성'; + throw new ValidationError(`사용자가 이미 ${status} 상태입니다`); + } + + const query = 'UPDATE users SET is_active = ?, updated_at = NOW() WHERE user_id = ?'; + await db.execute(query, [activeValue, id]); + + const statusText = activeValue === 1 ? '활성화' : '비활성화'; + + logger.info(`사용자 ${statusText} 성공`, { + userId: id, + username: users[0].username, + newStatus: activeValue, + updatedBy: req.user.username + }); + + res.json({ + success: true, + data: { user_id: id, is_active: activeValue }, + message: `사용자가 성공적으로 ${statusText}되었습니다` + }); + } catch (error) { + if (error instanceof NotFoundError || error instanceof ValidationError) { + throw error; + } + logger.error('사용자 상태 변경 실패', { userId: id, error: error.message }); + throw new DatabaseError('사용자 상태를 변경하는데 실패했습니다'); + } +}); + +/** + * 사용자 삭제 (Soft Delete) + */ +const deleteUser = asyncHandler(async (req, res) => { + checkAdminPermission(req.user); + + const { id } = req.params; + + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 사용자 ID입니다'); + } + + // 자기 자신 삭제 방지 + if (req.user && req.user.user_id == id) { + throw new ValidationError('자기 자신은 삭제할 수 없습니다'); + } + + logger.info('사용자 삭제 요청', { userId: id }); + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + // 사용자 존재 확인 + const checkQuery = 'SELECT user_id, username, is_active FROM users WHERE user_id = ?'; + const [users] = await db.execute(checkQuery, [id]); + + if (users.length === 0) { + throw new NotFoundError('사용자를 찾을 수 없습니다'); + } + + if (users[0].is_active === 0) { + throw new ValidationError('이미 비활성화된 사용자입니다'); + } + + // Soft Delete (is_active = 0) + const query = 'UPDATE users SET is_active = 0, updated_at = NOW() WHERE user_id = ?'; + await db.execute(query, [id]); + + logger.info('사용자 비활성화 성공', { + userId: id, + username: users[0].username, + deletedBy: req.user.username + }); + + res.json({ + success: true, + data: { user_id: id }, + message: '사용자가 성공적으로 비활성화되었습니다' + }); + } catch (error) { + if (error instanceof NotFoundError || error instanceof ValidationError) { + throw error; + } + logger.error('사용자 비활성화 실패', { userId: id, error: error.message }); + throw new DatabaseError('사용자를 비활성화하는데 실패했습니다'); + } +}); + +/** + * 사용자 영구 삭제 (Hard Delete) + */ +const permanentDeleteUser = asyncHandler(async (req, res) => { + checkAdminPermission(req.user); + + const { id } = req.params; + + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 사용자 ID입니다'); + } + + // 자기 자신 삭제 방지 + if (req.user && req.user.user_id == id) { + throw new ValidationError('자기 자신은 삭제할 수 없습니다'); + } + + logger.info('사용자 영구 삭제 요청', { userId: id }); + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + // 사용자 존재 확인 + const checkQuery = 'SELECT user_id, username FROM users WHERE user_id = ?'; + const [users] = await db.execute(checkQuery, [id]); + + if (users.length === 0) { + throw new NotFoundError('사용자를 찾을 수 없습니다'); + } + + const username = users[0].username; + + // 관련 데이터 삭제 (외래 키 제약 조건 때문에 순서 중요) + // 1. 로그인 로그 삭제 + await db.execute('DELETE FROM login_logs WHERE user_id = ?', [id]); + + // 2. 페이지 접근 권한 삭제 + await db.execute('DELETE FROM user_page_access WHERE user_id = ?', [id]); + + // 3. 사용자 삭제 + await db.execute('DELETE FROM users WHERE user_id = ?', [id]); + + logger.info('사용자 영구 삭제 성공', { + userId: id, + username: username, + deletedBy: req.user.username + }); + + res.json({ + success: true, + data: { user_id: id }, + message: `사용자 "${username}"이(가) 영구적으로 삭제되었습니다` + }); + } catch (error) { + if (error instanceof NotFoundError || error instanceof ValidationError) { + throw error; + } + logger.error('사용자 영구 삭제 실패', { userId: id, error: error.message }); + throw new DatabaseError('사용자를 영구 삭제하는데 실패했습니다'); + } +}); + +/** + * 사용자의 페이지 접근 권한 조회 + */ +const getUserPageAccess = asyncHandler(async (req, res) => { + const { id } = req.params; + + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 사용자 ID입니다'); + } + + logger.info('사용자 페이지 권한 조회 요청', { userId: id }); + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + // 권한 조회: user_page_access에 명시적 권한이 있으면 사용, 없으면 is_default_accessible 사용 + const query = ` + SELECT + p.id as page_id, + p.page_key, + p.page_name, + p.page_path, + p.category, + p.is_default_accessible, + COALESCE(upa.can_access, p.is_default_accessible) as can_access + FROM pages p + LEFT JOIN user_page_access upa ON p.id = upa.page_id AND upa.user_id = ? + ORDER BY p.category, p.display_order + `; + + const [pageAccess] = await db.execute(query, [id]); + + logger.info('사용자 페이지 권한 조회 성공', { userId: id, pageCount: pageAccess.length }); + + res.json({ + success: true, + data: { + pageAccess + }, + message: '페이지 권한 조회 성공' + }); + } catch (error) { + logger.error('사용자 페이지 권한 조회 실패', { userId: id, error: error.message }); + throw new DatabaseError('페이지 권한을 조회하는데 실패했습니다'); + } +}); + +/** + * 사용자의 페이지 접근 권한 업데이트 + */ +const updateUserPageAccess = asyncHandler(async (req, res) => { + checkAdminPermission(req.user); + + const { id } = req.params; + const { pageAccess } = req.body; + + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 사용자 ID입니다'); + } + + if (!Array.isArray(pageAccess)) { + throw new ValidationError('pageAccess는 배열이어야 합니다'); + } + + logger.info('사용자 페이지 권한 업데이트 요청', { + userId: id, + pageCount: pageAccess.length, + updatedBy: req.user.username + }); + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + // 트랜잭션 시작 + await db.query('START TRANSACTION'); + + // 기존 권한 삭제 + await db.execute('DELETE FROM user_page_access WHERE user_id = ?', [id]); + + // 새 권한 삽입 + if (pageAccess.length > 0) { + const values = pageAccess.map(p => [id, p.page_id, p.can_access]); + const placeholders = values.map(() => '(?, ?, ?)').join(', '); + const flatValues = values.flat(); + + await db.execute( + `INSERT INTO user_page_access (user_id, page_id, can_access) VALUES ${placeholders}`, + flatValues + ); + } + + // 커밋 + await db.query('COMMIT'); + + logger.info('사용자 페이지 권한 업데이트 성공', { + userId: id, + pageCount: pageAccess.length, + updatedBy: req.user.username + }); + + res.json({ + success: true, + data: { user_id: id }, + message: '페이지 권한이 성공적으로 업데이트되었습니다' + }); + } catch (error) { + // 롤백 + await db.query('ROLLBACK'); + logger.error('사용자 페이지 권한 업데이트 실패', { userId: id, error: error.message }); + throw new DatabaseError('페이지 권한을 업데이트하는데 실패했습니다'); + } +}); + +/** + * 사용자 비밀번호 초기화 (000000) + */ +const resetUserPassword = asyncHandler(async (req, res) => { + checkAdminPermission(req.user); + + const { id } = req.params; + + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 사용자 ID입니다'); + } + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + try { + // 사용자 존재 확인 + const [existing] = await db.execute('SELECT user_id, username FROM users WHERE user_id = ?', [id]); + + if (existing.length === 0) { + throw new NotFoundError('사용자를 찾을 수 없습니다'); + } + + // 비밀번호를 000000으로 초기화 + const hashedPassword = await bcrypt.hash('000000', 10); + await db.execute( + 'UPDATE users SET password = ?, password_changed_at = NULL, updated_at = NOW() WHERE user_id = ?', + [hashedPassword, id] + ); + + logger.info('사용자 비밀번호 초기화 성공', { + userId: id, + username: existing[0].username, + resetBy: req.user.username + }); + + res.json({ + success: true, + message: '비밀번호가 000000으로 초기화되었습니다' + }); + } catch (error) { + if (error instanceof NotFoundError || error instanceof ValidationError) { + throw error; + } + logger.error('비밀번호 초기화 실패', { userId: id, error: error.message }); + throw new DatabaseError('비밀번호 초기화에 실패했습니다'); + } +}); + +module.exports = { + getAllUsers, + getUserById, + createUser, + updateUser, + updateUserStatus, + deleteUser, + permanentDeleteUser, + getUserPageAccess, + updateUserPageAccess, + resetUserPassword +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/vacationBalanceController.js b/deploy/tkfb-package/api.hyungi.net/controllers/vacationBalanceController.js new file mode 100644 index 0000000..4eeaa3a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/vacationBalanceController.js @@ -0,0 +1,421 @@ +/** + * vacationBalanceController.js + * 휴가 잔액 관련 컨트롤러 + */ + +const vacationBalanceModel = require('../models/vacationBalanceModel'); +const vacationTypeModel = require('../models/vacationTypeModel'); + +const vacationBalanceController = { + /** + * 특정 작업자의 휴가 잔액 조회 (특정 연도) + * GET /api/vacation-balances/worker/:workerId/year/:year + */ + async getByWorkerAndYear(req, res) { + try { + const { workerId, year } = req.params; + + vacationBalanceModel.getByWorkerAndYear(workerId, year, (err, results) => { + if (err) { + console.error('휴가 잔액 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 잔액을 조회하는 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('getByWorkerAndYear 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 모든 작업자의 휴가 잔액 조회 (특정 연도) + * GET /api/vacation-balances/year/:year + */ + async getAllByYear(req, res) { + try { + const { year } = req.params; + + vacationBalanceModel.getAllByYear(year, (err, results) => { + if (err) { + console.error('전체 휴가 잔액 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '전체 휴가 잔액을 조회하는 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('getAllByYear 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 잔액 생성 + * POST /api/vacation-balances + */ + async createBalance(req, res) { + try { + const { + worker_id, + vacation_type_id, + year, + total_days, + used_days, + notes + } = req.body; + const created_by = req.user.user_id; + + // 필수 필드 검증 + if (!worker_id || !vacation_type_id || !year || total_days === undefined) { + return res.status(400).json({ + success: false, + message: '필수 필드가 누락되었습니다 (worker_id, vacation_type_id, year, total_days)' + }); + } + + // 중복 체크 + vacationBalanceModel.getByWorkerTypeYear(worker_id, vacation_type_id, year, (err, existing) => { + if (err) { + console.error('중복 체크 오류:', err); + return res.status(500).json({ + success: false, + message: '중복 체크 중 오류가 발생했습니다' + }); + } + + if (existing && existing.length > 0) { + return res.status(400).json({ + success: false, + message: '이미 해당 작업자의 해당 연도 휴가 잔액이 존재합니다' + }); + } + + const balanceData = { + worker_id, + vacation_type_id, + year, + total_days, + used_days: used_days || 0, + notes: notes || null, + created_by + }; + + vacationBalanceModel.create(balanceData, (err, result) => { + if (err) { + console.error('휴가 잔액 생성 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 잔액을 생성하는 중 오류가 발생했습니다' + }); + } + + res.status(201).json({ + success: true, + message: '휴가 잔액이 생성되었습니다', + data: { id: result.insertId } + }); + }); + }); + } catch (error) { + console.error('createBalance 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 잔액 수정 + * PUT /api/vacation-balances/:id + */ + async updateBalance(req, res) { + try { + const { id } = req.params; + const { total_days, used_days, notes } = req.body; + + const updateData = {}; + if (total_days !== undefined) updateData.total_days = total_days; + if (used_days !== undefined) updateData.used_days = used_days; + if (notes !== undefined) updateData.notes = notes; + updateData.updated_at = new Date(); + + if (Object.keys(updateData).length === 1) { + return res.status(400).json({ + success: false, + message: '수정할 데이터가 없습니다' + }); + } + + vacationBalanceModel.update(id, updateData, (err, result) => { + if (err) { + console.error('휴가 잔액 수정 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 잔액을 수정하는 중 오류가 발생했습니다' + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '휴가 잔액을 찾을 수 없습니다' + }); + } + + res.json({ + success: true, + message: '휴가 잔액이 수정되었습니다' + }); + }); + } catch (error) { + console.error('updateBalance 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 잔액 삭제 + * DELETE /api/vacation-balances/:id + */ + async deleteBalance(req, res) { + try { + const { id } = req.params; + + vacationBalanceModel.delete(id, (err, result) => { + if (err) { + console.error('휴가 잔액 삭제 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 잔액을 삭제하는 중 오류가 발생했습니다' + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '휴가 잔액을 찾을 수 없습니다' + }); + } + + res.json({ + success: true, + message: '휴가 잔액이 삭제되었습니다' + }); + }); + } catch (error) { + console.error('deleteBalance 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 근속년수 기반 연차 자동 계산 및 생성 + * POST /api/vacation-balances/auto-calculate + */ + async autoCalculateAndCreate(req, res) { + try { + const { worker_id, hire_date, year } = req.body; + const created_by = req.user.user_id; + + if (!worker_id || !hire_date || !year) { + return res.status(400).json({ + success: false, + message: '필수 필드가 누락되었습니다 (worker_id, hire_date, year)' + }); + } + + // 연차 일수 계산 + const annualDays = vacationBalanceModel.calculateAnnualLeaveDays(hire_date, year); + + // ANNUAL 휴가 유형 ID 조회 + vacationTypeModel.getByCode('ANNUAL', (err, types) => { + if (err || !types || types.length === 0) { + console.error('ANNUAL 휴가 유형 조회 오류:', err); + return res.status(500).json({ + success: false, + message: 'ANNUAL 휴가 유형을 찾을 수 없습니다' + }); + } + + const annualTypeId = types[0].id; + + // 중복 체크 + vacationBalanceModel.getByWorkerTypeYear(worker_id, annualTypeId, year, (err, existing) => { + if (err) { + console.error('중복 체크 오류:', err); + return res.status(500).json({ + success: false, + message: '중복 체크 중 오류가 발생했습니다' + }); + } + + if (existing && existing.length > 0) { + return res.status(400).json({ + success: false, + message: '이미 해당 작업자의 해당 연도 연차가 존재합니다' + }); + } + + const balanceData = { + worker_id, + vacation_type_id: annualTypeId, + year, + total_days: annualDays, + used_days: 0, + notes: `근속년수 기반 자동 계산 (입사일: ${hire_date})`, + created_by + }; + + vacationBalanceModel.create(balanceData, (err, result) => { + if (err) { + console.error('휴가 잔액 생성 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 잔액을 생성하는 중 오류가 발생했습니다' + }); + } + + res.status(201).json({ + success: true, + message: `${annualDays}일의 연차가 자동으로 생성되었습니다`, + data: { + id: result.insertId, + calculated_days: annualDays + } + }); + }); + }); + }); + } catch (error) { + console.error('autoCalculateAndCreate 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 잔액 일괄 저장 (upsert) + * POST /api/vacation-balances/bulk-upsert + */ + async bulkUpsert(req, res) { + try { + const { balances } = req.body; + const created_by = req.user.user_id; + + if (!balances || !Array.isArray(balances) || balances.length === 0) { + return res.status(400).json({ + success: false, + message: '저장할 데이터가 없습니다' + }); + } + + const { getDb } = require('../dbPool'); + const db = await getDb(); + + let successCount = 0; + let errorCount = 0; + + for (const balance of balances) { + const { worker_id, vacation_type_id, year, total_days, notes } = balance; + + if (!worker_id || !vacation_type_id || !year || total_days === undefined) { + errorCount++; + continue; + } + + try { + // Upsert 쿼리 + const query = ` + INSERT INTO vacation_balance_details + (worker_id, vacation_type_id, year, total_days, used_days, notes, created_by) + VALUES (?, ?, ?, ?, 0, ?, ?) + ON DUPLICATE KEY UPDATE + total_days = VALUES(total_days), + notes = VALUES(notes), + updated_at = NOW() + `; + + await db.query(query, [worker_id, vacation_type_id, year, total_days, notes || null, created_by]); + successCount++; + } catch (err) { + console.error('휴가 잔액 저장 오류:', err); + errorCount++; + } + } + + res.json({ + success: true, + message: `${successCount}건 저장 완료${errorCount > 0 ? `, ${errorCount}건 실패` : ''}`, + data: { successCount, errorCount } + }); + } catch (error) { + console.error('bulkUpsert 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 작업자의 사용 가능한 휴가 일수 조회 + * GET /api/vacation-balances/worker/:workerId/year/:year/available + */ + async getAvailableDays(req, res) { + try { + const { workerId, year } = req.params; + + vacationBalanceModel.getAvailableVacationDays(workerId, year, (err, results) => { + if (err) { + console.error('사용 가능 휴가 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '사용 가능 휴가를 조회하는 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('getAvailableDays 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + } +}; + +module.exports = vacationBalanceController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/vacationRequestController.js b/deploy/tkfb-package/api.hyungi.net/controllers/vacationRequestController.js new file mode 100644 index 0000000..8d4df9f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/vacationRequestController.js @@ -0,0 +1,565 @@ +/** + * vacationRequestController.js + * 휴가 신청 관련 컨트롤러 + */ + +const vacationRequestModel = require('../models/vacationRequestModel'); +// TODO: workerVacationBalanceModel 구현 필요 +// const workerVacationBalanceModel = require('../models/workerVacationBalanceModel'); + +const vacationRequestController = { + /** + * 휴가 신청 생성 + */ + async createRequest(req, res) { + try { + const { worker_id, vacation_type_id, start_date, end_date, days_used, reason } = req.body; + const requested_by = req.user.user_id; + + // 필수 필드 검증 + if (!worker_id || !vacation_type_id || !start_date || !end_date || !days_used) { + return res.status(400).json({ + success: false, + message: '필수 필드가 누락되었습니다' + }); + } + + // 날짜 유효성 검증 + const startDate = new Date(start_date); + const endDate = new Date(end_date); + + if (endDate < startDate) { + return res.status(400).json({ + success: false, + message: '종료일은 시작일보다 이후여야 합니다' + }); + } + + // 기간 중복 체크 + vacationRequestModel.checkOverlap(worker_id, start_date, end_date, null, (err, results) => { + if (err) { + console.error('기간 중복 체크 오류:', err); + return res.status(500).json({ + success: false, + message: '기간 중복 체크 중 오류가 발생했습니다' + }); + } + + if (results[0].count > 0) { + return res.status(400).json({ + success: false, + message: '해당 기간에 이미 신청된 휴가가 있습니다' + }); + } + + // TODO: 잔여 연차 확인 로직 구현 필요 + // 현재는 잔여 연차 확인 없이 신청 가능 + + // 휴가 신청 생성 + const requestData = { + worker_id, + vacation_type_id, + start_date, + end_date, + days_used, + reason: reason || null, + status: 'pending', + requested_by + }; + + vacationRequestModel.create(requestData, (err, result) => { + if (err) { + console.error('휴가 신청 생성 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 생성 중 오류가 발생했습니다' + }); + } + + res.status(201).json({ + success: true, + message: '휴가 신청이 완료되었습니다', + data: { + request_id: result.insertId + } + }); + }); + }); + } catch (error) { + console.error('휴가 신청 생성 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 신청 목록 조회 + */ + async getAllRequests(req, res) { + try { + const filters = { + worker_id: req.query.worker_id, + status: req.query.status, + start_date: req.query.start_date, + end_date: req.query.end_date, + vacation_type_id: req.query.vacation_type_id + }; + + // 일반 사용자는 자신의 신청만 조회 가능 + if (req.user.access_level !== 'system') { + if (req.user.worker_id) { + filters.worker_id = req.user.worker_id; + } else { + return res.status(403).json({ + success: false, + message: '권한이 없습니다' + }); + } + } + + vacationRequestModel.getAll(filters, (err, results) => { + if (err) { + console.error('휴가 신청 목록 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 목록 조회 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('휴가 신청 목록 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 특정 휴가 신청 조회 + */ + async getRequestById(req, res) { + try { + const { id } = req.params; + + vacationRequestModel.getById(id, (err, results) => { + if (err) { + console.error('휴가 신청 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 조회 중 오류가 발생했습니다' + }); + } + + if (results.length === 0) { + return res.status(404).json({ + success: false, + message: '해당 휴가 신청을 찾을 수 없습니다' + }); + } + + const request = results[0]; + + // 권한 검증: 관리자 또는 본인만 조회 가능 + if (req.user.access_level !== 'system' && req.user.worker_id !== request.worker_id) { + return res.status(403).json({ + success: false, + message: '권한이 없습니다' + }); + } + + res.json({ + success: true, + data: request + }); + }); + } catch (error) { + console.error('휴가 신청 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 신청 수정 (대기 중인 신청만) + */ + async updateRequest(req, res) { + try { + const { id } = req.params; + const { start_date, end_date, days_used, reason } = req.body; + + // 기존 신청 조회 + vacationRequestModel.getById(id, (err, results) => { + if (err) { + console.error('휴가 신청 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 조회 중 오류가 발생했습니다' + }); + } + + if (results.length === 0) { + return res.status(404).json({ + success: false, + message: '해당 휴가 신청을 찾을 수 없습니다' + }); + } + + const existingRequest = results[0]; + + // 권한 검증 + if (req.user.access_level !== 'system' && req.user.worker_id !== existingRequest.worker_id) { + return res.status(403).json({ + success: false, + message: '권한이 없습니다' + }); + } + + // 대기 중인 신청만 수정 가능 + if (existingRequest.status !== 'pending') { + return res.status(400).json({ + success: false, + message: '승인/거부된 신청은 수정할 수 없습니다' + }); + } + + const updateData = {}; + if (start_date) updateData.start_date = start_date; + if (end_date) updateData.end_date = end_date; + if (days_used) updateData.days_used = days_used; + if (reason !== undefined) updateData.reason = reason; + + // 날짜가 변경된 경우 중복 체크 + if (start_date || end_date) { + const newStartDate = start_date || existingRequest.start_date; + const newEndDate = end_date || existingRequest.end_date; + + vacationRequestModel.checkOverlap( + existingRequest.worker_id, + newStartDate, + newEndDate, + id, + (err, overlapResults) => { + if (err) { + console.error('기간 중복 체크 오류:', err); + return res.status(500).json({ + success: false, + message: '기간 중복 체크 중 오류가 발생했습니다' + }); + } + + if (overlapResults[0].count > 0) { + return res.status(400).json({ + success: false, + message: '해당 기간에 이미 신청된 휴가가 있습니다' + }); + } + + // 수정 실행 + vacationRequestModel.update(id, updateData, (err, result) => { + if (err) { + console.error('휴가 신청 수정 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 수정 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + message: '휴가 신청이 수정되었습니다' + }); + }); + } + ); + } else { + // 날짜 변경 없이 바로 수정 + vacationRequestModel.update(id, updateData, (err, result) => { + if (err) { + console.error('휴가 신청 수정 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 수정 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + message: '휴가 신청이 수정되었습니다' + }); + }); + } + }); + } catch (error) { + console.error('휴가 신청 수정 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 신청 삭제 (대기 중인 신청만) + */ + async deleteRequest(req, res) { + try { + const { id } = req.params; + + // 기존 신청 조회 + vacationRequestModel.getById(id, (err, results) => { + if (err) { + console.error('휴가 신청 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 조회 중 오류가 발생했습니다' + }); + } + + if (results.length === 0) { + return res.status(404).json({ + success: false, + message: '해당 휴가 신청을 찾을 수 없습니다' + }); + } + + const existingRequest = results[0]; + + // 권한 검증 + if (req.user.access_level !== 'system' && req.user.worker_id !== existingRequest.worker_id) { + return res.status(403).json({ + success: false, + message: '권한이 없습니다' + }); + } + + // 대기 중인 신청만 삭제 가능 + if (existingRequest.status !== 'pending') { + return res.status(400).json({ + success: false, + message: '승인/거부된 신청은 삭제할 수 없습니다' + }); + } + + vacationRequestModel.delete(id, (err, result) => { + if (err) { + console.error('휴가 신청 삭제 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 삭제 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + message: '휴가 신청이 삭제되었습니다' + }); + }); + }); + } catch (error) { + console.error('휴가 신청 삭제 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 신청 승인 (관리자만) + */ + async approveRequest(req, res) { + try { + const { id } = req.params; + const { review_note } = req.body; + const reviewed_by = req.user.user_id; + + // 관리자 권한 확인 + if (req.user.access_level !== 'system') { + return res.status(403).json({ + success: false, + message: '관리자만 승인할 수 있습니다' + }); + } + + // 기존 신청 조회 + vacationRequestModel.getById(id, (err, results) => { + if (err) { + console.error('휴가 신청 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 조회 중 오류가 발생했습니다' + }); + } + + if (results.length === 0) { + return res.status(404).json({ + success: false, + message: '해당 휴가 신청을 찾을 수 없습니다' + }); + } + + const request = results[0]; + + if (request.status !== 'pending') { + return res.status(400).json({ + success: false, + message: '이미 처리된 신청입니다' + }); + } + + // 상태 업데이트 + const statusData = { + status: 'approved', + reviewed_by, + review_note + }; + + vacationRequestModel.updateStatus(id, statusData, (err, result) => { + if (err) { + console.error('휴가 승인 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 승인 중 오류가 발생했습니다' + }); + } + + // TODO: 잔여 연차에서 차감 로직 구현 필요 + // 현재는 연차 차감 없이 승인만 처리 + + res.json({ + success: true, + message: '휴가 신청이 승인되었습니다' + }); + }); + }); + } catch (error) { + console.error('휴가 승인 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 신청 거부 (관리자만) + */ + async rejectRequest(req, res) { + try { + const { id } = req.params; + const { review_note } = req.body; + const reviewed_by = req.user.user_id; + + // 관리자 권한 확인 + if (req.user.access_level !== 'system') { + return res.status(403).json({ + success: false, + message: '관리자만 거부할 수 있습니다' + }); + } + + // 기존 신청 조회 + vacationRequestModel.getById(id, (err, results) => { + if (err) { + console.error('휴가 신청 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 신청 조회 중 오류가 발생했습니다' + }); + } + + if (results.length === 0) { + return res.status(404).json({ + success: false, + message: '해당 휴가 신청을 찾을 수 없습니다' + }); + } + + const request = results[0]; + + if (request.status !== 'pending') { + return res.status(400).json({ + success: false, + message: '이미 처리된 신청입니다' + }); + } + + // 상태 업데이트 + const statusData = { + status: 'rejected', + reviewed_by, + review_note + }; + + vacationRequestModel.updateStatus(id, statusData, (err, result) => { + if (err) { + console.error('휴가 거부 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 거부 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + message: '휴가 신청이 거부되었습니다' + }); + }); + }); + } catch (error) { + console.error('휴가 거부 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 대기 중인 휴가 신청 목록 (관리자용) + */ + async getPendingRequests(req, res) { + try { + // 관리자 권한 확인 + if (req.user.access_level !== 'system') { + return res.status(403).json({ + success: false, + message: '관리자만 조회할 수 있습니다' + }); + } + + vacationRequestModel.getAllPending((err, results) => { + if (err) { + console.error('대기 중인 휴가 신청 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '대기 중인 휴가 신청 조회 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('대기 중인 휴가 신청 조회 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + } +}; + +module.exports = vacationRequestController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/vacationTypeController.js b/deploy/tkfb-package/api.hyungi.net/controllers/vacationTypeController.js new file mode 100644 index 0000000..9eddaeb --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/vacationTypeController.js @@ -0,0 +1,333 @@ +/** + * vacationTypeController.js + * 휴가 유형 관련 컨트롤러 + */ + +const vacationTypeModel = require('../models/vacationTypeModel'); + +const vacationTypeController = { + /** + * 모든 활성 휴가 유형 조회 + * GET /api/vacation-types + */ + async getAllTypes(req, res) { + try { + vacationTypeModel.getAll((err, results) => { + if (err) { + console.error('휴가 유형 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 유형을 조회하는 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('getAllTypes 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 시스템 기본 휴가 유형 조회 + * GET /api/vacation-types/system + */ + async getSystemTypes(req, res) { + try { + vacationTypeModel.getSystemTypes((err, results) => { + if (err) { + console.error('시스템 휴가 유형 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '시스템 휴가 유형을 조회하는 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('getSystemTypes 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 특별 휴가 유형 조회 + * GET /api/vacation-types/special + */ + async getSpecialTypes(req, res) { + try { + vacationTypeModel.getSpecialTypes((err, results) => { + if (err) { + console.error('특별 휴가 유형 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '특별 휴가 유형을 조회하는 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + data: results + }); + }); + } catch (error) { + console.error('getSpecialTypes 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 특별 휴가 유형 생성 (관리자만) + * POST /api/vacation-types + */ + async createType(req, res) { + try { + const { + type_code, + type_name, + deduct_days, + priority, + description + } = req.body; + + // 필수 필드 검증 + if (!type_code || !type_name || !deduct_days) { + return res.status(400).json({ + success: false, + message: '필수 필드가 누락되었습니다 (type_code, type_name, deduct_days)' + }); + } + + // type_code 중복 체크 + vacationTypeModel.getByCode(type_code, (err, existingTypes) => { + if (err) { + console.error('type_code 중복 체크 오류:', err); + return res.status(500).json({ + success: false, + message: 'type_code 중복 체크 중 오류가 발생했습니다' + }); + } + + if (existingTypes && existingTypes.length > 0) { + return res.status(400).json({ + success: false, + message: '이미 존재하는 type_code입니다' + }); + } + + // 특별 휴가 유형으로 생성 + const typeData = { + type_code, + type_name, + deduct_days, + priority: priority || 50, + description: description || null, + is_special: true, + is_system: false, + is_active: true + }; + + vacationTypeModel.create(typeData, (err, result) => { + if (err) { + console.error('휴가 유형 생성 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 유형을 생성하는 중 오류가 발생했습니다' + }); + } + + res.status(201).json({ + success: true, + message: '특별 휴가 유형이 생성되었습니다', + data: { id: result.insertId } + }); + }); + }); + } catch (error) { + console.error('createType 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 유형 수정 (관리자만) + * PUT /api/vacation-types/:id + */ + async updateType(req, res) { + try { + const { id } = req.params; + const { + type_name, + deduct_days, + priority, + description, + is_active + } = req.body; + + // 먼저 해당 유형 조회 + vacationTypeModel.getById(id, (err, types) => { + if (err) { + console.error('휴가 유형 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 유형을 조회하는 중 오류가 발생했습니다' + }); + } + + if (!types || types.length === 0) { + return res.status(404).json({ + success: false, + message: '휴가 유형을 찾을 수 없습니다' + }); + } + + const type = types[0]; + + // 시스템 기본 휴가의 경우 제한적으로만 수정 가능 + const updateData = {}; + if (type.is_system) { + // 시스템 휴가는 priority와 description만 수정 가능 + if (priority !== undefined) updateData.priority = priority; + if (description !== undefined) updateData.description = description; + } else { + // 특별 휴가는 모든 필드 수정 가능 + if (type_name) updateData.type_name = type_name; + if (deduct_days !== undefined) updateData.deduct_days = deduct_days; + if (priority !== undefined) updateData.priority = priority; + if (description !== undefined) updateData.description = description; + if (is_active !== undefined) updateData.is_active = is_active; + } + + if (Object.keys(updateData).length === 0) { + return res.status(400).json({ + success: false, + message: '수정할 데이터가 없습니다' + }); + } + + updateData.updated_at = new Date(); + + vacationTypeModel.update(id, updateData, (err, result) => { + if (err) { + console.error('휴가 유형 수정 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 유형을 수정하는 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + message: '휴가 유형이 수정되었습니다' + }); + }); + }); + } catch (error) { + console.error('updateType 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 특별 휴가 유형 삭제 (관리자만, 시스템 기본 휴가는 삭제 불가) + * DELETE /api/vacation-types/:id + */ + async deleteType(req, res) { + try { + const { id } = req.params; + + vacationTypeModel.delete(id, (err, result) => { + if (err) { + console.error('휴가 유형 삭제 오류:', err); + return res.status(500).json({ + success: false, + message: '휴가 유형을 삭제하는 중 오류가 발생했습니다' + }); + } + + if (result.affectedRows === 0) { + return res.status(400).json({ + success: false, + message: '삭제할 수 없습니다. 시스템 기본 휴가이거나 존재하지 않는 휴가 유형입니다' + }); + } + + res.json({ + success: true, + message: '휴가 유형이 삭제되었습니다' + }); + }); + } catch (error) { + console.error('deleteType 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + }, + + /** + * 휴가 유형 우선순위 일괄 업데이트 (관리자만) + * PUT /api/vacation-types/priorities + */ + async updatePriorities(req, res) { + try { + const { priorities } = req.body; + + // priorities = [{ id: 1, priority: 10 }, { id: 2, priority: 20 }, ...] + if (!priorities || !Array.isArray(priorities)) { + return res.status(400).json({ + success: false, + message: 'priorities 배열이 필요합니다' + }); + } + + vacationTypeModel.updatePriorities(priorities, (err, result) => { + if (err) { + console.error('우선순위 업데이트 오류:', err); + return res.status(500).json({ + success: false, + message: '우선순위를 업데이트하는 중 오류가 발생했습니다' + }); + } + + res.json({ + success: true, + message: '우선순위가 업데이트되었습니다', + data: { updated: result.affectedRows } + }); + }); + } catch (error) { + console.error('updatePriorities 오류:', error); + res.status(500).json({ + success: false, + message: '서버 오류가 발생했습니다' + }); + } + } +}; + +module.exports = vacationTypeController; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/visitRequestController.js b/deploy/tkfb-package/api.hyungi.net/controllers/visitRequestController.js new file mode 100644 index 0000000..8a7e5b6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/visitRequestController.js @@ -0,0 +1,555 @@ +const visitRequestModel = require('../models/visitRequestModel'); + +// ==================== 출입 신청 관리 ==================== + +/** + * 출입 신청 생성 + */ +exports.createVisitRequest = (req, res) => { + const requester_id = req.user.user_id; + const requestData = { + requester_id, + ...req.body + }; + + // 필수 필드 검증 + const requiredFields = ['visitor_company', 'category_id', 'workplace_id', 'visit_date', 'visit_time', 'purpose_id']; + for (const field of requiredFields) { + if (!requestData[field]) { + return res.status(400).json({ + success: false, + message: `${field}는 필수 입력 항목입니다.` + }); + } + } + + visitRequestModel.createVisitRequest(requestData, (err, requestId) => { + if (err) { + console.error('출입 신청 생성 오류:', err); + return res.status(500).json({ + success: false, + message: '출입 신청 생성 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.status(201).json({ + success: true, + message: '출입 신청이 성공적으로 생성되었습니다.', + data: { request_id: requestId } + }); + }); +}; + +/** + * 출입 신청 목록 조회 + */ +exports.getAllVisitRequests = (req, res) => { + const filters = { + status: req.query.status, + visit_date: req.query.visit_date, + start_date: req.query.start_date, + end_date: req.query.end_date, + requester_id: req.query.requester_id, + category_id: req.query.category_id + }; + + visitRequestModel.getAllVisitRequests(filters, (err, requests) => { + if (err) { + console.error('출입 신청 목록 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '출입 신청 목록 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: requests + }); + }); +}; + +/** + * 출입 신청 상세 조회 + */ +exports.getVisitRequestById = (req, res) => { + const requestId = req.params.id; + + visitRequestModel.getVisitRequestById(requestId, (err, request) => { + if (err) { + console.error('출입 신청 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '출입 신청 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (!request) { + return res.status(404).json({ + success: false, + message: '출입 신청을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + data: request + }); + }); +}; + +/** + * 출입 신청 수정 + */ +exports.updateVisitRequest = (req, res) => { + const requestId = req.params.id; + const requestData = req.body; + + visitRequestModel.updateVisitRequest(requestId, requestData, (err, result) => { + if (err) { + console.error('출입 신청 수정 오류:', err); + return res.status(500).json({ + success: false, + message: '출입 신청 수정 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '출입 신청을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '출입 신청이 수정되었습니다.' + }); + }); +}; + +/** + * 출입 신청 삭제 + */ +exports.deleteVisitRequest = (req, res) => { + const requestId = req.params.id; + + visitRequestModel.deleteVisitRequest(requestId, (err, result) => { + if (err) { + console.error('출입 신청 삭제 오류:', err); + return res.status(500).json({ + success: false, + message: '출입 신청 삭제 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '출입 신청을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '출입 신청이 삭제되었습니다.' + }); + }); +}; + +/** + * 출입 신청 승인 + */ +exports.approveVisitRequest = (req, res) => { + const requestId = req.params.id; + const approvedBy = req.user.user_id; + + visitRequestModel.approveVisitRequest(requestId, approvedBy, (err, result) => { + if (err) { + console.error('출입 신청 승인 오류:', err); + return res.status(500).json({ + success: false, + message: '출입 신청 승인 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '출입 신청을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '출입 신청이 승인되었습니다.' + }); + }); +}; + +/** + * 출입 신청 반려 + */ +exports.rejectVisitRequest = (req, res) => { + const requestId = req.params.id; + const approvedBy = req.user.user_id; + const rejectionReason = req.body.rejection_reason || '사유 없음'; + + const rejectionData = { + approved_by: approvedBy, + rejection_reason: rejectionReason + }; + + visitRequestModel.rejectVisitRequest(requestId, rejectionData, (err, result) => { + if (err) { + console.error('출입 신청 반려 오류:', err); + return res.status(500).json({ + success: false, + message: '출입 신청 반려 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '출입 신청을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '출입 신청이 반려되었습니다.' + }); + }); +}; + +// ==================== 방문 목적 관리 ==================== + +/** + * 모든 방문 목적 조회 + */ +exports.getAllVisitPurposes = (req, res) => { + visitRequestModel.getAllVisitPurposes((err, purposes) => { + if (err) { + console.error('방문 목적 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '방문 목적 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: purposes + }); + }); +}; + +/** + * 활성 방문 목적만 조회 + */ +exports.getActiveVisitPurposes = (req, res) => { + visitRequestModel.getActiveVisitPurposes((err, purposes) => { + if (err) { + console.error('활성 방문 목적 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '활성 방문 목적 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: purposes + }); + }); +}; + +/** + * 방문 목적 추가 + */ +exports.createVisitPurpose = (req, res) => { + const purposeData = req.body; + + if (!purposeData.purpose_name) { + return res.status(400).json({ + success: false, + message: 'purpose_name은 필수 입력 항목입니다.' + }); + } + + visitRequestModel.createVisitPurpose(purposeData, (err, purposeId) => { + if (err) { + console.error('방문 목적 추가 오류:', err); + return res.status(500).json({ + success: false, + message: '방문 목적 추가 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.status(201).json({ + success: true, + message: '방문 목적이 추가되었습니다.', + data: { purpose_id: purposeId } + }); + }); +}; + +/** + * 방문 목적 수정 + */ +exports.updateVisitPurpose = (req, res) => { + const purposeId = req.params.id; + const purposeData = req.body; + + visitRequestModel.updateVisitPurpose(purposeId, purposeData, (err, result) => { + if (err) { + console.error('방문 목적 수정 오류:', err); + return res.status(500).json({ + success: false, + message: '방문 목적 수정 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '방문 목적을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '방문 목적이 수정되었습니다.' + }); + }); +}; + +/** + * 방문 목적 삭제 + */ +exports.deleteVisitPurpose = (req, res) => { + const purposeId = req.params.id; + + visitRequestModel.deleteVisitPurpose(purposeId, (err, result) => { + if (err) { + console.error('방문 목적 삭제 오류:', err); + return res.status(500).json({ + success: false, + message: '방문 목적 삭제 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '방문 목적을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '방문 목적이 삭제되었습니다.' + }); + }); +}; + +// ==================== 안전교육 기록 관리 ==================== + +/** + * 안전교육 기록 생성 + */ +exports.createTrainingRecord = (req, res) => { + const trainerId = req.user.user_id; + const trainingData = { + trainer_id: trainerId, + ...req.body + }; + + // 필수 필드 검증 + const requiredFields = ['request_id', 'training_date', 'training_start_time']; + for (const field of requiredFields) { + if (!trainingData[field]) { + return res.status(400).json({ + success: false, + message: `${field}는 필수 입력 항목입니다.` + }); + } + } + + visitRequestModel.createTrainingRecord(trainingData, (err, trainingId) => { + if (err) { + console.error('안전교육 기록 생성 오류:', err); + return res.status(500).json({ + success: false, + message: '안전교육 기록 생성 중 오류가 발생했습니다.', + error: err.message + }); + } + + // 안전교육 기록이 생성되면 출입 신청 상태를 training_completed로 변경 + console.log(`[교육 완료] request_id=${trainingData.request_id} 상태를 training_completed로 변경 중...`); + visitRequestModel.updateVisitRequestStatus(trainingData.request_id, 'training_completed', (statusErr) => { + if (statusErr) { + console.error('출입 신청 상태 업데이트 오류:', statusErr); + // 에러가 발생해도 교육 기록은 생성되었으므로 성공 응답 + } else { + console.log(`[교육 완료] request_id=${trainingData.request_id} 상태 변경 성공`); + } + + res.status(201).json({ + success: true, + message: '안전교육 기록이 생성되었습니다.', + data: { training_id: trainingId } + }); + }); + }); +}; + +/** + * 특정 출입 신청의 안전교육 기록 조회 + */ +exports.getTrainingRecordByRequestId = (req, res) => { + const requestId = req.params.requestId; + + visitRequestModel.getTrainingRecordByRequestId(requestId, (err, record) => { + if (err) { + console.error('안전교육 기록 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '안전교육 기록 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: record || null + }); + }); +}; + +/** + * 안전교육 기록 수정 + */ +exports.updateTrainingRecord = (req, res) => { + const trainingId = req.params.id; + const trainingData = req.body; + + visitRequestModel.updateTrainingRecord(trainingId, trainingData, (err, result) => { + if (err) { + console.error('안전교육 기록 수정 오류:', err); + return res.status(500).json({ + success: false, + message: '안전교육 기록 수정 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '안전교육 기록을 찾을 수 없습니다.' + }); + } + + res.json({ + success: true, + message: '안전교육 기록이 수정되었습니다.' + }); + }); +}; + +/** + * 안전교육 완료 (서명 포함) + */ +exports.completeTraining = (req, res) => { + const trainingId = req.params.id; + const signatureData = req.body.signature_data; + + if (!signatureData) { + return res.status(400).json({ + success: false, + message: '서명 데이터가 필요합니다.' + }); + } + + visitRequestModel.completeTraining(trainingId, signatureData, (err, result) => { + if (err) { + console.error('안전교육 완료 처리 오류:', err); + return res.status(500).json({ + success: false, + message: '안전교육 완료 처리 중 오류가 발생했습니다.', + error: err.message + }); + } + + if (result.affectedRows === 0) { + return res.status(404).json({ + success: false, + message: '안전교육 기록을 찾을 수 없습니다.' + }); + } + + // 교육 완료 후 출입 신청 상태를 'training_completed'로 변경 + visitRequestModel.getTrainingRecordByRequestId(trainingId, (err, record) => { + if (err || !record) { + return res.json({ + success: true, + message: '안전교육이 완료되었습니다.' + }); + } + + visitRequestModel.updateVisitRequestStatus(record.request_id, 'training_completed', (err) => { + if (err) { + console.error('출입 신청 상태 업데이트 오류:', err); + } + + res.json({ + success: true, + message: '안전교육이 완료되었습니다.' + }); + }); + }); + }); +}; + +/** + * 안전교육 기록 목록 조회 + */ +exports.getTrainingRecords = (req, res) => { + const filters = { + training_date: req.query.training_date, + start_date: req.query.start_date, + end_date: req.query.end_date, + trainer_id: req.query.trainer_id + }; + + visitRequestModel.getTrainingRecords(filters, (err, records) => { + if (err) { + console.error('안전교육 기록 목록 조회 오류:', err); + return res.status(500).json({ + success: false, + message: '안전교육 기록 목록 조회 중 오류가 발생했습니다.', + error: err.message + }); + } + + res.json({ + success: true, + data: records + }); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/workAnalysisController.js b/deploy/tkfb-package/api.hyungi.net/controllers/workAnalysisController.js new file mode 100644 index 0000000..506e003 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/workAnalysisController.js @@ -0,0 +1,490 @@ +/** + * 작업 분석 컨트롤러 + * + * 작업 보고서 다차원 분석 API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const WorkAnalysis = require('../models/WorkAnalysis'); +const { getDb } = require('../dbPool'); +const { ValidationError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); + +/** + * 날짜 유효성 검사 헬퍼 함수 + */ +const validateDateRange = (startDate, endDate) => { + if (!startDate || !endDate) { + throw new ValidationError('시작일과 종료일을 입력해주세요', { + required: ['start', 'end'], + received: { start: startDate, end: endDate } + }); + } + + const start = new Date(startDate); + const end = new Date(endDate); + + if (isNaN(start.getTime()) || isNaN(end.getTime())) { + throw new ValidationError('올바른 날짜 형식을 입력해주세요', { + format: 'YYYY-MM-DD', + received: { start: startDate, end: endDate } + }); + } + + if (start > end) { + throw new ValidationError('시작일이 종료일보다 늦을 수 없습니다', { + start: startDate, + end: endDate + }); + } + + // 너무 긴 기간 방지 (1년 제한) + const diffTime = Math.abs(end - start); + const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + if (diffDays > 365) { + throw new ValidationError('조회 기간은 1년을 초과할 수 없습니다', { + days: diffDays, + max: 365 + }); + } + + return { start, end }; +}; + +/** + * 기본 통계 조회 + */ +const getStats = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('기본 통계 조회 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const stats = await workAnalysis.getBasicStats(start, end); + + logger.info('기본 통계 조회 성공', { start, end }); + + res.json({ + success: true, + data: stats, + message: '기본 통계 조회 완료' + }); + } catch (error) { + logger.error('기본 통계 조회 실패', { start, end, error: error.message }); + throw new DatabaseError('기본 통계 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 일별 작업시간 추이 조회 + */ +const getDailyTrend = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('일별 추이 조회 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const trendData = await workAnalysis.getDailyTrend(start, end); + + logger.info('일별 추이 조회 성공', { start, end, dataPoints: trendData.length }); + + res.json({ + success: true, + data: trendData, + message: '일별 추이 조회 완료' + }); + } catch (error) { + logger.error('일별 추이 조회 실패', { start, end, error: error.message }); + throw new DatabaseError('일별 추이 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 작업자별 통계 조회 + */ +const getWorkerStats = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('작업자별 통계 조회 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const workerStats = await workAnalysis.getWorkerStats(start, end); + + logger.info('작업자별 통계 조회 성공', { + start, + end, + workerCount: workerStats.length + }); + + res.json({ + success: true, + data: workerStats, + message: '작업자별 통계 조회 완료' + }); + } catch (error) { + logger.error('작업자별 통계 조회 실패', { start, end, error: error.message }); + throw new DatabaseError('작업자별 통계 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 프로젝트별 통계 조회 + */ +const getProjectStats = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('프로젝트별 통계 조회 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const projectStats = await workAnalysis.getProjectStats(start, end); + + logger.info('프로젝트별 통계 조회 성공', { + start, + end, + projectCount: projectStats.length + }); + + res.json({ + success: true, + data: projectStats, + message: '프로젝트별 통계 조회 완료' + }); + } catch (error) { + logger.error('프로젝트별 통계 조회 실패', { start, end, error: error.message }); + throw new DatabaseError('프로젝트별 통계 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 작업유형별 통계 조회 + */ +const getWorkTypeStats = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('작업유형별 통계 조회 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const workTypeStats = await workAnalysis.getWorkTypeStats(start, end); + + logger.info('작업유형별 통계 조회 성공', { + start, + end, + workTypeCount: workTypeStats.length + }); + + res.json({ + success: true, + data: workTypeStats, + message: '작업유형별 통계 조회 완료' + }); + } catch (error) { + logger.error('작업유형별 통계 조회 실패', { start, end, error: error.message }); + throw new DatabaseError('작업유형별 통계 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 최근 작업 현황 조회 + */ +const getRecentWork = asyncHandler(async (req, res) => { + const { start, end, limit = 10 } = req.query; + validateDateRange(start, end); + + // limit 유효성 검사 (최대 5000까지 허용) + const limitNum = parseInt(limit); + if (isNaN(limitNum) || limitNum < 1 || limitNum > 5000) { + throw new ValidationError('limit은 1~5000 사이의 숫자여야 합니다', { + received: limit, + min: 1, + max: 5000 + }); + } + + logger.info('최근 작업 현황 조회 요청', { start, end, limit: limitNum }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const recentWork = await workAnalysis.getRecentWork(start, end, limitNum); + + logger.info('최근 작업 현황 조회 성공', { + start, + end, + limit: limitNum, + resultCount: recentWork.length + }); + + res.json({ + success: true, + data: recentWork, + message: '최근 작업 현황 조회 완료' + }); + } catch (error) { + logger.error('최근 작업 현황 조회 실패', { + start, + end, + limit: limitNum, + error: error.message + }); + throw new DatabaseError('최근 작업 현황 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 요일별 패턴 분석 조회 + */ +const getWeekdayPattern = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('요일별 패턴 분석 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const weekdayPattern = await workAnalysis.getWeekdayPattern(start, end); + + logger.info('요일별 패턴 분석 성공', { start, end }); + + res.json({ + success: true, + data: weekdayPattern, + message: '요일별 패턴 분석 완료' + }); + } catch (error) { + logger.error('요일별 패턴 분석 실패', { start, end, error: error.message }); + throw new DatabaseError('요일별 패턴 분석 중 오류가 발생했습니다'); + } +}); + +/** + * 에러 분석 조회 + */ +const getErrorAnalysis = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('에러 분석 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const errorAnalysis = await workAnalysis.getErrorAnalysis(start, end); + + logger.info('에러 분석 성공', { start, end }); + + res.json({ + success: true, + data: errorAnalysis, + message: '에러 분석 완료' + }); + } catch (error) { + logger.error('에러 분석 실패', { start, end, error: error.message }); + throw new DatabaseError('에러 분석 중 오류가 발생했습니다'); + } +}); + +/** + * 월별 비교 분석 조회 + */ +const getMonthlyComparison = asyncHandler(async (req, res) => { + const { year = new Date().getFullYear() } = req.query; + + const yearNum = parseInt(year); + if (isNaN(yearNum) || yearNum < 2000 || yearNum > 2050) { + throw new ValidationError('올바른 연도를 입력해주세요', { + received: year, + min: 2000, + max: 2050 + }); + } + + logger.info('월별 비교 분석 요청', { year: yearNum }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const monthlyData = await workAnalysis.getMonthlyComparison(yearNum); + + logger.info('월별 비교 분석 성공', { year: yearNum }); + + res.json({ + success: true, + data: monthlyData, + message: '월별 비교 분석 완료' + }); + } catch (error) { + logger.error('월별 비교 분석 실패', { year: yearNum, error: error.message }); + throw new DatabaseError('월별 비교 분석 중 오류가 발생했습니다'); + } +}); + +/** + * 작업자별 전문분야 분석 조회 + */ +const getWorkerSpecialization = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('작업자별 전문분야 분석 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + const specializationData = await workAnalysis.getWorkerSpecialization(start, end); + + // 작업자별로 그룹화하여 정리 + const groupedData = specializationData.reduce((acc, item) => { + if (!acc[item.worker_id]) { + acc[item.worker_id] = []; + } + acc[item.worker_id].push({ + work_type_id: item.work_type_id, + project_id: item.project_id, + totalHours: item.totalHours, + totalReports: item.totalReports, + percentage: item.percentage + }); + return acc; + }, {}); + + logger.info('작업자별 전문분야 분석 성공', { + start, + end, + workerCount: Object.keys(groupedData).length + }); + + res.json({ + success: true, + data: groupedData, + message: '작업자별 전문분야 분석 완료' + }); + } catch (error) { + logger.error('작업자별 전문분야 분석 실패', { start, end, error: error.message }); + throw new DatabaseError('작업자별 전문분야 분석 중 오류가 발생했습니다'); + } +}); + +/** + * 대시보드용 종합 데이터 조회 + */ +const getDashboardData = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('대시보드 데이터 조회 요청', { start, end }); + + try { + const db = await getDb(); + const workAnalysis = new WorkAnalysis(db); + + // 병렬로 여러 데이터 조회 + const [ + stats, + dailyTrend, + workerStats, + projectStats, + workTypeStats, + recentWork + ] = await Promise.all([ + workAnalysis.getBasicStats(start, end), + workAnalysis.getDailyTrend(start, end), + workAnalysis.getWorkerStats(start, end), + workAnalysis.getProjectStats(start, end), + workAnalysis.getWorkTypeStats(start, end), + workAnalysis.getRecentWork(start, end, 10) + ]); + + logger.info('대시보드 데이터 조회 성공', { start, end }); + + res.json({ + success: true, + data: { + stats, + dailyTrend, + workerStats, + projectStats, + workTypeStats, + recentWork + }, + message: '대시보드 데이터 조회 완료' + }); + } catch (error) { + logger.error('대시보드 데이터 조회 실패', { start, end, error: error.message }); + throw new DatabaseError('대시보드 데이터 조회 중 오류가 발생했습니다'); + } +}); + +const workAnalysisService = require('../services/workAnalysisService'); + +/** + * 프로젝트별-작업별 시간 분석 (총시간, 정규시간, 에러시간) + */ +const getProjectWorkTypeAnalysis = asyncHandler(async (req, res) => { + const { start, end } = req.query; + validateDateRange(start, end); + + logger.info('프로젝트별-작업별 시간 분석 요청', { start, end }); + + try { + const result = await workAnalysisService.getProjectWorkTypeAnalysis(start, end); + + logger.info('프로젝트별-작업별 시간 분석 성공', { + start, + end, + projectCount: result.summary.total_projects, + workTypeCount: result.summary.total_work_types, + totalHours: result.summary.grand_total_hours + }); + + res.json({ + success: true, + data: result, + message: '프로젝트별-작업별 시간 분석 완료' + }); + } catch (error) { + logger.error('프로젝트별-작업별 시간 분석 실패', { + start, + end, + error: error.message + }); + // Service throws DatabaseError wrapper or Error + if (error.name === 'DatabaseError') { + throw error; + } + throw new DatabaseError('프로젝트별-작업별 시간 분석 중 오류가 발생했습니다'); + } +}); + +module.exports = { + getStats, + getDailyTrend, + getWorkerStats, + getProjectStats, + getWorkTypeStats, + getRecentWork, + getWeekdayPattern, + getErrorAnalysis, + getMonthlyComparison, + getWorkerSpecialization, + getDashboardData, + getProjectWorkTypeAnalysis +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/workIssueController.js b/deploy/tkfb-package/api.hyungi.net/controllers/workIssueController.js new file mode 100644 index 0000000..0811be6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/workIssueController.js @@ -0,0 +1,674 @@ +/** + * 작업 중 문제 신고 컨트롤러 + */ + +const workIssueModel = require('../models/workIssueModel'); +const imageUploadService = require('../services/imageUploadService'); + +// ==================== 신고 카테고리 관리 ==================== + +/** + * 모든 카테고리 조회 + */ +exports.getAllCategories = (req, res) => { + workIssueModel.getAllCategories((err, categories) => { + if (err) { + console.error('카테고리 조회 실패:', err); + return res.status(500).json({ success: false, error: '카테고리 조회 실패' }); + } + res.json({ success: true, data: categories }); + }); +}; + +/** + * 타입별 카테고리 조회 + */ +exports.getCategoriesByType = (req, res) => { + const { type } = req.params; + + if (!['nonconformity', 'safety'].includes(type)) { + return res.status(400).json({ success: false, error: '유효하지 않은 카테고리 타입입니다.' }); + } + + workIssueModel.getCategoriesByType(type, (err, categories) => { + if (err) { + console.error('카테고리 조회 실패:', err); + return res.status(500).json({ success: false, error: '카테고리 조회 실패' }); + } + res.json({ success: true, data: categories }); + }); +}; + +/** + * 카테고리 생성 + */ +exports.createCategory = (req, res) => { + const { category_type, category_name, description, display_order } = req.body; + + if (!category_type || !category_name) { + return res.status(400).json({ success: false, error: '카테고리 타입과 이름은 필수입니다.' }); + } + + workIssueModel.createCategory( + { category_type, category_name, description, display_order }, + (err, categoryId) => { + if (err) { + console.error('카테고리 생성 실패:', err); + return res.status(500).json({ success: false, error: '카테고리 생성 실패' }); + } + res.status(201).json({ + success: true, + message: '카테고리가 생성되었습니다.', + data: { category_id: categoryId } + }); + } + ); +}; + +/** + * 카테고리 수정 + */ +exports.updateCategory = (req, res) => { + const { id } = req.params; + const { category_name, description, display_order, is_active } = req.body; + + workIssueModel.updateCategory( + id, + { category_name, description, display_order, is_active }, + (err, result) => { + if (err) { + console.error('카테고리 수정 실패:', err); + return res.status(500).json({ success: false, error: '카테고리 수정 실패' }); + } + res.json({ success: true, message: '카테고리가 수정되었습니다.' }); + } + ); +}; + +/** + * 카테고리 삭제 + */ +exports.deleteCategory = (req, res) => { + const { id } = req.params; + + workIssueModel.deleteCategory(id, (err, result) => { + if (err) { + console.error('카테고리 삭제 실패:', err); + return res.status(500).json({ success: false, error: '카테고리 삭제 실패' }); + } + res.json({ success: true, message: '카테고리가 삭제되었습니다.' }); + }); +}; + +// ==================== 사전 정의 항목 관리 ==================== + +/** + * 카테고리별 항목 조회 + */ +exports.getItemsByCategory = (req, res) => { + const { categoryId } = req.params; + + workIssueModel.getItemsByCategory(categoryId, (err, items) => { + if (err) { + console.error('항목 조회 실패:', err); + return res.status(500).json({ success: false, error: '항목 조회 실패' }); + } + res.json({ success: true, data: items }); + }); +}; + +/** + * 모든 항목 조회 + */ +exports.getAllItems = (req, res) => { + workIssueModel.getAllItems((err, items) => { + if (err) { + console.error('항목 조회 실패:', err); + return res.status(500).json({ success: false, error: '항목 조회 실패' }); + } + res.json({ success: true, data: items }); + }); +}; + +/** + * 항목 생성 + */ +exports.createItem = (req, res) => { + const { category_id, item_name, description, severity, display_order } = req.body; + + if (!category_id || !item_name) { + return res.status(400).json({ success: false, error: '카테고리 ID와 항목명은 필수입니다.' }); + } + + workIssueModel.createItem( + { category_id, item_name, description, severity, display_order }, + (err, itemId) => { + if (err) { + console.error('항목 생성 실패:', err); + return res.status(500).json({ success: false, error: '항목 생성 실패' }); + } + res.status(201).json({ + success: true, + message: '항목이 생성되었습니다.', + data: { item_id: itemId } + }); + } + ); +}; + +/** + * 항목 수정 + */ +exports.updateItem = (req, res) => { + const { id } = req.params; + const { item_name, description, severity, display_order, is_active } = req.body; + + workIssueModel.updateItem( + id, + { item_name, description, severity, display_order, is_active }, + (err, result) => { + if (err) { + console.error('항목 수정 실패:', err); + return res.status(500).json({ success: false, error: '항목 수정 실패' }); + } + res.json({ success: true, message: '항목이 수정되었습니다.' }); + } + ); +}; + +/** + * 항목 삭제 + */ +exports.deleteItem = (req, res) => { + const { id } = req.params; + + workIssueModel.deleteItem(id, (err, result) => { + if (err) { + console.error('항목 삭제 실패:', err); + return res.status(500).json({ success: false, error: '항목 삭제 실패' }); + } + res.json({ success: true, message: '항목이 삭제되었습니다.' }); + }); +}; + +// ==================== 문제 신고 관리 ==================== + +/** + * 신고 생성 + */ +exports.createReport = async (req, res) => { + try { + const { + factory_category_id, + workplace_id, + custom_location, + tbm_session_id, + visit_request_id, + issue_category_id, + issue_item_id, + custom_item_name, // 직접 입력한 항목명 + additional_description, + photos = [] + } = req.body; + + const reporter_id = req.user.user_id; + + if (!issue_category_id) { + return res.status(400).json({ success: false, error: '신고 카테고리는 필수입니다.' }); + } + + // 위치 정보 검증 (지도 선택 또는 기타 위치) + if (!factory_category_id && !custom_location) { + return res.status(400).json({ success: false, error: '위치 정보는 필수입니다.' }); + } + + // 항목 검증 (기존 항목 또는 직접 입력) + if (!issue_item_id && !custom_item_name) { + return res.status(400).json({ success: false, error: '신고 항목은 필수입니다.' }); + } + + // 직접 입력한 항목이 있으면 DB에 저장 + let finalItemId = issue_item_id; + if (custom_item_name && !issue_item_id) { + try { + finalItemId = await new Promise((resolve, reject) => { + workIssueModel.createItem( + { + category_id: issue_category_id, + item_name: custom_item_name, + description: '사용자 직접 입력', + severity: 'medium', + display_order: 999 // 마지막에 표시 + }, + (err, itemId) => { + if (err) reject(err); + else resolve(itemId); + } + ); + }); + } catch (itemErr) { + console.error('커스텀 항목 생성 실패:', itemErr); + return res.status(500).json({ success: false, error: '항목 저장 실패' }); + } + } + + // 사진 저장 (최대 5장) + const photoPaths = { + photo_path1: null, + photo_path2: null, + photo_path3: null, + photo_path4: null, + photo_path5: null + }; + + for (let i = 0; i < Math.min(photos.length, 5); i++) { + if (photos[i]) { + const savedPath = await imageUploadService.saveBase64Image(photos[i], 'issue'); + if (savedPath) { + photoPaths[`photo_path${i + 1}`] = savedPath; + } + } + } + + const reportData = { + reporter_id, + factory_category_id: factory_category_id || null, + workplace_id: workplace_id || null, + custom_location: custom_location || null, + tbm_session_id: tbm_session_id || null, + visit_request_id: visit_request_id || null, + issue_category_id, + issue_item_id: finalItemId || null, + additional_description: additional_description || null, + ...photoPaths + }; + + workIssueModel.createReport(reportData, (err, reportId) => { + if (err) { + console.error('신고 생성 실패:', err); + return res.status(500).json({ success: false, error: '신고 생성 실패' }); + } + res.status(201).json({ + success: true, + message: '문제 신고가 등록되었습니다.', + data: { report_id: reportId } + }); + }); + } catch (error) { + console.error('신고 생성 에러:', error); + res.status(500).json({ success: false, error: '서버 오류가 발생했습니다.' }); + } +}; + +/** + * 신고 목록 조회 + */ +exports.getAllReports = (req, res) => { + const filters = { + status: req.query.status, + category_type: req.query.category_type, + issue_category_id: req.query.issue_category_id, + factory_category_id: req.query.factory_category_id, + workplace_id: req.query.workplace_id, + assigned_user_id: req.query.assigned_user_id, + start_date: req.query.start_date, + end_date: req.query.end_date, + search: req.query.search, + limit: req.query.limit, + offset: req.query.offset + }; + + // 일반 사용자는 자신의 신고만 조회 (관리자 제외) + const userLevel = req.user.access_level; + if (!['admin', 'system', 'support_team'].includes(userLevel)) { + filters.reporter_id = req.user.user_id; + } + + workIssueModel.getAllReports(filters, (err, reports) => { + if (err) { + console.error('신고 목록 조회 실패:', err); + return res.status(500).json({ success: false, error: '신고 목록 조회 실패' }); + } + res.json({ success: true, data: reports }); + }); +}; + +/** + * 신고 상세 조회 + */ +exports.getReportById = (req, res) => { + const { id } = req.params; + + workIssueModel.getReportById(id, (err, report) => { + if (err) { + console.error('신고 상세 조회 실패:', err); + return res.status(500).json({ success: false, error: '신고 상세 조회 실패' }); + } + + if (!report) { + return res.status(404).json({ success: false, error: '신고를 찾을 수 없습니다.' }); + } + + // 권한 확인: 본인, 담당자, 또는 관리자 + const userLevel = req.user.access_level; + const isOwner = report.reporter_id === req.user.user_id; + const isAssignee = report.assigned_user_id === req.user.user_id; + const isManager = ['admin', 'system', 'support_team'].includes(userLevel); + + if (!isOwner && !isAssignee && !isManager) { + return res.status(403).json({ success: false, error: '권한이 없습니다.' }); + } + + res.json({ success: true, data: report }); + }); +}; + +/** + * 신고 수정 + */ +exports.updateReport = async (req, res) => { + try { + const { id } = req.params; + + // 기존 신고 확인 + workIssueModel.getReportById(id, async (err, report) => { + if (err) { + console.error('신고 조회 실패:', err); + return res.status(500).json({ success: false, error: '신고 조회 실패' }); + } + + if (!report) { + return res.status(404).json({ success: false, error: '신고를 찾을 수 없습니다.' }); + } + + // 권한 확인 + const userLevel = req.user.access_level; + const isOwner = report.reporter_id === req.user.user_id; + const isManager = ['admin', 'system'].includes(userLevel); + + if (!isOwner && !isManager) { + return res.status(403).json({ success: false, error: '수정 권한이 없습니다.' }); + } + + // 상태 확인: reported 상태에서만 수정 가능 (관리자 제외) + if (!isManager && report.status !== 'reported') { + return res.status(400).json({ success: false, error: '이미 접수된 신고는 수정할 수 없습니다.' }); + } + + const { + factory_category_id, + workplace_id, + custom_location, + issue_category_id, + issue_item_id, + additional_description, + photos = [] + } = req.body; + + // 사진 업데이트 처리 + const photoPaths = {}; + for (let i = 0; i < Math.min(photos.length, 5); i++) { + if (photos[i]) { + // 기존 사진 삭제 + const oldPath = report[`photo_path${i + 1}`]; + if (oldPath) { + await imageUploadService.deleteFile(oldPath); + } + // 새 사진 저장 + const savedPath = await imageUploadService.saveBase64Image(photos[i], 'issue'); + if (savedPath) { + photoPaths[`photo_path${i + 1}`] = savedPath; + } + } + } + + const updateData = { + factory_category_id, + workplace_id, + custom_location, + issue_category_id, + issue_item_id, + additional_description, + ...photoPaths + }; + + workIssueModel.updateReport(id, updateData, req.user.user_id, (updateErr, result) => { + if (updateErr) { + console.error('신고 수정 실패:', updateErr); + return res.status(500).json({ success: false, error: '신고 수정 실패' }); + } + res.json({ success: true, message: '신고가 수정되었습니다.' }); + }); + }); + } catch (error) { + console.error('신고 수정 에러:', error); + res.status(500).json({ success: false, error: '서버 오류가 발생했습니다.' }); + } +}; + +/** + * 신고 삭제 + */ +exports.deleteReport = async (req, res) => { + const { id } = req.params; + + workIssueModel.getReportById(id, async (err, report) => { + if (err) { + console.error('신고 조회 실패:', err); + return res.status(500).json({ success: false, error: '신고 조회 실패' }); + } + + if (!report) { + return res.status(404).json({ success: false, error: '신고를 찾을 수 없습니다.' }); + } + + // 권한 확인 + const userLevel = req.user.access_level; + const isOwner = report.reporter_id === req.user.user_id; + const isManager = ['admin', 'system'].includes(userLevel); + + if (!isOwner && !isManager) { + return res.status(403).json({ success: false, error: '삭제 권한이 없습니다.' }); + } + + workIssueModel.deleteReport(id, async (deleteErr, { result, photos }) => { + if (deleteErr) { + console.error('신고 삭제 실패:', deleteErr); + return res.status(500).json({ success: false, error: '신고 삭제 실패' }); + } + + // 사진 파일 삭제 + if (photos) { + const allPhotos = [ + photos.photo_path1, photos.photo_path2, photos.photo_path3, + photos.photo_path4, photos.photo_path5, + photos.resolution_photo_path1, photos.resolution_photo_path2 + ].filter(Boolean); + await imageUploadService.deleteMultipleFiles(allPhotos); + } + + res.json({ success: true, message: '신고가 삭제되었습니다.' }); + }); + }); +}; + +// ==================== 상태 관리 ==================== + +/** + * 신고 접수 + */ +exports.receiveReport = (req, res) => { + const { id } = req.params; + + workIssueModel.receiveReport(id, req.user.user_id, (err, result) => { + if (err) { + console.error('신고 접수 실패:', err); + return res.status(400).json({ success: false, error: err.message || '신고 접수 실패' }); + } + res.json({ success: true, message: '신고가 접수되었습니다.' }); + }); +}; + +/** + * 담당자 배정 + */ +exports.assignReport = (req, res) => { + const { id } = req.params; + const { assigned_department, assigned_user_id } = req.body; + + if (!assigned_user_id) { + return res.status(400).json({ success: false, error: '담당자는 필수입니다.' }); + } + + workIssueModel.assignReport(id, { + assigned_department, + assigned_user_id, + assigned_by: req.user.user_id + }, (err, result) => { + if (err) { + console.error('담당자 배정 실패:', err); + return res.status(400).json({ success: false, error: err.message || '담당자 배정 실패' }); + } + res.json({ success: true, message: '담당자가 배정되었습니다.' }); + }); +}; + +/** + * 처리 시작 + */ +exports.startProcessing = (req, res) => { + const { id } = req.params; + + workIssueModel.startProcessing(id, req.user.user_id, (err, result) => { + if (err) { + console.error('처리 시작 실패:', err); + return res.status(400).json({ success: false, error: err.message || '처리 시작 실패' }); + } + res.json({ success: true, message: '처리가 시작되었습니다.' }); + }); +}; + +/** + * 처리 완료 + */ +exports.completeReport = async (req, res) => { + try { + const { id } = req.params; + const { resolution_notes, resolution_photos = [] } = req.body; + + // 완료 사진 저장 + let resolution_photo_path1 = null; + let resolution_photo_path2 = null; + + if (resolution_photos[0]) { + resolution_photo_path1 = await imageUploadService.saveBase64Image(resolution_photos[0], 'resolution'); + } + if (resolution_photos[1]) { + resolution_photo_path2 = await imageUploadService.saveBase64Image(resolution_photos[1], 'resolution'); + } + + workIssueModel.completeReport(id, { + resolution_notes, + resolution_photo_path1, + resolution_photo_path2, + resolved_by: req.user.user_id + }, (err, result) => { + if (err) { + console.error('처리 완료 실패:', err); + return res.status(400).json({ success: false, error: err.message || '처리 완료 실패' }); + } + res.json({ success: true, message: '처리가 완료되었습니다.' }); + }); + } catch (error) { + console.error('처리 완료 에러:', error); + res.status(500).json({ success: false, error: '서버 오류가 발생했습니다.' }); + } +}; + +/** + * 신고 종료 + */ +exports.closeReport = (req, res) => { + const { id } = req.params; + + workIssueModel.closeReport(id, req.user.user_id, (err, result) => { + if (err) { + console.error('신고 종료 실패:', err); + return res.status(400).json({ success: false, error: err.message || '신고 종료 실패' }); + } + res.json({ success: true, message: '신고가 종료되었습니다.' }); + }); +}; + +/** + * 상태 변경 이력 조회 + */ +exports.getStatusLogs = (req, res) => { + const { id } = req.params; + + workIssueModel.getStatusLogs(id, (err, logs) => { + if (err) { + console.error('상태 이력 조회 실패:', err); + return res.status(500).json({ success: false, error: '상태 이력 조회 실패' }); + } + res.json({ success: true, data: logs }); + }); +}; + +// ==================== 통계 ==================== + +/** + * 통계 요약 + */ +exports.getStatsSummary = (req, res) => { + const filters = { + start_date: req.query.start_date, + end_date: req.query.end_date, + factory_category_id: req.query.factory_category_id + }; + + workIssueModel.getStatsSummary(filters, (err, stats) => { + if (err) { + console.error('통계 조회 실패:', err); + return res.status(500).json({ success: false, error: '통계 조회 실패' }); + } + res.json({ success: true, data: stats }); + }); +}; + +/** + * 카테고리별 통계 + */ +exports.getStatsByCategory = (req, res) => { + const filters = { + start_date: req.query.start_date, + end_date: req.query.end_date + }; + + workIssueModel.getStatsByCategory(filters, (err, stats) => { + if (err) { + console.error('카테고리별 통계 조회 실패:', err); + return res.status(500).json({ success: false, error: '통계 조회 실패' }); + } + res.json({ success: true, data: stats }); + }); +}; + +/** + * 작업장별 통계 + */ +exports.getStatsByWorkplace = (req, res) => { + const filters = { + start_date: req.query.start_date, + end_date: req.query.end_date, + factory_category_id: req.query.factory_category_id + }; + + workIssueModel.getStatsByWorkplace(filters, (err, stats) => { + if (err) { + console.error('작업장별 통계 조회 실패:', err); + return res.status(500).json({ success: false, error: '통계 조회 실패' }); + } + res.json({ success: true, data: stats }); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/workReportAnalysisController.js b/deploy/tkfb-package/api.hyungi.net/controllers/workReportAnalysisController.js new file mode 100644 index 0000000..2e376ac --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/workReportAnalysisController.js @@ -0,0 +1,429 @@ +/** + * 데일리 워크 레포트 분석 컨트롤러 + * + * 작업 보고서 종합 분석 API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const { getDb } = require('../dbPool'); +const { ValidationError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); + +/** + * 분석용 필터 데이터 조회 (프로젝트, 작업자, 작업유형 목록) + */ +const getAnalysisFilters = asyncHandler(async (req, res) => { + logger.info('분석 필터 데이터 조회 요청'); + + const db = await getDb(); + + try { + // 프로젝트 목록 + const [projects] = await db.query(` + SELECT DISTINCT p.project_id, p.project_name + FROM projects p + INNER JOIN daily_work_reports dwr ON p.project_id = dwr.project_id + ORDER BY p.project_name + `); + + // 작업자 목록 + const [workers] = await db.query(` + SELECT DISTINCT w.worker_id, w.worker_name + FROM workers w + INNER JOIN daily_work_reports dwr ON w.worker_id = dwr.worker_id + ORDER BY w.worker_name + `); + + // 작업 유형 목록 + const [workTypes] = await db.query(` + SELECT DISTINCT wt.id as work_type_id, wt.name as work_type_name + FROM work_types wt + INNER JOIN daily_work_reports dwr ON wt.id = dwr.work_type_id + ORDER BY wt.name + `); + + // 날짜 범위 + const [dateRange] = await db.query(` + SELECT + MIN(report_date) as min_date, + MAX(report_date) as max_date + FROM daily_work_reports + `); + + logger.info('분석 필터 데이터 조회 성공', { + projects: projects.length, + workers: workers.length, + workTypes: workTypes.length + }); + + res.json({ + success: true, + data: { + projects, + workers, + workTypes, + dateRange: dateRange[0] + }, + message: '분석 필터 데이터 조회 성공' + }); + } catch (error) { + logger.error('분석 필터 데이터 조회 실패', { error: error.message }); + throw new DatabaseError('필터 데이터 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 기간별 작업 분석 데이터 조회 + */ +const getAnalyticsByPeriod = asyncHandler(async (req, res) => { + const { start_date, end_date, project_id, worker_id } = req.query; + + if (!start_date || !end_date) { + throw new ValidationError('start_date와 end_date가 필요합니다', { + required: ['start_date', 'end_date'], + received: { start_date, end_date }, + example: 'start_date=2025-08-01&end_date=2025-08-31' + }); + } + + logger.info('기간별 분석 데이터 조회 요청', { + start_date, + end_date, + project_id, + worker_id + }); + + const db = await getDb(); + + try { + // 기본 조건 + let whereConditions = ['dwr.report_date BETWEEN ? AND ?']; + let queryParams = [start_date, end_date]; + + if (project_id) { + whereConditions.push('dwr.project_id = ?'); + queryParams.push(project_id); + } + + if (worker_id) { + whereConditions.push('dwr.worker_id = ?'); + queryParams.push(worker_id); + } + + const whereClause = whereConditions.join(' AND '); + + // 1. 전체 요약 통계 + const overallSql = ` + SELECT + COUNT(*) as total_entries, + SUM(dwr.work_hours) as total_hours, + COUNT(DISTINCT dwr.worker_id) as unique_workers, + COUNT(DISTINCT dwr.project_id) as unique_projects, + COUNT(DISTINCT dwr.report_date) as working_days, + AVG(dwr.work_hours) as avg_hours_per_entry, + COUNT(DISTINCT dwr.created_by) as contributors, + COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_entries, + ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate + FROM daily_work_reports dwr + WHERE ${whereClause} + `; + + const [overallStats] = await db.query(overallSql, queryParams); + + // 2. 일별 통계 + const dailyStatsSql = ` + SELECT + dwr.report_date, + SUM(dwr.work_hours) as daily_hours, + COUNT(*) as daily_entries, + COUNT(DISTINCT dwr.worker_id) as daily_workers + FROM daily_work_reports dwr + WHERE ${whereClause} + GROUP BY dwr.report_date + ORDER BY dwr.report_date ASC + `; + + const [dailyStats] = await db.query(dailyStatsSql, queryParams); + + // 3. 일별 에러 통계 + const dailyErrorStatsSql = ` + SELECT + dwr.report_date, + COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as daily_errors, + COUNT(*) as daily_total, + ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as daily_error_rate + FROM daily_work_reports dwr + WHERE ${whereClause} + GROUP BY dwr.report_date + ORDER BY dwr.report_date ASC + `; + + const [dailyErrorStats] = await db.query(dailyErrorStatsSql, queryParams); + + // 4. 에러 유형별 분석 + const errorAnalysisSql = ` + SELECT + et.id as error_type_id, + et.name as error_type_name, + COUNT(*) as error_count, + SUM(dwr.work_hours) as error_hours, + ROUND((COUNT(*) / (SELECT COUNT(*) FROM daily_work_reports WHERE error_type_id IS NOT NULL)) * 100, 2) as error_percentage + FROM daily_work_reports dwr + LEFT JOIN error_types et ON dwr.error_type_id = et.id + WHERE ${whereClause} AND dwr.error_type_id IS NOT NULL + GROUP BY et.id, et.name + ORDER BY error_count DESC + `; + + const [errorAnalysis] = await db.query(errorAnalysisSql, queryParams); + + // 5. 작업 유형별 분석 + const workTypeAnalysisSql = ` + SELECT + wt.id as work_type_id, + wt.name as work_type_name, + COUNT(*) as work_count, + SUM(dwr.work_hours) as total_hours, + AVG(dwr.work_hours) as avg_hours, + COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_count, + ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate + FROM daily_work_reports dwr + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + WHERE ${whereClause} + GROUP BY wt.id, wt.name + ORDER BY total_hours DESC + `; + + const [workTypeAnalysis] = await db.query(workTypeAnalysisSql, queryParams); + + // 6. 작업자별 성과 분석 + const workerAnalysisSql = ` + SELECT + w.worker_id, + w.worker_name, + COUNT(*) as total_entries, + SUM(dwr.work_hours) as total_hours, + AVG(dwr.work_hours) as avg_hours_per_entry, + COUNT(DISTINCT dwr.project_id) as projects_worked, + COUNT(DISTINCT dwr.report_date) as working_days, + COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_count, + ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE ${whereClause} + GROUP BY w.worker_id, w.worker_name + ORDER BY total_hours DESC + `; + + const [workerAnalysis] = await db.query(workerAnalysisSql, queryParams); + + // 7. 프로젝트별 분석 + const projectAnalysisSql = ` + SELECT + p.project_id, + p.project_name, + COUNT(*) as total_entries, + SUM(dwr.work_hours) as total_hours, + COUNT(DISTINCT dwr.worker_id) as workers_count, + COUNT(DISTINCT dwr.report_date) as working_days, + AVG(dwr.work_hours) as avg_hours_per_entry, + COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) as error_count, + ROUND((COUNT(CASE WHEN dwr.error_type_id IS NOT NULL THEN 1 END) / COUNT(*)) * 100, 2) as error_rate + FROM daily_work_reports dwr + LEFT JOIN projects p ON dwr.project_id = p.project_id + WHERE ${whereClause} + GROUP BY p.project_id, p.project_name + ORDER BY total_hours DESC + `; + + const [projectAnalysis] = await db.query(projectAnalysisSql, queryParams); + + logger.info('기간별 분석 데이터 조회 성공', { + start_date, + end_date, + total_entries: overallStats[0].total_entries, + total_hours: overallStats[0].total_hours + }); + + res.json({ + success: true, + data: { + summary: overallStats[0], + dailyStats, + dailyErrorStats, + errorAnalysis, + workTypeAnalysis, + workerAnalysis, + projectAnalysis, + period: { start_date, end_date }, + filters: { project_id, worker_id } + }, + message: '기간별 분석 데이터 조회 성공' + }); + } catch (error) { + logger.error('기간별 분석 데이터 조회 실패', { + start_date, + end_date, + error: error.message + }); + throw new DatabaseError('기간별 분석 데이터 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 프로젝트별 상세 분석 + */ +const getProjectAnalysis = asyncHandler(async (req, res) => { + const { start_date, end_date, project_id } = req.query; + + if (!start_date || !end_date) { + throw new ValidationError('start_date와 end_date가 필요합니다', { + required: ['start_date', 'end_date'], + received: { start_date, end_date } + }); + } + + logger.info('프로젝트별 분석 조회 요청', { + start_date, + end_date, + project_id + }); + + const db = await getDb(); + + try { + let whereConditions = ['dwr.report_date BETWEEN ? AND ?']; + let queryParams = [start_date, end_date]; + + if (project_id) { + whereConditions.push('dwr.project_id = ?'); + queryParams.push(project_id); + } + + const whereClause = whereConditions.join(' AND '); + + const projectStatsSql = ` + SELECT + dwr.project_id, + p.project_name, + SUM(dwr.work_hours) as total_hours, + COUNT(*) as total_entries, + COUNT(DISTINCT dwr.worker_id) as workers_count, + COUNT(DISTINCT dwr.report_date) as working_days, + AVG(dwr.work_hours) as avg_hours_per_entry + FROM daily_work_reports dwr + LEFT JOIN projects p ON dwr.project_id = p.project_id + WHERE ${whereClause} + GROUP BY dwr.project_id + ORDER BY total_hours DESC + `; + + const [projectStats] = await db.query(projectStatsSql, queryParams); + + logger.info('프로젝트별 분석 조회 성공', { + start_date, + end_date, + projectCount: projectStats.length + }); + + res.json({ + success: true, + data: { + projectStats, + period: { start_date, end_date } + }, + message: '프로젝트별 분석 조회 성공' + }); + } catch (error) { + logger.error('프로젝트별 분석 조회 실패', { + start_date, + end_date, + error: error.message + }); + throw new DatabaseError('프로젝트별 분석 데이터 조회 중 오류가 발생했습니다'); + } +}); + +/** + * 작업자별 상세 분석 + */ +const getWorkerAnalysis = asyncHandler(async (req, res) => { + const { start_date, end_date, worker_id } = req.query; + + if (!start_date || !end_date) { + throw new ValidationError('start_date와 end_date가 필요합니다', { + required: ['start_date', 'end_date'], + received: { start_date, end_date } + }); + } + + logger.info('작업자별 분석 조회 요청', { + start_date, + end_date, + worker_id + }); + + const db = await getDb(); + + try { + let whereConditions = ['dwr.report_date BETWEEN ? AND ?']; + let queryParams = [start_date, end_date]; + + if (worker_id) { + whereConditions.push('dwr.worker_id = ?'); + queryParams.push(worker_id); + } + + const whereClause = whereConditions.join(' AND '); + + const workerStatsSql = ` + SELECT + dwr.worker_id, + w.worker_name, + SUM(dwr.work_hours) as total_hours, + COUNT(*) as total_entries, + COUNT(DISTINCT dwr.project_id) as projects_worked, + COUNT(DISTINCT dwr.report_date) as working_days, + AVG(dwr.work_hours) as avg_hours_per_entry + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE ${whereClause} + GROUP BY dwr.worker_id + ORDER BY total_hours DESC + `; + + const [workerStats] = await db.query(workerStatsSql, queryParams); + + logger.info('작업자별 분석 조회 성공', { + start_date, + end_date, + workerCount: workerStats.length + }); + + res.json({ + success: true, + data: { + workerStats, + period: { start_date, end_date } + }, + message: '작업자별 분석 조회 성공' + }); + } catch (error) { + logger.error('작업자별 분석 조회 실패', { + start_date, + end_date, + error: error.message + }); + throw new DatabaseError('작업자별 분석 데이터 조회 중 오류가 발생했습니다'); + } +}); + +module.exports = { + getAnalysisFilters, + getAnalyticsByPeriod, + getProjectAnalysis, + getWorkerAnalysis +}; diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/workReportController.js b/deploy/tkfb-package/api.hyungi.net/controllers/workReportController.js new file mode 100644 index 0000000..2b3d555 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/workReportController.js @@ -0,0 +1,175 @@ +/** + * 작업 보고서 관리 컨트롤러 + * + * 작업 보고서 CRUD API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const workReportService = require('../services/workReportService'); +const { asyncHandler } = require('../middlewares/errorHandler'); + +/** + * 작업 보고서 생성 (단일 또는 다중) + */ +exports.createWorkReport = asyncHandler(async (req, res) => { + const result = await workReportService.createWorkReportService(req.body); + + res.json({ + success: true, + data: result, + message: '작업 보고서가 성공적으로 생성되었습니다' + }); +}); + +/** + * 날짜별 작업 보고서 조회 + */ +exports.getWorkReportsByDate = asyncHandler(async (req, res) => { + const { date } = req.params; + const rows = await workReportService.getWorkReportsByDateService(date); + + res.json({ + success: true, + data: rows, + message: '작업 보고서 조회 성공' + }); +}); + +/** + * 기간별 작업 보고서 조회 + */ +exports.getWorkReportsInRange = asyncHandler(async (req, res) => { + const { start, end } = req.query; + const rows = await workReportService.getWorkReportsInRangeService(start, end); + + res.json({ + success: true, + data: rows, + message: '작업 보고서 조회 성공' + }); +}); + +/** + * 단일 작업 보고서 조회 + */ +exports.getWorkReportById = asyncHandler(async (req, res) => { + const { id } = req.params; + const row = await workReportService.getWorkReportByIdService(id); + + res.json({ + success: true, + data: row, + message: '작업 보고서 조회 성공' + }); +}); + +/** + * 작업 보고서 수정 + */ +exports.updateWorkReport = asyncHandler(async (req, res) => { + const { id } = req.params; + const result = await workReportService.updateWorkReportService(id, req.body); + + res.json({ + success: true, + data: result, + message: '작업 보고서가 성공적으로 수정되었습니다' + }); +}); + +/** + * 작업 보고서 삭제 + */ +exports.removeWorkReport = asyncHandler(async (req, res) => { + const { id } = req.params; + const result = await workReportService.removeWorkReportService(id); + + res.json({ + success: true, + data: result, + message: '작업 보고서가 성공적으로 삭제되었습니다' + }); +}); + +/** + * 월간 요약 조회 + */ +exports.getSummary = asyncHandler(async (req, res) => { + const { year, month } = req.query; + const rows = await workReportService.getSummaryService(year, month); + + res.json({ + success: true, + data: rows, + message: '월간 요약 조회 성공' + }); +}); + +// ========== 부적합 원인 관리 API ========== + +/** + * 작업 보고서의 부적합 원인 목록 조회 + */ +exports.getReportDefects = asyncHandler(async (req, res) => { + const { reportId } = req.params; + const rows = await workReportService.getReportDefectsService(reportId); + + res.json({ + success: true, + data: rows, + message: '부적합 원인 조회 성공' + }); +}); + +/** + * 부적합 원인 저장 (전체 교체) + * 기존 부적합 원인을 모두 삭제하고 새로 저장 + */ +exports.saveReportDefects = asyncHandler(async (req, res) => { + const { reportId } = req.params; + const { defects } = req.body; // [{ error_type_id, defect_hours, note }] + + const result = await workReportService.saveReportDefectsService(reportId, defects); + + res.json({ + success: true, + data: result, + message: '부적합 원인이 저장되었습니다' + }); +}); + +/** + * 부적합 원인 추가 (단일) + */ +exports.addReportDefect = asyncHandler(async (req, res) => { + const { reportId } = req.params; + const { error_type_id, defect_hours, note } = req.body; + + const result = await workReportService.addReportDefectService(reportId, { + error_type_id, + defect_hours, + note + }); + + res.json({ + success: true, + data: result, + message: '부적합 원인이 추가되었습니다' + }); +}); + +/** + * 부적합 원인 삭제 + */ +exports.removeReportDefect = asyncHandler(async (req, res) => { + const { defectId } = req.params; + const result = await workReportService.removeReportDefectService(defectId); + + res.json({ + success: true, + data: result, + message: '부적합 원인이 삭제되었습니다' + }); +}); diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/workerController.js b/deploy/tkfb-package/api.hyungi.net/controllers/workerController.js new file mode 100644 index 0000000..27ed407 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/workerController.js @@ -0,0 +1,278 @@ +/** + * 작업자 관리 컨트롤러 + * + * 작업자 CRUD API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const workerModel = require('../models/workerModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); +const cache = require('../utils/cache'); +const { optimizedQueries } = require('../utils/queryOptimizer'); +const { hangulToRoman, generateUniqueUsername } = require('../utils/hangulToRoman'); +const bcrypt = require('bcrypt'); +const { getDb } = require('../dbPool'); + +/** + * 작업자 생성 + */ +exports.createWorker = asyncHandler(async (req, res) => { + const workerData = req.body; + const createAccount = req.body.create_account; + + logger.info('작업자 생성 요청', { name: workerData.worker_name, create_account: createAccount }); + + const lastID = await workerModel.create(workerData); + + // 계정 생성 요청이 있으면 users 테이블에 계정 생성 + if (createAccount && workerData.worker_name) { + try { + const db = await getDb(); + const username = await generateUniqueUsername(workerData.worker_name, db); + const hashedPassword = await bcrypt.hash('1234', 10); + + // User 역할 조회 + const [userRole] = await db.query('SELECT id FROM roles WHERE name = ?', ['User']); + + if (userRole && userRole.length > 0) { + await db.query( + `INSERT INTO users (username, password, name, worker_id, role_id, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, NOW(), NOW())`, + [username, hashedPassword, workerData.worker_name, lastID, userRole[0].id] + ); + + logger.info('작업자 계정 자동 생성 성공', { worker_id: lastID, username }); + } + } catch (accountError) { + logger.error('계정 생성 실패 (작업자는 생성됨)', { worker_id: lastID, error: accountError.message }); + } + } + + // 작업자 관련 캐시 무효화 + await cache.invalidateCache.worker(); + + logger.info('작업자 생성 성공', { worker_id: lastID }); + + res.status(201).json({ + success: true, + data: { worker_id: lastID }, + message: '작업자가 성공적으로 생성되었습니다' + }); +}); + +/** + * 전체 작업자 조회 (캐싱 및 페이지네이션 적용) + */ +exports.getAllWorkers = asyncHandler(async (req, res) => { + const { page = 1, limit = 100, search = '', status = '', department_id = null } = req.query; + + const cacheKey = cache.createKey('workers', 'list', page, limit, search, status, department_id); + + // 캐시에서 조회 + const cachedData = await cache.get(cacheKey); + if (cachedData) { + logger.debug('캐시 히트', { cacheKey }); + return res.json({ + success: true, + data: cachedData.data, + pagination: cachedData.pagination, + message: '작업자 목록 조회 성공 (캐시)' + }); + } + + // 최적화된 쿼리 사용 + const result = await optimizedQueries.getWorkersPaged(page, limit, search, status, department_id); + + // 캐시에 저장 (5분) + await cache.set(cacheKey, result, cache.TTL.MEDIUM); + logger.debug('캐시 저장', { cacheKey }); + + res.json({ + success: true, + data: result.data, + pagination: result.pagination, + message: '작업자 목록 조회 성공' + }); +}); + +/** + * 단일 작업자 조회 + */ +exports.getWorkerById = asyncHandler(async (req, res) => { + const id = parseInt(req.params.worker_id, 10); + + if (isNaN(id)) { + throw new ValidationError('유효하지 않은 작업자 ID입니다'); + } + + const row = await workerModel.getById(id); + + if (!row) { + throw new NotFoundError('작업자를 찾을 수 없습니다'); + } + + res.json({ + success: true, + data: row, + message: '작업자 조회 성공' + }); +}); + +/** + * 작업자 수정 + */ +exports.updateWorker = asyncHandler(async (req, res) => { + const id = parseInt(req.params.worker_id, 10); + + if (isNaN(id)) { + throw new ValidationError('유효하지 않은 작업자 ID입니다'); + } + + const workerData = { ...req.body, worker_id: id }; + const createAccount = req.body.create_account; + + console.log('🔧 작업자 수정 요청:', { + worker_id: id, + 받은데이터: req.body, + 처리할데이터: workerData, + create_account: createAccount + }); + + // 먼저 현재 작업자 정보 조회 (계정 여부 확인용) + const currentWorker = await workerModel.getById(id); + + if (!currentWorker) { + throw new NotFoundError('작업자를 찾을 수 없습니다'); + } + + // 작업자 정보 업데이트 + const changes = await workerModel.update(workerData); + + // 계정 생성/해제 처리 + const db = await getDb(); + const hasAccount = currentWorker.user_id !== null && currentWorker.user_id !== undefined; + let accountAction = null; + let accountUsername = null; + + console.log('🔍 계정 생성 체크:', { + createAccount, + hasAccount, + currentWorker_user_id: currentWorker.user_id, + worker_name: workerData.worker_name + }); + + if (createAccount && !hasAccount && workerData.worker_name) { + // 계정 생성 + console.log('✅ 계정 생성 로직 시작'); + try { + console.log('🔑 사용자명 생성 중...'); + const username = await generateUniqueUsername(workerData.worker_name, db); + console.log('🔑 생성된 사용자명:', username); + + const hashedPassword = await bcrypt.hash('1234', 10); + console.log('🔒 비밀번호 해싱 완료'); + + // User 역할 조회 + console.log('👤 User 역할 조회 중...'); + const [userRole] = await db.query('SELECT id FROM roles WHERE name = ?', ['User']); + console.log('👤 User 역할 조회 결과:', userRole); + + if (userRole && userRole.length > 0) { + console.log('💾 계정 DB 삽입 시작...'); + await db.query( + `INSERT INTO users (username, password, name, worker_id, role_id, created_at, updated_at) + VALUES (?, ?, ?, ?, ?, NOW(), NOW())`, + [username, hashedPassword, workerData.worker_name, id, userRole[0].id] + ); + console.log('✅ 계정 DB 삽입 완료'); + + accountAction = 'created'; + accountUsername = username; + logger.info('작업자 계정 생성 성공', { worker_id: id, username }); + } else { + console.log('❌ User 역할을 찾을 수 없음'); + } + } catch (accountError) { + console.error('❌ 계정 생성 오류:', accountError); + logger.error('계정 생성 실패', { worker_id: id, error: accountError.message }); + accountAction = 'failed'; + } + } else { + console.log('⏭️ 계정 생성 조건 불만족:', { createAccount, hasAccount, hasWorkerName: !!workerData.worker_name }); + } + + if (!createAccount && hasAccount) { + // 계정 연동 해제 (users.worker_id = NULL) + try { + await db.query('UPDATE users SET worker_id = NULL WHERE worker_id = ?', [id]); + accountAction = 'unlinked'; + logger.info('작업자 계정 연동 해제 성공', { worker_id: id }); + } catch (unlinkError) { + logger.error('계정 연동 해제 실패', { worker_id: id, error: unlinkError.message }); + accountAction = 'unlink_failed'; + } + } else if (createAccount && hasAccount) { + accountAction = 'already_exists'; + } + + // 작업자 관련 캐시 무효화 + logger.info('작업자 수정 후 캐시 무효화', { worker_id: id }); + await cache.invalidateCache.worker(); + + logger.info('작업자 수정 성공', { worker_id: id }); + + // 응답 메시지 구성 + let message = '작업자 정보가 성공적으로 수정되었습니다'; + if (accountAction === 'created') { + message += ` (계정 생성 완료: ${accountUsername}, 초기 비밀번호: 1234)`; + } else if (accountAction === 'unlinked') { + message += ' (계정 연동 해제 완료)'; + } else if (accountAction === 'already_exists') { + message += ' (이미 계정이 존재합니다)'; + } else if (accountAction === 'failed') { + message += ' (계정 생성 실패)'; + } + + res.json({ + success: true, + data: { + changes, + account_action: accountAction, + account_username: accountUsername + }, + message + }); +}); + +/** + * 작업자 삭제 + */ +exports.removeWorker = asyncHandler(async (req, res) => { + const id = parseInt(req.params.worker_id, 10); + + if (isNaN(id)) { + throw new ValidationError('유효하지 않은 작업자 ID입니다'); + } + + const changes = await workerModel.remove(id); + + if (changes === 0) { + throw new NotFoundError('작업자를 찾을 수 없습니다'); + } + + // 작업자 관련 캐시 무효화 + logger.info('작업자 삭제 후 캐시 무효화 시작', { worker_id: id }); + await cache.invalidateCache.worker(); + await cache.delPattern('workers:*'); + await cache.flush(); + logger.info('작업자 삭제 후 캐시 무효화 완료', { worker_id: id }); + + res.json({ + success: true, + message: '작업자가 성공적으로 삭제되었습니다' + }); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/controllers/workplaceController.js b/deploy/tkfb-package/api.hyungi.net/controllers/workplaceController.js new file mode 100644 index 0000000..b384529 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/controllers/workplaceController.js @@ -0,0 +1,575 @@ +/** + * 작업장 관리 컨트롤러 + * + * 작업장 카테고리(공장) 및 작업장 CRUD API 엔드포인트 핸들러 + * + * @author TK-FB-Project + * @since 2026-01-26 + */ + +const workplaceModel = require('../models/workplaceModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const { asyncHandler } = require('../middlewares/errorHandler'); +const logger = require('../utils/logger'); + +// ==================== 카테고리(공장) 관련 ==================== + +/** + * 카테고리 생성 + */ +exports.createCategory = asyncHandler(async (req, res) => { + const categoryData = req.body; + + if (!categoryData.category_name) { + throw new ValidationError('카테고리명은 필수 입력 항목입니다'); + } + + logger.info('카테고리 생성 요청', { name: categoryData.category_name }); + + const id = await new Promise((resolve, reject) => { + workplaceModel.createCategory(categoryData, (err, lastID) => { + if (err) reject(new DatabaseError('카테고리 생성 중 오류가 발생했습니다')); + else resolve(lastID); + }); + }); + + logger.info('카테고리 생성 성공', { category_id: id }); + + res.status(201).json({ + success: true, + data: { category_id: id }, + message: '카테고리가 성공적으로 생성되었습니다' + }); +}); + +/** + * 전체 카테고리 조회 + */ +exports.getAllCategories = asyncHandler(async (req, res) => { + const rows = await new Promise((resolve, reject) => { + workplaceModel.getAllCategories((err, data) => { + if (err) reject(new DatabaseError('카테고리 목록 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + res.json({ + success: true, + data: rows, + message: '카테고리 목록 조회 성공' + }); +}); + +/** + * 활성 카테고리만 조회 + */ +exports.getActiveCategories = asyncHandler(async (req, res) => { + const rows = await new Promise((resolve, reject) => { + workplaceModel.getActiveCategories((err, data) => { + if (err) reject(new DatabaseError('활성 카테고리 목록 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + res.json({ + success: true, + data: rows, + message: '활성 카테고리 목록 조회 성공' + }); +}); + +/** + * 단일 카테고리 조회 + */ +exports.getCategoryById = asyncHandler(async (req, res) => { + const categoryId = req.params.id; + + const category = await new Promise((resolve, reject) => { + workplaceModel.getCategoryById(categoryId, (err, data) => { + if (err) reject(new DatabaseError('카테고리 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + if (!category) { + throw new NotFoundError('카테고리를 찾을 수 없습니다'); + } + + res.json({ + success: true, + data: category, + message: '카테고리 조회 성공' + }); +}); + +/** + * 카테고리 수정 + */ +exports.updateCategory = asyncHandler(async (req, res) => { + const categoryId = req.params.id; + const categoryData = req.body; + + if (!categoryData.category_name) { + throw new ValidationError('카테고리명은 필수 입력 항목입니다'); + } + + logger.info('카테고리 수정 요청', { category_id: categoryId }); + + // 기존 카테고리 정보 가져오기 + const existingCategory = await new Promise((resolve, reject) => { + workplaceModel.getCategoryById(categoryId, (err, data) => { + if (err) reject(new DatabaseError('카테고리 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + if (!existingCategory) { + throw new NotFoundError('카테고리를 찾을 수 없습니다'); + } + + // layout_image가 요청에 없거나 null이면 기존 값 보존 + const updateData = { + ...categoryData, + layout_image: (categoryData.layout_image !== undefined && categoryData.layout_image !== null) + ? categoryData.layout_image + : existingCategory.layout_image + }; + + await new Promise((resolve, reject) => { + workplaceModel.updateCategory(categoryId, updateData, (err, result) => { + if (err) reject(new DatabaseError('카테고리 수정 중 오류가 발생했습니다')); + else resolve(result); + }); + }); + + logger.info('카테고리 수정 성공', { category_id: categoryId }); + + res.json({ + success: true, + message: '카테고리가 성공적으로 수정되었습니다' + }); +}); + +/** + * 카테고리 삭제 + */ +exports.deleteCategory = asyncHandler(async (req, res) => { + const categoryId = req.params.id; + + logger.info('카테고리 삭제 요청', { category_id: categoryId }); + + await new Promise((resolve, reject) => { + workplaceModel.deleteCategory(categoryId, (err, result) => { + if (err) reject(new DatabaseError('카테고리 삭제 중 오류가 발생했습니다')); + else resolve(result); + }); + }); + + logger.info('카테고리 삭제 성공', { category_id: categoryId }); + + res.json({ + success: true, + message: '카테고리가 성공적으로 삭제되었습니다' + }); +}); + +// ==================== 작업장 관련 ==================== + +/** + * 작업장 생성 + */ +exports.createWorkplace = asyncHandler(async (req, res) => { + const workplaceData = req.body; + + if (!workplaceData.workplace_name) { + throw new ValidationError('작업장명은 필수 입력 항목입니다'); + } + + logger.info('작업장 생성 요청', { name: workplaceData.workplace_name }); + + const id = await new Promise((resolve, reject) => { + workplaceModel.createWorkplace(workplaceData, (err, lastID) => { + if (err) reject(new DatabaseError('작업장 생성 중 오류가 발생했습니다')); + else resolve(lastID); + }); + }); + + logger.info('작업장 생성 성공', { workplace_id: id }); + + res.status(201).json({ + success: true, + data: { workplace_id: id }, + message: '작업장이 성공적으로 생성되었습니다' + }); +}); + +/** + * 전체 작업장 조회 + */ +exports.getAllWorkplaces = asyncHandler(async (req, res) => { + const categoryId = req.query.category_id; + + // 카테고리별 필터링 + if (categoryId) { + const rows = await new Promise((resolve, reject) => { + workplaceModel.getWorkplacesByCategory(categoryId, (err, data) => { + if (err) reject(new DatabaseError('작업장 목록 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + return res.json({ + success: true, + data: rows, + message: '작업장 목록 조회 성공' + }); + } + + // 전체 조회 + const rows = await new Promise((resolve, reject) => { + workplaceModel.getAllWorkplaces((err, data) => { + if (err) reject(new DatabaseError('작업장 목록 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + res.json({ + success: true, + data: rows, + message: '작업장 목록 조회 성공' + }); +}); + +/** + * 활성 작업장만 조회 + */ +exports.getActiveWorkplaces = asyncHandler(async (req, res) => { + const rows = await new Promise((resolve, reject) => { + workplaceModel.getActiveWorkplaces((err, data) => { + if (err) reject(new DatabaseError('활성 작업장 목록 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + res.json({ + success: true, + data: rows, + message: '활성 작업장 목록 조회 성공' + }); +}); + +/** + * 단일 작업장 조회 + */ +exports.getWorkplaceById = asyncHandler(async (req, res) => { + const workplaceId = req.params.id; + + const workplace = await new Promise((resolve, reject) => { + workplaceModel.getWorkplaceById(workplaceId, (err, data) => { + if (err) reject(new DatabaseError('작업장 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + if (!workplace) { + throw new NotFoundError('작업장을 찾을 수 없습니다'); + } + + res.json({ + success: true, + data: workplace, + message: '작업장 조회 성공' + }); +}); + +/** + * 작업장 수정 + */ +exports.updateWorkplace = asyncHandler(async (req, res) => { + const workplaceId = req.params.id; + const workplaceData = req.body; + + if (!workplaceData.workplace_name) { + throw new ValidationError('작업장명은 필수 입력 항목입니다'); + } + + logger.info('작업장 수정 요청', { workplace_id: workplaceId }); + + // 기존 작업장 정보 가져오기 + const existingWorkplace = await new Promise((resolve, reject) => { + workplaceModel.getWorkplaceById(workplaceId, (err, data) => { + if (err) reject(new DatabaseError('작업장 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + if (!existingWorkplace) { + throw new NotFoundError('작업장을 찾을 수 없습니다'); + } + + // layout_image가 요청에 없거나 null이면 기존 값 보존 + const updateData = { + ...workplaceData, + layout_image: (workplaceData.layout_image !== undefined && workplaceData.layout_image !== null) + ? workplaceData.layout_image + : existingWorkplace.layout_image + }; + + await new Promise((resolve, reject) => { + workplaceModel.updateWorkplace(workplaceId, updateData, (err, result) => { + if (err) reject(new DatabaseError('작업장 수정 중 오류가 발생했습니다')); + else resolve(result); + }); + }); + + logger.info('작업장 수정 성공', { workplace_id: workplaceId }); + + res.json({ + success: true, + message: '작업장이 성공적으로 수정되었습니다' + }); +}); + +/** + * 작업장 삭제 + */ +exports.deleteWorkplace = asyncHandler(async (req, res) => { + const workplaceId = req.params.id; + + logger.info('작업장 삭제 요청', { workplace_id: workplaceId }); + + await new Promise((resolve, reject) => { + workplaceModel.deleteWorkplace(workplaceId, (err, result) => { + if (err) reject(new DatabaseError('작업장 삭제 중 오류가 발생했습니다')); + else resolve(result); + }); + }); + + logger.info('작업장 삭제 성공', { workplace_id: workplaceId }); + + res.json({ + success: true, + message: '작업장이 성공적으로 삭제되었습니다' + }); +}); + +// ==================== 작업장 지도 영역 관련 ==================== + +/** + * 카테고리 레이아웃 이미지 업로드 + */ +exports.uploadCategoryLayoutImage = asyncHandler(async (req, res) => { + const categoryId = req.params.id; + + if (!req.file) { + throw new ValidationError('이미지 파일이 필요합니다'); + } + + const imagePath = `/uploads/${req.file.filename}`; + + logger.info('카테고리 레이아웃 이미지 업로드 요청', { category_id: categoryId, path: imagePath }); + + // 현재 카테고리 정보 가져오기 + const category = await new Promise((resolve, reject) => { + workplaceModel.getCategoryById(categoryId, (err, data) => { + if (err) reject(new DatabaseError('카테고리 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + if (!category) { + throw new NotFoundError('카테고리를 찾을 수 없습니다'); + } + + // 카테고리 정보 업데이트 (이미지 경로만 변경) + const updatedData = { + category_name: category.category_name, + description: category.description, + display_order: category.display_order, + is_active: category.is_active, + layout_image: imagePath + }; + + await new Promise((resolve, reject) => { + workplaceModel.updateCategory(categoryId, updatedData, (err, result) => { + if (err) reject(new DatabaseError('이미지 경로 저장 중 오류가 발생했습니다')); + else resolve(result); + }); + }); + + logger.info('레이아웃 이미지 업로드 성공', { category_id: categoryId }); + + res.json({ + success: true, + data: { image_path: imagePath }, + message: '레이아웃 이미지가 성공적으로 업로드되었습니다' + }); +}); + +/** + * 작업장 레이아웃 이미지 업로드 + */ +exports.uploadWorkplaceLayoutImage = asyncHandler(async (req, res) => { + const workplaceId = req.params.id; + + if (!req.file) { + throw new ValidationError('이미지 파일이 필요합니다'); + } + + const imagePath = `/uploads/${req.file.filename}`; + + logger.info('작업장 레이아웃 이미지 업로드 요청', { workplace_id: workplaceId, path: imagePath }); + + // 현재 작업장 정보 가져오기 + const workplace = await new Promise((resolve, reject) => { + workplaceModel.getWorkplaceById(workplaceId, (err, data) => { + if (err) reject(new DatabaseError('작업장 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + if (!workplace) { + throw new NotFoundError('작업장을 찾을 수 없습니다'); + } + + // 작업장 정보 업데이트 (이미지 경로만 변경) + const updatedData = { + workplace_name: workplace.workplace_name, + category_id: workplace.category_id, + description: workplace.description, + workplace_purpose: workplace.workplace_purpose, + display_priority: workplace.display_priority, + is_active: workplace.is_active, + layout_image: imagePath + }; + + await new Promise((resolve, reject) => { + workplaceModel.updateWorkplace(workplaceId, updatedData, (err, result) => { + if (err) reject(new DatabaseError('이미지 경로 저장 중 오류가 발생했습니다')); + else resolve(result); + }); + }); + + logger.info('작업장 레이아웃 이미지 업로드 성공', { workplace_id: workplaceId }); + + res.json({ + success: true, + data: { image_path: imagePath }, + message: '작업장 레이아웃 이미지가 성공적으로 업로드되었습니다' + }); +}); + +/** + * 지도 영역 생성 + */ +exports.createMapRegion = asyncHandler(async (req, res) => { + const regionData = req.body; + + if (!regionData.workplace_id || !regionData.category_id) { + throw new ValidationError('작업장 ID와 카테고리 ID는 필수 입력 항목입니다'); + } + + logger.info('지도 영역 생성 요청', { workplace_id: regionData.workplace_id }); + + const id = await new Promise((resolve, reject) => { + workplaceModel.createMapRegion(regionData, (err, lastID) => { + if (err) reject(new DatabaseError('지도 영역 생성 중 오류가 발생했습니다')); + else resolve(lastID); + }); + }); + + logger.info('지도 영역 생성 성공', { region_id: id }); + + res.status(201).json({ + success: true, + data: { region_id: id }, + message: '지도 영역이 성공적으로 생성되었습니다' + }); +}); + +/** + * 카테고리별 지도 영역 조회 (작업장 정보 포함) + */ +exports.getMapRegionsByCategory = asyncHandler(async (req, res) => { + const categoryId = req.params.categoryId; + + const rows = await new Promise((resolve, reject) => { + workplaceModel.getMapRegionsByCategory(categoryId, (err, data) => { + if (err) reject(new DatabaseError('지도 영역 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + res.json({ + success: true, + data: rows, + message: '지도 영역 조회 성공' + }); +}); + +/** + * 작업장별 지도 영역 조회 + */ +exports.getMapRegionByWorkplace = asyncHandler(async (req, res) => { + const workplaceId = req.params.workplaceId; + + const region = await new Promise((resolve, reject) => { + workplaceModel.getMapRegionByWorkplace(workplaceId, (err, data) => { + if (err) reject(new DatabaseError('지도 영역 조회 중 오류가 발생했습니다')); + else resolve(data); + }); + }); + + res.json({ + success: true, + data: region, + message: '지도 영역 조회 성공' + }); +}); + +/** + * 지도 영역 수정 + */ +exports.updateMapRegion = asyncHandler(async (req, res) => { + const regionId = req.params.id; + const regionData = req.body; + + logger.info('지도 영역 수정 요청', { region_id: regionId }); + + await new Promise((resolve, reject) => { + workplaceModel.updateMapRegion(regionId, regionData, (err, result) => { + if (err) reject(new DatabaseError('지도 영역 수정 중 오류가 발생했습니다')); + else resolve(result); + }); + }); + + logger.info('지도 영역 수정 성공', { region_id: regionId }); + + res.json({ + success: true, + message: '지도 영역이 성공적으로 수정되었습니다' + }); +}); + +/** + * 지도 영역 삭제 + */ +exports.deleteMapRegion = asyncHandler(async (req, res) => { + const regionId = req.params.id; + + logger.info('지도 영역 삭제 요청', { region_id: regionId }); + + await new Promise((resolve, reject) => { + workplaceModel.deleteMapRegion(regionId, (err, result) => { + if (err) reject(new DatabaseError('지도 영역 삭제 중 오류가 발생했습니다')); + else resolve(result); + }); + }); + + logger.info('지도 영역 삭제 성공', { region_id: regionId }); + + res.json({ + success: true, + message: '지도 영역이 성공적으로 삭제되었습니다' + }); +}); diff --git a/deploy/tkfb-package/api.hyungi.net/create-attendance-tables.js b/deploy/tkfb-package/api.hyungi.net/create-attendance-tables.js new file mode 100644 index 0000000..f9901b7 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/create-attendance-tables.js @@ -0,0 +1,193 @@ +// 근태 관리 테이블 생성 스크립트 +const mysql = require('mysql2/promise'); + +async function createAttendanceTables() { + let connection; + + try { + // 로컬 MySQL 연결 (기본 설정) + connection = await mysql.createConnection({ + host: 'localhost', + user: 'root', + password: '', // 비밀번호가 있다면 여기에 입력 + database: 'hyungi' + }); + + console.log('✅ MySQL 연결 성공'); + + // 1. 근로 유형 테이블 생성 + console.log('📋 근로 유형 테이블 생성 중...'); + await connection.execute(` + CREATE TABLE IF NOT EXISTS work_attendance_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + type_code VARCHAR(20) NOT NULL UNIQUE COMMENT '근로 유형 코드', + type_name VARCHAR(50) NOT NULL COMMENT '근로 유형명', + description TEXT COMMENT '설명', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) COMMENT='근로 유형 관리 테이블' + `); + + // 2. 휴가 유형 테이블 생성 + console.log('🏖️ 휴가 유형 테이블 생성 중...'); + await connection.execute(` + CREATE TABLE IF NOT EXISTS vacation_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + type_code VARCHAR(20) NOT NULL UNIQUE COMMENT '휴가 유형 코드', + type_name VARCHAR(50) NOT NULL COMMENT '휴가 유형명', + hours_deduction DECIMAL(4,2) NOT NULL COMMENT '차감 시간', + description TEXT COMMENT '설명', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) COMMENT='휴가 유형 관리 테이블' + `); + + // 3. 일일 근태 기록 테이블 생성 + console.log('📊 일일 근태 기록 테이블 생성 중...'); + await connection.execute(` + CREATE TABLE IF NOT EXISTS daily_attendance_records ( + id INT PRIMARY KEY AUTO_INCREMENT, + record_date DATE NOT NULL COMMENT '기록 날짜', + worker_id INT NOT NULL COMMENT '작업자 ID', + total_work_hours DECIMAL(4,2) DEFAULT 0 COMMENT '총 작업 시간', + attendance_type_id INT COMMENT '근로 유형 ID', + vacation_type_id INT NULL COMMENT '휴가 유형 ID', + is_vacation_processed BOOLEAN DEFAULT FALSE COMMENT '휴가 처리 여부', + overtime_approved BOOLEAN DEFAULT FALSE COMMENT '초과근무 승인 여부', + overtime_approved_by INT NULL COMMENT '초과근무 승인자 ID', + overtime_approved_at TIMESTAMP NULL COMMENT '초과근무 승인 시간', + status ENUM('incomplete', 'partial', 'complete', 'overtime', 'vacation', 'error') DEFAULT 'incomplete' COMMENT '상태', + notes TEXT COMMENT '비고', + created_by INT NOT NULL DEFAULT 1 COMMENT '생성자 ID', + updated_by INT NULL COMMENT '수정자 ID', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE KEY unique_worker_date (worker_id, record_date), + INDEX idx_record_date (record_date), + INDEX idx_worker_date (worker_id, record_date), + INDEX idx_status (status) + ) COMMENT='일일 근태 기록 테이블' + `); + + // 4. 작업자 휴가 잔여 관리 테이블 생성 + console.log('📅 휴가 잔여 관리 테이블 생성 중...'); + await connection.execute(` + CREATE TABLE IF NOT EXISTS worker_vacation_balance ( + id INT PRIMARY KEY AUTO_INCREMENT, + worker_id INT NOT NULL COMMENT '작업자 ID', + year YEAR NOT NULL COMMENT '연도', + total_annual_leave DECIMAL(4,2) DEFAULT 15.0 COMMENT '연간 총 연차 (일)', + used_annual_leave DECIMAL(4,2) DEFAULT 0 COMMENT '사용한 연차 (일)', + remaining_annual_leave DECIMAL(4,2) GENERATED ALWAYS AS (total_annual_leave - used_annual_leave) STORED COMMENT '잔여 연차 (일)', + notes TEXT COMMENT '비고', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE KEY unique_worker_year (worker_id, year), + INDEX idx_worker_year (worker_id, year) + ) COMMENT='작업자별 휴가 잔여 관리 테이블' + `); + + // 5. 기본 데이터 삽입 + console.log('📝 기본 데이터 삽입 중...'); + + // 근로 유형 기본 데이터 + await connection.execute(` + INSERT IGNORE INTO work_attendance_types (type_code, type_name, description) VALUES + ('REGULAR', '정시근로', '8시간 정규 근무'), + ('OVERTIME', '연장근로', '8시간 초과 근무'), + ('PARTIAL', '부분근로', '8시간 미만 근무'), + ('VACATION', '휴가근로', '휴가와 함께하는 부분 근무') + `); + + // 휴가 유형 기본 데이터 + await connection.execute(` + INSERT IGNORE INTO vacation_types (type_code, type_name, hours_deduction, description) VALUES + ('ANNUAL_FULL', '연차', 8.0, '하루 전체 연차'), + ('ANNUAL_HALF', '반차', 4.0, '반일 연차'), + ('ANNUAL_QUARTER', '반반차', 2.0, '1/4일 연차'), + ('SICK_FULL', '병가', 8.0, '하루 전체 병가'), + ('SICK_HALF', '반일병가', 4.0, '반일 병가'), + ('PERSONAL_FULL', '개인사유', 8.0, '개인사유로 인한 휴가'), + ('PERSONAL_HALF', '반일개인사유', 4.0, '반일 개인사유 휴가') + `); + + // 6. 휴가 전용 작업 유형 추가 + console.log('🏖️ 휴가 전용 작업 유형 추가 중...'); + await connection.execute(` + INSERT IGNORE INTO work_types (name, description, is_active) VALUES + ('휴가', '연차, 반차, 병가 등 휴가 처리용', TRUE) + `); + + // 7. daily_work_reports 테이블에 근태 기록 연결 컬럼 추가 (이미 있으면 무시) + try { + await connection.execute(` + ALTER TABLE daily_work_reports + ADD COLUMN attendance_record_id INT NULL COMMENT '근태 기록 ID' AFTER updated_by + `); + console.log('✅ daily_work_reports 테이블에 attendance_record_id 컬럼 추가됨'); + } catch (error) { + if (error.code !== 'ER_DUP_FIELDNAME') { + console.log('⚠️ attendance_record_id 컬럼 추가 실패:', error.message); + } else { + console.log('✅ attendance_record_id 컬럼이 이미 존재함'); + } + } + + // 8. 인덱스 추가 + try { + await connection.execute(`CREATE INDEX idx_attendance_record ON daily_work_reports(attendance_record_id)`); + console.log('✅ attendance_record_id 인덱스 추가됨'); + } catch (error) { + console.log('⚠️ 인덱스 추가 실패 (이미 존재할 수 있음):', error.message); + } + + console.log('🎉 근태 관리 DB 설정 완료!'); + console.log(''); + console.log('📋 생성된 테이블:'); + console.log(' - work_attendance_types (근로 유형)'); + console.log(' - vacation_types (휴가 유형)'); + console.log(' - daily_attendance_records (일일 근태 기록)'); + console.log(' - worker_vacation_balance (휴가 잔여 관리)'); + console.log(''); + console.log('✅ 기본 데이터도 모두 삽입되었습니다.'); + + } catch (error) { + console.error('❌ DB 설정 중 오류 발생:', error); + + // 다른 연결 정보로 시도 + if (error.code === 'ECONNREFUSED' || error.code === 'ER_ACCESS_DENIED_ERROR') { + console.log(''); + console.log('💡 다른 DB 연결 정보를 시도해보세요:'); + console.log(' - host: localhost 또는 127.0.0.1'); + console.log(' - port: 3306 (기본값)'); + console.log(' - user: root 또는 다른 사용자'); + console.log(' - password: 설정된 비밀번호'); + console.log(' - database: hyungi'); + } + + throw error; + } finally { + if (connection) { + await connection.end(); + } + } +} + +// 직접 실행 +if (require.main === module) { + createAttendanceTables() + .then(() => { + console.log('✅ 설정 완료'); + process.exit(0); + }) + .catch((error) => { + console.error('❌ 설정 실패:', error); + process.exit(1); + }); +} + +module.exports = { createAttendanceTables }; diff --git a/deploy/tkfb-package/api.hyungi.net/db.js b/deploy/tkfb-package/api.hyungi.net/db.js new file mode 100644 index 0000000..e099cab --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db.js @@ -0,0 +1,35 @@ +require('dotenv').config(); +const mysql = require('mysql2/promise'); +const retry = require('async-retry'); + +// 초기화된 pool을 export 하기 위한 변수 +let pool = null; + +const initPool = async () => { + if (pool) return pool; // 이미 초기화된 경우 재사용 + + await retry(async () => { + pool = mysql.createPool({ + host: process.env.DB_HOST, + port: process.env.DB_PORT || 3306, + user: process.env.DB_USER, + password: process.env.DB_PASS, + database: process.env.DB_NAME, + waitForConnections: true, + connectionLimit: 10, + queueLimit: 0 + }); + + const conn = await pool.getConnection(); + await conn.query('SET FOREIGN_KEY_CHECKS = 1'); + console.log(`✅ MariaDB 연결 성공: ${process.env.DB_HOST}:${process.env.DB_PORT || 3306}/${process.env.DB_NAME}`); + conn.release(); + }, { + retries: 10, + minTimeout: 3000 + }); + + return pool; +}; + +module.exports = initPool; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/db/connection.js b/deploy/tkfb-package/api.hyungi.net/db/connection.js new file mode 100644 index 0000000..9ad0597 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/connection.js @@ -0,0 +1,17 @@ +// db/connection.js - 레거시 콜백 방식 DB 래퍼 +const { getDb } = require('../dbPool'); + +// 콜백 방식 쿼리 래퍼 +const query = async (sql, params, callback) => { + try { + const db = await getDb(); + const [results] = await db.query(sql, params); + callback(null, results); + } catch (error) { + callback(error); + } +}; + +module.exports = { + query +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20251219003210_20251219_initial_schema.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20251219003210_20251219_initial_schema.js new file mode 100644 index 0000000..8b22422 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20251219003210_20251219_initial_schema.js @@ -0,0 +1,49 @@ +const fs = require('fs'); +const path = require('path'); + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function(knex) { + const schemaSql = fs.readFileSync(path.join(__dirname, '../../hyungi_schema_v2.sql'), 'utf8'); + return knex.raw(schemaSql); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function(knex) { + // down 마이그레이션은 모든 테이블을 역순으로 삭제하도록 구현합니다. + const tables = [ + 'cutting_plans', + 'daily_issue_reports', + 'daily_work_reports', + 'codes', + 'code_types', + 'factory_info', + 'equipment_list', + 'pipe_specs', + 'tasks', + 'worker_groups', + 'workers', + 'projects', + 'password_change_logs', + 'login_logs', + 'users' + ]; + + // 외래 키 제약 조건을 먼저 비활성화합니다. + return knex.raw('SET FOREIGN_KEY_CHECKS = 0;') + .then(() => { + // 각 테이블을 순회하며 drop table if exists를 실행합니다. + return tables.reduce((promise, tableName) => { + return promise.then(() => knex.schema.dropTableIfExists(tableName)); + }, Promise.resolve()); + }) + .finally(() => { + // 외래 키 제약 조건을 다시 활성화합니다. + return knex.raw('SET FOREIGN_KEY_CHECKS = 1;'); + }); +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20251219010000_add_columns_to_projects.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20251219010000_add_columns_to_projects.js new file mode 100644 index 0000000..c618cc6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20251219010000_add_columns_to_projects.js @@ -0,0 +1,23 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function(knex) { + return knex.schema.table('projects', function (table) { + table.boolean('is_active').defaultTo(true).after('pm'); + table.string('project_status').defaultTo('active').after('is_active'); + table.date('completed_date').nullable().after('project_status'); + }); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function(knex) { + return knex.schema.table('projects', function (table) { + table.dropColumn('is_active'); + table.dropColumn('project_status'); + table.dropColumn('completed_date'); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260106083251_create_permissions_tables.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260106083251_create_permissions_tables.js new file mode 100644 index 0000000..a53dfac --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260106083251_create_permissions_tables.js @@ -0,0 +1,57 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = function(knex) { + return knex.schema + // 1. roles 테이블 생성 + .createTable('roles', function(table) { + table.increments('id').primary(); + table.string('name', 50).notNullable().unique(); + table.string('description', 255); + table.timestamps(true, true); + }) + // 2. permissions 테이블 생성 + .createTable('permissions', function(table) { + table.increments('id').primary(); + table.string('name', 100).notNullable().unique(); // 예: 'user:create' + table.string('description', 255); + table.timestamps(true, true); + }) + // 3. role_permissions (역할-권한) 조인 테이블 생성 + .createTable('role_permissions', function(table) { + table.integer('role_id').unsigned().notNullable().references('id').inTable('roles').onDelete('CASCADE'); + table.integer('permission_id').unsigned().notNullable().references('id').inTable('permissions').onDelete('CASCADE'); + table.primary(['role_id', 'permission_id']); + }) + // 4. users 테이블에 role_id 추가 및 기존 컬럼 삭제 + .table('users', function(table) { + table.integer('role_id').unsigned().references('id').inTable('roles').onDelete('SET NULL').after('email'); + // 기존 컬럼들은 삭제 또는 비활성화 (데이터 보존을 위해 일단 이름 변경) + table.renameColumn('role', '_role_old'); + table.renameColumn('access_level', '_access_level_old'); + }) + // 5. user_permissions (사용자-개별 권한) 조인 테이블 생성 + .createTable('user_permissions', function(table) { + table.integer('user_id').notNullable().references('user_id').inTable('users').onDelete('CASCADE'); + table.integer('permission_id').unsigned().notNullable().references('id').inTable('permissions').onDelete('CASCADE'); + table.primary(['user_id', 'permission_id']); + }); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = function(knex) { + return knex.schema + .dropTableIfExists('user_permissions') + .dropTableIfExists('role_permissions') + .dropTableIfExists('permissions') + .dropTableIfExists('roles') + .table('users', function(table) { + table.dropColumn('role_id'); + table.renameColumn('_role_old', 'role'); + table.renameColumn('_access_level_old', 'access_level'); + }); +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260106083318_populate_permissions_data.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260106083318_populate_permissions_data.js new file mode 100644 index 0000000..353c94f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260106083318_populate_permissions_data.js @@ -0,0 +1,103 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = async function(knex) { + // 1. Roles 생성 + await knex('roles').insert([ + { id: 1, name: 'System Admin', description: '시스템 전체 관리자. 모든 권한을 가짐.' }, + { id: 2, name: 'Admin', description: '관리자. 사용자 및 프로젝트 관리 등 대부분의 권한을 가짐.' }, + { id: 3, name: 'Leader', description: '그룹장. 팀원 작업 현황 조회 등 중간 관리자 권한.' }, + { id: 4, name: 'Worker', description: '일반 작업자. 자신의 작업 보고서 작성 및 조회 권한.' }, + ]); + + // 2. Permissions 생성 (예시) + const permissions = [ + // User + { name: 'user:create', description: '사용자 생성' }, + { name: 'user:read', description: '사용자 정보 조회' }, + { name: 'user:update', description: '사용자 정보 수정' }, + { name: 'user:delete', description: '사용자 삭제' }, + // Project + { name: 'project:create', description: '프로젝트 생성' }, + { name: 'project:read', description: '프로젝트 조회' }, + { name: 'project:update', description: '프로젝트 수정' }, + { name: 'project:delete', description: '프로젝트 삭제' }, + // Work Report + { name: 'work-report:create', description: '작업 보고서 생성' }, + { name: 'work-report:read-own', description: '자신의 작업 보고서 조회' }, + { name: 'work-report:read-team', description: '팀의 작업 보고서 조회' }, + { name: 'work-report:read-all', description: '모든 작업 보고서 조회' }, + { name: 'work-report:update', description: '작업 보고서 수정' }, + { name: 'work-report:delete', description: '작업 보고서 삭제' }, + // System + { name: 'system:read-logs', description: '시스템 로그 조회' }, + { name: 'system:manage-settings', description: '시스템 설정 관리' }, + ]; + await knex('permissions').insert(permissions); + + // 3. Role-Permissions 매핑 + const allPermissions = await knex('permissions').select('id', 'name'); + const permissionMap = allPermissions.reduce((acc, p) => { + acc[p.name] = p.id; + return acc; + }, {}); + + const rolePermissions = { + // System Admin (모든 권한) + 'System Admin': allPermissions.map(p => p.id), + // Admin + 'Admin': [ + permissionMap['user:create'], permissionMap['user:read'], permissionMap['user:update'], permissionMap['user:delete'], + permissionMap['project:create'], permissionMap['project:read'], permissionMap['project:update'], permissionMap['project:delete'], + permissionMap['work-report:read-all'], permissionMap['work-report:update'], permissionMap['work-report:delete'], + ], + // Leader + 'Leader': [ + permissionMap['user:read'], + permissionMap['project:read'], + permissionMap['work-report:read-team'], + permissionMap['work-report:read-own'], + permissionMap['work-report:create'], + ], + // Worker + 'Worker': [ + permissionMap['work-report:create'], + permissionMap['work-report:read-own'], + ], + }; + + const rolePermissionInserts = []; + for (const roleName in rolePermissions) { + const roleId = (await knex('roles').where('name', roleName).first()).id; + rolePermissions[roleName].forEach(permissionId => { + rolePermissionInserts.push({ role_id: roleId, permission_id: permissionId }); + }); + } + await knex('role_permissions').insert(rolePermissionInserts); + + // 4. 기존 사용자에게 역할 부여 (예: 기존 admin -> Admin, leader -> Leader, user -> Worker) + await knex.raw(` + UPDATE users SET role_id = + CASE + WHEN _role_old = 'system' THEN (SELECT id FROM roles WHERE name = 'System Admin') + WHEN _role_old = 'admin' THEN (SELECT id FROM roles WHERE name = 'Admin') + WHEN _role_old = 'leader' THEN (SELECT id FROM roles WHERE name = 'Leader') + ELSE (SELECT id FROM roles WHERE name = 'Worker') + END + `); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = async function(knex) { + await knex('role_permissions').del(); + await knex('user_permissions').del(); + await knex('roles').del(); + await knex('permissions').del(); + + // 역할 롤백 (단순화된 버전) + await knex.raw("UPDATE users SET _role_old = 'user' WHERE role_id IS NOT NULL"); +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260107140000_update_worker_schema.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260107140000_update_worker_schema.js new file mode 100644 index 0000000..1592c7d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260107140000_update_worker_schema.js @@ -0,0 +1,62 @@ + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = async function (knex) { + const hasHireDate = await knex.schema.hasColumn('workers', 'hire_date'); + + if (!hasHireDate) { + await knex.schema.alterTable('workers', function (table) { + // Modify status to ENUM + // Note: Knex might not support modifying to ENUM easily across DBs, but valid for MySQL + // We use raw SQL for status modification to be safe with existing data + + // Add new columns + table.string('phone_number', 20).nullable().comment('전화번호'); + table.string('email', 100).nullable().comment('이메일'); + table.date('hire_date').nullable().comment('입사일'); + table.string('department', 100).nullable().comment('부서'); + table.text('notes').nullable().comment('비고'); + }); + + // Update status column using raw query + await knex.raw(` + ALTER TABLE workers + MODIFY COLUMN status ENUM('active', 'inactive') DEFAULT 'active' COMMENT '작업자 상태 (active: 활성, inactive: 비활성)' + `); + + // Add indexes + await knex.raw(`CREATE INDEX IF NOT EXISTS idx_workers_status ON workers(status)`); + await knex.raw(`CREATE INDEX IF NOT EXISTS idx_workers_hire_date ON workers(hire_date)`); + + // Set NULL status to active + await knex('workers').whereNull('status').update({ status: 'active' }); + } +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = async function (knex) { + // We generally don't want to lose data on rollback of this critical schema fix, + // but technically we should revert changes. + // For safety, we might skip dropping columns or implement it carefully. + + const hasHireDate = await knex.schema.hasColumn('workers', 'hire_date'); + if (hasHireDate) { + await knex.schema.alterTable('workers', function (table) { + table.dropColumn('phone_number'); + table.dropColumn('email'); + table.dropColumn('hire_date'); + table.dropColumn('department'); + table.dropColumn('notes'); + }); + + await knex.raw(` + ALTER TABLE workers + MODIFY COLUMN status VARCHAR(20) DEFAULT 'active' COMMENT '상태 (active, inactive)' + `); + } +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119000000_simplify_permissions_and_add_page_access.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119000000_simplify_permissions_and_add_page_access.js new file mode 100644 index 0000000..8c77102 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119000000_simplify_permissions_and_add_page_access.js @@ -0,0 +1,151 @@ +/** + * 권한 시스템 단순화 및 페이지 접근 권한 추가 + * - Leader와 Worker를 User로 통합 + * - 페이지 접근 권한 테이블 생성 + * - Admin이 사용자별 페이지 접근 권한을 설정할 수 있도록 함 + * + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = async function(knex) { + // 1. 페이지 목록 테이블 생성 + await knex.schema.createTable('pages', function(table) { + table.increments('id').primary(); + table.string('page_key', 100).notNullable().unique(); // 예: 'worker-management', 'project-management' + table.string('page_name', 100).notNullable(); // 예: '작업자 관리', '프로젝트 관리' + table.string('page_path', 255).notNullable(); // 예: '/pages/management/worker-management.html' + table.string('category', 50); // 예: 'management', 'dashboard', 'admin' + table.string('description', 255); + table.boolean('is_admin_only').defaultTo(false); // Admin 전용 페이지 여부 + table.integer('display_order').defaultTo(0); // 표시 순서 + table.timestamps(true, true); + }); + + // 2. 사용자별 페이지 접근 권한 테이블 생성 + await knex.schema.createTable('user_page_access', function(table) { + table.integer('user_id').notNullable() + .references('user_id').inTable('users').onDelete('CASCADE'); + table.integer('page_id').unsigned().notNullable() + .references('id').inTable('pages').onDelete('CASCADE'); + table.boolean('can_access').defaultTo(true); // 접근 가능 여부 + table.timestamp('granted_at').defaultTo(knex.fn.now()); + table.integer('granted_by') // 권한을 부여한 Admin의 user_id + .references('user_id').inTable('users').onDelete('SET NULL'); + table.primary(['user_id', 'page_id']); + }); + + // 3. 기본 페이지 목록 삽입 + await knex('pages').insert([ + // Dashboard + { page_key: 'dashboard-user', page_name: '사용자 대시보드', page_path: '/pages/dashboard/user.html', category: 'dashboard', is_admin_only: false, display_order: 1 }, + { page_key: 'dashboard-leader', page_name: '그룹장 대시보드', page_path: '/pages/dashboard/group-leader.html', category: 'dashboard', is_admin_only: false, display_order: 2 }, + + // Management + { page_key: 'worker-management', page_name: '작업자 관리', page_path: '/pages/management/worker-management.html', category: 'management', is_admin_only: false, display_order: 10 }, + { page_key: 'project-management', page_name: '프로젝트 관리', page_path: '/pages/management/project-management.html', category: 'management', is_admin_only: false, display_order: 11 }, + { page_key: 'work-management', page_name: '작업 관리', page_path: '/pages/management/work-management.html', category: 'management', is_admin_only: false, display_order: 12 }, + { page_key: 'code-management', page_name: '코드 관리', page_path: '/pages/management/code-management.html', category: 'management', is_admin_only: false, display_order: 13 }, + + // Common + { page_key: 'daily-work-report', page_name: '작업 현황 확인', page_path: '/pages/common/daily-work-report-viewer.html', category: 'common', is_admin_only: false, display_order: 20 }, + + // Admin + { page_key: 'user-management', page_name: '사용자 관리', page_path: '/pages/admin/manage-user.html', category: 'admin', is_admin_only: true, display_order: 100 }, + ]); + + // 4. roles 테이블 업데이트: Leader와 Worker를 User로 통합 + // Leader와 Worker 역할을 가진 사용자를 모두 User로 변경 + const userRoleId = await knex('roles').where('name', 'Worker').first().then(r => r.id); + const leaderRoleId = await knex('roles').where('name', 'Leader').first().then(r => r ? r.id : null); + + if (leaderRoleId) { + // Leader를 User로 변경 + await knex('users').where('role_id', leaderRoleId).update({ role_id: userRoleId }); + } + + // 5. role_permissions 업데이트: Worker 권한을 확장하여 모든 일반 기능 사용 가능하게 + const allPermissions = await knex('permissions').select('id', 'name'); + const permissionMap = allPermissions.reduce((acc, p) => { + acc[p.name] = p.id; + return acc; + }, {}); + + // Worker 역할의 기존 권한 삭제 + await knex('role_permissions').where('role_id', userRoleId).del(); + + // Worker(이제 User) 역할에 모든 일반 권한 부여 (Admin/System 권한 제외) + const userPermissions = [ + permissionMap['user:read'], + permissionMap['project:read'], + permissionMap['project:create'], + permissionMap['project:update'], + permissionMap['work-report:create'], + permissionMap['work-report:read-own'], + permissionMap['work-report:read-team'], + permissionMap['work-report:read-all'], + permissionMap['work-report:update'], + permissionMap['work-report:delete'], + ].filter(Boolean); // undefined 제거 + + const rolePermissionInserts = userPermissions.map(permissionId => ({ + role_id: userRoleId, + permission_id: permissionId + })); + + await knex('role_permissions').insert(rolePermissionInserts); + + // 6. Leader 역할 삭제 (더 이상 사용하지 않음) + if (leaderRoleId) { + await knex('role_permissions').where('role_id', leaderRoleId).del(); + await knex('roles').where('id', leaderRoleId).del(); + } + + // 7. Worker 역할 이름을 'User'로 변경 + await knex('roles').where('id', userRoleId).update({ + name: 'User', + description: '일반 사용자. 작업 보고서 및 프로젝트 관리 등 모든 일반 기능을 사용할 수 있음.' + }); + + // 8. 모든 일반 사용자에게 모든 페이지 접근 권한 부여 (Admin 페이지 제외) + const normalPages = await knex('pages').where('is_admin_only', false).select('id'); + const normalUsers = await knex('users').where('role_id', userRoleId).select('user_id'); + + const userPageAccessInserts = []; + normalUsers.forEach(user => { + normalPages.forEach(page => { + userPageAccessInserts.push({ + user_id: user.user_id, + page_id: page.id, + can_access: true + }); + }); + }); + + if (userPageAccessInserts.length > 0) { + await knex('user_page_access').insert(userPageAccessInserts); + } +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = async function(knex) { + // 테이블 삭제 (역순) + await knex.schema.dropTableIfExists('user_page_access'); + await knex.schema.dropTableIfExists('pages'); + + // User 역할을 다시 Worker로 변경 + const userRoleId = await knex('roles').where('name', 'User').first().then(r => r ? r.id : null); + if (userRoleId) { + await knex('roles').where('id', userRoleId).update({ + name: 'Worker', + description: '일반 작업자. 자신의 작업 보고서 작성 및 조회 권한.' + }); + } + + // Leader 역할 재생성 + await knex('roles').insert([ + { id: 3, name: 'Leader', description: '그룹장. 팀원 작업 현황 조회 등 중간 관리자 권한.' } + ]); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119095549_add_worker_display_fields.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119095549_add_worker_display_fields.js new file mode 100644 index 0000000..4cb664d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119095549_add_worker_display_fields.js @@ -0,0 +1,27 @@ +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.up = async function(knex) { + await knex.schema.alterTable('workers', (table) => { + // 재직 상태 (employed: 재직, resigned: 퇴사) + table.enum('employment_status', ['employed', 'resigned']) + .defaultTo('employed') + .notNullable() + .comment('재직 상태 (employed: 재직, resigned: 퇴사)'); + }); + + console.log('✅ workers 테이블에 employment_status 컬럼 추가 완료'); +}; + +/** + * @param { import("knex").Knex } knex + * @returns { Promise } + */ +exports.down = async function(knex) { + await knex.schema.alterTable('workers', (table) => { + table.dropColumn('employment_status'); + }); + + console.log('✅ workers 테이블에서 employment_status 컬럼 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120000_add_worker_fields.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120000_add_worker_fields.js new file mode 100644 index 0000000..607564b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120000_add_worker_fields.js @@ -0,0 +1,33 @@ +/** + * 마이그레이션: Workers 테이블에 급여 및 기본 연차 컬럼 추가 + * 작성일: 2026-01-19 + * + * 변경사항: + * - salary 컬럼 추가 (NULL 허용, 선택 사항) + * - base_annual_leave 컬럼 추가 (기본값: 15일) + */ + +exports.up = async function(knex) { + console.log('⏳ Workers 테이블에 salary, base_annual_leave 컬럼 추가 중...'); + + await knex.schema.alterTable('workers', (table) => { + // 급여 정보 (선택 사항, NULL 허용) + table.decimal('salary', 12, 2).nullable().comment('급여 (선택)'); + + // 기본 연차 일수 (기본값: 15일) + table.integer('base_annual_leave').defaultTo(15).notNullable().comment('기본 연차 일수'); + }); + + console.log('✅ Workers 테이블 컬럼 추가 완료'); +}; + +exports.down = async function(knex) { + console.log('⏳ Workers 테이블에서 salary, base_annual_leave 컬럼 제거 중...'); + + await knex.schema.alterTable('workers', (table) => { + table.dropColumn('salary'); + table.dropColumn('base_annual_leave'); + }); + + console.log('✅ Workers 테이블 컬럼 제거 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120001_create_attendance_tables.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120001_create_attendance_tables.js new file mode 100644 index 0000000..b94cb86 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120001_create_attendance_tables.js @@ -0,0 +1,112 @@ +/** + * 마이그레이션: 출근/근태 관련 테이블 생성 + * 작성일: 2026-01-19 + * + * 생성 테이블: + * - work_attendance_types: 출근 유형 (정상, 지각, 조퇴, 결근, 휴가) + * - vacation_types: 휴가 유형 (연차, 반차, 병가, 경조사) + * - daily_attendance_records: 일일 출근 기록 + * - worker_vacation_balance: 작업자 연차 잔액 (연도별) + */ + +exports.up = async function(knex) { + console.log('⏳ 출근/근태 관련 테이블 생성 중...'); + + // 1. 출근 유형 테이블 + await knex.schema.createTable('work_attendance_types', (table) => { + table.increments('id').primary(); + table.string('type_code', 20).unique().notNullable().comment('유형 코드'); + table.string('type_name', 50).notNullable().comment('유형 이름'); + table.text('description').nullable().comment('설명'); + table.boolean('is_active').defaultTo(true).comment('활성 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + }); + console.log('✅ work_attendance_types 테이블 생성 완료'); + + // 초기 데이터 입력 + await knex('work_attendance_types').insert([ + { type_code: 'NORMAL', type_name: '정상 출근', description: '정상 출근' }, + { type_code: 'LATE', type_name: '지각', description: '지각' }, + { type_code: 'EARLY_LEAVE', type_name: '조퇴', description: '조퇴' }, + { type_code: 'ABSENT', type_name: '결근', description: '무단 결근' }, + { type_code: 'VACATION', type_name: '휴가', description: '승인된 휴가' } + ]); + console.log('✅ work_attendance_types 초기 데이터 입력 완료'); + + // 2. 휴가 유형 테이블 + await knex.schema.createTable('vacation_types', (table) => { + table.increments('id').primary(); + table.string('type_code', 20).unique().notNullable().comment('휴가 코드'); + table.string('type_name', 50).notNullable().comment('휴가 이름'); + table.decimal('deduct_days', 3, 1).defaultTo(1.0).comment('차감 일수'); + table.boolean('is_active').defaultTo(true).comment('활성 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + }); + console.log('✅ vacation_types 테이블 생성 완료'); + + // 초기 데이터 입력 + await knex('vacation_types').insert([ + { type_code: 'ANNUAL', type_name: '연차', deduct_days: 1.0 }, + { type_code: 'HALF_ANNUAL', type_name: '반차', deduct_days: 0.5 }, + { type_code: 'SICK', type_name: '병가', deduct_days: 1.0 }, + { type_code: 'SPECIAL', type_name: '경조사', deduct_days: 0 } + ]); + console.log('✅ vacation_types 초기 데이터 입력 완료'); + + // 3. 일일 출근 기록 테이블 + await knex.schema.createTable('daily_attendance_records', (table) => { + table.increments('id').primary(); + table.integer('worker_id').unsigned().notNullable().comment('작업자 ID'); + table.date('record_date').notNullable().comment('기록 날짜'); + table.integer('attendance_type_id').unsigned().notNullable().comment('출근 유형 ID'); + table.integer('vacation_type_id').unsigned().nullable().comment('휴가 유형 ID'); + table.time('check_in_time').nullable().comment('출근 시간'); + table.time('check_out_time').nullable().comment('퇴근 시간'); + table.decimal('total_work_hours', 4, 2).defaultTo(0).comment('총 근무 시간'); + table.boolean('is_overtime_approved').defaultTo(false).comment('초과근무 승인 여부'); + table.text('notes').nullable().comment('비고'); + table.integer('created_by').unsigned().notNullable().comment('등록자 user_id'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + // 인덱스 및 제약조건 + table.unique(['worker_id', 'record_date']); + table.foreign('worker_id').references('workers.worker_id').onDelete('CASCADE'); + table.foreign('attendance_type_id').references('work_attendance_types.id'); + table.foreign('vacation_type_id').references('vacation_types.id'); + table.foreign('created_by').references('users.user_id'); + }); + console.log('✅ daily_attendance_records 테이블 생성 완료'); + + // 4. 작업자 연차 잔액 테이블 + await knex.schema.createTable('worker_vacation_balance', (table) => { + table.increments('id').primary(); + table.integer('worker_id').unsigned().notNullable().comment('작업자 ID'); + table.integer('year').notNullable().comment('연도'); + table.decimal('total_annual_leave', 4, 1).defaultTo(15.0).comment('총 연차'); + table.decimal('used_annual_leave', 4, 1).defaultTo(0).comment('사용 연차'); + // remaining_annual_leave는 애플리케이션 레벨에서 계산 + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + // 인덱스 및 제약조건 + table.unique(['worker_id', 'year']); + table.foreign('worker_id').references('workers.worker_id').onDelete('CASCADE'); + }); + console.log('✅ worker_vacation_balance 테이블 생성 완료'); + + console.log('✅ 모든 출근/근태 관련 테이블 생성 완료'); +}; + +exports.down = async function(knex) { + console.log('⏳ 출근/근태 관련 테이블 제거 중...'); + + await knex.schema.dropTableIfExists('worker_vacation_balance'); + await knex.schema.dropTableIfExists('daily_attendance_records'); + await knex.schema.dropTableIfExists('vacation_types'); + await knex.schema.dropTableIfExists('work_attendance_types'); + + console.log('✅ 모든 출근/근태 관련 테이블 제거 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120002_create_accounts_for_existing_workers.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120002_create_accounts_for_existing_workers.js new file mode 100644 index 0000000..6a45e11 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120002_create_accounts_for_existing_workers.js @@ -0,0 +1,104 @@ +/** + * 마이그레이션: 기존 작업자에게 계정 자동 생성 + * 작성일: 2026-01-19 + * + * 작업 내용: + * 1. 계정이 없는 기존 작업자 조회 + * 2. 각 작업자에 대해 users 테이블에 계정 생성 + * 3. username은 이름 기반으로 자동 생성 (예: 홍길동 → hong.gildong) + * 4. 초기 비밀번호는 '1234'로 통일 (첫 로그인 시 변경 권장) + * 5. 현재 연도 연차 잔액 초기화 (workers.annual_leave 사용) + */ + +const bcrypt = require('bcrypt'); +const { generateUniqueUsername } = require('../../utils/hangulToRoman'); + +exports.up = async function(knex) { + console.log('⏳ 기존 작업자들에게 계정 자동 생성 중...'); + + // 1. 계정이 없는 작업자 조회 + const workersWithoutAccount = await knex('workers') + .leftJoin('users', 'workers.worker_id', 'users.worker_id') + .whereNull('users.user_id') + .select( + 'workers.worker_id', + 'workers.worker_name', + 'workers.email', + 'workers.status', + 'workers.annual_leave' + ); + + console.log(`📊 계정이 없는 작업자: ${workersWithoutAccount.length}명`); + + if (workersWithoutAccount.length === 0) { + console.log('ℹ️ 계정이 필요한 작업자가 없습니다.'); + return; + } + + // 2. 각 작업자에 대해 계정 생성 + const initialPassword = '1234'; // 초기 비밀번호 + const hashedPassword = await bcrypt.hash(initialPassword, 10); + + // User 역할 ID 조회 + const userRole = await knex('roles') + .where('name', 'User') + .first(); + + if (!userRole) { + throw new Error('User 역할이 존재하지 않습니다. 권한 마이그레이션을 먼저 실행하세요.'); + } + + let successCount = 0; + let errorCount = 0; + + for (const worker of workersWithoutAccount) { + try { + // username 생성 (중복 체크 포함) + const username = await generateUniqueUsername(worker.worker_name, knex); + + // 계정 생성 + await knex('users').insert({ + username: username, + password: hashedPassword, + name: worker.worker_name, + email: worker.email, + worker_id: worker.worker_id, + role_id: userRole.id, + is_active: worker.status === 'active' ? 1 : 0, + created_at: knex.fn.now(), + updated_at: knex.fn.now() + }); + + console.log(`✅ ${worker.worker_name} (ID: ${worker.worker_id}) → username: ${username}`); + successCount++; + + // 현재 연도 연차 잔액 초기화 + const currentYear = new Date().getFullYear(); + await knex('worker_vacation_balance').insert({ + worker_id: worker.worker_id, + year: currentYear, + total_annual_leave: worker.annual_leave || 15, + used_annual_leave: 0, + created_at: knex.fn.now(), + updated_at: knex.fn.now() + }); + + } catch (error) { + console.error(`❌ ${worker.worker_name} 계정 생성 실패:`, error.message); + errorCount++; + } + } + + console.log(`\n📊 작업 완료: 성공 ${successCount}명, 실패 ${errorCount}명`); + console.log(`🔐 초기 비밀번호: ${initialPassword} (모든 계정 공통)`); + console.log('⚠️ 사용자들에게 첫 로그인 후 비밀번호를 변경하도록 안내해주세요!'); +}; + +exports.down = async function(knex) { + console.log('⏳ 자동 생성된 계정 제거 중...'); + + // 이 마이그레이션으로 생성된 계정은 구분하기 어려우므로 + // rollback 시 주의가 필요합니다. + console.log('⚠️ 경고: 이 마이그레이션의 rollback은 권장하지 않습니다.'); + console.log('ℹ️ 필요시 수동으로 users 테이블을 관리하세요.'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120003_add_guest_role.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120003_add_guest_role.js new file mode 100644 index 0000000..29a00fb --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260119120003_add_guest_role.js @@ -0,0 +1,51 @@ +/** + * 마이그레이션: 게스트 역할 추가 + * 작성일: 2026-01-19 + * + * 변경사항: + * - Guest 역할 추가 (계정 없이 특정 기능 접근 가능) + * - 게스트 전용 페이지 추가 (신고 채널 등) + */ + +exports.up = async function(knex) { + console.log('⏳ 게스트 역할 추가 중...'); + + // 1. Guest 역할 추가 + const [guestRoleId] = await knex('roles').insert({ + name: 'Guest', + description: '게스트 (계정 없이 특정 기능 접근 가능)', + created_at: knex.fn.now(), + updated_at: knex.fn.now() + }); + console.log(`✅ Guest 역할 추가 완료 (ID: ${guestRoleId})`); + + // 2. 게스트 전용 페이지 추가 + await knex('pages').insert({ + page_key: 'guest_report', + page_name: '신고 채널', + page_path: '/pages/guest/report.html', + category: 'guest', + is_admin_only: false, + created_at: knex.fn.now(), + updated_at: knex.fn.now() + }); + console.log('✅ 게스트 전용 페이지 추가 완료 (신고 채널)'); + + console.log('✅ 게스트 역할 추가 완료'); +}; + +exports.down = async function(knex) { + console.log('⏳ 게스트 역할 제거 중...'); + + // 페이지 제거 + await knex('pages') + .where('page_key', 'guest_report') + .delete(); + + // 역할 제거 + await knex('roles') + .where('name', 'Guest') + .delete(); + + console.log('✅ 게스트 역할 제거 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260120000000_create_tbm_system.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260120000000_create_tbm_system.js new file mode 100644 index 0000000..4ee0a02 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260120000000_create_tbm_system.js @@ -0,0 +1,158 @@ +/** + * 마이그레이션: TBM (Tool Box Meeting) 시스템 + * 작성일: 2026-01-20 + * + * 생성 테이블: + * - tbm_sessions: TBM 세션 (아침 미팅 기록) + * - tbm_team_assignments: TBM 팀 구성 (리더가 선택한 작업자들) + * - tbm_safety_checks: TBM 안전 체크리스트 + * - tbm_safety_records: TBM 안전 체크 기록 + * - team_handovers: 작업 인계 기록 (반차/조퇴 시) + */ + +exports.up = async function(knex) { + console.log('⏳ TBM 시스템 테이블 생성 중...'); + + // 1. TBM 세션 테이블 (아침 미팅) + await knex.schema.createTable('tbm_sessions', (table) => { + table.increments('session_id').primary(); + table.date('session_date').notNullable().comment('TBM 날짜'); + table.integer('leader_id').notNullable().comment('팀장 worker_id'); + table.integer('project_id').nullable().comment('프로젝트 ID'); + table.string('work_location', 200).nullable().comment('작업 장소'); + table.text('work_description').nullable().comment('작업 내용'); + table.text('safety_notes').nullable().comment('안전 관련 특이사항'); + table.enum('status', ['draft', 'completed', 'cancelled']).defaultTo('draft').comment('상태'); + table.time('start_time').nullable().comment('TBM 시작 시간'); + table.time('end_time').nullable().comment('TBM 종료 시간'); + table.integer('created_by').notNullable().comment('생성자 user_id'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + // 인덱스 및 제약조건 + table.index(['session_date', 'leader_id']); + table.foreign('leader_id').references('workers.worker_id'); + table.foreign('project_id').references('projects.project_id').onDelete('SET NULL'); + table.foreign('created_by').references('users.user_id'); + }); + console.log('✅ tbm_sessions 테이블 생성 완료'); + + // 2. TBM 팀 구성 테이블 (리더가 선택한 팀원들) + await knex.schema.createTable('tbm_team_assignments', (table) => { + table.increments('assignment_id').primary(); + table.integer('session_id').unsigned().notNullable().comment('TBM 세션 ID'); + table.integer('worker_id').notNullable().comment('팀원 worker_id'); + table.string('assigned_role', 100).nullable().comment('역할/담당'); + table.text('work_detail').nullable().comment('세부 작업 내용'); + table.boolean('is_present').defaultTo(true).comment('출석 여부'); + table.text('absence_reason').nullable().comment('결석 사유'); + table.timestamp('assigned_at').defaultTo(knex.fn.now()); + + // 인덱스 및 제약조건 + table.unique(['session_id', 'worker_id']); + table.foreign('session_id').references('tbm_sessions.session_id').onDelete('CASCADE'); + table.foreign('worker_id').references('workers.worker_id'); + }); + console.log('✅ tbm_team_assignments 테이블 생성 완료'); + + // 3. TBM 안전 체크리스트 마스터 테이블 + await knex.schema.createTable('tbm_safety_checks', (table) => { + table.increments('check_id').primary(); + table.string('check_category', 50).notNullable().comment('카테고리 (장비, PPE, 환경 등)'); + table.string('check_item', 200).notNullable().comment('체크 항목'); + table.text('description').nullable().comment('설명'); + table.integer('display_order').defaultTo(0).comment('표시 순서'); + table.boolean('is_required').defaultTo(true).comment('필수 체크 여부'); + table.boolean('is_active').defaultTo(true).comment('활성 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + table.index('check_category'); + }); + console.log('✅ tbm_safety_checks 테이블 생성 완료'); + + // 초기 안전 체크리스트 데이터 + await knex('tbm_safety_checks').insert([ + // PPE (개인 보호 장비) + { check_category: 'PPE', check_item: '안전모 착용 확인', display_order: 1, is_required: true }, + { check_category: 'PPE', check_item: '안전화 착용 확인', display_order: 2, is_required: true }, + { check_category: 'PPE', check_item: '안전조끼 착용 확인', display_order: 3, is_required: true }, + { check_category: 'PPE', check_item: '안전벨트 착용 확인 (고소작업 시)', display_order: 4, is_required: false }, + { check_category: 'PPE', check_item: '보안경/마스크 착용 확인', display_order: 5, is_required: false }, + + // 장비 점검 + { check_category: 'EQUIPMENT', check_item: '작업 도구 점검 완료', display_order: 10, is_required: true }, + { check_category: 'EQUIPMENT', check_item: '전동공구 안전 점검', display_order: 11, is_required: true }, + { check_category: 'EQUIPMENT', check_item: '사다리/비계 안전 확인', display_order: 12, is_required: false }, + { check_category: 'EQUIPMENT', check_item: '차량/중장비 점검 완료', display_order: 13, is_required: false }, + + // 작업 환경 + { check_category: 'ENVIRONMENT', check_item: '작업 장소 정리정돈 확인', display_order: 20, is_required: true }, + { check_category: 'ENVIRONMENT', check_item: '위험 구역 표시 확인', display_order: 21, is_required: true }, + { check_category: 'ENVIRONMENT', check_item: '기상 상태 확인 (우천, 강풍 등)', display_order: 22, is_required: true }, + { check_category: 'ENVIRONMENT', check_item: '작업 동선 안전 확인', display_order: 23, is_required: true }, + + // 비상 대응 + { check_category: 'EMERGENCY', check_item: '비상연락망 공유 완료', display_order: 30, is_required: true }, + { check_category: 'EMERGENCY', check_item: '소화기 위치 확인', display_order: 31, is_required: true }, + { check_category: 'EMERGENCY', check_item: '응급처치 키트 위치 확인', display_order: 32, is_required: true }, + ]); + console.log('✅ tbm_safety_checks 초기 데이터 입력 완료'); + + // 4. TBM 안전 체크 기록 테이블 + await knex.schema.createTable('tbm_safety_records', (table) => { + table.increments('record_id').primary(); + table.integer('session_id').unsigned().notNullable().comment('TBM 세션 ID'); + table.integer('check_id').unsigned().notNullable().comment('체크 항목 ID'); + table.boolean('is_checked').defaultTo(false).comment('체크 여부'); + table.text('notes').nullable().comment('비고/특이사항'); + table.integer('checked_by').nullable().comment('체크한 user_id'); + table.timestamp('checked_at').nullable().comment('체크 시간'); + + // 인덱스 및 제약조건 + table.unique(['session_id', 'check_id']); + table.foreign('session_id').references('tbm_sessions.session_id').onDelete('CASCADE'); + table.foreign('check_id').references('tbm_safety_checks.check_id'); + table.foreign('checked_by').references('users.user_id'); + }); + console.log('✅ tbm_safety_records 테이블 생성 완료'); + + // 5. 작업 인계 테이블 (반차/조퇴 시) + await knex.schema.createTable('team_handovers', (table) => { + table.increments('handover_id').primary(); + table.integer('session_id').unsigned().notNullable().comment('TBM 세션 ID'); + table.integer('from_leader_id').notNullable().comment('인계자 worker_id'); + table.integer('to_leader_id').notNullable().comment('인수자 worker_id'); + table.date('handover_date').notNullable().comment('인계 날짜'); + table.time('handover_time').nullable().comment('인계 시간'); + table.enum('reason', ['half_day', 'early_leave', 'emergency', 'other']).notNullable().comment('인계 사유'); + table.text('handover_notes').nullable().comment('인계 내용'); + table.text('worker_ids').nullable().comment('인계하는 작업자 IDs (JSON array)'); + table.boolean('is_confirmed').defaultTo(false).comment('인수 확인 여부'); + table.timestamp('confirmed_at').nullable().comment('인수 확인 시간'); + table.integer('confirmed_by').nullable().comment('인수 확인자 user_id'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + + // 인덱스 및 제약조건 + table.index(['session_id', 'handover_date']); + table.foreign('session_id').references('tbm_sessions.session_id').onDelete('CASCADE'); + table.foreign('from_leader_id').references('workers.worker_id'); + table.foreign('to_leader_id').references('workers.worker_id'); + table.foreign('confirmed_by').references('users.user_id'); + }); + console.log('✅ team_handovers 테이블 생성 완료'); + + console.log('✅ 모든 TBM 시스템 테이블 생성 완료'); +}; + +exports.down = async function(knex) { + console.log('⏳ TBM 시스템 테이블 제거 중...'); + + await knex.schema.dropTableIfExists('team_handovers'); + await knex.schema.dropTableIfExists('tbm_safety_records'); + await knex.schema.dropTableIfExists('tbm_safety_checks'); + await knex.schema.dropTableIfExists('tbm_team_assignments'); + await knex.schema.dropTableIfExists('tbm_sessions'); + + console.log('✅ 모든 TBM 시스템 테이블 제거 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260120000001_add_tbm_page.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260120000001_add_tbm_page.js new file mode 100644 index 0000000..4b3c9bb --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260120000001_add_tbm_page.js @@ -0,0 +1,33 @@ +/** + * 마이그레이션: TBM 페이지 등록 + * 작성일: 2026-01-20 + * + * pages 테이블에 TBM 페이지 추가 + */ + +exports.up = async function(knex) { + console.log('⏳ TBM 페이지 등록 중...'); + + // TBM 페이지 추가 + await knex('pages').insert([ + { + page_key: 'tbm', + page_name: 'TBM 관리', + page_path: '/pages/work/tbm.html', + category: 'work', + description: 'Tool Box Meeting - 아침 안전 회의 및 팀 구성 관리', + is_admin_only: false, + display_order: 10 + } + ]); + + console.log('✅ TBM 페이지 등록 완료'); +}; + +exports.down = async function(knex) { + console.log('⏳ TBM 페이지 제거 중...'); + + await knex('pages').where('page_key', 'tbm').del(); + + console.log('✅ TBM 페이지 제거 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126000001_create_workplace_categories.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126000001_create_workplace_categories.js new file mode 100644 index 0000000..2b000a1 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126000001_create_workplace_categories.js @@ -0,0 +1,24 @@ +/** + * 작업장 카테고리(공장) 테이블 생성 마이그레이션 + * 대분류: 제 1공장, 제 2공장 등 + */ + +exports.up = function(knex) { + return knex.schema.createTable('workplace_categories', function(table) { + table.increments('category_id').primary().comment('카테고리 ID'); + table.string('category_name', 100).notNullable().comment('카테고리명 (예: 제 1공장)'); + table.text('description').nullable().comment('설명'); + table.integer('display_order').defaultTo(0).comment('표시 순서'); + table.boolean('is_active').defaultTo(true).comment('활성화 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()).comment('생성일시'); + table.timestamp('updated_at').defaultTo(knex.fn.now()).comment('수정일시'); + + // 인덱스 + table.index('is_active'); + table.index('display_order'); + }); +}; + +exports.down = function(knex) { + return knex.schema.dropTableIfExists('workplace_categories'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126000002_create_workplaces.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126000002_create_workplaces.js new file mode 100644 index 0000000..6751b74 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126000002_create_workplaces.js @@ -0,0 +1,31 @@ +/** + * 작업장(작업 구역) 테이블 생성 마이그레이션 + * 소분류: 서스작업장, 조립구역 등 + */ + +exports.up = function(knex) { + return knex.schema.createTable('workplaces', function(table) { + table.increments('workplace_id').primary().comment('작업장 ID'); + table.integer('category_id').unsigned().nullable().comment('카테고리 ID (공장)'); + table.string('workplace_name', 255).notNullable().comment('작업장명'); + table.text('description').nullable().comment('설명'); + table.boolean('is_active').defaultTo(true).comment('활성화 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()).comment('생성일시'); + table.timestamp('updated_at').defaultTo(knex.fn.now()).comment('수정일시'); + + // 외래키 + table.foreign('category_id') + .references('category_id') + .inTable('workplace_categories') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + // 인덱스 + table.index('category_id'); + table.index('is_active'); + }); +}; + +exports.down = function(knex) { + return knex.schema.dropTableIfExists('workplaces'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010002_create_tasks.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010002_create_tasks.js new file mode 100644 index 0000000..aeb4bfc --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010002_create_tasks.js @@ -0,0 +1,36 @@ +/** + * 작업 테이블 생성 (공정=work_types에 속함) + * + * @param {import('knex').Knex} knex + */ +exports.up = function(knex) { + return knex.schema.createTable('tasks', function(table) { + table.increments('task_id').primary().comment('작업 ID'); + table.integer('work_type_id').nullable().comment('공정 ID (work_types 참조)'); + table.string('task_name', 255).notNullable().comment('작업명'); + table.text('description').nullable().comment('작업 설명'); + table.boolean('is_active').defaultTo(true).comment('활성화 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()).comment('생성일시'); + table.timestamp('updated_at').defaultTo(knex.fn.now()).comment('수정일시'); + + // 외래키 (work_types 테이블 참조) + table.foreign('work_type_id') + .references('id') + .inTable('work_types') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + // 인덱스 + table.index('work_type_id'); + table.index('is_active'); + }).then(() => { + console.log('✅ tasks 테이블 생성 완료'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = function(knex) { + return knex.schema.dropTableIfExists('tasks'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010003_add_work_type_task_to_tbm.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010003_add_work_type_task_to_tbm.js new file mode 100644 index 0000000..45d11bd --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010003_add_work_type_task_to_tbm.js @@ -0,0 +1,42 @@ +/** + * TBM 세션에 공정/작업 컬럼 추가 + * + * @param {import('knex').Knex} knex + */ +exports.up = function(knex) { + return knex.schema.table('tbm_sessions', function(table) { + table.integer('work_type_id').nullable().comment('공정 ID (work_types 참조)'); + table.integer('task_id').unsigned().nullable().comment('작업 ID (tasks 참조)'); + + // 외래키 추가 + table.foreign('work_type_id') + .references('id') + .inTable('work_types') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + table.foreign('task_id') + .references('task_id') + .inTable('tasks') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + // 인덱스 추가 + table.index('work_type_id'); + table.index('task_id'); + }).then(() => { + console.log('✅ tbm_sessions 테이블에 work_type_id, task_id 컬럼 추가 완료'); + }); +}; + +/** + * @param {import('knex').Knex} knex + */ +exports.down = function(knex) { + return knex.schema.table('tbm_sessions', function(table) { + table.dropForeign('work_type_id'); + table.dropForeign('task_id'); + table.dropColumn('work_type_id'); + table.dropColumn('task_id'); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010004_add_work_details_to_team_assignments.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010004_add_work_details_to_team_assignments.js new file mode 100644 index 0000000..3e4f6f6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260126010004_add_work_details_to_team_assignments.js @@ -0,0 +1,37 @@ +/** + * 마이그레이션: tbm_team_assignments 테이블 확장 + * 작업자별 프로젝트/공정/작업/작업장 정보 저장 가능하도록 컬럼 추가 및 외래키 설정 + */ + +exports.up = async function(knex) { + // 1. workplace_category_id와 workplace_id를 UNSIGNED로 변경 + await knex.raw(` + ALTER TABLE tbm_team_assignments + MODIFY COLUMN workplace_category_id INT UNSIGNED NULL COMMENT '작업자별 작업장 대분류 (공장)', + MODIFY COLUMN workplace_id INT UNSIGNED NULL COMMENT '작업자별 작업장 ID' + `); + + // 2. 외래키 제약조건 추가 + return knex.schema.alterTable('tbm_team_assignments', function(table) { + // 외래키 제약조건 추가 + table.foreign('workplace_category_id') + .references('category_id') + .inTable('workplace_categories') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + table.foreign('workplace_id') + .references('workplace_id') + .inTable('workplaces') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + }); +}; + +exports.down = function(knex) { + return knex.schema.alterTable('tbm_team_assignments', function(table) { + // 외래키 제약조건 제거 + table.dropForeign('workplace_category_id'); + table.dropForeign('workplace_id'); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127000001_remove_unused_tbm_fields.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127000001_remove_unused_tbm_fields.js new file mode 100644 index 0000000..1850a27 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127000001_remove_unused_tbm_fields.js @@ -0,0 +1,20 @@ +/** + * 마이그레이션: tbm_sessions 테이블에서 불필요한 컬럼 제거 + * work_description, safety_notes, start_time 컬럼 제거 + */ + +exports.up = function(knex) { + return knex.schema.alterTable('tbm_sessions', function(table) { + table.dropColumn('work_description'); + table.dropColumn('safety_notes'); + table.dropColumn('start_time'); + }); +}; + +exports.down = function(knex) { + return knex.schema.alterTable('tbm_sessions', function(table) { + table.text('work_description').nullable().comment('작업 내용'); + table.text('safety_notes').nullable().comment('안전 관련 특이사항'); + table.time('start_time').nullable().comment('시작 시간'); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127000002_add_workplace_map_images.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127000002_add_workplace_map_images.js new file mode 100644 index 0000000..2d276eb --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127000002_add_workplace_map_images.js @@ -0,0 +1,53 @@ +/** + * 마이그레이션: 작업장 지도 이미지 기능 추가 + * - workplace_categories에 layout_image 필드 추가 + * - workplace_map_regions 테이블 생성 (클릭 가능한 영역 정의) + */ + +exports.up = async function(knex) { + // 1. workplace_categories 테이블에 layout_image 필드 추가 + await knex.schema.alterTable('workplace_categories', function(table) { + table.string('layout_image', 500).nullable().comment('공장 배치도 이미지 경로'); + }); + + // 2. 작업장 지도 클릭 영역 정의 테이블 생성 + await knex.schema.createTable('workplace_map_regions', function(table) { + table.increments('region_id').primary().comment('영역 ID'); + table.integer('workplace_id').unsigned().notNullable().comment('작업장 ID'); + table.integer('category_id').unsigned().notNullable().comment('공장 카테고리 ID'); + + // 좌표 정보 (비율 기반: 0~100%) + table.decimal('x_start', 5, 2).notNullable().comment('시작 X 좌표 (%)'); + table.decimal('y_start', 5, 2).notNullable().comment('시작 Y 좌표 (%)'); + table.decimal('x_end', 5, 2).notNullable().comment('끝 X 좌표 (%)'); + table.decimal('y_end', 5, 2).notNullable().comment('끝 Y 좌표 (%)'); + + table.string('shape', 20).defaultTo('rect').comment('영역 모양 (rect, circle, polygon)'); + table.text('polygon_points').nullable().comment('다각형인 경우 좌표 배열 (JSON)'); + + table.timestamps(true, true); + + // 외래키 + table.foreign('workplace_id') + .references('workplace_id') + .inTable('workplaces') + .onDelete('CASCADE') + .onUpdate('CASCADE'); + + table.foreign('category_id') + .references('category_id') + .inTable('workplace_categories') + .onDelete('CASCADE') + .onUpdate('CASCADE'); + }); +}; + +exports.down = async function(knex) { + // 테이블 삭제 + await knex.schema.dropTableIfExists('workplace_map_regions'); + + // 필드 제거 + await knex.schema.alterTable('workplace_categories', function(table) { + table.dropColumn('layout_image'); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127010000_add_workplace_purpose_fields.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127010000_add_workplace_purpose_fields.js new file mode 100644 index 0000000..022ed3d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127010000_add_workplace_purpose_fields.js @@ -0,0 +1,17 @@ +/** + * 마이그레이션: 작업장 용도 및 표시 순서 필드 추가 + */ + +exports.up = function(knex) { + return knex.schema.alterTable('workplaces', function(table) { + table.string('workplace_purpose', 50).nullable().comment('작업장 용도 (작업구역, 설비, 휴게시설, 회의실 등)'); + table.integer('display_priority').defaultTo(0).comment('표시 우선순위 (숫자가 작을수록 먼저 표시)'); + }); +}; + +exports.down = function(knex) { + return knex.schema.alterTable('workplaces', function(table) { + table.dropColumn('workplace_purpose'); + table.dropColumn('display_priority'); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127020000_make_leader_id_nullable.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127020000_make_leader_id_nullable.js new file mode 100644 index 0000000..f05ed42 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127020000_make_leader_id_nullable.js @@ -0,0 +1,30 @@ +/** + * leader_id를 nullable로 변경 + * 관리자가 TBM을 입력할 때 leader_id를 NULL로 설정하고 created_by를 사용 + */ + +exports.up = async function(knex) { + // 1. 외래 키 제약조건 삭제 (존재하는 경우에만) + try { + await knex.raw('ALTER TABLE tbm_sessions DROP FOREIGN KEY tbm_sessions_leader_id_foreign'); + } catch (err) { + console.log('외래 키가 이미 존재하지 않음 (정상)'); + } + + // 2. leader_id를 nullable로 변경 (UNSIGNED 제거하여 workers.worker_id와 타입 일치) + await knex.raw('ALTER TABLE tbm_sessions MODIFY leader_id INT(11) NULL'); + + // 3. 외래 키 제약조건 다시 추가 (nullable 허용) + await knex.raw('ALTER TABLE tbm_sessions ADD CONSTRAINT tbm_sessions_leader_id_foreign FOREIGN KEY (leader_id) REFERENCES workers(worker_id) ON DELETE SET NULL'); +}; + +exports.down = async function(knex) { + // 1. 외래 키 제약조건 삭제 + await knex.raw('ALTER TABLE tbm_sessions DROP FOREIGN KEY tbm_sessions_leader_id_foreign'); + + // 2. leader_id를 NOT NULL로 되돌림 + await knex.raw('ALTER TABLE tbm_sessions MODIFY leader_id INT(11) NOT NULL'); + + // 3. 외래 키 제약조건 다시 추가 + await knex.raw('ALTER TABLE tbm_sessions ADD CONSTRAINT tbm_sessions_leader_id_foreign FOREIGN KEY (leader_id) REFERENCES workers(worker_id) ON DELETE CASCADE'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127030000_add_tbm_fields_to_work_reports.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127030000_add_tbm_fields_to_work_reports.js new file mode 100644 index 0000000..6d6ac4e --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127030000_add_tbm_fields_to_work_reports.js @@ -0,0 +1,55 @@ +/** + * daily_work_reports 테이블에 TBM 연동 필드 추가 + * - TBM 세션 및 팀 배정과 연결 + * - 작업 시간 및 오류 시간 추적 + */ + +exports.up = async function(knex) { + await knex.schema.table('daily_work_reports', (table) => { + // TBM 연동 필드 + table.integer('tbm_session_id').unsigned().nullable() + .comment('연결된 TBM 세션 ID'); + table.integer('tbm_assignment_id').unsigned().nullable() + .comment('연결된 TBM 팀 배정 ID'); + + // 작업 시간 추적 + table.time('start_time').nullable() + .comment('작업 시작 시간'); + table.time('end_time').nullable() + .comment('작업 종료 시간'); + table.decimal('total_hours', 5, 2).nullable() + .comment('총 작업 시간'); + table.decimal('regular_hours', 5, 2).nullable() + .comment('정규 작업 시간 (총 시간 - 오류 시간)'); + table.decimal('error_hours', 5, 2).nullable() + .comment('부적합 사항 처리 시간'); + + // 외래 키 제약조건 + table.foreign('tbm_session_id') + .references('session_id') + .inTable('tbm_sessions') + .onDelete('SET NULL'); + + table.foreign('tbm_assignment_id') + .references('assignment_id') + .inTable('tbm_team_assignments') + .onDelete('SET NULL'); + }); +}; + +exports.down = async function(knex) { + await knex.schema.table('daily_work_reports', (table) => { + // 외래 키 제약조건 삭제 + table.dropForeign('tbm_session_id'); + table.dropForeign('tbm_assignment_id'); + + // 컬럼 삭제 + table.dropColumn('tbm_session_id'); + table.dropColumn('tbm_assignment_id'); + table.dropColumn('start_time'); + table.dropColumn('end_time'); + table.dropColumn('total_hours'); + table.dropColumn('regular_hours'); + table.dropColumn('error_hours'); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127040000_update_pages_for_current_system.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127040000_update_pages_for_current_system.js new file mode 100644 index 0000000..4a19ab6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260127040000_update_pages_for_current_system.js @@ -0,0 +1,152 @@ +/** + * 현재 사용 중인 페이지를 pages 테이블에 업데이트 + */ + +exports.up = async function(knex) { + // 기존 페이지 모두 삭제 + await knex('pages').del(); + + // 현재 사용 중인 페이지들을 등록 + await knex('pages').insert([ + // 공통 페이지 + { + page_key: 'dashboard', + page_name: '대시보드', + page_path: '/pages/dashboard.html', + category: 'common', + description: '전체 현황 대시보드', + is_admin_only: 0, + display_order: 1 + }, + + // 작업 관련 페이지 + { + page_key: 'work.tbm', + page_name: 'TBM', + page_path: '/pages/work/tbm.html', + category: 'work', + description: 'TBM (Tool Box Meeting) 관리', + is_admin_only: 0, + display_order: 10 + }, + { + page_key: 'work.report_create', + page_name: '작업보고서 작성', + page_path: '/pages/work/report-create.html', + category: 'work', + description: '일일 작업보고서 작성', + is_admin_only: 0, + display_order: 11 + }, + { + page_key: 'work.report_view', + page_name: '작업보고서 조회', + page_path: '/pages/work/report-view.html', + category: 'work', + description: '작업보고서 조회 및 검색', + is_admin_only: 0, + display_order: 12 + }, + { + page_key: 'work.analysis', + page_name: '작업 분석', + page_path: '/pages/work/analysis.html', + category: 'work', + description: '작업 통계 및 분석', + is_admin_only: 0, + display_order: 13 + }, + + // Admin 페이지 + { + page_key: 'admin.accounts', + page_name: '계정 관리', + page_path: '/pages/admin/accounts.html', + category: 'admin', + description: '사용자 계정 관리', + is_admin_only: 1, + display_order: 20 + }, + { + page_key: 'admin.page_access', + page_name: '페이지 권한 관리', + page_path: '/pages/admin/page-access.html', + category: 'admin', + description: '사용자별 페이지 접근 권한 관리', + is_admin_only: 1, + display_order: 21 + }, + { + page_key: 'admin.workers', + page_name: '작업자 관리', + page_path: '/pages/admin/workers.html', + category: 'admin', + description: '작업자 정보 관리', + is_admin_only: 1, + display_order: 22 + }, + { + page_key: 'admin.projects', + page_name: '프로젝트 관리', + page_path: '/pages/admin/projects.html', + category: 'admin', + description: '프로젝트 관리', + is_admin_only: 1, + display_order: 23 + }, + { + page_key: 'admin.workplaces', + page_name: '작업장 관리', + page_path: '/pages/admin/workplaces.html', + category: 'admin', + description: '작업장소 관리', + is_admin_only: 1, + display_order: 24 + }, + { + page_key: 'admin.codes', + page_name: '코드 관리', + page_path: '/pages/admin/codes.html', + category: 'admin', + description: '시스템 코드 관리', + is_admin_only: 1, + display_order: 25 + }, + { + page_key: 'admin.tasks', + page_name: '작업 관리', + page_path: '/pages/admin/tasks.html', + category: 'admin', + description: '작업 유형 관리', + is_admin_only: 1, + display_order: 26 + }, + + // 프로필 페이지 + { + page_key: 'profile.info', + page_name: '내 정보', + page_path: '/pages/profile/info.html', + category: 'profile', + description: '내 프로필 정보', + is_admin_only: 0, + display_order: 30 + }, + { + page_key: 'profile.password', + page_name: '비밀번호 변경', + page_path: '/pages/profile/password.html', + category: 'profile', + description: '비밀번호 변경', + is_admin_only: 0, + display_order: 31 + } + ]); + + console.log('✅ 현재 사용 중인 페이지 목록 업데이트 완료'); +}; + +exports.down = async function(knex) { + await knex('pages').del(); + console.log('✅ 페이지 목록 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260128000000_add_layout_image_to_workplaces.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260128000000_add_layout_image_to_workplaces.js new file mode 100644 index 0000000..c4a5db4 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260128000000_add_layout_image_to_workplaces.js @@ -0,0 +1,22 @@ +/** + * 작업장 테이블에 레이아웃 이미지 컬럼 추가 + * + * @author TK-FB-Project + * @since 2026-01-28 + */ + +exports.up = async function(knex) { + await knex.schema.table('workplaces', (table) => { + table.string('layout_image', 500).nullable().comment('작업장 레이아웃 이미지 경로'); + }); + + console.log('✅ workplaces 테이블에 layout_image 컬럼 추가 완료'); +}; + +exports.down = async function(knex) { + await knex.schema.table('workplaces', (table) => { + table.dropColumn('layout_image'); + }); + + console.log('✅ workplaces 테이블에서 layout_image 컬럼 제거 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260128010000_create_equipments_table.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260128010000_create_equipments_table.js new file mode 100644 index 0000000..c1fb50b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260128010000_create_equipments_table.js @@ -0,0 +1,48 @@ +/** + * 설비 관리 테이블 생성 + * + * @author TK-FB-Project + * @since 2026-01-28 + */ + +exports.up = async function(knex) { + await knex.schema.createTable('equipments', (table) => { + table.increments('equipment_id').primary().comment('설비 ID'); + table.string('equipment_code', 50).notNullable().unique().comment('설비 코드 (예: CNC-01, LATHE-A)'); + table.string('equipment_name', 100).notNullable().comment('설비명'); + table.string('equipment_type', 50).nullable().comment('설비 유형 (예: CNC, 선반, 밀링 등)'); + table.string('model_name', 100).nullable().comment('모델명'); + table.string('manufacturer', 100).nullable().comment('제조사'); + table.date('installation_date').nullable().comment('설치일'); + table.string('serial_number', 100).nullable().comment('시리얼 번호'); + table.text('specifications').nullable().comment('사양 정보 (JSON 형태로 저장 가능)'); + table.enum('status', ['active', 'maintenance', 'inactive']).defaultTo('active').comment('설비 상태'); + table.text('notes').nullable().comment('비고'); + + // 작업장 연결 + table.integer('workplace_id').unsigned().nullable().comment('연결된 작업장 ID'); + table.foreign('workplace_id').references('workplace_id').inTable('workplaces').onDelete('SET NULL'); + + // 지도상 위치 정보 (백분율 기반) + table.decimal('map_x_percent', 5, 2).nullable().comment('지도상 X 위치 (%)'); + table.decimal('map_y_percent', 5, 2).nullable().comment('지도상 Y 위치 (%)'); + table.decimal('map_width_percent', 5, 2).nullable().comment('지도상 영역 너비 (%)'); + table.decimal('map_height_percent', 5, 2).nullable().comment('지도상 영역 높이 (%)'); + + // 타임스탬프 + table.timestamp('created_at').defaultTo(knex.fn.now()).comment('생성일시'); + table.timestamp('updated_at').defaultTo(knex.fn.now()).comment('수정일시'); + + // 인덱스 + table.index('workplace_id'); + table.index('equipment_type'); + table.index('status'); + }); + + console.log('✅ equipments 테이블 생성 완료'); +}; + +exports.down = async function(knex) { + await knex.schema.dropTableIfExists('equipments'); + console.log('✅ equipments 테이블 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000000_create_vacation_requests.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000000_create_vacation_requests.js new file mode 100644 index 0000000..3cdc18d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000000_create_vacation_requests.js @@ -0,0 +1,57 @@ +/** + * Migration: Create vacation_requests table + * Purpose: Track vacation request workflow (request, approval/rejection) + * Date: 2026-01-29 + */ + +exports.up = async function(knex) { + // Create vacation_requests table + await knex.schema.createTable('vacation_requests', (table) => { + table.increments('request_id').primary().comment('휴가 신청 ID'); + + // 작업자 정보 + table.integer('worker_id').notNullable().comment('작업자 ID'); + table.foreign('worker_id').references('worker_id').inTable('workers').onDelete('CASCADE'); + + // 휴가 정보 + table.integer('vacation_type_id').unsigned().notNullable().comment('휴가 유형 ID'); + table.foreign('vacation_type_id').references('id').inTable('vacation_types').onDelete('RESTRICT'); + + table.date('start_date').notNullable().comment('휴가 시작일'); + table.date('end_date').notNullable().comment('휴가 종료일'); + table.decimal('days_used', 4, 1).notNullable().comment('사용 일수 (0.5일 단위)'); + + table.text('reason').nullable().comment('휴가 사유'); + + // 신청 및 승인 정보 + table.enum('status', ['pending', 'approved', 'rejected']) + .notNullable() + .defaultTo('pending') + .comment('승인 상태: pending(대기), approved(승인), rejected(거부)'); + + table.integer('requested_by').notNullable().comment('신청자 user_id'); + table.foreign('requested_by').references('user_id').inTable('users').onDelete('RESTRICT'); + + table.integer('reviewed_by').nullable().comment('승인/거부자 user_id'); + table.foreign('reviewed_by').references('user_id').inTable('users').onDelete('SET NULL'); + + table.timestamp('reviewed_at').nullable().comment('승인/거부 일시'); + table.text('review_note').nullable().comment('승인/거부 메모'); + + // 타임스탬프 + table.timestamp('created_at').defaultTo(knex.fn.now()).comment('신청 일시'); + table.timestamp('updated_at').defaultTo(knex.fn.now()).comment('수정 일시'); + + // 인덱스 + table.index('worker_id', 'idx_vacation_requests_worker'); + table.index('status', 'idx_vacation_requests_status'); + table.index(['start_date', 'end_date'], 'idx_vacation_requests_dates'); + }); + + console.log('✅ vacation_requests 테이블 생성 완료'); +}; + +exports.down = async function(knex) { + await knex.schema.dropTableIfExists('vacation_requests'); + console.log('✅ vacation_requests 테이블 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000001_register_attendance_pages.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000001_register_attendance_pages.js new file mode 100644 index 0000000..e9ee5c9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000001_register_attendance_pages.js @@ -0,0 +1,84 @@ +/** + * Migration: Register attendance management pages + * Purpose: Add 4 new pages to pages table for attendance management system + * Date: 2026-01-29 + */ + +exports.up = async function(knex) { + // 페이지 등록 (실제 pages 테이블 컬럼에 맞춤) + await knex('pages').insert([ + { + page_key: 'daily-attendance', + page_name: '일일 출퇴근 입력', + page_path: '/pages/common/daily-attendance.html', + description: '일일 출퇴근 기록 입력 페이지 (관리자/조장)', + category: 'common', + is_admin_only: false, + display_order: 50 + }, + { + page_key: 'monthly-attendance', + page_name: '월별 출퇴근 현황', + page_path: '/pages/common/monthly-attendance.html', + description: '월별 출퇴근 현황 조회 페이지', + category: 'common', + is_admin_only: false, + display_order: 51 + }, + { + page_key: 'vacation-management', + page_name: '휴가 관리', + page_path: '/pages/common/vacation-management.html', + description: '휴가 신청 및 승인 관리 페이지', + category: 'common', + is_admin_only: false, + display_order: 52 + }, + { + page_key: 'attendance-report-comparison', + page_name: '출퇴근-작업보고서 대조', + page_path: '/pages/admin/attendance-report-comparison.html', + description: '출퇴근 기록과 작업보고서 대조 페이지 (관리자)', + category: 'admin', + is_admin_only: true, + display_order: 120 + } + ]); + + console.log('✅ 출퇴근 관리 페이지 4개 등록 완료'); + + // Admin 사용자(user_id=1)에게 페이지 접근 권한 부여 + const adminUserId = 1; + const pages = await knex('pages') + .whereIn('page_key', [ + 'daily-attendance', + 'monthly-attendance', + 'vacation-management', + 'attendance-report-comparison' + ]) + .select('id'); + + const accessRecords = pages.map(page => ({ + user_id: adminUserId, + page_id: page.id, + can_access: true, + granted_by: adminUserId + })); + + await knex('user_page_access').insert(accessRecords); + console.log('✅ Admin 사용자에게 출퇴근 관리 페이지 접근 권한 부여 완료'); +}; + +exports.down = async function(knex) { + // 페이지 삭제 (user_page_access는 FK CASCADE로 자동 삭제됨) + await knex('pages') + .whereIn('page_key', [ + 'daily-attendance', + 'monthly-attendance', + 'vacation-management', + 'attendance-report-comparison' + ]) + .delete(); + + console.log('✅ 출퇴근 관리 페이지 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000002_add_attendance_is_present.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000002_add_attendance_is_present.js new file mode 100644 index 0000000..0ebafd3 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000002_add_attendance_is_present.js @@ -0,0 +1,35 @@ +/** + * 출퇴근 출근 여부 필드 추가 + * 아침 출근 확인용 간단한 필드 + */ + +exports.up = async function(knex) { + // 컬럼 존재 여부 확인 + const hasColumn = await knex.schema.hasColumn('daily_attendance_records', 'is_present'); + + if (!hasColumn) { + await knex.schema.table('daily_attendance_records', (table) => { + // 출근 여부 (아침에 체크) + table.boolean('is_present').defaultTo(true).comment('출근 여부'); + }); + + // 기존 데이터는 모두 출근으로 처리 + await knex('daily_attendance_records') + .whereNotNull('id') + .update({ is_present: true }); + + console.log('✅ is_present 컬럼 추가 완료'); + } else { + console.log('⏭️ is_present 컬럼이 이미 존재합니다'); + } +}; + +exports.down = async function(knex) { + const hasColumn = await knex.schema.hasColumn('daily_attendance_records', 'is_present'); + + if (hasColumn) { + await knex.schema.table('daily_attendance_records', (table) => { + table.dropColumn('is_present'); + }); + } +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000003_update_vacation_pages.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000003_update_vacation_pages.js new file mode 100644 index 0000000..54b57c9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000003_update_vacation_pages.js @@ -0,0 +1,57 @@ +/** + * 휴가 관리 페이지 분리 및 등록 + * - 기존 vacation-management.html을 2개 페이지로 분리 + * - vacation-request.html: 작업자 휴가 신청 및 본인 내역 확인 + * - vacation-management.html: 관리자 휴가 승인/직접입력/전체내역 (3개 탭) + */ + +exports.up = async function(knex) { + // 기존 vacation-management 페이지 삭제 + await knex('pages') + .where('page_key', 'vacation-management') + .del(); + + // 새로운 휴가 관리 페이지 2개 등록 + await knex('pages').insert([ + { + page_key: 'vacation-request', + page_name: '휴가 신청', + page_path: '/pages/common/vacation-request.html', + category: 'common', + description: '작업자가 휴가를 신청하고 본인의 신청 내역을 확인하는 페이지', + is_admin_only: 0, + display_order: 51 + }, + { + page_key: 'vacation-management', + page_name: '휴가 관리', + page_path: '/pages/common/vacation-management.html', + category: 'common', + description: '관리자가 휴가 승인, 직접 입력, 전체 내역을 관리하는 페이지', + is_admin_only: 1, + display_order: 52 + } + ]); + + console.log('✅ 휴가 관리 페이지 분리 완료 (기존 1개 → 신규 2개)'); +}; + +exports.down = async function(knex) { + // 새로운 페이지 삭제 + await knex('pages') + .whereIn('page_key', ['vacation-request', 'vacation-management']) + .del(); + + // 기존 vacation-management 페이지 복원 + await knex('pages').insert({ + page_key: 'vacation-management', + page_name: '휴가 관리', + page_path: '/pages/common/vacation-management.html.old', + category: 'common', + description: '휴가 신청 및 승인 관리', + is_admin_only: 0, + display_order: 50 + }); + + console.log('✅ 휴가 관리 페이지 롤백 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000004_extend_vacation_types.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000004_extend_vacation_types.js new file mode 100644 index 0000000..0672e80 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000004_extend_vacation_types.js @@ -0,0 +1,55 @@ +/** + * vacation_types 테이블 확장 + * - 특별 휴가 유형 추가 기능 + * - 차감 우선순위 관리 + * - 시스템 기본 휴가 보호 + */ + +exports.up = async function(knex) { + // vacation_types 테이블 확장 + await knex.schema.table('vacation_types', (table) => { + table.boolean('is_special').defaultTo(false).comment('특별 휴가 여부 (장기근속, 출산 등)'); + table.integer('priority').defaultTo(99).comment('차감 우선순위 (낮을수록 먼저 차감)'); + table.text('description').nullable().comment('휴가 설명'); + table.boolean('is_system').defaultTo(true).comment('시스템 기본 휴가 (삭제 불가)'); + }); + + // 기존 휴가 유형에 우선순위 설정 + await knex('vacation_types').where('type_code', 'ANNUAL').update({ + priority: 10, + is_system: true, + description: '근로기준법에 따른 연차 유급휴가' + }); + + await knex('vacation_types').where('type_code', 'HALF_ANNUAL').update({ + priority: 10, + is_system: true, + description: '반일 연차 (0.5일)' + }); + + await knex('vacation_types').where('type_code', 'SICK').update({ + priority: 20, + is_system: true, + description: '병가' + }); + + await knex('vacation_types').where('type_code', 'SPECIAL').update({ + priority: 0, + is_system: true, + description: '경조사 휴가 (무급)' + }); + + console.log('✅ vacation_types 테이블 확장 완료'); +}; + +exports.down = async function(knex) { + // 컬럼 삭제 + await knex.schema.table('vacation_types', (table) => { + table.dropColumn('is_special'); + table.dropColumn('priority'); + table.dropColumn('description'); + table.dropColumn('is_system'); + }); + + console.log('✅ vacation_types 테이블 롤백 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000005_create_vacation_balance_details.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000005_create_vacation_balance_details.js new file mode 100644 index 0000000..75b8f7b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000005_create_vacation_balance_details.js @@ -0,0 +1,87 @@ +/** + * vacation_balance_details 테이블 생성 및 데이터 마이그레이션 + * - 작업자별, 휴가 유형별, 연도별 휴가 잔액 관리 + * - 기존 worker_vacation_balance 데이터 이관 + */ + +exports.up = async function(knex) { + // vacation_balance_details 테이블 생성 + await knex.schema.createTable('vacation_balance_details', (table) => { + table.increments('id').primary(); + table.integer('worker_id').notNullable().comment('작업자 ID'); + table.integer('vacation_type_id').unsigned().notNullable().comment('휴가 유형 ID'); + table.integer('year').notNullable().comment('연도'); + table.decimal('total_days', 4, 1).defaultTo(0).comment('총 발생 일수'); + table.decimal('used_days', 4, 1).defaultTo(0).comment('사용 일수'); + table.text('notes').nullable().comment('비고'); + table.integer('created_by').notNullable().comment('생성자 ID'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + // 인덱스 + table.unique(['worker_id', 'vacation_type_id', 'year'], 'unique_worker_vacation_year'); + table.index(['worker_id', 'year'], 'idx_worker_year'); + table.index('vacation_type_id', 'idx_vacation_type'); + + // 외래키 + table.foreign('worker_id').references('worker_id').inTable('workers').onDelete('CASCADE'); + table.foreign('vacation_type_id').references('id').inTable('vacation_types').onDelete('RESTRICT'); + table.foreign('created_by').references('user_id').inTable('users'); + }); + + // remaining_days를 generated column으로 추가 (Raw SQL) + await knex.raw(` + ALTER TABLE vacation_balance_details + ADD COLUMN remaining_days DECIMAL(4,1) + GENERATED ALWAYS AS (total_days - used_days) STORED + COMMENT '잔여 일수' + `); + + console.log('✅ vacation_balance_details 테이블 생성 완료'); + + // 기존 worker_vacation_balance 데이터를 vacation_balance_details로 마이그레이션 + const existingBalances = await knex('worker_vacation_balance').select('*'); + + if (existingBalances.length > 0) { + // ANNUAL 휴가 유형 ID 조회 + const annualType = await knex('vacation_types') + .where('type_code', 'ANNUAL') + .first(); + + if (!annualType) { + throw new Error('ANNUAL 휴가 유형을 찾을 수 없습니다'); + } + + // 관리자 사용자 ID 조회 (created_by 용) + // role_id 1 = System Admin, 2 = Admin + const adminUser = await knex('users') + .whereIn('role_id', [1, 2]) + .first(); + + const createdById = adminUser ? adminUser.user_id : 1; + + // 데이터 변환 및 삽입 + const balanceDetails = existingBalances.map(balance => ({ + worker_id: balance.worker_id, + vacation_type_id: annualType.id, + year: balance.year, + total_days: balance.total_annual_leave || 0, + used_days: balance.used_annual_leave || 0, + notes: 'Migrated from worker_vacation_balance', + created_by: createdById, + created_at: balance.created_at, + updated_at: balance.updated_at + })); + + await knex('vacation_balance_details').insert(balanceDetails); + + console.log(`✅ ${balanceDetails.length}건의 기존 휴가 데이터 마이그레이션 완료`); + } +}; + +exports.down = async function(knex) { + // vacation_balance_details 테이블 삭제 + await knex.schema.dropTableIfExists('vacation_balance_details'); + + console.log('✅ vacation_balance_details 테이블 롤백 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000006_register_vacation_pages.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000006_register_vacation_pages.js new file mode 100644 index 0000000..0773a7f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129000006_register_vacation_pages.js @@ -0,0 +1,38 @@ +/** + * 새로운 휴가 관리 페이지 등록 + * - annual-vacation-overview: 연간 연차 현황 (차트) + * - vacation-allocation: 휴가 발생 입력 및 관리 + */ + +exports.up = async function(knex) { + await knex('pages').insert([ + { + page_key: 'annual-vacation-overview', + page_name: '연간 연차 현황', + page_path: '/pages/common/annual-vacation-overview.html', + category: 'common', + description: '모든 작업자의 연간 연차 현황을 차트로 시각화', + is_admin_only: 1, + display_order: 54 + }, + { + page_key: 'vacation-allocation', + page_name: '휴가 발생 입력', + page_path: '/pages/common/vacation-allocation.html', + category: 'common', + description: '작업자별 휴가 발생 입력 및 특별 휴가 관리', + is_admin_only: 1, + display_order: 55 + } + ]); + + console.log('✅ 휴가 관리 신규 페이지 2개 등록 완료'); +}; + +exports.down = async function(knex) { + await knex('pages') + .whereIn('page_key', ['annual-vacation-overview', 'vacation-allocation']) + .del(); + + console.log('✅ 휴가 관리 페이지 롤백 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129010000_create_visit_request_system.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129010000_create_visit_request_system.js new file mode 100644 index 0000000..ae65516 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129010000_create_visit_request_system.js @@ -0,0 +1,153 @@ +/** + * 마이그레이션: 출입 신청 및 안전교육 시스템 + * - 방문 목적 타입 테이블 + * - 출입 신청 테이블 + * - 안전교육 기록 테이블 + */ + +exports.up = async function(knex) { + // 1. 방문 목적 타입 테이블 생성 + await knex.schema.createTable('visit_purpose_types', function(table) { + table.increments('purpose_id').primary().comment('방문 목적 ID'); + table.string('purpose_name', 100).notNullable().comment('방문 목적명'); + table.integer('display_order').defaultTo(0).comment('표시 순서'); + table.boolean('is_active').defaultTo(true).comment('활성 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + }); + + // 초기 데이터 삽입 + await knex('visit_purpose_types').insert([ + { purpose_name: '외주작업', display_order: 1, is_active: true }, + { purpose_name: '검사', display_order: 2, is_active: true }, + { purpose_name: '견학', display_order: 3, is_active: true }, + { purpose_name: '기타', display_order: 99, is_active: true } + ]); + + // 2. 출입 신청 테이블 생성 + await knex.schema.createTable('workplace_visit_requests', function(table) { + table.increments('request_id').primary().comment('신청 ID'); + + // 신청자 정보 + table.integer('requester_id').notNullable().comment('신청자 user_id'); + + // 방문자 정보 + table.string('visitor_company', 200).notNullable().comment('방문자 소속 (회사명 또는 "일용직")'); + table.integer('visitor_count').defaultTo(1).comment('방문 인원'); + + // 방문 장소 + table.integer('category_id').unsigned().notNullable().comment('방문 구역 (공장)'); + table.integer('workplace_id').unsigned().notNullable().comment('방문 작업장'); + + // 방문 일시 + table.date('visit_date').notNullable().comment('방문 날짜'); + table.time('visit_time').notNullable().comment('방문 시간'); + + // 방문 목적 + table.integer('purpose_id').unsigned().notNullable().comment('방문 목적 ID'); + table.text('notes').nullable().comment('비고'); + + // 상태 관리 + table.enum('status', ['pending', 'approved', 'rejected', 'training_completed']) + .defaultTo('pending') + .comment('신청 상태'); + + // 승인 정보 + table.integer('approved_by').nullable().comment('승인자 user_id'); + table.timestamp('approved_at').nullable().comment('승인 시간'); + table.text('rejection_reason').nullable().comment('반려 사유'); + + // 타임스탬프 + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + // 외래키 + table.foreign('requester_id') + .references('user_id') + .inTable('users') + .onDelete('RESTRICT') + .onUpdate('CASCADE'); + + table.foreign('category_id') + .references('category_id') + .inTable('workplace_categories') + .onDelete('RESTRICT') + .onUpdate('CASCADE'); + + table.foreign('workplace_id') + .references('workplace_id') + .inTable('workplaces') + .onDelete('RESTRICT') + .onUpdate('CASCADE'); + + table.foreign('purpose_id') + .references('purpose_id') + .inTable('visit_purpose_types') + .onDelete('RESTRICT') + .onUpdate('CASCADE'); + + table.foreign('approved_by') + .references('user_id') + .inTable('users') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + // 인덱스 + table.index('visit_date', 'idx_visit_date'); + table.index('status', 'idx_status'); + table.index(['visit_date', 'status'], 'idx_visit_date_status'); + }); + + // 3. 안전교육 기록 테이블 생성 + await knex.schema.createTable('safety_training_records', function(table) { + table.increments('training_id').primary().comment('교육 기록 ID'); + + table.integer('request_id').unsigned().notNullable().comment('출입 신청 ID'); + + // 교육 진행 정보 + table.integer('trainer_id').notNullable().comment('교육 진행자 user_id'); + table.date('training_date').notNullable().comment('교육 날짜'); + table.time('training_start_time').notNullable().comment('교육 시작 시간'); + table.time('training_end_time').nullable().comment('교육 종료 시간'); + + // 교육 내용 + table.text('training_topics').nullable().comment('교육 내용 (JSON 배열)'); + + // 서명 데이터 (Base64 이미지) + table.text('signature_data', 'longtext').nullable().comment('교육 이수자 서명 (Base64 PNG)'); + + // 완료 정보 + table.timestamp('completed_at').nullable().comment('교육 완료 시간'); + + // 타임스탬프 + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + // 외래키 + table.foreign('request_id') + .references('request_id') + .inTable('workplace_visit_requests') + .onDelete('CASCADE') + .onUpdate('CASCADE'); + + table.foreign('trainer_id') + .references('user_id') + .inTable('users') + .onDelete('RESTRICT') + .onUpdate('CASCADE'); + + // 인덱스 + table.index('training_date', 'idx_training_date'); + table.index('request_id', 'idx_request_id'); + }); + + console.log('✅ 출입 신청 및 안전교육 시스템 테이블 생성 완료'); +}; + +exports.down = async function(knex) { + // 역순으로 테이블 삭제 + await knex.schema.dropTableIfExists('safety_training_records'); + await knex.schema.dropTableIfExists('workplace_visit_requests'); + await knex.schema.dropTableIfExists('visit_purpose_types'); + + console.log('✅ 출입 신청 및 안전교육 시스템 테이블 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129010001_register_visit_pages.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129010001_register_visit_pages.js new file mode 100644 index 0000000..6721083 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260129010001_register_visit_pages.js @@ -0,0 +1,50 @@ +/** + * 마이그레이션: 출입 신청 및 안전관리 페이지 등록 + */ + +exports.up = async function(knex) { + // 1. 출입 신청 페이지 등록 + await knex('pages').insert({ + page_key: 'visit-request', + page_name: '출입 신청', + page_path: '/pages/work/visit-request.html', + category: 'work', + description: '작업장 출입 신청 및 안전교육 신청', + is_admin_only: 0, + display_order: 15 + }); + + // 2. 안전관리 대시보드 페이지 등록 + await knex('pages').insert({ + page_key: 'safety-management', + page_name: '안전관리', + page_path: '/pages/admin/safety-management.html', + category: 'admin', + description: '출입 신청 승인 및 안전교육 관리', + is_admin_only: 0, + display_order: 60 + }); + + // 3. 안전교육 진행 페이지 등록 + await knex('pages').insert({ + page_key: 'safety-training-conduct', + page_name: '안전교육 진행', + page_path: '/pages/admin/safety-training-conduct.html', + category: 'admin', + description: '안전교육 실시 및 서명 관리', + is_admin_only: 0, + display_order: 61 + }); + + console.log('✅ 출입 신청 및 안전관리 페이지 등록 완료'); +}; + +exports.down = async function(knex) { + await knex('pages').whereIn('page_key', [ + 'visit-request', + 'safety-management', + 'safety-training-conduct' + ]).delete(); + + console.log('✅ 출입 신청 및 안전관리 페이지 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260130000001_create_work_issue_system.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260130000001_create_work_issue_system.js new file mode 100644 index 0000000..73af1b1 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260130000001_create_work_issue_system.js @@ -0,0 +1,266 @@ +/** + * 마이그레이션: 작업 중 문제 신고 시스템 + * - 신고 카테고리 테이블 (부적합/안전) + * - 사전 정의 신고 항목 테이블 + * - 문제 신고 메인 테이블 + * - 상태 변경 이력 테이블 + */ + +exports.up = async function(knex) { + // 1. 신고 카테고리 테이블 생성 + await knex.schema.createTable('issue_report_categories', function(table) { + table.increments('category_id').primary().comment('카테고리 ID'); + table.enum('category_type', ['nonconformity', 'safety']).notNullable().comment('카테고리 유형 (부적합/안전)'); + table.string('category_name', 100).notNullable().comment('카테고리명'); + table.text('description').nullable().comment('카테고리 설명'); + table.integer('display_order').defaultTo(0).comment('표시 순서'); + table.boolean('is_active').defaultTo(true).comment('활성 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + + table.index('category_type', 'idx_irc_category_type'); + table.index('is_active', 'idx_irc_is_active'); + }); + + // 카테고리 초기 데이터 삽입 + await knex('issue_report_categories').insert([ + // 부적합 사항 + { category_type: 'nonconformity', category_name: '자재누락', display_order: 1, is_active: true }, + { category_type: 'nonconformity', category_name: '설계미스', display_order: 2, is_active: true }, + { category_type: 'nonconformity', category_name: '입고불량', display_order: 3, is_active: true }, + { category_type: 'nonconformity', category_name: '검사미스', display_order: 4, is_active: true }, + { category_type: 'nonconformity', category_name: '기타 부적합', display_order: 99, is_active: true }, + // 안전 관련 + { category_type: 'safety', category_name: '보호구 미착용', display_order: 1, is_active: true }, + { category_type: 'safety', category_name: '위험구역 출입', display_order: 2, is_active: true }, + { category_type: 'safety', category_name: '안전시설 파손', display_order: 3, is_active: true }, + { category_type: 'safety', category_name: '안전수칙 위반', display_order: 4, is_active: true }, + { category_type: 'safety', category_name: '기타 안전', display_order: 99, is_active: true } + ]); + + // 2. 사전 정의 신고 항목 테이블 생성 + await knex.schema.createTable('issue_report_items', function(table) { + table.increments('item_id').primary().comment('항목 ID'); + table.integer('category_id').unsigned().notNullable().comment('소속 카테고리 ID'); + table.string('item_name', 200).notNullable().comment('신고 항목명'); + table.text('description').nullable().comment('항목 설명'); + table.enum('severity', ['low', 'medium', 'high', 'critical']).defaultTo('medium').comment('심각도'); + table.integer('display_order').defaultTo(0).comment('표시 순서'); + table.boolean('is_active').defaultTo(true).comment('활성 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + + table.foreign('category_id') + .references('category_id') + .inTable('issue_report_categories') + .onDelete('CASCADE') + .onUpdate('CASCADE'); + + table.index('category_id', 'idx_iri_category_id'); + table.index('is_active', 'idx_iri_is_active'); + }); + + // 사전 정의 항목 초기 데이터 삽입 + await knex('issue_report_items').insert([ + // 자재누락 (category_id: 1) + { category_id: 1, item_name: '배관 자재 미입고', severity: 'high', display_order: 1 }, + { category_id: 1, item_name: '피팅류 부족', severity: 'medium', display_order: 2 }, + { category_id: 1, item_name: '밸브류 미입고', severity: 'high', display_order: 3 }, + { category_id: 1, item_name: '가스켓/볼트류 부족', severity: 'low', display_order: 4 }, + { category_id: 1, item_name: '서포트 자재 부족', severity: 'medium', display_order: 5 }, + + // 설계미스 (category_id: 2) + { category_id: 2, item_name: '도면 치수 오류', severity: 'high', display_order: 1 }, + { category_id: 2, item_name: '스펙 불일치', severity: 'high', display_order: 2 }, + { category_id: 2, item_name: '누락된 상세도', severity: 'medium', display_order: 3 }, + { category_id: 2, item_name: '간섭 발생', severity: 'critical', display_order: 4 }, + + // 입고불량 (category_id: 3) + { category_id: 3, item_name: '외관 불량', severity: 'medium', display_order: 1 }, + { category_id: 3, item_name: '치수 불량', severity: 'high', display_order: 2 }, + { category_id: 3, item_name: '수량 부족', severity: 'medium', display_order: 3 }, + { category_id: 3, item_name: '재질 불일치', severity: 'critical', display_order: 4 }, + + // 검사미스 (category_id: 4) + { category_id: 4, item_name: '치수 검사 누락', severity: 'high', display_order: 1 }, + { category_id: 4, item_name: '외관 검사 누락', severity: 'medium', display_order: 2 }, + { category_id: 4, item_name: '용접 검사 누락', severity: 'critical', display_order: 3 }, + { category_id: 4, item_name: '도장 검사 누락', severity: 'medium', display_order: 4 }, + + // 보호구 미착용 (category_id: 6) + { category_id: 6, item_name: '안전모 미착용', severity: 'high', display_order: 1 }, + { category_id: 6, item_name: '안전화 미착용', severity: 'high', display_order: 2 }, + { category_id: 6, item_name: '보안경 미착용', severity: 'medium', display_order: 3 }, + { category_id: 6, item_name: '안전대 미착용', severity: 'critical', display_order: 4 }, + { category_id: 6, item_name: '귀마개 미착용', severity: 'low', display_order: 5 }, + { category_id: 6, item_name: '안전장갑 미착용', severity: 'medium', display_order: 6 }, + + // 위험구역 출입 (category_id: 7) + { category_id: 7, item_name: '통제구역 무단 출입', severity: 'critical', display_order: 1 }, + { category_id: 7, item_name: '고소 작업 구역 무단 출입', severity: 'critical', display_order: 2 }, + { category_id: 7, item_name: '밀폐공간 무단 진입', severity: 'critical', display_order: 3 }, + { category_id: 7, item_name: '장비 가동 구역 무단 접근', severity: 'high', display_order: 4 }, + + // 안전시설 파손 (category_id: 8) + { category_id: 8, item_name: '안전난간 파손', severity: 'high', display_order: 1 }, + { category_id: 8, item_name: '경고 표지판 훼손', severity: 'medium', display_order: 2 }, + { category_id: 8, item_name: '안전망 파손', severity: 'high', display_order: 3 }, + { category_id: 8, item_name: '비상조명 고장', severity: 'medium', display_order: 4 }, + { category_id: 8, item_name: '소화설비 파손', severity: 'critical', display_order: 5 }, + + // 안전수칙 위반 (category_id: 9) + { category_id: 9, item_name: '지정 통로 미사용', severity: 'medium', display_order: 1 }, + { category_id: 9, item_name: '고소 작업 안전 미준수', severity: 'critical', display_order: 2 }, + { category_id: 9, item_name: '화기 작업 절차 미준수', severity: 'critical', display_order: 3 }, + { category_id: 9, item_name: '정리정돈 미흡', severity: 'low', display_order: 4 }, + { category_id: 9, item_name: '장비 조작 절차 미준수', severity: 'high', display_order: 5 } + ]); + + // 3. 문제 신고 메인 테이블 생성 + await knex.schema.createTable('work_issue_reports', function(table) { + table.increments('report_id').primary().comment('신고 ID'); + + // 신고자 정보 + table.integer('reporter_id').notNullable().comment('신고자 user_id'); + table.datetime('report_date').defaultTo(knex.fn.now()).comment('신고 일시'); + + // 위치 정보 + table.integer('factory_category_id').unsigned().nullable().comment('공장 카테고리 ID (지도 외 위치 시 null)'); + table.integer('workplace_id').unsigned().nullable().comment('작업장 ID (지도 외 위치 시 null)'); + table.string('custom_location', 200).nullable().comment('기타 위치 (지도 외 선택 시)'); + + // 작업 연결 정보 (선택적) + table.integer('tbm_session_id').unsigned().nullable().comment('연결된 TBM 세션'); + table.integer('visit_request_id').unsigned().nullable().comment('연결된 출입 신청'); + + // 신고 내용 + table.integer('issue_category_id').unsigned().notNullable().comment('신고 카테고리 ID'); + table.integer('issue_item_id').unsigned().nullable().comment('사전 정의 신고 항목 ID'); + table.text('additional_description').nullable().comment('추가 설명'); + + // 사진 (최대 5장) + table.string('photo_path1', 255).nullable().comment('사진 1'); + table.string('photo_path2', 255).nullable().comment('사진 2'); + table.string('photo_path3', 255).nullable().comment('사진 3'); + table.string('photo_path4', 255).nullable().comment('사진 4'); + table.string('photo_path5', 255).nullable().comment('사진 5'); + + // 상태 관리 + table.enum('status', ['reported', 'received', 'in_progress', 'completed', 'closed']) + .defaultTo('reported') + .comment('상태: 신고→접수→처리중→완료→종료'); + + // 담당자 배정 + table.string('assigned_department', 100).nullable().comment('담당 부서'); + table.integer('assigned_user_id').nullable().comment('담당자 user_id'); + table.datetime('assigned_at').nullable().comment('배정 일시'); + table.integer('assigned_by').nullable().comment('배정자 user_id'); + + // 처리 정보 + table.text('resolution_notes').nullable().comment('처리 내용'); + table.string('resolution_photo_path1', 255).nullable().comment('처리 완료 사진 1'); + table.string('resolution_photo_path2', 255).nullable().comment('처리 완료 사진 2'); + table.datetime('resolved_at').nullable().comment('처리 완료 일시'); + table.integer('resolved_by').nullable().comment('처리 완료자 user_id'); + + // 수정 이력 (JSON) + table.json('modification_history').nullable().comment('수정 이력 추적'); + + // 타임스탬프 + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + // 외래키 + table.foreign('reporter_id') + .references('user_id') + .inTable('users') + .onDelete('RESTRICT') + .onUpdate('CASCADE'); + + table.foreign('factory_category_id') + .references('category_id') + .inTable('workplace_categories') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + table.foreign('workplace_id') + .references('workplace_id') + .inTable('workplaces') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + table.foreign('issue_category_id') + .references('category_id') + .inTable('issue_report_categories') + .onDelete('RESTRICT') + .onUpdate('CASCADE'); + + table.foreign('issue_item_id') + .references('item_id') + .inTable('issue_report_items') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + table.foreign('assigned_user_id') + .references('user_id') + .inTable('users') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + table.foreign('assigned_by') + .references('user_id') + .inTable('users') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + table.foreign('resolved_by') + .references('user_id') + .inTable('users') + .onDelete('SET NULL') + .onUpdate('CASCADE'); + + // 인덱스 + table.index('reporter_id', 'idx_wir_reporter_id'); + table.index('status', 'idx_wir_status'); + table.index('report_date', 'idx_wir_report_date'); + table.index(['factory_category_id', 'workplace_id'], 'idx_wir_workplace'); + table.index('issue_category_id', 'idx_wir_issue_category'); + table.index('assigned_user_id', 'idx_wir_assigned_user'); + }); + + // 4. 상태 변경 이력 테이블 생성 + await knex.schema.createTable('work_issue_status_logs', function(table) { + table.increments('log_id').primary().comment('로그 ID'); + table.integer('report_id').unsigned().notNullable().comment('신고 ID'); + table.string('previous_status', 50).nullable().comment('이전 상태'); + table.string('new_status', 50).notNullable().comment('새 상태'); + table.integer('changed_by').notNullable().comment('변경자 user_id'); + table.text('change_reason').nullable().comment('변경 사유'); + table.timestamp('changed_at').defaultTo(knex.fn.now()); + + table.foreign('report_id') + .references('report_id') + .inTable('work_issue_reports') + .onDelete('CASCADE') + .onUpdate('CASCADE'); + + table.foreign('changed_by') + .references('user_id') + .inTable('users') + .onDelete('RESTRICT') + .onUpdate('CASCADE'); + + table.index('report_id', 'idx_wisl_report_id'); + table.index('changed_at', 'idx_wisl_changed_at'); + }); + + console.log('작업 중 문제 신고 시스템 테이블 생성 완료'); +}; + +exports.down = async function(knex) { + // 역순으로 테이블 삭제 + await knex.schema.dropTableIfExists('work_issue_status_logs'); + await knex.schema.dropTableIfExists('work_issue_reports'); + await knex.schema.dropTableIfExists('issue_report_items'); + await knex.schema.dropTableIfExists('issue_report_categories'); + + console.log('작업 중 문제 신고 시스템 테이블 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260130000002_register_issue_pages.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260130000002_register_issue_pages.js new file mode 100644 index 0000000..602e1be --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260130000002_register_issue_pages.js @@ -0,0 +1,50 @@ +/** + * 마이그레이션: 문제 신고 관련 페이지 등록 + */ + +exports.up = async function(knex) { + // 문제 신고 등록 페이지 + await knex('pages').insert({ + page_key: 'issue-report', + page_name: '문제 신고', + page_path: '/pages/work/issue-report.html', + category: 'work', + description: '작업 중 문제(부적합/안전) 신고 등록', + is_admin_only: 0, + display_order: 16 + }); + + // 신고 목록 페이지 + await knex('pages').insert({ + page_key: 'issue-list', + page_name: '신고 목록', + page_path: '/pages/work/issue-list.html', + category: 'work', + description: '문제 신고 목록 조회 및 관리', + is_admin_only: 0, + display_order: 17 + }); + + // 신고 상세 페이지 + await knex('pages').insert({ + page_key: 'issue-detail', + page_name: '신고 상세', + page_path: '/pages/work/issue-detail.html', + category: 'work', + description: '문제 신고 상세 조회', + is_admin_only: 0, + display_order: 18 + }); + + console.log('✅ 문제 신고 페이지 등록 완료'); +}; + +exports.down = async function(knex) { + await knex('pages').whereIn('page_key', [ + 'issue-report', + 'issue-list', + 'issue-detail' + ]).delete(); + + console.log('✅ 문제 신고 페이지 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202000001_create_work_report_defects.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202000001_create_work_report_defects.js new file mode 100644 index 0000000..15d4d84 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202000001_create_work_report_defects.js @@ -0,0 +1,47 @@ +/** + * 작업보고서 부적합 상세 테이블 마이그레이션 + * + * 기존: error_hours, error_type_id (단일 값) + * 변경: 여러 부적합 원인 + 각 원인별 시간 저장 가능 + */ + +exports.up = function(knex) { + return knex.schema + // 1. work_report_defects 테이블 생성 + .createTable('work_report_defects', function(table) { + table.increments('defect_id').primary(); + table.integer('report_id').notNullable() + .comment('daily_work_reports의 id'); + table.integer('error_type_id').notNullable() + .comment('error_types의 id (부적합 원인)'); + table.decimal('defect_hours', 4, 1).notNullable().defaultTo(0) + .comment('해당 원인의 부적합 시간'); + table.text('note').nullable() + .comment('추가 메모'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + + // 외래키 + table.foreign('report_id').references('id').inTable('daily_work_reports').onDelete('CASCADE'); + table.foreign('error_type_id').references('id').inTable('error_types'); + + // 인덱스 + table.index('report_id'); + table.index('error_type_id'); + + // 같은 보고서에 같은 원인이 중복되지 않도록 + table.unique(['report_id', 'error_type_id']); + }) + // 2. 기존 데이터 마이그레이션 (error_hours > 0인 경우) + .then(function() { + return knex.raw(` + INSERT INTO work_report_defects (report_id, error_type_id, defect_hours, created_at) + SELECT id, error_type_id, error_hours, created_at + FROM daily_work_reports + WHERE error_hours > 0 AND error_type_id IS NOT NULL + `); + }); +}; + +exports.down = function(knex) { + return knex.schema.dropTableIfExists('work_report_defects'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202100000_expand_safety_checklist.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202100000_expand_safety_checklist.js new file mode 100644 index 0000000..62d303d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202100000_expand_safety_checklist.js @@ -0,0 +1,141 @@ +/** + * 안전 체크리스트 확장 마이그레이션 + * + * 1. tbm_safety_checks 테이블 확장 (check_type, weather_condition, task_id) + * 2. weather_conditions 테이블 생성 (날씨 조건 코드) + * 3. tbm_weather_records 테이블 생성 (세션별 날씨 기록) + * 4. 초기 날씨별 체크항목 데이터 + * + * @since 2026-02-02 + */ + +exports.up = function(knex) { + return knex.schema + // 1. tbm_safety_checks 테이블 확장 + .alterTable('tbm_safety_checks', function(table) { + table.enum('check_type', ['basic', 'weather', 'task']).defaultTo('basic').after('check_category'); + table.string('weather_condition', 50).nullable().after('check_type'); + table.integer('task_id').unsigned().nullable().after('weather_condition'); + + // 인덱스 추가 + table.index('check_type'); + table.index('weather_condition'); + table.index('task_id'); + }) + + // 2. weather_conditions 테이블 생성 + .createTable('weather_conditions', function(table) { + table.string('condition_code', 50).primary(); + table.string('condition_name', 100).notNullable(); + table.text('description').nullable(); + table.string('icon', 50).nullable(); + table.decimal('temp_threshold_min', 4, 1).nullable(); // 최소 기온 기준 + table.decimal('temp_threshold_max', 4, 1).nullable(); // 최대 기온 기준 + table.decimal('wind_threshold', 4, 1).nullable(); // 풍속 기준 (m/s) + table.decimal('precip_threshold', 5, 1).nullable(); // 강수량 기준 (mm) + table.boolean('is_active').defaultTo(true); + table.integer('display_order').defaultTo(0); + table.timestamp('created_at').defaultTo(knex.fn.now()); + }) + + // 3. tbm_weather_records 테이블 생성 + .createTable('tbm_weather_records', function(table) { + table.increments('record_id').primary(); + table.integer('session_id').unsigned().notNullable(); + table.date('weather_date').notNullable(); + table.decimal('temperature', 4, 1).nullable(); // 기온 (섭씨) + table.integer('humidity').nullable(); // 습도 (%) + table.decimal('wind_speed', 4, 1).nullable(); // 풍속 (m/s) + table.decimal('precipitation', 5, 1).nullable(); // 강수량 (mm) + table.string('sky_condition', 50).nullable(); // 하늘 상태 + table.string('weather_condition', 50).nullable(); // 주요 날씨 상태 + table.json('weather_conditions').nullable(); // 복수 조건 ['rain', 'wind'] + table.string('data_source', 50).defaultTo('api'); // 데이터 출처 + table.timestamp('fetched_at').nullable(); + table.timestamp('created_at').defaultTo(knex.fn.now()); + + // 외래키 + table.foreign('session_id').references('session_id').inTable('tbm_sessions').onDelete('CASCADE'); + + // 인덱스 + table.index('weather_date'); + table.unique(['session_id']); + }) + + // 4. 초기 데이터 삽입 + .then(function() { + // 기존 체크항목을 'basic' 유형으로 업데이트 + return knex('tbm_safety_checks').update({ check_type: 'basic' }); + }) + .then(function() { + // 날씨 조건 코드 삽입 + return knex('weather_conditions').insert([ + { condition_code: 'clear', condition_name: '맑음', description: '맑은 날씨', icon: 'sunny', display_order: 1 }, + { condition_code: 'rain', condition_name: '비', description: '비 오는 날씨', icon: 'rainy', precip_threshold: 0.1, display_order: 2 }, + { condition_code: 'snow', condition_name: '눈', description: '눈 오는 날씨', icon: 'snowy', display_order: 3 }, + { condition_code: 'heat', condition_name: '폭염', description: '기온 35도 이상', icon: 'hot', temp_threshold_min: 35, display_order: 4 }, + { condition_code: 'cold', condition_name: '한파', description: '기온 영하 10도 이하', icon: 'cold', temp_threshold_max: -10, display_order: 5 }, + { condition_code: 'wind', condition_name: '강풍', description: '풍속 10m/s 이상', icon: 'windy', wind_threshold: 10, display_order: 6 }, + { condition_code: 'fog', condition_name: '안개', description: '시정 1km 미만', icon: 'foggy', display_order: 7 }, + { condition_code: 'dust', condition_name: '미세먼지', description: '미세먼지 나쁨 이상', icon: 'dusty', display_order: 8 } + ]); + }) + .then(function() { + // 날씨별 안전 체크항목 삽입 + return knex('tbm_safety_checks').insert([ + // 비 (rain) + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'rain', check_item: '우의/우산 준비 확인', description: '비 오는 날 우의 또는 우산 준비 여부', is_required: true, display_order: 1 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'rain', check_item: '미끄럼 방지 조치 확인', description: '빗물로 인한 미끄러움 방지 조치', is_required: true, display_order: 2 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'rain', check_item: '전기 작업 중단 여부 확인', description: '우천 시 전기 작업 중단 필요성 확인', is_required: true, display_order: 3 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'rain', check_item: '배수 상태 확인', description: '작업장 배수 상태 점검', is_required: false, display_order: 4 }, + + // 눈 (snow) + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'snow', check_item: '제설 작업 완료 확인', description: '작업장 주변 제설 작업 완료 여부', is_required: true, display_order: 1 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'snow', check_item: '동파 방지 조치 확인', description: '배관 및 설비 동파 방지 조치', is_required: true, display_order: 2 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'snow', check_item: '미끄럼 방지 모래/염화칼슘 비치', description: '미끄럼 방지를 위한 모래 또는 염화칼슘 비치', is_required: true, display_order: 3 }, + + // 폭염 (heat) + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'heat', check_item: '그늘막/휴게소 확보', description: '무더위 휴식을 위한 그늘막 또는 휴게소 확보', is_required: true, display_order: 1 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'heat', check_item: '음료수/식염 포도당 비치', description: '열사병 예방을 위한 음료수 및 염분 보충제 비치', is_required: true, display_order: 2 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'heat', check_item: '무더위 휴식 시간 확보', description: '10~15시 사이 충분한 휴식 시간 확보', is_required: true, display_order: 3 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'heat', check_item: '작업자 건강 상태 확인', description: '열사병 증상 체크 및 건강 상태 확인', is_required: true, display_order: 4 }, + + // 한파 (cold) + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'cold', check_item: '방한복/방한장갑 착용 확인', description: '동상 방지를 위한 방한복 및 방한장갑 착용', is_required: true, display_order: 1 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'cold', check_item: '난방시설 가동 확인', description: '휴게 공간 난방시설 가동 상태 확인', is_required: true, display_order: 2 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'cold', check_item: '온열 음료 비치', description: '체온 유지를 위한 따뜻한 음료 비치', is_required: false, display_order: 3 }, + + // 강풍 (wind) + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'wind', check_item: '고소 작업 중단 여부 확인', description: '강풍 시 고소 작업 중단 필요성 확인', is_required: true, display_order: 1 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'wind', check_item: '자재/장비 결박 확인', description: '바람에 날릴 수 있는 자재 및 장비 고정', is_required: true, display_order: 2 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'wind', check_item: '가설물 안전 점검', description: '가설 구조물 및 비계 안전 상태 점검', is_required: true, display_order: 3 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'wind', check_item: '크레인 작업 중단 여부 확인', description: '강풍 시 크레인 작업 중단 필요성 확인', is_required: true, display_order: 4 }, + + // 안개 (fog) + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'fog', check_item: '경광등/조명 확보', description: '시정 확보를 위한 경광등 및 조명 설치', is_required: true, display_order: 1 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'fog', check_item: '차량 운행 주의 안내', description: '안개로 인한 차량 운행 주의 안내', is_required: true, display_order: 2 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'fog', check_item: '작업 구역 표시 강화', description: '시인성 확보를 위한 작업 구역 표시 강화', is_required: false, display_order: 3 }, + + // 미세먼지 (dust) + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'dust', check_item: '보호 마스크 착용 확인', description: 'KF94 이상 마스크 착용 여부 확인', is_required: true, display_order: 1 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'dust', check_item: '실외 작업 시간 조정', description: '미세먼지 농도에 따른 실외 작업 시간 조정', is_required: true, display_order: 2 }, + { check_category: 'WEATHER', check_type: 'weather', weather_condition: 'dust', check_item: '호흡기 질환자 실내 배치', description: '호흡기 질환 작업자 실내 작업 배치', is_required: false, display_order: 3 } + ]); + }); +}; + +exports.down = function(knex) { + return knex.schema + .dropTableIfExists('tbm_weather_records') + .dropTableIfExists('weather_conditions') + .then(function() { + return knex.schema.alterTable('tbm_safety_checks', function(table) { + table.dropIndex('check_type'); + table.dropIndex('weather_condition'); + table.dropIndex('task_id'); + table.dropColumn('check_type'); + table.dropColumn('weather_condition'); + table.dropColumn('task_id'); + }); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202200000_reorganize_pages.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202200000_reorganize_pages.js new file mode 100644 index 0000000..df21ca4 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260202200000_reorganize_pages.js @@ -0,0 +1,319 @@ +/** + * 페이지 구조 재구성 마이그레이션 + * - 페이지 경로 업데이트 (safety/, attendance/ 폴더로 이동) + * - 카테고리 재분류 + * - 역할별 기본 페이지 권한 테이블 생성 + */ + +exports.up = async function(knex) { + // 1. 페이지 경로 업데이트 - safety 폴더로 이동된 페이지들 + const safetyPageUpdates = [ + { + old_key: 'issue-report', + new_key: 'safety.issue_report', + new_path: '/pages/safety/issue-report.html', + new_category: 'safety', + new_name: '이슈 신고' + }, + { + old_key: 'issue-list', + new_key: 'safety.issue_list', + new_path: '/pages/safety/issue-list.html', + new_category: 'safety', + new_name: '이슈 목록' + }, + { + old_key: 'issue-detail', + new_key: 'safety.issue_detail', + new_path: '/pages/safety/issue-detail.html', + new_category: 'safety', + new_name: '이슈 상세' + }, + { + old_key: 'visit-request', + new_key: 'safety.visit_request', + new_path: '/pages/safety/visit-request.html', + new_category: 'safety', + new_name: '방문 요청' + }, + { + old_key: 'safety-management', + new_key: 'safety.management', + new_path: '/pages/safety/management.html', + new_category: 'safety', + new_name: '안전 관리' + }, + { + old_key: 'safety-training-conduct', + new_key: 'safety.training_conduct', + new_path: '/pages/safety/training-conduct.html', + new_category: 'safety', + new_name: '안전교육 진행' + } + ]; + + // 2. 페이지 경로 업데이트 - attendance 폴더로 이동된 페이지들 + const attendancePageUpdates = [ + { + old_key: 'daily-attendance', + new_key: 'attendance.daily', + new_path: '/pages/attendance/daily.html', + new_category: 'attendance', + new_name: '일일 출퇴근' + }, + { + old_key: 'monthly-attendance', + new_key: 'attendance.monthly', + new_path: '/pages/attendance/monthly.html', + new_category: 'attendance', + new_name: '월간 근태' + }, + { + old_key: 'annual-vacation-overview', + new_key: 'attendance.annual_overview', + new_path: '/pages/attendance/annual-overview.html', + new_category: 'attendance', + new_name: '연간 휴가 현황' + }, + { + old_key: 'vacation-request', + new_key: 'attendance.vacation_request', + new_path: '/pages/attendance/vacation-request.html', + new_category: 'attendance', + new_name: '휴가 신청' + }, + { + old_key: 'vacation-management', + new_key: 'attendance.vacation_management', + new_path: '/pages/attendance/vacation-management.html', + new_category: 'attendance', + new_name: '휴가 관리' + }, + { + old_key: 'vacation-allocation', + new_key: 'attendance.vacation_allocation', + new_path: '/pages/attendance/vacation-allocation.html', + new_category: 'attendance', + new_name: '휴가 발생 입력' + } + ]; + + // 3. admin 폴더 내 파일명 변경 + const adminPageUpdates = [ + { + old_key: 'attendance-report-comparison', + new_key: 'admin.attendance_report', + new_path: '/pages/admin/attendance-report.html', + new_category: 'admin', + new_name: '출퇴근-보고서 대조' + } + ]; + + // 모든 업데이트 실행 + const allUpdates = [...safetyPageUpdates, ...attendancePageUpdates, ...adminPageUpdates]; + + for (const update of allUpdates) { + await knex('pages') + .where('page_key', update.old_key) + .update({ + page_key: update.new_key, + page_path: update.new_path, + category: update.new_category, + page_name: update.new_name + }); + } + + // 4. 안전 체크리스트 관리 페이지 추가 (새로 생성된 페이지) + const existingChecklistPage = await knex('pages') + .where('page_key', 'safety.checklist_manage') + .orWhere('page_key', 'safety-checklist-manage') + .first(); + + if (!existingChecklistPage) { + await knex('pages').insert({ + page_key: 'safety.checklist_manage', + page_name: '안전 체크리스트 관리', + page_path: '/pages/safety/checklist-manage.html', + category: 'safety', + description: '안전 체크리스트 항목 관리', + is_admin_only: 1, + display_order: 50 + }); + } + + // 5. 휴가 승인/직접입력 페이지 추가 (새로 생성된 페이지인 경우) + const vacationPages = [ + { + page_key: 'attendance.vacation_approval', + page_name: '휴가 승인 관리', + page_path: '/pages/attendance/vacation-approval.html', + category: 'attendance', + description: '휴가 신청 승인/거부', + is_admin_only: 1, + display_order: 65 + }, + { + page_key: 'attendance.vacation_input', + page_name: '휴가 직접 입력', + page_path: '/pages/attendance/vacation-input.html', + category: 'attendance', + description: '관리자 휴가 직접 입력', + is_admin_only: 1, + display_order: 66 + } + ]; + + for (const page of vacationPages) { + const existing = await knex('pages').where('page_key', page.page_key).first(); + if (!existing) { + await knex('pages').insert(page); + } + } + + // 6. role_default_pages 테이블 생성 (역할별 기본 페이지 권한) + const tableExists = await knex.schema.hasTable('role_default_pages'); + if (!tableExists) { + await knex.schema.createTable('role_default_pages', (table) => { + table.integer('role_id').unsigned().notNullable() + .references('id').inTable('roles').onDelete('CASCADE'); + table.integer('page_id').unsigned().notNullable() + .references('id').inTable('pages').onDelete('CASCADE'); + table.primary(['role_id', 'page_id']); + table.timestamps(true, true); + }); + } + + // 7. 기본 역할-페이지 매핑 데이터 삽입 + // 역할 조회 + const roles = await knex('roles').select('id', 'name'); + const pages = await knex('pages').select('id', 'page_key', 'category'); + + const roleMap = {}; + roles.forEach(r => { roleMap[r.name] = r.id; }); + + const pageMap = {}; + pages.forEach(p => { pageMap[p.page_key] = p.id; }); + + // Worker 역할 기본 페이지 (대시보드, 작업보고서, 휴가신청) + const workerPages = [ + 'dashboard', + 'work.report_create', + 'work.report_view', + 'attendance.vacation_request' + ]; + + // Leader 역할 기본 페이지 (Worker + TBM, 안전, 근태 일부) + const leaderPages = [ + ...workerPages, + 'work.tbm', + 'work.analysis', + 'safety.issue_report', + 'safety.issue_list', + 'attendance.daily', + 'attendance.monthly' + ]; + + // SafetyManager 역할 기본 페이지 (Leader + 안전 전체) + const safetyManagerPages = [ + ...leaderPages, + 'safety.issue_detail', + 'safety.visit_request', + 'safety.management', + 'safety.training_conduct', + 'safety.checklist_manage' + ]; + + // 역할별 페이지 매핑 삽입 + const rolePageMappings = []; + + if (roleMap['Worker']) { + workerPages.forEach(pageKey => { + if (pageMap[pageKey]) { + rolePageMappings.push({ role_id: roleMap['Worker'], page_id: pageMap[pageKey] }); + } + }); + } + + if (roleMap['Leader']) { + leaderPages.forEach(pageKey => { + if (pageMap[pageKey]) { + rolePageMappings.push({ role_id: roleMap['Leader'], page_id: pageMap[pageKey] }); + } + }); + } + + if (roleMap['SafetyManager']) { + safetyManagerPages.forEach(pageKey => { + if (pageMap[pageKey]) { + rolePageMappings.push({ role_id: roleMap['SafetyManager'], page_id: pageMap[pageKey] }); + } + }); + } + + // 중복 제거 후 삽입 + for (const mapping of rolePageMappings) { + const existing = await knex('role_default_pages') + .where('role_id', mapping.role_id) + .where('page_id', mapping.page_id) + .first(); + + if (!existing) { + await knex('role_default_pages').insert(mapping); + } + } + + console.log('페이지 구조 재구성 완료'); + console.log(`- 업데이트된 페이지: ${allUpdates.length}개`); + console.log(`- 역할별 기본 페이지 매핑: ${rolePageMappings.length}개`); +}; + +exports.down = async function(knex) { + // 1. role_default_pages 테이블 삭제 + await knex.schema.dropTableIfExists('role_default_pages'); + + // 2. 페이지 경로 원복 - safety → work/admin + const safetyRevert = [ + { new_key: 'safety.issue_report', old_key: 'issue-report', old_path: '/pages/work/issue-report.html', old_category: 'work' }, + { new_key: 'safety.issue_list', old_key: 'issue-list', old_path: '/pages/work/issue-list.html', old_category: 'work' }, + { new_key: 'safety.issue_detail', old_key: 'issue-detail', old_path: '/pages/work/issue-detail.html', old_category: 'work' }, + { new_key: 'safety.visit_request', old_key: 'visit-request', old_path: '/pages/work/visit-request.html', old_category: 'work' }, + { new_key: 'safety.management', old_key: 'safety-management', old_path: '/pages/admin/safety-management.html', old_category: 'admin' }, + { new_key: 'safety.training_conduct', old_key: 'safety-training-conduct', old_path: '/pages/admin/safety-training-conduct.html', old_category: 'admin' }, + ]; + + // 3. 페이지 경로 원복 - attendance → common + const attendanceRevert = [ + { new_key: 'attendance.daily', old_key: 'daily-attendance', old_path: '/pages/common/daily-attendance.html', old_category: 'common' }, + { new_key: 'attendance.monthly', old_key: 'monthly-attendance', old_path: '/pages/common/monthly-attendance.html', old_category: 'common' }, + { new_key: 'attendance.annual_overview', old_key: 'annual-vacation-overview', old_path: '/pages/common/annual-vacation-overview.html', old_category: 'common' }, + { new_key: 'attendance.vacation_request', old_key: 'vacation-request', old_path: '/pages/common/vacation-request.html', old_category: 'common' }, + { new_key: 'attendance.vacation_management', old_key: 'vacation-management', old_path: '/pages/common/vacation-management.html', old_category: 'common' }, + { new_key: 'attendance.vacation_allocation', old_key: 'vacation-allocation', old_path: '/pages/common/vacation-allocation.html', old_category: 'common' }, + ]; + + // 4. admin 파일명 원복 + const adminRevert = [ + { new_key: 'admin.attendance_report', old_key: 'attendance-report-comparison', old_path: '/pages/admin/attendance-report-comparison.html', old_category: 'admin' } + ]; + + const allReverts = [...safetyRevert, ...attendanceRevert, ...adminRevert]; + + for (const revert of allReverts) { + await knex('pages') + .where('page_key', revert.new_key) + .update({ + page_key: revert.old_key, + page_path: revert.old_path, + category: revert.old_category + }); + } + + // 5. 새로 추가된 페이지 삭제 + await knex('pages').whereIn('page_key', [ + 'safety.checklist_manage', + 'attendance.vacation_approval', + 'attendance.vacation_input' + ]).del(); + + console.log('페이지 구조 재구성 롤백 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260203090000_add_category_to_defects.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260203090000_add_category_to_defects.js new file mode 100644 index 0000000..5ff74af --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260203090000_add_category_to_defects.js @@ -0,0 +1,43 @@ +/** + * 작업보고서 부적합에 카테고리/아이템 컬럼 추가 + * + * 변경사항: + * 1. work_report_defects 테이블에 category_id, item_id 컬럼 추가 + * 2. issue_report_categories, issue_report_items 테이블 참조 + */ + +exports.up = function(knex) { + return knex.schema + .alterTable('work_report_defects', function(table) { + // 카테고리 ID 추가 + table.integer('category_id').unsigned().nullable() + .comment('issue_report_categories의 category_id (직접 입력 시)') + .after('issue_report_id'); + + // 아이템 ID 추가 + table.integer('item_id').unsigned().nullable() + .comment('issue_report_items의 item_id (직접 입력 시)') + .after('category_id'); + + // 외래키 추가 + table.foreign('category_id') + .references('category_id') + .inTable('issue_report_categories') + .onDelete('SET NULL'); + + table.foreign('item_id') + .references('item_id') + .inTable('issue_report_items') + .onDelete('SET NULL'); + }); +}; + +exports.down = function(knex) { + return knex.schema + .alterTable('work_report_defects', function(table) { + table.dropForeign('category_id'); + table.dropForeign('item_id'); + table.dropColumn('category_id'); + table.dropColumn('item_id'); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260203100000_link_defects_to_issues.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260203100000_link_defects_to_issues.js new file mode 100644 index 0000000..e89e476 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260203100000_link_defects_to_issues.js @@ -0,0 +1,85 @@ +/** + * 작업보고서 부적합을 신고 시스템과 연동 + * + * 변경사항: + * 1. work_report_defects 테이블에 issue_report_id 컬럼 추가 + * 2. error_type_id를 NULL 허용으로 변경 (신고 연동 시 불필요) + * 3. work_issue_reports.report_id (unsigned int)와 타입 일치 필요 + */ + +exports.up = function(knex) { + return knex.schema + .alterTable('work_report_defects', function(table) { + // 1. issue_report_id 컬럼 추가 (unsigned int로 work_issue_reports.report_id와 타입 일치) + table.integer('issue_report_id').unsigned().nullable() + .comment('work_issue_reports의 report_id (신고된 이슈 연결)') + .after('error_type_id'); + + // 2. 외래키 추가 (work_issue_reports.report_id 참조) + table.foreign('issue_report_id') + .references('report_id') + .inTable('work_issue_reports') + .onDelete('SET NULL'); + + // 3. 인덱스 추가 + table.index('issue_report_id'); + }) + // 4. error_type_id를 NULL 허용으로 변경 + .then(function() { + return knex.raw(` + ALTER TABLE work_report_defects + MODIFY COLUMN error_type_id INT NULL + COMMENT 'error_types의 id (부적합 원인) - 레거시, issue_report_id 사용 권장' + `); + }) + // 5. 유니크 제약 수정 (issue_report_id도 고려) + .then(function() { + // 기존 유니크 제약 삭제 + return knex.raw(` + ALTER TABLE work_report_defects + DROP INDEX work_report_defects_report_id_error_type_id_unique + `).catch(() => { + // 인덱스가 없을 수 있음 - 무시 + }); + }) + .then(function() { + // 새 유니크 제약 추가 (report_id + issue_report_id 조합) + return knex.raw(` + ALTER TABLE work_report_defects + ADD UNIQUE INDEX work_report_defects_report_issue_unique (report_id, issue_report_id) + `).catch(() => { + // 이미 존재할 수 있음 - 무시 + }); + }); +}; + +exports.down = function(knex) { + return knex.schema + .alterTable('work_report_defects', function(table) { + // 외래키 및 인덱스 삭제 + table.dropForeign('issue_report_id'); + table.dropIndex('issue_report_id'); + table.dropColumn('issue_report_id'); + }) + // error_type_id를 다시 NOT NULL로 변경 + .then(function() { + return knex.raw(` + ALTER TABLE work_report_defects + MODIFY COLUMN error_type_id INT NOT NULL + COMMENT 'error_types의 id (부적합 원인)' + `); + }) + // 기존 유니크 제약 복원 + .then(function() { + return knex.raw(` + ALTER TABLE work_report_defects + DROP INDEX IF EXISTS work_report_defects_report_issue_unique + `).catch(() => {}); + }) + .then(function() { + return knex.raw(` + ALTER TABLE work_report_defects + ADD UNIQUE INDEX work_report_defects_report_id_error_type_id_unique (report_id, error_type_id) + `).catch(() => {}); + }); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204001000_create_notification_recipients.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204001000_create_notification_recipients.sql new file mode 100644 index 0000000..7c4e5e9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204001000_create_notification_recipients.sql @@ -0,0 +1,23 @@ +-- 알림 수신자 설정 테이블 +-- 알림 유형별로 지정된 사용자에게만 알림이 전송됨 + +CREATE TABLE IF NOT EXISTS notification_recipients ( + id INT AUTO_INCREMENT PRIMARY KEY, + notification_type ENUM('repair', 'safety', 'nonconformity', 'equipment', 'maintenance', 'system') NOT NULL COMMENT '알림 유형', + user_id INT NOT NULL COMMENT '수신자 ID', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 여부', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + created_by INT NULL COMMENT '등록자', + UNIQUE KEY unique_type_user (notification_type, user_id), + FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE, + INDEX idx_nr_type (notification_type), + INDEX idx_nr_active (is_active) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='알림 수신자 설정'; + +-- 알림 유형 설명: +-- repair: 설비 수리 신청 +-- safety: 안전 신고 +-- nonconformity: 부적합 신고 +-- equipment: 설비 관련 +-- maintenance: 정기점검 +-- system: 시스템 알림 diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204100000_add_equipment_purchase_fields.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204100000_add_equipment_purchase_fields.js new file mode 100644 index 0000000..ac79357 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204100000_add_equipment_purchase_fields.js @@ -0,0 +1,35 @@ +/** + * 설비 테이블에 구입처 및 구입가격 컬럼 추가 + * + * @author TK-FB-Project + * @since 2026-02-04 + */ + +exports.up = async function(knex) { + // 컬럼 존재 여부 확인 + const hasSupplier = await knex.schema.hasColumn('equipments', 'supplier'); + const hasPurchasePrice = await knex.schema.hasColumn('equipments', 'purchase_price'); + + if (!hasSupplier || !hasPurchasePrice) { + await knex.schema.alterTable('equipments', (table) => { + if (!hasSupplier) { + table.string('supplier', 100).nullable().after('manufacturer').comment('구입처'); + } + if (!hasPurchasePrice) { + table.decimal('purchase_price', 15, 0).nullable().after('supplier').comment('구입가격'); + } + }); + console.log('✅ equipments 테이블에 supplier, purchase_price 컬럼 추가 완료'); + } else { + console.log('ℹ️ supplier, purchase_price 컬럼이 이미 존재합니다. 스킵합니다.'); + } +}; + +exports.down = async function(knex) { + await knex.schema.alterTable('equipments', (table) => { + table.dropColumn('supplier'); + table.dropColumn('purchase_price'); + }); + + console.log('✅ equipments 테이블에서 supplier, purchase_price 컬럼 삭제 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204100000_create_daily_patrol_system.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204100000_create_daily_patrol_system.js new file mode 100644 index 0000000..e5bac4e --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204100000_create_daily_patrol_system.js @@ -0,0 +1,166 @@ +/** + * 마이그레이션: 일일순회점검 시스템 + * 작성일: 2026-02-04 + * + * 생성 테이블: + * - patrol_checklist_items: 순회점검 체크리스트 마스터 + * - daily_patrol_sessions: 순회점검 세션 기록 + * - patrol_check_records: 순회점검 체크 결과 + * - workplace_items: 작업장 물품 현황 (용기, 플레이트 등) + */ + +exports.up = async function(knex) { + console.log('⏳ 일일순회점검 시스템 테이블 생성 중...'); + + // 1. 순회점검 체크리스트 마스터 테이블 + await knex.schema.createTable('patrol_checklist_items', (table) => { + table.increments('item_id').primary(); + table.integer('workplace_id').unsigned().nullable().comment('특정 작업장 전용 (NULL=공통)'); + table.integer('category_id').unsigned().nullable().comment('특정 공장 전용 (NULL=공통)'); + table.string('check_category', 50).notNullable().comment('분류 (안전, 정리정돈, 설비 등)'); + table.string('check_item', 200).notNullable().comment('점검 항목'); + table.text('description').nullable().comment('설명'); + table.integer('display_order').defaultTo(0).comment('표시 순서'); + table.boolean('is_required').defaultTo(true).comment('필수 체크 여부'); + table.boolean('is_active').defaultTo(true).comment('활성 여부'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + table.index('workplace_id'); + table.index('category_id'); + table.index('check_category'); + table.foreign('workplace_id').references('workplaces.workplace_id').onDelete('CASCADE'); + table.foreign('category_id').references('workplace_categories.category_id').onDelete('CASCADE'); + }); + console.log('✅ patrol_checklist_items 테이블 생성 완료'); + + // 초기 순회점검 체크리스트 데이터 + await knex('patrol_checklist_items').insert([ + // 안전 관련 + { check_category: 'SAFETY', check_item: '소화기 상태 확인', display_order: 1, is_required: true }, + { check_category: 'SAFETY', check_item: '비상구 통로 확보 확인', display_order: 2, is_required: true }, + { check_category: 'SAFETY', check_item: '안전표지판 부착 상태', display_order: 3, is_required: true }, + { check_category: 'SAFETY', check_item: '위험물 관리 상태', display_order: 4, is_required: true }, + + // 정리정돈 + { check_category: 'ORGANIZATION', check_item: '작업장 정리정돈 상태', display_order: 10, is_required: true }, + { check_category: 'ORGANIZATION', check_item: '통로 장애물 여부', display_order: 11, is_required: true }, + { check_category: 'ORGANIZATION', check_item: '폐기물 처리 상태', display_order: 12, is_required: true }, + { check_category: 'ORGANIZATION', check_item: '자재 적재 상태', display_order: 13, is_required: true }, + + // 설비 + { check_category: 'EQUIPMENT', check_item: '설비 외관 이상 여부', display_order: 20, is_required: false }, + { check_category: 'EQUIPMENT', check_item: '설비 작동 상태', display_order: 21, is_required: false }, + { check_category: 'EQUIPMENT', check_item: '설비 청결 상태', display_order: 22, is_required: false }, + + // 환경 + { check_category: 'ENVIRONMENT', check_item: '조명 상태', display_order: 30, is_required: true }, + { check_category: 'ENVIRONMENT', check_item: '환기 상태', display_order: 31, is_required: true }, + { check_category: 'ENVIRONMENT', check_item: '누수/누유 여부', display_order: 32, is_required: true }, + ]); + console.log('✅ patrol_checklist_items 초기 데이터 입력 완료'); + + // 2. 순회점검 세션 테이블 + await knex.schema.createTable('daily_patrol_sessions', (table) => { + table.increments('session_id').primary(); + table.date('patrol_date').notNullable().comment('점검 날짜'); + table.enum('patrol_time', ['morning', 'afternoon']).notNullable().comment('점검 시간대'); + table.integer('inspector_id').notNullable().comment('순찰자 user_id'); // signed (users.user_id) + table.integer('category_id').unsigned().nullable().comment('공장 ID'); + table.enum('status', ['in_progress', 'completed']).defaultTo('in_progress').comment('상태'); + table.text('notes').nullable().comment('특이사항'); + table.time('started_at').nullable().comment('점검 시작 시간'); + table.time('completed_at').nullable().comment('점검 완료 시간'); + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + table.unique(['patrol_date', 'patrol_time', 'category_id']); + table.index(['patrol_date', 'patrol_time']); + table.index('inspector_id'); + table.foreign('inspector_id').references('users.user_id'); + table.foreign('category_id').references('workplace_categories.category_id').onDelete('SET NULL'); + }); + console.log('✅ daily_patrol_sessions 테이블 생성 완료'); + + // 3. 순회점검 체크 기록 테이블 + await knex.schema.createTable('patrol_check_records', (table) => { + table.increments('record_id').primary(); + table.integer('session_id').unsigned().notNullable().comment('순회점검 세션 ID'); + table.integer('workplace_id').unsigned().notNullable().comment('작업장 ID'); + table.integer('check_item_id').unsigned().notNullable().comment('체크항목 ID'); + table.boolean('is_checked').defaultTo(false).comment('체크 여부'); + table.enum('check_result', ['good', 'warning', 'bad']).nullable().comment('점검 결과'); + table.text('note').nullable().comment('비고'); + table.timestamp('checked_at').nullable().comment('체크 시간'); + + // 인덱스명 길이 제한으로 인해 수동으로 지정 + table.unique(['session_id', 'workplace_id', 'check_item_id'], 'pcr_session_wp_item_unique'); + table.index(['session_id', 'workplace_id'], 'pcr_session_wp_idx'); + table.foreign('session_id').references('daily_patrol_sessions.session_id').onDelete('CASCADE'); + table.foreign('workplace_id').references('workplaces.workplace_id').onDelete('CASCADE'); + table.foreign('check_item_id').references('patrol_checklist_items.item_id').onDelete('CASCADE'); + }); + console.log('✅ patrol_check_records 테이블 생성 완료'); + + // 4. 작업장 물품 현황 테이블 + await knex.schema.createTable('workplace_items', (table) => { + table.increments('item_id').primary(); + table.integer('workplace_id').unsigned().notNullable().comment('작업장 ID'); + table.integer('patrol_session_id').unsigned().nullable().comment('등록한 순회점검 세션'); + table.integer('project_id').nullable().comment('관련 프로젝트'); // signed (projects.project_id) + table.enum('item_type', ['container', 'plate', 'material', 'tool', 'other']).notNullable().comment('물품 유형'); + table.string('item_name', 100).nullable().comment('물품명/설명'); + table.integer('quantity').defaultTo(1).comment('수량'); + table.decimal('x_percent', 5, 2).nullable().comment('지도상 X 위치 (%)'); + table.decimal('y_percent', 5, 2).nullable().comment('지도상 Y 위치 (%)'); + table.decimal('width_percent', 5, 2).nullable().comment('지도상 너비 (%)'); + table.decimal('height_percent', 5, 2).nullable().comment('지도상 높이 (%)'); + table.boolean('is_active').defaultTo(true).comment('현재 존재 여부'); + table.integer('created_by').notNullable().comment('등록자 user_id'); // signed (users.user_id) + table.timestamp('created_at').defaultTo(knex.fn.now()); + table.integer('updated_by').nullable().comment('최종 수정자 user_id'); // signed (users.user_id) + table.timestamp('updated_at').defaultTo(knex.fn.now()); + + table.index(['workplace_id', 'is_active']); + table.index('project_id'); + table.foreign('workplace_id').references('workplaces.workplace_id').onDelete('CASCADE'); + table.foreign('patrol_session_id').references('daily_patrol_sessions.session_id').onDelete('SET NULL'); + table.foreign('project_id').references('projects.project_id').onDelete('SET NULL'); + table.foreign('created_by').references('users.user_id'); + table.foreign('updated_by').references('users.user_id'); + }); + console.log('✅ workplace_items 테이블 생성 완료'); + + // 물품 유형 코드 테이블 (선택적 확장용) + await knex.schema.createTable('item_types', (table) => { + table.string('type_code', 20).primary(); + table.string('type_name', 50).notNullable().comment('유형명'); + table.string('icon', 10).nullable().comment('아이콘 이모지'); + table.string('color', 20).nullable().comment('표시 색상'); + table.integer('display_order').defaultTo(0); + table.boolean('is_active').defaultTo(true); + }); + + await knex('item_types').insert([ + { type_code: 'container', type_name: '용기', icon: '📦', color: '#3b82f6', display_order: 1 }, + { type_code: 'plate', type_name: '플레이트', icon: '🔲', color: '#10b981', display_order: 2 }, + { type_code: 'material', type_name: '자재', icon: '🧱', color: '#f59e0b', display_order: 3 }, + { type_code: 'tool', type_name: '공구/장비', icon: '🔧', color: '#8b5cf6', display_order: 4 }, + { type_code: 'other', type_name: '기타', icon: '📍', color: '#6b7280', display_order: 5 }, + ]); + console.log('✅ item_types 테이블 생성 및 초기 데이터 완료'); + + console.log('✅ 모든 일일순회점검 시스템 테이블 생성 완료'); +}; + +exports.down = async function(knex) { + console.log('⏳ 일일순회점검 시스템 테이블 제거 중...'); + + await knex.schema.dropTableIfExists('item_types'); + await knex.schema.dropTableIfExists('workplace_items'); + await knex.schema.dropTableIfExists('patrol_check_records'); + await knex.schema.dropTableIfExists('daily_patrol_sessions'); + await knex.schema.dropTableIfExists('patrol_checklist_items'); + + console.log('✅ 모든 일일순회점검 시스템 테이블 제거 완료'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_add_columns.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_add_columns.sql new file mode 100644 index 0000000..53ed1db --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_add_columns.sql @@ -0,0 +1,13 @@ +-- 설비 테이블 컬럼 추가 (phpMyAdmin용) +-- 현재 구조: equipment_id, factory_id, equipment_name, model, status, purchase_date, description, created_at, updated_at + +-- 필요한 컬럼 추가 +ALTER TABLE equipments ADD COLUMN equipment_code VARCHAR(50) NULL COMMENT '관리번호' AFTER equipment_id; +ALTER TABLE equipments ADD COLUMN specifications TEXT NULL COMMENT '규격' AFTER model; +ALTER TABLE equipments ADD COLUMN serial_number VARCHAR(100) NULL COMMENT '시리얼번호(S/N)' AFTER specifications; +ALTER TABLE equipments ADD COLUMN supplier VARCHAR(100) NULL COMMENT '구입처' AFTER purchase_date; +ALTER TABLE equipments ADD COLUMN purchase_price DECIMAL(15, 0) NULL COMMENT '구입가격' AFTER supplier; +ALTER TABLE equipments ADD COLUMN manufacturer VARCHAR(100) NULL COMMENT '제조사(메이커)' AFTER purchase_price; + +-- equipment_code에 유니크 인덱스 추가 +ALTER TABLE equipments ADD UNIQUE INDEX idx_equipment_code (equipment_code); diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_full_setup.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_full_setup.sql new file mode 100644 index 0000000..63b458c --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_full_setup.sql @@ -0,0 +1,138 @@ +-- 설비 관리 전체 설정 스크립트 +-- 1. 새 컬럼 추가 (supplier, purchase_price) +-- 2. 65개 설비 데이터 입력 +-- +-- 실행: mysql -u [user] -p [database] < 20260204_equipment_full_setup.sql + +-- ============================================ +-- STEP 1: 새 컬럼 추가 +-- ============================================ + +-- 컬럼이 이미 존재하는지 확인 후 추가 +SET @dbname = DATABASE(); +SET @tablename = 'equipments'; + +-- supplier 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname +AND table_name = @tablename +AND column_name = 'supplier'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN supplier VARCHAR(100) NULL COMMENT ''구입처'' AFTER manufacturer', + 'SELECT ''supplier column already exists'''); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +-- purchase_price 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname +AND table_name = @tablename +AND column_name = 'purchase_price'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN purchase_price DECIMAL(15, 0) NULL COMMENT ''구입가격'' AFTER supplier', + 'SELECT ''purchase_price column already exists'''); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +SELECT '컬럼 추가 완료' AS status; + +-- ============================================ +-- STEP 2: 기존 데이터 삭제 (선택사항) +-- ============================================ +-- 주의: 기존 데이터가 있으면 삭제됩니다 +DELETE FROM equipments WHERE equipment_code LIKE 'TKP-%'; + +-- ============================================ +-- STEP 3: 65개 설비 데이터 입력 +-- ============================================ + +INSERT INTO equipments (equipment_code, equipment_name, model_name, specifications, serial_number, installation_date, supplier, purchase_price, manufacturer, status) VALUES +('TKP-001', 'AIR COMPRESSOR', 'AR10E', '7.5KW(10HP)', 'K603023Y', '2016-06-01', '지티씨', NULL, '경원', 'active'), +('TKP-002', 'TURN TABLE', 'YCT-200T', '220V', NULL, '2016-05-30', '형진종합공구', 3600000, '유체기계', 'active'), +('TKP-003', 'BAND SAW(中)', 'CY300W', '1500W*380V', '20150943', '2016-05-30', '형진종합공구', 4800000, '유림싸이겐', 'active'), +('TKP-004', 'BAND SAW(小)', 'XB-180WA', '180(VICE)', NULL, '2016-05-30', '형진종합공구', 2700000, '렉스', 'active'), +('TKP-005', 'BAND SAW(小)', 'XB-180WA', '180(VICE)', NULL, '2019-05-30', NULL, NULL, '렉스', 'active'), +('TKP-006', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-001', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-007', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-002', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-008', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-003', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-009', 'CO2용접기', 'COD-500A', '500A', '10880', '2016-05-30', '형진종합공구', 2000000, '대성용접기', 'active'), +('TKP-010', 'O2용접기', 'GSORK', '220V', NULL, '2016-05-30', '형진종합공구', 620000, '재현오토닉스', 'active'), +('TKP-011', 'PIPE BEVELLING MACHINE', 'S-200LT_MT(테이블포함)', '2" ~ 8"', 'KR-17030007', '2017-03-29', 'DCS ENG', 12000000, 'DCS ENG', 'active'), +('TKP-012', 'CO2용접기', '500MX', '220/380V,500A', NULL, '2017-08-02', '현대용접기', 1800000, '현대용접기', 'active'), +('TKP-013', '프라즈마', 'Perfect-150AP', '220/380/440V,140A', NULL, '2017-08-02', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-014', '터닝로라', 'JK-5-TR', '5TON/380V', NULL, '2017-09-08', '정일기공', 5700000, '정일기공', 'active'), +('TKP-015', '터닝로라', 'JK-5-TR', '5TON/380V', NULL, '2017-09-08', '정일기공', 5700000, '정일기공', 'active'), +('TKP-016', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-005', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-017', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-006', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-018', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-007', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-019', '전해연마기', 'ONB-8000VP', '220V/MAX1200W', '8022701', '2018-03-13', '오토기전', 1450000, '메탈브라이트(오토기전)', 'active'), +('TKP-020', '지게차', '50DA-9F', '5000KGS', 'HHKHFV36JJ0000061', '2018-05-10', '현대지게차', 45000000, '현대지게차', 'active'), +('TKP-021', '조방', NULL, '3658*12190', NULL, '2018-05-11', '천우기계공업/삼덕금속', 14200000, '테크니컬코리아', 'active'), +('TKP-022', 'BAND SAW(大)', 'WBS-RC500AN', '3,300kgs / 7.88kw', 'BC50A18-005F001', '2018-05-31', '원공사', 36000000, '원공사', 'active'), +('TKP-023', 'AIR COMPRESSOR', 'AR20E', '0.95Mpa', 'AR020FE358', '2018-06-05', '경원기계', NULL, '경원기계', 'active'), +('TKP-024', 'TURN TABLE', 'YCT-200TA', '220V', NULL, '2018-06-12', '청운종합공구', 3245000, '유체기계', 'active'), +('TKP-025', 'TIG용접기', 'Perfect-500WT', '500A/AC DC', 'ADKAC017B-006', '2018-06-12', '현대용접기', 2400000, '퍼펙트대대', 'active'), +('TKP-026', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAI018B-002', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-027', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAA018B-009', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-028', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAA018B-001', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-029', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1806077', '2018-07-06', '청운종합공구', 2300000, '대산', 'active'), +('TKP-030', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1807028', '2018-07-10', '청운종합공구', 2300000, '대산', 'active'), +('TKP-031', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1807029', '2018-07-10', '청운종합공구', 2300000, '대산', 'active'), +('TKP-032', '만능탭 드릴링머신', 'SF-TDM32', '1.5KW', NULL, '2018-11-09', '㈜애스앤애프', 2927000, '㈜애스앤에프', 'active'), +('TKP-033', '지게차', '30D-9B', '2850KGS', 'HHKHHN51KK0000864', '2019-03-06', '현대지게차', 29400000, '현대지게차', 'active'), +('TKP-034', '갠츄리크레인', 'CRANE - DHG', '50/10Ton x SP20M x T/L50M x H15M', NULL, '2019-05-09', '유진산업기계', 249000000, '반도호이스트', 'active'), +('TKP-035', 'OVER HEAD CRANE', 'CRANE - DHO', '20Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 58000000, '반도호이스트', 'active'), +('TKP-036', 'OVER HEAD CRANE', 'CRANE - DHO', '20Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 58000000, '반도호이스트', 'active'), +('TKP-037', 'OVER HEAD CRANE', 'CRANE - DHO', '5Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 29000000, '반도호이스트', 'active'), +('TKP-038', 'OVER HEAD CRANE', 'CRANE - DHO', '5Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 29000000, '반도호이스트', 'active'), +('TKP-039', '고소작업대', NULL, '250 Kg', NULL, '2019-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-040', '고소작업대', NULL, '250 Kg', NULL, '2019-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-041', 'AIR CONDITIONER', '코끼리 냉장고', NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-042', 'AIR CONDITIONER', NULL, NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-043', 'AIR CONDITIONER', NULL, NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-044', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-045', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-046', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-047', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-048', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-049', '자동용접기', NULL, NULL, NULL, '2019-01-01', 'Swage-Lok', 50000000, 'Swage-Lok', 'active'), +('TKP-050', 'Magnetic Drill', NULL, NULL, NULL, '2020-01-01', '청운종합공구', NULL, 'NITTO', 'active'), +('TKP-051', 'Magnetic Drill', NULL, NULL, NULL, '2020-01-01', '청운종합공구', NULL, 'Key-Yang', 'active'), +('TKP-052', 'Tube Bending M/C', NULL, NULL, NULL, '2020-01-01', NULL, NULL, 'REMS', 'active'), +('TKP-053', 'Unit Test Panel', NULL, NULL, NULL, '2021-01-01', NULL, NULL, NULL, 'active'), +('TKP-054', '고소작업대', NULL, '500 Kg', NULL, '2021-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-055', '용접봉 건조기', '주문제작', '박스형', NULL, '2022-05-04', '진원하이텍', 2300000, '진원하이텍', 'active'), +('TKP-056', 'C&T 가공기', 'MS-CTK469', NULL, NULL, '2022-07-20', 'Swage-Lok', 7347600, 'Swage-Lok', 'active'), +('TKP-057', '테이블형 튜브 벤딩기', 'MS-BTT-K', '1/2", 1/4"', NULL, '2022-06-03', 'Swage-Lok', 20000000, 'Swage-Lok', 'active'), +('TKP-058', '자동용접기 헤드', 'SWS-10H-D-15', '1/2"', NULL, '2022-06-03', 'Swage-Lok', 20000000, 'Swage-Lok', 'active'), +('TKP-059', '천장주행크레인', 'HC-75D-13105', '7.5ton', NULL, '2023-06-09', '에이치앤씨', 22800000, '에이치앤씨', 'active'), +('TKP-060', 'AED', 'CU-SP1 Plus', '저출력심장충격기', NULL, '2023-11-09', '제이메디', 1600000, '제이메디', 'active'), +('TKP-061', '베벨머신', 'S-150', 'O.D 20mm ~ 170mm', NULL, '2023-12-12', 'DCSENG', 16000000, 'DCSENG', 'active'), +('TKP-062', '피막제거기', 'CM4_OD_GC', '최대 폭 48mm, 최대 깊이 15mm, 6"이상', NULL, '2023-12-12', 'DCSENG', 2000000, 'DCSENG', 'active'), +('TKP-063', '피막제거기', 'S-CM4_OD', '최대 폭 48mm, 최대 깊이 15mm, 1" 이상', NULL, '2023-12-12', 'DCSENG', 1200000, 'DCSENG', 'active'), +('TKP-064', '텅스텐 가공기', 'S-TGR', '0.89kg, 0.25~3.2', NULL, '2023-12-12', 'DCSENG', 800000, 'DCSENG', 'active'), +('TKP-065', '전동대차', 'LPM15', '2.0 ton', NULL, '2023-12-20', '두산산업차량', 2800000, '두산산업차량', 'active'); + +-- ============================================ +-- STEP 4: 결과 확인 +-- ============================================ +SELECT '===== 설비 데이터 입력 완료 =====' AS status; +SELECT COUNT(*) AS total_equipments FROM equipments; +SELECT + SUM(CASE WHEN purchase_price IS NOT NULL THEN purchase_price ELSE 0 END) AS total_purchase_value, + COUNT(CASE WHEN purchase_price IS NOT NULL THEN 1 END) AS equipments_with_price +FROM equipments; + +-- 최신 10개 설비 확인 +SELECT equipment_code, equipment_name, supplier, + FORMAT(purchase_price, 0) AS purchase_price_formatted, + manufacturer +FROM equipments +ORDER BY equipment_code DESC +LIMIT 10; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_insert_data.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_insert_data.sql new file mode 100644 index 0000000..d47a457 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_insert_data.sql @@ -0,0 +1,73 @@ +-- 설비 데이터 입력 (실제 테이블 구조에 맞춤) +-- 먼저 20260204_equipment_add_columns.sql 실행 후 이 파일 실행 + +-- 기존 TKP 데이터 삭제 +DELETE FROM equipments WHERE equipment_code LIKE 'TKP-%'; + +-- 65개 설비 데이터 입력 +INSERT INTO equipments (equipment_code, equipment_name, model, specifications, serial_number, purchase_date, supplier, purchase_price, manufacturer, status) VALUES +('TKP-001', 'AIR COMPRESSOR', 'AR10E', '7.5KW(10HP)', 'K603023Y', '2016-06-01', '지티씨', NULL, '경원', 'active'), +('TKP-002', 'TURN TABLE', 'YCT-200T', '220V', NULL, '2016-05-30', '형진종합공구', 3600000, '유체기계', 'active'), +('TKP-003', 'BAND SAW(中)', 'CY300W', '1500W*380V', '20150943', '2016-05-30', '형진종합공구', 4800000, '유림싸이겐', 'active'), +('TKP-004', 'BAND SAW(小)', 'XB-180WA', '180(VICE)', NULL, '2016-05-30', '형진종합공구', 2700000, '렉스', 'active'), +('TKP-005', 'BAND SAW(小)', 'XB-180WA', '180(VICE)', NULL, '2019-05-30', NULL, NULL, '렉스', 'active'), +('TKP-006', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-001', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-007', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-002', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-008', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-003', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-009', 'CO2용접기', 'COD-500A', '500A', '10880', '2016-05-30', '형진종합공구', 2000000, '대성용접기', 'active'), +('TKP-010', 'O2용접기', 'GSORK', '220V', NULL, '2016-05-30', '형진종합공구', 620000, '재현오토닉스', 'active'), +('TKP-011', 'PIPE BEVELLING MACHINE', 'S-200LT_MT(테이블포함)', '2" ~ 8"', 'KR-17030007', '2017-03-29', 'DCS ENG', 12000000, 'DCS ENG', 'active'), +('TKP-012', 'CO2용접기', '500MX', '220/380V,500A', NULL, '2017-08-02', '현대용접기', 1800000, '현대용접기', 'active'), +('TKP-013', '프라즈마', 'Perfect-150AP', '220/380/440V,140A', NULL, '2017-08-02', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-014', '터닝로라', 'JK-5-TR', '5TON/380V', NULL, '2017-09-08', '정일기공', 5700000, '정일기공', 'active'), +('TKP-015', '터닝로라', 'JK-5-TR', '5TON/380V', NULL, '2017-09-08', '정일기공', 5700000, '정일기공', 'active'), +('TKP-016', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-005', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-017', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-006', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-018', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-007', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-019', '전해연마기', 'ONB-8000VP', '220V/MAX1200W', '8022701', '2018-03-13', '오토기전', 1450000, '메탈브라이트(오토기전)', 'active'), +('TKP-020', '지게차', '50DA-9F', '5000KGS', 'HHKHFV36JJ0000061', '2018-05-10', '현대지게차', 45000000, '현대지게차', 'active'), +('TKP-021', '조방', NULL, '3658*12190', NULL, '2018-05-11', '천우기계공업/삼덕금속', 14200000, '테크니컬코리아', 'active'), +('TKP-022', 'BAND SAW(大)', 'WBS-RC500AN', '3,300kgs / 7.88kw', 'BC50A18-005F001', '2018-05-31', '원공사', 36000000, '원공사', 'active'), +('TKP-023', 'AIR COMPRESSOR', 'AR20E', '0.95Mpa', 'AR020FE358', '2018-06-05', '경원기계', NULL, '경원기계', 'active'), +('TKP-024', 'TURN TABLE', 'YCT-200TA', '220V', NULL, '2018-06-12', '청운종합공구', 3245000, '유체기계', 'active'), +('TKP-025', 'TIG용접기', 'Perfect-500WT', '500A/AC DC', 'ADKAC017B-006', '2018-06-12', '현대용접기', 2400000, '퍼펙트대대', 'active'), +('TKP-026', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAI018B-002', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-027', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAA018B-009', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-028', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAA018B-001', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-029', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1806077', '2018-07-06', '청운종합공구', 2300000, '대산', 'active'), +('TKP-030', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1807028', '2018-07-10', '청운종합공구', 2300000, '대산', 'active'), +('TKP-031', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1807029', '2018-07-10', '청운종합공구', 2300000, '대산', 'active'), +('TKP-032', '만능탭 드릴링머신', 'SF-TDM32', '1.5KW', NULL, '2018-11-09', '㈜애스앤애프', 2927000, '㈜애스앤에프', 'active'), +('TKP-033', '지게차', '30D-9B', '2850KGS', 'HHKHHN51KK0000864', '2019-03-06', '현대지게차', 29400000, '현대지게차', 'active'), +('TKP-034', '갠츄리크레인', 'CRANE - DHG', '50/10Ton x SP20M x T/L50M x H15M', NULL, '2019-05-09', '유진산업기계', 249000000, '반도호이스트', 'active'), +('TKP-035', 'OVER HEAD CRANE', 'CRANE - DHO', '20Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 58000000, '반도호이스트', 'active'), +('TKP-036', 'OVER HEAD CRANE', 'CRANE - DHO', '20Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 58000000, '반도호이스트', 'active'), +('TKP-037', 'OVER HEAD CRANE', 'CRANE - DHO', '5Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 29000000, '반도호이스트', 'active'), +('TKP-038', 'OVER HEAD CRANE', 'CRANE - DHO', '5Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 29000000, '반도호이스트', 'active'), +('TKP-039', '고소작업대', NULL, '250 Kg', NULL, '2019-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-040', '고소작업대', NULL, '250 Kg', NULL, '2019-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-041', 'AIR CONDITIONER', '코끼리 냉장고', NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-042', 'AIR CONDITIONER', NULL, NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-043', 'AIR CONDITIONER', NULL, NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-044', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-045', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-046', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-047', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-048', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-049', '자동용접기', NULL, NULL, NULL, '2019-01-01', 'Swage-Lok', 50000000, 'Swage-Lok', 'active'), +('TKP-050', 'Magnetic Drill', NULL, NULL, NULL, '2020-01-01', '청운종합공구', NULL, 'NITTO', 'active'), +('TKP-051', 'Magnetic Drill', NULL, NULL, NULL, '2020-01-01', '청운종합공구', NULL, 'Key-Yang', 'active'), +('TKP-052', 'Tube Bending M/C', NULL, NULL, NULL, '2020-01-01', NULL, NULL, 'REMS', 'active'), +('TKP-053', 'Unit Test Panel', NULL, NULL, NULL, '2021-01-01', NULL, NULL, NULL, 'active'), +('TKP-054', '고소작업대', NULL, '500 Kg', NULL, '2021-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-055', '용접봉 건조기', '주문제작', '박스형', NULL, '2022-05-04', '진원하이텍', 2300000, '진원하이텍', 'active'), +('TKP-056', 'C&T 가공기', 'MS-CTK469', NULL, NULL, '2022-07-20', 'Swage-Lok', 7347600, 'Swage-Lok', 'active'), +('TKP-057', '테이블형 튜브 벤딩기', 'MS-BTT-K', '1/2", 1/4"', NULL, '2022-06-03', 'Swage-Lok', 20000000, 'Swage-Lok', 'active'), +('TKP-058', '자동용접기 헤드', 'SWS-10H-D-15', '1/2"', NULL, '2022-06-03', 'Swage-Lok', 20000000, 'Swage-Lok', 'active'), +('TKP-059', '천장주행크레인', 'HC-75D-13105', '7.5ton', NULL, '2023-06-09', '에이치앤씨', 22800000, '에이치앤씨', 'active'), +('TKP-060', 'AED', 'CU-SP1 Plus', '저출력심장충격기', NULL, '2023-11-09', '제이메디', 1600000, '제이메디', 'active'), +('TKP-061', '베벨머신', 'S-150', 'O.D 20mm ~ 170mm', NULL, '2023-12-12', 'DCSENG', 16000000, 'DCSENG', 'active'), +('TKP-062', '피막제거기', 'CM4_OD_GC', '최대 폭 48mm, 최대 깊이 15mm, 6"이상', NULL, '2023-12-12', 'DCSENG', 2000000, 'DCSENG', 'active'), +('TKP-063', '피막제거기', 'S-CM4_OD', '최대 폭 48mm, 최대 깊이 15mm, 1" 이상', NULL, '2023-12-12', 'DCSENG', 1200000, 'DCSENG', 'active'), +('TKP-064', '텅스텐 가공기', 'S-TGR', '0.89kg, 0.25~3.2', NULL, '2023-12-12', 'DCSENG', 800000, 'DCSENG', 'active'), +('TKP-065', '전동대차', 'LPM15', '2.0 ton', NULL, '2023-12-20', '두산산업차량', 2800000, '두산산업차량', 'active'); diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_simple.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_simple.sql new file mode 100644 index 0000000..c49fc81 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260204_equipment_simple.sql @@ -0,0 +1,78 @@ +-- 설비 관리 설정 (phpMyAdmin용 단순 버전) +-- phpMyAdmin에서 가져오기로 실행 + +-- ============================================ +-- STEP 2: 기존 TKP 데이터 삭제 +-- ============================================ +DELETE FROM equipments WHERE equipment_code LIKE 'TKP-%'; + +-- ============================================ +-- STEP 3: 65개 설비 데이터 입력 +-- ============================================ + +INSERT INTO equipments (equipment_code, equipment_name, model_name, specifications, serial_number, installation_date, supplier, purchase_price, manufacturer, status) VALUES +('TKP-001', 'AIR COMPRESSOR', 'AR10E', '7.5KW(10HP)', 'K603023Y', '2016-06-01', '지티씨', NULL, '경원', 'active'), +('TKP-002', 'TURN TABLE', 'YCT-200T', '220V', NULL, '2016-05-30', '형진종합공구', 3600000, '유체기계', 'active'), +('TKP-003', 'BAND SAW(中)', 'CY300W', '1500W*380V', '20150943', '2016-05-30', '형진종합공구', 4800000, '유림싸이겐', 'active'), +('TKP-004', 'BAND SAW(小)', 'XB-180WA', '180(VICE)', NULL, '2016-05-30', '형진종합공구', 2700000, '렉스', 'active'), +('TKP-005', 'BAND SAW(小)', 'XB-180WA', '180(VICE)', NULL, '2019-05-30', NULL, NULL, '렉스', 'active'), +('TKP-006', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-001', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-007', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-002', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-008', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-003', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-009', 'CO2용접기', 'COD-500A', '500A', '10880', '2016-05-30', '형진종합공구', 2000000, '대성용접기', 'active'), +('TKP-010', 'O2용접기', 'GSORK', '220V', NULL, '2016-05-30', '형진종합공구', 620000, '재현오토닉스', 'active'), +('TKP-011', 'PIPE BEVELLING MACHINE', 'S-200LT_MT(테이블포함)', '2" ~ 8"', 'KR-17030007', '2017-03-29', 'DCS ENG', 12000000, 'DCS ENG', 'active'), +('TKP-012', 'CO2용접기', '500MX', '220/380V,500A', NULL, '2017-08-02', '현대용접기', 1800000, '현대용접기', 'active'), +('TKP-013', '프라즈마', 'Perfect-150AP', '220/380/440V,140A', NULL, '2017-08-02', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-014', '터닝로라', 'JK-5-TR', '5TON/380V', NULL, '2017-09-08', '정일기공', 5700000, '정일기공', 'active'), +('TKP-015', '터닝로라', 'JK-5-TR', '5TON/380V', NULL, '2017-09-08', '정일기공', 5700000, '정일기공', 'active'), +('TKP-016', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-005', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-017', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-006', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-018', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-007', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-019', '전해연마기', 'ONB-8000VP', '220V/MAX1200W', '8022701', '2018-03-13', '오토기전', 1450000, '메탈브라이트(오토기전)', 'active'), +('TKP-020', '지게차', '50DA-9F', '5000KGS', 'HHKHFV36JJ0000061', '2018-05-10', '현대지게차', 45000000, '현대지게차', 'active'), +('TKP-021', '조방', NULL, '3658*12190', NULL, '2018-05-11', '천우기계공업/삼덕금속', 14200000, '테크니컬코리아', 'active'), +('TKP-022', 'BAND SAW(大)', 'WBS-RC500AN', '3,300kgs / 7.88kw', 'BC50A18-005F001', '2018-05-31', '원공사', 36000000, '원공사', 'active'), +('TKP-023', 'AIR COMPRESSOR', 'AR20E', '0.95Mpa', 'AR020FE358', '2018-06-05', '경원기계', NULL, '경원기계', 'active'), +('TKP-024', 'TURN TABLE', 'YCT-200TA', '220V', NULL, '2018-06-12', '청운종합공구', 3245000, '유체기계', 'active'), +('TKP-025', 'TIG용접기', 'Perfect-500WT', '500A/AC DC', 'ADKAC017B-006', '2018-06-12', '현대용접기', 2400000, '퍼펙트대대', 'active'), +('TKP-026', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAI018B-002', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-027', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAA018B-009', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-028', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAA018B-001', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-029', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1806077', '2018-07-06', '청운종합공구', 2300000, '대산', 'active'), +('TKP-030', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1807028', '2018-07-10', '청운종합공구', 2300000, '대산', 'active'), +('TKP-031', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1807029', '2018-07-10', '청운종합공구', 2300000, '대산', 'active'), +('TKP-032', '만능탭 드릴링머신', 'SF-TDM32', '1.5KW', NULL, '2018-11-09', '㈜애스앤애프', 2927000, '㈜애스앤에프', 'active'), +('TKP-033', '지게차', '30D-9B', '2850KGS', 'HHKHHN51KK0000864', '2019-03-06', '현대지게차', 29400000, '현대지게차', 'active'), +('TKP-034', '갠츄리크레인', 'CRANE - DHG', '50/10Ton x SP20M x T/L50M x H15M', NULL, '2019-05-09', '유진산업기계', 249000000, '반도호이스트', 'active'), +('TKP-035', 'OVER HEAD CRANE', 'CRANE - DHO', '20Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 58000000, '반도호이스트', 'active'), +('TKP-036', 'OVER HEAD CRANE', 'CRANE - DHO', '20Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 58000000, '반도호이스트', 'active'), +('TKP-037', 'OVER HEAD CRANE', 'CRANE - DHO', '5Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 29000000, '반도호이스트', 'active'), +('TKP-038', 'OVER HEAD CRANE', 'CRANE - DHO', '5Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 29000000, '반도호이스트', 'active'), +('TKP-039', '고소작업대', NULL, '250 Kg', NULL, '2019-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-040', '고소작업대', NULL, '250 Kg', NULL, '2019-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-041', 'AIR CONDITIONER', '코끼리 냉장고', NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-042', 'AIR CONDITIONER', NULL, NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-043', 'AIR CONDITIONER', NULL, NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-044', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-045', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-046', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-047', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-048', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-049', '자동용접기', NULL, NULL, NULL, '2019-01-01', 'Swage-Lok', 50000000, 'Swage-Lok', 'active'), +('TKP-050', 'Magnetic Drill', NULL, NULL, NULL, '2020-01-01', '청운종합공구', NULL, 'NITTO', 'active'), +('TKP-051', 'Magnetic Drill', NULL, NULL, NULL, '2020-01-01', '청운종합공구', NULL, 'Key-Yang', 'active'), +('TKP-052', 'Tube Bending M/C', NULL, NULL, NULL, '2020-01-01', NULL, NULL, 'REMS', 'active'), +('TKP-053', 'Unit Test Panel', NULL, NULL, NULL, '2021-01-01', NULL, NULL, NULL, 'active'), +('TKP-054', '고소작업대', NULL, '500 Kg', NULL, '2021-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-055', '용접봉 건조기', '주문제작', '박스형', NULL, '2022-05-04', '진원하이텍', 2300000, '진원하이텍', 'active'), +('TKP-056', 'C&T 가공기', 'MS-CTK469', NULL, NULL, '2022-07-20', 'Swage-Lok', 7347600, 'Swage-Lok', 'active'), +('TKP-057', '테이블형 튜브 벤딩기', 'MS-BTT-K', '1/2", 1/4"', NULL, '2022-06-03', 'Swage-Lok', 20000000, 'Swage-Lok', 'active'), +('TKP-058', '자동용접기 헤드', 'SWS-10H-D-15', '1/2"', NULL, '2022-06-03', 'Swage-Lok', 20000000, 'Swage-Lok', 'active'), +('TKP-059', '천장주행크레인', 'HC-75D-13105', '7.5ton', NULL, '2023-06-09', '에이치앤씨', 22800000, '에이치앤씨', 'active'), +('TKP-060', 'AED', 'CU-SP1 Plus', '저출력심장충격기', NULL, '2023-11-09', '제이메디', 1600000, '제이메디', 'active'), +('TKP-061', '베벨머신', 'S-150', 'O.D 20mm ~ 170mm', NULL, '2023-12-12', 'DCSENG', 16000000, 'DCSENG', 'active'), +('TKP-062', '피막제거기', 'CM4_OD_GC', '최대 폭 48mm, 최대 깊이 15mm, 6"이상', NULL, '2023-12-12', 'DCSENG', 2000000, 'DCSENG', 'active'), +('TKP-063', '피막제거기', 'S-CM4_OD', '최대 폭 48mm, 최대 깊이 15mm, 1" 이상', NULL, '2023-12-12', 'DCSENG', 1200000, 'DCSENG', 'active'), +('TKP-064', '텅스텐 가공기', 'S-TGR', '0.89kg, 0.25~3.2', NULL, '2023-12-12', 'DCSENG', 800000, 'DCSENG', 'active'), +('TKP-065', '전동대차', 'LPM15', '2.0 ton', NULL, '2023-12-20', '두산산업차량', 2800000, '두산산업차량', 'active'); diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205001000_create_equipment_photos.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205001000_create_equipment_photos.sql new file mode 100644 index 0000000..bdfa74a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205001000_create_equipment_photos.sql @@ -0,0 +1,17 @@ +-- 설비 사진 테이블 생성 +-- 실행: docker exec -i tkfb_db mysql -u hyungi -p'your_password' hyungi < db/migrations/20260205001000_create_equipment_photos.sql + +CREATE TABLE IF NOT EXISTS equipment_photos ( + photo_id INT AUTO_INCREMENT PRIMARY KEY, + equipment_id INT UNSIGNED NOT NULL, + photo_path VARCHAR(255) NOT NULL COMMENT '이미지 경로', + description VARCHAR(200) COMMENT '사진 설명', + display_order INT DEFAULT 0 COMMENT '표시 순서', + uploaded_by INT COMMENT '업로드한 사용자 ID', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT fk_eq_photos_equipment FOREIGN KEY (equipment_id) + REFERENCES equipments(equipment_id) ON DELETE CASCADE, + CONSTRAINT fk_eq_photos_user FOREIGN KEY (uploaded_by) + REFERENCES users(user_id) ON DELETE SET NULL, + INDEX idx_eq_photos_equipment_id (equipment_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205002000_add_equipment_move_fields.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205002000_add_equipment_move_fields.sql new file mode 100644 index 0000000..694194a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205002000_add_equipment_move_fields.sql @@ -0,0 +1,174 @@ +-- 설비 임시이동 필드 추가 및 신고 시스템 연동 +-- 실행: docker exec -i tkfb_db mysql -u hyungi -p'your_password' hyungi < db/migrations/20260205002000_add_equipment_move_fields.sql + +SET @dbname = DATABASE(); + +-- ============================================ +-- STEP 1: equipments 테이블에 임시이동 필드 추가 +-- ============================================ + +-- current_workplace_id 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'equipments' AND column_name = 'current_workplace_id'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN current_workplace_id INT UNSIGNED NULL COMMENT ''현재 임시 위치 - 작업장 ID'' AFTER map_height_percent', + 'SELECT ''current_workplace_id already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- current_map_x_percent 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'equipments' AND column_name = 'current_map_x_percent'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN current_map_x_percent DECIMAL(5,2) NULL COMMENT ''현재 위치 X%'' AFTER current_workplace_id', + 'SELECT ''current_map_x_percent already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- current_map_y_percent 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'equipments' AND column_name = 'current_map_y_percent'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN current_map_y_percent DECIMAL(5,2) NULL COMMENT ''현재 위치 Y%'' AFTER current_map_x_percent', + 'SELECT ''current_map_y_percent already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- current_map_width_percent 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'equipments' AND column_name = 'current_map_width_percent'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN current_map_width_percent DECIMAL(5,2) NULL COMMENT ''현재 위치 너비%'' AFTER current_map_y_percent', + 'SELECT ''current_map_width_percent already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- current_map_height_percent 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'equipments' AND column_name = 'current_map_height_percent'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN current_map_height_percent DECIMAL(5,2) NULL COMMENT ''현재 위치 높이%'' AFTER current_map_width_percent', + 'SELECT ''current_map_height_percent already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- is_temporarily_moved 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'equipments' AND column_name = 'is_temporarily_moved'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN is_temporarily_moved BOOLEAN DEFAULT FALSE COMMENT ''임시 이동 상태'' AFTER current_map_height_percent', + 'SELECT ''is_temporarily_moved already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- moved_at 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'equipments' AND column_name = 'moved_at'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN moved_at DATETIME NULL COMMENT ''이동 일시'' AFTER is_temporarily_moved', + 'SELECT ''moved_at already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- moved_by 컬럼 추가 +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'equipments' AND column_name = 'moved_by'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE equipments ADD COLUMN moved_by INT NULL COMMENT ''이동 처리자'' AFTER moved_at', + 'SELECT ''moved_by already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- Foreign Key: current_workplace_id -> workplaces +SELECT COUNT(*) INTO @fk_exists +FROM information_schema.table_constraints +WHERE table_schema = @dbname AND table_name = 'equipments' AND constraint_name = 'fk_eq_current_workplace'; + +SET @sql = IF(@fk_exists = 0, + 'ALTER TABLE equipments ADD CONSTRAINT fk_eq_current_workplace FOREIGN KEY (current_workplace_id) REFERENCES workplaces(workplace_id) ON DELETE SET NULL', + 'SELECT ''fk_eq_current_workplace already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SELECT 'equipments 임시이동 필드 추가 완료' AS status; + +-- ============================================ +-- STEP 2: work_issue_reports에 equipment_id 필드 추가 +-- ============================================ + +SELECT COUNT(*) INTO @col_exists +FROM information_schema.columns +WHERE table_schema = @dbname AND table_name = 'work_issue_reports' AND column_name = 'equipment_id'; + +SET @sql = IF(@col_exists = 0, + 'ALTER TABLE work_issue_reports ADD COLUMN equipment_id INT UNSIGNED NULL COMMENT ''관련 설비 ID'' AFTER visit_request_id', + 'SELECT ''equipment_id already exists in work_issue_reports'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- Foreign Key +SELECT COUNT(*) INTO @fk_exists +FROM information_schema.table_constraints +WHERE table_schema = @dbname AND table_name = 'work_issue_reports' AND constraint_name = 'fk_wir_equipment'; + +SET @sql = IF(@fk_exists = 0 AND @col_exists = 0, + 'ALTER TABLE work_issue_reports ADD CONSTRAINT fk_wir_equipment FOREIGN KEY (equipment_id) REFERENCES equipments(equipment_id) ON DELETE SET NULL', + 'SELECT ''fk_wir_equipment already exists or column not added'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +-- Index +SELECT COUNT(*) INTO @idx_exists +FROM information_schema.statistics +WHERE table_schema = @dbname AND table_name = 'work_issue_reports' AND index_name = 'idx_wir_equipment_id'; + +SET @sql = IF(@idx_exists = 0 AND @col_exists = 0, + 'ALTER TABLE work_issue_reports ADD INDEX idx_wir_equipment_id (equipment_id)', + 'SELECT ''idx_wir_equipment_id already exists'''); +PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; + +SELECT 'work_issue_reports equipment_id 추가 완료' AS status; + +-- ============================================ +-- STEP 3: 설비 수리 카테고리 추가 +-- ============================================ + +INSERT INTO issue_report_categories (category_type, category_name, description, display_order, is_active) +SELECT 'nonconformity', '설비 수리', '설비 고장 및 수리 요청', 10, 1 +WHERE NOT EXISTS ( + SELECT 1 FROM issue_report_categories WHERE category_name = '설비 수리' +); + +-- 설비 수리 카테고리에 기본 항목 추가 +SET @category_id = (SELECT category_id FROM issue_report_categories WHERE category_name = '설비 수리' LIMIT 1); + +INSERT INTO issue_report_items (category_id, item_name, description, severity, display_order, is_active) +SELECT @category_id, '기계 고장', '기계 작동 불가 또는 이상', 'high', 1, 1 +WHERE @category_id IS NOT NULL AND NOT EXISTS ( + SELECT 1 FROM issue_report_items WHERE category_id = @category_id AND item_name = '기계 고장' +); + +INSERT INTO issue_report_items (category_id, item_name, description, severity, display_order, is_active) +SELECT @category_id, '부품 교체 필요', '소모품 또는 부품 교체 필요', 'medium', 2, 1 +WHERE @category_id IS NOT NULL AND NOT EXISTS ( + SELECT 1 FROM issue_report_items WHERE category_id = @category_id AND item_name = '부품 교체 필요' +); + +INSERT INTO issue_report_items (category_id, item_name, description, severity, display_order, is_active) +SELECT @category_id, '정기 점검 필요', '예방 정비 또는 정기 점검', 'low', 3, 1 +WHERE @category_id IS NOT NULL AND NOT EXISTS ( + SELECT 1 FROM issue_report_items WHERE category_id = @category_id AND item_name = '정기 점검 필요' +); + +INSERT INTO issue_report_items (category_id, item_name, description, severity, display_order, is_active) +SELECT @category_id, '외부 수리 필요', '전문 업체 수리가 필요한 경우', 'high', 4, 1 +WHERE @category_id IS NOT NULL AND NOT EXISTS ( + SELECT 1 FROM issue_report_items WHERE category_id = @category_id AND item_name = '외부 수리 필요' +); + +SELECT '설비 수리 카테고리 및 항목 추가 완료' AS status; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205003000_create_equipment_external_logs.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205003000_create_equipment_external_logs.sql new file mode 100644 index 0000000..11a8291 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205003000_create_equipment_external_logs.sql @@ -0,0 +1,86 @@ +-- 설비 외부반출 테이블 생성 및 상태 ENUM 확장 +-- 실행: docker exec -i tkfb_db mysql -u hyungi -p'your_password' hyungi < db/migrations/20260205003000_create_equipment_external_logs.sql + +SET @dbname = DATABASE(); + +-- ============================================ +-- STEP 1: equipment_external_logs 테이블 생성 +-- ============================================ + +CREATE TABLE IF NOT EXISTS equipment_external_logs ( + log_id INT AUTO_INCREMENT PRIMARY KEY, + equipment_id INT UNSIGNED NOT NULL COMMENT '설비 ID', + log_type ENUM('export', 'return') NOT NULL COMMENT '반출/반입', + export_date DATE COMMENT '반출일', + expected_return_date DATE COMMENT '반입 예정일', + actual_return_date DATE COMMENT '실제 반입일', + destination VARCHAR(200) COMMENT '반출처 (수리업체명 등)', + reason TEXT COMMENT '반출 사유', + notes TEXT COMMENT '비고', + exported_by INT COMMENT '반출 담당자', + returned_by INT COMMENT '반입 담당자', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + CONSTRAINT fk_eel_equipment FOREIGN KEY (equipment_id) + REFERENCES equipments(equipment_id) ON DELETE CASCADE, + CONSTRAINT fk_eel_exported_by FOREIGN KEY (exported_by) + REFERENCES users(user_id) ON DELETE SET NULL, + CONSTRAINT fk_eel_returned_by FOREIGN KEY (returned_by) + REFERENCES users(user_id) ON DELETE SET NULL, + INDEX idx_eel_equipment_id (equipment_id), + INDEX idx_eel_log_type (log_type), + INDEX idx_eel_export_date (export_date) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +SELECT 'equipment_external_logs 테이블 생성 완료' AS status; + +-- ============================================ +-- STEP 2: equipments 테이블 status ENUM 확장 +-- ============================================ + +-- 현재 status 컬럼의 ENUM 값 확인 후 확장 +-- 기존: active, maintenance, repair_needed, inactive +-- 추가: external (외부 반출), repair_external (수리 외주) + +ALTER TABLE equipments +MODIFY COLUMN status ENUM( + 'active', -- 정상 가동 + 'maintenance', -- 점검 중 + 'repair_needed', -- 수리 필요 + 'inactive', -- 비활성 + 'external', -- 외부 반출 + 'repair_external' -- 수리 외주 (외부 수리) +) DEFAULT 'active' COMMENT '설비 상태'; + +SELECT 'equipments status ENUM 확장 완료' AS status; + +-- ============================================ +-- STEP 3: 설비 이동 이력 테이블 생성 (선택) +-- ============================================ + +CREATE TABLE IF NOT EXISTS equipment_move_logs ( + log_id INT AUTO_INCREMENT PRIMARY KEY, + equipment_id INT UNSIGNED NOT NULL COMMENT '설비 ID', + move_type ENUM('temporary', 'return') NOT NULL COMMENT '임시이동/복귀', + from_workplace_id INT UNSIGNED COMMENT '이전 작업장', + to_workplace_id INT UNSIGNED COMMENT '이동 작업장', + from_x_percent DECIMAL(5,2) COMMENT '이전 X좌표', + from_y_percent DECIMAL(5,2) COMMENT '이전 Y좌표', + to_x_percent DECIMAL(5,2) COMMENT '이동 X좌표', + to_y_percent DECIMAL(5,2) COMMENT '이동 Y좌표', + reason TEXT COMMENT '이동 사유', + moved_by INT COMMENT '이동 처리자', + moved_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT fk_eml_equipment FOREIGN KEY (equipment_id) + REFERENCES equipments(equipment_id) ON DELETE CASCADE, + CONSTRAINT fk_eml_from_workplace FOREIGN KEY (from_workplace_id) + REFERENCES workplaces(workplace_id) ON DELETE SET NULL, + CONSTRAINT fk_eml_to_workplace FOREIGN KEY (to_workplace_id) + REFERENCES workplaces(workplace_id) ON DELETE SET NULL, + CONSTRAINT fk_eml_moved_by FOREIGN KEY (moved_by) + REFERENCES users(user_id) ON DELETE SET NULL, + INDEX idx_eml_equipment_id (equipment_id), + INDEX idx_eml_move_type (move_type) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +SELECT 'equipment_move_logs 테이블 생성 완료' AS status; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205004000_create_notifications.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205004000_create_notifications.sql new file mode 100644 index 0000000..a1ca15e --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205004000_create_notifications.sql @@ -0,0 +1,46 @@ +-- 알림 시스템 테이블 생성 +-- 실행: docker exec -i tkfb_db mysql -u hyungi -p'your_password' hyungi < db/migrations/20260205004000_create_notifications.sql + +-- ============================================ +-- STEP 1: notifications 테이블 생성 +-- ============================================ + +CREATE TABLE IF NOT EXISTS notifications ( + notification_id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NULL COMMENT '특정 사용자에게만 표시 (NULL이면 전체)', + type ENUM('repair', 'safety', 'system', 'equipment', 'maintenance') NOT NULL DEFAULT 'system', + title VARCHAR(200) NOT NULL, + message TEXT, + link_url VARCHAR(500) COMMENT '클릭시 이동할 URL', + reference_type VARCHAR(50) COMMENT '연관 테이블 (equipment_repair_requests 등)', + reference_id INT COMMENT '연관 레코드 ID', + is_read BOOLEAN DEFAULT FALSE, + read_at DATETIME NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + created_by INT NULL, + INDEX idx_notifications_user (user_id), + INDEX idx_notifications_type (type), + INDEX idx_notifications_is_read (is_read), + INDEX idx_notifications_created (created_at DESC) +); + +-- 수리 요청 테이블 수정 (알림 연동을 위해) +-- equipment_repair_requests 테이블이 없으면 생성 +CREATE TABLE IF NOT EXISTS equipment_repair_requests ( + request_id INT AUTO_INCREMENT PRIMARY KEY, + equipment_id INT UNSIGNED NOT NULL, + repair_type VARCHAR(100) NOT NULL, + description TEXT, + urgency ENUM('low', 'normal', 'high', 'urgent') DEFAULT 'normal', + status ENUM('pending', 'in_progress', 'completed', 'cancelled') DEFAULT 'pending', + requested_by INT, + assigned_to INT NULL, + completed_at DATETIME NULL, + notes TEXT, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (equipment_id) REFERENCES equipments(equipment_id) ON DELETE CASCADE, + INDEX idx_err_equipment (equipment_id), + INDEX idx_err_status (status), + INDEX idx_err_created (created_at DESC) +); diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205_fix_work_type_id_data.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205_fix_work_type_id_data.js new file mode 100644 index 0000000..53c520a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260205_fix_work_type_id_data.js @@ -0,0 +1,105 @@ +/** + * 마이그레이션: TBM 기반 작업보고서의 work_type_id를 task_id로 수정 + * + * 문제: TBM에서 작업보고서 생성 시 work_type_id(공정 ID)가 저장됨 + * 해결: tbm_team_assignments 테이블의 task_id로 업데이트 + * + * 실행: node db/migrations/20260205_fix_work_type_id_data.js + */ + +const { getDb } = require('../../dbPool'); + +async function migrate() { + const db = await getDb(); + + console.log('🔄 TBM 기반 작업보고서 work_type_id 수정 시작...\n'); + + try { + // 1. 수정 대상 확인 (TBM 기반이면서 work_type_id가 task_id와 다른 경우) + const [checkResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id as current_work_type_id, + ta.task_id as correct_task_id, + ta.work_type_id as tbm_work_type_id, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + INNER JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + ORDER BY dwr.report_date DESC + `); + + console.log(`📊 수정 대상: ${checkResult.length}개 레코드\n`); + + if (checkResult.length === 0) { + console.log('✅ 수정할 데이터가 없습니다.'); + return; + } + + // 수정 대상 샘플 출력 + console.log('📋 수정 대상 샘플 (최대 10개):'); + console.log('─'.repeat(80)); + checkResult.slice(0, 10).forEach(row => { + console.log(` ID: ${row.id} | ${row.worker_name} | ${row.report_date}`); + console.log(` 현재 work_type_id: ${row.current_work_type_id} → 올바른 task_id: ${row.correct_task_id}`); + }); + if (checkResult.length > 10) { + console.log(` ... 외 ${checkResult.length - 10}개`); + } + console.log('─'.repeat(80)); + + // 2. 업데이트 실행 + const [updateResult] = await db.query(` + UPDATE daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + SET dwr.work_type_id = ta.task_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + `); + + console.log(`\n✅ 업데이트 완료: ${updateResult.affectedRows}개 레코드 수정됨`); + + // 3. 수정 결과 확인 + const [verifyResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id, + ta.task_id, + t.task_name, + wt.name as work_type_name + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + WHERE dwr.tbm_assignment_id IS NOT NULL + LIMIT 5 + `); + + console.log('\n📋 수정 후 샘플 확인:'); + console.log('─'.repeat(80)); + verifyResult.forEach(row => { + console.log(` ID: ${row.id} | work_type_id: ${row.work_type_id} | task: ${row.task_name || 'N/A'} | 공정: ${row.work_type_name || 'N/A'}`); + }); + console.log('─'.repeat(80)); + + } catch (error) { + console.error('❌ 마이그레이션 실패:', error.message); + throw error; + } +} + +// 실행 +migrate() + .then(() => { + console.log('\n🎉 마이그레이션 완료!'); + process.exit(0); + }) + .catch(err => { + console.error('\n💥 마이그레이션 실패:', err); + process.exit(1); + }); diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_final.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_final.sql new file mode 100644 index 0000000..3082a30 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_final.sql @@ -0,0 +1,56 @@ +-- ============================================ +-- error_types → issue_report_items 마이그레이션 +-- 실행 전 반드시 백업하세요! +-- ============================================ + +-- STEP 1: 현재 상태 확인 +-- ============================================ +SELECT 'Before Migration' as status; +SELECT error_type_id, COUNT(*) as cnt FROM daily_work_reports WHERE error_type_id IS NOT NULL GROUP BY error_type_id; + + +-- STEP 2: 매핑 업데이트 실행 +-- ============================================ +-- 주의: 순서가 중요! (충돌 방지를 위해 큰 숫자부터) + +-- 6 (검사불량) → 14 (치수 검사 누락) +UPDATE daily_work_reports SET error_type_id = 14 WHERE error_type_id = 6; + +-- 5 (설비고장) → 38 (기계 고장) +UPDATE daily_work_reports SET error_type_id = 38 WHERE error_type_id = 5; + +-- 4 (작업불량) → 43 (NDE 불합격) +UPDATE daily_work_reports SET error_type_id = 43 WHERE error_type_id = 4; + +-- 3 (입고지연) → 1 (배관 자재 미입고) - 이미 1이므로 충돌 가능, 임시값 사용 +UPDATE daily_work_reports SET error_type_id = 99991 WHERE error_type_id = 3; + +-- 2 (외주작업 불량) → 10 (외관 불량) +UPDATE daily_work_reports SET error_type_id = 10 WHERE error_type_id = 2; + +-- 1 (설계미스) → 6 (도면 치수 오류) - 6은 이미 업데이트됨 +UPDATE daily_work_reports SET error_type_id = 6 WHERE error_type_id = 1; + +-- 임시값 복원: 99991 → 1 +UPDATE daily_work_reports SET error_type_id = 1 WHERE error_type_id = 99991; + + +-- STEP 3: 마이그레이션 결과 확인 +-- ============================================ +SELECT 'After Migration' as status; +SELECT + dwr.error_type_id, + iri.item_name, + irc.category_name, + COUNT(*) as cnt +FROM daily_work_reports dwr +LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id +LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id +WHERE dwr.error_type_id IS NOT NULL +GROUP BY dwr.error_type_id, iri.item_name, irc.category_name; + + +-- STEP 4: error_types 테이블 삭제 (선택사항) +-- ============================================ +-- 마이그레이션 확인 후 주석 해제하여 실행 +-- DROP TABLE IF EXISTS error_types; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.js b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.js new file mode 100644 index 0000000..18659f1 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.js @@ -0,0 +1,112 @@ +/** + * 마이그레이션: error_types에서 issue_report_items로 전환 + * + * 기존 daily_work_reports.error_type_id가 error_types.id를 참조하던 것을 + * issue_report_items.item_id를 참조하도록 변경 + * + * 기존 error_types 데이터: + * id=1: 설계미스 + * id=2: 외주작업 불량 + * id=3: 입고지연 + * + * 새 issue_report_categories 데이터: + * category_id=1: 자재누락 (nonconformity) + * category_id=2: 설계미스 (nonconformity) + * category_id=3: 입고불량 (nonconformity) + * + * 매핑 전략: + * - error_types.id=1 (설계미스) → issue_report_items에서 '설계미스' 카테고리의 첫 번째 항목 + * - error_types.id=2 (외주작업 불량) → issue_report_items에서 '입고불량' 카테고리의 '외관 불량' 항목 + * - error_types.id=3 (입고지연) → issue_report_items에서 '자재누락' 카테고리의 첫 번째 항목 + */ + +exports.up = async function(knex) { + console.log('=== error_type_id 마이그레이션 시작 ==='); + + // 1. 기존 error_types 데이터와 새 issue_report_items 매핑 테이블 조회 + const [categories] = await knex.raw(` + SELECT category_id, category_name + FROM issue_report_categories + WHERE category_type = 'nonconformity' + `); + console.log('부적합 카테고리:', categories); + + const [items] = await knex.raw(` + SELECT iri.item_id, iri.item_name, iri.category_id, irc.category_name + FROM issue_report_items iri + JOIN issue_report_categories irc ON iri.category_id = irc.category_id + WHERE irc.category_type = 'nonconformity' + ORDER BY iri.category_id, iri.display_order + `); + console.log('부적합 항목:', items); + + // 2. 매핑 정의 (기존 error_type_id → 새 issue_report_items.item_id) + // 설계미스 카테고리 찾기 + const designMissCategory = categories.find(c => c.category_name === '설계미스'); + const incomingDefectCategory = categories.find(c => c.category_name === '입고불량'); + const materialShortageCategory = categories.find(c => c.category_name === '자재누락'); + + // 각 카테고리의 첫 번째 항목 찾기 + const designMissItem = items.find(i => i.category_id === designMissCategory?.category_id); + const incomingDefectItem = items.find(i => i.category_id === incomingDefectCategory?.category_id); + const materialShortageItem = items.find(i => i.category_id === materialShortageCategory?.category_id); + + console.log('매핑 결과:'); + console.log(' - 설계미스(1) → item_id:', designMissItem?.item_id); + console.log(' - 외주작업불량(2) → item_id:', incomingDefectItem?.item_id); + console.log(' - 입고지연(3) → item_id:', materialShortageItem?.item_id); + + // 3. 기존 데이터 업데이트 + if (designMissItem) { + const [result1] = await knex.raw(` + UPDATE daily_work_reports + SET error_type_id = ? + WHERE error_type_id = 1 + `, [designMissItem.item_id]); + console.log('설계미스(1) 업데이트:', result1.affectedRows, '건'); + } + + if (incomingDefectItem) { + const [result2] = await knex.raw(` + UPDATE daily_work_reports + SET error_type_id = ? + WHERE error_type_id = 2 + `, [incomingDefectItem.item_id]); + console.log('외주작업불량(2) 업데이트:', result2.affectedRows, '건'); + } + + if (materialShortageItem) { + const [result3] = await knex.raw(` + UPDATE daily_work_reports + SET error_type_id = ? + WHERE error_type_id = 3 + `, [materialShortageItem.item_id]); + console.log('입고지연(3) 업데이트:', result3.affectedRows, '건'); + } + + // 4. 매핑 안된 나머지 데이터 확인 (4 이상의 error_type_id) + const [unmapped] = await knex.raw(` + SELECT DISTINCT error_type_id, COUNT(*) as cnt + FROM daily_work_reports + WHERE error_type_id IS NOT NULL + AND error_type_id NOT IN (?, ?, ?) + GROUP BY error_type_id + `, [ + designMissItem?.item_id || 0, + incomingDefectItem?.item_id || 0, + materialShortageItem?.item_id || 0 + ]); + + if (unmapped.length > 0) { + console.log('⚠️ 매핑되지 않은 error_type_id 발견:', unmapped); + console.log(' 이 데이터는 수동으로 확인 필요'); + } + + console.log('=== error_type_id 마이그레이션 완료 ==='); +}; + +exports.down = async function(knex) { + // 롤백은 복잡하므로 로그만 출력 + console.log('⚠️ 이 마이그레이션은 자동 롤백을 지원하지 않습니다.'); + console.log(' 데이터 복구가 필요한 경우 백업에서 복원해주세요.'); +}; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.sql new file mode 100644 index 0000000..4330533 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/20260206_migrate_error_types_to_issue_items.sql @@ -0,0 +1,73 @@ +-- ============================================ +-- error_types → issue_report_items 마이그레이션 +-- ============================================ + +-- STEP 1: 현재 데이터 확인 +-- ============================================ + +-- 기존 error_types 확인 +SELECT * FROM error_types; + +-- 새 issue_report_categories 확인 (부적합만) +SELECT * FROM issue_report_categories WHERE category_type = 'nonconformity'; + +-- 새 issue_report_items 확인 (부적합만) +SELECT + iri.item_id, + iri.item_name, + iri.category_id, + irc.category_name +FROM issue_report_items iri +JOIN issue_report_categories irc ON iri.category_id = irc.category_id +WHERE irc.category_type = 'nonconformity' +ORDER BY irc.display_order, iri.display_order; + +-- 현재 daily_work_reports에서 사용 중인 error_type_id 확인 +SELECT + error_type_id, + COUNT(*) as cnt, + et.name as old_error_name +FROM daily_work_reports dwr +LEFT JOIN error_types et ON dwr.error_type_id = et.id +WHERE error_type_id IS NOT NULL +GROUP BY error_type_id +ORDER BY error_type_id; + + +-- STEP 2: 매핑 업데이트 (실제 item_id 확인 후 수정 필요!) +-- ============================================ + +-- 먼저 위 쿼리로 실제 item_id 값을 확인하세요! +-- 아래는 예시입니다. 실제 값으로 수정해서 사용하세요. + +-- 예시: 설계미스(error_type_id=1) → 설계미스 카테고리의 '도면 치수 오류' 항목 +-- UPDATE daily_work_reports SET error_type_id = 6 WHERE error_type_id = 1; + +-- 예시: 외주작업 불량(error_type_id=2) → 입고불량 카테고리의 '외관 불량' 항목 +-- UPDATE daily_work_reports SET error_type_id = 10 WHERE error_type_id = 2; + +-- 예시: 입고지연(error_type_id=3) → 자재누락 카테고리의 '배관 자재 미입고' 항목 +-- UPDATE daily_work_reports SET error_type_id = 1 WHERE error_type_id = 3; + + +-- STEP 3: 매핑 검증 +-- ============================================ + +-- 업데이트 후 확인 +SELECT + dwr.error_type_id, + iri.item_name, + irc.category_name, + COUNT(*) as cnt +FROM daily_work_reports dwr +LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id +LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id +WHERE dwr.error_type_id IS NOT NULL +GROUP BY dwr.error_type_id, iri.item_name, irc.category_name; + + +-- STEP 4: error_types 테이블 삭제 (매핑 완료 후) +-- ============================================ + +-- 주의: 반드시 STEP 2, 3 완료 후 실행! +-- DROP TABLE IF EXISTS error_types; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/add_equipment_purchase_fields.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/add_equipment_purchase_fields.sql new file mode 100644 index 0000000..3714211 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/add_equipment_purchase_fields.sql @@ -0,0 +1,13 @@ +-- 설비 테이블에 구입처 및 구입가격 컬럼 추가 +-- 실행: mysql -u [user] -p [database] < add_equipment_purchase_fields.sql + +-- 컬럼 추가 +ALTER TABLE equipments +ADD COLUMN supplier VARCHAR(100) NULL COMMENT '구입처' AFTER manufacturer, +ADD COLUMN purchase_price DECIMAL(15, 0) NULL COMMENT '구입가격' AFTER supplier; + +-- 확인 +SELECT COLUMN_NAME, DATA_TYPE, IS_NULLABLE, COLUMN_COMMENT +FROM INFORMATION_SCHEMA.COLUMNS +WHERE TABLE_NAME = 'equipments' +AND COLUMN_NAME IN ('supplier', 'purchase_price'); diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/insert_equipment_data.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/insert_equipment_data.sql new file mode 100644 index 0000000..a66a252 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/insert_equipment_data.sql @@ -0,0 +1,77 @@ +-- 설비 데이터 입력 +-- 실행 전 먼저 add_equipment_purchase_fields.sql 실행 필요 +-- 실행: mysql -u [user] -p [database] < insert_equipment_data.sql + +-- 기존 데이터 삭제 (필요시 주석 해제) +-- TRUNCATE TABLE equipments; + +INSERT INTO equipments (equipment_code, equipment_name, model_name, specifications, serial_number, installation_date, supplier, purchase_price, manufacturer, status) VALUES +('TKP-001', 'AIR COMPRESSOR', 'AR10E', '7.5KW(10HP)', 'K603023Y', '2016-06-01', '지티씨', NULL, '경원', 'active'), +('TKP-002', 'TURN TABLE', 'YCT-200T', '220V', NULL, '2016-05-30', '형진종합공구', 3600000, '유체기계', 'active'), +('TKP-003', 'BAND SAW(中)', 'CY300W', '1500W*380V', '20150943', '2016-05-30', '형진종합공구', 4800000, '유림싸이겐', 'active'), +('TKP-004', 'BAND SAW(小)', 'XB-180WA', '180(VICE)', NULL, '2016-05-30', '형진종합공구', 2700000, '렉스', 'active'), +('TKP-005', 'BAND SAW(小)', 'XB-180WA', '180(VICE)', NULL, '2019-05-30', NULL, NULL, '렉스', 'active'), +('TKP-006', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-001', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-007', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-002', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-008', 'TIG용접기', 'DAESUNG-500DT', '500A', 'TEAG0168-003', '2016-05-30', '형진종합공구', 2200000, '대성용접기', 'active'), +('TKP-009', 'CO2용접기', 'COD-500A', '500A', '10880', '2016-05-30', '형진종합공구', 2000000, '대성용접기', 'active'), +('TKP-010', 'O2용접기', 'GSORK', '220V', NULL, '2016-05-30', '형진종합공구', 620000, '재현오토닉스', 'active'), +('TKP-011', 'PIPE BEVELLING MACHINE', 'S-200LT_MT(테이블포함)', '2" ~ 8"', 'KR-17030007', '2017-03-29', 'DCS ENG', 12000000, 'DCS ENG', 'active'), +('TKP-012', 'CO2용접기', '500MX', '220/380V,500A', NULL, '2017-08-02', '현대용접기', 1800000, '현대용접기', 'active'), +('TKP-013', '프라즈마', 'Perfect-150AP', '220/380/440V,140A', NULL, '2017-08-02', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-014', '터닝로라', 'JK-5-TR', '5TON/380V', NULL, '2017-09-08', '정일기공', 5700000, '정일기공', 'active'), +('TKP-015', '터닝로라', 'JK-5-TR', '5TON/380V', NULL, '2017-09-08', '정일기공', 5700000, '정일기공', 'active'), +('TKP-016', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-005', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-017', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-006', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-018', 'TIG용접기', 'Perfect-500PT', '500A/350A', 'TJAD017B-007', '2017-10-18', '현대용접기', 1600000, '퍼펙트대대', 'active'), +('TKP-019', '전해연마기', 'ONB-8000VP', '220V/MAX1200W', '8022701', '2018-03-13', '오토기전', 1450000, '메탈브라이트(오토기전)', 'active'), +('TKP-020', '지게차', '50DA-9F', '5000KGS', 'HHKHFV36JJ0000061', '2018-05-10', '현대지게차', 45000000, '현대지게차', 'active'), +('TKP-021', '조방', NULL, '3658*12190', NULL, '2018-05-11', '천우기계공업/삼덕금속', 14200000, '테크니컬코리아', 'active'), +('TKP-022', 'BAND SAW(大)', 'WBS-RC500AN', '3,300kgs / 7.88kw', 'BC50A18-005F001', '2018-05-31', '원공사', 36000000, '원공사', 'active'), +('TKP-023', 'AIR COMPRESSOR', 'AR20E', '0.95Mpa', 'AR020FE358', '2018-06-05', '경원기계', NULL, '경원기계', 'active'), +('TKP-024', 'TURN TABLE', 'YCT-200TA', '220V', NULL, '2018-06-12', '청운종합공구', 3245000, '유체기계', 'active'), +('TKP-025', 'TIG용접기', 'Perfect-500WT', '500A/AC DC', 'ADKAC017B-006', '2018-06-12', '현대용접기', 2400000, '퍼펙트대대', 'active'), +('TKP-026', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAI018B-002', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-027', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAA018B-009', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-028', 'TIG용접기', 'Perfect-500PT', '500A/DC', 'TAAA018B-001', '2018-06-12', '현대용접기', 1900000, '퍼펙트대대', 'active'), +('TKP-029', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1806077', '2018-07-06', '청운종합공구', 2300000, '대산', 'active'), +('TKP-030', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1807028', '2018-07-10', '청운종합공구', 2300000, '대산', 'active'), +('TKP-031', 'ELECTRIC CHAIN HOIST', 'DSM-2S', '3Ph-60Hz-380V', 'K1807029', '2018-07-10', '청운종합공구', 2300000, '대산', 'active'), +('TKP-032', '만능탭 드릴링머신', 'SF-TDM32', '1.5KW', NULL, '2018-11-09', '㈜애스앤애프', 2927000, '㈜애스앤에프', 'active'), +('TKP-033', '지게차', '30D-9B', '2850KGS', 'HHKHHN51KK0000864', '2019-03-06', '현대지게차', 29400000, '현대지게차', 'active'), +('TKP-034', '갠츄리크레인', 'CRANE - DHG', '50/10Ton x SP20M x T/L50M x H15M', NULL, '2019-05-09', '유진산업기계', 249000000, '반도호이스트', 'active'), +('TKP-035', 'OVER HEAD CRANE', 'CRANE - DHO', '20Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 58000000, '반도호이스트', 'active'), +('TKP-036', 'OVER HEAD CRANE', 'CRANE - DHO', '20Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 58000000, '반도호이스트', 'active'), +('TKP-037', 'OVER HEAD CRANE', 'CRANE - DHO', '5Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 29000000, '반도호이스트', 'active'), +('TKP-038', 'OVER HEAD CRANE', 'CRANE - DHO', '5Ton x SP24.0M x T/L67M x H11M', NULL, '2019-05-09', '유진산업기계', 29000000, '반도호이스트', 'active'), +('TKP-039', '고소작업대', NULL, '250 Kg', NULL, '2019-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-040', '고소작업대', NULL, '250 Kg', NULL, '2019-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-041', 'AIR CONDITIONER', '코끼리 냉장고', NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-042', 'AIR CONDITIONER', NULL, NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-043', 'AIR CONDITIONER', NULL, NULL, NULL, '2019-01-01', NULL, NULL, '㈜에스엔에프', 'active'), +('TKP-044', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-045', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-046', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-047', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-048', '용접흄집진기', NULL, '5 HP / 60 m3/Min', NULL, '2019-01-01', NULL, NULL, NULL, 'active'), +('TKP-049', '자동용접기', NULL, NULL, NULL, '2019-01-01', 'Swage-Lok', 50000000, 'Swage-Lok', 'active'), +('TKP-050', 'Magnetic Drill', NULL, NULL, NULL, '2020-01-01', '청운종합공구', NULL, 'NITTO', 'active'), +('TKP-051', 'Magnetic Drill', NULL, NULL, NULL, '2020-01-01', '청운종합공구', NULL, 'Key-Yang', 'active'), +('TKP-052', 'Tube Bending M/C', NULL, NULL, NULL, '2020-01-01', NULL, NULL, 'REMS', 'active'), +('TKP-053', 'Unit Test Panel', NULL, NULL, NULL, '2021-01-01', NULL, NULL, NULL, 'active'), +('TKP-054', '고소작업대', NULL, '500 Kg', NULL, '2021-01-01', NULL, NULL, '㈜쓰리제이테크', 'active'), +('TKP-055', '용접봉 건조기', '주문제작', '박스형', NULL, '2022-05-04', '진원하이텍', 2300000, '진원하이텍', 'active'), +('TKP-056', 'C&T 가공기', 'MS-CTK469', NULL, NULL, '2022-07-20', 'Swage-Lok', 7347600, 'Swage-Lok', 'active'), +('TKP-057', '테이블형 튜브 벤딩기', 'MS-BTT-K', '1/2", 1/4"', NULL, '2022-06-03', 'Swage-Lok', 20000000, 'Swage-Lok', 'active'), +('TKP-058', '자동용접기 헤드', 'SWS-10H-D-15', '1/2"', NULL, '2022-06-03', 'Swage-Lok', 20000000, 'Swage-Lok', 'active'), +('TKP-059', '천장주행크레인', 'HC-75D-13105', '7.5ton', NULL, '2023-06-09', '에이치앤씨', 22800000, '에이치앤씨', 'active'), +('TKP-060', 'AED', 'CU-SP1 Plus', '저출력심장충격기', NULL, '2023-11-09', '제이메디', 1600000, '제이메디', 'active'), +('TKP-061', '베벨머신', 'S-150', 'O.D 20mm ~ 170mm', NULL, '2023-12-12', 'DCSENG', 16000000, 'DCSENG', 'active'), +('TKP-062', '피막제거기', 'CM4_OD_GC', '최대 폭 48mm, 최대 깊이 15mm, 6"이상', NULL, '2023-12-12', 'DCSENG', 2000000, 'DCSENG', 'active'), +('TKP-063', '피막제거기', 'S-CM4_OD', '최대 폭 48mm, 최대 깊이 15mm, 1" 이상', NULL, '2023-12-12', 'DCSENG', 1200000, 'DCSENG', 'active'), +('TKP-064', '텅스텐 가공기', 'S-TGR', '0.89kg, 0.25~3.2', NULL, '2023-12-12', 'DCSENG', 800000, 'DCSENG', 'active'), +('TKP-065', '전동대차', 'LPM15', '2.0 ton', NULL, '2023-12-20', '두산산업차량', 2800000, '두산산업차량', 'active'); + +-- 입력 확인 +SELECT COUNT(*) AS total_count FROM equipments; +SELECT equipment_code, equipment_name, supplier, purchase_price, manufacturer FROM equipments ORDER BY equipment_code LIMIT 10; diff --git a/deploy/tkfb-package/api.hyungi.net/db/migrations/sync_production_attendance.sql b/deploy/tkfb-package/api.hyungi.net/db/migrations/sync_production_attendance.sql new file mode 100644 index 0000000..2740b71 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db/migrations/sync_production_attendance.sql @@ -0,0 +1,34 @@ +-- ===================================================== +-- daily_attendance_records 테이블 운영 DB 동기화 +-- 실행 전 백업 권장 +-- ===================================================== + +-- 1. is_present 컬럼 추가 (출근 체크용) +ALTER TABLE `daily_attendance_records` +ADD COLUMN IF NOT EXISTS `is_present` TINYINT(1) DEFAULT 1 COMMENT '출근 여부' AFTER `is_overtime_approved`; + +-- 기존 데이터는 모두 출근으로 설정 +UPDATE `daily_attendance_records` SET `is_present` = 1 WHERE `is_present` IS NULL; + +-- 2. created_by 컬럼 추가 (등록자) +ALTER TABLE `daily_attendance_records` +ADD COLUMN IF NOT EXISTS `created_by` INT NULL COMMENT '등록자 user_id' AFTER `is_present`; + +-- 기존 데이터는 시스템(1)으로 설정 +UPDATE `daily_attendance_records` SET `created_by` = 1 WHERE `created_by` IS NULL; + +-- 3. check_in_time, check_out_time 컬럼 추가 (선택사항) +ALTER TABLE `daily_attendance_records` +ADD COLUMN IF NOT EXISTS `check_in_time` TIME NULL COMMENT '출근 시간' AFTER `vacation_type_id`; + +ALTER TABLE `daily_attendance_records` +ADD COLUMN IF NOT EXISTS `check_out_time` TIME NULL COMMENT '퇴근 시간' AFTER `check_in_time`; + +-- 4. notes 컬럼 추가 +ALTER TABLE `daily_attendance_records` +ADD COLUMN IF NOT EXISTS `notes` TEXT NULL COMMENT '비고' AFTER `is_overtime_approved`; + +-- ===================================================== +-- 확인용 쿼리 +-- ===================================================== +-- DESCRIBE `daily_attendance_records`; diff --git a/deploy/tkfb-package/api.hyungi.net/dbPool.js b/deploy/tkfb-package/api.hyungi.net/dbPool.js new file mode 100644 index 0000000..79976ee --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/dbPool.js @@ -0,0 +1,11 @@ +/** + * 데이터베이스 풀 (호환성 레거시 파일) + * + * @deprecated 이 파일은 하위 호환성을 위해 유지됩니다. + * 새로운 코드에서는 './config/database'를 직접 import하세요. + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +module.exports = require('./config/database'); diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/daily_work_reports_backup_20250902_081944.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/daily_work_reports_backup_20250902_081944.sql new file mode 100644 index 0000000..b268d63 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/daily_work_reports_backup_20250902_081944.sql @@ -0,0 +1,774 @@ +-- MariaDB dump 10.19 Distrib 10.9.8-MariaDB, for debian-linux-gnu (aarch64) +-- +-- Host: localhost Database: hyungi_dev +-- ------------------------------------------------------ +-- Server version 10.9.8-MariaDB-1:10.9.8+maria~ubu2204 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Table structure for table `daily_work_reports` +-- + +DROP TABLE IF EXISTS `daily_work_reports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_work_reports` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `report_date` date NOT NULL COMMENT '작업 날짜', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `project_id` int(11) NOT NULL COMMENT '프로젝트 ID', + `work_type_id` int(11) NOT NULL COMMENT '작업 유형 ID', + `work_status_id` int(11) DEFAULT 1 COMMENT '업무 상태 ID (1:정규, 2:에러)', + `error_type_id` int(11) DEFAULT NULL COMMENT '에러 유형 ID (에러일 때만)', + `work_hours` decimal(4,2) NOT NULL COMMENT '작업 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `created_by` int(11) NOT NULL DEFAULT 1 COMMENT '작성자 user_id', + `updated_by` int(11) DEFAULT NULL COMMENT '수정자 user_id', + PRIMARY KEY (`id`), + KEY `idx_report_date` (`report_date`), + KEY `idx_worker_date` (`worker_id`,`report_date`), + KEY `idx_project_date` (`project_id`,`report_date`), + KEY `idx_work_type` (`work_type_id`), + KEY `idx_work_status` (`work_status_id`), + KEY `idx_error_type` (`error_type_id`), + KEY `idx_created_by` (`created_by`), + KEY `idx_date_worker_creator` (`report_date`,`worker_id`,`created_by`) +) ENGINE=InnoDB AUTO_INCREMENT=741 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_work_reports` +-- + +LOCK TABLES `daily_work_reports` WRITE; +/*!40000 ALTER TABLE `daily_work_reports` DISABLE KEYS */; +INSERT INTO `daily_work_reports` VALUES +(14,'2025-06-02',1,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL), +(15,'2025-06-02',3,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL), +(16,'2025-06-02',4,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL), +(17,'2025-06-02',6,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL), +(18,'2025-06-02',7,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL), +(19,'2025-06-02',9,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL), +(20,'2025-06-02',2,3,2,1,NULL,8.00,'2025-06-16 05:10:47','2025-06-16 05:10:47',1,NULL), +(21,'2025-06-04',1,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL), +(22,'2025-06-04',3,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL), +(23,'2025-06-04',5,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL), +(24,'2025-06-04',7,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL), +(25,'2025-06-04',9,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL), +(26,'2025-06-04',10,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL), +(27,'2025-06-04',2,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL), +(28,'2025-06-04',6,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL), +(29,'2025-06-04',8,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL), +(30,'2025-06-05',1,4,3,2,1,8.00,'2025-06-16 05:12:57','2025-06-16 05:12:57',1,NULL), +(31,'2025-06-05',3,4,3,2,1,8.00,'2025-06-16 05:12:57','2025-06-16 05:12:57',1,NULL), +(32,'2025-06-05',4,4,3,2,1,8.00,'2025-06-16 05:12:57','2025-06-16 05:12:57',1,NULL), +(33,'2025-06-05',7,4,3,2,1,8.00,'2025-06-16 05:12:57','2025-06-16 05:12:57',1,NULL), +(34,'2025-06-05',10,4,3,2,1,8.00,'2025-06-16 05:12:57','2025-06-16 05:12:57',1,NULL), +(35,'2025-06-05',9,4,3,2,1,8.00,'2025-06-16 05:12:57','2025-06-16 05:12:57',1,NULL), +(36,'2025-06-05',2,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL), +(37,'2025-06-05',5,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL), +(38,'2025-06-05',6,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL), +(39,'2025-06-05',8,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL), +(40,'2025-06-16',5,3,2,1,NULL,8.00,'2025-06-16 06:12:01','2025-06-16 06:12:01',5,NULL), +(43,'2025-06-16',2,3,2,1,NULL,8.00,'2025-06-16 06:12:01','2025-06-16 06:12:01',5,NULL), +(44,'2025-06-16',6,3,2,2,4,4.00,'2025-06-16 06:13:02','2025-06-16 06:13:02',5,NULL), +(45,'2025-06-16',6,3,2,1,NULL,4.00,'2025-06-16 06:13:50','2025-06-16 06:13:50',5,NULL), +(46,'2025-06-16',8,3,2,2,4,4.00,'2025-06-16 06:15:22','2025-06-16 06:15:22',5,NULL), +(47,'2025-06-16',8,3,2,1,NULL,4.00,'2025-06-16 06:15:22','2025-06-16 06:15:22',5,NULL), +(48,'2025-06-16',4,4,3,2,1,8.00,'2025-06-16 06:46:44','2025-06-16 06:46:44',3,NULL), +(50,'2025-06-16',1,4,3,2,1,8.00,'2025-06-16 06:46:44','2025-06-16 06:46:44',3,NULL), +(51,'2025-06-16',9,4,3,1,NULL,8.00,'2025-06-16 06:48:29','2025-06-16 06:48:29',3,NULL), +(52,'2025-06-16',10,4,3,1,NULL,6.00,'2025-06-16 06:50:09','2025-06-16 06:50:09',6,NULL), +(53,'2025-06-16',10,4,3,2,1,2.00,'2025-06-16 06:50:09','2025-06-16 06:50:09',6,NULL), +(54,'2025-06-16',3,4,3,1,NULL,6.00,'2025-06-16 06:50:09','2025-06-16 06:50:09',6,NULL), +(55,'2025-06-16',3,4,3,2,1,2.00,'2025-06-16 06:50:09','2025-06-16 06:50:09',6,NULL), +(56,'2025-06-17',2,3,2,1,NULL,8.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL), +(57,'2025-06-17',2,3,2,1,NULL,2.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL), +(58,'2025-06-17',5,3,2,1,NULL,8.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL), +(59,'2025-06-17',5,3,2,1,NULL,2.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL), +(60,'2025-06-17',6,3,2,1,NULL,8.00,'2025-06-17 08:24:33','2025-06-17 08:24:33',5,NULL), +(61,'2025-06-17',6,3,2,2,4,2.00,'2025-06-17 08:24:33','2025-06-17 08:24:33',5,NULL), +(62,'2025-06-17',8,3,2,1,NULL,8.00,'2025-06-17 08:24:33','2025-06-17 08:24:33',5,NULL), +(63,'2025-06-17',8,3,2,2,4,2.00,'2025-06-17 08:24:33','2025-06-17 08:24:33',5,NULL), +(65,'2025-06-17',9,4,3,2,1,4.00,'2025-06-17 08:25:24','2025-06-17 08:25:24',3,NULL), +(66,'2025-06-17',1,4,3,2,1,4.00,'2025-06-17 08:27:06','2025-06-17 08:27:06',3,NULL), +(67,'2025-06-17',4,4,3,2,1,4.00,'2025-06-17 08:27:06','2025-06-17 08:27:06',3,NULL), +(68,'2025-06-17',1,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL), +(69,'2025-06-17',9,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL), +(70,'2025-06-17',4,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL), +(71,'2025-06-17',9,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL), +(72,'2025-06-17',4,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL), +(73,'2025-06-17',1,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL), +(74,'2025-06-17',10,4,3,1,NULL,8.00,'2025-06-17 08:34:11','2025-06-17 08:34:11',6,NULL), +(75,'2025-06-17',10,4,3,2,1,2.00,'2025-06-17 08:34:11','2025-06-17 08:34:11',6,NULL), +(76,'2025-06-17',3,4,3,1,NULL,8.00,'2025-06-17 08:34:11','2025-06-17 08:34:11',6,NULL), +(77,'2025-06-17',3,4,3,2,1,2.00,'2025-06-17 08:34:11','2025-06-17 08:34:11',6,NULL), +(78,'2025-06-18',6,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL), +(79,'2025-06-18',2,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL), +(80,'2025-06-18',8,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL), +(81,'2025-06-18',2,3,2,1,NULL,2.00,'2025-06-18 08:41:02','2025-06-18 08:41:02',5,NULL), +(82,'2025-06-18',6,3,2,1,NULL,2.00,'2025-06-18 08:41:03','2025-06-18 08:41:03',5,NULL), +(83,'2025-06-18',8,3,2,1,NULL,2.00,'2025-06-18 08:41:03','2025-06-18 08:41:03',5,NULL), +(84,'2025-06-18',5,4,3,1,NULL,8.00,'2025-06-18 08:41:45','2025-06-18 08:41:45',5,NULL), +(85,'2025-06-18',5,4,3,1,NULL,2.00,'2025-06-18 08:41:45','2025-06-18 08:41:45',5,NULL), +(86,'2025-06-18',10,4,3,1,NULL,9.00,'2025-06-18 08:47:55','2025-06-18 08:47:55',6,NULL), +(87,'2025-06-18',10,4,3,2,1,1.00,'2025-06-18 08:47:55','2025-06-18 08:47:55',6,NULL), +(88,'2025-06-18',3,4,3,1,NULL,9.00,'2025-06-18 08:47:55','2025-06-18 08:47:55',6,NULL), +(89,'2025-06-18',3,4,3,2,1,1.00,'2025-06-18 08:47:55','2025-06-18 08:47:55',6,NULL), +(90,'2025-06-18',4,4,3,2,1,4.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL), +(91,'2025-06-18',4,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL), +(92,'2025-06-18',9,4,3,2,1,4.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL), +(93,'2025-06-18',9,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL), +(94,'2025-06-18',1,4,3,2,1,4.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL), +(95,'2025-06-18',1,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL), +(96,'2025-06-18',7,4,3,2,1,4.00,'2025-06-18 09:00:17','2025-06-18 09:00:17',3,NULL), +(97,'2025-06-18',7,4,3,1,NULL,6.00,'2025-06-18 09:00:17','2025-06-18 09:00:17',3,NULL), +(98,'2025-06-19',8,3,2,1,NULL,8.00,'2025-06-19 06:37:59','2025-06-19 06:37:59',5,NULL), +(99,'2025-06-19',2,3,2,1,NULL,8.00,'2025-06-19 06:37:59','2025-06-19 06:37:59',5,NULL), +(100,'2025-06-19',10,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL), +(101,'2025-06-19',3,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL), +(102,'2025-06-19',5,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL), +(103,'2025-06-19',9,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(104,'2025-06-19',9,4,3,2,1,2.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(105,'2025-06-19',4,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(106,'2025-06-19',4,4,3,2,1,2.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(107,'2025-06-19',1,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(108,'2025-06-19',1,4,3,2,1,2.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(109,'2025-06-19',7,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(110,'2025-06-19',7,4,3,2,1,2.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(111,'2025-06-19',6,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(112,'2025-06-19',6,4,3,2,1,2.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL), +(113,'2025-06-20',9,4,3,2,1,2.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL), +(114,'2025-06-20',9,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL), +(115,'2025-06-20',4,4,3,2,1,2.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL), +(116,'2025-06-20',4,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL), +(117,'2025-06-20',7,4,3,2,1,2.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL), +(118,'2025-06-20',7,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL), +(119,'2025-06-20',6,4,3,2,1,2.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL), +(120,'2025-06-20',6,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL), +(121,'2025-06-20',1,4,3,2,1,2.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL), +(122,'2025-06-20',1,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL), +(123,'2025-06-20',5,4,3,2,1,2.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL), +(124,'2025-06-20',5,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL), +(125,'2025-06-20',10,4,3,1,NULL,8.00,'2025-06-20 06:45:30','2025-06-20 06:45:30',6,NULL), +(126,'2025-06-20',3,4,3,1,NULL,8.00,'2025-06-20 06:45:31','2025-06-20 06:45:31',6,NULL), +(127,'2025-06-23',10,4,3,1,NULL,8.00,'2025-06-23 06:42:58','2025-06-23 06:42:58',6,NULL), +(128,'2025-06-23',3,4,3,1,NULL,8.00,'2025-06-23 06:42:58','2025-06-23 06:42:58',6,NULL), +(129,'2025-06-23',5,4,3,2,1,2.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(130,'2025-06-23',5,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(131,'2025-06-23',1,4,3,2,1,2.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(132,'2025-06-23',1,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(133,'2025-06-23',9,4,3,2,1,2.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(134,'2025-06-23',9,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(135,'2025-06-23',4,4,3,2,1,2.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(136,'2025-06-23',4,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(137,'2025-06-23',7,4,3,2,1,2.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(138,'2025-06-23',7,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(139,'2025-06-23',6,4,3,2,1,2.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(140,'2025-06-23',6,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL), +(141,'2025-06-24',10,4,3,1,NULL,12.00,'2025-06-24 11:10:32','2025-06-24 11:10:32',6,NULL), +(142,'2025-06-24',3,4,3,1,NULL,12.00,'2025-06-24 11:10:32','2025-06-24 11:10:32',6,NULL), +(143,'2025-06-24',9,4,3,2,1,2.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(144,'2025-06-24',9,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(145,'2025-06-24',5,4,3,2,1,2.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(146,'2025-06-24',5,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(147,'2025-06-24',4,4,3,2,1,2.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(148,'2025-06-24',4,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(149,'2025-06-24',7,4,3,2,1,2.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(150,'2025-06-24',7,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(151,'2025-06-24',6,4,3,2,1,2.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(152,'2025-06-24',6,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(153,'2025-06-24',1,4,3,2,1,2.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(154,'2025-06-24',1,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL), +(155,'2025-06-24',8,3,2,1,NULL,8.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL), +(156,'2025-06-24',8,3,2,1,NULL,4.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL), +(157,'2025-06-24',2,3,2,1,NULL,8.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL), +(158,'2025-06-24',2,3,2,1,NULL,4.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL), +(159,'2025-06-25',2,3,2,1,NULL,8.00,'2025-06-25 11:08:04','2025-06-25 11:08:04',5,NULL), +(160,'2025-06-25',2,3,2,1,NULL,4.00,'2025-06-25 11:08:04','2025-06-25 11:08:04',5,NULL), +(161,'2025-06-25',8,3,2,1,NULL,8.00,'2025-06-25 11:08:05','2025-06-25 11:08:05',5,NULL), +(162,'2025-06-25',8,3,2,1,NULL,4.00,'2025-06-25 11:08:05','2025-06-25 11:08:05',5,NULL), +(163,'2025-06-25',10,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL), +(164,'2025-06-25',9,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL), +(165,'2025-06-25',3,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL), +(166,'2025-06-25',6,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL), +(167,'2025-06-26',10,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL), +(168,'2025-06-26',5,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL), +(169,'2025-06-26',7,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL), +(170,'2025-06-26',1,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL), +(171,'2025-06-26',4,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL), +(172,'2025-06-26',8,3,2,1,NULL,8.00,'2025-06-26 11:11:31','2025-06-26 11:11:31',5,NULL), +(173,'2025-06-26',8,3,2,1,NULL,4.00,'2025-06-26 11:11:31','2025-06-26 11:11:31',5,NULL), +(174,'2025-06-26',2,3,2,1,NULL,8.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL), +(175,'2025-06-26',2,3,2,1,NULL,4.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL), +(176,'2025-06-26',9,3,2,1,NULL,8.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL), +(177,'2025-06-26',9,3,2,1,NULL,4.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL), +(178,'2025-06-26',3,3,2,1,NULL,12.00,'2025-06-26 11:19:34','2025-06-26 11:19:34',6,NULL), +(179,'2025-06-26',6,3,2,1,NULL,12.00,'2025-06-26 11:19:34','2025-06-26 11:19:34',6,NULL), +(182,'2025-06-27',2,3,2,1,NULL,4.00,'2025-06-27 01:54:40','2025-06-27 01:54:40',5,NULL), +(183,'2025-06-27',9,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL), +(184,'2025-06-27',10,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL), +(185,'2025-06-27',7,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL), +(186,'2025-06-27',5,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL), +(187,'2025-06-27',4,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL), +(188,'2025-06-27',1,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL), +(189,'2025-06-27',3,3,2,1,NULL,8.00,'2025-06-27 06:49:08','2025-06-27 06:49:08',6,NULL), +(191,'2025-06-27',6,3,2,1,NULL,4.00,'2025-06-27 06:58:46','2025-06-27 06:58:46',6,NULL), +(192,'2025-06-27',8,3,2,1,NULL,6.00,'2025-06-27 07:00:10','2025-06-27 07:00:10',5,NULL), +(193,'2025-06-30',6,3,2,2,4,2.00,'2025-07-05 01:37:29','2025-07-05 01:37:29',3,NULL), +(194,'2025-06-30',6,3,2,1,NULL,2.00,'2025-07-05 01:37:29','2025-07-07 04:15:25',3,3), +(195,'2025-06-30',2,3,2,1,NULL,4.00,'2025-07-05 01:38:19','2025-07-07 04:15:40',3,3), +(196,'2025-06-30',3,3,2,1,NULL,8.00,'2025-07-05 01:38:19','2025-07-05 01:38:19',3,NULL), +(197,'2025-06-30',8,3,2,1,NULL,6.00,'2025-07-05 01:38:19','2025-07-07 04:15:02',3,3), +(198,'2025-07-01',3,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL), +(199,'2025-07-01',2,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL), +(200,'2025-07-01',6,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL), +(201,'2025-07-01',8,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL), +(202,'2025-07-01',10,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL), +(203,'2025-07-01',9,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL), +(204,'2025-07-01',2,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:42:08',3,3), +(205,'2025-07-01',3,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:42:02',3,3), +(206,'2025-07-01',6,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:41:56',3,3), +(207,'2025-07-01',8,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:41:48',3,3), +(208,'2025-07-01',9,3,2,2,4,2.00,'2025-07-05 01:40:10','2025-07-05 01:40:10',3,NULL), +(209,'2025-07-01',10,3,2,2,4,2.00,'2025-07-05 01:40:10','2025-07-05 01:40:10',3,NULL), +(210,'2025-07-01',7,4,3,1,NULL,5.00,'2025-07-05 01:42:57','2025-07-05 01:42:57',3,NULL), +(211,'2025-07-01',7,4,3,2,2,3.00,'2025-07-05 01:42:57','2025-07-05 01:42:57',3,NULL), +(212,'2025-07-01',5,4,3,1,NULL,8.00,'2025-07-05 01:42:57','2025-07-07 04:21:24',3,3), +(213,'2025-07-01',5,4,3,2,2,4.00,'2025-07-05 01:42:57','2025-07-07 04:21:10',3,3), +(214,'2025-07-01',4,4,3,1,NULL,8.00,'2025-07-05 01:42:57','2025-07-07 04:21:41',3,3), +(215,'2025-07-01',4,4,3,2,2,4.00,'2025-07-05 01:42:57','2025-07-07 04:21:32',3,3), +(216,'2025-07-01',1,4,3,1,NULL,5.00,'2025-07-05 01:42:57','2025-07-05 01:42:57',3,NULL), +(217,'2025-07-01',1,4,3,2,2,3.00,'2025-07-05 01:42:57','2025-07-05 01:42:57',3,NULL), +(218,'2025-07-02',2,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL), +(219,'2025-07-02',3,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL), +(220,'2025-07-02',10,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL), +(221,'2025-07-02',9,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL), +(222,'2025-07-02',8,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL), +(223,'2025-07-02',6,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL), +(224,'2025-07-02',7,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL), +(225,'2025-07-02',5,4,3,2,2,4.00,'2025-07-05 01:44:11','2025-07-05 01:44:11',3,NULL), +(226,'2025-07-02',5,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:44:54',3,3), +(227,'2025-07-02',4,4,3,2,2,4.00,'2025-07-05 01:44:11','2025-07-05 01:44:11',3,NULL), +(228,'2025-07-02',4,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:44:59',3,3), +(229,'2025-07-02',1,4,3,2,2,4.00,'2025-07-05 01:44:11','2025-07-05 01:44:11',3,NULL), +(230,'2025-07-02',1,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:45:05',3,3), +(231,'2025-07-03',2,3,2,1,NULL,10.00,'2025-07-05 01:45:44','2025-07-05 01:45:44',3,NULL), +(232,'2025-07-03',6,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL), +(233,'2025-07-03',9,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL), +(234,'2025-07-03',8,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL), +(235,'2025-07-03',7,4,3,1,NULL,10.00,'2025-07-05 01:46:07','2025-07-05 01:46:07',3,NULL), +(236,'2025-07-03',1,4,3,1,NULL,10.00,'2025-07-05 01:46:07','2025-07-05 01:46:07',3,NULL), +(237,'2025-07-03',3,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL), +(238,'2025-07-03',4,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL), +(239,'2025-07-03',5,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL), +(240,'2025-07-03',10,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL), +(241,'2025-07-04',10,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(242,'2025-07-04',10,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(243,'2025-07-04',5,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(244,'2025-07-04',5,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(245,'2025-07-04',4,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(246,'2025-07-04',4,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(247,'2025-07-04',9,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(248,'2025-07-04',9,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(249,'2025-07-04',8,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(250,'2025-07-04',8,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(251,'2025-07-04',3,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(252,'2025-07-04',3,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(253,'2025-07-04',2,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(254,'2025-07-04',2,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(255,'2025-07-04',7,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(256,'2025-07-04',7,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(257,'2025-07-04',6,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(258,'2025-07-04',6,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(259,'2025-07-04',1,4,3,2,2,2.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(260,'2025-07-04',1,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL), +(261,'2025-07-05',8,4,2,1,NULL,8.00,'2025-07-05 05:36:38','2025-07-05 05:36:38',5,NULL), +(262,'2025-07-05',5,4,2,1,NULL,8.00,'2025-07-05 05:36:38','2025-07-05 05:36:38',5,NULL), +(263,'2025-07-05',4,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL), +(264,'2025-07-05',3,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL), +(265,'2025-07-05',2,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL), +(266,'2025-07-05',1,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL), +(267,'2025-07-06',10,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:08',5,3), +(268,'2025-07-06',9,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:16',5,3), +(269,'2025-07-06',7,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:22',5,3), +(270,'2025-07-06',6,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:27',5,3), +(271,'2025-07-06',4,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:33',5,3), +(272,'2025-07-06',3,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:39',5,3), +(273,'2025-07-06',2,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:44',5,3), +(274,'2025-07-06',1,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:49',5,3), +(275,'2025-07-07',10,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(276,'2025-07-07',9,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(277,'2025-07-07',8,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(278,'2025-07-07',7,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(279,'2025-07-07',3,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(280,'2025-07-07',4,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(281,'2025-07-07',5,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(282,'2025-07-07',6,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(283,'2025-07-07',2,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(284,'2025-07-07',1,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL), +(285,'2025-07-08',10,4,3,1,NULL,8.00,'2025-07-08 06:36:57','2025-07-08 06:36:57',3,NULL), +(286,'2025-07-08',9,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(287,'2025-07-08',8,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(288,'2025-07-08',7,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(289,'2025-07-08',6,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(290,'2025-07-08',1,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(291,'2025-07-08',2,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(292,'2025-07-08',3,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(293,'2025-07-08',5,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(294,'2025-07-08',4,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL), +(295,'2025-07-09',10,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL), +(296,'2025-07-09',9,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL), +(297,'2025-07-09',8,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL), +(298,'2025-07-09',7,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL), +(299,'2025-07-09',6,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL), +(300,'2025-07-09',2,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL), +(301,'2025-07-09',3,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL), +(302,'2025-07-09',4,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL), +(303,'2025-07-09',5,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL), +(304,'2025-07-09',1,4,3,1,NULL,4.00,'2025-07-09 22:09:10','2025-07-09 22:09:10',5,NULL), +(305,'2025-07-10',9,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL), +(306,'2025-07-10',8,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL), +(307,'2025-07-10',5,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL), +(308,'2025-07-10',6,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL), +(309,'2025-07-10',2,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL), +(310,'2025-07-10',3,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL), +(311,'2025-07-10',4,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL), +(312,'2025-07-10',1,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL), +(313,'2025-07-10',7,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL), +(314,'2025-07-10',10,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL), +(315,'2025-07-12',9,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL), +(316,'2025-07-12',8,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL), +(317,'2025-07-12',6,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL), +(318,'2025-07-12',5,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL), +(319,'2025-07-12',4,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL), +(320,'2025-07-12',2,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL), +(321,'2025-07-12',1,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL), +(322,'2025-07-14',8,4,3,1,NULL,6.00,'2025-07-14 06:46:30','2025-07-14 06:46:30',3,NULL), +(323,'2025-07-14',10,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL), +(324,'2025-07-14',9,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL), +(325,'2025-07-14',7,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL), +(326,'2025-07-14',6,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL), +(327,'2025-07-14',1,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL), +(328,'2025-07-14',2,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL), +(329,'2025-07-14',3,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL), +(330,'2025-07-14',4,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL), +(331,'2025-07-15',3,3,2,1,NULL,8.00,'2025-07-15 05:57:06','2025-07-15 05:57:06',5,NULL), +(332,'2025-07-15',9,3,2,1,NULL,8.00,'2025-07-15 05:57:06','2025-07-15 05:57:06',5,NULL), +(333,'2025-07-15',5,3,2,2,4,4.00,'2025-07-15 05:57:47','2025-07-15 05:57:47',5,NULL), +(334,'2025-07-15',5,4,3,1,NULL,4.00,'2025-07-15 05:57:47','2025-07-15 05:57:47',5,NULL), +(335,'2025-07-15',10,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL), +(336,'2025-07-15',8,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL), +(337,'2025-07-15',7,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL), +(338,'2025-07-15',6,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL), +(339,'2025-07-15',2,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL), +(340,'2025-07-15',1,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL), +(341,'2025-07-14',5,4,3,1,NULL,8.00,'2025-07-15 06:57:26','2025-07-15 06:57:26',3,NULL), +(342,'2025-07-16',4,4,3,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL), +(343,'2025-07-16',4,3,2,1,NULL,4.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL), +(344,'2025-07-16',4,3,2,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL), +(345,'2025-07-16',5,4,3,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL), +(346,'2025-07-16',5,3,2,1,NULL,4.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL), +(347,'2025-07-16',5,3,2,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL), +(348,'2025-07-16',10,4,3,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL), +(349,'2025-07-16',10,3,2,1,NULL,4.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL), +(350,'2025-07-16',10,3,2,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL), +(351,'2025-07-16',6,4,3,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL), +(352,'2025-07-16',6,3,2,1,NULL,4.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL), +(353,'2025-07-16',6,3,2,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL), +(354,'2025-07-16',9,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL), +(355,'2025-07-16',8,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL), +(356,'2025-07-16',3,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL), +(357,'2025-07-16',2,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL), +(358,'2025-07-16',1,4,3,1,NULL,8.00,'2025-07-16 06:51:31','2025-07-16 06:51:31',3,NULL), +(359,'2025-07-16',7,4,3,1,NULL,8.00,'2025-07-16 06:51:31','2025-07-16 06:51:31',3,NULL), +(360,'2025-07-17',1,3,3,1,NULL,8.00,'2025-07-17 06:45:22','2025-07-17 06:45:22',3,NULL), +(361,'2025-07-17',5,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL), +(362,'2025-07-17',5,3,2,2,4,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL), +(363,'2025-07-17',4,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL), +(364,'2025-07-17',4,3,2,2,4,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL), +(365,'2025-07-17',2,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL), +(366,'2025-07-17',2,3,2,2,4,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL), +(367,'2025-07-17',10,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL), +(368,'2025-07-17',9,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL), +(369,'2025-07-17',8,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL), +(370,'2025-07-17',7,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL), +(371,'2025-07-17',6,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL), +(372,'2025-07-17',3,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL), +(373,'2025-07-18',7,4,3,2,1,2.00,'2025-07-18 05:54:47','2025-07-18 05:54:47',3,NULL), +(374,'2025-07-18',1,4,3,2,1,2.00,'2025-07-18 05:54:48','2025-07-18 05:54:48',3,NULL), +(376,'2025-07-18',5,4,3,1,NULL,2.00,'2025-07-18 05:58:33','2025-07-18 05:58:33',3,NULL), +(377,'2025-07-18',5,3,2,1,NULL,6.00,'2025-07-18 05:58:33','2025-07-18 05:58:33',3,NULL), +(378,'2025-07-18',7,3,2,1,NULL,6.00,'2025-07-18 05:59:42','2025-07-18 05:59:42',3,NULL), +(379,'2025-07-18',1,3,3,1,NULL,6.00,'2025-07-18 06:00:15','2025-07-18 06:00:15',3,NULL), +(380,'2025-07-18',10,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL), +(381,'2025-07-18',9,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL), +(382,'2025-07-18',8,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL), +(383,'2025-07-18',6,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL), +(384,'2025-07-18',4,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL), +(385,'2025-07-18',3,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL), +(386,'2025-07-18',2,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL), +(387,'2025-07-21',5,4,3,2,1,4.00,'2025-07-21 06:40:08','2025-07-21 06:40:08',5,NULL), +(388,'2025-07-21',5,3,2,1,NULL,4.00,'2025-07-21 06:40:08','2025-07-21 06:40:08',5,NULL), +(389,'2025-07-21',4,4,3,2,1,4.00,'2025-07-21 06:40:08','2025-07-21 06:40:08',5,NULL), +(390,'2025-07-21',4,3,2,1,NULL,4.00,'2025-07-21 06:40:08','2025-07-21 06:40:08',5,NULL), +(391,'2025-07-21',10,3,2,1,NULL,6.00,'2025-07-21 06:40:32','2025-07-22 06:58:42',5,3), +(392,'2025-07-21',9,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL), +(393,'2025-07-21',8,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL), +(394,'2025-07-21',7,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL), +(395,'2025-07-21',6,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL), +(396,'2025-07-21',3,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL), +(397,'2025-07-21',2,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL), +(398,'2025-07-21',1,3,3,1,NULL,8.00,'2025-07-21 06:53:37','2025-07-21 06:53:37',3,NULL), +(399,'2025-07-22',10,3,2,1,NULL,8.00,'2025-07-22 06:45:47','2025-07-22 06:45:47',5,NULL), +(400,'2025-07-22',9,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL), +(401,'2025-07-22',8,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL), +(402,'2025-07-22',7,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL), +(403,'2025-07-22',6,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL), +(404,'2025-07-22',4,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL), +(405,'2025-07-22',3,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL), +(406,'2025-07-22',2,4,3,2,1,8.00,'2025-07-22 06:46:11','2025-07-22 06:46:11',5,NULL), +(407,'2025-07-22',5,3,3,1,NULL,8.00,'2025-07-22 06:46:11','2025-07-22 06:46:11',3,NULL), +(408,'2025-07-22',1,3,3,1,NULL,8.00,'2025-07-22 06:46:11','2025-07-22 06:46:11',3,NULL), +(409,'2025-07-23',4,3,3,1,NULL,8.00,'2025-07-23 06:45:06','2025-07-23 06:45:06',5,NULL), +(410,'2025-07-23',5,3,3,1,NULL,8.00,'2025-07-23 06:45:28','2025-07-23 06:45:28',3,NULL), +(411,'2025-07-23',1,3,3,1,NULL,8.00,'2025-07-23 06:45:28','2025-07-23 06:45:28',3,NULL), +(412,'2025-07-23',10,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL), +(413,'2025-07-23',9,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL), +(414,'2025-07-23',7,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL), +(415,'2025-07-23',6,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL), +(416,'2025-07-23',3,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL), +(417,'2025-07-23',2,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL), +(418,'2025-07-24',4,3,3,1,NULL,8.00,'2025-07-24 06:36:55','2025-07-24 06:36:55',5,NULL), +(419,'2025-07-24',10,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL), +(420,'2025-07-24',9,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL), +(421,'2025-07-24',7,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL), +(422,'2025-07-24',6,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL), +(423,'2025-07-24',3,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL), +(424,'2025-07-24',2,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL), +(425,'2025-07-24',5,3,3,1,NULL,8.00,'2025-07-24 06:47:04','2025-07-24 06:47:04',3,NULL), +(426,'2025-07-24',1,3,3,1,NULL,8.00,'2025-07-24 06:47:04','2025-07-24 06:47:04',3,NULL), +(427,'2025-07-25',4,3,3,1,NULL,8.00,'2025-07-25 06:44:23','2025-07-25 06:44:23',5,NULL), +(428,'2025-07-25',10,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL), +(429,'2025-07-25',9,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL), +(430,'2025-07-25',8,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL), +(431,'2025-07-25',6,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL), +(432,'2025-07-25',3,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL), +(433,'2025-07-25',2,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL), +(434,'2025-07-25',5,4,3,1,NULL,8.00,'2025-07-25 06:45:18','2025-07-25 06:45:18',3,NULL), +(435,'2025-07-25',7,4,3,1,NULL,8.00,'2025-07-25 06:45:19','2025-07-25 06:45:19',3,NULL), +(436,'2025-07-25',1,4,3,1,NULL,8.00,'2025-07-25 06:45:19','2025-07-25 06:45:19',3,NULL), +(437,'2025-07-28',5,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL), +(438,'2025-07-28',4,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL), +(439,'2025-07-28',1,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL), +(440,'2025-07-28',2,5,2,1,NULL,4.00,'2025-07-28 06:33:08','2025-07-28 06:33:08',5,NULL), +(441,'2025-07-28',2,3,2,1,NULL,4.00,'2025-07-28 06:33:08','2025-07-28 06:33:08',5,NULL), +(442,'2025-07-28',10,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL), +(443,'2025-07-28',9,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL), +(444,'2025-07-28',8,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL), +(445,'2025-07-28',7,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL), +(446,'2025-07-28',6,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL), +(447,'2025-07-28',3,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL), +(448,'2025-07-29',5,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL), +(449,'2025-07-29',4,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL), +(450,'2025-07-29',1,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL), +(451,'2025-07-30',5,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL), +(452,'2025-07-30',4,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL), +(453,'2025-07-30',1,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL), +(454,'2025-07-30',10,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL), +(455,'2025-07-30',9,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL), +(456,'2025-07-30',8,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL), +(457,'2025-07-30',7,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL), +(458,'2025-07-30',6,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL), +(459,'2025-07-30',3,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL), +(460,'2025-07-30',2,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL), +(461,'2025-07-31',1,3,3,1,NULL,4.00,'2025-07-31 06:42:56','2025-07-31 06:42:56',5,NULL), +(462,'2025-07-31',4,3,3,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL), +(463,'2025-07-31',4,3,2,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL), +(464,'2025-07-31',5,3,3,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL), +(465,'2025-07-31',5,3,2,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL), +(466,'2025-07-31',10,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL), +(467,'2025-07-31',9,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL), +(468,'2025-07-31',8,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL), +(469,'2025-07-31',7,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL), +(470,'2025-07-31',6,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL), +(471,'2025-07-31',3,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL), +(472,'2025-07-31',2,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL), +(473,'2025-07-11',10,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(474,'2025-07-11',5,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(475,'2025-07-11',4,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(476,'2025-07-11',9,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(477,'2025-07-11',8,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(478,'2025-07-11',3,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(479,'2025-07-11',2,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(480,'2025-07-11',7,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(481,'2025-07-11',6,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(482,'2025-07-11',1,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL), +(483,'2025-08-01',10,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL), +(484,'2025-08-01',9,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL), +(485,'2025-08-01',8,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL), +(486,'2025-08-01',7,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL), +(487,'2025-08-01',6,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL), +(488,'2025-08-01',3,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL), +(489,'2025-08-01',2,3,2,1,NULL,8.00,'2025-08-01 04:57:48','2025-08-01 04:57:48',5,NULL), +(490,'2025-08-01',4,3,3,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL), +(491,'2025-08-01',4,5,1,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL), +(492,'2025-08-01',5,3,3,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL), +(493,'2025-08-01',5,5,1,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL), +(494,'2025-08-07',9,3,2,2,4,4.00,'2025-08-07 06:42:39','2025-08-07 06:42:39',5,NULL), +(495,'2025-08-07',9,3,2,1,NULL,4.00,'2025-08-07 06:42:39','2025-08-07 06:42:39',5,NULL), +(496,'2025-08-07',7,3,2,2,4,4.00,'2025-08-07 06:42:39','2025-08-07 06:42:39',5,NULL), +(497,'2025-08-07',7,3,2,1,NULL,4.00,'2025-08-07 06:42:39','2025-08-07 06:42:39',5,NULL), +(498,'2025-08-07',10,5,2,1,NULL,8.00,'2025-08-07 06:43:14','2025-08-07 06:43:14',5,NULL), +(499,'2025-08-07',4,5,2,1,NULL,8.00,'2025-08-07 06:43:15','2025-08-07 06:43:15',5,NULL), +(500,'2025-08-07',2,5,2,1,NULL,8.00,'2025-08-07 06:43:15','2025-08-07 06:43:15',5,NULL), +(501,'2025-08-07',6,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL), +(502,'2025-08-07',3,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL), +(503,'2025-08-07',8,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL), +(504,'2025-08-07',1,3,3,1,NULL,8.00,'2025-08-07 06:43:52','2025-08-07 06:43:52',3,NULL), +(505,'2025-08-08',1,3,3,1,NULL,8.00,'2025-08-08 06:45:20','2025-08-08 06:45:20',3,NULL), +(506,'2025-08-08',10,5,2,1,NULL,8.00,'2025-08-08 06:58:42','2025-08-08 06:58:42',5,NULL), +(507,'2025-08-08',2,5,2,1,NULL,8.00,'2025-08-08 06:58:42','2025-08-08 06:58:42',5,NULL), +(508,'2025-08-08',9,3,2,1,NULL,8.00,'2025-08-08 06:59:18','2025-08-08 06:59:18',5,NULL), +(509,'2025-08-08',8,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL), +(510,'2025-08-08',3,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL), +(511,'2025-08-08',4,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL), +(512,'2025-08-08',6,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL), +(513,'2025-08-11',1,3,3,1,NULL,8.00,'2025-08-11 06:27:37','2025-08-11 06:27:37',3,NULL), +(514,'2025-08-11',1,3,3,1,NULL,8.00,'2025-08-11 06:27:37','2025-08-11 06:27:37',3,NULL), +(515,'2025-08-11',10,5,2,1,NULL,8.00,'2025-08-11 06:46:23','2025-08-11 06:46:23',5,NULL), +(516,'2025-08-11',2,5,2,1,NULL,8.00,'2025-08-11 06:46:23','2025-08-11 06:46:23',5,NULL), +(517,'2025-08-11',8,3,2,1,NULL,8.00,'2025-08-11 06:46:49','2025-08-11 06:46:49',5,NULL), +(518,'2025-08-11',7,3,2,1,NULL,8.00,'2025-08-11 06:46:49','2025-08-11 06:46:49',5,NULL), +(519,'2025-08-11',6,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL), +(520,'2025-08-11',5,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL), +(521,'2025-08-11',4,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL), +(522,'2025-08-11',3,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL), +(523,'2025-08-12',10,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL), +(524,'2025-08-12',9,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL), +(525,'2025-08-12',8,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL), +(526,'2025-08-12',7,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL), +(527,'2025-08-12',5,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL), +(528,'2025-08-12',4,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL), +(529,'2025-08-12',3,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL), +(530,'2025-08-12',1,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL), +(531,'2025-08-13',1,3,3,1,NULL,8.00,'2025-08-13 06:31:32','2025-08-13 06:31:32',3,NULL), +(532,'2025-08-13',2,3,2,1,NULL,4.00,'2025-08-13 06:36:13','2025-08-13 06:36:13',5,NULL), +(533,'2025-08-13',2,5,2,1,NULL,4.00,'2025-08-13 06:36:13','2025-08-13 06:36:13',5,NULL), +(534,'2025-08-13',9,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL), +(535,'2025-08-13',8,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL), +(536,'2025-08-13',7,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL), +(537,'2025-08-13',6,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL), +(538,'2025-08-13',5,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL), +(539,'2025-08-13',4,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL), +(540,'2025-08-13',3,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL), +(541,'2025-08-13',10,5,2,1,NULL,8.00,'2025-08-13 06:37:19','2025-08-13 06:37:19',5,NULL), +(542,'2025-08-14',1,3,3,2,1,4.00,'2025-08-14 06:35:27','2025-08-14 06:35:27',3,NULL), +(543,'2025-08-14',1,3,3,1,NULL,4.00,'2025-08-14 06:35:27','2025-08-14 06:35:27',3,NULL), +(544,'2025-08-14',10,5,2,1,NULL,4.00,'2025-08-14 06:39:03','2025-08-14 06:39:03',5,NULL), +(545,'2025-08-14',10,5,3,1,NULL,4.00,'2025-08-14 06:39:03','2025-08-14 06:39:03',5,NULL), +(546,'2025-08-14',2,5,2,1,NULL,2.00,'2025-08-14 06:39:44','2025-08-14 06:39:44',5,NULL), +(547,'2025-08-14',2,3,2,1,NULL,6.00,'2025-08-14 06:39:44','2025-08-14 06:39:44',5,NULL), +(548,'2025-08-14',9,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL), +(549,'2025-08-14',8,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL), +(550,'2025-08-14',7,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL), +(551,'2025-08-14',6,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL), +(552,'2025-08-14',5,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL), +(553,'2025-08-14',4,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL), +(554,'2025-08-18',2,3,2,1,NULL,8.00,'2025-08-18 06:21:36','2025-08-18 06:21:36',5,NULL), +(555,'2025-08-18',8,3,2,1,NULL,8.00,'2025-08-18 06:21:36','2025-08-18 06:21:36',5,NULL), +(556,'2025-08-18',4,3,2,1,NULL,8.00,'2025-08-18 06:22:01','2025-08-18 06:22:01',5,NULL), +(557,'2025-08-18',10,5,3,1,NULL,6.00,'2025-08-18 06:22:53','2025-08-18 06:22:53',5,NULL), +(558,'2025-08-18',10,3,2,1,NULL,2.00,'2025-08-18 06:22:53','2025-08-18 06:22:53',5,NULL), +(559,'2025-08-18',9,3,2,1,NULL,4.00,'2025-08-18 06:23:34','2025-08-18 06:23:34',5,NULL), +(560,'2025-08-18',9,3,3,1,NULL,4.00,'2025-08-18 06:23:34','2025-08-18 06:23:34',5,NULL), +(561,'2025-08-18',5,3,3,2,1,4.00,'2025-08-18 06:41:24','2025-08-18 06:41:24',3,NULL), +(562,'2025-08-18',1,3,3,2,1,4.00,'2025-08-18 06:41:24','2025-08-18 06:41:24',3,NULL), +(563,'2025-08-18',7,3,3,2,1,4.00,'2025-08-18 06:41:24','2025-08-18 06:41:24',3,NULL), +(564,'2025-08-18',7,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL), +(565,'2025-08-18',5,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL), +(566,'2025-08-18',1,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL), +(567,'2025-08-18',6,3,3,1,NULL,8.00,'2025-08-18 06:43:35','2025-08-18 06:43:35',6,NULL), +(568,'2025-08-18',3,3,3,1,NULL,8.00,'2025-08-18 06:43:35','2025-08-18 06:43:35',6,NULL), +(569,'2025-08-19',1,3,3,1,NULL,6.00,'2025-08-19 08:02:49','2025-08-19 08:02:49',5,NULL), +(570,'2025-08-19',3,3,3,1,NULL,10.00,'2025-08-19 08:03:30','2025-08-19 08:03:30',5,NULL), +(571,'2025-08-19',6,3,3,1,NULL,10.00,'2025-08-19 08:03:30','2025-08-19 08:03:30',5,NULL), +(572,'2025-08-19',7,3,3,1,NULL,10.00,'2025-08-19 08:03:30','2025-08-19 08:03:30',5,NULL), +(573,'2025-08-19',9,3,3,1,NULL,10.00,'2025-08-19 08:03:30','2025-08-19 08:03:30',5,NULL), +(574,'2025-08-19',10,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL), +(575,'2025-08-19',8,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL), +(576,'2025-08-19',5,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL), +(577,'2025-08-19',4,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL), +(578,'2025-08-19',2,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL), +(579,'2025-08-19',3,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL), +(580,'2025-08-19',7,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL), +(581,'2025-08-19',6,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL), +(582,'2025-08-20',2,3,2,1,NULL,8.00,'2025-08-20 06:19:36','2025-08-20 06:19:36',5,NULL), +(583,'2025-08-20',5,3,1,1,NULL,2.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL), +(584,'2025-08-20',5,3,2,1,NULL,6.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL), +(585,'2025-08-20',4,3,1,1,NULL,2.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL), +(586,'2025-08-20',4,3,2,1,NULL,6.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL), +(587,'2025-08-20',6,3,3,1,NULL,4.00,'2025-08-20 06:43:46','2025-08-20 06:43:46',3,NULL), +(588,'2025-08-20',10,3,3,1,NULL,8.00,'2025-08-20 06:44:23','2025-08-20 06:44:23',3,NULL), +(589,'2025-08-20',9,3,3,1,NULL,8.00,'2025-08-20 06:44:23','2025-08-20 06:44:23',3,NULL), +(590,'2025-08-20',8,3,3,1,NULL,8.00,'2025-08-20 06:44:23','2025-08-20 06:44:23',3,NULL), +(591,'2025-08-20',7,3,3,1,NULL,8.00,'2025-08-20 06:44:24','2025-08-20 06:44:24',3,NULL), +(592,'2025-08-20',3,3,3,1,NULL,8.00,'2025-08-20 06:44:24','2025-08-20 06:44:24',3,NULL), +(593,'2025-08-20',1,3,3,1,NULL,8.00,'2025-08-20 06:44:24','2025-08-20 06:44:24',3,NULL), +(594,'2025-08-20',10,3,3,1,NULL,8.00,'2025-08-20 06:44:26','2025-08-20 06:44:26',6,NULL), +(595,'2025-08-20',3,3,3,1,NULL,8.00,'2025-08-20 06:44:26','2025-08-20 06:44:26',6,NULL), +(596,'2025-08-21',7,3,3,1,NULL,8.00,'2025-08-21 06:30:36','2025-08-21 06:30:36',3,NULL), +(597,'2025-08-21',1,3,3,1,NULL,8.00,'2025-08-21 06:30:36','2025-08-21 06:30:36',3,NULL), +(598,'2025-08-21',1,3,3,1,NULL,8.00,'2025-08-21 07:50:38','2025-08-21 07:50:38',5,NULL), +(599,'2025-08-21',7,3,3,1,NULL,8.00,'2025-08-21 07:50:38','2025-08-21 07:50:38',5,NULL), +(600,'2025-08-21',10,3,3,1,NULL,8.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL), +(601,'2025-08-21',10,3,3,1,NULL,2.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL), +(602,'2025-08-21',9,3,3,1,NULL,8.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL), +(603,'2025-08-21',9,3,3,1,NULL,2.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL), +(604,'2025-08-21',6,3,3,1,NULL,8.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL), +(605,'2025-08-21',6,3,3,1,NULL,2.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL), +(606,'2025-08-21',3,3,3,1,NULL,8.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL), +(607,'2025-08-21',3,3,3,1,NULL,2.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL), +(608,'2025-08-21',2,3,2,1,NULL,8.00,'2025-08-21 07:54:46','2025-08-21 07:54:46',5,NULL), +(609,'2025-08-21',2,5,2,1,NULL,2.00,'2025-08-21 07:54:46','2025-08-21 07:54:46',5,NULL), +(610,'2025-08-21',8,3,3,1,NULL,4.00,'2025-08-21 07:55:25','2025-08-21 07:55:25',5,NULL), +(611,'2025-08-21',8,3,2,1,NULL,6.00,'2025-08-21 07:55:25','2025-08-21 07:55:25',5,NULL), +(612,'2025-08-21',6,3,3,1,NULL,10.00,'2025-08-21 08:24:50','2025-08-21 08:24:50',6,NULL), +(613,'2025-08-21',3,3,3,1,NULL,10.00,'2025-08-21 08:24:50','2025-08-21 08:24:50',6,NULL), +(614,'2025-08-22',2,3,2,1,NULL,8.00,'2025-08-22 06:21:15','2025-08-22 06:21:15',5,NULL), +(615,'2025-08-22',8,3,2,1,NULL,4.00,'2025-08-22 06:23:12','2025-08-22 06:23:12',5,NULL), +(616,'2025-08-22',8,3,3,1,NULL,4.00,'2025-08-22 06:23:12','2025-08-22 06:23:12',5,NULL), +(617,'2025-08-22',5,3,3,1,NULL,8.00,'2025-08-22 06:23:55','2025-08-22 06:23:55',5,NULL), +(618,'2025-08-22',6,3,2,1,NULL,4.00,'2025-08-22 06:27:43','2025-08-22 06:27:43',3,NULL), +(619,'2025-08-22',10,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL), +(620,'2025-08-22',9,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL), +(621,'2025-08-22',7,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL), +(622,'2025-08-22',4,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL), +(623,'2025-08-22',3,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL), +(624,'2025-08-22',1,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL), +(625,'2025-08-23',4,3,2,1,NULL,2.00,'2025-08-23 04:57:02','2025-08-23 04:57:02',5,NULL), +(626,'2025-08-23',4,3,3,1,NULL,6.00,'2025-08-23 04:57:02','2025-08-23 04:57:02',5,NULL), +(627,'2025-08-23',2,3,2,1,NULL,8.00,'2025-08-23 04:57:25','2025-08-23 04:57:25',5,NULL), +(628,'2025-08-23',10,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL), +(629,'2025-08-23',9,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL), +(630,'2025-08-23',8,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL), +(631,'2025-08-23',6,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL), +(632,'2025-08-23',5,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL), +(633,'2025-08-23',3,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL), +(634,'2025-08-23',1,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL), +(635,'2025-08-25',10,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(636,'2025-08-25',9,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(637,'2025-08-25',8,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(638,'2025-08-25',7,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(639,'2025-08-25',6,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(640,'2025-08-25',5,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(641,'2025-08-25',4,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(642,'2025-08-25',3,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(643,'2025-08-25',2,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(644,'2025-08-25',1,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL), +(645,'2025-08-25',6,3,3,1,NULL,8.00,'2025-08-25 06:49:16','2025-08-25 06:49:16',6,NULL), +(646,'2025-08-25',3,3,3,1,NULL,8.00,'2025-08-25 06:49:17','2025-08-25 06:49:17',6,NULL), +(647,'2025-08-26',4,8,3,1,NULL,8.00,'2025-08-26 07:28:03','2025-08-26 07:28:03',5,NULL), +(648,'2025-08-26',4,3,3,1,NULL,2.00,'2025-08-26 07:28:03','2025-08-26 07:28:03',5,NULL), +(649,'2025-08-26',2,8,3,1,NULL,10.00,'2025-08-26 07:28:35','2025-08-26 07:28:35',5,NULL), +(650,'2025-08-26',10,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL), +(651,'2025-08-26',9,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL), +(652,'2025-08-26',8,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL), +(653,'2025-08-26',7,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL), +(654,'2025-08-26',6,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL), +(655,'2025-08-26',5,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL), +(656,'2025-08-26',3,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL), +(657,'2025-08-26',1,3,3,1,NULL,10.00,'2025-08-26 07:29:03','2025-08-26 07:29:03',5,NULL), +(658,'2025-08-26',6,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL), +(659,'2025-08-26',10,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL), +(660,'2025-08-26',3,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL), +(661,'2025-08-27',10,3,3,2,5,8.00,'2025-08-27 06:44:47','2025-08-27 06:44:47',3,NULL), +(662,'2025-08-27',9,3,3,2,5,8.00,'2025-08-27 06:44:47','2025-08-27 06:44:47',3,NULL), +(663,'2025-08-27',7,3,3,2,5,8.00,'2025-08-27 06:44:47','2025-08-27 06:44:47',3,NULL), +(664,'2025-08-27',6,3,3,2,5,8.00,'2025-08-27 06:44:47','2025-08-27 06:44:47',3,NULL), +(665,'2025-08-27',5,3,3,2,5,8.00,'2025-08-27 06:44:47','2025-08-27 06:44:47',3,NULL), +(666,'2025-08-27',4,3,3,2,5,8.00,'2025-08-27 06:44:47','2025-08-27 06:44:47',3,NULL), +(667,'2025-08-27',3,3,3,2,5,8.00,'2025-08-27 06:44:47','2025-08-27 06:44:47',3,NULL), +(668,'2025-08-27',1,3,3,2,5,8.00,'2025-08-27 06:44:48','2025-08-27 06:44:48',3,NULL), +(669,'2025-08-27',2,3,3,2,1,2.00,'2025-08-27 06:45:32','2025-08-27 06:45:32',5,NULL), +(670,'2025-08-27',2,8,2,1,NULL,6.00,'2025-08-27 06:45:32','2025-08-27 06:45:32',5,NULL), +(671,'2025-08-27',8,3,3,2,1,2.00,'2025-08-27 06:45:32','2025-08-27 06:45:32',5,NULL), +(672,'2025-08-27',8,8,2,1,NULL,6.00,'2025-08-27 06:45:32','2025-08-27 06:45:32',5,NULL), +(673,'2025-08-28',10,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL), +(674,'2025-08-28',10,3,3,2,1,4.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL), +(675,'2025-08-28',5,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL), +(676,'2025-08-28',5,3,3,2,1,4.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL), +(677,'2025-08-28',6,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL), +(678,'2025-08-28',6,3,3,2,1,4.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL), +(679,'2025-08-28',3,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL), +(680,'2025-08-28',3,3,3,2,1,4.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL), +(681,'2025-08-28',4,3,3,1,NULL,4.00,'2025-08-28 08:37:46','2025-08-28 08:37:46',5,NULL), +(682,'2025-08-28',4,5,3,1,NULL,4.00,'2025-08-28 08:37:46','2025-08-28 08:37:46',5,NULL), +(683,'2025-08-28',8,8,2,1,NULL,4.00,'2025-08-28 08:38:15','2025-08-28 08:38:15',5,NULL), +(684,'2025-08-28',8,5,3,1,NULL,4.00,'2025-08-28 08:38:15','2025-08-28 08:38:15',5,NULL), +(685,'2025-08-28',2,3,3,2,1,2.00,'2025-08-28 08:38:50','2025-08-28 08:38:50',5,NULL), +(686,'2025-08-28',2,5,3,1,NULL,6.00,'2025-08-28 08:38:50','2025-08-28 08:38:50',5,NULL), +(687,'2025-08-28',1,3,3,2,1,8.00,'2025-08-28 08:39:24','2025-08-28 08:39:24',5,NULL), +(689,'2025-08-28',9,3,3,2,4,8.00,'2025-08-28 08:40:00','2025-08-28 08:40:00',5,NULL), +(690,'2025-08-28',7,3,3,2,4,8.00,'2025-08-28 08:40:00','2025-08-28 08:40:00',5,NULL), +(694,'2025-08-28',4,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL), +(695,'2025-08-28',8,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL), +(696,'2025-08-28',2,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL), +(698,'2025-08-28',9,3,3,1,NULL,2.00,'2025-08-28 08:45:19','2025-08-28 08:45:19',5,NULL), +(699,'2025-08-28',7,3,3,1,NULL,2.00,'2025-08-28 08:45:19','2025-08-28 08:45:19',5,NULL), +(703,'2025-08-29',10,3,3,2,5,8.00,'2025-08-29 06:47:02','2025-08-29 06:47:02',3,NULL), +(704,'2025-08-29',9,3,3,2,5,8.00,'2025-08-29 06:47:02','2025-08-29 06:47:02',3,NULL), +(706,'2025-08-29',7,3,3,2,5,8.00,'2025-08-29 06:47:02','2025-08-29 06:47:02',3,NULL), +(710,'2025-08-29',1,3,3,2,5,8.00,'2025-08-29 06:47:02','2025-08-29 06:47:02',3,NULL), +(713,'2025-08-29',5,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL), +(714,'2025-08-29',5,3,3,2,1,2.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL), +(715,'2025-08-29',3,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL), +(716,'2025-08-29',3,3,3,2,1,2.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL), +(717,'2025-08-29',6,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL), +(718,'2025-08-29',6,3,3,2,1,2.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL), +(719,'2025-08-29',8,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL), +(720,'2025-08-29',4,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL), +(721,'2025-08-29',2,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL), +(722,'2025-08-30',2,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL), +(723,'2025-08-30',8,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL), +(724,'2025-08-30',4,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL), +(725,'2025-08-30',10,3,3,2,1,8.00,'2025-08-30 05:36:49','2025-08-30 05:36:49',3,NULL), +(726,'2025-08-30',9,3,3,2,1,8.00,'2025-08-30 05:36:49','2025-08-30 05:36:49',3,NULL), +(727,'2025-08-30',7,3,3,2,1,8.00,'2025-08-30 05:36:49','2025-08-30 05:36:49',3,NULL), +(728,'2025-08-30',6,3,3,2,1,8.00,'2025-08-30 05:36:49','2025-08-30 05:36:49',3,NULL), +(729,'2025-08-30',5,3,3,2,1,8.00,'2025-08-30 05:36:49','2025-08-30 05:36:49',3,NULL), +(730,'2025-08-30',3,3,3,2,1,8.00,'2025-08-30 05:36:49','2025-08-30 05:36:49',3,NULL), +(731,'2025-08-30',1,3,3,2,1,8.00,'2025-08-30 05:36:49','2025-08-30 05:36:49',3,NULL), +(732,'2025-09-01',7,3,3,1,NULL,8.00,'2025-09-01 06:18:28','2025-09-01 06:18:28',3,NULL), +(733,'2025-09-01',9,3,3,1,NULL,8.00,'2025-09-01 06:18:28','2025-09-01 06:18:28',3,NULL), +(734,'2025-09-01',10,3,3,2,5,4.00,'2025-09-01 06:19:11','2025-09-01 06:19:11',3,NULL), +(735,'2025-09-01',3,3,3,2,5,4.00,'2025-09-01 06:19:11','2025-09-01 06:19:11',3,NULL), +(736,'2025-09-01',1,3,3,2,5,4.00,'2025-09-01 06:19:11','2025-09-01 06:19:11',3,NULL), +(737,'2025-09-01',10,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL), +(738,'2025-09-01',3,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL), +(739,'2025-09-01',1,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL), +(740,'2025-09-01',5,3,3,2,1,8.00,'2025-09-01 06:20:03','2025-09-01 06:20:03',3,NULL); +/*!40000 ALTER TABLE `daily_work_reports` ENABLE KEYS */; +UNLOCK TABLES; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2025-09-01 23:19:44 diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/hyungi.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/hyungi.sql new file mode 100644 index 0000000..94c5b49 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/hyungi.sql @@ -0,0 +1,2563 @@ +작-- phpMyAdmin SQL Dump +-- version 5.2.2 +-- https://www.phpmyadmin.net/ +-- +-- 호스트: db_hyungi_net +-- 생성 시간: 25-06-27 23:07 +-- 서버 버전: 10.9.8-MariaDB-1:10.9.8+maria~ubu2204 +-- PHP 버전: 8.2.27 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- 데이터베이스: `hyungi` +-- + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `activity_logs` +-- + +CREATE TABLE `activity_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `activity_type` varchar(100) DEFAULT NULL, + `table_name` varchar(50) DEFAULT NULL, + `record_id` int(11) DEFAULT NULL, + `action` enum('create','read','update','delete') DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `CuttingPlan` +-- + +CREATE TABLE `CuttingPlan` ( + `cutting_plan_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `drawing_name` varchar(255) NOT NULL, + `area_number` varchar(100) DEFAULT NULL, + `spool_number` varchar(255) DEFAULT NULL, + `length` decimal(10,2) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `spec_id` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `DailyIssueReports` +-- + +CREATE TABLE `DailyIssueReports` ( + `id` int(11) NOT NULL, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `issue_type_id` int(11) DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `start_time` time NOT NULL, + `end_time` time NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `DailyIssueReports` +-- + +INSERT INTO `DailyIssueReports` (`id`, `date`, `worker_id`, `project_id`, `issue_type_id`, `description`, `created_at`, `start_time`, `end_time`) VALUES +(1, '2025-06-02', 1, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(2, '2025-06-02', 9, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(3, '2025-06-02', 7, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(4, '2025-06-04', 10, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(5, '2025-06-04', 6, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(6, '2025-06-04', 3, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(7, '2025-06-11', 10, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'), +(8, '2025-06-11', 6, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'), +(9, '2025-06-11', 3, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `daily_worker_summary` +-- + +CREATE TABLE `daily_worker_summary` ( + `id` int(11) NOT NULL, + `report_date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `total_hours` decimal(4,2) NOT NULL DEFAULT 8.00 COMMENT '총 근무시간', + `work_status` enum('normal','annual_leave','half_leave','overtime') DEFAULT 'normal' COMMENT '근무 상태', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `daily_work_reports` +-- + +CREATE TABLE `daily_work_reports` ( + `id` int(11) NOT NULL, + `report_date` date NOT NULL COMMENT '작업 날짜', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `project_id` int(11) NOT NULL COMMENT '프로젝트 ID', + `work_type_id` int(11) NOT NULL COMMENT '작업 유형 ID', + `work_status_id` int(11) DEFAULT 1 COMMENT '업무 상태 ID (1:정규, 2:에러)', + `error_type_id` int(11) DEFAULT NULL COMMENT '에러 유형 ID (에러일 때만)', + `work_hours` decimal(4,2) NOT NULL COMMENT '작업 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `created_by` int(11) NOT NULL DEFAULT 1 COMMENT '작성자 user_id', + `updated_by` int(11) DEFAULT NULL COMMENT '수정자 user_id' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `daily_work_reports` +-- + +INSERT INTO `daily_work_reports` (`id`, `report_date`, `worker_id`, `project_id`, `work_type_id`, `work_status_id`, `error_type_id`, `work_hours`, `created_at`, `updated_at`, `created_by`, `updated_by`) VALUES +(14, '2025-06-02', 1, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(15, '2025-06-02', 3, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(16, '2025-06-02', 4, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(17, '2025-06-02', 6, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(18, '2025-06-02', 7, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(19, '2025-06-02', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(20, '2025-06-02', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:10:47', '2025-06-16 05:10:47', 1, NULL), +(21, '2025-06-04', 1, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(22, '2025-06-04', 3, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(23, '2025-06-04', 5, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(24, '2025-06-04', 7, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(25, '2025-06-04', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(26, '2025-06-04', 10, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(27, '2025-06-04', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(28, '2025-06-04', 6, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(29, '2025-06-04', 8, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(30, '2025-06-05', 1, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(31, '2025-06-05', 3, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(32, '2025-06-05', 4, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(33, '2025-06-05', 7, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(34, '2025-06-05', 10, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(35, '2025-06-05', 9, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(36, '2025-06-05', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(37, '2025-06-05', 5, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(38, '2025-06-05', 6, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(39, '2025-06-05', 8, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(40, '2025-06-16', 5, 3, 2, 1, NULL, 8.00, '2025-06-16 06:12:01', '2025-06-16 06:12:01', 5, NULL), +(43, '2025-06-16', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 06:12:01', '2025-06-16 06:12:01', 5, NULL), +(44, '2025-06-16', 6, 3, 2, 2, 4, 4.00, '2025-06-16 06:13:02', '2025-06-16 06:13:02', 5, NULL), +(45, '2025-06-16', 6, 3, 2, 1, NULL, 4.00, '2025-06-16 06:13:50', '2025-06-16 06:13:50', 5, NULL), +(46, '2025-06-16', 8, 3, 2, 2, 4, 4.00, '2025-06-16 06:15:22', '2025-06-16 06:15:22', 5, NULL), +(47, '2025-06-16', 8, 3, 2, 1, NULL, 4.00, '2025-06-16 06:15:22', '2025-06-16 06:15:22', 5, NULL), +(48, '2025-06-16', 4, 4, 3, 2, 1, 8.00, '2025-06-16 06:46:44', '2025-06-16 06:46:44', 3, NULL), +(50, '2025-06-16', 1, 4, 3, 2, 1, 8.00, '2025-06-16 06:46:44', '2025-06-16 06:46:44', 3, NULL), +(51, '2025-06-16', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 06:48:29', '2025-06-16 06:48:29', 3, NULL), +(52, '2025-06-16', 10, 4, 3, 1, NULL, 6.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(53, '2025-06-16', 10, 4, 3, 2, 1, 2.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(54, '2025-06-16', 3, 4, 3, 1, NULL, 6.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(55, '2025-06-16', 3, 4, 3, 2, 1, 2.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(56, '2025-06-17', 2, 3, 2, 1, NULL, 8.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(57, '2025-06-17', 2, 3, 2, 1, NULL, 2.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(58, '2025-06-17', 5, 3, 2, 1, NULL, 8.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(59, '2025-06-17', 5, 3, 2, 1, NULL, 2.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(60, '2025-06-17', 6, 3, 2, 1, NULL, 8.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(61, '2025-06-17', 6, 3, 2, 2, 4, 2.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(62, '2025-06-17', 8, 3, 2, 1, NULL, 8.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(63, '2025-06-17', 8, 3, 2, 2, 4, 2.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(65, '2025-06-17', 9, 4, 3, 2, 1, 4.00, '2025-06-17 08:25:24', '2025-06-17 08:25:24', 3, NULL), +(66, '2025-06-17', 1, 4, 3, 2, 1, 4.00, '2025-06-17 08:27:06', '2025-06-17 08:27:06', 3, NULL), +(67, '2025-06-17', 4, 4, 3, 2, 1, 4.00, '2025-06-17 08:27:06', '2025-06-17 08:27:06', 3, NULL), +(68, '2025-06-17', 1, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(69, '2025-06-17', 9, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(70, '2025-06-17', 4, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(71, '2025-06-17', 9, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(72, '2025-06-17', 4, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(73, '2025-06-17', 1, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(74, '2025-06-17', 10, 4, 3, 1, NULL, 8.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(75, '2025-06-17', 10, 4, 3, 2, 1, 2.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(76, '2025-06-17', 3, 4, 3, 1, NULL, 8.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(77, '2025-06-17', 3, 4, 3, 2, 1, 2.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(78, '2025-06-18', 6, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(79, '2025-06-18', 2, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(80, '2025-06-18', 8, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(81, '2025-06-18', 2, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:02', '2025-06-18 08:41:02', 5, NULL), +(82, '2025-06-18', 6, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:03', '2025-06-18 08:41:03', 5, NULL), +(83, '2025-06-18', 8, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:03', '2025-06-18 08:41:03', 5, NULL), +(84, '2025-06-18', 5, 4, 3, 1, NULL, 8.00, '2025-06-18 08:41:45', '2025-06-18 08:41:45', 5, NULL), +(85, '2025-06-18', 5, 4, 3, 1, NULL, 2.00, '2025-06-18 08:41:45', '2025-06-18 08:41:45', 5, NULL), +(86, '2025-06-18', 10, 4, 3, 1, NULL, 9.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(87, '2025-06-18', 10, 4, 3, 2, 1, 1.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(88, '2025-06-18', 3, 4, 3, 1, NULL, 9.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(89, '2025-06-18', 3, 4, 3, 2, 1, 1.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(90, '2025-06-18', 4, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(91, '2025-06-18', 4, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(92, '2025-06-18', 9, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(93, '2025-06-18', 9, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(94, '2025-06-18', 1, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(95, '2025-06-18', 1, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(96, '2025-06-18', 7, 4, 3, 2, 1, 4.00, '2025-06-18 09:00:17', '2025-06-18 09:00:17', 3, NULL), +(97, '2025-06-18', 7, 4, 3, 1, NULL, 6.00, '2025-06-18 09:00:17', '2025-06-18 09:00:17', 3, NULL), +(98, '2025-06-19', 8, 3, 2, 1, NULL, 8.00, '2025-06-19 06:37:59', '2025-06-19 06:37:59', 5, NULL), +(99, '2025-06-19', 2, 3, 2, 1, NULL, 8.00, '2025-06-19 06:37:59', '2025-06-19 06:37:59', 5, NULL), +(100, '2025-06-19', 10, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(101, '2025-06-19', 3, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(102, '2025-06-19', 5, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(103, '2025-06-19', 9, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(104, '2025-06-19', 9, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(105, '2025-06-19', 4, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(106, '2025-06-19', 4, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(107, '2025-06-19', 1, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(108, '2025-06-19', 1, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(109, '2025-06-19', 7, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(110, '2025-06-19', 7, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(111, '2025-06-19', 6, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(112, '2025-06-19', 6, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(113, '2025-06-20', 9, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(114, '2025-06-20', 9, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(115, '2025-06-20', 4, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(116, '2025-06-20', 4, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(117, '2025-06-20', 7, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(118, '2025-06-20', 7, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(119, '2025-06-20', 6, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(120, '2025-06-20', 6, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(121, '2025-06-20', 1, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(122, '2025-06-20', 1, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(123, '2025-06-20', 5, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(124, '2025-06-20', 5, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(125, '2025-06-20', 10, 4, 3, 1, NULL, 8.00, '2025-06-20 06:45:30', '2025-06-20 06:45:30', 6, NULL), +(126, '2025-06-20', 3, 4, 3, 1, NULL, 8.00, '2025-06-20 06:45:31', '2025-06-20 06:45:31', 6, NULL), +(127, '2025-06-23', 10, 4, 3, 1, NULL, 8.00, '2025-06-23 06:42:58', '2025-06-23 06:42:58', 6, NULL), +(128, '2025-06-23', 3, 4, 3, 1, NULL, 8.00, '2025-06-23 06:42:58', '2025-06-23 06:42:58', 6, NULL), +(129, '2025-06-23', 5, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(130, '2025-06-23', 5, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(131, '2025-06-23', 1, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(132, '2025-06-23', 1, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(133, '2025-06-23', 9, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(134, '2025-06-23', 9, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(135, '2025-06-23', 4, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(136, '2025-06-23', 4, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(137, '2025-06-23', 7, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(138, '2025-06-23', 7, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(139, '2025-06-23', 6, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(140, '2025-06-23', 6, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(141, '2025-06-24', 10, 4, 3, 1, NULL, 12.00, '2025-06-24 11:10:32', '2025-06-24 11:10:32', 6, NULL), +(142, '2025-06-24', 3, 4, 3, 1, NULL, 12.00, '2025-06-24 11:10:32', '2025-06-24 11:10:32', 6, NULL), +(143, '2025-06-24', 9, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(144, '2025-06-24', 9, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(145, '2025-06-24', 5, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(146, '2025-06-24', 5, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(147, '2025-06-24', 4, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(148, '2025-06-24', 4, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(149, '2025-06-24', 7, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(150, '2025-06-24', 7, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(151, '2025-06-24', 6, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(152, '2025-06-24', 6, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(153, '2025-06-24', 1, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(154, '2025-06-24', 1, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(155, '2025-06-24', 8, 3, 2, 1, NULL, 8.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(156, '2025-06-24', 8, 3, 2, 1, NULL, 4.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(157, '2025-06-24', 2, 3, 2, 1, NULL, 8.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(158, '2025-06-24', 2, 3, 2, 1, NULL, 4.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(159, '2025-06-25', 2, 3, 2, 1, NULL, 8.00, '2025-06-25 11:08:04', '2025-06-25 11:08:04', 5, NULL), +(160, '2025-06-25', 2, 3, 2, 1, NULL, 4.00, '2025-06-25 11:08:04', '2025-06-25 11:08:04', 5, NULL), +(161, '2025-06-25', 8, 3, 2, 1, NULL, 8.00, '2025-06-25 11:08:05', '2025-06-25 11:08:05', 5, NULL), +(162, '2025-06-25', 8, 3, 2, 1, NULL, 4.00, '2025-06-25 11:08:05', '2025-06-25 11:08:05', 5, NULL), +(163, '2025-06-25', 10, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(164, '2025-06-25', 9, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(165, '2025-06-25', 3, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(166, '2025-06-25', 6, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(167, '2025-06-26', 10, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(168, '2025-06-26', 5, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(169, '2025-06-26', 7, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(170, '2025-06-26', 1, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(171, '2025-06-26', 4, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(172, '2025-06-26', 8, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:31', '2025-06-26 11:11:31', 5, NULL), +(173, '2025-06-26', 8, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:31', '2025-06-26 11:11:31', 5, NULL), +(174, '2025-06-26', 2, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(175, '2025-06-26', 2, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(176, '2025-06-26', 9, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(177, '2025-06-26', 9, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(178, '2025-06-26', 3, 3, 2, 1, NULL, 12.00, '2025-06-26 11:19:34', '2025-06-26 11:19:34', 6, NULL), +(179, '2025-06-26', 6, 3, 2, 1, NULL, 12.00, '2025-06-26 11:19:34', '2025-06-26 11:19:34', 6, NULL), +(182, '2025-06-27', 2, 3, 2, 1, NULL, 4.00, '2025-06-27 01:54:40', '2025-06-27 01:54:40', 5, NULL), +(183, '2025-06-27', 9, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(184, '2025-06-27', 10, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(185, '2025-06-27', 7, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(186, '2025-06-27', 5, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(187, '2025-06-27', 4, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(188, '2025-06-27', 1, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(189, '2025-06-27', 3, 3, 2, 1, NULL, 8.00, '2025-06-27 06:49:08', '2025-06-27 06:49:08', 6, NULL), +(191, '2025-06-27', 6, 3, 2, 1, NULL, 4.00, '2025-06-27 06:58:46', '2025-06-27 06:58:46', 6, NULL), +(192, '2025-06-27', 8, 3, 2, 1, NULL, 6.00, '2025-06-27 07:00:10', '2025-06-27 07:00:10', 5, NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `EquipmentList` +-- + +CREATE TABLE `EquipmentList` ( + `equipment_id` int(11) NOT NULL, + `factory_id` int(11) DEFAULT NULL, + `equipment_name` varchar(255) NOT NULL, + `model` varchar(100) DEFAULT NULL, + `status` text DEFAULT 'operational', + `purchase_date` date DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `error_types` +-- + +CREATE TABLE `error_types` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL COMMENT '에러 유형명', + `description` text DEFAULT NULL COMMENT '에러 설명', + `severity` enum('low','medium','high','critical') DEFAULT 'medium' COMMENT '심각도', + `solution_guide` text DEFAULT NULL COMMENT '해결 가이드', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `error_types` +-- + +INSERT INTO `error_types` (`id`, `name`, `description`, `severity`, `solution_guide`, `created_at`, `updated_at`) VALUES +(1, '설계미스', '설계미스', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:03'), +(2, '외주작업 불량', '입고 자재 불량', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:05'), +(3, '입고지연', '자재 미입고', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:11'), +(4, '작업불량', '작업자 실수', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:13'), +(5, '설비고장', '장비없음', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:16'), +(6, '검사불량', '검사불량', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-24 04:36:18'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `FactoryInfo` +-- + +CREATE TABLE `FactoryInfo` ( + `factory_id` int(11) NOT NULL, + `factory_name` varchar(255) NOT NULL, + `address` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `map_image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `FactoryInfo` +-- + +INSERT INTO `FactoryInfo` (`factory_id`, `factory_name`, `address`, `description`, `map_image_url`, `created_at`, `updated_at`) VALUES +(3, '제1공장 휴게공간 및 작업자 사물함', '현대기아로 771-9', '개인 보관함, 컨테이너(휴게공간), 화장실, 흡연장', '/uploads/map_image-1746593523450.png', '2025-05-07 04:52:03', '2025-05-07 04:52:03'), +(4, '제 1공장 공구 및 용접봉 보관 구역', '현대기아로 771-9', '소모품, 공구류, 용접봉 보관 구역', '/uploads/map_image-1746593674259.png', '2025-05-07 04:53:59', '2025-05-07 04:53:59'), +(5, 'ee', 'ee', 'ee', NULL, '2025-06-03 22:13:23', '2025-06-03 22:13:23'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `IssueTypes` +-- + +CREATE TABLE `IssueTypes` ( + `issue_type_id` int(11) NOT NULL, + `category` varchar(100) NOT NULL, + `subcategory` varchar(100) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `IssueTypes` +-- + +INSERT INTO `IssueTypes` (`issue_type_id`, `category`, `subcategory`) VALUES +(1, '구매팀', '자재입고지연'), +(2, '구매팀', '자재전달 미흡'), +(3, '품질', '검사 내용 전달 미흡'), +(4, '품질', '검사오류'), +(5, '설계', '설계미스(치수)'), +(6, '설계', '설계미스(작업불가)'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `login_logs` +-- + +CREATE TABLE `login_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `login_time` datetime DEFAULT current_timestamp(), + `logout_time` datetime DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `login_status` enum('success','failed','locked') DEFAULT 'success', + `failure_reason` varchar(100) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `login_logs` +-- + +INSERT INTO `login_logs` (`log_id`, `user_id`, `login_time`, `logout_time`, `ip_address`, `user_agent`, `login_status`, `failure_reason`) VALUES +(1, 3, '2025-06-15 05:58:39', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(3, 4, '2025-06-15 06:04:06', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(4, 3, '2025-06-15 06:24:53', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(5, 3, '2025-06-15 06:24:55', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(6, 3, '2025-06-15 06:32:41', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(7, 3, '2025-06-15 07:03:19', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(8, 3, '2025-06-15 07:03:21', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(9, 3, '2025-06-15 07:03:25', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(10, 1, '2025-06-15 07:40:16', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(11, 6, '2025-06-15 07:42:02', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(12, 3, '2025-06-15 07:43:30', NULL, '118.235.6.135', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(13, 3, '2025-06-15 22:02:59', NULL, '118.235.6.29', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(14, 4, '2025-06-15 22:15:25', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(15, 3, '2025-06-15 22:15:34', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(16, 6, '2025-06-15 22:15:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'failed', 'invalid_password'), +(17, 6, '2025-06-15 22:15:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(18, 3, '2025-06-15 22:16:39', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(19, 3, '2025-06-15 22:17:14', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(20, 6, '2025-06-15 22:21:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(21, 1, '2025-06-15 22:21:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(22, 6, '2025-06-15 22:22:06', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(23, 5, '2025-06-15 22:22:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(24, 6, '2025-06-15 22:23:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(25, 3, '2025-06-15 22:24:49', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(26, 3, '2025-06-15 22:30:18', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(27, 3, '2025-06-15 22:31:21', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(28, 5, '2025-06-15 22:44:31', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(29, 4, '2025-06-15 22:57:51', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(30, 4, '2025-06-15 22:57:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(31, 4, '2025-06-15 22:57:54', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(32, 4, '2025-06-15 22:57:55', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(33, 4, '2025-06-15 23:11:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(34, 4, '2025-06-15 23:28:04', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(35, 3, '2025-06-15 23:33:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(36, 3, '2025-06-16 00:58:53', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(37, 3, '2025-06-16 01:15:46', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(38, 5, '2025-06-16 01:16:43', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(39, 1, '2025-06-16 01:25:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(40, 1, '2025-06-16 01:26:08', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(41, 3, '2025-06-16 02:27:20', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(42, 3, '2025-06-16 02:45:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(43, 3, '2025-06-16 03:04:13', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(44, 3, '2025-06-16 03:17:28', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(45, 5, '2025-06-16 03:17:55', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(46, 3, '2025-06-16 03:18:56', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(47, 5, '2025-06-16 03:19:13', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(48, 1, '2025-06-16 03:55:56', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(49, 1, '2025-06-16 04:24:37', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(50, 1, '2025-06-16 04:51:36', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(51, 1, '2025-06-16 05:07:05', NULL, '118.235.7.233', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(52, 1, '2025-06-16 05:07:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(53, 1, '2025-06-16 05:43:14', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(54, 5, '2025-06-16 06:11:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(55, 1, '2025-06-16 06:19:46', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(56, 1, '2025-06-16 06:23:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(57, 1, '2025-06-16 06:39:12', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(58, 3, '2025-06-16 06:45:26', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(59, 6, '2025-06-16 06:46:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(60, 1, '2025-06-16 21:18:09', NULL, '118.235.7.45', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(61, 1, '2025-06-17 08:15:45', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(62, 5, '2025-06-17 08:22:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(63, 3, '2025-06-17 08:23:05', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'failed', 'invalid_password'), +(64, 3, '2025-06-17 08:23:21', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(65, 3, '2025-06-17 08:28:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(66, 3, '2025-06-17 08:32:25', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(67, 6, '2025-06-17 08:33:07', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(68, 1, '2025-06-17 08:36:01', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(69, 5, '2025-06-17 09:00:56', NULL, '118.235.7.173', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(70, 3, '2025-06-18 02:30:13', NULL, '118.235.6.77', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(71, 1, '2025-06-18 08:07:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(72, 1, '2025-06-18 08:07:47', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(73, 5, '2025-06-18 08:39:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(74, 6, '2025-06-18 08:46:53', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(75, 3, '2025-06-18 08:47:03', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(76, 6, '2025-06-18 08:57:48', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(77, 5, '2025-06-18 08:58:14', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(78, 3, '2025-06-18 08:59:12', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(79, 5, '2025-06-19 06:37:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(80, 3, '2025-06-19 06:57:01', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(81, 6, '2025-06-19 06:57:22', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(82, 5, '2025-06-19 06:57:56', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(83, 6, '2025-06-19 06:58:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(84, 3, '2025-06-19 06:59:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(85, 3, '2025-06-20 06:42:26', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(86, 6, '2025-06-20 06:45:06', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(87, 5, '2025-06-20 06:49:26', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(88, 3, '2025-06-20 06:49:47', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(89, 6, '2025-06-20 06:50:17', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(90, 3, '2025-06-20 22:46:20', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(91, 1, '2025-06-23 05:03:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(92, 6, '2025-06-23 06:41:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(93, 3, '2025-06-23 06:49:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(94, 6, '2025-06-23 06:50:01', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(95, 5, '2025-06-23 06:50:28', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(96, 1, '2025-06-24 05:24:17', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(97, 3, '2025-06-24 05:25:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(98, 1, '2025-06-24 09:22:29', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(99, 3, '2025-06-24 11:09:38', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(100, 6, '2025-06-24 11:09:48', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(101, 5, '2025-06-24 11:10:23', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(102, 3, '2025-06-24 11:11:29', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(103, 5, '2025-06-24 11:12:06', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(104, 6, '2025-06-24 11:12:31', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(105, 3, '2025-06-24 21:41:01', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(106, 3, '2025-06-25 04:40:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(107, 3, '2025-06-25 05:24:57', NULL, '118.235.6.179', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(108, 1, '2025-06-25 07:05:20', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(109, 1, '2025-06-25 07:06:41', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(110, 3, '2025-06-25 07:09:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(111, 3, '2025-06-25 08:49:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(112, 3, '2025-06-25 09:20:05', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(113, 3, '2025-06-25 09:40:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(114, 3, '2025-06-25 09:57:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(115, 1, '2025-06-25 10:11:03', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(116, 1, '2025-06-25 10:26:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(117, 1, '2025-06-25 10:49:29', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(118, 5, '2025-06-25 11:07:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(119, 6, '2025-06-25 11:10:41', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(120, 6, '2025-06-25 11:13:55', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(121, 5, '2025-06-25 11:14:25', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(122, 6, '2025-06-25 11:20:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(123, 1, '2025-06-25 11:24:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(124, 3, '2025-06-26 10:27:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(125, 5, '2025-06-26 11:10:47', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(126, 6, '2025-06-26 11:15:57', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(127, 3, '2025-06-26 11:17:07', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(128, 5, '2025-06-26 11:17:40', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(129, 6, '2025-06-26 11:19:00', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(130, 1, '2025-06-26 22:15:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(131, 1, '2025-06-26 22:31:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(132, 1, '2025-06-26 22:47:22', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(133, 5, '2025-06-27 01:52:48', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(134, 5, '2025-06-27 01:53:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(135, 3, '2025-06-27 06:47:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(136, 6, '2025-06-27 06:48:39', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(137, 3, '2025-06-27 06:57:15', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(138, 5, '2025-06-27 06:57:34', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(139, 6, '2025-06-27 06:57:59', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(140, 3, '2025-06-27 06:59:04', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(141, 5, '2025-06-27 06:59:29', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `password_change_logs` +-- + +CREATE TABLE `password_change_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) NOT NULL, + `changed_by_user_id` int(11) DEFAULT NULL, + `changed_at` datetime DEFAULT current_timestamp(), + `change_type` enum('self','admin','reset','initial') DEFAULT 'self', + `ip_address` varchar(45) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `password_change_logs` +-- + +INSERT INTO `password_change_logs` (`log_id`, `user_id`, `changed_by_user_id`, `changed_at`, `change_type`, `ip_address`) VALUES +(1, 4, NULL, '2025-06-15 06:03:42', 'admin', NULL), +(2, 3, NULL, '2025-06-15 06:03:52', 'admin', NULL), +(3, 3, 3, '2025-06-15 06:32:30', 'self', NULL), +(4, 3, 1, '2025-06-15 07:40:39', 'admin', NULL), +(5, 5, 1, '2025-06-15 07:41:02', 'initial', NULL), +(6, 6, 1, '2025-06-15 07:41:32', 'initial', NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `PipeSpecs` +-- + +CREATE TABLE `PipeSpecs` ( + `spec_id` int(11) NOT NULL, + `material` varchar(50) NOT NULL COMMENT '재질 (예: SS400, STS304)', + `diameter_in` varchar(10) NOT NULL COMMENT '직경 (inch, 예: 2")', + `schedule` varchar(50) NOT NULL COMMENT '스케줄 (예: STD, SCH10, SCH40)' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `PipeSpecs` +-- + +INSERT INTO `PipeSpecs` (`spec_id`, `material`, `diameter_in`, `schedule`) VALUES +(2, '516-70N', '1', 'SCH80'), +(1, 'A106', '3/4', 'SCH80'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Processes` +-- + +CREATE TABLE `Processes` ( + `process_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `process_name` varchar(255) NOT NULL, + `process_start` date NOT NULL, + `process_end` date DEFAULT NULL, + `planned_worker_count` int(11) NOT NULL, + `process_description` text DEFAULT NULL, + `note` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Projects` +-- + +CREATE TABLE `Projects` ( + `project_id` int(11) NOT NULL, + `job_no` varchar(50) NOT NULL, + `project_name` varchar(255) NOT NULL, + `contract_date` date DEFAULT NULL, + `due_date` date DEFAULT NULL, + `delivery_method` varchar(100) DEFAULT NULL, + `site` varchar(100) DEFAULT NULL, + `pm` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Projects` +-- + +INSERT INTO `Projects` (`project_id`, `job_no`, `project_name`, `contract_date`, `due_date`, `delivery_method`, `site`, `pm`, `created_at`, `updated_at`) VALUES +(1, 'TKO-24008P', 'YHP Project', '2024-05-16', '2025-05-16', 'FOB', 'Quang Ninh(Vietnam)', '장형태', '2025-04-15 22:40:28', '2025-04-15 22:40:28'), +(2, 'TKG-24009P', '한화에어로스페이스 순천', '2024-06-05', '2025-05-31', '.', '순천', '장형태', '2025-04-15 22:42:41', '2025-04-15 22:42:41'), +(3, 'TKG-24011P', '효성화학 에틸렌 탱크 건설공사', '2024-06-22', '2025-12-25', '.', '울산', '김길종', '2025-04-15 22:43:53', '2025-04-15 22:43:53'), +(4, 'TKG-24013P', '김천 솔라 파워 그린 수소 Project', '2024-10-08', '2025-07-25', '.', '김천', '김길종', '2025-04-15 22:44:57', '2025-04-15 22:44:57'), +(5, 'TKG-24016P', 'LG Chem P3RE Project', '2024-11-27', '2025-09-30', '.', '.', '장형태', '2025-04-15 22:46:36', '2025-04-15 22:46:36'), +(7, 'TKO-25003F', '25년 안전보건시설설비', '2025-01-03', '2025-12-31', '.', '.', '.', '2025-04-15 22:47:32', '2025-04-15 22:47:32'), +(8, 'TKG-25007P', 'P Project', '2025-01-16', '2025-10-31', '.', '오창읍', '장형태', '2025-04-15 22:48:50', '2025-04-15 22:48:50'), +(10, 'TKR-25008P', 'DIG Airgas LG CHEM', '2025-01-23', '2025-10-15', '.', '여수', '서태원', '2025-04-15 22:50:05', '2025-04-15 22:50:05'), +(11, 'TKR-25010P', 'FK FISCHER Project', '2025-03-12', '2025-11-30', '.', '울산', '전상신', '2025-04-15 22:51:12', '2025-04-15 22:51:12'), +(12, 'TKO-24007P', 'MP7 Project', '2024-07-03', '2025-01-05', '.', '.', '윤지민', '2025-04-15 23:56:26', '2025-04-15 23:56:26'), +(13, '연차/휴무', '연차/휴무', '2025-01-01', '2025-12-31', '.', '.', '.', '2025-04-16 01:58:23', '2025-04-16 01:58:23'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Tasks` +-- + +CREATE TABLE `Tasks` ( + `task_id` int(11) NOT NULL, + `category` varchar(255) NOT NULL, + `subcategory` varchar(255) DEFAULT NULL, + `task_name` varchar(255) NOT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Tasks` +-- + +INSERT INTO `Tasks` (`task_id`, `category`, `subcategory`, `task_name`, `description`, `created_at`, `updated_at`) VALUES +(1, 'Base', 'Fabrication', '용접', '...', '2025-04-15 10:41:43', '2025-04-15 10:41:43'), +(3, 'Vessel', 'MI and Marking', 'Marking', '..', '2025-04-15 22:25:58', '2025-04-15 22:25:58'), +(4, 'Vessel', 'Cutting', '자재 커팅', '..', '2025-04-15 22:26:17', '2025-04-15 22:26:17'), +(5, 'Vessel', 'Fabrication', '용접', '..', '2025-04-15 22:26:43', '2025-04-15 22:26:43'), +(7, 'PKG', 'Pipe Pre-Fabrication', '취부&용접', '배관사 1명\n용접사 1명', '2025-04-15 22:37:14', '2025-04-15 22:37:14'), +(8, 'PKG', '1st Piping Assembly', '1차 조립', '.', '2025-04-15 22:38:49', '2025-04-15 22:38:49'), +(9, 'PKG', 'Re-Assembly', '재조립', '.', '2025-04-15 22:39:18', '2025-04-15 22:39:18'), +(13, '작업지원', '구매팀', '.', '.', '2025-04-16 03:03:40', '2025-04-16 03:03:40'), +(14, '기타', '시설설비제작', '.', '.', '2025-04-16 03:30:53', '2025-04-16 03:30:53'), +(15, '기타', '휴가/연차/휴무', '.', '.', '2025-04-16 05:18:13', '2025-04-16 05:18:13'), +(16, 'PKG', '제품설치', '설치작업', 'Skid, 용기 등 설치', '2025-04-29 04:39:36', '2025-04-29 04:39:36'), +(18, '작업지원', '품질팀', 'test지원', '.', '2025-06-25 07:07:08', '2025-06-25 07:07:08'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `uploaded_documents` +-- + +CREATE TABLE `uploaded_documents` ( + `id` int(11) NOT NULL, + `title` varchar(255) NOT NULL, + `tags` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `original_name` varchar(255) DEFAULT NULL, + `stored_name` varchar(255) NOT NULL, + `file_path` varchar(500) DEFAULT NULL, + `file_type` varchar(50) DEFAULT NULL, + `file_size` int(11) DEFAULT NULL, + `submitted_by` varchar(100) DEFAULT NULL, + `dt_imported` tinyint(1) DEFAULT 0, + `dt_uuid` varchar(100) DEFAULT NULL, + `of_task_created` tinyint(1) DEFAULT 0, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Users` +-- + +CREATE TABLE `Users` ( + `user_id` int(11) NOT NULL, + `username` varchar(100) NOT NULL, + `password` varchar(255) NOT NULL, + `role` varchar(30) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `access_level` varchar(30) DEFAULT NULL, + `worker_id` int(11) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `last_login_at` datetime DEFAULT NULL, + `password_changed_at` datetime DEFAULT NULL, + `failed_login_attempts` int(11) DEFAULT 0, + `locked_until` datetime DEFAULT NULL, + `name` varchar(50) DEFAULT NULL, + `email` varchar(255) DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Users` +-- + +INSERT INTO `Users` (`user_id`, `username`, `password`, `role`, `created_at`, `access_level`, `worker_id`, `is_active`, `last_login_at`, `password_changed_at`, `failed_login_attempts`, `locked_until`, `name`, `email`, `updated_at`) VALUES +(1, 'hyungi', '$2b$10$lwSfKipx0fQ.9nfMUBmzt.WXzerdxuT5MVX4b3YhFeHxyYlUjM7bi', 'admin', '2025-05-06 05:03:02', 'system', NULL, 1, '2025-06-26 22:47:22', '2025-05-06 05:03:02', 0, NULL, NULL, NULL, '2025-06-26 22:47:22'), +(3, '김두수', '$2a$10$z3i2EVOotRFBj.KHzx5LQOKlXD0QHLNFEvJcd6FlO6/1TCYGk6SSu', 'leader', '2025-06-07 23:48:35', 'group_leader', 1, 1, '2025-06-27 06:59:04', '2025-06-15 07:40:39', 0, NULL, '김두수', NULL, '2025-06-27 06:59:04'), +(4, '김아무개', '$2a$10$QAJIoPyi.apz91exp8GsiO/prAD5Xwanht6XImP1jvKsy/7Ba/b8.', 'user', '2025-06-11 08:03:59', 'worker', NULL, 1, '2025-06-15 23:28:04', '2025-06-15 06:03:42', 0, NULL, '김아무개', NULL, '2025-06-15 23:28:04'), +(5, '임영규', '$2a$10$66ps/MEEi4BVABfJc5P0y.yCap09NhTMyd1A/7rFVxESytQGlB3wC', NULL, '2025-06-15 07:41:02', 'group_leader', 3, 1, '2025-06-27 06:59:29', '2025-06-15 07:41:02', 0, NULL, '임영규', NULL, '2025-06-27 06:59:29'), +(6, '반치원', '$2a$10$jcn6f7flRLZlr5yKQcXDIePodRK0rsM4deNnNGjuOlredeTVsRYZ6', NULL, '2025-06-15 07:41:32', 'group_leader', 3, 1, '2025-06-27 06:57:59', '2025-06-15 07:41:32', 0, NULL, '반치원', NULL, '2025-06-27 06:57:59'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Workers` +-- + +CREATE TABLE `Workers` ( + `worker_id` int(11) NOT NULL, + `worker_name` varchar(100) NOT NULL, + `join_date` date DEFAULT NULL, + `job_type` varchar(100) DEFAULT NULL, + `salary` decimal(10,2) DEFAULT NULL, + `annual_leave` int(11) DEFAULT NULL, + `status` text DEFAULT 'active', + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Workers` +-- + +INSERT INTO `Workers` (`worker_id`, `worker_name`, `join_date`, `job_type`, `salary`, `annual_leave`, `status`, `created_at`, `updated_at`) VALUES +(1, '김두수', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:08', '2025-04-15 22:23:08'), +(2, '임영규', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:17', '2025-04-15 22:23:17'), +(3, '반치원', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:22', '2025-04-15 22:23:22'), +(4, '황인용', '2025-04-01', '가공,조공', 220000.00, 15, '..', '2025-04-15 22:23:33', '2025-04-15 22:23:33'), +(5, '표영진', '2025-04-01', '가공,조공', 220000.00, 15, '..', '2025-04-15 22:23:38', '2025-04-15 22:23:38'), +(6, '김윤섭', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:23:46', '2025-04-15 22:23:46'), +(7, '이창호', '2025-04-01', '용접,배관', 220000.00, 15, '..', '2025-04-15 22:23:51', '2025-04-15 22:23:51'), +(8, '최광욱', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:23:57', '2025-04-15 22:23:57'), +(9, '박현수', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:24:01', '2025-04-15 22:24:01'), +(10, '조윤호', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:24:07', '2025-04-15 22:24:07'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `worker_groups` +-- + +CREATE TABLE `worker_groups` ( + `id` int(11) NOT NULL, + `group_leader_id` int(11) NOT NULL, + `worker_id` int(11) NOT NULL, + `group_name` varchar(100) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `WorkReports` +-- + +CREATE TABLE `WorkReports` ( + `id` int(11) NOT NULL, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `morning_task_id` int(11) DEFAULT NULL, + `afternoon_task_id` int(11) DEFAULT NULL, + `overtime_hours` decimal(4,1) DEFAULT 0.0, + `overtime_task_id` int(11) DEFAULT NULL, + `work_details` text DEFAULT NULL, + `note` text DEFAULT NULL, + `memo` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `morning_project_id` int(11) DEFAULT NULL, + `afternoon_project_id` int(11) DEFAULT NULL, + `overtime_project_id` int(11) DEFAULT NULL, + `task_id` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `WorkReports` +-- + +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(176, '2025-01-02', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(177, '2025-01-02', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(178, '2025-01-02', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(179, '2025-01-02', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(180, '2025-01-02', 8, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(181, '2025-01-02', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(182, '2025-01-02', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(183, '2025-01-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 15), +(194, '2025-01-03', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(195, '2025-01-03', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(196, '2025-01-03', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 15), +(197, '2025-01-03', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(198, '2025-01-03', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 15), +(199, '2025-01-03', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(200, '2025-01-03', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(201, '2025-01-03', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(202, '2025-01-03', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(203, '2025-01-04', 7, 12, NULL, NULL, NULL, NULL, '휴일근무', NULL, NULL, '2025-04-16 05:43:25', '2025-04-16 05:43:25', NULL, NULL, NULL, 12), +(204, '2025-01-06', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:03', '2025-04-16 05:44:03', NULL, NULL, NULL, 12), +(205, '2025-01-06', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:03', '2025-04-16 05:44:03', NULL, NULL, NULL, 12), +(206, '2025-01-06', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(207, '2025-01-06', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(208, '2025-01-06', 8, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(209, '2025-01-06', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(210, '2025-01-06', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(211, '2025-01-06', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(212, '2025-01-06', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(213, '2025-01-07', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(214, '2025-01-07', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 1), +(215, '2025-01-07', 3, 12, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(216, '2025-01-07', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(217, '2025-01-07', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 1), +(218, '2025-01-07', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(219, '2025-01-07', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(220, '2025-01-07', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:25', '2025-04-16 05:45:25', NULL, NULL, NULL, 12), +(221, '2025-01-07', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:25', '2025-04-16 05:45:25', NULL, NULL, NULL, 1), +(222, '2025-01-08', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(223, '2025-01-08', 2, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(224, '2025-01-08', 3, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(225, '2025-01-08', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(226, '2025-01-08', 8, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(227, '2025-01-08', 9, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(228, '2025-01-08', 6, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(229, '2025-01-08', 4, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(230, '2025-01-08', 5, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(231, '2025-01-09', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(232, '2025-01-09', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(233, '2025-01-09', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(234, '2025-01-09', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(235, '2025-01-09', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(236, '2025-01-09', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(237, '2025-01-09', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(238, '2025-01-09', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(239, '2025-01-09', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(240, '2025-01-10', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:16', '2025-04-16 05:49:16', NULL, NULL, NULL, 13), +(241, '2025-01-10', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(242, '2025-01-10', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(243, '2025-01-10', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(244, '2025-01-10', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(245, '2025-01-10', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(246, '2025-01-10', 6, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 15), +(247, '2025-01-10', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(248, '2025-01-10', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(249, '2025-01-13', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(250, '2025-01-13', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(251, '2025-01-13', 3, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(252, '2025-01-13', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(253, '2025-01-13', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(254, '2025-01-13', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(255, '2025-01-13', 6, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(256, '2025-01-13', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 15), +(257, '2025-01-13', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(258, '2025-01-14', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(259, '2025-01-14', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(260, '2025-01-14', 3, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(261, '2025-01-14', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(262, '2025-01-14', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(263, '2025-01-14', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(265, '2025-01-14', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(266, '2025-01-14', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(267, '2025-01-14', 6, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(268, '2025-01-15', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(269, '2025-01-15', 2, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 14), +(270, '2025-01-15', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(271, '2025-01-15', 7, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 13), +(272, '2025-01-15', 8, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 14), +(273, '2025-01-15', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(275, '2025-01-15', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(276, '2025-01-15', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:38', '2025-04-16 05:52:38', NULL, NULL, NULL, 1), +(277, '2025-01-15', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:38', '2025-04-16 05:52:38', NULL, NULL, NULL, 1), +(278, '2025-01-16', 1, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(279, '2025-01-16', 2, 7, NULL, NULL, NULL, NULL, '근무', NULL, '볼트 보관함 제작', '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 14), +(280, '2025-01-16', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(281, '2025-01-16', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(282, '2025-01-16', 8, 7, NULL, NULL, NULL, NULL, '근무', NULL, '볼트 보관함 제작', '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 14), +(283, '2025-01-16', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(285, '2025-01-16', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(286, '2025-01-16', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(287, '2025-01-16', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(288, '2025-01-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(289, '2025-01-17', 2, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(290, '2025-01-17', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(291, '2025-01-17', 7, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(292, '2025-01-17', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(293, '2025-01-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(295, '2025-01-17', 4, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(296, '2025-01-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(297, '2025-01-17', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(298, '2025-01-20', 1, 7, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(299, '2025-01-20', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 8), +(300, '2025-01-20', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(301, '2025-01-20', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(302, '2025-01-20', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(303, '2025-01-20', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(304, '2025-01-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(305, '2025-01-20', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(306, '2025-01-20', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(307, '2025-01-21', 1, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 15), +(308, '2025-01-21', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 8), +(309, '2025-01-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(310, '2025-01-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(311, '2025-01-21', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 8), +(312, '2025-01-21', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 15), +(313, '2025-01-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(314, '2025-01-21', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(315, '2025-01-21', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:07', '2025-04-16 05:59:07', NULL, NULL, NULL, 1), +(316, '2025-01-22', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(317, '2025-01-22', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(318, '2025-01-22', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(319, '2025-01-22', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(320, '2025-01-22', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(321, '2025-01-22', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(322, '2025-01-22', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(323, '2025-01-22', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(324, '2025-01-22', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(325, '2025-01-23', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(326, '2025-01-23', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 8), +(327, '2025-01-23', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(328, '2025-01-23', 7, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(329, '2025-01-23', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(330, '2025-01-23', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(331, '2025-01-23', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(332, '2025-01-23', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(333, '2025-01-23', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 8), +(334, '2025-01-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(335, '2025-01-24', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 8), +(336, '2025-01-24', 3, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(337, '2025-01-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(338, '2025-01-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(339, '2025-01-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(340, '2025-01-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(341, '2025-01-24', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 8), +(342, '2025-01-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(343, '2025-02-03', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(344, '2025-02-03', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 8), +(345, '2025-02-03', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(346, '2025-02-03', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(347, '2025-02-03', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(348, '2025-02-03', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(349, '2025-02-03', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(350, '2025-02-03', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 8), +(351, '2025-02-03', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(352, '2025-02-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(353, '2025-02-04', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(354, '2025-02-04', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 8), +(355, '2025-02-04', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(356, '2025-02-04', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(357, '2025-02-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(358, '2025-02-04', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(359, '2025-02-04', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 8), +(360, '2025-02-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(361, '2025-02-05', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 8), +(362, '2025-02-05', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(363, '2025-02-05', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(364, '2025-02-05', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(365, '2025-02-05', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(366, '2025-02-05', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(367, '2025-02-05', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 1), +(368, '2025-02-05', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 8), +(369, '2025-02-05', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 1), +(370, '2025-02-06', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(371, '2025-02-06', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 15), +(372, '2025-02-06', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(373, '2025-02-06', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(374, '2025-02-06', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(375, '2025-02-06', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(376, '2025-02-06', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(377, '2025-02-06', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(378, '2025-02-06', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(379, '2025-02-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(380, '2025-02-07', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 8), +(381, '2025-02-07', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(382, '2025-02-07', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 15), +(383, '2025-02-07', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(384, '2025-02-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(385, '2025-02-07', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(386, '2025-02-07', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 8), +(387, '2025-02-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(388, '2025-02-10', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(389, '2025-02-10', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 8), +(390, '2025-02-10', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(391, '2025-02-10', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(392, '2025-02-10', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(393, '2025-02-10', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(394, '2025-02-10', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(395, '2025-02-10', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 8), +(396, '2025-02-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(397, '2025-02-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(398, '2025-02-11', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 8), +(399, '2025-02-11', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(400, '2025-02-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(401, '2025-02-11', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(402, '2025-02-11', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(403, '2025-02-11', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(404, '2025-02-11', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 8), +(405, '2025-02-11', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(406, '2025-02-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(407, '2025-02-12', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 8), +(408, '2025-02-12', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(409, '2025-02-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(410, '2025-02-12', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(411, '2025-02-12', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(412, '2025-02-12', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 15), +(413, '2025-02-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(414, '2025-02-12', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(415, '2025-02-13', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(416, '2025-02-13', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 7), +(417, '2025-02-13', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(418, '2025-02-13', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(419, '2025-02-13', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(420, '2025-02-13', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(421, '2025-02-13', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(422, '2025-02-13', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 7), +(423, '2025-02-13', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(424, '2025-02-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(425, '2025-02-14', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 7), +(426, '2025-02-14', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(427, '2025-02-14', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(428, '2025-02-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(429, '2025-02-14', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(430, '2025-02-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(431, '2025-02-14', 4, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 7), +(432, '2025-02-14', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(433, '2025-02-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:39', '2025-04-16 06:18:39', NULL, NULL, NULL, 1), +(434, '2025-02-17', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 8), +(435, '2025-02-17', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(436, '2025-02-17', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(437, '2025-02-17', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 15), +(438, '2025-02-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(439, '2025-02-17', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(440, '2025-02-17', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 8), +(441, '2025-02-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(442, '2025-02-18', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(443, '2025-02-18', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 15), +(444, '2025-02-18', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(445, '2025-02-18', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(446, '2025-02-18', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(447, '2025-02-18', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(448, '2025-02-18', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 7), +(449, '2025-02-18', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(450, '2025-02-18', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(451, '2025-02-19', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(452, '2025-02-19', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(453, '2025-02-19', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(454, '2025-02-19', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(455, '2025-02-19', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(456, '2025-02-19', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(457, '2025-02-19', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(458, '2025-02-19', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(459, '2025-02-19', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(460, '2025-02-20', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(461, '2025-02-20', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(462, '2025-02-20', 3, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(463, '2025-02-20', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(464, '2025-02-20', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(465, '2025-02-20', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(466, '2025-02-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(467, '2025-02-20', 7, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(468, '2025-02-20', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(469, '2025-02-21', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(470, '2025-02-21', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(471, '2025-02-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(472, '2025-02-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(473, '2025-02-21', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(474, '2025-02-21', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(475, '2025-02-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(476, '2025-02-21', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(477, '2025-02-21', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(478, '2025-02-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(479, '2025-02-24', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(480, '2025-02-24', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(481, '2025-02-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(482, '2025-02-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(483, '2025-02-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(484, '2025-02-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(485, '2025-02-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(486, '2025-02-24', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:33', '2025-04-16 06:24:33', NULL, NULL, NULL, 7), +(487, '2025-02-24', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, '근무시작', '2025-04-16 06:25:07', '2025-04-16 06:25:07', NULL, NULL, NULL, 7), +(488, '2025-02-25', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(489, '2025-02-25', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(490, '2025-02-25', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(491, '2025-02-25', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(492, '2025-02-25', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(493, '2025-02-25', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(494, '2025-02-25', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(495, '2025-02-25', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(496, '2025-02-25', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(497, '2025-02-25', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(498, '2025-02-26', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '당진출장 건', '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 14), +(499, '2025-02-26', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(500, '2025-02-26', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(501, '2025-02-26', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '당진출장 건', '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 14), +(502, '2025-02-26', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(503, '2025-02-26', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(504, '2025-02-26', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(505, '2025-02-26', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 15), +(506, '2025-02-26', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(507, '2025-02-26', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(508, '2025-02-27', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(509, '2025-02-27', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(510, '2025-02-27', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(511, '2025-02-27', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(512, '2025-02-27', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(513, '2025-02-27', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(514, '2025-02-27', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(515, '2025-02-27', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(516, '2025-02-27', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(517, '2025-02-27', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(518, '2025-02-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 13), +(519, '2025-02-28', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(520, '2025-02-28', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(521, '2025-02-28', 7, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 13), +(522, '2025-02-28', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(523, '2025-02-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(524, '2025-02-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(525, '2025-02-28', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(526, '2025-02-28', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 15), +(527, '2025-02-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(528, '2025-03-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(529, '2025-03-04', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(530, '2025-03-04', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 8), +(531, '2025-03-04', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 15), +(532, '2025-03-04', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(533, '2025-03-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(534, '2025-03-04', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(535, '2025-03-04', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(536, '2025-03-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(537, '2025-03-04', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 8), +(538, '2025-03-05', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(539, '2025-03-05', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(540, '2025-03-05', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 8), +(541, '2025-03-05', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(542, '2025-03-05', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(543, '2025-03-05', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(544, '2025-03-05', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(545, '2025-03-05', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 15), +(546, '2025-03-05', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(547, '2025-03-05', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 8), +(548, '2025-03-06', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(549, '2025-03-06', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(550, '2025-03-06', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 8), +(551, '2025-03-06', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 15), +(552, '2025-03-06', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(553, '2025-03-06', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(554, '2025-03-06', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(555, '2025-03-06', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(556, '2025-03-06', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(557, '2025-03-06', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 8), +(558, '2025-03-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(559, '2025-03-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 13), +(560, '2025-03-07', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 8), +(561, '2025-03-07', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 15), +(562, '2025-03-07', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(563, '2025-03-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(564, '2025-03-07', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(565, '2025-03-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 13), +(566, '2025-03-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(567, '2025-03-07', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 8), +(568, '2025-03-10', 1, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(569, '2025-03-10', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 3), +(570, '2025-03-10', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(571, '2025-03-10', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 15), +(572, '2025-03-10', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 7), +(573, '2025-03-10', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 15), +(574, '2025-03-10', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 7), +(575, '2025-03-10', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 3), +(576, '2025-03-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(577, '2025-03-10', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(578, '2025-03-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:06', '2025-04-16 06:39:06', NULL, NULL, NULL, 8), +(579, '2025-03-11', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(580, '2025-03-11', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(581, '2025-03-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(582, '2025-03-11', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(583, '2025-03-11', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 15), +(584, '2025-03-11', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(585, '2025-03-11', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(586, '2025-03-11', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(587, '2025-03-11', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(588, '2025-03-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(589, '2025-03-12', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(590, '2025-03-12', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(591, '2025-03-12', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(592, '2025-03-12', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(593, '2025-03-12', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 15), +(594, '2025-03-12', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(595, '2025-03-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(596, '2025-03-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(597, '2025-03-12', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(598, '2025-03-13', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(599, '2025-03-13', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(600, '2025-03-13', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(601, '2025-03-13', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(602, '2025-03-13', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(603, '2025-03-13', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 15), +(604, '2025-03-13', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(605, '2025-03-13', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(606, '2025-03-13', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(607, '2025-03-13', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(608, '2025-03-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(609, '2025-03-14', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 4), +(610, '2025-03-14', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(612, '2025-03-14', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(613, '2025-03-14', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 15), +(614, '2025-03-14', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(615, '2025-03-14', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(616, '2025-03-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(617, '2025-03-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(628, '2025-03-18', 1, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(629, '2025-03-18', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(630, '2025-03-18', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(631, '2025-03-18', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(632, '2025-03-18', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(633, '2025-03-18', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 15), +(634, '2025-03-18', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(635, '2025-03-18', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(636, '2025-03-18', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(637, '2025-03-18', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(648, '2025-03-17', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(649, '2025-03-17', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 4), +(650, '2025-03-17', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(651, '2025-03-17', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 4), +(652, '2025-03-17', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(653, '2025-03-17', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 15), +(654, '2025-03-17', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(655, '2025-03-17', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(656, '2025-03-17', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(657, '2025-03-17', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(658, '2025-03-19', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 4), +(659, '2025-03-19', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(660, '2025-03-19', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(661, '2025-03-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 4), +(662, '2025-03-19', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(663, '2025-03-19', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(664, '2025-03-19', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(665, '2025-03-19', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, '용접기 보관함 제작', '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 14), +(666, '2025-03-19', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 4), +(667, '2025-03-19', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(668, '2025-03-20', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(669, '2025-03-20', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(670, '2025-03-20', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(671, '2025-03-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(672, '2025-03-20', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(673, '2025-03-20', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(674, '2025-03-20', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(675, '2025-03-20', 4, 7, NULL, NULL, 2.0, NULL, '근무', NULL, '용접기 보관함 제작', '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 14), +(676, '2025-03-20', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(677, '2025-03-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(678, '2025-03-21', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:27', '2025-04-16 21:34:27', NULL, NULL, NULL, 8), +(679, '2025-03-21', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(680, '2025-03-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(681, '2025-03-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(682, '2025-03-21', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(683, '2025-03-21', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(684, '2025-03-21', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(685, '2025-03-21', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, '용기 보관함 제작', '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 14), +(686, '2025-03-21', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(687, '2025-03-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(688, '2025-03-24', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(689, '2025-03-24', 2, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(690, '2025-03-24', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(691, '2025-03-24', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(692, '2025-03-24', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(693, '2025-03-24', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(694, '2025-03-24', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(695, '2025-03-24', 4, 7, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 보관함 제작', '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 14), +(696, '2025-03-24', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(697, '2025-03-24', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(698, '2025-03-25', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(699, '2025-03-25', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(700, '2025-03-25', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(701, '2025-03-25', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(702, '2025-03-25', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(703, '2025-03-25', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(704, '2025-03-25', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(705, '2025-03-25', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 14), +(706, '2025-03-25', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(707, '2025-03-25', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(708, '2025-03-26', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 13), +(709, '2025-03-26', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 15), +(710, '2025-03-26', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(711, '2025-03-26', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(712, '2025-03-26', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(713, '2025-03-26', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(714, '2025-03-26', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(715, '2025-03-26', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 13), +(716, '2025-03-26', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(717, '2025-03-26', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(718, '2025-03-27', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(719, '2025-03-27', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(720, '2025-03-27', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(721, '2025-03-27', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(722, '2025-03-27', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(723, '2025-03-27', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(724, '2025-03-27', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 15), +(725, '2025-03-27', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(726, '2025-03-27', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(727, '2025-03-27', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(728, '2025-03-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(729, '2025-03-28', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(730, '2025-03-28', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 15), +(731, '2025-03-28', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 15), +(732, '2025-03-28', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(733, '2025-03-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(734, '2025-03-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(735, '2025-03-28', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(736, '2025-03-28', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(737, '2025-03-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(738, '2025-03-31', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(739, '2025-03-31', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 5), +(740, '2025-03-31', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(741, '2025-03-31', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(742, '2025-03-31', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(743, '2025-03-31', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(744, '2025-03-31', 10, 13, NULL, NULL, NULL, NULL, '유급', NULL, '외조모상(2일)', '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 15), +(745, '2025-03-31', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 5), +(746, '2025-03-31', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(747, '2025-03-31', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(748, '2025-03-14', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-17 01:53:24', '2025-04-17 01:53:24', NULL, NULL, NULL, 4), +(749, '2025-04-01', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(750, '2025-04-01', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(751, '2025-04-01', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(752, '2025-04-01', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(753, '2025-04-01', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(754, '2025-04-01', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(755, '2025-04-01', 10, 13, NULL, NULL, NULL, NULL, '유급', NULL, '외조모상', '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 15), +(756, '2025-04-01', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(757, '2025-04-01', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(758, '2025-04-01', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:43', '2025-04-17 04:22:43', NULL, NULL, NULL, 9), +(769, '2025-04-02', 1, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-17 04:25:55', '2025-04-17 04:25:55', NULL, NULL, NULL, 9), +(770, '2025-04-02', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(771, '2025-04-02', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(773, '2025-04-02', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(774, '2025-04-02', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(775, '2025-04-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 15), +(776, '2025-04-02', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 15), +(777, '2025-04-02', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(778, '2025-04-02', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(779, '2025-04-03', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(780, '2025-04-03', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(781, '2025-04-03', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(783, '2025-04-03', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(784, '2025-04-03', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(785, '2025-04-03', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(786, '2025-04-03', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(787, '2025-04-03', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(788, '2025-04-03', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(789, '2025-04-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(790, '2025-04-04', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(791, '2025-04-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(792, '2025-04-04', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(793, '2025-04-04', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(794, '2025-04-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(795, '2025-04-04', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(796, '2025-04-04', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(797, '2025-04-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(798, '2025-04-04', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(799, '2025-04-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(800, '2025-04-07', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(801, '2025-04-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(802, '2025-04-07', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(803, '2025-04-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(804, '2025-04-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(805, '2025-04-07', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(806, '2025-04-07', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(807, '2025-04-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(808, '2025-04-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(809, '2025-04-08', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(811, '2025-04-08', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(812, '2025-04-08', 7, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(813, '2025-04-08', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(814, '2025-04-08', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(815, '2025-04-08', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(816, '2025-04-08', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(817, '2025-04-08', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(818, '2025-04-08', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(819, '2025-04-09', 1, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-17 04:43:02', '2025-04-17 04:43:02', NULL, NULL, NULL, 9), +(820, '2025-04-09', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:02', '2025-04-17 04:43:02', NULL, NULL, NULL, 9), +(821, '2025-04-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(822, '2025-04-09', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(823, '2025-04-09', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(824, '2025-04-09', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(825, '2025-04-09', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(826, '2025-04-09', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(827, '2025-04-09', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(828, '2025-04-09', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(829, '2025-04-10', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(830, '2025-04-10', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(831, '2025-04-10', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(832, '2025-04-10', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(833, '2025-04-10', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(834, '2025-04-10', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(835, '2025-04-10', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(836, '2025-04-10', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(837, '2025-04-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(838, '2025-04-10', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(839, '2025-04-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 9), +(840, '2025-04-11', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 9), +(841, '2025-04-11', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 5), +(842, '2025-04-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(843, '2025-04-11', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 5), +(844, '2025-04-11', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 15), +(845, '2025-04-11', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 5), +(846, '2025-04-11', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(847, '2025-04-11', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 15), +(848, '2025-04-11', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(849, '2025-04-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(850, '2025-04-14', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(851, '2025-04-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 5), +(852, '2025-04-14', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(853, '2025-04-14', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 5), +(854, '2025-04-14', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(855, '2025-04-14', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(856, '2025-04-14', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(857, '2025-04-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(858, '2025-04-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(859, '2025-04-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(860, '2025-04-17', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(861, '2025-04-17', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(862, '2025-04-17', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(863, '2025-04-17', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(864, '2025-04-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(865, '2025-04-17', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(866, '2025-04-17', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(867, '2025-04-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(868, '2025-04-17', 6, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(879, '2025-04-21', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(880, '2025-04-21', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(881, '2025-04-21', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(882, '2025-04-21', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(883, '2025-04-21', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(884, '2025-04-21', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(885, '2025-04-21', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(886, '2025-04-21', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(887, '2025-04-21', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(888, '2025-04-21', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(889, '2025-04-22', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(890, '2025-04-22', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(891, '2025-04-22', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(892, '2025-04-22', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(893, '2025-04-22', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(894, '2025-04-22', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(895, '2025-04-22', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(896, '2025-04-22', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(897, '2025-04-22', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(898, '2025-04-22', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(899, '2025-04-23', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(900, '2025-04-23', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(901, '2025-04-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(902, '2025-04-23', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(903, '2025-04-23', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(904, '2025-04-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(905, '2025-04-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(906, '2025-04-23', 4, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(907, '2025-04-23', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(908, '2025-04-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(909, '2025-04-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, '벨브 부적합 관련 작업 추가', '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(910, '2025-04-24', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(911, '2025-04-24', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(912, '2025-04-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(913, '2025-04-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(914, '2025-04-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(915, '2025-04-24', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(916, '2025-04-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(917, '2025-04-24', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(918, '2025-04-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(919, '2025-04-25', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(920, '2025-04-25', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(921, '2025-04-25', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 5), +(922, '2025-04-25', 7, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(923, '2025-04-25', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(924, '2025-04-25', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(925, '2025-04-25', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(926, '2025-04-25', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '확관 작업', '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 5), +(927, '2025-04-25', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(928, '2025-04-25', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:39', '2025-04-25 04:23:39', NULL, NULL, NULL, 5), +(929, '2025-04-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:22', '2025-04-28 23:20:22', NULL, NULL, NULL, 9), +(930, '2025-04-28', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(931, '2025-04-28', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(932, '2025-04-28', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(934, '2025-04-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(935, '2025-04-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(936, '2025-04-28', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(937, '2025-04-28', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(938, '2025-04-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(939, '2025-04-29', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 9), +(940, '2025-04-29', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(941, '2025-04-29', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(942, '2025-04-29', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 9), +(943, '2025-04-29', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(944, '2025-04-29', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(945, '2025-04-29', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 14), +(946, '2025-04-29', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(947, '2025-04-29', 8, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(948, '2025-04-29', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(949, '2025-04-30', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(950, '2025-04-30', 2, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(951, '2025-04-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(953, '2025-04-30', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 15), +(954, '2025-04-30', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(955, '2025-04-30', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(956, '2025-04-30', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(957, '2025-04-30', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 15), +(958, '2025-04-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(959, '2025-04-30', 4, 7, NULL, NULL, NULL, NULL, '반반차', NULL, '제2공장 공사', '2025-04-30 04:22:04', '2025-04-30 04:22:04', NULL, NULL, NULL, 14), +(1023, '2025-04-15', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1024, '2025-04-15', 2, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1025, '2025-04-15', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1026, '2025-04-15', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1027, '2025-04-15', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1028, '2025-04-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1029, '2025-04-15', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1030, '2025-04-15', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1031, '2025-04-15', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1032, '2025-04-15', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1033, '2025-04-16', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1034, '2025-04-16', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1035, '2025-04-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(1036, '2025-04-16', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1037, '2025-04-16', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1038, '2025-04-16', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1039, '2025-04-16', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1040, '2025-04-16', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 15), +(1041, '2025-04-16', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1042, '2025-04-16', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1043, '2025-04-18', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1044, '2025-04-18', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1045, '2025-04-18', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1046, '2025-04-18', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1047, '2025-04-18', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 15), +(1048, '2025-04-18', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1049, '2025-04-18', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1050, '2025-04-18', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1051, '2025-04-18', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1052, '2025-04-18', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1053, '2025-04-02', 7, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-07 02:19:00', '2025-05-07 02:19:00', NULL, NULL, NULL, 9), +(1054, '2025-04-03', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 02:19:45', '2025-05-07 02:19:45', NULL, NULL, NULL, 9), +(1055, '2025-04-08', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 02:20:22', '2025-05-07 02:20:22', NULL, NULL, NULL, 9), +(1056, '2025-04-28', 8, 1, NULL, NULL, NULL, NULL, '반반차', NULL, 'NCR 벨브라인 설치', '2025-05-07 02:21:44', '2025-05-07 02:21:44', NULL, NULL, NULL, 9), +(1057, '2025-05-02', 1, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1058, '2025-05-02', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1059, '2025-05-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1060, '2025-05-02', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1061, '2025-05-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1062, '2025-05-02', 6, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1063, '2025-05-02', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1064, '2025-05-02', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1065, '2025-05-02', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1066, '2025-05-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1067, '2025-05-07', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1068, '2025-05-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1069, '2025-05-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1070, '2025-05-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1071, '2025-05-07', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1072, '2025-05-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1073, '2025-05-07', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1074, '2025-05-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1075, '2025-05-07', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1076, '2025-05-07', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1078, '2025-05-08', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1079, '2025-05-08', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1080, '2025-05-08', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1081, '2025-05-08', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1082, '2025-05-08', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1083, '2025-05-08', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1084, '2025-05-08', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1085, '2025-05-08', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1086, '2025-05-08', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1087, '2025-05-08', 1, 7, NULL, NULL, NULL, NULL, '반반차', NULL, '작업장 구역 설치', '2025-05-08 06:57:51', '2025-05-08 06:57:51', NULL, NULL, NULL, 14), +(1088, '2025-05-09', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1089, '2025-05-09', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1090, '2025-05-09', 3, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1091, '2025-05-09', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1092, '2025-05-09', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1093, '2025-05-09', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1094, '2025-05-09', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1095, '2025-05-09', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1096, '2025-05-09', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1097, '2025-05-09', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1100, '2025-05-12', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-11 21:52:46', '2025-05-11 21:52:46', NULL, NULL, NULL, 15), +(1108, '2025-05-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1111, '2025-05-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1113, '2025-05-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1115, '2025-05-12', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1116, '2025-05-12', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1117, '2025-05-13', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1118, '2025-05-13', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1119, '2025-05-13', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1120, '2025-05-13', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1121, '2025-05-13', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1122, '2025-05-13', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1123, '2025-05-13', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1124, '2025-05-13', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1125, '2025-05-13', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1126, '2025-05-13', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1127, '2025-05-12', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1128, '2025-05-12', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1129, '2025-05-12', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1130, '2025-05-12', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1131, '2025-05-14', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1132, '2025-05-14', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1133, '2025-05-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1134, '2025-05-14', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1135, '2025-05-14', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1136, '2025-05-14', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1137, '2025-05-14', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1138, '2025-05-14', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1139, '2025-05-14', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1140, '2025-05-14', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1141, '2025-05-15', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 14), +(1142, '2025-05-15', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1143, '2025-05-15', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1144, '2025-05-15', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1145, '2025-05-15', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1146, '2025-05-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1147, '2025-05-15', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 14), +(1148, '2025-05-15', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1149, '2025-05-15', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1150, '2025-05-15', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1151, '2025-05-16', 1, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1152, '2025-05-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1153, '2025-05-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1154, '2025-05-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1155, '2025-05-16', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1156, '2025-05-16', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1157, '2025-05-16', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1158, '2025-05-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1159, '2025-05-16', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1160, '2025-05-16', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1171, '2025-05-19', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1172, '2025-05-19', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 4), +(1173, '2025-05-19', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1174, '2025-05-19', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1175, '2025-05-19', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1176, '2025-05-19', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1177, '2025-05-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1179, '2025-05-19', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1180, '2025-05-19', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1181, '2025-05-21', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1183, '2025-05-21', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1184, '2025-05-21', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1185, '2025-05-21', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1186, '2025-05-21', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1187, '2025-05-21', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1188, '2025-05-21', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1189, '2025-05-21', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1190, '2025-05-21', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1191, '2025-05-20', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1192, '2025-05-20', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 3), +(1193, '2025-05-20', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1194, '2025-05-20', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1195, '2025-05-20', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1196, '2025-05-20', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1197, '2025-05-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1198, '2025-05-20', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1199, '2025-05-20', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1200, '2025-05-20', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1201, '2025-05-22', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1202, '2025-05-22', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 3), +(1203, '2025-05-22', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1204, '2025-05-22', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1205, '2025-05-22', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1206, '2025-05-22', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1207, '2025-05-22', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1208, '2025-05-22', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1209, '2025-05-22', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1210, '2025-05-22', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1211, '2025-05-21', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-22 04:54:12', '2025-05-22 04:54:12', NULL, NULL, NULL, 15), +(1215, '2025-05-26', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-26 06:58:00', '2025-05-26 06:58:00', NULL, NULL, NULL, 15), +(1222, '2025-05-19', 8, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-01 22:34:36', '2025-06-01 22:34:36', NULL, NULL, NULL, 3), +(1223, '2025-05-26', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1224, '2025-05-26', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1225, '2025-05-26', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1226, '2025-05-26', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1227, '2025-05-26', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1228, '2025-05-26', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1229, '2025-05-26', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1230, '2025-05-26', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1231, '2025-05-26', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1232, '2025-05-23', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1233, '2025-05-23', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 3), +(1234, '2025-05-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1235, '2025-05-23', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1236, '2025-05-23', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1237, '2025-05-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1238, '2025-05-23', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1239, '2025-05-23', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1240, '2025-05-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1241, '2025-05-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1242, '2025-05-27', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1243, '2025-05-27', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1244, '2025-05-27', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1245, '2025-05-27', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1246, '2025-05-27', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1247, '2025-05-27', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1248, '2025-05-27', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1249, '2025-05-27', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1250, '2025-05-27', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1251, '2025-05-27', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1252, '2025-05-28', 1, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-06-01 22:46:40', '2025-06-01 22:46:40', NULL, NULL, NULL, 8), +(1258, '2025-05-28', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:46:40', '2025-06-01 22:46:40', NULL, NULL, NULL, 8), +(1262, '2025-05-28', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1263, '2025-05-28', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1264, '2025-05-28', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1265, '2025-05-28', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1266, '2025-05-28', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1267, '2025-05-28', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1268, '2025-05-28', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1269, '2025-05-28', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1270, '2025-05-29', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1271, '2025-05-29', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1272, '2025-05-29', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1273, '2025-05-29', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1274, '2025-05-29', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1275, '2025-05-29', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1276, '2025-05-29', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1277, '2025-05-29', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1278, '2025-05-29', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1279, '2025-05-29', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1281, '2025-05-30', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1282, '2025-05-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1283, '2025-05-30', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1284, '2025-05-30', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1285, '2025-05-30', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1286, '2025-05-30', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1287, '2025-05-30', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1288, '2025-05-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1289, '2025-05-30', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1290, '2025-06-02', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:18', '2025-06-01 22:52:18', NULL, NULL, NULL, 8), +(1291, '2025-06-02', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 5), +(1292, '2025-06-02', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1293, '2025-06-02', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1294, '2025-06-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1295, '2025-06-02', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1296, '2025-06-02', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1297, '2025-06-02', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1298, '2025-06-02', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1299, '2025-06-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1300, '2025-05-30', 1, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-01 23:17:51', '2025-06-01 23:17:51', NULL, NULL, NULL, 8), +(1301, '2025-01-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 23:31:26', '2025-06-01 23:31:26', NULL, NULL, NULL, 15), +(1302, '2025-06-04', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1303, '2025-06-04', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1304, '2025-06-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1305, '2025-06-04', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 15), +(1306, '2025-06-04', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1307, '2025-06-04', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1308, '2025-06-04', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1309, '2025-06-04', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1310, '2025-06-04', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1311, '2025-06-04', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1312, '2025-06-09', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:28', NULL, NULL, NULL, 8), +(1313, '2025-06-09', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1314, '2025-06-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:30', NULL, NULL, NULL, 8), +(1315, '2025-06-09', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1316, '2025-06-09', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:31', NULL, NULL, NULL, 8), +(1317, '2025-06-09', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1318, '2025-06-09', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:32', NULL, NULL, NULL, 8), +(1319, '2025-06-09', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1320, '2025-06-09', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 15), +(1321, '2025-06-09', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:34', NULL, NULL, NULL, 8), +(1322, '2025-06-10', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:03', '2025-06-13 03:43:51', NULL, NULL, NULL, 8), +(1323, '2025-06-10', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:03', '2025-06-10 08:47:03', NULL, NULL, NULL, 5), +(1324, '2025-06-10', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:03', '2025-06-13 03:43:53', NULL, NULL, NULL, 8), +(1325, '2025-06-10', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:54', NULL, NULL, NULL, 8), +(1326, '2025-06-10', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1327, '2025-06-10', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1328, '2025-06-10', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:55', NULL, NULL, NULL, 8), +(1329, '2025-06-10', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1330, '2025-06-10', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:56', NULL, NULL, NULL, 8), +(1331, '2025-06-10', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:56', NULL, NULL, NULL, 8), +(1332, '2025-06-11', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:18', NULL, NULL, NULL, 8), +(1333, '2025-06-11', 2, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1334, '2025-06-11', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:19', NULL, NULL, NULL, 8), +(1335, '2025-06-11', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:20', NULL, NULL, NULL, 8), +(1336, '2025-06-11', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1337, '2025-06-11', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1338, '2025-06-11', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:22', NULL, NULL, NULL, 8), +(1339, '2025-06-11', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1340, '2025-06-11', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:23', NULL, NULL, NULL, 8), +(1341, '2025-06-11', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:23', NULL, NULL, NULL, 8), +(1342, '2025-06-13', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1343, '2025-06-13', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1344, '2025-06-13', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1345, '2025-06-13', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1346, '2025-06-13', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1347, '2025-06-13', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1348, '2025-06-13', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 15), +(1349, '2025-06-13', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1350, '2025-06-13', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1351, '2025-06-13', 10, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1352, '2025-06-05', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1353, '2025-06-05', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1354, '2025-06-05', 3, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1355, '2025-06-05', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1356, '2025-06-05', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1357, '2025-06-05', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1358, '2025-06-05', 7, 4, NULL, NULL, NULL, NULL, '반반차', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1359, '2025-06-05', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1360, '2025-06-05', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1361, '2025-06-05', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1362, '2025-06-12', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1363, '2025-06-12', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1364, '2025-06-12', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1365, '2025-06-12', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1366, '2025-06-12', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1367, '2025-06-12', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1368, '2025-06-12', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1369, '2025-06-12', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1370, '2025-06-12', 9, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1371, '2025-06-12', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1372, '2025-06-16', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:26', '2025-06-16 04:26:26', NULL, NULL, NULL, 8), +(1373, '2025-06-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1374, '2025-06-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1375, '2025-06-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1376, '2025-06-16', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1377, '2025-06-16', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'Vessel NDE 불량 수리', '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1378, '2025-06-16', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 15), +(1379, '2025-06-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'Vessel NDE 불량 수리', '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1380, '2025-06-16', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1381, '2025-06-16', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1382, '2025-06-17', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1383, '2025-06-17', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1384, '2025-06-17', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1385, '2025-06-17', 4, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:36:28', NULL, NULL, NULL, 5), +(1386, '2025-06-17', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1387, '2025-06-17', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 비파괴 불량', '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1388, '2025-06-17', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1389, '2025-06-17', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 비파괴 불량', '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1390, '2025-06-17', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1391, '2025-06-17', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1392, '2025-06-18', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1393, '2025-06-18', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1394, '2025-06-18', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1395, '2025-06-18', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1396, '2025-06-18', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1397, '2025-06-18', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1398, '2025-06-18', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1399, '2025-06-18', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1400, '2025-06-18', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1401, '2025-06-18', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1402, '2025-06-24', 1, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1403, '2025-06-24', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 5), +(1404, '2025-06-24', 3, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1405, '2025-06-24', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1406, '2025-06-24', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1407, '2025-06-24', 6, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1408, '2025-06-24', 7, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1409, '2025-06-24', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 5), +(1410, '2025-06-24', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1411, '2025-06-24', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1412, '2025-06-25', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1413, '2025-06-25', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 5), +(1414, '2025-06-25', 3, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1415, '2025-06-25', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1416, '2025-06-25', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1417, '2025-06-25', 6, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1418, '2025-06-25', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1419, '2025-06-25', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 5), +(1420, '2025-06-25', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1421, '2025-06-25', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1422, '2025-06-26', 1, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1423, '2025-06-26', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1424, '2025-06-26', 3, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1425, '2025-06-26', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1426, '2025-06-26', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1427, '2025-06-26', 6, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1428, '2025-06-26', 7, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1429, '2025-06-26', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1430, '2025-06-26', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1431, '2025-06-26', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1432, '2025-06-27', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1433, '2025-06-27', 2, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1434, '2025-06-27', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1435, '2025-06-27', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1436, '2025-06-27', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1437, '2025-06-27', 6, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1438, '2025-06-27', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1439, '2025-06-27', 8, 3, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1440, '2025-06-27', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1441, '2025-06-27', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_report_audit_log` +-- + +CREATE TABLE `work_report_audit_log` ( + `log_id` int(11) NOT NULL, + `action` enum('ADD_ACCUMULATE','DELETE_SINGLE','UPDATE','DELETE','CREATE','DELETE_BATCH') NOT NULL COMMENT '작업 유형', + `report_id` int(11) DEFAULT NULL COMMENT '관련 보고서 ID', + `old_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 전 값' CHECK (json_valid(`old_values`)), + `new_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 후 값' CHECK (json_valid(`new_values`)), + `changed_by` int(11) NOT NULL COMMENT '변경자 ID', + `change_reason` varchar(500) DEFAULT NULL COMMENT '변경 사유', + `ip_address` varchar(45) DEFAULT NULL COMMENT 'IP 주소', + `user_agent` text DEFAULT NULL COMMENT '사용자 에이전트', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '변경 시간' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_report_audit_log` +-- + +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(1, 'ADD_ACCUMULATE', 12, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 02:56:12'), +(2, 'DELETE_SINGLE', 12, '{\"worker_name\":\"김두수\",\"project_name\":\"MP7 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:36'), +(3, 'DELETE_SINGLE', 11, '{\"worker_name\":\"김두수\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:39'), +(4, 'DELETE_SINGLE', 7, '{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:41'), +(5, 'ADD_ACCUMULATE', 13, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":1,\"my_total\":\"1.00\",\"grand_total\":1,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"1.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 03:18:37'), +(6, 'DELETE_SINGLE', 13, '{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:19:23'), +(7, 'ADD_ACCUMULATE', 14, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(8, 'ADD_ACCUMULATE', 15, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(9, 'ADD_ACCUMULATE', 16, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(10, 'ADD_ACCUMULATE', 17, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(11, 'ADD_ACCUMULATE', 18, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(12, 'ADD_ACCUMULATE', 19, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(13, 'ADD_ACCUMULATE', 20, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:47'), +(14, 'ADD_ACCUMULATE', 21, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(15, 'ADD_ACCUMULATE', 22, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(16, 'ADD_ACCUMULATE', 23, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(17, 'ADD_ACCUMULATE', 24, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(18, 'ADD_ACCUMULATE', 25, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(19, 'ADD_ACCUMULATE', 26, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(20, 'ADD_ACCUMULATE', 27, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(21, 'ADD_ACCUMULATE', 28, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(22, 'ADD_ACCUMULATE', 29, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(23, 'ADD_ACCUMULATE', 30, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(24, 'ADD_ACCUMULATE', 31, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(25, 'ADD_ACCUMULATE', 32, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(26, 'ADD_ACCUMULATE', 33, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(27, 'ADD_ACCUMULATE', 34, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(28, 'ADD_ACCUMULATE', 35, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(29, 'ADD_ACCUMULATE', 36, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(30, 'ADD_ACCUMULATE', 37, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(31, 'ADD_ACCUMULATE', 38, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(32, 'ADD_ACCUMULATE', 39, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(33, 'ADD_ACCUMULATE', 40, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(34, 'ADD_ACCUMULATE', 41, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(35, 'ADD_ACCUMULATE', 42, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(36, 'ADD_ACCUMULATE', 43, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(37, 'DELETE_SINGLE', 42, '{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:12:33'), +(38, 'ADD_ACCUMULATE', 44, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:13:02'), +(39, 'ADD_ACCUMULATE', 45, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:13:50'), +(40, 'DELETE_SINGLE', 41, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:14:48'), +(41, 'ADD_ACCUMULATE', 46, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:15:22'), +(42, 'DELETE_SINGLE', 1, '{\"worker_name\":\"김두수\",\"project_name\":\"25년 안전보건시설설비\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-01T00:00:00.000Z\"}', NULL, 1, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:20:38'), +(43, 'ADD_ACCUMULATE', 48, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(44, 'ADD_ACCUMULATE', 49, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(45, 'ADD_ACCUMULATE', 50, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(46, 'DELETE_SINGLE', 49, '{\"worker_name\":\"박현수\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:47:54'), +(47, 'ADD_ACCUMULATE', 51, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:48:29'), +(48, 'ADD_ACCUMULATE', 52, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-16 06:50:09'), +(49, 'ADD_ACCUMULATE', 54, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-16 06:50:09'), +(50, 'ADD_ACCUMULATE', 56, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:23:41'), +(51, 'ADD_ACCUMULATE', 58, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:23:41'), +(52, 'ADD_ACCUMULATE', 60, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:33'), +(53, 'ADD_ACCUMULATE', 62, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:33'), +(54, 'ADD_ACCUMULATE', 64, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:44'), +(55, 'ADD_ACCUMULATE', 65, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:25:24'), +(56, 'DELETE_SINGLE', 64, '{\"worker_name\":\"황인용\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-17T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-17 08:26:17'), +(57, 'ADD_ACCUMULATE', 66, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:27:06'), +(58, 'ADD_ACCUMULATE', 67, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:27:06'), +(59, 'ADD_ACCUMULATE', 68, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(60, 'ADD_ACCUMULATE', 69, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(61, 'ADD_ACCUMULATE', 70, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(62, 'ADD_ACCUMULATE', 71, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(63, 'ADD_ACCUMULATE', 72, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(64, 'ADD_ACCUMULATE', 73, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(65, 'ADD_ACCUMULATE', 74, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-17 08:34:11'), +(66, 'ADD_ACCUMULATE', 76, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-17 08:34:11'), +(67, 'ADD_ACCUMULATE', 78, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(68, 'ADD_ACCUMULATE', 79, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(69, 'ADD_ACCUMULATE', 80, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(70, 'ADD_ACCUMULATE', 81, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:02'), +(71, 'ADD_ACCUMULATE', 82, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:03'), +(72, 'ADD_ACCUMULATE', 83, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:03'), +(73, 'ADD_ACCUMULATE', 84, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:45'), +(74, 'ADD_ACCUMULATE', 86, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-18 08:47:55'), +(75, 'ADD_ACCUMULATE', 88, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-18 08:47:55'), +(76, 'ADD_ACCUMULATE', 90, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(77, 'ADD_ACCUMULATE', 92, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(78, 'ADD_ACCUMULATE', 94, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(79, 'ADD_ACCUMULATE', 96, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 09:00:17'), +(80, 'ADD_ACCUMULATE', 98, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-19 06:37:59'), +(81, 'ADD_ACCUMULATE', 99, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-19 06:37:59'), +(82, 'ADD_ACCUMULATE', 100, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(83, 'ADD_ACCUMULATE', 101, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(84, 'ADD_ACCUMULATE', 102, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(85, 'ADD_ACCUMULATE', 103, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(86, 'ADD_ACCUMULATE', 105, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(87, 'ADD_ACCUMULATE', 107, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(88, 'ADD_ACCUMULATE', 109, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(89, 'ADD_ACCUMULATE', 111, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(90, 'ADD_ACCUMULATE', 113, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(91, 'ADD_ACCUMULATE', 115, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(92, 'ADD_ACCUMULATE', 117, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(93, 'ADD_ACCUMULATE', 119, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(94, 'ADD_ACCUMULATE', 121, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(95, 'ADD_ACCUMULATE', 123, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(96, 'ADD_ACCUMULATE', 125, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-20 06:45:30'), +(97, 'ADD_ACCUMULATE', 126, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-20 06:45:31'), +(98, 'ADD_ACCUMULATE', 127, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-23 06:42:58'), +(99, 'ADD_ACCUMULATE', 128, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-23 06:42:58'), +(100, 'ADD_ACCUMULATE', 129, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(101, 'ADD_ACCUMULATE', 131, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(102, 'ADD_ACCUMULATE', 133, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(103, 'ADD_ACCUMULATE', 135, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(104, 'ADD_ACCUMULATE', 137, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(105, 'ADD_ACCUMULATE', 139, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(106, 'ADD_ACCUMULATE', 141, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-24 11:10:32'), +(107, 'ADD_ACCUMULATE', 142, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-24 11:10:32'), +(108, 'ADD_ACCUMULATE', 143, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(109, 'ADD_ACCUMULATE', 145, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(110, 'ADD_ACCUMULATE', 147, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(111, 'ADD_ACCUMULATE', 149, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(112, 'ADD_ACCUMULATE', 151, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(113, 'ADD_ACCUMULATE', 153, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(114, 'ADD_ACCUMULATE', 155, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:05'), +(115, 'ADD_ACCUMULATE', 157, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:05'), +(116, 'ADD_ACCUMULATE', 159, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-25 11:08:04'), +(117, 'ADD_ACCUMULATE', 161, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-25 11:08:05'), +(118, 'ADD_ACCUMULATE', 163, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(119, 'ADD_ACCUMULATE', 164, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(120, 'ADD_ACCUMULATE', 165, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(121, 'ADD_ACCUMULATE', 166, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(122, 'ADD_ACCUMULATE', 167, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(123, 'ADD_ACCUMULATE', 168, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(124, 'ADD_ACCUMULATE', 169, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(125, 'ADD_ACCUMULATE', 170, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(126, 'ADD_ACCUMULATE', 171, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(127, 'ADD_ACCUMULATE', 172, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:31'), +(128, 'ADD_ACCUMULATE', 174, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:32'), +(129, 'ADD_ACCUMULATE', 176, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:32'), +(130, 'ADD_ACCUMULATE', 178, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-26 11:19:34'), +(131, 'ADD_ACCUMULATE', 179, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-26 11:19:34'), +(132, 'ADD_ACCUMULATE', 180, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:21'), +(133, 'ADD_ACCUMULATE', 181, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:21'), +(134, 'ADD_ACCUMULATE', 182, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:40'), +(135, 'ADD_ACCUMULATE', 183, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(136, 'ADD_ACCUMULATE', 184, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(137, 'ADD_ACCUMULATE', 185, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(138, 'ADD_ACCUMULATE', 186, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(139, 'ADD_ACCUMULATE', 187, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(140, 'ADD_ACCUMULATE', 188, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(141, 'ADD_ACCUMULATE', 189, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:49:08'), +(142, 'ADD_ACCUMULATE', 190, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:49:08'), +(143, 'DELETE_SINGLE', 190, '{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 6, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:58:25'), +(144, 'ADD_ACCUMULATE', 191, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"4.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:58:46'), +(145, 'DELETE_SINGLE', 181, '{\"worker_name\":\"박현수\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:59:37'), +(146, 'DELETE_SINGLE', 180, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:59:42'), +(147, 'ADD_ACCUMULATE', 192, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 07:00:10'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_status_types` +-- + +CREATE TABLE `work_status_types` ( + `id` int(11) NOT NULL, + `name` varchar(50) NOT NULL COMMENT '상태명', + `description` text DEFAULT NULL COMMENT '상태 설명', + `is_error` tinyint(1) DEFAULT 0 COMMENT '에러 상태 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_status_types` +-- + +INSERT INTO `work_status_types` (`id`, `name`, `description`, `is_error`, `created_at`) VALUES +(1, '정규', '정상적으로 완료된 작업', 0, '2025-06-16 02:21:16'), +(2, '에러', '오류가 발생한 작업', 1, '2025-06-16 02:21:16'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_types` +-- + +CREATE TABLE `work_types` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL COMMENT '작업 유형명', + `description` text DEFAULT NULL COMMENT '작업 유형 설명', + `category` varchar(50) DEFAULT NULL COMMENT '작업 카테고리', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_types` +-- + +INSERT INTO `work_types` (`id`, `name`, `description`, `category`, `created_at`, `updated_at`) VALUES +(1, 'Base(구조물)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:42'), +(2, 'Vessel(용기)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:47'), +(3, 'Piping Assembly(배관)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:50'), +(4, '작업대기', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:56'); + +-- +-- 덤프된 테이블의 인덱스 +-- + +-- +-- 테이블의 인덱스 `activity_logs` +-- +ALTER TABLE `activity_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_user_activity` (`user_id`,`activity_type`,`created_at`), + ADD KEY `idx_table_record` (`table_name`,`record_id`); + +-- +-- 테이블의 인덱스 `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + ADD PRIMARY KEY (`cutting_plan_id`), + ADD KEY `project_id` (`project_id`), + ADD KEY `fk_cuttingplan_spec` (`spec_id`); + +-- +-- 테이블의 인덱스 `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + ADD PRIMARY KEY (`id`), + ADD KEY `worker_id` (`worker_id`), + ADD KEY `fk_dird_project` (`project_id`), + ADD KEY `fk_dird_issuetype` (`issue_type_id`); + +-- +-- 테이블의 인덱스 `daily_worker_summary` +-- +ALTER TABLE `daily_worker_summary` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `unique_worker_date` (`worker_id`,`report_date`); + +-- +-- 테이블의 인덱스 `daily_work_reports` +-- +ALTER TABLE `daily_work_reports` + ADD PRIMARY KEY (`id`), + ADD KEY `idx_report_date` (`report_date`), + ADD KEY `idx_worker_date` (`worker_id`,`report_date`), + ADD KEY `idx_project_date` (`project_id`,`report_date`), + ADD KEY `idx_work_type` (`work_type_id`), + ADD KEY `idx_work_status` (`work_status_id`), + ADD KEY `idx_error_type` (`error_type_id`), + ADD KEY `idx_created_by` (`created_by`), + ADD KEY `idx_date_worker_creator` (`report_date`,`worker_id`,`created_by`); + +-- +-- 테이블의 인덱스 `EquipmentList` +-- +ALTER TABLE `EquipmentList` + ADD PRIMARY KEY (`equipment_id`), + ADD KEY `factory_id` (`factory_id`); + +-- +-- 테이블의 인덱스 `error_types` +-- +ALTER TABLE `error_types` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `FactoryInfo` +-- +ALTER TABLE `FactoryInfo` + ADD PRIMARY KEY (`factory_id`); + +-- +-- 테이블의 인덱스 `IssueTypes` +-- +ALTER TABLE `IssueTypes` + ADD PRIMARY KEY (`issue_type_id`); + +-- +-- 테이블의 인덱스 `login_logs` +-- +ALTER TABLE `login_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_user_login` (`user_id`,`login_time`); + +-- +-- 테이블의 인덱스 `password_change_logs` +-- +ALTER TABLE `password_change_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `changed_by_user_id` (`changed_by_user_id`), + ADD KEY `idx_user_changes` (`user_id`,`changed_at`); + +-- +-- 테이블의 인덱스 `PipeSpecs` +-- +ALTER TABLE `PipeSpecs` + ADD PRIMARY KEY (`spec_id`), + ADD UNIQUE KEY `unique_spec` (`material`,`diameter_in`,`schedule`); + +-- +-- 테이블의 인덱스 `Processes` +-- +ALTER TABLE `Processes` + ADD PRIMARY KEY (`process_id`), + ADD KEY `project_id` (`project_id`); + +-- +-- 테이블의 인덱스 `Projects` +-- +ALTER TABLE `Projects` + ADD PRIMARY KEY (`project_id`); + +-- +-- 테이블의 인덱스 `Tasks` +-- +ALTER TABLE `Tasks` + ADD PRIMARY KEY (`task_id`); + +-- +-- 테이블의 인덱스 `uploaded_documents` +-- +ALTER TABLE `uploaded_documents` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `Users` +-- +ALTER TABLE `Users` + ADD PRIMARY KEY (`user_id`), + ADD UNIQUE KEY `username` (`username`), + ADD UNIQUE KEY `email` (`email`), + ADD KEY `fk_worker` (`worker_id`), + ADD KEY `idx_username` (`username`), + ADD KEY `idx_active_users` (`is_active`,`access_level`); + +-- +-- 테이블의 인덱스 `Workers` +-- +ALTER TABLE `Workers` + ADD PRIMARY KEY (`worker_id`); + +-- +-- 테이블의 인덱스 `worker_groups` +-- +ALTER TABLE `worker_groups` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `uk_leader_worker` (`group_leader_id`,`worker_id`), + ADD KEY `idx_group_leader` (`group_leader_id`), + ADD KEY `idx_worker` (`worker_id`), + ADD KEY `idx_is_active` (`is_active`); + +-- +-- 테이블의 인덱스 `WorkReports` +-- +ALTER TABLE `WorkReports` + ADD PRIMARY KEY (`id`), + ADD KEY `worker_id` (`worker_id`), + ADD KEY `project_id` (`project_id`), + ADD KEY `morning_task_id` (`morning_task_id`), + ADD KEY `afternoon_task_id` (`afternoon_task_id`), + ADD KEY `overtime_task_id` (`overtime_task_id`); + +-- +-- 테이블의 인덱스 `work_report_audit_log` +-- +ALTER TABLE `work_report_audit_log` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_action_date` (`action`,`created_at`), + ADD KEY `idx_changed_by` (`changed_by`), + ADD KEY `idx_report_id` (`report_id`); + +-- +-- 테이블의 인덱스 `work_status_types` +-- +ALTER TABLE `work_status_types` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `work_types` +-- +ALTER TABLE `work_types` + ADD PRIMARY KEY (`id`); + +-- +-- 덤프된 테이블의 AUTO_INCREMENT +-- + +-- +-- 테이블의 AUTO_INCREMENT `activity_logs` +-- +ALTER TABLE `activity_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + MODIFY `cutting_plan_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; + +-- +-- 테이블의 AUTO_INCREMENT `daily_worker_summary` +-- +ALTER TABLE `daily_worker_summary` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; + +-- +-- 테이블의 AUTO_INCREMENT `daily_work_reports` +-- +ALTER TABLE `daily_work_reports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=193; + +-- +-- 테이블의 AUTO_INCREMENT `EquipmentList` +-- +ALTER TABLE `EquipmentList` + MODIFY `equipment_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `error_types` +-- +ALTER TABLE `error_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; + +-- +-- 테이블의 AUTO_INCREMENT `FactoryInfo` +-- +ALTER TABLE `FactoryInfo` + MODIFY `factory_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; + +-- +-- 테이블의 AUTO_INCREMENT `IssueTypes` +-- +ALTER TABLE `IssueTypes` + MODIFY `issue_type_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `login_logs` +-- +ALTER TABLE `login_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=142; + +-- +-- 테이블의 AUTO_INCREMENT `password_change_logs` +-- +ALTER TABLE `password_change_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `PipeSpecs` +-- +ALTER TABLE `PipeSpecs` + MODIFY `spec_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; + +-- +-- 테이블의 AUTO_INCREMENT `Processes` +-- +ALTER TABLE `Processes` + MODIFY `process_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `Projects` +-- +ALTER TABLE `Projects` + MODIFY `project_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=14; + +-- +-- 테이블의 AUTO_INCREMENT `Tasks` +-- +ALTER TABLE `Tasks` + MODIFY `task_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19; + +-- +-- 테이블의 AUTO_INCREMENT `uploaded_documents` +-- +ALTER TABLE `uploaded_documents` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `Users` +-- +ALTER TABLE `Users` + MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `Workers` +-- +ALTER TABLE `Workers` + MODIFY `worker_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12; + +-- +-- 테이블의 AUTO_INCREMENT `worker_groups` +-- +ALTER TABLE `worker_groups` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `WorkReports` +-- +ALTER TABLE `WorkReports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1442; + +-- +-- 테이블의 AUTO_INCREMENT `work_report_audit_log` +-- +ALTER TABLE `work_report_audit_log` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=148; + +-- +-- 테이블의 AUTO_INCREMENT `work_status_types` +-- +ALTER TABLE `work_status_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- 테이블의 AUTO_INCREMENT `work_types` +-- +ALTER TABLE `work_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11; + +-- +-- 덤프된 테이블의 제약사항 +-- + +-- +-- 테이블의 제약사항 `activity_logs` +-- +ALTER TABLE `activity_logs` + ADD CONSTRAINT `activity_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE SET NULL; + +-- +-- 테이블의 제약사항 `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + ADD CONSTRAINT `CuttingPlan_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`), + ADD CONSTRAINT `fk_cuttingplan_spec` FOREIGN KEY (`spec_id`) REFERENCES `PipeSpecs` (`spec_id`); + +-- +-- 테이블의 제약사항 `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + ADD CONSTRAINT `dailyissuereports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`), + ADD CONSTRAINT `fk_dird_issuetype` FOREIGN KEY (`issue_type_id`) REFERENCES `IssueTypes` (`issue_type_id`), + ADD CONSTRAINT `fk_dird_project` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`); + +-- +-- 테이블의 제약사항 `EquipmentList` +-- +ALTER TABLE `EquipmentList` + ADD CONSTRAINT `EquipmentList_ibfk_1` FOREIGN KEY (`factory_id`) REFERENCES `FactoryInfo` (`factory_id`); + +-- +-- 테이블의 제약사항 `login_logs` +-- +ALTER TABLE `login_logs` + ADD CONSTRAINT `login_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE; + +-- +-- 테이블의 제약사항 `password_change_logs` +-- +ALTER TABLE `password_change_logs` + ADD CONSTRAINT `password_change_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `password_change_logs_ibfk_2` FOREIGN KEY (`changed_by_user_id`) REFERENCES `Users` (`user_id`) ON DELETE SET NULL; + +-- +-- 테이블의 제약사항 `Processes` +-- +ALTER TABLE `Processes` + ADD CONSTRAINT `Processes_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`); + +-- +-- 테이블의 제약사항 `Users` +-- +ALTER TABLE `Users` + ADD CONSTRAINT `fk_worker` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`); + +-- +-- 테이블의 제약사항 `worker_groups` +-- +ALTER TABLE `worker_groups` + ADD CONSTRAINT `fk_group_leader` FOREIGN KEY (`group_leader_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `fk_group_worker` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`) ON DELETE CASCADE; + +-- +-- 테이블의 제약사항 `WorkReports` +-- +ALTER TABLE `WorkReports` + ADD CONSTRAINT `WorkReports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`), + ADD CONSTRAINT `WorkReports_ibfk_2` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`), + ADD CONSTRAINT `WorkReports_ibfk_3` FOREIGN KEY (`morning_task_id`) REFERENCES `Tasks` (`task_id`), + ADD CONSTRAINT `WorkReports_ibfk_4` FOREIGN KEY (`afternoon_task_id`) REFERENCES `Tasks` (`task_id`), + ADD CONSTRAINT `WorkReports_ibfk_5` FOREIGN KEY (`overtime_task_id`) REFERENCES `Tasks` (`task_id`); +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/hyungi_fixed.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/hyungi_fixed.sql new file mode 100644 index 0000000..1f8697b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/hyungi_fixed.sql @@ -0,0 +1,2563 @@ +-- -- phpMyAdmin SQL Dump +-- version 5.2.2 +-- https://www.phpmyadmin.net/ +-- +-- 호스트: db_hyungi_net +-- 생성 시간: 25-06-27 23:07 +-- 서버 버전: 10.9.8-MariaDB-1:10.9.8+maria~ubu2204 +-- PHP 버전: 8.2.27 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- 데이터베이스: `hyungi` +-- + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `activity_logs` +-- + +CREATE TABLE `activity_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `activity_type` varchar(100) DEFAULT NULL, + `table_name` varchar(50) DEFAULT NULL, + `record_id` int(11) DEFAULT NULL, + `action` enum('create','read','update','delete') DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `CuttingPlan` +-- + +CREATE TABLE `CuttingPlan` ( + `cutting_plan_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `drawing_name` varchar(255) NOT NULL, + `area_number` varchar(100) DEFAULT NULL, + `spool_number` varchar(255) DEFAULT NULL, + `length` decimal(10,2) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `spec_id` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `DailyIssueReports` +-- + +CREATE TABLE `DailyIssueReports` ( + `id` int(11) NOT NULL, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `issue_type_id` int(11) DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `start_time` time NOT NULL, + `end_time` time NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `DailyIssueReports` +-- + +INSERT INTO `DailyIssueReports` (`id`, `date`, `worker_id`, `project_id`, `issue_type_id`, `description`, `created_at`, `start_time`, `end_time`) VALUES +(1, '2025-06-02', 1, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(2, '2025-06-02', 9, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(3, '2025-06-02', 7, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(4, '2025-06-04', 10, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(5, '2025-06-04', 6, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(6, '2025-06-04', 3, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(7, '2025-06-11', 10, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'), +(8, '2025-06-11', 6, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'), +(9, '2025-06-11', 3, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `daily_worker_summary` +-- + +CREATE TABLE `daily_worker_summary` ( + `id` int(11) NOT NULL, + `report_date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `total_hours` decimal(4,2) NOT NULL DEFAULT 8.00 COMMENT '총 근무시간', + `work_status` enum('normal','annual_leave','half_leave','overtime') DEFAULT 'normal' COMMENT '근무 상태', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `daily_work_reports` +-- + +CREATE TABLE `daily_work_reports` ( + `id` int(11) NOT NULL, + `report_date` date NOT NULL COMMENT '작업 날짜', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `project_id` int(11) NOT NULL COMMENT '프로젝트 ID', + `work_type_id` int(11) NOT NULL COMMENT '작업 유형 ID', + `work_status_id` int(11) DEFAULT 1 COMMENT '업무 상태 ID (1:정규, 2:에러)', + `error_type_id` int(11) DEFAULT NULL COMMENT '에러 유형 ID (에러일 때만)', + `work_hours` decimal(4,2) NOT NULL COMMENT '작업 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `created_by` int(11) NOT NULL DEFAULT 1 COMMENT '작성자 user_id', + `updated_by` int(11) DEFAULT NULL COMMENT '수정자 user_id' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `daily_work_reports` +-- + +INSERT INTO `daily_work_reports` (`id`, `report_date`, `worker_id`, `project_id`, `work_type_id`, `work_status_id`, `error_type_id`, `work_hours`, `created_at`, `updated_at`, `created_by`, `updated_by`) VALUES +(14, '2025-06-02', 1, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(15, '2025-06-02', 3, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(16, '2025-06-02', 4, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(17, '2025-06-02', 6, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(18, '2025-06-02', 7, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(19, '2025-06-02', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(20, '2025-06-02', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:10:47', '2025-06-16 05:10:47', 1, NULL), +(21, '2025-06-04', 1, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(22, '2025-06-04', 3, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(23, '2025-06-04', 5, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(24, '2025-06-04', 7, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(25, '2025-06-04', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(26, '2025-06-04', 10, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(27, '2025-06-04', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(28, '2025-06-04', 6, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(29, '2025-06-04', 8, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(30, '2025-06-05', 1, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(31, '2025-06-05', 3, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(32, '2025-06-05', 4, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(33, '2025-06-05', 7, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(34, '2025-06-05', 10, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(35, '2025-06-05', 9, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(36, '2025-06-05', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(37, '2025-06-05', 5, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(38, '2025-06-05', 6, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(39, '2025-06-05', 8, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(40, '2025-06-16', 5, 3, 2, 1, NULL, 8.00, '2025-06-16 06:12:01', '2025-06-16 06:12:01', 5, NULL), +(43, '2025-06-16', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 06:12:01', '2025-06-16 06:12:01', 5, NULL), +(44, '2025-06-16', 6, 3, 2, 2, 4, 4.00, '2025-06-16 06:13:02', '2025-06-16 06:13:02', 5, NULL), +(45, '2025-06-16', 6, 3, 2, 1, NULL, 4.00, '2025-06-16 06:13:50', '2025-06-16 06:13:50', 5, NULL), +(46, '2025-06-16', 8, 3, 2, 2, 4, 4.00, '2025-06-16 06:15:22', '2025-06-16 06:15:22', 5, NULL), +(47, '2025-06-16', 8, 3, 2, 1, NULL, 4.00, '2025-06-16 06:15:22', '2025-06-16 06:15:22', 5, NULL), +(48, '2025-06-16', 4, 4, 3, 2, 1, 8.00, '2025-06-16 06:46:44', '2025-06-16 06:46:44', 3, NULL), +(50, '2025-06-16', 1, 4, 3, 2, 1, 8.00, '2025-06-16 06:46:44', '2025-06-16 06:46:44', 3, NULL), +(51, '2025-06-16', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 06:48:29', '2025-06-16 06:48:29', 3, NULL), +(52, '2025-06-16', 10, 4, 3, 1, NULL, 6.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(53, '2025-06-16', 10, 4, 3, 2, 1, 2.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(54, '2025-06-16', 3, 4, 3, 1, NULL, 6.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(55, '2025-06-16', 3, 4, 3, 2, 1, 2.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(56, '2025-06-17', 2, 3, 2, 1, NULL, 8.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(57, '2025-06-17', 2, 3, 2, 1, NULL, 2.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(58, '2025-06-17', 5, 3, 2, 1, NULL, 8.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(59, '2025-06-17', 5, 3, 2, 1, NULL, 2.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(60, '2025-06-17', 6, 3, 2, 1, NULL, 8.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(61, '2025-06-17', 6, 3, 2, 2, 4, 2.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(62, '2025-06-17', 8, 3, 2, 1, NULL, 8.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(63, '2025-06-17', 8, 3, 2, 2, 4, 2.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(65, '2025-06-17', 9, 4, 3, 2, 1, 4.00, '2025-06-17 08:25:24', '2025-06-17 08:25:24', 3, NULL), +(66, '2025-06-17', 1, 4, 3, 2, 1, 4.00, '2025-06-17 08:27:06', '2025-06-17 08:27:06', 3, NULL), +(67, '2025-06-17', 4, 4, 3, 2, 1, 4.00, '2025-06-17 08:27:06', '2025-06-17 08:27:06', 3, NULL), +(68, '2025-06-17', 1, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(69, '2025-06-17', 9, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(70, '2025-06-17', 4, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(71, '2025-06-17', 9, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(72, '2025-06-17', 4, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(73, '2025-06-17', 1, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(74, '2025-06-17', 10, 4, 3, 1, NULL, 8.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(75, '2025-06-17', 10, 4, 3, 2, 1, 2.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(76, '2025-06-17', 3, 4, 3, 1, NULL, 8.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(77, '2025-06-17', 3, 4, 3, 2, 1, 2.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(78, '2025-06-18', 6, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(79, '2025-06-18', 2, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(80, '2025-06-18', 8, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(81, '2025-06-18', 2, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:02', '2025-06-18 08:41:02', 5, NULL), +(82, '2025-06-18', 6, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:03', '2025-06-18 08:41:03', 5, NULL), +(83, '2025-06-18', 8, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:03', '2025-06-18 08:41:03', 5, NULL), +(84, '2025-06-18', 5, 4, 3, 1, NULL, 8.00, '2025-06-18 08:41:45', '2025-06-18 08:41:45', 5, NULL), +(85, '2025-06-18', 5, 4, 3, 1, NULL, 2.00, '2025-06-18 08:41:45', '2025-06-18 08:41:45', 5, NULL), +(86, '2025-06-18', 10, 4, 3, 1, NULL, 9.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(87, '2025-06-18', 10, 4, 3, 2, 1, 1.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(88, '2025-06-18', 3, 4, 3, 1, NULL, 9.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(89, '2025-06-18', 3, 4, 3, 2, 1, 1.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(90, '2025-06-18', 4, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(91, '2025-06-18', 4, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(92, '2025-06-18', 9, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(93, '2025-06-18', 9, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(94, '2025-06-18', 1, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(95, '2025-06-18', 1, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(96, '2025-06-18', 7, 4, 3, 2, 1, 4.00, '2025-06-18 09:00:17', '2025-06-18 09:00:17', 3, NULL), +(97, '2025-06-18', 7, 4, 3, 1, NULL, 6.00, '2025-06-18 09:00:17', '2025-06-18 09:00:17', 3, NULL), +(98, '2025-06-19', 8, 3, 2, 1, NULL, 8.00, '2025-06-19 06:37:59', '2025-06-19 06:37:59', 5, NULL), +(99, '2025-06-19', 2, 3, 2, 1, NULL, 8.00, '2025-06-19 06:37:59', '2025-06-19 06:37:59', 5, NULL), +(100, '2025-06-19', 10, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(101, '2025-06-19', 3, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(102, '2025-06-19', 5, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(103, '2025-06-19', 9, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(104, '2025-06-19', 9, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(105, '2025-06-19', 4, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(106, '2025-06-19', 4, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(107, '2025-06-19', 1, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(108, '2025-06-19', 1, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(109, '2025-06-19', 7, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(110, '2025-06-19', 7, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(111, '2025-06-19', 6, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(112, '2025-06-19', 6, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(113, '2025-06-20', 9, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(114, '2025-06-20', 9, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(115, '2025-06-20', 4, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(116, '2025-06-20', 4, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(117, '2025-06-20', 7, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(118, '2025-06-20', 7, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(119, '2025-06-20', 6, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(120, '2025-06-20', 6, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(121, '2025-06-20', 1, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(122, '2025-06-20', 1, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(123, '2025-06-20', 5, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(124, '2025-06-20', 5, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(125, '2025-06-20', 10, 4, 3, 1, NULL, 8.00, '2025-06-20 06:45:30', '2025-06-20 06:45:30', 6, NULL), +(126, '2025-06-20', 3, 4, 3, 1, NULL, 8.00, '2025-06-20 06:45:31', '2025-06-20 06:45:31', 6, NULL), +(127, '2025-06-23', 10, 4, 3, 1, NULL, 8.00, '2025-06-23 06:42:58', '2025-06-23 06:42:58', 6, NULL), +(128, '2025-06-23', 3, 4, 3, 1, NULL, 8.00, '2025-06-23 06:42:58', '2025-06-23 06:42:58', 6, NULL), +(129, '2025-06-23', 5, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(130, '2025-06-23', 5, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(131, '2025-06-23', 1, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(132, '2025-06-23', 1, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(133, '2025-06-23', 9, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(134, '2025-06-23', 9, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(135, '2025-06-23', 4, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(136, '2025-06-23', 4, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(137, '2025-06-23', 7, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(138, '2025-06-23', 7, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(139, '2025-06-23', 6, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(140, '2025-06-23', 6, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(141, '2025-06-24', 10, 4, 3, 1, NULL, 12.00, '2025-06-24 11:10:32', '2025-06-24 11:10:32', 6, NULL), +(142, '2025-06-24', 3, 4, 3, 1, NULL, 12.00, '2025-06-24 11:10:32', '2025-06-24 11:10:32', 6, NULL), +(143, '2025-06-24', 9, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(144, '2025-06-24', 9, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(145, '2025-06-24', 5, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(146, '2025-06-24', 5, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(147, '2025-06-24', 4, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(148, '2025-06-24', 4, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(149, '2025-06-24', 7, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(150, '2025-06-24', 7, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(151, '2025-06-24', 6, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(152, '2025-06-24', 6, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(153, '2025-06-24', 1, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(154, '2025-06-24', 1, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(155, '2025-06-24', 8, 3, 2, 1, NULL, 8.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(156, '2025-06-24', 8, 3, 2, 1, NULL, 4.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(157, '2025-06-24', 2, 3, 2, 1, NULL, 8.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(158, '2025-06-24', 2, 3, 2, 1, NULL, 4.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(159, '2025-06-25', 2, 3, 2, 1, NULL, 8.00, '2025-06-25 11:08:04', '2025-06-25 11:08:04', 5, NULL), +(160, '2025-06-25', 2, 3, 2, 1, NULL, 4.00, '2025-06-25 11:08:04', '2025-06-25 11:08:04', 5, NULL), +(161, '2025-06-25', 8, 3, 2, 1, NULL, 8.00, '2025-06-25 11:08:05', '2025-06-25 11:08:05', 5, NULL), +(162, '2025-06-25', 8, 3, 2, 1, NULL, 4.00, '2025-06-25 11:08:05', '2025-06-25 11:08:05', 5, NULL), +(163, '2025-06-25', 10, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(164, '2025-06-25', 9, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(165, '2025-06-25', 3, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(166, '2025-06-25', 6, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(167, '2025-06-26', 10, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(168, '2025-06-26', 5, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(169, '2025-06-26', 7, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(170, '2025-06-26', 1, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(171, '2025-06-26', 4, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(172, '2025-06-26', 8, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:31', '2025-06-26 11:11:31', 5, NULL), +(173, '2025-06-26', 8, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:31', '2025-06-26 11:11:31', 5, NULL), +(174, '2025-06-26', 2, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(175, '2025-06-26', 2, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(176, '2025-06-26', 9, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(177, '2025-06-26', 9, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(178, '2025-06-26', 3, 3, 2, 1, NULL, 12.00, '2025-06-26 11:19:34', '2025-06-26 11:19:34', 6, NULL), +(179, '2025-06-26', 6, 3, 2, 1, NULL, 12.00, '2025-06-26 11:19:34', '2025-06-26 11:19:34', 6, NULL), +(182, '2025-06-27', 2, 3, 2, 1, NULL, 4.00, '2025-06-27 01:54:40', '2025-06-27 01:54:40', 5, NULL), +(183, '2025-06-27', 9, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(184, '2025-06-27', 10, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(185, '2025-06-27', 7, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(186, '2025-06-27', 5, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(187, '2025-06-27', 4, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(188, '2025-06-27', 1, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(189, '2025-06-27', 3, 3, 2, 1, NULL, 8.00, '2025-06-27 06:49:08', '2025-06-27 06:49:08', 6, NULL), +(191, '2025-06-27', 6, 3, 2, 1, NULL, 4.00, '2025-06-27 06:58:46', '2025-06-27 06:58:46', 6, NULL), +(192, '2025-06-27', 8, 3, 2, 1, NULL, 6.00, '2025-06-27 07:00:10', '2025-06-27 07:00:10', 5, NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `EquipmentList` +-- + +CREATE TABLE `EquipmentList` ( + `equipment_id` int(11) NOT NULL, + `factory_id` int(11) DEFAULT NULL, + `equipment_name` varchar(255) NOT NULL, + `model` varchar(100) DEFAULT NULL, + `status` text DEFAULT 'operational', + `purchase_date` date DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `error_types` +-- + +CREATE TABLE `error_types` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL COMMENT '에러 유형명', + `description` text DEFAULT NULL COMMENT '에러 설명', + `severity` enum('low','medium','high','critical') DEFAULT 'medium' COMMENT '심각도', + `solution_guide` text DEFAULT NULL COMMENT '해결 가이드', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `error_types` +-- + +INSERT INTO `error_types` (`id`, `name`, `description`, `severity`, `solution_guide`, `created_at`, `updated_at`) VALUES +(1, '설계미스', '설계미스', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:03'), +(2, '외주작업 불량', '입고 자재 불량', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:05'), +(3, '입고지연', '자재 미입고', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:11'), +(4, '작업불량', '작업자 실수', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:13'), +(5, '설비고장', '장비없음', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:16'), +(6, '검사불량', '검사불량', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-24 04:36:18'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `FactoryInfo` +-- + +CREATE TABLE `FactoryInfo` ( + `factory_id` int(11) NOT NULL, + `factory_name` varchar(255) NOT NULL, + `address` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `map_image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `FactoryInfo` +-- + +INSERT INTO `FactoryInfo` (`factory_id`, `factory_name`, `address`, `description`, `map_image_url`, `created_at`, `updated_at`) VALUES +(3, '제1공장 휴게공간 및 작업자 사물함', '현대기아로 771-9', '개인 보관함, 컨테이너(휴게공간), 화장실, 흡연장', '/uploads/map_image-1746593523450.png', '2025-05-07 04:52:03', '2025-05-07 04:52:03'), +(4, '제 1공장 공구 및 용접봉 보관 구역', '현대기아로 771-9', '소모품, 공구류, 용접봉 보관 구역', '/uploads/map_image-1746593674259.png', '2025-05-07 04:53:59', '2025-05-07 04:53:59'), +(5, 'ee', 'ee', 'ee', NULL, '2025-06-03 22:13:23', '2025-06-03 22:13:23'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `IssueTypes` +-- + +CREATE TABLE `IssueTypes` ( + `issue_type_id` int(11) NOT NULL, + `category` varchar(100) NOT NULL, + `subcategory` varchar(100) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `IssueTypes` +-- + +INSERT INTO `IssueTypes` (`issue_type_id`, `category`, `subcategory`) VALUES +(1, '구매팀', '자재입고지연'), +(2, '구매팀', '자재전달 미흡'), +(3, '품질', '검사 내용 전달 미흡'), +(4, '품질', '검사오류'), +(5, '설계', '설계미스(치수)'), +(6, '설계', '설계미스(작업불가)'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `login_logs` +-- + +CREATE TABLE `login_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `login_time` datetime DEFAULT current_timestamp(), + `logout_time` datetime DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `login_status` enum('success','failed','locked') DEFAULT 'success', + `failure_reason` varchar(100) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `login_logs` +-- + +INSERT INTO `login_logs` (`log_id`, `user_id`, `login_time`, `logout_time`, `ip_address`, `user_agent`, `login_status`, `failure_reason`) VALUES +(1, 3, '2025-06-15 05:58:39', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(3, 4, '2025-06-15 06:04:06', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(4, 3, '2025-06-15 06:24:53', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(5, 3, '2025-06-15 06:24:55', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(6, 3, '2025-06-15 06:32:41', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(7, 3, '2025-06-15 07:03:19', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(8, 3, '2025-06-15 07:03:21', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(9, 3, '2025-06-15 07:03:25', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(10, 1, '2025-06-15 07:40:16', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(11, 6, '2025-06-15 07:42:02', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(12, 3, '2025-06-15 07:43:30', NULL, '118.235.6.135', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(13, 3, '2025-06-15 22:02:59', NULL, '118.235.6.29', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(14, 4, '2025-06-15 22:15:25', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(15, 3, '2025-06-15 22:15:34', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(16, 6, '2025-06-15 22:15:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'failed', 'invalid_password'), +(17, 6, '2025-06-15 22:15:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(18, 3, '2025-06-15 22:16:39', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(19, 3, '2025-06-15 22:17:14', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(20, 6, '2025-06-15 22:21:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(21, 1, '2025-06-15 22:21:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(22, 6, '2025-06-15 22:22:06', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(23, 5, '2025-06-15 22:22:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(24, 6, '2025-06-15 22:23:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(25, 3, '2025-06-15 22:24:49', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(26, 3, '2025-06-15 22:30:18', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(27, 3, '2025-06-15 22:31:21', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(28, 5, '2025-06-15 22:44:31', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(29, 4, '2025-06-15 22:57:51', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(30, 4, '2025-06-15 22:57:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(31, 4, '2025-06-15 22:57:54', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(32, 4, '2025-06-15 22:57:55', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(33, 4, '2025-06-15 23:11:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(34, 4, '2025-06-15 23:28:04', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(35, 3, '2025-06-15 23:33:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(36, 3, '2025-06-16 00:58:53', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(37, 3, '2025-06-16 01:15:46', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(38, 5, '2025-06-16 01:16:43', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(39, 1, '2025-06-16 01:25:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(40, 1, '2025-06-16 01:26:08', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(41, 3, '2025-06-16 02:27:20', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(42, 3, '2025-06-16 02:45:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(43, 3, '2025-06-16 03:04:13', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(44, 3, '2025-06-16 03:17:28', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(45, 5, '2025-06-16 03:17:55', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(46, 3, '2025-06-16 03:18:56', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(47, 5, '2025-06-16 03:19:13', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(48, 1, '2025-06-16 03:55:56', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(49, 1, '2025-06-16 04:24:37', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(50, 1, '2025-06-16 04:51:36', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(51, 1, '2025-06-16 05:07:05', NULL, '118.235.7.233', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(52, 1, '2025-06-16 05:07:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(53, 1, '2025-06-16 05:43:14', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(54, 5, '2025-06-16 06:11:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(55, 1, '2025-06-16 06:19:46', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(56, 1, '2025-06-16 06:23:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(57, 1, '2025-06-16 06:39:12', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(58, 3, '2025-06-16 06:45:26', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(59, 6, '2025-06-16 06:46:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(60, 1, '2025-06-16 21:18:09', NULL, '118.235.7.45', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(61, 1, '2025-06-17 08:15:45', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(62, 5, '2025-06-17 08:22:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(63, 3, '2025-06-17 08:23:05', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'failed', 'invalid_password'), +(64, 3, '2025-06-17 08:23:21', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(65, 3, '2025-06-17 08:28:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(66, 3, '2025-06-17 08:32:25', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(67, 6, '2025-06-17 08:33:07', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(68, 1, '2025-06-17 08:36:01', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(69, 5, '2025-06-17 09:00:56', NULL, '118.235.7.173', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(70, 3, '2025-06-18 02:30:13', NULL, '118.235.6.77', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(71, 1, '2025-06-18 08:07:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(72, 1, '2025-06-18 08:07:47', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(73, 5, '2025-06-18 08:39:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(74, 6, '2025-06-18 08:46:53', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(75, 3, '2025-06-18 08:47:03', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(76, 6, '2025-06-18 08:57:48', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(77, 5, '2025-06-18 08:58:14', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(78, 3, '2025-06-18 08:59:12', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(79, 5, '2025-06-19 06:37:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(80, 3, '2025-06-19 06:57:01', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(81, 6, '2025-06-19 06:57:22', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(82, 5, '2025-06-19 06:57:56', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(83, 6, '2025-06-19 06:58:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(84, 3, '2025-06-19 06:59:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(85, 3, '2025-06-20 06:42:26', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(86, 6, '2025-06-20 06:45:06', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(87, 5, '2025-06-20 06:49:26', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(88, 3, '2025-06-20 06:49:47', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(89, 6, '2025-06-20 06:50:17', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(90, 3, '2025-06-20 22:46:20', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(91, 1, '2025-06-23 05:03:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(92, 6, '2025-06-23 06:41:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(93, 3, '2025-06-23 06:49:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(94, 6, '2025-06-23 06:50:01', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(95, 5, '2025-06-23 06:50:28', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(96, 1, '2025-06-24 05:24:17', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(97, 3, '2025-06-24 05:25:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(98, 1, '2025-06-24 09:22:29', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(99, 3, '2025-06-24 11:09:38', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(100, 6, '2025-06-24 11:09:48', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(101, 5, '2025-06-24 11:10:23', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(102, 3, '2025-06-24 11:11:29', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(103, 5, '2025-06-24 11:12:06', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(104, 6, '2025-06-24 11:12:31', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(105, 3, '2025-06-24 21:41:01', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(106, 3, '2025-06-25 04:40:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(107, 3, '2025-06-25 05:24:57', NULL, '118.235.6.179', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(108, 1, '2025-06-25 07:05:20', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(109, 1, '2025-06-25 07:06:41', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(110, 3, '2025-06-25 07:09:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(111, 3, '2025-06-25 08:49:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(112, 3, '2025-06-25 09:20:05', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(113, 3, '2025-06-25 09:40:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(114, 3, '2025-06-25 09:57:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(115, 1, '2025-06-25 10:11:03', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(116, 1, '2025-06-25 10:26:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(117, 1, '2025-06-25 10:49:29', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(118, 5, '2025-06-25 11:07:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(119, 6, '2025-06-25 11:10:41', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(120, 6, '2025-06-25 11:13:55', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(121, 5, '2025-06-25 11:14:25', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(122, 6, '2025-06-25 11:20:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(123, 1, '2025-06-25 11:24:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(124, 3, '2025-06-26 10:27:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(125, 5, '2025-06-26 11:10:47', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(126, 6, '2025-06-26 11:15:57', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(127, 3, '2025-06-26 11:17:07', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(128, 5, '2025-06-26 11:17:40', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(129, 6, '2025-06-26 11:19:00', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(130, 1, '2025-06-26 22:15:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(131, 1, '2025-06-26 22:31:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(132, 1, '2025-06-26 22:47:22', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(133, 5, '2025-06-27 01:52:48', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(134, 5, '2025-06-27 01:53:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(135, 3, '2025-06-27 06:47:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(136, 6, '2025-06-27 06:48:39', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(137, 3, '2025-06-27 06:57:15', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(138, 5, '2025-06-27 06:57:34', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(139, 6, '2025-06-27 06:57:59', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(140, 3, '2025-06-27 06:59:04', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(141, 5, '2025-06-27 06:59:29', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `password_change_logs` +-- + +CREATE TABLE `password_change_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) NOT NULL, + `changed_by_user_id` int(11) DEFAULT NULL, + `changed_at` datetime DEFAULT current_timestamp(), + `change_type` enum('self','admin','reset','initial') DEFAULT 'self', + `ip_address` varchar(45) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `password_change_logs` +-- + +INSERT INTO `password_change_logs` (`log_id`, `user_id`, `changed_by_user_id`, `changed_at`, `change_type`, `ip_address`) VALUES +(1, 4, NULL, '2025-06-15 06:03:42', 'admin', NULL), +(2, 3, NULL, '2025-06-15 06:03:52', 'admin', NULL), +(3, 3, 3, '2025-06-15 06:32:30', 'self', NULL), +(4, 3, 1, '2025-06-15 07:40:39', 'admin', NULL), +(5, 5, 1, '2025-06-15 07:41:02', 'initial', NULL), +(6, 6, 1, '2025-06-15 07:41:32', 'initial', NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `PipeSpecs` +-- + +CREATE TABLE `PipeSpecs` ( + `spec_id` int(11) NOT NULL, + `material` varchar(50) NOT NULL COMMENT '재질 (예: SS400, STS304)', + `diameter_in` varchar(10) NOT NULL COMMENT '직경 (inch, 예: 2")', + `schedule` varchar(50) NOT NULL COMMENT '스케줄 (예: STD, SCH10, SCH40)' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `PipeSpecs` +-- + +INSERT INTO `PipeSpecs` (`spec_id`, `material`, `diameter_in`, `schedule`) VALUES +(2, '516-70N', '1', 'SCH80'), +(1, 'A106', '3/4', 'SCH80'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Processes` +-- + +CREATE TABLE `Processes` ( + `process_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `process_name` varchar(255) NOT NULL, + `process_start` date NOT NULL, + `process_end` date DEFAULT NULL, + `planned_worker_count` int(11) NOT NULL, + `process_description` text DEFAULT NULL, + `note` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Projects` +-- + +CREATE TABLE `Projects` ( + `project_id` int(11) NOT NULL, + `job_no` varchar(50) NOT NULL, + `project_name` varchar(255) NOT NULL, + `contract_date` date DEFAULT NULL, + `due_date` date DEFAULT NULL, + `delivery_method` varchar(100) DEFAULT NULL, + `site` varchar(100) DEFAULT NULL, + `pm` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Projects` +-- + +INSERT INTO `Projects` (`project_id`, `job_no`, `project_name`, `contract_date`, `due_date`, `delivery_method`, `site`, `pm`, `created_at`, `updated_at`) VALUES +(1, 'TKO-24008P', 'YHP Project', '2024-05-16', '2025-05-16', 'FOB', 'Quang Ninh(Vietnam)', '장형태', '2025-04-15 22:40:28', '2025-04-15 22:40:28'), +(2, 'TKG-24009P', '한화에어로스페이스 순천', '2024-06-05', '2025-05-31', '.', '순천', '장형태', '2025-04-15 22:42:41', '2025-04-15 22:42:41'), +(3, 'TKG-24011P', '효성화학 에틸렌 탱크 건설공사', '2024-06-22', '2025-12-25', '.', '울산', '김길종', '2025-04-15 22:43:53', '2025-04-15 22:43:53'), +(4, 'TKG-24013P', '김천 솔라 파워 그린 수소 Project', '2024-10-08', '2025-07-25', '.', '김천', '김길종', '2025-04-15 22:44:57', '2025-04-15 22:44:57'), +(5, 'TKG-24016P', 'LG Chem P3RE Project', '2024-11-27', '2025-09-30', '.', '.', '장형태', '2025-04-15 22:46:36', '2025-04-15 22:46:36'), +(7, 'TKO-25003F', '25년 안전보건시설설비', '2025-01-03', '2025-12-31', '.', '.', '.', '2025-04-15 22:47:32', '2025-04-15 22:47:32'), +(8, 'TKG-25007P', 'P Project', '2025-01-16', '2025-10-31', '.', '오창읍', '장형태', '2025-04-15 22:48:50', '2025-04-15 22:48:50'), +(10, 'TKR-25008P', 'DIG Airgas LG CHEM', '2025-01-23', '2025-10-15', '.', '여수', '서태원', '2025-04-15 22:50:05', '2025-04-15 22:50:05'), +(11, 'TKR-25010P', 'FK FISCHER Project', '2025-03-12', '2025-11-30', '.', '울산', '전상신', '2025-04-15 22:51:12', '2025-04-15 22:51:12'), +(12, 'TKO-24007P', 'MP7 Project', '2024-07-03', '2025-01-05', '.', '.', '윤지민', '2025-04-15 23:56:26', '2025-04-15 23:56:26'), +(13, '연차/휴무', '연차/휴무', '2025-01-01', '2025-12-31', '.', '.', '.', '2025-04-16 01:58:23', '2025-04-16 01:58:23'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Tasks` +-- + +CREATE TABLE `Tasks` ( + `task_id` int(11) NOT NULL, + `category` varchar(255) NOT NULL, + `subcategory` varchar(255) DEFAULT NULL, + `task_name` varchar(255) NOT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Tasks` +-- + +INSERT INTO `Tasks` (`task_id`, `category`, `subcategory`, `task_name`, `description`, `created_at`, `updated_at`) VALUES +(1, 'Base', 'Fabrication', '용접', '...', '2025-04-15 10:41:43', '2025-04-15 10:41:43'), +(3, 'Vessel', 'MI and Marking', 'Marking', '..', '2025-04-15 22:25:58', '2025-04-15 22:25:58'), +(4, 'Vessel', 'Cutting', '자재 커팅', '..', '2025-04-15 22:26:17', '2025-04-15 22:26:17'), +(5, 'Vessel', 'Fabrication', '용접', '..', '2025-04-15 22:26:43', '2025-04-15 22:26:43'), +(7, 'PKG', 'Pipe Pre-Fabrication', '취부&용접', '배관사 1명\n용접사 1명', '2025-04-15 22:37:14', '2025-04-15 22:37:14'), +(8, 'PKG', '1st Piping Assembly', '1차 조립', '.', '2025-04-15 22:38:49', '2025-04-15 22:38:49'), +(9, 'PKG', 'Re-Assembly', '재조립', '.', '2025-04-15 22:39:18', '2025-04-15 22:39:18'), +(13, '작업지원', '구매팀', '.', '.', '2025-04-16 03:03:40', '2025-04-16 03:03:40'), +(14, '기타', '시설설비제작', '.', '.', '2025-04-16 03:30:53', '2025-04-16 03:30:53'), +(15, '기타', '휴가/연차/휴무', '.', '.', '2025-04-16 05:18:13', '2025-04-16 05:18:13'), +(16, 'PKG', '제품설치', '설치작업', 'Skid, 용기 등 설치', '2025-04-29 04:39:36', '2025-04-29 04:39:36'), +(18, '작업지원', '품질팀', 'test지원', '.', '2025-06-25 07:07:08', '2025-06-25 07:07:08'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `uploaded_documents` +-- + +CREATE TABLE `uploaded_documents` ( + `id` int(11) NOT NULL, + `title` varchar(255) NOT NULL, + `tags` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `original_name` varchar(255) DEFAULT NULL, + `stored_name` varchar(255) NOT NULL, + `file_path` varchar(500) DEFAULT NULL, + `file_type` varchar(50) DEFAULT NULL, + `file_size` int(11) DEFAULT NULL, + `submitted_by` varchar(100) DEFAULT NULL, + `dt_imported` tinyint(1) DEFAULT 0, + `dt_uuid` varchar(100) DEFAULT NULL, + `of_task_created` tinyint(1) DEFAULT 0, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Users` +-- + +CREATE TABLE `Users` ( + `user_id` int(11) NOT NULL, + `username` varchar(100) NOT NULL, + `password` varchar(255) NOT NULL, + `role` varchar(30) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `access_level` varchar(30) DEFAULT NULL, + `worker_id` int(11) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `last_login_at` datetime DEFAULT NULL, + `password_changed_at` datetime DEFAULT NULL, + `failed_login_attempts` int(11) DEFAULT 0, + `locked_until` datetime DEFAULT NULL, + `name` varchar(50) DEFAULT NULL, + `email` varchar(255) DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Users` +-- + +INSERT INTO `Users` (`user_id`, `username`, `password`, `role`, `created_at`, `access_level`, `worker_id`, `is_active`, `last_login_at`, `password_changed_at`, `failed_login_attempts`, `locked_until`, `name`, `email`, `updated_at`) VALUES +(1, 'hyungi', '$2b$10$lwSfKipx0fQ.9nfMUBmzt.WXzerdxuT5MVX4b3YhFeHxyYlUjM7bi', 'admin', '2025-05-06 05:03:02', 'system', NULL, 1, '2025-06-26 22:47:22', '2025-05-06 05:03:02', 0, NULL, NULL, NULL, '2025-06-26 22:47:22'), +(3, '김두수', '$2a$10$z3i2EVOotRFBj.KHzx5LQOKlXD0QHLNFEvJcd6FlO6/1TCYGk6SSu', 'leader', '2025-06-07 23:48:35', 'group_leader', 1, 1, '2025-06-27 06:59:04', '2025-06-15 07:40:39', 0, NULL, '김두수', NULL, '2025-06-27 06:59:04'), +(4, '김아무개', '$2a$10$QAJIoPyi.apz91exp8GsiO/prAD5Xwanht6XImP1jvKsy/7Ba/b8.', 'user', '2025-06-11 08:03:59', 'worker', NULL, 1, '2025-06-15 23:28:04', '2025-06-15 06:03:42', 0, NULL, '김아무개', NULL, '2025-06-15 23:28:04'), +(5, '임영규', '$2a$10$66ps/MEEi4BVABfJc5P0y.yCap09NhTMyd1A/7rFVxESytQGlB3wC', NULL, '2025-06-15 07:41:02', 'group_leader', 3, 1, '2025-06-27 06:59:29', '2025-06-15 07:41:02', 0, NULL, '임영규', NULL, '2025-06-27 06:59:29'), +(6, '반치원', '$2a$10$jcn6f7flRLZlr5yKQcXDIePodRK0rsM4deNnNGjuOlredeTVsRYZ6', NULL, '2025-06-15 07:41:32', 'group_leader', 3, 1, '2025-06-27 06:57:59', '2025-06-15 07:41:32', 0, NULL, '반치원', NULL, '2025-06-27 06:57:59'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Workers` +-- + +CREATE TABLE `Workers` ( + `worker_id` int(11) NOT NULL, + `worker_name` varchar(100) NOT NULL, + `join_date` date DEFAULT NULL, + `job_type` varchar(100) DEFAULT NULL, + `salary` decimal(10,2) DEFAULT NULL, + `annual_leave` int(11) DEFAULT NULL, + `status` text DEFAULT 'active', + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Workers` +-- + +INSERT INTO `Workers` (`worker_id`, `worker_name`, `join_date`, `job_type`, `salary`, `annual_leave`, `status`, `created_at`, `updated_at`) VALUES +(1, '김두수', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:08', '2025-04-15 22:23:08'), +(2, '임영규', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:17', '2025-04-15 22:23:17'), +(3, '반치원', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:22', '2025-04-15 22:23:22'), +(4, '황인용', '2025-04-01', '가공,조공', 220000.00, 15, '..', '2025-04-15 22:23:33', '2025-04-15 22:23:33'), +(5, '표영진', '2025-04-01', '가공,조공', 220000.00, 15, '..', '2025-04-15 22:23:38', '2025-04-15 22:23:38'), +(6, '김윤섭', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:23:46', '2025-04-15 22:23:46'), +(7, '이창호', '2025-04-01', '용접,배관', 220000.00, 15, '..', '2025-04-15 22:23:51', '2025-04-15 22:23:51'), +(8, '최광욱', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:23:57', '2025-04-15 22:23:57'), +(9, '박현수', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:24:01', '2025-04-15 22:24:01'), +(10, '조윤호', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:24:07', '2025-04-15 22:24:07'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `worker_groups` +-- + +CREATE TABLE `worker_groups` ( + `id` int(11) NOT NULL, + `group_leader_id` int(11) NOT NULL, + `worker_id` int(11) NOT NULL, + `group_name` varchar(100) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `WorkReports` +-- + +CREATE TABLE `WorkReports` ( + `id` int(11) NOT NULL, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `morning_task_id` int(11) DEFAULT NULL, + `afternoon_task_id` int(11) DEFAULT NULL, + `overtime_hours` decimal(4,1) DEFAULT 0.0, + `overtime_task_id` int(11) DEFAULT NULL, + `work_details` text DEFAULT NULL, + `note` text DEFAULT NULL, + `memo` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `morning_project_id` int(11) DEFAULT NULL, + `afternoon_project_id` int(11) DEFAULT NULL, + `overtime_project_id` int(11) DEFAULT NULL, + `task_id` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `WorkReports` +-- + +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(176, '2025-01-02', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(177, '2025-01-02', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(178, '2025-01-02', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(179, '2025-01-02', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(180, '2025-01-02', 8, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(181, '2025-01-02', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(182, '2025-01-02', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(183, '2025-01-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 15), +(194, '2025-01-03', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(195, '2025-01-03', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(196, '2025-01-03', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 15), +(197, '2025-01-03', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(198, '2025-01-03', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 15), +(199, '2025-01-03', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(200, '2025-01-03', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(201, '2025-01-03', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(202, '2025-01-03', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(203, '2025-01-04', 7, 12, NULL, NULL, NULL, NULL, '휴일근무', NULL, NULL, '2025-04-16 05:43:25', '2025-04-16 05:43:25', NULL, NULL, NULL, 12), +(204, '2025-01-06', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:03', '2025-04-16 05:44:03', NULL, NULL, NULL, 12), +(205, '2025-01-06', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:03', '2025-04-16 05:44:03', NULL, NULL, NULL, 12), +(206, '2025-01-06', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(207, '2025-01-06', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(208, '2025-01-06', 8, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(209, '2025-01-06', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(210, '2025-01-06', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(211, '2025-01-06', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(212, '2025-01-06', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(213, '2025-01-07', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(214, '2025-01-07', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 1), +(215, '2025-01-07', 3, 12, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(216, '2025-01-07', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(217, '2025-01-07', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 1), +(218, '2025-01-07', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(219, '2025-01-07', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(220, '2025-01-07', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:25', '2025-04-16 05:45:25', NULL, NULL, NULL, 12), +(221, '2025-01-07', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:25', '2025-04-16 05:45:25', NULL, NULL, NULL, 1), +(222, '2025-01-08', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(223, '2025-01-08', 2, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(224, '2025-01-08', 3, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(225, '2025-01-08', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(226, '2025-01-08', 8, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(227, '2025-01-08', 9, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(228, '2025-01-08', 6, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(229, '2025-01-08', 4, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(230, '2025-01-08', 5, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(231, '2025-01-09', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(232, '2025-01-09', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(233, '2025-01-09', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(234, '2025-01-09', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(235, '2025-01-09', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(236, '2025-01-09', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(237, '2025-01-09', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(238, '2025-01-09', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(239, '2025-01-09', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(240, '2025-01-10', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:16', '2025-04-16 05:49:16', NULL, NULL, NULL, 13), +(241, '2025-01-10', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(242, '2025-01-10', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(243, '2025-01-10', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(244, '2025-01-10', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(245, '2025-01-10', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(246, '2025-01-10', 6, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 15), +(247, '2025-01-10', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(248, '2025-01-10', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(249, '2025-01-13', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(250, '2025-01-13', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(251, '2025-01-13', 3, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(252, '2025-01-13', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(253, '2025-01-13', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(254, '2025-01-13', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(255, '2025-01-13', 6, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(256, '2025-01-13', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 15), +(257, '2025-01-13', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(258, '2025-01-14', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(259, '2025-01-14', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(260, '2025-01-14', 3, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(261, '2025-01-14', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(262, '2025-01-14', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(263, '2025-01-14', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(265, '2025-01-14', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(266, '2025-01-14', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(267, '2025-01-14', 6, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(268, '2025-01-15', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(269, '2025-01-15', 2, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 14), +(270, '2025-01-15', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(271, '2025-01-15', 7, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 13), +(272, '2025-01-15', 8, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 14), +(273, '2025-01-15', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(275, '2025-01-15', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(276, '2025-01-15', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:38', '2025-04-16 05:52:38', NULL, NULL, NULL, 1), +(277, '2025-01-15', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:38', '2025-04-16 05:52:38', NULL, NULL, NULL, 1), +(278, '2025-01-16', 1, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(279, '2025-01-16', 2, 7, NULL, NULL, NULL, NULL, '근무', NULL, '볼트 보관함 제작', '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 14), +(280, '2025-01-16', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(281, '2025-01-16', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(282, '2025-01-16', 8, 7, NULL, NULL, NULL, NULL, '근무', NULL, '볼트 보관함 제작', '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 14), +(283, '2025-01-16', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(285, '2025-01-16', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(286, '2025-01-16', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(287, '2025-01-16', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(288, '2025-01-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(289, '2025-01-17', 2, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(290, '2025-01-17', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(291, '2025-01-17', 7, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(292, '2025-01-17', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(293, '2025-01-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(295, '2025-01-17', 4, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(296, '2025-01-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(297, '2025-01-17', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(298, '2025-01-20', 1, 7, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(299, '2025-01-20', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 8), +(300, '2025-01-20', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(301, '2025-01-20', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(302, '2025-01-20', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(303, '2025-01-20', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(304, '2025-01-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(305, '2025-01-20', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(306, '2025-01-20', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(307, '2025-01-21', 1, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 15), +(308, '2025-01-21', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 8), +(309, '2025-01-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(310, '2025-01-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(311, '2025-01-21', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 8), +(312, '2025-01-21', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 15), +(313, '2025-01-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(314, '2025-01-21', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(315, '2025-01-21', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:07', '2025-04-16 05:59:07', NULL, NULL, NULL, 1), +(316, '2025-01-22', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(317, '2025-01-22', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(318, '2025-01-22', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(319, '2025-01-22', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(320, '2025-01-22', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(321, '2025-01-22', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(322, '2025-01-22', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(323, '2025-01-22', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(324, '2025-01-22', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(325, '2025-01-23', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(326, '2025-01-23', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 8), +(327, '2025-01-23', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(328, '2025-01-23', 7, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(329, '2025-01-23', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(330, '2025-01-23', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(331, '2025-01-23', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(332, '2025-01-23', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(333, '2025-01-23', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 8), +(334, '2025-01-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(335, '2025-01-24', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 8), +(336, '2025-01-24', 3, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(337, '2025-01-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(338, '2025-01-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(339, '2025-01-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(340, '2025-01-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(341, '2025-01-24', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 8), +(342, '2025-01-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(343, '2025-02-03', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(344, '2025-02-03', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 8), +(345, '2025-02-03', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(346, '2025-02-03', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(347, '2025-02-03', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(348, '2025-02-03', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(349, '2025-02-03', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(350, '2025-02-03', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 8), +(351, '2025-02-03', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(352, '2025-02-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(353, '2025-02-04', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(354, '2025-02-04', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 8), +(355, '2025-02-04', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(356, '2025-02-04', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(357, '2025-02-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(358, '2025-02-04', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(359, '2025-02-04', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 8), +(360, '2025-02-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(361, '2025-02-05', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 8), +(362, '2025-02-05', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(363, '2025-02-05', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(364, '2025-02-05', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(365, '2025-02-05', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(366, '2025-02-05', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(367, '2025-02-05', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 1), +(368, '2025-02-05', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 8), +(369, '2025-02-05', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 1), +(370, '2025-02-06', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(371, '2025-02-06', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 15), +(372, '2025-02-06', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(373, '2025-02-06', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(374, '2025-02-06', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(375, '2025-02-06', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(376, '2025-02-06', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(377, '2025-02-06', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(378, '2025-02-06', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(379, '2025-02-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(380, '2025-02-07', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 8), +(381, '2025-02-07', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(382, '2025-02-07', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 15), +(383, '2025-02-07', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(384, '2025-02-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(385, '2025-02-07', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(386, '2025-02-07', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 8), +(387, '2025-02-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(388, '2025-02-10', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(389, '2025-02-10', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 8), +(390, '2025-02-10', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(391, '2025-02-10', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(392, '2025-02-10', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(393, '2025-02-10', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(394, '2025-02-10', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(395, '2025-02-10', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 8), +(396, '2025-02-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(397, '2025-02-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(398, '2025-02-11', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 8), +(399, '2025-02-11', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(400, '2025-02-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(401, '2025-02-11', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(402, '2025-02-11', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(403, '2025-02-11', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(404, '2025-02-11', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 8), +(405, '2025-02-11', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(406, '2025-02-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(407, '2025-02-12', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 8), +(408, '2025-02-12', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(409, '2025-02-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(410, '2025-02-12', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(411, '2025-02-12', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(412, '2025-02-12', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 15), +(413, '2025-02-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(414, '2025-02-12', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(415, '2025-02-13', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(416, '2025-02-13', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 7), +(417, '2025-02-13', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(418, '2025-02-13', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(419, '2025-02-13', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(420, '2025-02-13', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(421, '2025-02-13', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(422, '2025-02-13', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 7), +(423, '2025-02-13', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(424, '2025-02-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(425, '2025-02-14', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 7), +(426, '2025-02-14', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(427, '2025-02-14', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(428, '2025-02-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(429, '2025-02-14', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(430, '2025-02-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(431, '2025-02-14', 4, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 7), +(432, '2025-02-14', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(433, '2025-02-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:39', '2025-04-16 06:18:39', NULL, NULL, NULL, 1), +(434, '2025-02-17', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 8), +(435, '2025-02-17', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(436, '2025-02-17', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(437, '2025-02-17', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 15), +(438, '2025-02-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(439, '2025-02-17', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(440, '2025-02-17', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 8), +(441, '2025-02-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(442, '2025-02-18', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(443, '2025-02-18', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 15), +(444, '2025-02-18', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(445, '2025-02-18', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(446, '2025-02-18', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(447, '2025-02-18', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(448, '2025-02-18', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 7), +(449, '2025-02-18', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(450, '2025-02-18', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(451, '2025-02-19', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(452, '2025-02-19', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(453, '2025-02-19', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(454, '2025-02-19', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(455, '2025-02-19', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(456, '2025-02-19', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(457, '2025-02-19', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(458, '2025-02-19', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(459, '2025-02-19', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(460, '2025-02-20', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(461, '2025-02-20', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(462, '2025-02-20', 3, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(463, '2025-02-20', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(464, '2025-02-20', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(465, '2025-02-20', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(466, '2025-02-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(467, '2025-02-20', 7, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(468, '2025-02-20', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(469, '2025-02-21', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(470, '2025-02-21', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(471, '2025-02-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(472, '2025-02-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(473, '2025-02-21', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(474, '2025-02-21', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(475, '2025-02-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(476, '2025-02-21', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(477, '2025-02-21', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(478, '2025-02-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(479, '2025-02-24', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(480, '2025-02-24', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(481, '2025-02-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(482, '2025-02-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(483, '2025-02-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(484, '2025-02-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(485, '2025-02-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(486, '2025-02-24', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:33', '2025-04-16 06:24:33', NULL, NULL, NULL, 7), +(487, '2025-02-24', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, '근무시작', '2025-04-16 06:25:07', '2025-04-16 06:25:07', NULL, NULL, NULL, 7), +(488, '2025-02-25', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(489, '2025-02-25', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(490, '2025-02-25', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(491, '2025-02-25', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(492, '2025-02-25', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(493, '2025-02-25', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(494, '2025-02-25', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(495, '2025-02-25', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(496, '2025-02-25', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(497, '2025-02-25', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(498, '2025-02-26', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '당진출장 건', '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 14), +(499, '2025-02-26', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(500, '2025-02-26', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(501, '2025-02-26', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '당진출장 건', '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 14), +(502, '2025-02-26', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(503, '2025-02-26', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(504, '2025-02-26', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(505, '2025-02-26', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 15), +(506, '2025-02-26', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(507, '2025-02-26', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(508, '2025-02-27', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(509, '2025-02-27', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(510, '2025-02-27', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(511, '2025-02-27', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(512, '2025-02-27', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(513, '2025-02-27', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(514, '2025-02-27', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(515, '2025-02-27', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(516, '2025-02-27', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(517, '2025-02-27', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(518, '2025-02-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 13), +(519, '2025-02-28', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(520, '2025-02-28', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(521, '2025-02-28', 7, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 13), +(522, '2025-02-28', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(523, '2025-02-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(524, '2025-02-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(525, '2025-02-28', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(526, '2025-02-28', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 15), +(527, '2025-02-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(528, '2025-03-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(529, '2025-03-04', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(530, '2025-03-04', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 8), +(531, '2025-03-04', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 15), +(532, '2025-03-04', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(533, '2025-03-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(534, '2025-03-04', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(535, '2025-03-04', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(536, '2025-03-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(537, '2025-03-04', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 8), +(538, '2025-03-05', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(539, '2025-03-05', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(540, '2025-03-05', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 8), +(541, '2025-03-05', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(542, '2025-03-05', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(543, '2025-03-05', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(544, '2025-03-05', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(545, '2025-03-05', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 15), +(546, '2025-03-05', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(547, '2025-03-05', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 8), +(548, '2025-03-06', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(549, '2025-03-06', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(550, '2025-03-06', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 8), +(551, '2025-03-06', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 15), +(552, '2025-03-06', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(553, '2025-03-06', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(554, '2025-03-06', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(555, '2025-03-06', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(556, '2025-03-06', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(557, '2025-03-06', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 8), +(558, '2025-03-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(559, '2025-03-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 13), +(560, '2025-03-07', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 8), +(561, '2025-03-07', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 15), +(562, '2025-03-07', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(563, '2025-03-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(564, '2025-03-07', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(565, '2025-03-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 13), +(566, '2025-03-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(567, '2025-03-07', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 8), +(568, '2025-03-10', 1, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(569, '2025-03-10', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 3), +(570, '2025-03-10', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(571, '2025-03-10', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 15), +(572, '2025-03-10', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 7), +(573, '2025-03-10', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 15), +(574, '2025-03-10', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 7), +(575, '2025-03-10', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 3), +(576, '2025-03-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(577, '2025-03-10', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(578, '2025-03-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:06', '2025-04-16 06:39:06', NULL, NULL, NULL, 8), +(579, '2025-03-11', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(580, '2025-03-11', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(581, '2025-03-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(582, '2025-03-11', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(583, '2025-03-11', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 15), +(584, '2025-03-11', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(585, '2025-03-11', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(586, '2025-03-11', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(587, '2025-03-11', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(588, '2025-03-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(589, '2025-03-12', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(590, '2025-03-12', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(591, '2025-03-12', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(592, '2025-03-12', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(593, '2025-03-12', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 15), +(594, '2025-03-12', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(595, '2025-03-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(596, '2025-03-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(597, '2025-03-12', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(598, '2025-03-13', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(599, '2025-03-13', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(600, '2025-03-13', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(601, '2025-03-13', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(602, '2025-03-13', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(603, '2025-03-13', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 15), +(604, '2025-03-13', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(605, '2025-03-13', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(606, '2025-03-13', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(607, '2025-03-13', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(608, '2025-03-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(609, '2025-03-14', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 4), +(610, '2025-03-14', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(612, '2025-03-14', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(613, '2025-03-14', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 15), +(614, '2025-03-14', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(615, '2025-03-14', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(616, '2025-03-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(617, '2025-03-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(628, '2025-03-18', 1, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(629, '2025-03-18', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(630, '2025-03-18', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(631, '2025-03-18', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(632, '2025-03-18', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(633, '2025-03-18', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 15), +(634, '2025-03-18', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(635, '2025-03-18', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(636, '2025-03-18', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(637, '2025-03-18', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(648, '2025-03-17', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(649, '2025-03-17', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 4), +(650, '2025-03-17', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(651, '2025-03-17', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 4), +(652, '2025-03-17', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(653, '2025-03-17', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 15), +(654, '2025-03-17', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(655, '2025-03-17', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(656, '2025-03-17', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(657, '2025-03-17', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(658, '2025-03-19', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 4), +(659, '2025-03-19', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(660, '2025-03-19', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(661, '2025-03-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 4), +(662, '2025-03-19', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(663, '2025-03-19', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(664, '2025-03-19', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(665, '2025-03-19', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, '용접기 보관함 제작', '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 14), +(666, '2025-03-19', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 4), +(667, '2025-03-19', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(668, '2025-03-20', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(669, '2025-03-20', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(670, '2025-03-20', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(671, '2025-03-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(672, '2025-03-20', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(673, '2025-03-20', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(674, '2025-03-20', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(675, '2025-03-20', 4, 7, NULL, NULL, 2.0, NULL, '근무', NULL, '용접기 보관함 제작', '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 14), +(676, '2025-03-20', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(677, '2025-03-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(678, '2025-03-21', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:27', '2025-04-16 21:34:27', NULL, NULL, NULL, 8), +(679, '2025-03-21', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(680, '2025-03-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(681, '2025-03-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(682, '2025-03-21', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(683, '2025-03-21', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(684, '2025-03-21', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(685, '2025-03-21', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, '용기 보관함 제작', '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 14), +(686, '2025-03-21', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(687, '2025-03-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(688, '2025-03-24', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(689, '2025-03-24', 2, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(690, '2025-03-24', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(691, '2025-03-24', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(692, '2025-03-24', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(693, '2025-03-24', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(694, '2025-03-24', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(695, '2025-03-24', 4, 7, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 보관함 제작', '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 14), +(696, '2025-03-24', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(697, '2025-03-24', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(698, '2025-03-25', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(699, '2025-03-25', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(700, '2025-03-25', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(701, '2025-03-25', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(702, '2025-03-25', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(703, '2025-03-25', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(704, '2025-03-25', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(705, '2025-03-25', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 14), +(706, '2025-03-25', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(707, '2025-03-25', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(708, '2025-03-26', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 13), +(709, '2025-03-26', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 15), +(710, '2025-03-26', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(711, '2025-03-26', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(712, '2025-03-26', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(713, '2025-03-26', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(714, '2025-03-26', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(715, '2025-03-26', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 13), +(716, '2025-03-26', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(717, '2025-03-26', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(718, '2025-03-27', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(719, '2025-03-27', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(720, '2025-03-27', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(721, '2025-03-27', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(722, '2025-03-27', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(723, '2025-03-27', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(724, '2025-03-27', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 15), +(725, '2025-03-27', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(726, '2025-03-27', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(727, '2025-03-27', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(728, '2025-03-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(729, '2025-03-28', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(730, '2025-03-28', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 15), +(731, '2025-03-28', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 15), +(732, '2025-03-28', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(733, '2025-03-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(734, '2025-03-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(735, '2025-03-28', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(736, '2025-03-28', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(737, '2025-03-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(738, '2025-03-31', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(739, '2025-03-31', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 5), +(740, '2025-03-31', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(741, '2025-03-31', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(742, '2025-03-31', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(743, '2025-03-31', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(744, '2025-03-31', 10, 13, NULL, NULL, NULL, NULL, '유급', NULL, '외조모상(2일)', '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 15), +(745, '2025-03-31', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 5), +(746, '2025-03-31', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(747, '2025-03-31', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(748, '2025-03-14', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-17 01:53:24', '2025-04-17 01:53:24', NULL, NULL, NULL, 4), +(749, '2025-04-01', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(750, '2025-04-01', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(751, '2025-04-01', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(752, '2025-04-01', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(753, '2025-04-01', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(754, '2025-04-01', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(755, '2025-04-01', 10, 13, NULL, NULL, NULL, NULL, '유급', NULL, '외조모상', '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 15), +(756, '2025-04-01', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(757, '2025-04-01', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(758, '2025-04-01', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:43', '2025-04-17 04:22:43', NULL, NULL, NULL, 9), +(769, '2025-04-02', 1, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-17 04:25:55', '2025-04-17 04:25:55', NULL, NULL, NULL, 9), +(770, '2025-04-02', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(771, '2025-04-02', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(773, '2025-04-02', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(774, '2025-04-02', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(775, '2025-04-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 15), +(776, '2025-04-02', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 15), +(777, '2025-04-02', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(778, '2025-04-02', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(779, '2025-04-03', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(780, '2025-04-03', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(781, '2025-04-03', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(783, '2025-04-03', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(784, '2025-04-03', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(785, '2025-04-03', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(786, '2025-04-03', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(787, '2025-04-03', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(788, '2025-04-03', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(789, '2025-04-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(790, '2025-04-04', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(791, '2025-04-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(792, '2025-04-04', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(793, '2025-04-04', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(794, '2025-04-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(795, '2025-04-04', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(796, '2025-04-04', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(797, '2025-04-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(798, '2025-04-04', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(799, '2025-04-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(800, '2025-04-07', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(801, '2025-04-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(802, '2025-04-07', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(803, '2025-04-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(804, '2025-04-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(805, '2025-04-07', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(806, '2025-04-07', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(807, '2025-04-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(808, '2025-04-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(809, '2025-04-08', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(811, '2025-04-08', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(812, '2025-04-08', 7, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(813, '2025-04-08', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(814, '2025-04-08', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(815, '2025-04-08', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(816, '2025-04-08', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(817, '2025-04-08', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(818, '2025-04-08', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(819, '2025-04-09', 1, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-17 04:43:02', '2025-04-17 04:43:02', NULL, NULL, NULL, 9), +(820, '2025-04-09', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:02', '2025-04-17 04:43:02', NULL, NULL, NULL, 9), +(821, '2025-04-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(822, '2025-04-09', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(823, '2025-04-09', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(824, '2025-04-09', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(825, '2025-04-09', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(826, '2025-04-09', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(827, '2025-04-09', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(828, '2025-04-09', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(829, '2025-04-10', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(830, '2025-04-10', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(831, '2025-04-10', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(832, '2025-04-10', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(833, '2025-04-10', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(834, '2025-04-10', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(835, '2025-04-10', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(836, '2025-04-10', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(837, '2025-04-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(838, '2025-04-10', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(839, '2025-04-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 9), +(840, '2025-04-11', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 9), +(841, '2025-04-11', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 5), +(842, '2025-04-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(843, '2025-04-11', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 5), +(844, '2025-04-11', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 15), +(845, '2025-04-11', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 5), +(846, '2025-04-11', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(847, '2025-04-11', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 15), +(848, '2025-04-11', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(849, '2025-04-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(850, '2025-04-14', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(851, '2025-04-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 5), +(852, '2025-04-14', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(853, '2025-04-14', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 5), +(854, '2025-04-14', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(855, '2025-04-14', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(856, '2025-04-14', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(857, '2025-04-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(858, '2025-04-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(859, '2025-04-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(860, '2025-04-17', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(861, '2025-04-17', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(862, '2025-04-17', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(863, '2025-04-17', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(864, '2025-04-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(865, '2025-04-17', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(866, '2025-04-17', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(867, '2025-04-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(868, '2025-04-17', 6, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(879, '2025-04-21', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(880, '2025-04-21', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(881, '2025-04-21', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(882, '2025-04-21', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(883, '2025-04-21', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(884, '2025-04-21', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(885, '2025-04-21', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(886, '2025-04-21', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(887, '2025-04-21', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(888, '2025-04-21', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(889, '2025-04-22', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(890, '2025-04-22', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(891, '2025-04-22', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(892, '2025-04-22', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(893, '2025-04-22', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(894, '2025-04-22', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(895, '2025-04-22', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(896, '2025-04-22', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(897, '2025-04-22', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(898, '2025-04-22', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(899, '2025-04-23', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(900, '2025-04-23', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(901, '2025-04-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(902, '2025-04-23', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(903, '2025-04-23', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(904, '2025-04-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(905, '2025-04-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(906, '2025-04-23', 4, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(907, '2025-04-23', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(908, '2025-04-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(909, '2025-04-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, '벨브 부적합 관련 작업 추가', '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(910, '2025-04-24', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(911, '2025-04-24', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(912, '2025-04-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(913, '2025-04-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(914, '2025-04-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(915, '2025-04-24', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(916, '2025-04-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(917, '2025-04-24', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(918, '2025-04-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(919, '2025-04-25', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(920, '2025-04-25', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(921, '2025-04-25', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 5), +(922, '2025-04-25', 7, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(923, '2025-04-25', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(924, '2025-04-25', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(925, '2025-04-25', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(926, '2025-04-25', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '확관 작업', '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 5), +(927, '2025-04-25', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(928, '2025-04-25', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:39', '2025-04-25 04:23:39', NULL, NULL, NULL, 5), +(929, '2025-04-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:22', '2025-04-28 23:20:22', NULL, NULL, NULL, 9), +(930, '2025-04-28', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(931, '2025-04-28', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(932, '2025-04-28', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(934, '2025-04-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(935, '2025-04-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(936, '2025-04-28', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(937, '2025-04-28', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(938, '2025-04-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(939, '2025-04-29', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 9), +(940, '2025-04-29', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(941, '2025-04-29', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(942, '2025-04-29', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 9), +(943, '2025-04-29', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(944, '2025-04-29', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(945, '2025-04-29', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 14), +(946, '2025-04-29', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(947, '2025-04-29', 8, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(948, '2025-04-29', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(949, '2025-04-30', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(950, '2025-04-30', 2, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(951, '2025-04-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(953, '2025-04-30', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 15), +(954, '2025-04-30', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(955, '2025-04-30', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(956, '2025-04-30', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(957, '2025-04-30', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 15), +(958, '2025-04-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(959, '2025-04-30', 4, 7, NULL, NULL, NULL, NULL, '반반차', NULL, '제2공장 공사', '2025-04-30 04:22:04', '2025-04-30 04:22:04', NULL, NULL, NULL, 14), +(1023, '2025-04-15', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1024, '2025-04-15', 2, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1025, '2025-04-15', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1026, '2025-04-15', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1027, '2025-04-15', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1028, '2025-04-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1029, '2025-04-15', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1030, '2025-04-15', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1031, '2025-04-15', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1032, '2025-04-15', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1033, '2025-04-16', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1034, '2025-04-16', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1035, '2025-04-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(1036, '2025-04-16', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1037, '2025-04-16', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1038, '2025-04-16', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1039, '2025-04-16', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1040, '2025-04-16', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 15), +(1041, '2025-04-16', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1042, '2025-04-16', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1043, '2025-04-18', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1044, '2025-04-18', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1045, '2025-04-18', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1046, '2025-04-18', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1047, '2025-04-18', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 15), +(1048, '2025-04-18', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1049, '2025-04-18', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1050, '2025-04-18', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1051, '2025-04-18', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1052, '2025-04-18', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1053, '2025-04-02', 7, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-07 02:19:00', '2025-05-07 02:19:00', NULL, NULL, NULL, 9), +(1054, '2025-04-03', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 02:19:45', '2025-05-07 02:19:45', NULL, NULL, NULL, 9), +(1055, '2025-04-08', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 02:20:22', '2025-05-07 02:20:22', NULL, NULL, NULL, 9), +(1056, '2025-04-28', 8, 1, NULL, NULL, NULL, NULL, '반반차', NULL, 'NCR 벨브라인 설치', '2025-05-07 02:21:44', '2025-05-07 02:21:44', NULL, NULL, NULL, 9), +(1057, '2025-05-02', 1, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1058, '2025-05-02', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1059, '2025-05-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1060, '2025-05-02', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1061, '2025-05-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1062, '2025-05-02', 6, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1063, '2025-05-02', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1064, '2025-05-02', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1065, '2025-05-02', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1066, '2025-05-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1067, '2025-05-07', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1068, '2025-05-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1069, '2025-05-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1070, '2025-05-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1071, '2025-05-07', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1072, '2025-05-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1073, '2025-05-07', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1074, '2025-05-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1075, '2025-05-07', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1076, '2025-05-07', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1078, '2025-05-08', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1079, '2025-05-08', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1080, '2025-05-08', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1081, '2025-05-08', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1082, '2025-05-08', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1083, '2025-05-08', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1084, '2025-05-08', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1085, '2025-05-08', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1086, '2025-05-08', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1087, '2025-05-08', 1, 7, NULL, NULL, NULL, NULL, '반반차', NULL, '작업장 구역 설치', '2025-05-08 06:57:51', '2025-05-08 06:57:51', NULL, NULL, NULL, 14), +(1088, '2025-05-09', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1089, '2025-05-09', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1090, '2025-05-09', 3, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1091, '2025-05-09', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1092, '2025-05-09', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1093, '2025-05-09', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1094, '2025-05-09', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1095, '2025-05-09', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1096, '2025-05-09', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1097, '2025-05-09', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1100, '2025-05-12', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-11 21:52:46', '2025-05-11 21:52:46', NULL, NULL, NULL, 15), +(1108, '2025-05-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1111, '2025-05-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1113, '2025-05-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1115, '2025-05-12', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1116, '2025-05-12', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1117, '2025-05-13', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1118, '2025-05-13', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1119, '2025-05-13', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1120, '2025-05-13', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1121, '2025-05-13', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1122, '2025-05-13', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1123, '2025-05-13', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1124, '2025-05-13', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1125, '2025-05-13', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1126, '2025-05-13', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1127, '2025-05-12', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1128, '2025-05-12', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1129, '2025-05-12', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1130, '2025-05-12', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1131, '2025-05-14', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1132, '2025-05-14', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1133, '2025-05-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1134, '2025-05-14', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1135, '2025-05-14', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1136, '2025-05-14', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1137, '2025-05-14', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1138, '2025-05-14', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1139, '2025-05-14', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1140, '2025-05-14', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1141, '2025-05-15', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 14), +(1142, '2025-05-15', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1143, '2025-05-15', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1144, '2025-05-15', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1145, '2025-05-15', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1146, '2025-05-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1147, '2025-05-15', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 14), +(1148, '2025-05-15', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1149, '2025-05-15', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1150, '2025-05-15', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1151, '2025-05-16', 1, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1152, '2025-05-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1153, '2025-05-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1154, '2025-05-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1155, '2025-05-16', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1156, '2025-05-16', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1157, '2025-05-16', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1158, '2025-05-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1159, '2025-05-16', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1160, '2025-05-16', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1171, '2025-05-19', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1172, '2025-05-19', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 4), +(1173, '2025-05-19', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1174, '2025-05-19', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1175, '2025-05-19', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1176, '2025-05-19', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1177, '2025-05-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1179, '2025-05-19', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1180, '2025-05-19', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1181, '2025-05-21', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1183, '2025-05-21', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1184, '2025-05-21', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1185, '2025-05-21', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1186, '2025-05-21', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1187, '2025-05-21', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1188, '2025-05-21', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1189, '2025-05-21', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1190, '2025-05-21', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1191, '2025-05-20', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1192, '2025-05-20', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 3), +(1193, '2025-05-20', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1194, '2025-05-20', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1195, '2025-05-20', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1196, '2025-05-20', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1197, '2025-05-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1198, '2025-05-20', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1199, '2025-05-20', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1200, '2025-05-20', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1201, '2025-05-22', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1202, '2025-05-22', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 3), +(1203, '2025-05-22', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1204, '2025-05-22', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1205, '2025-05-22', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1206, '2025-05-22', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1207, '2025-05-22', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1208, '2025-05-22', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1209, '2025-05-22', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1210, '2025-05-22', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1211, '2025-05-21', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-22 04:54:12', '2025-05-22 04:54:12', NULL, NULL, NULL, 15), +(1215, '2025-05-26', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-26 06:58:00', '2025-05-26 06:58:00', NULL, NULL, NULL, 15), +(1222, '2025-05-19', 8, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-01 22:34:36', '2025-06-01 22:34:36', NULL, NULL, NULL, 3), +(1223, '2025-05-26', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1224, '2025-05-26', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1225, '2025-05-26', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1226, '2025-05-26', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1227, '2025-05-26', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1228, '2025-05-26', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1229, '2025-05-26', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1230, '2025-05-26', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1231, '2025-05-26', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1232, '2025-05-23', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1233, '2025-05-23', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 3), +(1234, '2025-05-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1235, '2025-05-23', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1236, '2025-05-23', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1237, '2025-05-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1238, '2025-05-23', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1239, '2025-05-23', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1240, '2025-05-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1241, '2025-05-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1242, '2025-05-27', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1243, '2025-05-27', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1244, '2025-05-27', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1245, '2025-05-27', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1246, '2025-05-27', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1247, '2025-05-27', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1248, '2025-05-27', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1249, '2025-05-27', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1250, '2025-05-27', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1251, '2025-05-27', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1252, '2025-05-28', 1, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-06-01 22:46:40', '2025-06-01 22:46:40', NULL, NULL, NULL, 8), +(1258, '2025-05-28', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:46:40', '2025-06-01 22:46:40', NULL, NULL, NULL, 8), +(1262, '2025-05-28', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1263, '2025-05-28', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1264, '2025-05-28', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1265, '2025-05-28', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1266, '2025-05-28', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1267, '2025-05-28', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1268, '2025-05-28', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1269, '2025-05-28', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1270, '2025-05-29', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1271, '2025-05-29', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1272, '2025-05-29', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1273, '2025-05-29', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1274, '2025-05-29', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1275, '2025-05-29', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1276, '2025-05-29', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1277, '2025-05-29', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1278, '2025-05-29', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1279, '2025-05-29', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1281, '2025-05-30', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1282, '2025-05-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1283, '2025-05-30', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1284, '2025-05-30', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1285, '2025-05-30', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1286, '2025-05-30', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1287, '2025-05-30', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1288, '2025-05-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1289, '2025-05-30', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1290, '2025-06-02', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:18', '2025-06-01 22:52:18', NULL, NULL, NULL, 8), +(1291, '2025-06-02', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 5), +(1292, '2025-06-02', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1293, '2025-06-02', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1294, '2025-06-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1295, '2025-06-02', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1296, '2025-06-02', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1297, '2025-06-02', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1298, '2025-06-02', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1299, '2025-06-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1300, '2025-05-30', 1, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-01 23:17:51', '2025-06-01 23:17:51', NULL, NULL, NULL, 8), +(1301, '2025-01-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 23:31:26', '2025-06-01 23:31:26', NULL, NULL, NULL, 15), +(1302, '2025-06-04', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1303, '2025-06-04', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1304, '2025-06-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1305, '2025-06-04', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 15), +(1306, '2025-06-04', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1307, '2025-06-04', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1308, '2025-06-04', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1309, '2025-06-04', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1310, '2025-06-04', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1311, '2025-06-04', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1312, '2025-06-09', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:28', NULL, NULL, NULL, 8), +(1313, '2025-06-09', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1314, '2025-06-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:30', NULL, NULL, NULL, 8), +(1315, '2025-06-09', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1316, '2025-06-09', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:31', NULL, NULL, NULL, 8), +(1317, '2025-06-09', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1318, '2025-06-09', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:32', NULL, NULL, NULL, 8), +(1319, '2025-06-09', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1320, '2025-06-09', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 15), +(1321, '2025-06-09', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:34', NULL, NULL, NULL, 8), +(1322, '2025-06-10', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:03', '2025-06-13 03:43:51', NULL, NULL, NULL, 8), +(1323, '2025-06-10', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:03', '2025-06-10 08:47:03', NULL, NULL, NULL, 5), +(1324, '2025-06-10', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:03', '2025-06-13 03:43:53', NULL, NULL, NULL, 8), +(1325, '2025-06-10', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:54', NULL, NULL, NULL, 8), +(1326, '2025-06-10', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1327, '2025-06-10', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1328, '2025-06-10', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:55', NULL, NULL, NULL, 8), +(1329, '2025-06-10', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1330, '2025-06-10', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:56', NULL, NULL, NULL, 8), +(1331, '2025-06-10', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:56', NULL, NULL, NULL, 8), +(1332, '2025-06-11', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:18', NULL, NULL, NULL, 8), +(1333, '2025-06-11', 2, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1334, '2025-06-11', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:19', NULL, NULL, NULL, 8), +(1335, '2025-06-11', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:20', NULL, NULL, NULL, 8), +(1336, '2025-06-11', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1337, '2025-06-11', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1338, '2025-06-11', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:22', NULL, NULL, NULL, 8), +(1339, '2025-06-11', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1340, '2025-06-11', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:23', NULL, NULL, NULL, 8), +(1341, '2025-06-11', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:23', NULL, NULL, NULL, 8), +(1342, '2025-06-13', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1343, '2025-06-13', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1344, '2025-06-13', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1345, '2025-06-13', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1346, '2025-06-13', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1347, '2025-06-13', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1348, '2025-06-13', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 15), +(1349, '2025-06-13', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1350, '2025-06-13', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1351, '2025-06-13', 10, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1352, '2025-06-05', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1353, '2025-06-05', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1354, '2025-06-05', 3, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1355, '2025-06-05', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1356, '2025-06-05', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1357, '2025-06-05', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1358, '2025-06-05', 7, 4, NULL, NULL, NULL, NULL, '반반차', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1359, '2025-06-05', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1360, '2025-06-05', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1361, '2025-06-05', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1362, '2025-06-12', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1363, '2025-06-12', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1364, '2025-06-12', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1365, '2025-06-12', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1366, '2025-06-12', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1367, '2025-06-12', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1368, '2025-06-12', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1369, '2025-06-12', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1370, '2025-06-12', 9, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1371, '2025-06-12', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1372, '2025-06-16', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:26', '2025-06-16 04:26:26', NULL, NULL, NULL, 8), +(1373, '2025-06-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1374, '2025-06-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1375, '2025-06-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1376, '2025-06-16', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1377, '2025-06-16', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'Vessel NDE 불량 수리', '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1378, '2025-06-16', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 15), +(1379, '2025-06-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'Vessel NDE 불량 수리', '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1380, '2025-06-16', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1381, '2025-06-16', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1382, '2025-06-17', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1383, '2025-06-17', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1384, '2025-06-17', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1385, '2025-06-17', 4, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:36:28', NULL, NULL, NULL, 5), +(1386, '2025-06-17', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1387, '2025-06-17', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 비파괴 불량', '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1388, '2025-06-17', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1389, '2025-06-17', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 비파괴 불량', '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1390, '2025-06-17', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1391, '2025-06-17', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1392, '2025-06-18', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1393, '2025-06-18', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1394, '2025-06-18', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1395, '2025-06-18', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1396, '2025-06-18', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1397, '2025-06-18', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1398, '2025-06-18', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1399, '2025-06-18', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1400, '2025-06-18', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1401, '2025-06-18', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1402, '2025-06-24', 1, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1403, '2025-06-24', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 5), +(1404, '2025-06-24', 3, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1405, '2025-06-24', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1406, '2025-06-24', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1407, '2025-06-24', 6, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1408, '2025-06-24', 7, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1409, '2025-06-24', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 5), +(1410, '2025-06-24', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1411, '2025-06-24', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1412, '2025-06-25', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1413, '2025-06-25', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 5), +(1414, '2025-06-25', 3, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1415, '2025-06-25', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1416, '2025-06-25', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1417, '2025-06-25', 6, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1418, '2025-06-25', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1419, '2025-06-25', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 5), +(1420, '2025-06-25', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1421, '2025-06-25', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1422, '2025-06-26', 1, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1423, '2025-06-26', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1424, '2025-06-26', 3, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1425, '2025-06-26', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1426, '2025-06-26', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1427, '2025-06-26', 6, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1428, '2025-06-26', 7, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1429, '2025-06-26', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1430, '2025-06-26', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1431, '2025-06-26', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1432, '2025-06-27', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1433, '2025-06-27', 2, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1434, '2025-06-27', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1435, '2025-06-27', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1436, '2025-06-27', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1437, '2025-06-27', 6, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1438, '2025-06-27', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1439, '2025-06-27', 8, 3, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1440, '2025-06-27', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1441, '2025-06-27', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_report_audit_log` +-- + +CREATE TABLE `work_report_audit_log` ( + `log_id` int(11) NOT NULL, + `action` enum('ADD_ACCUMULATE','DELETE_SINGLE','UPDATE','DELETE','CREATE','DELETE_BATCH') NOT NULL COMMENT '작업 유형', + `report_id` int(11) DEFAULT NULL COMMENT '관련 보고서 ID', + `old_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 전 값' CHECK (json_valid(`old_values`)), + `new_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 후 값' CHECK (json_valid(`new_values`)), + `changed_by` int(11) NOT NULL COMMENT '변경자 ID', + `change_reason` varchar(500) DEFAULT NULL COMMENT '변경 사유', + `ip_address` varchar(45) DEFAULT NULL COMMENT 'IP 주소', + `user_agent` text DEFAULT NULL COMMENT '사용자 에이전트', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '변경 시간' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_report_audit_log` +-- + +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(1, 'ADD_ACCUMULATE', 12, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 02:56:12'), +(2, 'DELETE_SINGLE', 12, '{\"worker_name\":\"김두수\",\"project_name\":\"MP7 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:36'), +(3, 'DELETE_SINGLE', 11, '{\"worker_name\":\"김두수\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:39'), +(4, 'DELETE_SINGLE', 7, '{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:41'), +(5, 'ADD_ACCUMULATE', 13, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":1,\"my_total\":\"1.00\",\"grand_total\":1,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"1.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 03:18:37'), +(6, 'DELETE_SINGLE', 13, '{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:19:23'), +(7, 'ADD_ACCUMULATE', 14, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(8, 'ADD_ACCUMULATE', 15, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(9, 'ADD_ACCUMULATE', 16, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(10, 'ADD_ACCUMULATE', 17, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(11, 'ADD_ACCUMULATE', 18, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(12, 'ADD_ACCUMULATE', 19, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(13, 'ADD_ACCUMULATE', 20, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:47'), +(14, 'ADD_ACCUMULATE', 21, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(15, 'ADD_ACCUMULATE', 22, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(16, 'ADD_ACCUMULATE', 23, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(17, 'ADD_ACCUMULATE', 24, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(18, 'ADD_ACCUMULATE', 25, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(19, 'ADD_ACCUMULATE', 26, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(20, 'ADD_ACCUMULATE', 27, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(21, 'ADD_ACCUMULATE', 28, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(22, 'ADD_ACCUMULATE', 29, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(23, 'ADD_ACCUMULATE', 30, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(24, 'ADD_ACCUMULATE', 31, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(25, 'ADD_ACCUMULATE', 32, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(26, 'ADD_ACCUMULATE', 33, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(27, 'ADD_ACCUMULATE', 34, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(28, 'ADD_ACCUMULATE', 35, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(29, 'ADD_ACCUMULATE', 36, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(30, 'ADD_ACCUMULATE', 37, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(31, 'ADD_ACCUMULATE', 38, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(32, 'ADD_ACCUMULATE', 39, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(33, 'ADD_ACCUMULATE', 40, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(34, 'ADD_ACCUMULATE', 41, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(35, 'ADD_ACCUMULATE', 42, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(36, 'ADD_ACCUMULATE', 43, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(37, 'DELETE_SINGLE', 42, '{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:12:33'), +(38, 'ADD_ACCUMULATE', 44, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:13:02'), +(39, 'ADD_ACCUMULATE', 45, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:13:50'), +(40, 'DELETE_SINGLE', 41, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:14:48'), +(41, 'ADD_ACCUMULATE', 46, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:15:22'), +(42, 'DELETE_SINGLE', 1, '{\"worker_name\":\"김두수\",\"project_name\":\"25년 안전보건시설설비\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-01T00:00:00.000Z\"}', NULL, 1, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:20:38'), +(43, 'ADD_ACCUMULATE', 48, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(44, 'ADD_ACCUMULATE', 49, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(45, 'ADD_ACCUMULATE', 50, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(46, 'DELETE_SINGLE', 49, '{\"worker_name\":\"박현수\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:47:54'), +(47, 'ADD_ACCUMULATE', 51, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:48:29'), +(48, 'ADD_ACCUMULATE', 52, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-16 06:50:09'), +(49, 'ADD_ACCUMULATE', 54, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-16 06:50:09'), +(50, 'ADD_ACCUMULATE', 56, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:23:41'), +(51, 'ADD_ACCUMULATE', 58, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:23:41'), +(52, 'ADD_ACCUMULATE', 60, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:33'), +(53, 'ADD_ACCUMULATE', 62, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:33'), +(54, 'ADD_ACCUMULATE', 64, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:44'), +(55, 'ADD_ACCUMULATE', 65, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:25:24'), +(56, 'DELETE_SINGLE', 64, '{\"worker_name\":\"황인용\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-17T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-17 08:26:17'), +(57, 'ADD_ACCUMULATE', 66, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:27:06'), +(58, 'ADD_ACCUMULATE', 67, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:27:06'), +(59, 'ADD_ACCUMULATE', 68, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(60, 'ADD_ACCUMULATE', 69, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(61, 'ADD_ACCUMULATE', 70, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(62, 'ADD_ACCUMULATE', 71, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(63, 'ADD_ACCUMULATE', 72, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(64, 'ADD_ACCUMULATE', 73, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(65, 'ADD_ACCUMULATE', 74, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-17 08:34:11'), +(66, 'ADD_ACCUMULATE', 76, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-17 08:34:11'), +(67, 'ADD_ACCUMULATE', 78, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(68, 'ADD_ACCUMULATE', 79, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(69, 'ADD_ACCUMULATE', 80, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(70, 'ADD_ACCUMULATE', 81, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:02'), +(71, 'ADD_ACCUMULATE', 82, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:03'), +(72, 'ADD_ACCUMULATE', 83, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:03'), +(73, 'ADD_ACCUMULATE', 84, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:45'), +(74, 'ADD_ACCUMULATE', 86, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-18 08:47:55'), +(75, 'ADD_ACCUMULATE', 88, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-18 08:47:55'), +(76, 'ADD_ACCUMULATE', 90, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(77, 'ADD_ACCUMULATE', 92, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(78, 'ADD_ACCUMULATE', 94, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(79, 'ADD_ACCUMULATE', 96, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 09:00:17'), +(80, 'ADD_ACCUMULATE', 98, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-19 06:37:59'), +(81, 'ADD_ACCUMULATE', 99, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-19 06:37:59'), +(82, 'ADD_ACCUMULATE', 100, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(83, 'ADD_ACCUMULATE', 101, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(84, 'ADD_ACCUMULATE', 102, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(85, 'ADD_ACCUMULATE', 103, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(86, 'ADD_ACCUMULATE', 105, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(87, 'ADD_ACCUMULATE', 107, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(88, 'ADD_ACCUMULATE', 109, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(89, 'ADD_ACCUMULATE', 111, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(90, 'ADD_ACCUMULATE', 113, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(91, 'ADD_ACCUMULATE', 115, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(92, 'ADD_ACCUMULATE', 117, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(93, 'ADD_ACCUMULATE', 119, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(94, 'ADD_ACCUMULATE', 121, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(95, 'ADD_ACCUMULATE', 123, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(96, 'ADD_ACCUMULATE', 125, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-20 06:45:30'), +(97, 'ADD_ACCUMULATE', 126, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-20 06:45:31'), +(98, 'ADD_ACCUMULATE', 127, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-23 06:42:58'), +(99, 'ADD_ACCUMULATE', 128, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-23 06:42:58'), +(100, 'ADD_ACCUMULATE', 129, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(101, 'ADD_ACCUMULATE', 131, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(102, 'ADD_ACCUMULATE', 133, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(103, 'ADD_ACCUMULATE', 135, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(104, 'ADD_ACCUMULATE', 137, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(105, 'ADD_ACCUMULATE', 139, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(106, 'ADD_ACCUMULATE', 141, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-24 11:10:32'), +(107, 'ADD_ACCUMULATE', 142, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-24 11:10:32'), +(108, 'ADD_ACCUMULATE', 143, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(109, 'ADD_ACCUMULATE', 145, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(110, 'ADD_ACCUMULATE', 147, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(111, 'ADD_ACCUMULATE', 149, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(112, 'ADD_ACCUMULATE', 151, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(113, 'ADD_ACCUMULATE', 153, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(114, 'ADD_ACCUMULATE', 155, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:05'), +(115, 'ADD_ACCUMULATE', 157, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:05'), +(116, 'ADD_ACCUMULATE', 159, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-25 11:08:04'), +(117, 'ADD_ACCUMULATE', 161, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-25 11:08:05'), +(118, 'ADD_ACCUMULATE', 163, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(119, 'ADD_ACCUMULATE', 164, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(120, 'ADD_ACCUMULATE', 165, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(121, 'ADD_ACCUMULATE', 166, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(122, 'ADD_ACCUMULATE', 167, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(123, 'ADD_ACCUMULATE', 168, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(124, 'ADD_ACCUMULATE', 169, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(125, 'ADD_ACCUMULATE', 170, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(126, 'ADD_ACCUMULATE', 171, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(127, 'ADD_ACCUMULATE', 172, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:31'), +(128, 'ADD_ACCUMULATE', 174, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:32'), +(129, 'ADD_ACCUMULATE', 176, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:32'), +(130, 'ADD_ACCUMULATE', 178, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-26 11:19:34'), +(131, 'ADD_ACCUMULATE', 179, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-26 11:19:34'), +(132, 'ADD_ACCUMULATE', 180, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:21'), +(133, 'ADD_ACCUMULATE', 181, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:21'), +(134, 'ADD_ACCUMULATE', 182, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:40'), +(135, 'ADD_ACCUMULATE', 183, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(136, 'ADD_ACCUMULATE', 184, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(137, 'ADD_ACCUMULATE', 185, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(138, 'ADD_ACCUMULATE', 186, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(139, 'ADD_ACCUMULATE', 187, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(140, 'ADD_ACCUMULATE', 188, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(141, 'ADD_ACCUMULATE', 189, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:49:08'), +(142, 'ADD_ACCUMULATE', 190, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:49:08'), +(143, 'DELETE_SINGLE', 190, '{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 6, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:58:25'), +(144, 'ADD_ACCUMULATE', 191, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"4.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:58:46'), +(145, 'DELETE_SINGLE', 181, '{\"worker_name\":\"박현수\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:59:37'), +(146, 'DELETE_SINGLE', 180, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:59:42'), +(147, 'ADD_ACCUMULATE', 192, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 07:00:10'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_status_types` +-- + +CREATE TABLE `work_status_types` ( + `id` int(11) NOT NULL, + `name` varchar(50) NOT NULL COMMENT '상태명', + `description` text DEFAULT NULL COMMENT '상태 설명', + `is_error` tinyint(1) DEFAULT 0 COMMENT '에러 상태 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_status_types` +-- + +INSERT INTO `work_status_types` (`id`, `name`, `description`, `is_error`, `created_at`) VALUES +(1, '정규', '정상적으로 완료된 작업', 0, '2025-06-16 02:21:16'), +(2, '에러', '오류가 발생한 작업', 1, '2025-06-16 02:21:16'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_types` +-- + +CREATE TABLE `work_types` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL COMMENT '작업 유형명', + `description` text DEFAULT NULL COMMENT '작업 유형 설명', + `category` varchar(50) DEFAULT NULL COMMENT '작업 카테고리', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_types` +-- + +INSERT INTO `work_types` (`id`, `name`, `description`, `category`, `created_at`, `updated_at`) VALUES +(1, 'Base(구조물)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:42'), +(2, 'Vessel(용기)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:47'), +(3, 'Piping Assembly(배관)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:50'), +(4, '작업대기', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:56'); + +-- +-- 덤프된 테이블의 인덱스 +-- + +-- +-- 테이블의 인덱스 `activity_logs` +-- +ALTER TABLE `activity_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_user_activity` (`user_id`,`activity_type`,`created_at`), + ADD KEY `idx_table_record` (`table_name`,`record_id`); + +-- +-- 테이블의 인덱스 `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + ADD PRIMARY KEY (`cutting_plan_id`), + ADD KEY `project_id` (`project_id`), + ADD KEY `fk_cuttingplan_spec` (`spec_id`); + +-- +-- 테이블의 인덱스 `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + ADD PRIMARY KEY (`id`), + ADD KEY `worker_id` (`worker_id`), + ADD KEY `fk_dird_project` (`project_id`), + ADD KEY `fk_dird_issuetype` (`issue_type_id`); + +-- +-- 테이블의 인덱스 `daily_worker_summary` +-- +ALTER TABLE `daily_worker_summary` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `unique_worker_date` (`worker_id`,`report_date`); + +-- +-- 테이블의 인덱스 `daily_work_reports` +-- +ALTER TABLE `daily_work_reports` + ADD PRIMARY KEY (`id`), + ADD KEY `idx_report_date` (`report_date`), + ADD KEY `idx_worker_date` (`worker_id`,`report_date`), + ADD KEY `idx_project_date` (`project_id`,`report_date`), + ADD KEY `idx_work_type` (`work_type_id`), + ADD KEY `idx_work_status` (`work_status_id`), + ADD KEY `idx_error_type` (`error_type_id`), + ADD KEY `idx_created_by` (`created_by`), + ADD KEY `idx_date_worker_creator` (`report_date`,`worker_id`,`created_by`); + +-- +-- 테이블의 인덱스 `EquipmentList` +-- +ALTER TABLE `EquipmentList` + ADD PRIMARY KEY (`equipment_id`), + ADD KEY `factory_id` (`factory_id`); + +-- +-- 테이블의 인덱스 `error_types` +-- +ALTER TABLE `error_types` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `FactoryInfo` +-- +ALTER TABLE `FactoryInfo` + ADD PRIMARY KEY (`factory_id`); + +-- +-- 테이블의 인덱스 `IssueTypes` +-- +ALTER TABLE `IssueTypes` + ADD PRIMARY KEY (`issue_type_id`); + +-- +-- 테이블의 인덱스 `login_logs` +-- +ALTER TABLE `login_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_user_login` (`user_id`,`login_time`); + +-- +-- 테이블의 인덱스 `password_change_logs` +-- +ALTER TABLE `password_change_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `changed_by_user_id` (`changed_by_user_id`), + ADD KEY `idx_user_changes` (`user_id`,`changed_at`); + +-- +-- 테이블의 인덱스 `PipeSpecs` +-- +ALTER TABLE `PipeSpecs` + ADD PRIMARY KEY (`spec_id`), + ADD UNIQUE KEY `unique_spec` (`material`,`diameter_in`,`schedule`); + +-- +-- 테이블의 인덱스 `Processes` +-- +ALTER TABLE `Processes` + ADD PRIMARY KEY (`process_id`), + ADD KEY `project_id` (`project_id`); + +-- +-- 테이블의 인덱스 `Projects` +-- +ALTER TABLE `Projects` + ADD PRIMARY KEY (`project_id`); + +-- +-- 테이블의 인덱스 `Tasks` +-- +ALTER TABLE `Tasks` + ADD PRIMARY KEY (`task_id`); + +-- +-- 테이블의 인덱스 `uploaded_documents` +-- +ALTER TABLE `uploaded_documents` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `Users` +-- +ALTER TABLE `Users` + ADD PRIMARY KEY (`user_id`), + ADD UNIQUE KEY `username` (`username`), + ADD UNIQUE KEY `email` (`email`), + ADD KEY `fk_worker` (`worker_id`), + ADD KEY `idx_username` (`username`), + ADD KEY `idx_active_users` (`is_active`,`access_level`); + +-- +-- 테이블의 인덱스 `Workers` +-- +ALTER TABLE `Workers` + ADD PRIMARY KEY (`worker_id`); + +-- +-- 테이블의 인덱스 `worker_groups` +-- +ALTER TABLE `worker_groups` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `uk_leader_worker` (`group_leader_id`,`worker_id`), + ADD KEY `idx_group_leader` (`group_leader_id`), + ADD KEY `idx_worker` (`worker_id`), + ADD KEY `idx_is_active` (`is_active`); + +-- +-- 테이블의 인덱스 `WorkReports` +-- +ALTER TABLE `WorkReports` + ADD PRIMARY KEY (`id`), + ADD KEY `worker_id` (`worker_id`), + ADD KEY `project_id` (`project_id`), + ADD KEY `morning_task_id` (`morning_task_id`), + ADD KEY `afternoon_task_id` (`afternoon_task_id`), + ADD KEY `overtime_task_id` (`overtime_task_id`); + +-- +-- 테이블의 인덱스 `work_report_audit_log` +-- +ALTER TABLE `work_report_audit_log` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_action_date` (`action`,`created_at`), + ADD KEY `idx_changed_by` (`changed_by`), + ADD KEY `idx_report_id` (`report_id`); + +-- +-- 테이블의 인덱스 `work_status_types` +-- +ALTER TABLE `work_status_types` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `work_types` +-- +ALTER TABLE `work_types` + ADD PRIMARY KEY (`id`); + +-- +-- 덤프된 테이블의 AUTO_INCREMENT +-- + +-- +-- 테이블의 AUTO_INCREMENT `activity_logs` +-- +ALTER TABLE `activity_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + MODIFY `cutting_plan_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; + +-- +-- 테이블의 AUTO_INCREMENT `daily_worker_summary` +-- +ALTER TABLE `daily_worker_summary` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; + +-- +-- 테이블의 AUTO_INCREMENT `daily_work_reports` +-- +ALTER TABLE `daily_work_reports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=193; + +-- +-- 테이블의 AUTO_INCREMENT `EquipmentList` +-- +ALTER TABLE `EquipmentList` + MODIFY `equipment_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `error_types` +-- +ALTER TABLE `error_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; + +-- +-- 테이블의 AUTO_INCREMENT `FactoryInfo` +-- +ALTER TABLE `FactoryInfo` + MODIFY `factory_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; + +-- +-- 테이블의 AUTO_INCREMENT `IssueTypes` +-- +ALTER TABLE `IssueTypes` + MODIFY `issue_type_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `login_logs` +-- +ALTER TABLE `login_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=142; + +-- +-- 테이블의 AUTO_INCREMENT `password_change_logs` +-- +ALTER TABLE `password_change_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `PipeSpecs` +-- +ALTER TABLE `PipeSpecs` + MODIFY `spec_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; + +-- +-- 테이블의 AUTO_INCREMENT `Processes` +-- +ALTER TABLE `Processes` + MODIFY `process_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `Projects` +-- +ALTER TABLE `Projects` + MODIFY `project_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=14; + +-- +-- 테이블의 AUTO_INCREMENT `Tasks` +-- +ALTER TABLE `Tasks` + MODIFY `task_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19; + +-- +-- 테이블의 AUTO_INCREMENT `uploaded_documents` +-- +ALTER TABLE `uploaded_documents` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `Users` +-- +ALTER TABLE `Users` + MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `Workers` +-- +ALTER TABLE `Workers` + MODIFY `worker_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12; + +-- +-- 테이블의 AUTO_INCREMENT `worker_groups` +-- +ALTER TABLE `worker_groups` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `WorkReports` +-- +ALTER TABLE `WorkReports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1442; + +-- +-- 테이블의 AUTO_INCREMENT `work_report_audit_log` +-- +ALTER TABLE `work_report_audit_log` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=148; + +-- +-- 테이블의 AUTO_INCREMENT `work_status_types` +-- +ALTER TABLE `work_status_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- 테이블의 AUTO_INCREMENT `work_types` +-- +ALTER TABLE `work_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11; + +-- +-- 덤프된 테이블의 제약사항 +-- + +-- +-- 테이블의 제약사항 `activity_logs` +-- +ALTER TABLE `activity_logs` + ADD CONSTRAINT `activity_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE SET NULL; + +-- +-- 테이블의 제약사항 `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + ADD CONSTRAINT `CuttingPlan_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`), + ADD CONSTRAINT `fk_cuttingplan_spec` FOREIGN KEY (`spec_id`) REFERENCES `PipeSpecs` (`spec_id`); + +-- +-- 테이블의 제약사항 `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + ADD CONSTRAINT `dailyissuereports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`), + ADD CONSTRAINT `fk_dird_issuetype` FOREIGN KEY (`issue_type_id`) REFERENCES `IssueTypes` (`issue_type_id`), + ADD CONSTRAINT `fk_dird_project` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`); + +-- +-- 테이블의 제약사항 `EquipmentList` +-- +ALTER TABLE `EquipmentList` + ADD CONSTRAINT `EquipmentList_ibfk_1` FOREIGN KEY (`factory_id`) REFERENCES `FactoryInfo` (`factory_id`); + +-- +-- 테이블의 제약사항 `login_logs` +-- +ALTER TABLE `login_logs` + ADD CONSTRAINT `login_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE; + +-- +-- 테이블의 제약사항 `password_change_logs` +-- +ALTER TABLE `password_change_logs` + ADD CONSTRAINT `password_change_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `password_change_logs_ibfk_2` FOREIGN KEY (`changed_by_user_id`) REFERENCES `Users` (`user_id`) ON DELETE SET NULL; + +-- +-- 테이블의 제약사항 `Processes` +-- +ALTER TABLE `Processes` + ADD CONSTRAINT `Processes_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`); + +-- +-- 테이블의 제약사항 `Users` +-- +ALTER TABLE `Users` + ADD CONSTRAINT `fk_worker` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`); + +-- +-- 테이블의 제약사항 `worker_groups` +-- +ALTER TABLE `worker_groups` + ADD CONSTRAINT `fk_group_leader` FOREIGN KEY (`group_leader_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `fk_group_worker` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`) ON DELETE CASCADE; + +-- +-- 테이블의 제약사항 `WorkReports` +-- +ALTER TABLE `WorkReports` + ADD CONSTRAINT `WorkReports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`), + ADD CONSTRAINT `WorkReports_ibfk_2` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`), + ADD CONSTRAINT `WorkReports_ibfk_3` FOREIGN KEY (`morning_task_id`) REFERENCES `Tasks` (`task_id`), + ADD CONSTRAINT `WorkReports_ibfk_4` FOREIGN KEY (`afternoon_task_id`) REFERENCES `Tasks` (`task_id`), + ADD CONSTRAINT `WorkReports_ibfk_5` FOREIGN KEY (`overtime_task_id`) REFERENCES `Tasks` (`task_id`); +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/004_add_work_attendance_tracking.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/004_add_work_attendance_tracking.sql new file mode 100644 index 0000000..d27de88 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/004_add_work_attendance_tracking.sql @@ -0,0 +1,359 @@ +-- 근로 및 휴가 관리를 위한 테이블 확장 +-- 작성일: 2025-11-03 + +-- 1. 근로 유형 테이블 생성 +CREATE TABLE IF NOT EXISTS work_attendance_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + type_code VARCHAR(20) NOT NULL UNIQUE COMMENT '근로 유형 코드', + type_name VARCHAR(50) NOT NULL COMMENT '근로 유형명', + description TEXT COMMENT '설명', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) COMMENT='근로 유형 관리 테이블'; + +-- 2. 휴가 유형 테이블 생성 +CREATE TABLE IF NOT EXISTS vacation_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + type_code VARCHAR(20) NOT NULL UNIQUE COMMENT '휴가 유형 코드', + type_name VARCHAR(50) NOT NULL COMMENT '휴가 유형명', + hours_deduction DECIMAL(4,2) NOT NULL COMMENT '차감 시간', + description TEXT COMMENT '설명', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) COMMENT='휴가 유형 관리 테이블'; + +-- 3. 일일 근태 기록 테이블 생성 +CREATE TABLE IF NOT EXISTS daily_attendance_records ( + id INT PRIMARY KEY AUTO_INCREMENT, + record_date DATE NOT NULL COMMENT '기록 날짜', + worker_id INT NOT NULL COMMENT '작업자 ID', + total_work_hours DECIMAL(4,2) DEFAULT 0 COMMENT '총 작업 시간', + attendance_type_id INT COMMENT '근로 유형 ID', + vacation_type_id INT NULL COMMENT '휴가 유형 ID', + is_vacation_processed BOOLEAN DEFAULT FALSE COMMENT '휴가 처리 여부', + overtime_approved BOOLEAN DEFAULT FALSE COMMENT '초과근무 승인 여부', + overtime_approved_by INT NULL COMMENT '초과근무 승인자 ID', + overtime_approved_at TIMESTAMP NULL COMMENT '초과근무 승인 시간', + status ENUM('incomplete', 'partial', 'complete', 'overtime', 'vacation', 'error') DEFAULT 'incomplete' COMMENT '상태', + notes TEXT COMMENT '비고', + created_by INT NOT NULL COMMENT '생성자 ID', + updated_by INT NULL COMMENT '수정자 ID', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + -- 외래키 제약조건 + FOREIGN KEY (worker_id) REFERENCES workers(worker_id) ON DELETE CASCADE, + FOREIGN KEY (attendance_type_id) REFERENCES work_attendance_types(id), + FOREIGN KEY (vacation_type_id) REFERENCES vacation_types(id), + FOREIGN KEY (overtime_approved_by) REFERENCES users(user_id), + FOREIGN KEY (created_by) REFERENCES users(user_id), + FOREIGN KEY (updated_by) REFERENCES users(user_id), + + -- 유니크 제약조건 (작업자별 날짜별 하나의 기록) + UNIQUE KEY unique_worker_date (worker_id, record_date), + + -- 인덱스 + INDEX idx_record_date (record_date), + INDEX idx_worker_date (worker_id, record_date), + INDEX idx_status (status) +) COMMENT='일일 근태 기록 테이블'; + +-- 4. 휴가 잔여 관리 테이블 생성 +CREATE TABLE IF NOT EXISTS worker_vacation_balance ( + id INT PRIMARY KEY AUTO_INCREMENT, + worker_id INT NOT NULL COMMENT '작업자 ID', + year YEAR NOT NULL COMMENT '연도', + total_annual_leave DECIMAL(4,2) DEFAULT 15.0 COMMENT '연간 총 연차 (일)', + used_annual_leave DECIMAL(4,2) DEFAULT 0 COMMENT '사용한 연차 (일)', + remaining_annual_leave DECIMAL(4,2) GENERATED ALWAYS AS (total_annual_leave - used_annual_leave) STORED COMMENT '잔여 연차 (일)', + notes TEXT COMMENT '비고', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + -- 외래키 제약조건 + FOREIGN KEY (worker_id) REFERENCES workers(worker_id) ON DELETE CASCADE, + + -- 유니크 제약조건 (작업자별 연도별 하나의 기록) + UNIQUE KEY unique_worker_year (worker_id, year), + + -- 인덱스 + INDEX idx_worker_year (worker_id, year) +) COMMENT='작업자별 휴가 잔여 관리 테이블'; + +-- 5. 기본 데이터 삽입 + +-- 근로 유형 기본 데이터 +INSERT INTO work_attendance_types (type_code, type_name, description) VALUES +('REGULAR', '정시근로', '8시간 정규 근무'), +('OVERTIME', '연장근로', '8시간 초과 근무'), +('PARTIAL', '부분근로', '8시간 미만 근무'), +('VACATION', '휴가근로', '휴가와 함께하는 부분 근무') +ON DUPLICATE KEY UPDATE + type_name = VALUES(type_name), + description = VALUES(description); + +-- 휴가 유형 기본 데이터 +INSERT INTO vacation_types (type_code, type_name, hours_deduction, description) VALUES +('ANNUAL_FULL', '연차', 8.0, '하루 전체 연차'), +('ANNUAL_HALF', '반차', 4.0, '반일 연차'), +('ANNUAL_QUARTER', '반반차', 2.0, '1/4일 연차'), +('SICK_FULL', '병가', 8.0, '하루 전체 병가'), +('SICK_HALF', '반일병가', 4.0, '반일 병가'), +('PERSONAL_FULL', '개인사유', 8.0, '개인사유로 인한 휴가'), +('PERSONAL_HALF', '반일개인사유', 4.0, '반일 개인사유 휴가') +ON DUPLICATE KEY UPDATE + type_name = VALUES(type_name), + hours_deduction = VALUES(hours_deduction), + description = VALUES(description); + +-- 6. daily_work_reports 테이블에 근태 기록 연결 컬럼 추가 +ALTER TABLE daily_work_reports +ADD COLUMN attendance_record_id INT NULL COMMENT '근태 기록 ID' AFTER updated_by, +ADD INDEX idx_attendance_record (attendance_record_id); + +-- 외래키 제약조건 추가 (나중에 데이터 정리 후) +-- ALTER TABLE daily_work_reports +-- ADD FOREIGN KEY (attendance_record_id) REFERENCES daily_attendance_records(id); + +-- 7. 휴가 전용 작업 유형 추가 (work_types 테이블에) +INSERT INTO work_types (name, description, is_active) VALUES +('휴가', '연차, 반차, 병가 등 휴가 처리용', TRUE) +ON DUPLICATE KEY UPDATE + description = VALUES(description), + is_active = VALUES(is_active); + +-- 8. 뷰 생성 - 일일 근태 현황 조회용 +CREATE OR REPLACE VIEW v_daily_attendance_summary AS +SELECT + dar.id, + dar.record_date, + dar.worker_id, + w.worker_name, + w.job_type, + dar.total_work_hours, + wat.type_name as attendance_type, + vt.type_name as vacation_type, + dar.is_vacation_processed, + dar.overtime_approved, + dar.status, + CASE + WHEN dar.status = 'incomplete' THEN '미입력' + WHEN dar.status = 'partial' THEN '부분입력' + WHEN dar.status = 'complete' THEN '정시근로' + WHEN dar.status = 'overtime' THEN '연장근로' + WHEN dar.status = 'vacation' THEN '휴가' + WHEN dar.status = 'error' THEN '오류' + ELSE '알수없음' + END as status_text, + dar.notes, + dar.created_at, + dar.updated_at +FROM daily_attendance_records dar +LEFT JOIN workers w ON dar.worker_id = w.worker_id +LEFT JOIN work_attendance_types wat ON dar.attendance_type_id = wat.id +LEFT JOIN vacation_types vt ON dar.vacation_type_id = vt.id +ORDER BY dar.record_date DESC, w.worker_name; + +-- 9. 트리거 생성 - daily_work_reports 변경 시 근태 기록 자동 업데이트 +DELIMITER // + +CREATE OR REPLACE TRIGGER tr_update_attendance_on_work_report +AFTER INSERT ON daily_work_reports +FOR EACH ROW +BEGIN + DECLARE total_hours DECIMAL(4,2); + DECLARE attendance_type INT; + DECLARE vacation_type INT; + DECLARE record_status VARCHAR(20); + DECLARE existing_record_id INT; + + -- 해당 작업자의 해당 날짜 총 작업시간 계산 + SELECT COALESCE(SUM(work_hours), 0) INTO total_hours + FROM daily_work_reports + WHERE worker_id = NEW.worker_id + AND report_date = NEW.report_date; + + -- 휴가 처리 여부 확인 (work_type_id가 휴가용인지) + SELECT id INTO vacation_type + FROM vacation_types + WHERE (total_hours = 0 AND type_code = 'ANNUAL_FULL') + OR (total_hours = 4 AND type_code = 'ANNUAL_HALF') + OR (total_hours = 6 AND type_code = 'ANNUAL_QUARTER') + LIMIT 1; + + -- 근로 유형 결정 + IF total_hours = 0 THEN + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'PARTIAL'; + SET record_status = 'incomplete'; + ELSEIF total_hours < 8 THEN + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'PARTIAL'; + SET record_status = 'partial'; + ELSEIF total_hours = 8 THEN + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'REGULAR'; + SET record_status = 'complete'; + ELSE + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'OVERTIME'; + SET record_status = 'overtime'; + END IF; + + -- 휴가 처리된 경우 상태 조정 + IF vacation_type IS NOT NULL THEN + SET record_status = 'vacation'; + END IF; + + -- 기존 근태 기록 확인 + SELECT id INTO existing_record_id + FROM daily_attendance_records + WHERE worker_id = NEW.worker_id AND record_date = NEW.report_date; + + -- 근태 기록 업데이트 또는 생성 + IF existing_record_id IS NOT NULL THEN + UPDATE daily_attendance_records + SET + total_work_hours = total_hours, + attendance_type_id = attendance_type, + vacation_type_id = vacation_type, + is_vacation_processed = (vacation_type IS NOT NULL), + status = record_status, + updated_by = NEW.created_by, + updated_at = CURRENT_TIMESTAMP + WHERE id = existing_record_id; + ELSE + INSERT INTO daily_attendance_records ( + record_date, worker_id, total_work_hours, attendance_type_id, + vacation_type_id, is_vacation_processed, status, created_by + ) VALUES ( + NEW.report_date, NEW.worker_id, total_hours, attendance_type, + vacation_type, (vacation_type IS NOT NULL), record_status, NEW.created_by + ); + END IF; +END// + +DELIMITER ; + +-- 10. 기존 데이터 마이그레이션을 위한 프로시저 +DELIMITER // + +CREATE OR REPLACE PROCEDURE sp_migrate_existing_work_reports() +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE v_worker_id INT; + DECLARE v_report_date DATE; + DECLARE cur CURSOR FOR + SELECT DISTINCT worker_id, report_date + FROM daily_work_reports + ORDER BY report_date DESC, worker_id; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + OPEN cur; + + read_loop: LOOP + FETCH cur INTO v_worker_id, v_report_date; + IF done THEN + LEAVE read_loop; + END IF; + + -- 각 작업자별 날짜별로 근태 기록 생성/업데이트 + CALL sp_update_attendance_record(v_worker_id, v_report_date); + END LOOP; + + CLOSE cur; +END// + +CREATE OR REPLACE PROCEDURE sp_update_attendance_record( + IN p_worker_id INT, + IN p_report_date DATE +) +BEGIN + DECLARE total_hours DECIMAL(4,2); + DECLARE attendance_type INT; + DECLARE vacation_type INT; + DECLARE record_status VARCHAR(20); + DECLARE existing_record_id INT; + DECLARE has_vacation_work INT DEFAULT 0; + + -- 해당 작업자의 해당 날짜 총 작업시간 계산 + SELECT COALESCE(SUM(work_hours), 0) INTO total_hours + FROM daily_work_reports + WHERE worker_id = p_worker_id + AND report_date = p_report_date; + + -- 휴가 관련 작업이 있는지 확인 (work_type_id = 999 또는 휴가 관련) + SELECT COUNT(*) INTO has_vacation_work + FROM daily_work_reports dwr + JOIN work_types wt ON dwr.work_type_id = wt.id + WHERE dwr.worker_id = p_worker_id + AND dwr.report_date = p_report_date + AND (wt.name LIKE '%휴가%' OR wt.name LIKE '%연차%' OR wt.name LIKE '%반차%'); + + -- 휴가 유형 결정 + IF has_vacation_work > 0 THEN + IF total_hours = 0 THEN + SELECT id INTO vacation_type FROM vacation_types WHERE type_code = 'ANNUAL_FULL' LIMIT 1; + ELSEIF total_hours = 4 THEN + SELECT id INTO vacation_type FROM vacation_types WHERE type_code = 'ANNUAL_HALF' LIMIT 1; + ELSEIF total_hours = 6 THEN + SELECT id INTO vacation_type FROM vacation_types WHERE type_code = 'ANNUAL_QUARTER' LIMIT 1; + END IF; + END IF; + + -- 근로 유형 및 상태 결정 + IF vacation_type IS NOT NULL THEN + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'VACATION'; + SET record_status = 'vacation'; + ELSEIF total_hours = 0 THEN + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'PARTIAL'; + SET record_status = 'incomplete'; + ELSEIF total_hours < 8 THEN + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'PARTIAL'; + SET record_status = 'partial'; + ELSEIF total_hours = 8 THEN + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'REGULAR'; + SET record_status = 'complete'; + ELSE + SELECT id INTO attendance_type FROM work_attendance_types WHERE type_code = 'OVERTIME'; + SET record_status = 'overtime'; + END IF; + + -- 기존 근태 기록 확인 + SELECT id INTO existing_record_id + FROM daily_attendance_records + WHERE worker_id = p_worker_id AND record_date = p_report_date; + + -- 근태 기록 업데이트 또는 생성 + IF existing_record_id IS NOT NULL THEN + UPDATE daily_attendance_records + SET + total_work_hours = total_hours, + attendance_type_id = attendance_type, + vacation_type_id = vacation_type, + is_vacation_processed = (vacation_type IS NOT NULL), + status = record_status, + updated_by = 1, + updated_at = CURRENT_TIMESTAMP + WHERE id = existing_record_id; + ELSE + INSERT INTO daily_attendance_records ( + record_date, worker_id, total_work_hours, attendance_type_id, + vacation_type_id, is_vacation_processed, status, created_by + ) VALUES ( + p_report_date, p_worker_id, total_hours, attendance_type, + vacation_type, (vacation_type IS NOT NULL), record_status, 1 + ); + END IF; +END// + +DELIMITER ; + +-- 11. 권한 및 인덱스 최적화 +-- 추가 인덱스 생성 +CREATE INDEX idx_daily_work_reports_worker_date ON daily_work_reports(worker_id, report_date); +CREATE INDEX idx_daily_work_reports_work_type ON daily_work_reports(work_type_id); + +-- 마이그레이션 실행 (주석 해제하여 실행) +-- CALL sp_migrate_existing_work_reports(); + +-- 완료 메시지 +SELECT 'DB 확장 완료: 근로 및 휴가 관리 시스템이 성공적으로 구축되었습니다.' as message; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/005_add_attendance_management.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/005_add_attendance_management.sql new file mode 100644 index 0000000..00905f2 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/005_add_attendance_management.sql @@ -0,0 +1,143 @@ +-- 근태 관리 시스템 테이블 추가 +-- 작성일: 2025-11-03 +-- 설명: 근로 유형, 휴가 유형, 일일 근태 기록, 휴가 잔여 관리 테이블 + +-- 1. 근로 유형 테이블 생성 +CREATE TABLE IF NOT EXISTS `work_attendance_types` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `type_code` VARCHAR(20) NOT NULL UNIQUE COMMENT '근로 유형 코드', + `type_name` VARCHAR(50) NOT NULL COMMENT '근로 유형명', + `description` TEXT COMMENT '설명', + `is_active` BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='근로 유형 관리 테이블'; + +-- 2. 휴가 유형 테이블 생성 +CREATE TABLE IF NOT EXISTS `vacation_types` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `type_code` VARCHAR(20) NOT NULL UNIQUE COMMENT '휴가 유형 코드', + `type_name` VARCHAR(50) NOT NULL COMMENT '휴가 유형명', + `hours_deduction` DECIMAL(4,2) NOT NULL COMMENT '차감 시간', + `description` TEXT COMMENT '설명', + `is_active` BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='휴가 유형 관리 테이블'; + +-- 3. 일일 근태 기록 테이블 생성 +CREATE TABLE IF NOT EXISTS `daily_attendance_records` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `record_date` DATE NOT NULL COMMENT '기록 날짜', + `worker_id` INT NOT NULL COMMENT '작업자 ID', + `total_work_hours` DECIMAL(4,2) DEFAULT 0 COMMENT '총 작업 시간', + `attendance_type_id` INT COMMENT '근로 유형 ID', + `vacation_type_id` INT NULL COMMENT '휴가 유형 ID', + `is_vacation_processed` BOOLEAN DEFAULT FALSE COMMENT '휴가 처리 여부', + `overtime_approved` BOOLEAN DEFAULT FALSE COMMENT '초과근무 승인 여부', + `overtime_approved_by` INT NULL COMMENT '초과근무 승인자 ID', + `overtime_approved_at` TIMESTAMP NULL COMMENT '초과근무 승인 시간', + `status` ENUM('incomplete', 'partial', 'complete', 'overtime', 'vacation', 'error') DEFAULT 'incomplete' COMMENT '상태', + `notes` TEXT COMMENT '비고', + `created_by` INT NOT NULL DEFAULT 1 COMMENT '생성자 ID', + `updated_by` INT NULL COMMENT '수정자 ID', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + -- 인덱스 + UNIQUE KEY `unique_worker_date` (`worker_id`, `record_date`), + INDEX `idx_record_date` (`record_date`), + INDEX `idx_worker_date` (`worker_id`, `record_date`), + INDEX `idx_status` (`status`), + + -- 외래키 (기존 테이블과의 관계) + FOREIGN KEY (`worker_id`) REFERENCES `workers`(`worker_id`) ON DELETE CASCADE, + FOREIGN KEY (`attendance_type_id`) REFERENCES `work_attendance_types`(`id`), + FOREIGN KEY (`vacation_type_id`) REFERENCES `vacation_types`(`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='일일 근태 기록 테이블'; + +-- 4. 작업자 휴가 잔여 관리 테이블 생성 +CREATE TABLE IF NOT EXISTS `worker_vacation_balance` ( + `id` INT PRIMARY KEY AUTO_INCREMENT, + `worker_id` INT NOT NULL COMMENT '작업자 ID', + `year` YEAR NOT NULL COMMENT '연도', + `total_annual_leave` DECIMAL(4,2) DEFAULT 15.0 COMMENT '연간 총 연차 (일)', + `used_annual_leave` DECIMAL(4,2) DEFAULT 0 COMMENT '사용한 연차 (일)', + `remaining_annual_leave` DECIMAL(4,2) GENERATED ALWAYS AS (`total_annual_leave` - `used_annual_leave`) STORED COMMENT '잔여 연차 (일)', + `notes` TEXT COMMENT '비고', + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + `updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + -- 인덱스 + UNIQUE KEY `unique_worker_year` (`worker_id`, `year`), + INDEX `idx_worker_year` (`worker_id`, `year`), + + -- 외래키 + FOREIGN KEY (`worker_id`) REFERENCES `workers`(`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='작업자별 휴가 잔여 관리 테이블'; + +-- 5. daily_work_reports 테이블에 근태 기록 연결 컬럼 추가 +ALTER TABLE `daily_work_reports` +ADD COLUMN IF NOT EXISTS `attendance_record_id` INT NULL COMMENT '근태 기록 ID' AFTER `updated_by`; + +-- 인덱스 추가 +CREATE INDEX IF NOT EXISTS `idx_attendance_record` ON `daily_work_reports`(`attendance_record_id`); +CREATE INDEX IF NOT EXISTS `idx_daily_work_reports_worker_date` ON `daily_work_reports`(`worker_id`, `report_date`); + +-- 6. 기본 데이터 삽입 + +-- 근로 유형 기본 데이터 +INSERT IGNORE INTO `work_attendance_types` (`type_code`, `type_name`, `description`) VALUES +('REGULAR', '정시근로', '8시간 정규 근무'), +('OVERTIME', '연장근로', '8시간 초과 근무'), +('PARTIAL', '부분근로', '8시간 미만 근무'), +('VACATION', '휴가근로', '휴가와 함께하는 부분 근무'); + +-- 휴가 유형 기본 데이터 +INSERT IGNORE INTO `vacation_types` (`type_code`, `type_name`, `hours_deduction`, `description`) VALUES +('ANNUAL_FULL', '연차', 8.0, '하루 전체 연차'), +('ANNUAL_HALF', '반차', 4.0, '반일 연차'), +('ANNUAL_QUARTER', '반반차', 2.0, '1/4일 연차'), +('SICK_FULL', '병가', 8.0, '하루 전체 병가'), +('SICK_HALF', '반일병가', 4.0, '반일 병가'), +('PERSONAL_FULL', '개인사유', 8.0, '개인사유로 인한 휴가'), +('PERSONAL_HALF', '반일개인사유', 4.0, '반일 개인사유 휴가'); + +-- 7. 휴가 전용 작업 유형 추가 (이미 있으면 무시) +INSERT IGNORE INTO `work_types` (`name`, `description`, `is_active`) VALUES +('휴가', '연차, 반차, 병가 등 휴가 처리용', TRUE); + +-- 8. 뷰 생성 - 일일 근태 현황 조회용 +CREATE OR REPLACE VIEW `v_daily_attendance_summary` AS +SELECT + dar.id, + dar.record_date, + dar.worker_id, + w.worker_name, + w.job_type, + dar.total_work_hours, + wat.type_name as attendance_type, + vt.type_name as vacation_type, + dar.is_vacation_processed, + dar.overtime_approved, + dar.status, + CASE + WHEN dar.status = 'incomplete' THEN '미입력' + WHEN dar.status = 'partial' THEN '부분입력' + WHEN dar.status = 'complete' THEN '정시근로' + WHEN dar.status = 'overtime' THEN '연장근로' + WHEN dar.status = 'vacation' THEN '휴가' + WHEN dar.status = 'error' THEN '오류' + ELSE '알수없음' + END as status_text, + dar.notes, + dar.created_at, + dar.updated_at +FROM daily_attendance_records dar +LEFT JOIN workers w ON dar.worker_id = w.worker_id +LEFT JOIN work_attendance_types wat ON dar.attendance_type_id = wat.id +LEFT JOIN vacation_types vt ON dar.vacation_type_id = vt.id +ORDER BY dar.record_date DESC, w.worker_name; + +-- 완료 메시지 +SELECT '✅ 근태 관리 시스템 테이블이 성공적으로 생성되었습니다.' as message; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/006_add_description_column.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/006_add_description_column.sql new file mode 100644 index 0000000..9626382 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/006_add_description_column.sql @@ -0,0 +1,16 @@ +-- 006_add_description_column.sql +-- daily_work_reports 테이블에 description 컬럼 추가 + +-- description 컬럼 추가 (이미 존재하는 경우 무시) +SET @sql = (SELECT IF( + (SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS + WHERE table_name = 'daily_work_reports' + AND table_schema = 'hyungi' + AND column_name = 'description') = 0, + 'ALTER TABLE daily_work_reports ADD COLUMN description TEXT COMMENT ''작업 설명'' AFTER work_hours', + 'SELECT ''description column already exists'' as message' +)); + +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/007_create_monthly_worker_status.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/007_create_monthly_worker_status.sql new file mode 100644 index 0000000..c7a2aae --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/007_create_monthly_worker_status.sql @@ -0,0 +1,249 @@ +-- 007_create_monthly_worker_status.sql +-- 월별 작업자 상태 집계 테이블 생성 + +-- 월별 작업자 상태 집계 테이블 +CREATE TABLE IF NOT EXISTS monthly_worker_status ( + id INT PRIMARY KEY AUTO_INCREMENT, + year INT NOT NULL COMMENT '연도', + month INT NOT NULL COMMENT '월 (1-12)', + worker_id INT NOT NULL COMMENT '작업자 ID', + date DATE NOT NULL COMMENT '날짜', + + -- 작업 시간 정보 + total_work_hours DECIMAL(5,2) DEFAULT 0.00 COMMENT '총 작업시간', + actual_work_hours DECIMAL(5,2) DEFAULT 0.00 COMMENT '실제 작업시간 (휴가 제외)', + vacation_hours DECIMAL(5,2) DEFAULT 0.00 COMMENT '휴가 시간', + + -- 작업 건수 + total_work_count INT DEFAULT 0 COMMENT '총 작업 건수', + regular_work_count INT DEFAULT 0 COMMENT '정규 작업 건수', + error_work_count INT DEFAULT 0 COMMENT '오류 작업 건수', + + -- 상태 정보 + work_status ENUM( + 'incomplete', -- 미입력 (0시간) + 'partial', -- 부분입력 (8시간 미만) + 'complete', -- 정시근로 (8시간) + 'overtime', -- 연장근로 (8시간 초과) + 'vacation-full', -- 연차 (8시간) + 'vacation-half', -- 반차 (4시간) + 'vacation-quarter',-- 반반차 (2시간) + 'vacation-half-half', -- 조퇴 (6시간) + 'error', -- 오류 발생 + 'overtime-warning' -- 초과근무 확인필요 (12시간 초과) + ) NOT NULL DEFAULT 'incomplete' COMMENT '작업 상태', + + has_vacation BOOLEAN DEFAULT FALSE COMMENT '휴가 여부', + has_error BOOLEAN DEFAULT FALSE COMMENT '오류 여부', + has_issues BOOLEAN DEFAULT FALSE COMMENT '문제 여부 (미입력/부분입력)', + + -- 메타 정보 + last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '마지막 업데이트 시간', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + + -- 인덱스 + UNIQUE KEY unique_worker_date (worker_id, date), + KEY idx_year_month (year, month), + KEY idx_worker_year_month (worker_id, year, month), + KEY idx_status (work_status), + KEY idx_has_issues (has_issues), + KEY idx_has_error (has_error), + + -- 외래키 + FOREIGN KEY (worker_id) REFERENCES workers(worker_id) ON DELETE CASCADE +) COMMENT='월별 작업자 상태 집계 테이블'; + +-- 월별 집계 요약 테이블 (캘린더 최적화용) +CREATE TABLE IF NOT EXISTS monthly_summary ( + id INT PRIMARY KEY AUTO_INCREMENT, + year INT NOT NULL COMMENT '연도', + month INT NOT NULL COMMENT '월 (1-12)', + date DATE NOT NULL COMMENT '날짜', + + -- 작업자 수 + total_workers INT DEFAULT 0 COMMENT '총 작업자 수', + working_workers INT DEFAULT 0 COMMENT '작업한 작업자 수', + + -- 상태별 작업자 수 + incomplete_workers INT DEFAULT 0 COMMENT '미입력 작업자 수', + partial_workers INT DEFAULT 0 COMMENT '부분입력 작업자 수', + complete_workers INT DEFAULT 0 COMMENT '완료 작업자 수', + overtime_workers INT DEFAULT 0 COMMENT '연장근로 작업자 수', + vacation_workers INT DEFAULT 0 COMMENT '휴가 작업자 수', + error_workers INT DEFAULT 0 COMMENT '오류 작업자 수', + + -- 집계 정보 + total_work_hours DECIMAL(8,2) DEFAULT 0.00 COMMENT '총 작업시간', + total_work_count INT DEFAULT 0 COMMENT '총 작업 건수', + total_error_count INT DEFAULT 0 COMMENT '총 오류 건수', + + -- 상태 플래그 (캘린더 표시용) + has_issues BOOLEAN DEFAULT FALSE COMMENT '문제 있음 (미입력/부분입력)', + has_errors BOOLEAN DEFAULT FALSE COMMENT '오류 있음', + + -- 메타 정보 + last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + + -- 인덱스 + UNIQUE KEY unique_date (date), + KEY idx_year_month (year, month), + KEY idx_has_issues (has_issues), + KEY idx_has_errors (has_errors) +) COMMENT='월별 일자별 요약 테이블 (캘린더 최적화용)'; + +-- 집계 데이터 업데이트 함수 +DELIMITER $$ + +CREATE OR REPLACE PROCEDURE UpdateMonthlyWorkerStatus( + IN p_date DATE, + IN p_worker_id INT +) +BEGIN + DECLARE v_year INT; + DECLARE v_month INT; + DECLARE v_total_hours DECIMAL(5,2); + DECLARE v_actual_hours DECIMAL(5,2); + DECLARE v_vacation_hours DECIMAL(5,2); + DECLARE v_total_count INT; + DECLARE v_regular_count INT; + DECLARE v_error_count INT; + DECLARE v_has_vacation BOOLEAN; + DECLARE v_has_error BOOLEAN; + DECLARE v_has_issues BOOLEAN; + DECLARE v_status VARCHAR(20); + + -- 연도, 월 추출 + SET v_year = YEAR(p_date); + SET v_month = MONTH(p_date); + + -- 해당 날짜의 작업자 데이터 집계 + SELECT + COALESCE(SUM(work_hours), 0), + COALESCE(SUM(CASE WHEN project_id != 13 THEN work_hours ELSE 0 END), 0), + COALESCE(SUM(CASE WHEN project_id = 13 THEN work_hours ELSE 0 END), 0), + COUNT(*), + COUNT(CASE WHEN project_id != 13 AND work_status_id != 2 THEN 1 END), + COUNT(CASE WHEN work_status_id = 2 THEN 1 END), + MAX(CASE WHEN project_id = 13 THEN 1 ELSE 0 END), + MAX(CASE WHEN work_status_id = 2 THEN 1 ELSE 0 END) + INTO + v_total_hours, v_actual_hours, v_vacation_hours, + v_total_count, v_regular_count, v_error_count, + v_has_vacation, v_has_error + FROM daily_work_reports + WHERE report_date = p_date AND worker_id = p_worker_id; + + -- 상태 결정 로직 + IF v_has_error THEN + SET v_status = 'error'; + SET v_has_issues = FALSE; + ELSEIF v_total_hours > 12 THEN + SET v_status = 'overtime-warning'; + SET v_has_issues = TRUE; + ELSEIF v_has_vacation AND v_vacation_hours > 0 THEN + -- 휴가 상태 결정 + CASE v_vacation_hours + WHEN 8 THEN SET v_status = 'vacation-full'; + WHEN 6 THEN SET v_status = 'vacation-half-half'; + WHEN 4 THEN SET v_status = 'vacation-half'; + WHEN 2 THEN SET v_status = 'vacation-quarter'; + ELSE SET v_status = 'vacation-full'; + END CASE; + SET v_has_issues = FALSE; + ELSEIF v_total_hours > 8 THEN + SET v_status = 'overtime'; + SET v_has_issues = FALSE; + ELSEIF v_total_hours = 8 THEN + SET v_status = 'complete'; + SET v_has_issues = FALSE; + ELSEIF v_total_hours > 0 THEN + SET v_status = 'partial'; + SET v_has_issues = TRUE; + ELSE + SET v_status = 'incomplete'; + SET v_has_issues = TRUE; + END IF; + + -- 데이터 업서트 + INSERT INTO monthly_worker_status ( + year, month, worker_id, date, + total_work_hours, actual_work_hours, vacation_hours, + total_work_count, regular_work_count, error_work_count, + work_status, has_vacation, has_error, has_issues + ) VALUES ( + v_year, v_month, p_worker_id, p_date, + v_total_hours, v_actual_hours, v_vacation_hours, + v_total_count, v_regular_count, v_error_count, + v_status, v_has_vacation, v_has_error, v_has_issues + ) ON DUPLICATE KEY UPDATE + total_work_hours = v_total_hours, + actual_work_hours = v_actual_hours, + vacation_hours = v_vacation_hours, + total_work_count = v_total_count, + regular_work_count = v_regular_count, + error_work_count = v_error_count, + work_status = v_status, + has_vacation = v_has_vacation, + has_error = v_has_error, + has_issues = v_has_issues, + last_updated = CURRENT_TIMESTAMP; + + -- 일별 요약도 업데이트 + CALL UpdateDailySummary(p_date); +END$$ + +-- 일별 요약 업데이트 함수 +CREATE OR REPLACE PROCEDURE UpdateDailySummary( + IN p_date DATE +) +BEGIN + DECLARE v_year INT; + DECLARE v_month INT; + + SET v_year = YEAR(p_date); + SET v_month = MONTH(p_date); + + INSERT INTO monthly_summary ( + year, month, date, + total_workers, working_workers, + incomplete_workers, partial_workers, complete_workers, + overtime_workers, vacation_workers, error_workers, + total_work_hours, total_work_count, total_error_count, + has_issues, has_errors + ) + SELECT + v_year, v_month, p_date, + COUNT(*) as total_workers, + COUNT(CASE WHEN work_status != 'incomplete' THEN 1 END) as working_workers, + COUNT(CASE WHEN work_status = 'incomplete' THEN 1 END) as incomplete_workers, + COUNT(CASE WHEN work_status = 'partial' THEN 1 END) as partial_workers, + COUNT(CASE WHEN work_status IN ('complete') THEN 1 END) as complete_workers, + COUNT(CASE WHEN work_status = 'overtime' THEN 1 END) as overtime_workers, + COUNT(CASE WHEN work_status LIKE 'vacation%' THEN 1 END) as vacation_workers, + COUNT(CASE WHEN work_status = 'error' THEN 1 END) as error_workers, + SUM(total_work_hours) as total_work_hours, + SUM(total_work_count) as total_work_count, + SUM(error_work_count) as total_error_count, + MAX(has_issues) as has_issues, + MAX(has_error) as has_errors + FROM monthly_worker_status + WHERE date = p_date + ON DUPLICATE KEY UPDATE + total_workers = VALUES(total_workers), + working_workers = VALUES(working_workers), + incomplete_workers = VALUES(incomplete_workers), + partial_workers = VALUES(partial_workers), + complete_workers = VALUES(complete_workers), + overtime_workers = VALUES(overtime_workers), + vacation_workers = VALUES(vacation_workers), + error_workers = VALUES(error_workers), + total_work_hours = VALUES(total_work_hours), + total_work_count = VALUES(total_work_count), + total_error_count = VALUES(total_error_count), + has_issues = VALUES(has_issues), + has_errors = VALUES(has_errors), + last_updated = CURRENT_TIMESTAMP; +END$$ + +DELIMITER ; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/008_create_update_triggers.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/008_create_update_triggers.sql new file mode 100644 index 0000000..7fca042 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/008_create_update_triggers.sql @@ -0,0 +1,36 @@ +-- 008_create_update_triggers.sql +-- 작업보고서 변경 시 월별 집계 자동 업데이트 트리거 + +DELIMITER $$ + +-- 작업보고서 INSERT 트리거 +CREATE OR REPLACE TRIGGER tr_daily_work_reports_insert +AFTER INSERT ON daily_work_reports +FOR EACH ROW +BEGIN + CALL UpdateMonthlyWorkerStatus(NEW.report_date, NEW.worker_id); +END$$ + +-- 작업보고서 UPDATE 트리거 +CREATE OR REPLACE TRIGGER tr_daily_work_reports_update +AFTER UPDATE ON daily_work_reports +FOR EACH ROW +BEGIN + -- 기존 날짜 업데이트 + CALL UpdateMonthlyWorkerStatus(OLD.report_date, OLD.worker_id); + + -- 새 날짜가 다르면 새 날짜도 업데이트 + IF OLD.report_date != NEW.report_date OR OLD.worker_id != NEW.worker_id THEN + CALL UpdateMonthlyWorkerStatus(NEW.report_date, NEW.worker_id); + END IF; +END$$ + +-- 작업보고서 DELETE 트리거 +CREATE OR REPLACE TRIGGER tr_daily_work_reports_delete +AFTER DELETE ON daily_work_reports +FOR EACH ROW +BEGIN + CALL UpdateMonthlyWorkerStatus(OLD.report_date, OLD.worker_id); +END$$ + +DELIMITER ; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/009_add_overtime_warning_columns.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/009_add_overtime_warning_columns.sql new file mode 100644 index 0000000..7437c7d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/009_add_overtime_warning_columns.sql @@ -0,0 +1,67 @@ +-- 009_add_overtime_warning_columns.sql +-- monthly_summary 테이블에 12시간 초과(확인필요) 상태 컬럼 추가 + +-- monthly_summary 테이블에 컬럼 추가 +ALTER TABLE monthly_summary +ADD COLUMN overtime_warning_workers INT DEFAULT 0 COMMENT '확인필요(12시간초과) 작업자 수' AFTER error_workers, +ADD COLUMN has_overtime_warning BOOLEAN DEFAULT FALSE COMMENT '확인필요 상태 있음' AFTER has_errors; + +-- UpdateDailySummary 프로시저 업데이트 +DROP PROCEDURE IF EXISTS UpdateDailySummary; +DELIMITER // +CREATE PROCEDURE UpdateDailySummary( + IN p_date DATE +) +BEGIN + DECLARE v_year INT; + DECLARE v_month INT; + + SET v_year = YEAR(p_date); + SET v_month = MONTH(p_date); + + INSERT INTO monthly_summary ( + year, month, date, + total_workers, working_workers, + incomplete_workers, partial_workers, complete_workers, + overtime_workers, vacation_workers, error_workers, overtime_warning_workers, + total_work_hours, total_work_count, total_error_count, + has_issues, has_errors, has_overtime_warning + ) + SELECT + v_year, v_month, p_date, + COUNT(*) as total_workers, + COUNT(CASE WHEN work_status != 'incomplete' THEN 1 END) as working_workers, + COUNT(CASE WHEN work_status = 'incomplete' THEN 1 END) as incomplete_workers, + COUNT(CASE WHEN work_status = 'partial' THEN 1 END) as partial_workers, + COUNT(CASE WHEN work_status IN ('complete', 'overtime', 'vacation-full', 'vacation-half', 'vacation-quarter', 'vacation-half-half') THEN 1 END) as complete_workers, + COUNT(CASE WHEN work_status = 'overtime' THEN 1 END) as overtime_workers, + COUNT(CASE WHEN work_status LIKE 'vacation%' THEN 1 END) as vacation_workers, + COUNT(CASE WHEN work_status = 'error' THEN 1 END) as error_workers, + COUNT(CASE WHEN work_status = 'overtime-warning' THEN 1 END) as overtime_warning_workers, + SUM(total_work_hours) as total_work_hours, + SUM(total_work_count) as total_work_count, + SUM(error_work_count) as total_error_count, + MAX(has_issues) as has_issues, + MAX(has_error) as has_errors, + MAX(CASE WHEN work_status = 'overtime-warning' THEN 1 ELSE 0 END) as has_overtime_warning + FROM monthly_worker_status + WHERE date = p_date + ON DUPLICATE KEY UPDATE + total_workers = VALUES(total_workers), + working_workers = VALUES(working_workers), + incomplete_workers = VALUES(incomplete_workers), + partial_workers = VALUES(partial_workers), + complete_workers = VALUES(complete_workers), + overtime_workers = VALUES(overtime_workers), + vacation_workers = VALUES(vacation_workers), + error_workers = VALUES(error_workers), + overtime_warning_workers = VALUES(overtime_warning_workers), + total_work_hours = VALUES(total_work_hours), + total_work_count = VALUES(total_work_count), + total_error_count = VALUES(total_error_count), + has_issues = VALUES(has_issues), + has_errors = VALUES(has_errors), + has_overtime_warning = VALUES(has_overtime_warning), + last_updated = CURRENT_TIMESTAMP; +END // +DELIMITER ; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/009_fix_duplicate_monthly_status.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/009_fix_duplicate_monthly_status.sql new file mode 100644 index 0000000..46e840d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/009_fix_duplicate_monthly_status.sql @@ -0,0 +1,72 @@ +-- 009_fix_duplicate_monthly_status.sql +-- monthly_worker_status 테이블의 중복 데이터 정리 + +-- 1. 중복 데이터 확인 (디버깅용) +-- SELECT worker_id, date, COUNT(*) as cnt +-- FROM monthly_worker_status +-- GROUP BY worker_id, date +-- HAVING cnt > 1; + +-- 2. 중복 데이터 정리: 같은 worker_id, date에 대해 최신 데이터만 남기고 나머지 삭제 +DELETE mws1 FROM monthly_worker_status mws1 +INNER JOIN ( + SELECT + worker_id, + date, + MAX(id) as keep_id + FROM monthly_worker_status + GROUP BY worker_id, date +) mws2 ON mws1.worker_id = mws2.worker_id + AND mws1.date = mws2.date + AND mws1.id < mws2.keep_id; + +-- 3. 중복 제거 후 데이터 재집계 (선택사항) +-- 만약 합산이 필요하다면 다음 프로시저를 실행 +DELIMITER $$ + +CREATE OR REPLACE PROCEDURE ConsolidateDuplicateMonthlyStatus() +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE v_worker_id INT; + DECLARE v_date DATE; + + -- 중복이 있는 worker_id, date 조합 찾기 + DECLARE cur CURSOR FOR + SELECT worker_id, date + FROM monthly_worker_status + GROUP BY worker_id, date + HAVING COUNT(*) > 1; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + OPEN cur; + + read_loop: LOOP + FETCH cur INTO v_worker_id, v_date; + IF done THEN + LEAVE read_loop; + END IF; + + -- 해당 작업자의 해당 날짜 데이터를 재계산하여 업데이트 + CALL UpdateMonthlyWorkerStatus(v_date, v_worker_id); + END LOOP; + + CLOSE cur; +END$$ + +DELIMITER ; + +-- 4. 프로시저 실행하여 중복 데이터 통합 +-- CALL ConsolidateDuplicateMonthlyStatus(); + +-- 5. 확인: 중복이 남아있는지 체크 +SELECT + '중복 체크 완료' as message, + COUNT(*) as remaining_duplicates +FROM ( + SELECT worker_id, date, COUNT(*) as cnt + FROM monthly_worker_status + GROUP BY worker_id, date + HAVING cnt > 1 +) duplicates; + diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/010_add_project_status.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/010_add_project_status.sql new file mode 100644 index 0000000..3372d2d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/010_add_project_status.sql @@ -0,0 +1,22 @@ +-- 010_add_project_status.sql +-- 프로젝트 테이블에 활성화/비활성화 상태 필드 추가 + +-- 프로젝트 상태 필드 추가 +ALTER TABLE projects +ADD COLUMN is_active BOOLEAN DEFAULT TRUE COMMENT '프로젝트 활성화 상태 (TRUE: 활성, FALSE: 비활성)'; + +-- 프로젝트 완료일 필드 추가 (납품일) +ALTER TABLE projects +ADD COLUMN completed_date DATE NULL COMMENT '프로젝트 완료일 (납품일)'; + +-- 프로젝트 상태 필드 추가 (진행상태) +ALTER TABLE projects +ADD COLUMN project_status ENUM('planning', 'active', 'completed', 'cancelled') DEFAULT 'active' COMMENT '프로젝트 진행 상태'; + +-- 기존 프로젝트들을 모두 활성 상태로 설정 +UPDATE projects SET is_active = TRUE WHERE is_active IS NULL; + +-- 인덱스 추가 (성능 최적화) +CREATE INDEX idx_projects_is_active ON projects(is_active); +CREATE INDEX idx_projects_status ON projects(project_status); +CREATE INDEX idx_projects_completed_date ON projects(completed_date); diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/011_add_worker_status.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/011_add_worker_status.sql new file mode 100644 index 0000000..9f9aa8f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/011_add_worker_status.sql @@ -0,0 +1,30 @@ +-- 011_add_worker_status.sql +-- workers 테이블에 추가 정보 필드 추가 + +-- 작업자 상태 필드 수정 (기존 text에서 ENUM으로) +ALTER TABLE workers +MODIFY COLUMN status ENUM('active', 'inactive') DEFAULT 'active' COMMENT '작업자 상태 (active: 활성, inactive: 비활성)'; + +-- 작업자 추가 정보 필드들 추가 +ALTER TABLE workers +ADD COLUMN phone_number VARCHAR(20) NULL COMMENT '전화번호'; + +ALTER TABLE workers +ADD COLUMN email VARCHAR(100) NULL COMMENT '이메일'; + +ALTER TABLE workers +ADD COLUMN hire_date DATE NULL COMMENT '입사일'; + +ALTER TABLE workers +ADD COLUMN department VARCHAR(100) NULL COMMENT '부서'; + +ALTER TABLE workers +ADD COLUMN notes TEXT NULL COMMENT '비고'; + +-- 기존 작업자들을 모두 활성 상태로 설정 +UPDATE workers SET status = 'active' WHERE status IS NULL; + +-- 인덱스 추가 (성능 최적화) +CREATE INDEX idx_workers_status ON workers(status); +CREATE INDEX idx_workers_job_type ON workers(job_type); +CREATE INDEX idx_workers_hire_date ON workers(hire_date); diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/01_complete_data.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/01_complete_data.sql new file mode 100644 index 0000000..931114b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/01_complete_data.sql @@ -0,0 +1,4567 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.2 +-- https://www.phpmyadmin.net/ +-- +-- 호스트: db_hyungi_net +-- 생성 시간: 25-10-11 00:23 +-- 서버 버전: 10.9.8-MariaDB-1:10.9.8+maria~ubu2204 +-- PHP 버전: 8.2.27 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- 데이터베이스: `hyungi` +-- + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `activity_logs` +-- + +CREATE TABLE `activity_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `activity_type` varchar(100) DEFAULT NULL, + `table_name` varchar(50) DEFAULT NULL, + `record_id` int(11) DEFAULT NULL, + `action` enum('create','read','update','delete') DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `CuttingPlan` +-- + +CREATE TABLE `CuttingPlan` ( + `cutting_plan_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `drawing_name` varchar(255) NOT NULL, + `area_number` varchar(100) DEFAULT NULL, + `spool_number` varchar(255) DEFAULT NULL, + `length` decimal(10,2) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `spec_id` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `DailyIssueReports` +-- + +CREATE TABLE `DailyIssueReports` ( + `id` int(11) NOT NULL, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `issue_type_id` int(11) DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `start_time` time NOT NULL, + `end_time` time NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `DailyIssueReports` +-- + +INSERT INTO `DailyIssueReports` (`id`, `date`, `worker_id`, `project_id`, `issue_type_id`, `description`, `created_at`, `start_time`, `end_time`) VALUES +(1, '2025-06-02', 1, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(2, '2025-06-02', 9, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(3, '2025-06-02', 7, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(4, '2025-06-04', 10, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(5, '2025-06-04', 6, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(6, '2025-06-04', 3, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(7, '2025-06-11', 10, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'), +(8, '2025-06-11', 6, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'), +(9, '2025-06-11', 3, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `daily_worker_summary` +-- + +CREATE TABLE `daily_worker_summary` ( + `id` int(11) NOT NULL, + `report_date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `total_hours` decimal(4,2) NOT NULL DEFAULT 8.00 COMMENT '총 근무시간', + `work_status` enum('normal','annual_leave','half_leave','overtime') DEFAULT 'normal' COMMENT '근무 상태', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `daily_work_reports` +-- + +CREATE TABLE `daily_work_reports` ( + `id` int(11) NOT NULL, + `report_date` date NOT NULL COMMENT '작업 날짜', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `project_id` int(11) NOT NULL COMMENT '프로젝트 ID', + `work_type_id` int(11) NOT NULL COMMENT '작업 유형 ID', + `work_status_id` int(11) DEFAULT 1 COMMENT '업무 상태 ID (1:정규, 2:에러)', + `error_type_id` int(11) DEFAULT NULL COMMENT '에러 유형 ID (에러일 때만)', + `work_hours` decimal(4,2) NOT NULL COMMENT '작업 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `created_by` int(11) NOT NULL DEFAULT 1 COMMENT '작성자 user_id', + `updated_by` int(11) DEFAULT NULL COMMENT '수정자 user_id' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `daily_work_reports` +-- + +INSERT INTO `daily_work_reports` (`id`, `report_date`, `worker_id`, `project_id`, `work_type_id`, `work_status_id`, `error_type_id`, `work_hours`, `created_at`, `updated_at`, `created_by`, `updated_by`) VALUES +(14, '2025-06-02', 1, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(15, '2025-06-02', 3, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(16, '2025-06-02', 4, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(17, '2025-06-02', 6, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(18, '2025-06-02', 7, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(19, '2025-06-02', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(20, '2025-06-02', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:10:47', '2025-06-16 05:10:47', 1, NULL), +(21, '2025-06-04', 1, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(22, '2025-06-04', 3, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(23, '2025-06-04', 5, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(24, '2025-06-04', 7, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(25, '2025-06-04', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(26, '2025-06-04', 10, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(27, '2025-06-04', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(28, '2025-06-04', 6, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(29, '2025-06-04', 8, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(30, '2025-06-05', 1, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(31, '2025-06-05', 3, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(32, '2025-06-05', 4, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(33, '2025-06-05', 7, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(34, '2025-06-05', 10, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(35, '2025-06-05', 9, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(36, '2025-06-05', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(37, '2025-06-05', 5, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(38, '2025-06-05', 6, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(39, '2025-06-05', 8, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(40, '2025-06-16', 5, 3, 2, 1, NULL, 8.00, '2025-06-16 06:12:01', '2025-06-16 06:12:01', 5, NULL), +(43, '2025-06-16', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 06:12:01', '2025-06-16 06:12:01', 5, NULL), +(44, '2025-06-16', 6, 3, 2, 2, 4, 4.00, '2025-06-16 06:13:02', '2025-06-16 06:13:02', 5, NULL), +(45, '2025-06-16', 6, 3, 2, 1, NULL, 4.00, '2025-06-16 06:13:50', '2025-06-16 06:13:50', 5, NULL), +(46, '2025-06-16', 8, 3, 2, 2, 4, 4.00, '2025-06-16 06:15:22', '2025-06-16 06:15:22', 5, NULL), +(47, '2025-06-16', 8, 3, 2, 1, NULL, 4.00, '2025-06-16 06:15:22', '2025-06-16 06:15:22', 5, NULL), +(48, '2025-06-16', 4, 4, 3, 2, 1, 8.00, '2025-06-16 06:46:44', '2025-06-16 06:46:44', 3, NULL), +(50, '2025-06-16', 1, 4, 3, 2, 1, 8.00, '2025-06-16 06:46:44', '2025-06-16 06:46:44', 3, NULL), +(51, '2025-06-16', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 06:48:29', '2025-06-16 06:48:29', 3, NULL), +(52, '2025-06-16', 10, 4, 3, 1, NULL, 6.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(53, '2025-06-16', 10, 4, 3, 2, 1, 2.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(54, '2025-06-16', 3, 4, 3, 1, NULL, 6.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(55, '2025-06-16', 3, 4, 3, 2, 1, 2.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(56, '2025-06-17', 2, 3, 2, 1, NULL, 8.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(57, '2025-06-17', 2, 3, 2, 1, NULL, 2.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(58, '2025-06-17', 5, 3, 2, 1, NULL, 8.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(59, '2025-06-17', 5, 3, 2, 1, NULL, 2.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(60, '2025-06-17', 6, 3, 2, 1, NULL, 8.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(61, '2025-06-17', 6, 3, 2, 2, 4, 2.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(62, '2025-06-17', 8, 3, 2, 1, NULL, 8.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(63, '2025-06-17', 8, 3, 2, 2, 4, 2.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(65, '2025-06-17', 9, 4, 3, 2, 1, 4.00, '2025-06-17 08:25:24', '2025-06-17 08:25:24', 3, NULL), +(66, '2025-06-17', 1, 4, 3, 2, 1, 4.00, '2025-06-17 08:27:06', '2025-06-17 08:27:06', 3, NULL), +(67, '2025-06-17', 4, 4, 3, 2, 1, 4.00, '2025-06-17 08:27:06', '2025-06-17 08:27:06', 3, NULL), +(68, '2025-06-17', 1, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(69, '2025-06-17', 9, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(70, '2025-06-17', 4, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(71, '2025-06-17', 9, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(72, '2025-06-17', 4, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(73, '2025-06-17', 1, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(74, '2025-06-17', 10, 4, 3, 1, NULL, 8.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(75, '2025-06-17', 10, 4, 3, 2, 1, 2.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(76, '2025-06-17', 3, 4, 3, 1, NULL, 8.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(77, '2025-06-17', 3, 4, 3, 2, 1, 2.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(78, '2025-06-18', 6, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(79, '2025-06-18', 2, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(80, '2025-06-18', 8, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(81, '2025-06-18', 2, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:02', '2025-06-18 08:41:02', 5, NULL), +(82, '2025-06-18', 6, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:03', '2025-06-18 08:41:03', 5, NULL), +(83, '2025-06-18', 8, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:03', '2025-06-18 08:41:03', 5, NULL), +(84, '2025-06-18', 5, 4, 3, 1, NULL, 8.00, '2025-06-18 08:41:45', '2025-06-18 08:41:45', 5, NULL), +(85, '2025-06-18', 5, 4, 3, 1, NULL, 2.00, '2025-06-18 08:41:45', '2025-06-18 08:41:45', 5, NULL), +(86, '2025-06-18', 10, 4, 3, 1, NULL, 9.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(87, '2025-06-18', 10, 4, 3, 2, 1, 1.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(88, '2025-06-18', 3, 4, 3, 1, NULL, 9.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(89, '2025-06-18', 3, 4, 3, 2, 1, 1.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(90, '2025-06-18', 4, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(91, '2025-06-18', 4, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(92, '2025-06-18', 9, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(93, '2025-06-18', 9, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(94, '2025-06-18', 1, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(95, '2025-06-18', 1, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(96, '2025-06-18', 7, 4, 3, 2, 1, 4.00, '2025-06-18 09:00:17', '2025-06-18 09:00:17', 3, NULL), +(97, '2025-06-18', 7, 4, 3, 1, NULL, 6.00, '2025-06-18 09:00:17', '2025-06-18 09:00:17', 3, NULL), +(98, '2025-06-19', 8, 3, 2, 1, NULL, 8.00, '2025-06-19 06:37:59', '2025-06-19 06:37:59', 5, NULL), +(99, '2025-06-19', 2, 3, 2, 1, NULL, 8.00, '2025-06-19 06:37:59', '2025-06-19 06:37:59', 5, NULL), +(100, '2025-06-19', 10, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(101, '2025-06-19', 3, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(102, '2025-06-19', 5, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(103, '2025-06-19', 9, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(104, '2025-06-19', 9, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(105, '2025-06-19', 4, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(106, '2025-06-19', 4, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(107, '2025-06-19', 1, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(108, '2025-06-19', 1, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(109, '2025-06-19', 7, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(110, '2025-06-19', 7, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(111, '2025-06-19', 6, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(112, '2025-06-19', 6, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(113, '2025-06-20', 9, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(114, '2025-06-20', 9, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(115, '2025-06-20', 4, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(116, '2025-06-20', 4, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(117, '2025-06-20', 7, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(118, '2025-06-20', 7, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(119, '2025-06-20', 6, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(120, '2025-06-20', 6, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(121, '2025-06-20', 1, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(122, '2025-06-20', 1, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(123, '2025-06-20', 5, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(124, '2025-06-20', 5, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(125, '2025-06-20', 10, 4, 3, 1, NULL, 8.00, '2025-06-20 06:45:30', '2025-06-20 06:45:30', 6, NULL), +(126, '2025-06-20', 3, 4, 3, 1, NULL, 8.00, '2025-06-20 06:45:31', '2025-06-20 06:45:31', 6, NULL), +(127, '2025-06-23', 10, 4, 3, 1, NULL, 8.00, '2025-06-23 06:42:58', '2025-06-23 06:42:58', 6, NULL), +(128, '2025-06-23', 3, 4, 3, 1, NULL, 8.00, '2025-06-23 06:42:58', '2025-06-23 06:42:58', 6, NULL), +(129, '2025-06-23', 5, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(130, '2025-06-23', 5, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(131, '2025-06-23', 1, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(132, '2025-06-23', 1, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(133, '2025-06-23', 9, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(134, '2025-06-23', 9, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(135, '2025-06-23', 4, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(136, '2025-06-23', 4, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(137, '2025-06-23', 7, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(138, '2025-06-23', 7, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(139, '2025-06-23', 6, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(140, '2025-06-23', 6, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(141, '2025-06-24', 10, 4, 3, 1, NULL, 12.00, '2025-06-24 11:10:32', '2025-06-24 11:10:32', 6, NULL), +(142, '2025-06-24', 3, 4, 3, 1, NULL, 12.00, '2025-06-24 11:10:32', '2025-06-24 11:10:32', 6, NULL), +(143, '2025-06-24', 9, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(144, '2025-06-24', 9, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(145, '2025-06-24', 5, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(146, '2025-06-24', 5, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(147, '2025-06-24', 4, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(148, '2025-06-24', 4, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(149, '2025-06-24', 7, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(150, '2025-06-24', 7, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(151, '2025-06-24', 6, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(152, '2025-06-24', 6, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(153, '2025-06-24', 1, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(154, '2025-06-24', 1, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(155, '2025-06-24', 8, 3, 2, 1, NULL, 8.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(156, '2025-06-24', 8, 3, 2, 1, NULL, 4.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(157, '2025-06-24', 2, 3, 2, 1, NULL, 8.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(158, '2025-06-24', 2, 3, 2, 1, NULL, 4.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(159, '2025-06-25', 2, 3, 2, 1, NULL, 8.00, '2025-06-25 11:08:04', '2025-06-25 11:08:04', 5, NULL), +(160, '2025-06-25', 2, 3, 2, 1, NULL, 4.00, '2025-06-25 11:08:04', '2025-06-25 11:08:04', 5, NULL), +(161, '2025-06-25', 8, 3, 2, 1, NULL, 8.00, '2025-06-25 11:08:05', '2025-06-25 11:08:05', 5, NULL), +(162, '2025-06-25', 8, 3, 2, 1, NULL, 4.00, '2025-06-25 11:08:05', '2025-06-25 11:08:05', 5, NULL), +(163, '2025-06-25', 10, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(164, '2025-06-25', 9, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(165, '2025-06-25', 3, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(166, '2025-06-25', 6, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(167, '2025-06-26', 10, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(168, '2025-06-26', 5, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(169, '2025-06-26', 7, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(170, '2025-06-26', 1, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(171, '2025-06-26', 4, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(172, '2025-06-26', 8, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:31', '2025-06-26 11:11:31', 5, NULL), +(173, '2025-06-26', 8, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:31', '2025-06-26 11:11:31', 5, NULL), +(174, '2025-06-26', 2, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(175, '2025-06-26', 2, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(176, '2025-06-26', 9, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(177, '2025-06-26', 9, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(178, '2025-06-26', 3, 3, 2, 1, NULL, 12.00, '2025-06-26 11:19:34', '2025-06-26 11:19:34', 6, NULL), +(179, '2025-06-26', 6, 3, 2, 1, NULL, 12.00, '2025-06-26 11:19:34', '2025-06-26 11:19:34', 6, NULL), +(182, '2025-06-27', 2, 3, 2, 1, NULL, 4.00, '2025-06-27 01:54:40', '2025-06-27 01:54:40', 5, NULL), +(183, '2025-06-27', 9, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(184, '2025-06-27', 10, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(185, '2025-06-27', 7, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(186, '2025-06-27', 5, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(187, '2025-06-27', 4, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(188, '2025-06-27', 1, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(189, '2025-06-27', 3, 3, 2, 1, NULL, 8.00, '2025-06-27 06:49:08', '2025-06-27 06:49:08', 6, NULL), +(191, '2025-06-27', 6, 3, 2, 1, NULL, 4.00, '2025-06-27 06:58:46', '2025-06-27 06:58:46', 6, NULL), +(192, '2025-06-27', 8, 3, 2, 1, NULL, 6.00, '2025-06-27 07:00:10', '2025-06-27 07:00:10', 5, NULL), +(193, '2025-06-30', 6, 3, 2, 2, 4, 2.00, '2025-07-05 01:37:29', '2025-07-05 01:37:29', 3, NULL), +(194, '2025-06-30', 6, 3, 2, 1, NULL, 2.00, '2025-07-05 01:37:29', '2025-07-07 04:15:25', 3, 3), +(195, '2025-06-30', 2, 3, 2, 1, NULL, 4.00, '2025-07-05 01:38:19', '2025-07-07 04:15:40', 3, 3), +(196, '2025-06-30', 3, 3, 2, 1, NULL, 8.00, '2025-07-05 01:38:19', '2025-07-05 01:38:19', 3, NULL), +(197, '2025-06-30', 8, 3, 2, 1, NULL, 6.00, '2025-07-05 01:38:19', '2025-07-07 04:15:02', 3, 3), +(198, '2025-07-01', 3, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(199, '2025-07-01', 2, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(200, '2025-07-01', 6, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(201, '2025-07-01', 8, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(202, '2025-07-01', 10, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(203, '2025-07-01', 9, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(204, '2025-07-01', 2, 3, 2, 1, NULL, 2.00, '2025-07-05 01:39:48', '2025-07-05 01:42:08', 3, 3), +(205, '2025-07-01', 3, 3, 2, 1, NULL, 2.00, '2025-07-05 01:39:48', '2025-07-05 01:42:02', 3, 3), +(206, '2025-07-01', 6, 3, 2, 1, NULL, 2.00, '2025-07-05 01:39:48', '2025-07-05 01:41:56', 3, 3), +(207, '2025-07-01', 8, 3, 2, 1, NULL, 2.00, '2025-07-05 01:39:48', '2025-07-05 01:41:48', 3, 3), +(208, '2025-07-01', 9, 3, 2, 2, 4, 2.00, '2025-07-05 01:40:10', '2025-07-05 01:40:10', 3, NULL), +(209, '2025-07-01', 10, 3, 2, 2, 4, 2.00, '2025-07-05 01:40:10', '2025-07-05 01:40:10', 3, NULL), +(210, '2025-07-01', 7, 4, 3, 1, NULL, 5.00, '2025-07-05 01:42:57', '2025-07-05 01:42:57', 3, NULL), +(211, '2025-07-01', 7, 4, 3, 2, 2, 3.00, '2025-07-05 01:42:57', '2025-07-05 01:42:57', 3, NULL), +(212, '2025-07-01', 5, 4, 3, 1, NULL, 8.00, '2025-07-05 01:42:57', '2025-07-07 04:21:24', 3, 3), +(213, '2025-07-01', 5, 4, 3, 2, 2, 4.00, '2025-07-05 01:42:57', '2025-07-07 04:21:10', 3, 3), +(214, '2025-07-01', 4, 4, 3, 1, NULL, 8.00, '2025-07-05 01:42:57', '2025-07-07 04:21:41', 3, 3), +(215, '2025-07-01', 4, 4, 3, 2, 2, 4.00, '2025-07-05 01:42:57', '2025-07-07 04:21:32', 3, 3), +(216, '2025-07-01', 1, 4, 3, 1, NULL, 5.00, '2025-07-05 01:42:57', '2025-07-05 01:42:57', 3, NULL), +(217, '2025-07-01', 1, 4, 3, 2, 2, 3.00, '2025-07-05 01:42:57', '2025-07-05 01:42:57', 3, NULL), +(218, '2025-07-02', 2, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(219, '2025-07-02', 3, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(220, '2025-07-02', 10, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(221, '2025-07-02', 9, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(222, '2025-07-02', 8, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(223, '2025-07-02', 6, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(224, '2025-07-02', 7, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(225, '2025-07-02', 5, 4, 3, 2, 2, 4.00, '2025-07-05 01:44:11', '2025-07-05 01:44:11', 3, NULL), +(226, '2025-07-02', 5, 4, 3, 1, NULL, 6.00, '2025-07-05 01:44:11', '2025-07-05 01:44:54', 3, 3), +(227, '2025-07-02', 4, 4, 3, 2, 2, 4.00, '2025-07-05 01:44:11', '2025-07-05 01:44:11', 3, NULL), +(228, '2025-07-02', 4, 4, 3, 1, NULL, 6.00, '2025-07-05 01:44:11', '2025-07-05 01:44:59', 3, 3), +(229, '2025-07-02', 1, 4, 3, 2, 2, 4.00, '2025-07-05 01:44:11', '2025-07-05 01:44:11', 3, NULL), +(230, '2025-07-02', 1, 4, 3, 1, NULL, 6.00, '2025-07-05 01:44:11', '2025-07-05 01:45:05', 3, 3), +(231, '2025-07-03', 2, 3, 2, 1, NULL, 10.00, '2025-07-05 01:45:44', '2025-07-05 01:45:44', 3, NULL), +(232, '2025-07-03', 6, 3, 2, 1, NULL, 10.00, '2025-07-05 01:45:45', '2025-07-05 01:45:45', 3, NULL), +(233, '2025-07-03', 9, 3, 2, 1, NULL, 10.00, '2025-07-05 01:45:45', '2025-07-05 01:45:45', 3, NULL), +(234, '2025-07-03', 8, 3, 2, 1, NULL, 10.00, '2025-07-05 01:45:45', '2025-07-05 01:45:45', 3, NULL), +(235, '2025-07-03', 7, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:07', '2025-07-05 01:46:07', 3, NULL), +(236, '2025-07-03', 1, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:07', '2025-07-05 01:46:07', 3, NULL), +(237, '2025-07-03', 3, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:08', '2025-07-05 01:46:08', 3, NULL), +(238, '2025-07-03', 4, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:08', '2025-07-05 01:46:08', 3, NULL), +(239, '2025-07-03', 5, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:08', '2025-07-05 01:46:08', 3, NULL), +(240, '2025-07-03', 10, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:08', '2025-07-05 01:46:08', 3, NULL), +(241, '2025-07-04', 10, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(242, '2025-07-04', 10, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(243, '2025-07-04', 5, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(244, '2025-07-04', 5, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(245, '2025-07-04', 4, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(246, '2025-07-04', 4, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(247, '2025-07-04', 9, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(248, '2025-07-04', 9, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(249, '2025-07-04', 8, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(250, '2025-07-04', 8, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(251, '2025-07-04', 3, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(252, '2025-07-04', 3, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(253, '2025-07-04', 2, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(254, '2025-07-04', 2, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(255, '2025-07-04', 7, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(256, '2025-07-04', 7, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(257, '2025-07-04', 6, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(258, '2025-07-04', 6, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(259, '2025-07-04', 1, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(260, '2025-07-04', 1, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(261, '2025-07-05', 8, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:38', '2025-07-05 05:36:38', 5, NULL), +(262, '2025-07-05', 5, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:38', '2025-07-05 05:36:38', 5, NULL), +(263, '2025-07-05', 4, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:39', '2025-07-05 05:36:39', 5, NULL), +(264, '2025-07-05', 3, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:39', '2025-07-05 05:36:39', 5, NULL), +(265, '2025-07-05', 2, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:39', '2025-07-05 05:36:39', 5, NULL), +(266, '2025-07-05', 1, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:39', '2025-07-05 05:36:39', 5, NULL), +(267, '2025-07-06', 10, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:08', 5, 3), +(268, '2025-07-06', 9, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:16', 5, 3), +(269, '2025-07-06', 7, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:22', 5, 3), +(270, '2025-07-06', 6, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:27', 5, 3), +(271, '2025-07-06', 4, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:33', 5, 3), +(272, '2025-07-06', 3, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:39', 5, 3), +(273, '2025-07-06', 2, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:44', 5, 3), +(274, '2025-07-06', 1, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:49', 5, 3), +(275, '2025-07-07', 10, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(276, '2025-07-07', 9, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(277, '2025-07-07', 8, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(278, '2025-07-07', 7, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(279, '2025-07-07', 3, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(280, '2025-07-07', 4, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(281, '2025-07-07', 5, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(282, '2025-07-07', 6, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(283, '2025-07-07', 2, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(284, '2025-07-07', 1, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(285, '2025-07-08', 10, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:57', '2025-07-08 06:36:57', 3, NULL), +(286, '2025-07-08', 9, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(287, '2025-07-08', 8, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(288, '2025-07-08', 7, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(289, '2025-07-08', 6, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(290, '2025-07-08', 1, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(291, '2025-07-08', 2, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(292, '2025-07-08', 3, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(293, '2025-07-08', 5, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(294, '2025-07-08', 4, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(295, '2025-07-09', 10, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:40', '2025-07-09 22:08:40', 5, NULL), +(296, '2025-07-09', 9, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:40', '2025-07-09 22:08:40', 5, NULL), +(297, '2025-07-09', 8, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:40', '2025-07-09 22:08:40', 5, NULL), +(298, '2025-07-09', 7, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:41', '2025-07-09 22:08:41', 5, NULL), +(299, '2025-07-09', 6, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:41', '2025-07-09 22:08:41', 5, NULL), +(300, '2025-07-09', 2, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:41', '2025-07-09 22:08:41', 5, NULL), +(301, '2025-07-09', 3, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:42', '2025-07-09 22:08:42', 5, NULL), +(302, '2025-07-09', 4, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:42', '2025-07-09 22:08:42', 5, NULL), +(303, '2025-07-09', 5, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:42', '2025-07-09 22:08:42', 5, NULL), +(304, '2025-07-09', 1, 4, 3, 1, NULL, 4.00, '2025-07-09 22:09:10', '2025-07-09 22:09:10', 5, NULL), +(305, '2025-07-10', 9, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:58', '2025-07-10 06:33:58', 3, NULL), +(306, '2025-07-10', 8, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:58', '2025-07-10 06:33:58', 3, NULL), +(307, '2025-07-10', 5, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:58', '2025-07-10 06:33:58', 3, NULL), +(308, '2025-07-10', 6, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(309, '2025-07-10', 2, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(310, '2025-07-10', 3, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(311, '2025-07-10', 4, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(312, '2025-07-10', 1, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(313, '2025-07-10', 7, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(314, '2025-07-10', 10, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(315, '2025-07-12', 9, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(316, '2025-07-12', 8, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(317, '2025-07-12', 6, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(318, '2025-07-12', 5, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(319, '2025-07-12', 4, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(320, '2025-07-12', 2, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(321, '2025-07-12', 1, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(322, '2025-07-14', 8, 4, 3, 1, NULL, 6.00, '2025-07-14 06:46:30', '2025-07-14 06:46:30', 3, NULL), +(323, '2025-07-14', 10, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(324, '2025-07-14', 9, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(325, '2025-07-14', 7, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(326, '2025-07-14', 6, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(327, '2025-07-14', 1, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(328, '2025-07-14', 2, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(329, '2025-07-14', 3, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(330, '2025-07-14', 4, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(331, '2025-07-15', 3, 3, 2, 1, NULL, 8.00, '2025-07-15 05:57:06', '2025-07-15 05:57:06', 5, NULL), +(332, '2025-07-15', 9, 3, 2, 1, NULL, 8.00, '2025-07-15 05:57:06', '2025-07-15 05:57:06', 5, NULL), +(333, '2025-07-15', 5, 3, 2, 2, 4, 4.00, '2025-07-15 05:57:47', '2025-07-15 05:57:47', 5, NULL), +(334, '2025-07-15', 5, 4, 3, 1, NULL, 4.00, '2025-07-15 05:57:47', '2025-07-15 05:57:47', 5, NULL), +(335, '2025-07-15', 10, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(336, '2025-07-15', 8, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(337, '2025-07-15', 7, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(338, '2025-07-15', 6, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(339, '2025-07-15', 2, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(340, '2025-07-15', 1, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(341, '2025-07-14', 5, 4, 3, 1, NULL, 8.00, '2025-07-15 06:57:26', '2025-07-15 06:57:26', 3, NULL), +(342, '2025-07-16', 4, 4, 3, 1, NULL, 2.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(343, '2025-07-16', 4, 3, 2, 1, NULL, 4.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(344, '2025-07-16', 4, 3, 2, 1, NULL, 2.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(345, '2025-07-16', 5, 4, 3, 1, NULL, 2.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(346, '2025-07-16', 5, 3, 2, 1, NULL, 4.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(347, '2025-07-16', 5, 3, 2, 1, NULL, 2.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(348, '2025-07-16', 10, 4, 3, 1, NULL, 2.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(349, '2025-07-16', 10, 3, 2, 1, NULL, 4.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(350, '2025-07-16', 10, 3, 2, 1, NULL, 2.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(351, '2025-07-16', 6, 4, 3, 1, NULL, 2.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(352, '2025-07-16', 6, 3, 2, 1, NULL, 4.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(353, '2025-07-16', 6, 3, 2, 1, NULL, 2.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(354, '2025-07-16', 9, 3, 2, 1, NULL, 8.00, '2025-07-16 06:48:32', '2025-07-16 06:48:32', 5, NULL), +(355, '2025-07-16', 8, 3, 2, 1, NULL, 8.00, '2025-07-16 06:48:32', '2025-07-16 06:48:32', 5, NULL), +(356, '2025-07-16', 3, 3, 2, 1, NULL, 8.00, '2025-07-16 06:48:32', '2025-07-16 06:48:32', 5, NULL), +(357, '2025-07-16', 2, 3, 2, 1, NULL, 8.00, '2025-07-16 06:48:32', '2025-07-16 06:48:32', 5, NULL), +(358, '2025-07-16', 1, 4, 3, 1, NULL, 8.00, '2025-07-16 06:51:31', '2025-07-16 06:51:31', 3, NULL), +(359, '2025-07-16', 7, 4, 3, 1, NULL, 8.00, '2025-07-16 06:51:31', '2025-07-16 06:51:31', 3, NULL), +(360, '2025-07-17', 1, 3, 3, 1, NULL, 8.00, '2025-07-17 06:45:22', '2025-07-17 06:45:22', 3, NULL), +(361, '2025-07-17', 5, 3, 2, 1, NULL, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(362, '2025-07-17', 5, 3, 2, 2, 4, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(363, '2025-07-17', 4, 3, 2, 1, NULL, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(364, '2025-07-17', 4, 3, 2, 2, 4, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(365, '2025-07-17', 2, 3, 2, 1, NULL, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(366, '2025-07-17', 2, 3, 2, 2, 4, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(367, '2025-07-17', 10, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(368, '2025-07-17', 9, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(369, '2025-07-17', 8, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(370, '2025-07-17', 7, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(371, '2025-07-17', 6, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(372, '2025-07-17', 3, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(373, '2025-07-18', 7, 4, 3, 2, 1, 2.00, '2025-07-18 05:54:47', '2025-07-18 05:54:47', 3, NULL), +(374, '2025-07-18', 1, 4, 3, 2, 1, 2.00, '2025-07-18 05:54:48', '2025-07-18 05:54:48', 3, NULL), +(376, '2025-07-18', 5, 4, 3, 1, NULL, 2.00, '2025-07-18 05:58:33', '2025-07-18 05:58:33', 3, NULL), +(377, '2025-07-18', 5, 3, 2, 1, NULL, 6.00, '2025-07-18 05:58:33', '2025-07-18 05:58:33', 3, NULL), +(378, '2025-07-18', 7, 3, 2, 1, NULL, 6.00, '2025-07-18 05:59:42', '2025-07-18 05:59:42', 3, NULL), +(379, '2025-07-18', 1, 3, 3, 1, NULL, 6.00, '2025-07-18 06:00:15', '2025-07-18 06:00:15', 3, NULL), +(380, '2025-07-18', 10, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(381, '2025-07-18', 9, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(382, '2025-07-18', 8, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(383, '2025-07-18', 6, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(384, '2025-07-18', 4, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(385, '2025-07-18', 3, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(386, '2025-07-18', 2, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(387, '2025-07-21', 5, 4, 3, 2, 1, 4.00, '2025-07-21 06:40:08', '2025-07-21 06:40:08', 5, NULL), +(388, '2025-07-21', 5, 3, 2, 1, NULL, 4.00, '2025-07-21 06:40:08', '2025-07-21 06:40:08', 5, NULL), +(389, '2025-07-21', 4, 4, 3, 2, 1, 4.00, '2025-07-21 06:40:08', '2025-07-21 06:40:08', 5, NULL), +(390, '2025-07-21', 4, 3, 2, 1, NULL, 4.00, '2025-07-21 06:40:08', '2025-07-21 06:40:08', 5, NULL), +(391, '2025-07-21', 10, 3, 2, 1, NULL, 6.00, '2025-07-21 06:40:32', '2025-07-22 06:58:42', 5, 3), +(392, '2025-07-21', 9, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(393, '2025-07-21', 8, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(394, '2025-07-21', 7, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(395, '2025-07-21', 6, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(396, '2025-07-21', 3, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(397, '2025-07-21', 2, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(398, '2025-07-21', 1, 3, 3, 1, NULL, 8.00, '2025-07-21 06:53:37', '2025-07-21 06:53:37', 3, NULL), +(399, '2025-07-22', 10, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:47', '2025-07-22 06:45:47', 5, NULL), +(400, '2025-07-22', 9, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(401, '2025-07-22', 8, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(402, '2025-07-22', 7, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(403, '2025-07-22', 6, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(404, '2025-07-22', 4, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(405, '2025-07-22', 3, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(406, '2025-07-22', 2, 4, 3, 2, 1, 8.00, '2025-07-22 06:46:11', '2025-07-22 06:46:11', 5, NULL), +(407, '2025-07-22', 5, 3, 3, 1, NULL, 8.00, '2025-07-22 06:46:11', '2025-07-22 06:46:11', 3, NULL), +(408, '2025-07-22', 1, 3, 3, 1, NULL, 8.00, '2025-07-22 06:46:11', '2025-07-22 06:46:11', 3, NULL), +(409, '2025-07-23', 4, 3, 3, 1, NULL, 8.00, '2025-07-23 06:45:06', '2025-07-23 06:45:06', 5, NULL), +(410, '2025-07-23', 5, 3, 3, 1, NULL, 8.00, '2025-07-23 06:45:28', '2025-07-23 06:45:28', 3, NULL), +(411, '2025-07-23', 1, 3, 3, 1, NULL, 8.00, '2025-07-23 06:45:28', '2025-07-23 06:45:28', 3, NULL), +(412, '2025-07-23', 10, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(413, '2025-07-23', 9, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(414, '2025-07-23', 7, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(415, '2025-07-23', 6, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(416, '2025-07-23', 3, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(417, '2025-07-23', 2, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(418, '2025-07-24', 4, 3, 3, 1, NULL, 8.00, '2025-07-24 06:36:55', '2025-07-24 06:36:55', 5, NULL), +(419, '2025-07-24', 10, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(420, '2025-07-24', 9, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(421, '2025-07-24', 7, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(422, '2025-07-24', 6, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(423, '2025-07-24', 3, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(424, '2025-07-24', 2, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(425, '2025-07-24', 5, 3, 3, 1, NULL, 8.00, '2025-07-24 06:47:04', '2025-07-24 06:47:04', 3, NULL), +(426, '2025-07-24', 1, 3, 3, 1, NULL, 8.00, '2025-07-24 06:47:04', '2025-07-24 06:47:04', 3, NULL), +(427, '2025-07-25', 4, 3, 3, 1, NULL, 8.00, '2025-07-25 06:44:23', '2025-07-25 06:44:23', 5, NULL), +(428, '2025-07-25', 10, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(429, '2025-07-25', 9, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(430, '2025-07-25', 8, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(431, '2025-07-25', 6, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(432, '2025-07-25', 3, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(433, '2025-07-25', 2, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(434, '2025-07-25', 5, 4, 3, 1, NULL, 8.00, '2025-07-25 06:45:18', '2025-07-25 06:45:18', 3, NULL), +(435, '2025-07-25', 7, 4, 3, 1, NULL, 8.00, '2025-07-25 06:45:19', '2025-07-25 06:45:19', 3, NULL), +(436, '2025-07-25', 1, 4, 3, 1, NULL, 8.00, '2025-07-25 06:45:19', '2025-07-25 06:45:19', 3, NULL), +(437, '2025-07-28', 5, 3, 3, 1, NULL, 8.00, '2025-07-28 06:30:39', '2025-07-28 06:30:39', 3, NULL), +(438, '2025-07-28', 4, 3, 3, 1, NULL, 8.00, '2025-07-28 06:30:39', '2025-07-28 06:30:39', 3, NULL), +(439, '2025-07-28', 1, 3, 3, 1, NULL, 8.00, '2025-07-28 06:30:39', '2025-07-28 06:30:39', 3, NULL), +(440, '2025-07-28', 2, 5, 2, 1, NULL, 4.00, '2025-07-28 06:33:08', '2025-07-28 06:33:08', 5, NULL), +(441, '2025-07-28', 2, 3, 2, 1, NULL, 4.00, '2025-07-28 06:33:08', '2025-07-28 06:33:08', 5, NULL), +(442, '2025-07-28', 10, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(443, '2025-07-28', 9, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(444, '2025-07-28', 8, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(445, '2025-07-28', 7, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(446, '2025-07-28', 6, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(447, '2025-07-28', 3, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(448, '2025-07-29', 5, 3, 3, 1, NULL, 8.00, '2025-07-29 06:39:13', '2025-07-29 06:39:13', 3, NULL), +(449, '2025-07-29', 4, 3, 3, 1, NULL, 8.00, '2025-07-29 06:39:13', '2025-07-29 06:39:13', 3, NULL), +(450, '2025-07-29', 1, 3, 3, 1, NULL, 8.00, '2025-07-29 06:39:13', '2025-07-29 06:39:13', 3, NULL), +(451, '2025-07-30', 5, 3, 3, 1, NULL, 8.00, '2025-07-30 06:50:30', '2025-07-30 06:50:30', 3, NULL), +(452, '2025-07-30', 4, 3, 3, 1, NULL, 8.00, '2025-07-30 06:50:30', '2025-07-30 06:50:30', 3, NULL), +(453, '2025-07-30', 1, 3, 3, 1, NULL, 8.00, '2025-07-30 06:50:30', '2025-07-30 06:50:30', 3, NULL), +(454, '2025-07-30', 10, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(455, '2025-07-30', 9, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(456, '2025-07-30', 8, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(457, '2025-07-30', 7, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(458, '2025-07-30', 6, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(459, '2025-07-30', 3, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(460, '2025-07-30', 2, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(461, '2025-07-31', 1, 3, 3, 1, NULL, 4.00, '2025-07-31 06:42:56', '2025-07-31 06:42:56', 5, NULL), +(462, '2025-07-31', 4, 3, 3, 1, NULL, 4.00, '2025-07-31 06:43:32', '2025-07-31 06:43:32', 5, NULL), +(463, '2025-07-31', 4, 3, 2, 1, NULL, 4.00, '2025-07-31 06:43:32', '2025-07-31 06:43:32', 5, NULL), +(464, '2025-07-31', 5, 3, 3, 1, NULL, 4.00, '2025-07-31 06:43:32', '2025-07-31 06:43:32', 5, NULL), +(465, '2025-07-31', 5, 3, 2, 1, NULL, 4.00, '2025-07-31 06:43:32', '2025-07-31 06:43:32', 5, NULL), +(466, '2025-07-31', 10, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(467, '2025-07-31', 9, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(468, '2025-07-31', 8, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(469, '2025-07-31', 7, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(470, '2025-07-31', 6, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(471, '2025-07-31', 3, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(472, '2025-07-31', 2, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(473, '2025-07-11', 10, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(474, '2025-07-11', 5, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(475, '2025-07-11', 4, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(476, '2025-07-11', 9, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(477, '2025-07-11', 8, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(478, '2025-07-11', 3, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(479, '2025-07-11', 2, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(480, '2025-07-11', 7, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(481, '2025-07-11', 6, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(482, '2025-07-11', 1, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(483, '2025-08-01', 10, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(484, '2025-08-01', 9, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(485, '2025-08-01', 8, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(486, '2025-08-01', 7, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(487, '2025-08-01', 6, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(488, '2025-08-01', 3, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(489, '2025-08-01', 2, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:48', '2025-08-01 04:57:48', 5, NULL), +(490, '2025-08-01', 4, 3, 3, 1, NULL, 4.00, '2025-08-01 05:02:28', '2025-08-01 05:02:28', 3, NULL), +(491, '2025-08-01', 4, 5, 1, 1, NULL, 4.00, '2025-08-01 05:02:28', '2025-08-01 05:02:28', 3, NULL), +(492, '2025-08-01', 5, 3, 3, 1, NULL, 4.00, '2025-08-01 05:02:28', '2025-08-01 05:02:28', 3, NULL), +(493, '2025-08-01', 5, 5, 1, 1, NULL, 4.00, '2025-08-01 05:02:28', '2025-08-01 05:02:28', 3, NULL), +(494, '2025-08-07', 9, 3, 2, 2, 4, 4.00, '2025-08-07 06:42:39', '2025-08-07 06:42:39', 5, NULL), +(495, '2025-08-07', 9, 3, 2, 1, NULL, 4.00, '2025-08-07 06:42:39', '2025-08-07 06:42:39', 5, NULL), +(496, '2025-08-07', 7, 3, 2, 2, 4, 4.00, '2025-08-07 06:42:39', '2025-08-07 06:42:39', 5, NULL), +(497, '2025-08-07', 7, 3, 2, 1, NULL, 4.00, '2025-08-07 06:42:39', '2025-08-07 06:42:39', 5, NULL), +(498, '2025-08-07', 10, 5, 2, 1, NULL, 8.00, '2025-08-07 06:43:14', '2025-08-07 06:43:14', 5, NULL), +(499, '2025-08-07', 4, 5, 2, 1, NULL, 8.00, '2025-08-07 06:43:15', '2025-08-07 06:43:15', 5, NULL), +(500, '2025-08-07', 2, 5, 2, 1, NULL, 8.00, '2025-08-07 06:43:15', '2025-08-07 06:43:15', 5, NULL), +(501, '2025-08-07', 6, 3, 2, 1, NULL, 8.00, '2025-08-07 06:43:39', '2025-08-07 06:43:39', 5, NULL), +(502, '2025-08-07', 3, 3, 2, 1, NULL, 8.00, '2025-08-07 06:43:39', '2025-08-07 06:43:39', 5, NULL), +(503, '2025-08-07', 8, 3, 2, 1, NULL, 8.00, '2025-08-07 06:43:39', '2025-08-07 06:43:39', 5, NULL), +(504, '2025-08-07', 1, 3, 3, 1, NULL, 8.00, '2025-08-07 06:43:52', '2025-08-07 06:43:52', 3, NULL), +(505, '2025-08-08', 1, 3, 3, 1, NULL, 8.00, '2025-08-08 06:45:20', '2025-08-08 06:45:20', 3, NULL), +(506, '2025-08-08', 10, 5, 2, 1, NULL, 8.00, '2025-08-08 06:58:42', '2025-08-08 06:58:42', 5, NULL), +(507, '2025-08-08', 2, 5, 2, 1, NULL, 8.00, '2025-08-08 06:58:42', '2025-08-08 06:58:42', 5, NULL), +(508, '2025-08-08', 9, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:18', '2025-08-08 06:59:18', 5, NULL), +(509, '2025-08-08', 8, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:19', '2025-08-08 06:59:19', 5, NULL), +(510, '2025-08-08', 3, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:19', '2025-08-08 06:59:19', 5, NULL), +(511, '2025-08-08', 4, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:19', '2025-08-08 06:59:19', 5, NULL), +(512, '2025-08-08', 6, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:19', '2025-08-08 06:59:19', 5, NULL), +(513, '2025-08-11', 1, 3, 3, 1, NULL, 8.00, '2025-08-11 06:27:37', '2025-08-11 06:27:37', 3, NULL), +(514, '2025-08-11', 1, 3, 3, 1, NULL, 8.00, '2025-08-11 06:27:37', '2025-08-11 06:27:37', 3, NULL), +(515, '2025-08-11', 10, 5, 2, 1, NULL, 8.00, '2025-08-11 06:46:23', '2025-08-11 06:46:23', 5, NULL), +(516, '2025-08-11', 2, 5, 2, 1, NULL, 8.00, '2025-08-11 06:46:23', '2025-08-11 06:46:23', 5, NULL), +(517, '2025-08-11', 8, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:49', '2025-08-11 06:46:49', 5, NULL), +(518, '2025-08-11', 7, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:49', '2025-08-11 06:46:49', 5, NULL), +(519, '2025-08-11', 6, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:50', '2025-08-11 06:46:50', 5, NULL), +(520, '2025-08-11', 5, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:50', '2025-08-11 06:46:50', 5, NULL), +(521, '2025-08-11', 4, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:50', '2025-08-11 06:46:50', 5, NULL), +(522, '2025-08-11', 3, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:50', '2025-08-11 06:46:50', 5, NULL), +(523, '2025-08-12', 10, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(524, '2025-08-12', 9, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(525, '2025-08-12', 8, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(526, '2025-08-12', 7, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(527, '2025-08-12', 5, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(528, '2025-08-12', 4, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(529, '2025-08-12', 3, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(530, '2025-08-12', 1, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(531, '2025-08-13', 1, 3, 3, 1, NULL, 8.00, '2025-08-13 06:31:32', '2025-08-13 06:31:32', 3, NULL), +(532, '2025-08-13', 2, 3, 2, 1, NULL, 4.00, '2025-08-13 06:36:13', '2025-08-13 06:36:13', 5, NULL); +INSERT INTO `daily_work_reports` (`id`, `report_date`, `worker_id`, `project_id`, `work_type_id`, `work_status_id`, `error_type_id`, `work_hours`, `created_at`, `updated_at`, `created_by`, `updated_by`) VALUES +(533, '2025-08-13', 2, 5, 2, 1, NULL, 4.00, '2025-08-13 06:36:13', '2025-08-13 06:36:13', 5, NULL), +(534, '2025-08-13', 9, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(535, '2025-08-13', 8, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(536, '2025-08-13', 7, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(537, '2025-08-13', 6, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(538, '2025-08-13', 5, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(539, '2025-08-13', 4, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(540, '2025-08-13', 3, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(541, '2025-08-13', 10, 5, 2, 1, NULL, 8.00, '2025-08-13 06:37:19', '2025-08-13 06:37:19', 5, NULL), +(542, '2025-08-14', 1, 3, 3, 2, 1, 4.00, '2025-08-14 06:35:27', '2025-08-14 06:35:27', 3, NULL), +(543, '2025-08-14', 1, 3, 3, 1, NULL, 4.00, '2025-08-14 06:35:27', '2025-08-14 06:35:27', 3, NULL), +(544, '2025-08-14', 10, 5, 2, 1, NULL, 4.00, '2025-08-14 06:39:03', '2025-08-14 06:39:03', 5, NULL), +(545, '2025-08-14', 10, 5, 3, 1, NULL, 4.00, '2025-08-14 06:39:03', '2025-08-14 06:39:03', 5, NULL), +(546, '2025-08-14', 2, 5, 2, 1, NULL, 2.00, '2025-08-14 06:39:44', '2025-08-14 06:39:44', 5, NULL), +(547, '2025-08-14', 2, 3, 2, 1, NULL, 6.00, '2025-08-14 06:39:44', '2025-08-14 06:39:44', 5, NULL), +(548, '2025-08-14', 9, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(549, '2025-08-14', 8, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(550, '2025-08-14', 7, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(551, '2025-08-14', 6, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(552, '2025-08-14', 5, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(553, '2025-08-14', 4, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(554, '2025-08-18', 2, 3, 2, 1, NULL, 8.00, '2025-08-18 06:21:36', '2025-08-18 06:21:36', 5, NULL), +(555, '2025-08-18', 8, 3, 2, 1, NULL, 8.00, '2025-08-18 06:21:36', '2025-08-18 06:21:36', 5, NULL), +(556, '2025-08-18', 4, 3, 2, 1, NULL, 8.00, '2025-08-18 06:22:01', '2025-08-18 06:22:01', 5, NULL), +(557, '2025-08-18', 10, 5, 3, 1, NULL, 6.00, '2025-08-18 06:22:53', '2025-08-18 06:22:53', 5, NULL), +(558, '2025-08-18', 10, 3, 2, 1, NULL, 2.00, '2025-08-18 06:22:53', '2025-08-18 06:22:53', 5, NULL), +(559, '2025-08-18', 9, 3, 2, 1, NULL, 4.00, '2025-08-18 06:23:34', '2025-08-18 06:23:34', 5, NULL), +(560, '2025-08-18', 9, 3, 3, 1, NULL, 4.00, '2025-08-18 06:23:34', '2025-08-18 06:23:34', 5, NULL), +(561, '2025-08-18', 5, 3, 3, 2, 1, 4.00, '2025-08-18 06:41:24', '2025-08-18 06:41:24', 3, NULL), +(562, '2025-08-18', 1, 3, 3, 2, 1, 4.00, '2025-08-18 06:41:24', '2025-08-18 06:41:24', 3, NULL), +(563, '2025-08-18', 7, 3, 3, 2, 1, 4.00, '2025-08-18 06:41:24', '2025-08-18 06:41:24', 3, NULL), +(564, '2025-08-18', 7, 3, 3, 1, NULL, 4.00, '2025-08-18 06:43:10', '2025-08-18 06:43:10', 3, NULL), +(565, '2025-08-18', 5, 3, 3, 1, NULL, 4.00, '2025-08-18 06:43:10', '2025-08-18 06:43:10', 3, NULL), +(566, '2025-08-18', 1, 3, 3, 1, NULL, 4.00, '2025-08-18 06:43:10', '2025-08-18 06:43:10', 3, NULL), +(567, '2025-08-18', 6, 3, 3, 1, NULL, 8.00, '2025-08-18 06:43:35', '2025-08-18 06:43:35', 6, NULL), +(568, '2025-08-18', 3, 3, 3, 1, NULL, 8.00, '2025-08-18 06:43:35', '2025-08-18 06:43:35', 6, NULL), +(569, '2025-08-19', 1, 3, 3, 1, NULL, 6.00, '2025-08-19 08:02:49', '2025-08-19 08:02:49', 5, NULL), +(573, '2025-08-19', 9, 3, 3, 1, NULL, 10.00, '2025-08-19 08:03:30', '2025-08-19 08:03:30', 5, NULL), +(574, '2025-08-19', 10, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(575, '2025-08-19', 8, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(576, '2025-08-19', 5, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(577, '2025-08-19', 4, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(578, '2025-08-19', 2, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(579, '2025-08-19', 3, 3, 3, 1, NULL, 10.00, '2025-08-19 08:36:51', '2025-08-19 08:36:51', 6, NULL), +(580, '2025-08-19', 7, 3, 3, 1, NULL, 10.00, '2025-08-19 08:36:51', '2025-08-19 08:36:51', 6, NULL), +(581, '2025-08-19', 6, 3, 3, 1, NULL, 10.00, '2025-08-19 08:36:51', '2025-08-19 08:36:51', 6, NULL), +(582, '2025-08-20', 2, 3, 2, 1, NULL, 8.00, '2025-08-20 06:19:36', '2025-08-20 06:19:36', 5, NULL), +(583, '2025-08-20', 5, 3, 1, 1, NULL, 2.00, '2025-08-20 06:21:28', '2025-08-20 06:21:28', 5, NULL), +(584, '2025-08-20', 5, 3, 2, 1, NULL, 6.00, '2025-08-20 06:21:28', '2025-08-20 06:21:28', 5, NULL), +(585, '2025-08-20', 4, 3, 1, 1, NULL, 2.00, '2025-08-20 06:21:28', '2025-08-20 06:21:28', 5, NULL), +(586, '2025-08-20', 4, 3, 2, 1, NULL, 6.00, '2025-08-20 06:21:28', '2025-08-20 06:21:28', 5, NULL), +(587, '2025-08-20', 6, 3, 3, 1, NULL, 4.00, '2025-08-20 06:43:46', '2025-08-20 06:43:46', 3, NULL), +(589, '2025-08-20', 9, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:23', '2025-08-20 06:44:23', 3, NULL), +(590, '2025-08-20', 8, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:23', '2025-08-20 06:44:23', 3, NULL), +(591, '2025-08-20', 7, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:24', '2025-08-20 06:44:24', 3, NULL), +(593, '2025-08-20', 1, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:24', '2025-08-20 06:44:24', 3, NULL), +(594, '2025-08-20', 10, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:26', '2025-08-20 06:44:26', 6, NULL), +(595, '2025-08-20', 3, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:26', '2025-08-20 06:44:26', 6, NULL), +(596, '2025-08-21', 7, 3, 3, 1, NULL, 8.00, '2025-08-21 06:30:36', '2025-08-21 06:30:36', 3, NULL), +(597, '2025-08-21', 1, 3, 3, 1, NULL, 8.00, '2025-08-21 06:30:36', '2025-08-21 06:30:36', 3, NULL), +(600, '2025-08-21', 10, 3, 3, 1, NULL, 8.00, '2025-08-21 07:51:23', '2025-08-21 07:51:23', 5, NULL), +(601, '2025-08-21', 10, 3, 3, 1, NULL, 2.00, '2025-08-21 07:51:23', '2025-08-21 07:51:23', 5, NULL), +(602, '2025-08-21', 9, 3, 3, 1, NULL, 8.00, '2025-08-21 07:51:23', '2025-08-21 07:51:23', 5, NULL), +(603, '2025-08-21', 9, 3, 3, 1, NULL, 2.00, '2025-08-21 07:51:23', '2025-08-21 07:51:23', 5, NULL), +(608, '2025-08-21', 2, 3, 2, 1, NULL, 8.00, '2025-08-21 07:54:46', '2025-08-21 07:54:46', 5, NULL), +(609, '2025-08-21', 2, 5, 2, 1, NULL, 2.00, '2025-08-21 07:54:46', '2025-08-21 07:54:46', 5, NULL), +(610, '2025-08-21', 8, 3, 3, 1, NULL, 4.00, '2025-08-21 07:55:25', '2025-08-21 07:55:25', 5, NULL), +(611, '2025-08-21', 8, 3, 2, 1, NULL, 6.00, '2025-08-21 07:55:25', '2025-08-21 07:55:25', 5, NULL), +(612, '2025-08-21', 6, 3, 3, 1, NULL, 10.00, '2025-08-21 08:24:50', '2025-08-21 08:24:50', 6, NULL), +(613, '2025-08-21', 3, 3, 3, 1, NULL, 10.00, '2025-08-21 08:24:50', '2025-08-21 08:24:50', 6, NULL), +(614, '2025-08-22', 2, 3, 2, 1, NULL, 8.00, '2025-08-22 06:21:15', '2025-08-22 06:21:15', 5, NULL), +(615, '2025-08-22', 8, 3, 2, 1, NULL, 4.00, '2025-08-22 06:23:12', '2025-08-22 06:23:12', 5, NULL), +(616, '2025-08-22', 8, 3, 3, 1, NULL, 4.00, '2025-08-22 06:23:12', '2025-08-22 06:23:12', 5, NULL), +(617, '2025-08-22', 5, 3, 3, 1, NULL, 8.00, '2025-08-22 06:23:55', '2025-08-22 06:23:55', 5, NULL), +(618, '2025-08-22', 6, 3, 2, 1, NULL, 4.00, '2025-08-22 06:27:43', '2025-08-22 06:27:43', 3, NULL), +(619, '2025-08-22', 10, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(620, '2025-08-22', 9, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(621, '2025-08-22', 7, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(622, '2025-08-22', 4, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(623, '2025-08-22', 3, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(624, '2025-08-22', 1, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(625, '2025-08-23', 4, 3, 2, 1, NULL, 2.00, '2025-08-23 04:57:02', '2025-08-23 04:57:02', 5, NULL), +(626, '2025-08-23', 4, 3, 3, 1, NULL, 6.00, '2025-08-23 04:57:02', '2025-08-23 04:57:02', 5, NULL), +(627, '2025-08-23', 2, 3, 2, 1, NULL, 8.00, '2025-08-23 04:57:25', '2025-08-23 04:57:25', 5, NULL), +(628, '2025-08-23', 10, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(629, '2025-08-23', 9, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(630, '2025-08-23', 8, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(631, '2025-08-23', 6, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(632, '2025-08-23', 5, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(633, '2025-08-23', 3, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(634, '2025-08-23', 1, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(635, '2025-08-25', 10, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(636, '2025-08-25', 9, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(637, '2025-08-25', 8, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(638, '2025-08-25', 7, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(640, '2025-08-25', 5, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(641, '2025-08-25', 4, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(643, '2025-08-25', 2, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(644, '2025-08-25', 1, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(645, '2025-08-25', 6, 3, 3, 1, NULL, 8.00, '2025-08-25 06:49:16', '2025-08-25 06:49:16', 6, NULL), +(646, '2025-08-25', 3, 3, 3, 1, NULL, 8.00, '2025-08-25 06:49:17', '2025-08-25 06:49:17', 6, NULL), +(647, '2025-08-26', 4, 8, 3, 1, NULL, 8.00, '2025-08-26 07:28:03', '2025-08-26 07:28:03', 5, NULL), +(648, '2025-08-26', 4, 3, 3, 1, NULL, 2.00, '2025-08-26 07:28:03', '2025-08-26 07:28:03', 5, NULL), +(649, '2025-08-26', 2, 8, 3, 1, NULL, 10.00, '2025-08-26 07:28:35', '2025-08-26 07:28:35', 5, NULL), +(651, '2025-08-26', 9, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:02', '2025-08-26 07:29:02', 5, NULL), +(652, '2025-08-26', 8, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:02', '2025-08-26 07:29:02', 5, NULL), +(653, '2025-08-26', 7, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:02', '2025-08-26 07:29:02', 5, NULL), +(655, '2025-08-26', 5, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:02', '2025-08-26 07:29:02', 5, NULL), +(657, '2025-08-26', 1, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:03', '2025-08-26 07:29:03', 5, NULL), +(658, '2025-08-26', 6, 3, 3, 1, NULL, 10.00, '2025-08-26 08:22:12', '2025-08-26 08:22:12', 6, NULL), +(659, '2025-08-26', 10, 3, 3, 1, NULL, 10.00, '2025-08-26 08:22:12', '2025-08-26 08:22:12', 6, NULL), +(660, '2025-08-26', 3, 3, 3, 1, NULL, 10.00, '2025-08-26 08:22:12', '2025-08-26 08:22:12', 6, NULL), +(661, '2025-08-27', 10, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(662, '2025-08-27', 9, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(663, '2025-08-27', 7, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(664, '2025-08-27', 6, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(665, '2025-08-27', 5, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(666, '2025-08-27', 4, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(667, '2025-08-27', 3, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(668, '2025-08-27', 1, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:48', '2025-08-27 06:44:48', 3, NULL), +(669, '2025-08-27', 2, 3, 3, 2, 1, 2.00, '2025-08-27 06:45:32', '2025-08-27 06:45:32', 5, NULL), +(670, '2025-08-27', 2, 8, 2, 1, NULL, 6.00, '2025-08-27 06:45:32', '2025-08-27 06:45:32', 5, NULL), +(671, '2025-08-27', 8, 3, 3, 2, 1, 2.00, '2025-08-27 06:45:32', '2025-08-27 06:45:32', 5, NULL), +(672, '2025-08-27', 8, 8, 2, 1, NULL, 6.00, '2025-08-27 06:45:32', '2025-08-27 06:45:32', 5, NULL), +(673, '2025-08-28', 10, 3, 3, 1, NULL, 6.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(674, '2025-08-28', 10, 3, 3, 2, 1, 4.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(675, '2025-08-28', 5, 3, 3, 1, NULL, 6.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(676, '2025-08-28', 5, 3, 3, 2, 1, 4.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(677, '2025-08-28', 6, 3, 3, 1, NULL, 6.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(678, '2025-08-28', 6, 3, 3, 2, 1, 4.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(679, '2025-08-28', 3, 3, 3, 1, NULL, 6.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(680, '2025-08-28', 3, 3, 3, 2, 1, 4.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(681, '2025-08-28', 4, 3, 3, 1, NULL, 4.00, '2025-08-28 08:37:46', '2025-08-28 08:37:46', 5, NULL), +(682, '2025-08-28', 4, 5, 3, 1, NULL, 4.00, '2025-08-28 08:37:46', '2025-08-28 08:37:46', 5, NULL), +(683, '2025-08-28', 8, 8, 2, 1, NULL, 4.00, '2025-08-28 08:38:15', '2025-08-28 08:38:15', 5, NULL), +(684, '2025-08-28', 8, 5, 3, 1, NULL, 4.00, '2025-08-28 08:38:15', '2025-08-28 08:38:15', 5, NULL), +(685, '2025-08-28', 2, 3, 3, 2, 1, 2.00, '2025-08-28 08:38:50', '2025-08-28 08:38:50', 5, NULL), +(686, '2025-08-28', 2, 5, 3, 1, NULL, 6.00, '2025-08-28 08:38:50', '2025-08-28 08:38:50', 5, NULL), +(687, '2025-08-28', 1, 3, 3, 2, 1, 8.00, '2025-08-28 08:39:24', '2025-08-28 08:39:24', 5, NULL), +(689, '2025-08-28', 9, 3, 3, 2, 4, 8.00, '2025-08-28 08:40:00', '2025-08-28 08:40:00', 5, NULL), +(690, '2025-08-28', 7, 3, 3, 2, 4, 8.00, '2025-08-28 08:40:00', '2025-08-28 08:40:00', 5, NULL), +(694, '2025-08-28', 4, 5, 3, 1, NULL, 2.00, '2025-08-28 08:44:56', '2025-08-28 08:44:56', 5, NULL), +(695, '2025-08-28', 8, 5, 3, 1, NULL, 2.00, '2025-08-28 08:44:56', '2025-08-28 08:44:56', 5, NULL), +(696, '2025-08-28', 2, 5, 3, 1, NULL, 2.00, '2025-08-28 08:44:56', '2025-08-28 08:44:56', 5, NULL), +(698, '2025-08-28', 9, 3, 3, 1, NULL, 2.00, '2025-08-28 08:45:19', '2025-08-28 08:45:19', 5, NULL), +(699, '2025-08-28', 7, 3, 3, 1, NULL, 2.00, '2025-08-28 08:45:19', '2025-08-28 08:45:19', 5, NULL), +(703, '2025-08-29', 10, 3, 3, 2, 5, 8.00, '2025-08-29 06:47:02', '2025-08-29 06:47:02', 3, NULL), +(704, '2025-08-29', 9, 3, 3, 2, 5, 8.00, '2025-08-29 06:47:02', '2025-08-29 06:47:02', 3, NULL), +(706, '2025-08-29', 7, 3, 3, 2, 5, 8.00, '2025-08-29 06:47:02', '2025-08-29 06:47:02', 3, NULL), +(710, '2025-08-29', 1, 3, 3, 2, 5, 8.00, '2025-08-29 06:47:02', '2025-08-29 06:47:02', 3, NULL), +(713, '2025-08-29', 5, 3, 3, 1, NULL, 6.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(714, '2025-08-29', 5, 3, 3, 2, 1, 2.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(715, '2025-08-29', 3, 3, 3, 1, NULL, 6.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(716, '2025-08-29', 3, 3, 3, 2, 1, 2.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(717, '2025-08-29', 6, 3, 3, 1, NULL, 6.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(718, '2025-08-29', 6, 3, 3, 2, 1, 2.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(719, '2025-08-29', 8, 5, 3, 1, NULL, 8.00, '2025-08-29 21:55:56', '2025-08-29 21:55:56', 5, NULL), +(720, '2025-08-29', 4, 5, 3, 1, NULL, 8.00, '2025-08-29 21:55:56', '2025-08-29 21:55:56', 5, NULL), +(721, '2025-08-29', 2, 5, 3, 1, NULL, 8.00, '2025-08-29 21:55:56', '2025-08-29 21:55:56', 5, NULL), +(722, '2025-08-30', 2, 5, 3, 1, NULL, 8.00, '2025-08-30 05:12:03', '2025-08-30 05:12:03', 5, NULL), +(723, '2025-08-30', 8, 5, 3, 1, NULL, 8.00, '2025-08-30 05:12:03', '2025-08-30 05:12:03', 5, NULL), +(724, '2025-08-30', 4, 5, 3, 1, NULL, 8.00, '2025-08-30 05:12:03', '2025-08-30 05:12:03', 5, NULL), +(725, '2025-08-30', 10, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(726, '2025-08-30', 9, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(727, '2025-08-30', 7, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(728, '2025-08-30', 6, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(729, '2025-08-30', 5, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(730, '2025-08-30', 3, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(731, '2025-08-30', 1, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(732, '2025-09-01', 7, 3, 3, 1, NULL, 8.00, '2025-09-01 06:18:28', '2025-09-01 06:18:28', 3, NULL), +(733, '2025-09-01', 9, 3, 3, 1, NULL, 8.00, '2025-09-01 06:18:28', '2025-09-01 06:18:28', 3, NULL), +(734, '2025-09-01', 10, 3, 3, 2, 5, 4.00, '2025-09-01 06:19:11', '2025-09-01 06:19:11', 3, NULL), +(735, '2025-09-01', 3, 3, 3, 2, 5, 4.00, '2025-09-01 06:19:11', '2025-09-01 06:19:11', 3, NULL), +(736, '2025-09-01', 1, 3, 3, 2, 5, 4.00, '2025-09-01 06:19:11', '2025-09-01 06:19:11', 3, NULL), +(737, '2025-09-01', 10, 3, 3, 1, NULL, 4.00, '2025-09-01 06:19:35', '2025-09-01 06:19:35', 3, NULL), +(738, '2025-09-01', 3, 3, 3, 1, NULL, 4.00, '2025-09-01 06:19:35', '2025-09-01 06:19:35', 3, NULL), +(739, '2025-09-01', 1, 3, 3, 1, NULL, 4.00, '2025-09-01 06:19:35', '2025-09-01 06:19:35', 3, NULL), +(740, '2025-09-01', 5, 3, 3, 2, 1, 8.00, '2025-09-01 06:20:03', '2025-09-01 06:20:03', 3, NULL), +(741, '2025-08-21', 4, 3, 3, 1, NULL, 10.00, '2025-09-01 23:18:03', '2025-09-01 23:18:03', 3, NULL), +(742, '2025-08-21', 5, 3, 3, 1, NULL, 10.00, '2025-09-01 23:18:03', '2025-09-01 23:18:03', 3, NULL), +(745, '2025-09-02', 10, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(746, '2025-09-02', 9, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(747, '2025-09-02', 6, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(748, '2025-09-02', 5, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(749, '2025-09-02', 3, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(750, '2025-09-02', 1, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(751, '2025-09-02', 10, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(752, '2025-09-02', 9, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(753, '2025-09-02', 6, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(754, '2025-09-02', 5, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(755, '2025-09-02', 3, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(756, '2025-09-02', 1, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(757, '2025-09-02', 8, 3, 3, 1, NULL, 10.00, '2025-09-02 07:37:19', '2025-09-02 07:37:19', 3, NULL), +(758, '2025-09-02', 7, 3, 3, 1, NULL, 10.00, '2025-09-02 07:37:19', '2025-09-02 07:37:19', 3, NULL), +(759, '2025-09-02', 2, 5, 3, 1, NULL, 8.00, '2025-09-02 08:16:14', '2025-09-02 08:16:14', 5, NULL), +(760, '2025-09-02', 2, 5, 3, 1, NULL, 2.00, '2025-09-02 08:16:14', '2025-09-02 08:16:14', 5, NULL), +(761, '2025-09-02', 4, 5, 3, 1, NULL, 8.00, '2025-09-02 08:16:14', '2025-09-02 08:16:14', 5, NULL), +(762, '2025-09-02', 4, 5, 3, 1, NULL, 2.00, '2025-09-02 08:16:14', '2025-09-02 08:16:14', 5, NULL), +(763, '2025-09-03', 10, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:47', '2025-09-03 06:34:47', 3, NULL), +(764, '2025-09-03', 9, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:47', '2025-09-03 06:34:47', 3, NULL), +(765, '2025-09-03', 8, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(766, '2025-09-03', 7, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(767, '2025-09-03', 6, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(768, '2025-09-03', 5, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(769, '2025-09-03', 3, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(770, '2025-09-03', 1, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(771, '2025-09-03', 2, 5, 3, 1, NULL, 8.00, '2025-09-03 06:44:18', '2025-09-03 06:44:18', 5, NULL), +(772, '2025-09-04', 10, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:32', '2025-09-04 06:41:32', 6, NULL), +(773, '2025-09-04', 5, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:32', '2025-09-04 06:41:32', 6, NULL), +(774, '2025-09-04', 9, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:32', '2025-09-04 06:41:32', 6, NULL), +(775, '2025-09-04', 8, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:32', '2025-09-04 06:41:32', 6, NULL), +(776, '2025-09-04', 3, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:33', '2025-09-04 06:41:33', 6, NULL), +(777, '2025-09-04', 7, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:33', '2025-09-04 06:41:33', 6, NULL), +(778, '2025-09-04', 1, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:33', '2025-09-04 06:41:33', 6, NULL), +(779, '2025-09-04', 6, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:33', '2025-09-04 06:41:33', 6, NULL), +(780, '2025-09-04', 2, 5, 3, 1, NULL, 8.00, '2025-09-04 06:48:34', '2025-09-04 06:48:34', 5, NULL), +(781, '2025-09-04', 4, 5, 3, 1, NULL, 8.00, '2025-09-04 06:48:34', '2025-09-04 06:48:34', 5, NULL), +(782, '2025-09-05', 10, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:30', '2025-09-05 06:39:30', 3, NULL), +(783, '2025-09-05', 9, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:30', '2025-09-05 06:39:30', 3, NULL), +(784, '2025-09-05', 7, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:30', '2025-09-05 06:39:30', 3, NULL), +(785, '2025-09-05', 6, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:31', '2025-09-05 06:39:31', 3, NULL), +(786, '2025-09-05', 5, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:31', '2025-09-05 06:39:31', 3, NULL), +(787, '2025-09-05', 3, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:31', '2025-09-05 06:39:31', 3, NULL), +(788, '2025-09-05', 1, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:31', '2025-09-05 06:39:31', 3, NULL), +(789, '2025-09-05', 2, 5, 3, 1, NULL, 8.00, '2025-09-05 22:09:55', '2025-09-05 22:09:55', 5, NULL), +(790, '2025-09-05', 8, 5, 3, 1, NULL, 8.00, '2025-09-05 22:09:55', '2025-09-05 22:09:55', 5, NULL), +(791, '2025-09-05', 4, 5, 3, 1, NULL, 8.00, '2025-09-05 22:09:55', '2025-09-05 22:09:55', 5, NULL), +(792, '2025-09-06', 8, 10, 3, 1, NULL, 8.00, '2025-09-06 04:21:10', '2025-09-06 04:21:10', 5, NULL), +(793, '2025-09-06', 4, 10, 3, 1, NULL, 8.00, '2025-09-06 04:21:10', '2025-09-06 04:21:10', 5, NULL), +(794, '2025-09-06', 2, 10, 3, 1, NULL, 8.00, '2025-09-06 04:21:10', '2025-09-06 04:21:10', 5, NULL), +(795, '2025-09-06', 10, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:18', '2025-09-06 05:28:18', 3, NULL), +(796, '2025-09-06', 9, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:18', '2025-09-06 05:28:18', 3, NULL), +(797, '2025-09-06', 7, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:18', '2025-09-06 05:28:18', 3, NULL), +(798, '2025-09-06', 6, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:19', '2025-09-06 05:28:19', 3, NULL), +(799, '2025-09-06', 5, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:19', '2025-09-06 05:28:19', 3, NULL), +(800, '2025-09-06', 3, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:19', '2025-09-06 05:28:19', 3, NULL), +(801, '2025-09-06', 1, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:19', '2025-09-06 05:28:19', 3, NULL), +(802, '2025-09-08', 10, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(803, '2025-09-08', 9, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(804, '2025-09-08', 7, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(805, '2025-09-08', 6, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(806, '2025-09-08', 5, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(807, '2025-09-08', 3, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(808, '2025-09-08', 1, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(809, '2025-09-08', 8, 5, 3, 1, NULL, 8.00, '2025-09-08 06:47:37', '2025-09-08 06:47:37', 5, NULL), +(810, '2025-09-08', 4, 5, 3, 1, NULL, 8.00, '2025-09-08 06:47:37', '2025-09-08 06:47:37', 5, NULL), +(811, '2025-09-08', 2, 5, 3, 1, NULL, 8.00, '2025-09-08 06:47:37', '2025-09-08 06:47:37', 5, NULL), +(812, '2025-09-09', 10, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(813, '2025-09-09', 9, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(814, '2025-09-09', 7, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(815, '2025-09-09', 6, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(816, '2025-09-09', 5, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(817, '2025-09-09', 3, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(818, '2025-09-09', 1, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(819, '2025-09-09', 8, 5, 3, 1, NULL, 8.00, '2025-09-09 06:44:29', '2025-09-09 06:44:29', 5, NULL), +(820, '2025-09-09', 4, 5, 3, 1, NULL, 8.00, '2025-09-09 06:44:29', '2025-09-09 06:44:29', 5, NULL), +(821, '2025-09-09', 2, 5, 3, 1, NULL, 8.00, '2025-09-09 06:44:29', '2025-09-09 06:44:29', 5, NULL), +(822, '2025-09-10', 10, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(823, '2025-09-10', 9, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(824, '2025-09-10', 7, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(825, '2025-09-10', 6, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(826, '2025-09-10', 5, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(827, '2025-09-10', 3, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(828, '2025-09-10', 1, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(829, '2025-09-10', 8, 5, 3, 1, NULL, 8.00, '2025-09-10 06:48:43', '2025-09-10 06:48:43', 5, NULL), +(830, '2025-09-10', 4, 5, 3, 1, NULL, 8.00, '2025-09-10 06:48:43', '2025-09-10 06:48:43', 5, NULL), +(831, '2025-09-10', 2, 5, 3, 1, NULL, 8.00, '2025-09-10 06:48:43', '2025-09-10 06:48:43', 5, NULL), +(832, '2025-09-11', 2, 5, 3, 1, NULL, 2.00, '2025-09-11 06:37:11', '2025-09-11 06:37:11', 5, NULL), +(833, '2025-09-11', 2, 8, 3, 1, NULL, 6.00, '2025-09-11 06:37:11', '2025-09-11 06:37:11', 5, NULL), +(834, '2025-09-11', 4, 5, 3, 1, NULL, 2.00, '2025-09-11 06:38:24', '2025-09-11 06:38:24', 5, NULL), +(835, '2025-09-11', 4, 8, 3, 1, NULL, 2.00, '2025-09-11 06:38:24', '2025-09-11 06:38:24', 5, NULL), +(836, '2025-09-11', 4, 3, 3, 1, NULL, 4.00, '2025-09-11 06:38:24', '2025-09-11 06:38:24', 5, NULL), +(838, '2025-09-11', 1, 3, 1, 1, NULL, 4.00, '2025-09-11 06:40:48', '2025-09-11 06:40:48', 5, NULL), +(840, '2025-09-11', 5, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(841, '2025-09-11', 8, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(842, '2025-09-11', 3, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(843, '2025-09-11', 7, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(844, '2025-09-11', 6, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(845, '2025-09-11', 10, 3, 2, 1, NULL, 4.00, '2025-09-11 06:41:51', '2025-09-11 06:41:51', 5, NULL), +(846, '2025-09-11', 10, 3, 3, 1, NULL, 4.00, '2025-09-11 06:41:51', '2025-09-11 06:41:51', 5, NULL), +(847, '2025-09-11', 9, 3, 2, 1, NULL, 4.00, '2025-09-11 06:41:51', '2025-09-11 06:41:51', 5, NULL), +(848, '2025-09-11', 9, 3, 3, 1, NULL, 4.00, '2025-09-11 06:41:51', '2025-09-11 06:41:51', 5, NULL), +(851, '2025-09-12', 10, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(852, '2025-09-12', 9, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(853, '2025-09-12', 8, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(854, '2025-09-12', 6, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(855, '2025-09-12', 5, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(856, '2025-09-12', 4, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(857, '2025-09-12', 3, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(858, '2025-09-12', 2, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(859, '2025-09-12', 1, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(860, '2025-09-12', 7, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(861, '2025-09-13', 10, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(862, '2025-09-13', 8, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(863, '2025-09-13', 7, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(864, '2025-09-13', 6, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(865, '2025-09-13', 5, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(866, '2025-09-13', 4, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(867, '2025-09-13', 3, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(868, '2025-09-13', 2, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(869, '2025-09-13', 1, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(870, '2025-09-14', 9, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:40', '2025-09-14 04:47:40', 3, NULL), +(871, '2025-09-14', 8, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:40', '2025-09-14 04:47:40', 3, NULL), +(872, '2025-09-14', 7, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:40', '2025-09-14 04:47:40', 3, NULL), +(873, '2025-09-14', 6, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:40', '2025-09-14 04:47:40', 3, NULL), +(874, '2025-09-14', 5, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(875, '2025-09-14', 4, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(876, '2025-09-14', 3, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(877, '2025-09-14', 2, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(878, '2025-09-14', 1, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(879, '2025-09-15', 5, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:00', '2025-09-15 06:50:00', 3, NULL), +(880, '2025-09-15', 10, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:00', '2025-09-15 06:50:00', 3, NULL), +(881, '2025-09-15', 9, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:00', '2025-09-15 06:50:00', 3, NULL), +(882, '2025-09-15', 8, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:00', '2025-09-15 06:50:00', 3, NULL), +(883, '2025-09-15', 7, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(884, '2025-09-15', 6, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(885, '2025-09-15', 4, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(886, '2025-09-15', 3, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(887, '2025-09-15', 2, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(888, '2025-09-15', 1, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(889, '2025-09-16', 2, 8, 3, 1, NULL, 8.00, '2025-09-16 06:51:19', '2025-09-16 06:51:19', 5, NULL), +(890, '2025-09-16', 4, 8, 3, 1, NULL, 8.00, '2025-09-16 06:51:19', '2025-09-16 06:51:19', 5, NULL), +(891, '2025-09-16', 8, 8, 2, 1, NULL, 2.00, '2025-09-16 06:52:12', '2025-09-16 06:52:12', 5, NULL), +(892, '2025-09-16', 8, 3, 2, 1, NULL, 6.00, '2025-09-16 06:52:12', '2025-09-16 06:52:12', 5, NULL), +(893, '2025-09-17', 4, 8, 3, 1, NULL, 8.00, '2025-09-17 06:43:08', '2025-09-17 06:43:08', 5, NULL), +(894, '2025-09-17', 2, 8, 3, 1, NULL, 8.00, '2025-09-17 06:43:08', '2025-09-17 06:43:08', 5, NULL), +(895, '2025-09-17', 10, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(896, '2025-09-17', 9, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(897, '2025-09-17', 8, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(898, '2025-09-17', 7, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(899, '2025-09-17', 6, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(900, '2025-09-17', 5, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(901, '2025-09-17', 3, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(902, '2025-09-17', 1, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(903, '2025-09-18', 7, 3, 3, 1, NULL, 8.00, '2025-09-18 06:43:40', '2025-09-18 06:43:40', 3, NULL), +(904, '2025-09-18', 1, 3, 3, 1, NULL, 8.00, '2025-09-18 06:43:40', '2025-09-18 06:43:40', 3, NULL), +(905, '2025-09-18', 10, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(906, '2025-09-18', 9, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(907, '2025-09-18', 8, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(908, '2025-09-18', 6, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(909, '2025-09-18', 3, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(910, '2025-09-18', 5, 3, 2, 1, NULL, 6.00, '2025-09-18 06:46:39', '2025-09-18 06:46:39', 3, NULL), +(911, '2025-09-18', 2, 8, 3, 1, NULL, 8.00, '2025-09-18 06:54:48', '2025-09-18 06:54:48', 5, NULL), +(912, '2025-09-18', 4, 8, 3, 1, NULL, 8.00, '2025-09-18 06:54:48', '2025-09-18 06:54:48', 5, NULL), +(913, '2025-09-19', 4, 8, 3, 1, NULL, 8.00, '2025-09-19 06:51:40', '2025-09-19 06:51:40', 5, NULL), +(914, '2025-09-19', 2, 8, 3, 1, NULL, 8.00, '2025-09-19 06:51:40', '2025-09-19 06:51:40', 5, NULL), +(915, '2025-09-19', 10, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(916, '2025-09-19', 8, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(917, '2025-09-19', 7, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(918, '2025-09-19', 6, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(919, '2025-09-19', 5, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(920, '2025-09-19', 3, 3, 2, 1, NULL, 4.00, '2025-09-19 06:52:23', '2025-09-19 06:52:23', 5, NULL), +(921, '2025-09-20', 4, 8, 3, 1, NULL, 8.00, '2025-09-20 05:30:19', '2025-09-20 05:30:19', 5, NULL), +(922, '2025-09-20', 2, 8, 3, 1, NULL, 8.00, '2025-09-20 05:30:19', '2025-09-20 05:30:19', 5, NULL), +(923, '2025-09-22', 10, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(924, '2025-09-22', 9, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(925, '2025-09-22', 8, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(926, '2025-09-22', 7, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(927, '2025-09-22', 5, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(928, '2025-09-22', 1, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(929, '2025-09-22', 4, 8, 3, 1, NULL, 8.00, '2025-09-22 06:50:29', '2025-09-22 06:50:29', 5, NULL), +(930, '2025-09-22', 2, 8, 3, 1, NULL, 8.00, '2025-09-22 06:50:29', '2025-09-22 06:50:29', 5, NULL), +(931, '2025-09-23', 4, 8, 3, 1, NULL, 8.00, '2025-09-23 05:46:40', '2025-09-23 05:46:40', 5, NULL), +(932, '2025-09-23', 2, 8, 3, 1, NULL, 8.00, '2025-09-23 05:46:40', '2025-09-23 05:46:40', 5, NULL), +(933, '2025-09-24', 4, 8, 3, 1, NULL, 8.00, '2025-09-25 01:14:58', '2025-09-25 01:14:58', 5, NULL), +(934, '2025-09-24', 2, 8, 3, 1, NULL, 8.00, '2025-09-25 01:14:58', '2025-09-25 01:14:58', 5, NULL), +(935, '2025-09-29', 7, 14, 1, 1, NULL, 8.00, '2025-09-29 06:36:07', '2025-09-29 06:36:07', 3, NULL), +(936, '2025-09-29', 1, 14, 1, 1, NULL, 8.00, '2025-09-29 06:36:07', '2025-09-29 06:36:07', 3, NULL), +(937, '2025-09-29', 10, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(938, '2025-09-29', 8, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(939, '2025-09-29', 6, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(940, '2025-09-29', 9, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(941, '2025-09-29', 5, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(942, '2025-09-29', 4, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(943, '2025-09-29', 3, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(944, '2025-09-29', 2, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(945, '2025-09-30', 10, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(946, '2025-09-30', 9, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(947, '2025-09-30', 8, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(948, '2025-09-30', 6, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(949, '2025-09-30', 5, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(950, '2025-09-30', 4, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(951, '2025-09-30', 3, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:27', '2025-09-30 06:52:27', 3, NULL), +(953, '2025-09-30', 1, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:27', '2025-09-30 06:52:27', 3, NULL), +(954, '2025-09-30', 2, 8, 3, 1, NULL, 8.00, '2025-09-30 06:56:55', '2025-09-30 06:56:55', 5, NULL), +(955, '2025-10-02', 5, 3, 2, 1, NULL, 6.00, '2025-10-02 05:25:58', '2025-10-02 05:25:58', 3, NULL), +(956, '2025-10-02', 8, 3, 2, 1, NULL, 6.00, '2025-10-02 05:25:59', '2025-10-02 05:25:59', 3, NULL), +(957, '2025-10-02', 10, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:32', '2025-10-02 06:22:32', 3, NULL), +(958, '2025-10-02', 9, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:32', '2025-10-02 06:22:32', 3, NULL), +(959, '2025-10-02', 7, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:32', '2025-10-02 06:22:32', 3, NULL), +(960, '2025-10-02', 6, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:32', '2025-10-02 06:22:32', 3, NULL), +(961, '2025-10-02', 4, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:33', '2025-10-02 06:22:33', 3, NULL), +(962, '2025-10-02', 2, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:33', '2025-10-02 06:22:33', 3, NULL), +(963, '2025-10-02', 1, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:33', '2025-10-02 06:22:33', 3, NULL), +(964, '2025-09-01', 8, 5, 3, 1, NULL, 8.00, '2025-10-10 23:35:07', '2025-10-10 23:35:07', 3, NULL), +(965, '2025-09-01', 4, 5, 3, 1, NULL, 8.00, '2025-10-10 23:35:07', '2025-10-10 23:35:07', 3, NULL), +(966, '2025-09-01', 2, 5, 3, 1, NULL, 8.00, '2025-10-10 23:35:07', '2025-10-10 23:35:07', 3, NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `EquipmentList` +-- + +CREATE TABLE `EquipmentList` ( + `equipment_id` int(11) NOT NULL, + `factory_id` int(11) DEFAULT NULL, + `equipment_name` varchar(255) NOT NULL, + `model` varchar(100) DEFAULT NULL, + `status` text DEFAULT 'operational', + `purchase_date` date DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `error_types` +-- + +CREATE TABLE `error_types` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL COMMENT '에러 유형명', + `description` text DEFAULT NULL COMMENT '에러 설명', + `severity` enum('low','medium','high','critical') DEFAULT 'medium' COMMENT '심각도', + `solution_guide` text DEFAULT NULL COMMENT '해결 가이드', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `error_types` +-- + +INSERT INTO `error_types` (`id`, `name`, `description`, `severity`, `solution_guide`, `created_at`, `updated_at`) VALUES +(1, '설계미스', '설계미스', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:03'), +(2, '외주작업 불량', '입고 자재 불량', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:05'), +(3, '입고지연', '자재 미입고', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:11'), +(4, '작업불량', '작업자 실수', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:13'), +(5, '설비고장', '장비없음', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:16'), +(6, '검사불량', '검사불량', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-24 04:36:18'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `FactoryInfo` +-- + +CREATE TABLE `FactoryInfo` ( + `factory_id` int(11) NOT NULL, + `factory_name` varchar(255) NOT NULL, + `address` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `map_image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `FactoryInfo` +-- + +INSERT INTO `FactoryInfo` (`factory_id`, `factory_name`, `address`, `description`, `map_image_url`, `created_at`, `updated_at`) VALUES +(3, '제1공장 휴게공간 및 작업자 사물함', '현대기아로 771-9', '개인 보관함, 컨테이너(휴게공간), 화장실, 흡연장', '/uploads/map_image-1746593523450.png', '2025-05-07 04:52:03', '2025-05-07 04:52:03'), +(4, '제 1공장 공구 및 용접봉 보관 구역', '현대기아로 771-9', '소모품, 공구류, 용접봉 보관 구역', '/uploads/map_image-1746593674259.png', '2025-05-07 04:53:59', '2025-05-07 04:53:59'), +(5, 'ee', 'ee', 'ee', NULL, '2025-06-03 22:13:23', '2025-06-03 22:13:23'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `IssueTypes` +-- + +CREATE TABLE `IssueTypes` ( + `issue_type_id` int(11) NOT NULL, + `category` varchar(100) NOT NULL, + `subcategory` varchar(100) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `IssueTypes` +-- + +INSERT INTO `IssueTypes` (`issue_type_id`, `category`, `subcategory`) VALUES +(1, '구매팀', '자재입고지연'), +(2, '구매팀', '자재전달 미흡'), +(3, '품질', '검사 내용 전달 미흡'), +(4, '품질', '검사오류'), +(5, '설계', '설계미스(치수)'), +(6, '설계', '설계미스(작업불가)'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `login_logs` +-- + +CREATE TABLE `login_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `login_time` datetime DEFAULT current_timestamp(), + `logout_time` datetime DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `login_status` enum('success','failed','locked') DEFAULT 'success', + `failure_reason` varchar(100) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `login_logs` +-- + +INSERT INTO `login_logs` (`log_id`, `user_id`, `login_time`, `logout_time`, `ip_address`, `user_agent`, `login_status`, `failure_reason`) VALUES +(1, 3, '2025-06-15 05:58:39', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(3, 4, '2025-06-15 06:04:06', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(4, 3, '2025-06-15 06:24:53', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(5, 3, '2025-06-15 06:24:55', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(6, 3, '2025-06-15 06:32:41', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(7, 3, '2025-06-15 07:03:19', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(8, 3, '2025-06-15 07:03:21', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(9, 3, '2025-06-15 07:03:25', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(10, 1, '2025-06-15 07:40:16', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(11, 6, '2025-06-15 07:42:02', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(12, 3, '2025-06-15 07:43:30', NULL, '118.235.6.135', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(13, 3, '2025-06-15 22:02:59', NULL, '118.235.6.29', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(14, 4, '2025-06-15 22:15:25', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(15, 3, '2025-06-15 22:15:34', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(16, 6, '2025-06-15 22:15:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'failed', 'invalid_password'), +(17, 6, '2025-06-15 22:15:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(18, 3, '2025-06-15 22:16:39', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(19, 3, '2025-06-15 22:17:14', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(20, 6, '2025-06-15 22:21:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(21, 1, '2025-06-15 22:21:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(22, 6, '2025-06-15 22:22:06', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(23, 5, '2025-06-15 22:22:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(24, 6, '2025-06-15 22:23:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(25, 3, '2025-06-15 22:24:49', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(26, 3, '2025-06-15 22:30:18', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(27, 3, '2025-06-15 22:31:21', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(28, 5, '2025-06-15 22:44:31', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(29, 4, '2025-06-15 22:57:51', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(30, 4, '2025-06-15 22:57:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(31, 4, '2025-06-15 22:57:54', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(32, 4, '2025-06-15 22:57:55', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(33, 4, '2025-06-15 23:11:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(34, 4, '2025-06-15 23:28:04', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(35, 3, '2025-06-15 23:33:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(36, 3, '2025-06-16 00:58:53', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(37, 3, '2025-06-16 01:15:46', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(38, 5, '2025-06-16 01:16:43', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(39, 1, '2025-06-16 01:25:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(40, 1, '2025-06-16 01:26:08', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(41, 3, '2025-06-16 02:27:20', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(42, 3, '2025-06-16 02:45:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(43, 3, '2025-06-16 03:04:13', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(44, 3, '2025-06-16 03:17:28', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(45, 5, '2025-06-16 03:17:55', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(46, 3, '2025-06-16 03:18:56', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(47, 5, '2025-06-16 03:19:13', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(48, 1, '2025-06-16 03:55:56', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(49, 1, '2025-06-16 04:24:37', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(50, 1, '2025-06-16 04:51:36', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(51, 1, '2025-06-16 05:07:05', NULL, '118.235.7.233', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(52, 1, '2025-06-16 05:07:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(53, 1, '2025-06-16 05:43:14', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(54, 5, '2025-06-16 06:11:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(55, 1, '2025-06-16 06:19:46', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(56, 1, '2025-06-16 06:23:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(57, 1, '2025-06-16 06:39:12', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(58, 3, '2025-06-16 06:45:26', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(59, 6, '2025-06-16 06:46:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(60, 1, '2025-06-16 21:18:09', NULL, '118.235.7.45', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(61, 1, '2025-06-17 08:15:45', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(62, 5, '2025-06-17 08:22:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(63, 3, '2025-06-17 08:23:05', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'failed', 'invalid_password'), +(64, 3, '2025-06-17 08:23:21', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(65, 3, '2025-06-17 08:28:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(66, 3, '2025-06-17 08:32:25', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(67, 6, '2025-06-17 08:33:07', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(68, 1, '2025-06-17 08:36:01', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(69, 5, '2025-06-17 09:00:56', NULL, '118.235.7.173', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(70, 3, '2025-06-18 02:30:13', NULL, '118.235.6.77', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(71, 1, '2025-06-18 08:07:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(72, 1, '2025-06-18 08:07:47', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(73, 5, '2025-06-18 08:39:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(74, 6, '2025-06-18 08:46:53', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(75, 3, '2025-06-18 08:47:03', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(76, 6, '2025-06-18 08:57:48', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(77, 5, '2025-06-18 08:58:14', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(78, 3, '2025-06-18 08:59:12', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(79, 5, '2025-06-19 06:37:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(80, 3, '2025-06-19 06:57:01', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(81, 6, '2025-06-19 06:57:22', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(82, 5, '2025-06-19 06:57:56', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(83, 6, '2025-06-19 06:58:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(84, 3, '2025-06-19 06:59:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(85, 3, '2025-06-20 06:42:26', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(86, 6, '2025-06-20 06:45:06', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(87, 5, '2025-06-20 06:49:26', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(88, 3, '2025-06-20 06:49:47', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(89, 6, '2025-06-20 06:50:17', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(90, 3, '2025-06-20 22:46:20', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(91, 1, '2025-06-23 05:03:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(92, 6, '2025-06-23 06:41:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(93, 3, '2025-06-23 06:49:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(94, 6, '2025-06-23 06:50:01', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(95, 5, '2025-06-23 06:50:28', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(96, 1, '2025-06-24 05:24:17', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(97, 3, '2025-06-24 05:25:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(98, 1, '2025-06-24 09:22:29', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(99, 3, '2025-06-24 11:09:38', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(100, 6, '2025-06-24 11:09:48', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(101, 5, '2025-06-24 11:10:23', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(102, 3, '2025-06-24 11:11:29', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(103, 5, '2025-06-24 11:12:06', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(104, 6, '2025-06-24 11:12:31', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(105, 3, '2025-06-24 21:41:01', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(106, 3, '2025-06-25 04:40:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(107, 3, '2025-06-25 05:24:57', NULL, '118.235.6.179', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(108, 1, '2025-06-25 07:05:20', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(109, 1, '2025-06-25 07:06:41', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(110, 3, '2025-06-25 07:09:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(111, 3, '2025-06-25 08:49:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(112, 3, '2025-06-25 09:20:05', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(113, 3, '2025-06-25 09:40:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(114, 3, '2025-06-25 09:57:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(115, 1, '2025-06-25 10:11:03', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(116, 1, '2025-06-25 10:26:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(117, 1, '2025-06-25 10:49:29', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(118, 5, '2025-06-25 11:07:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(119, 6, '2025-06-25 11:10:41', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(120, 6, '2025-06-25 11:13:55', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(121, 5, '2025-06-25 11:14:25', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(122, 6, '2025-06-25 11:20:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(123, 1, '2025-06-25 11:24:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(124, 3, '2025-06-26 10:27:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(125, 5, '2025-06-26 11:10:47', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(126, 6, '2025-06-26 11:15:57', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(127, 3, '2025-06-26 11:17:07', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(128, 5, '2025-06-26 11:17:40', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(129, 6, '2025-06-26 11:19:00', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(130, 1, '2025-06-26 22:15:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(131, 1, '2025-06-26 22:31:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(132, 1, '2025-06-26 22:47:22', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(133, 5, '2025-06-27 01:52:48', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(134, 5, '2025-06-27 01:53:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(135, 3, '2025-06-27 06:47:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(136, 6, '2025-06-27 06:48:39', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(137, 3, '2025-06-27 06:57:15', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(138, 5, '2025-06-27 06:57:34', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(139, 6, '2025-06-27 06:57:59', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(140, 3, '2025-06-27 06:59:04', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(141, 5, '2025-06-27 06:59:29', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(142, 3, '2025-07-05 01:25:41', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(143, 3, '2025-07-05 01:26:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(144, 3, '2025-07-05 01:41:35', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(145, 3, '2025-07-05 01:46:29', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(146, 3, '2025-07-05 01:46:57', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(147, 3, '2025-07-05 01:47:17', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(148, 5, '2025-07-05 01:48:23', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(149, 3, '2025-07-05 01:49:42', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(150, 3, '2025-07-05 01:50:41', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(151, 1, '2025-07-05 01:52:14', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(152, 3, '2025-07-05 02:12:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(153, 3, '2025-07-05 04:48:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(154, 5, '2025-07-05 05:36:08', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(155, 3, '2025-07-05 05:52:08', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(156, 5, '2025-07-06 05:33:53', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(157, 3, '2025-07-06 05:45:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(158, 1, '2025-07-07 01:40:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(159, 1, '2025-07-07 01:40:39', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(160, 3, '2025-07-07 01:54:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(161, 3, '2025-07-07 02:13:32', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(162, 1, '2025-07-07 02:28:26', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(163, 3, '2025-07-07 02:45:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(164, 1, '2025-07-07 03:33:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(165, 1, '2025-07-07 03:51:07', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(166, 1, '2025-07-07 03:56:23', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(167, 1, '2025-07-07 03:57:20', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(168, 1, '2025-07-07 03:58:02', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(169, 1, '2025-07-07 03:58:37', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(170, 3, '2025-07-07 04:00:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(171, 1, '2025-07-07 04:03:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(172, 1, '2025-07-07 04:10:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(173, 3, '2025-07-07 04:13:46', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(174, 1, '2025-07-07 04:23:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(175, 3, '2025-07-07 04:25:09', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(176, 6, '2025-07-07 06:48:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(177, 3, '2025-07-07 06:51:59', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(178, 1, '2025-07-07 23:33:26', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(179, 1, '2025-07-07 23:37:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(180, 3, '2025-07-08 06:36:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(181, 3, '2025-07-08 06:59:17', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(182, 3, '2025-07-09 06:59:29', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(183, 5, '2025-07-09 22:07:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(184, 3, '2025-07-10 02:09:48', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(185, 1, '2025-07-10 02:11:20', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(186, 3, '2025-07-10 06:28:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(187, 3, '2025-07-10 06:57:12', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(188, 3, '2025-07-11 06:59:42', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(189, 3, '2025-07-12 05:39:34', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(190, 3, '2025-07-12 05:41:00', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(191, 3, '2025-07-12 05:58:31', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(192, 3, '2025-07-14 06:45:52', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(193, 3, '2025-07-15 00:09:52', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(194, 5, '2025-07-15 05:56:33', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(195, 3, '2025-07-15 06:56:35', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(196, 5, '2025-07-16 06:45:52', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(197, 3, '2025-07-16 06:51:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(198, 3, '2025-07-17 06:44:45', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(199, 5, '2025-07-17 06:45:54', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(200, 3, '2025-07-17 06:58:06', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(201, 3, '2025-07-18 05:54:03', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(202, 5, '2025-07-18 06:35:45', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(203, 5, '2025-07-21 06:39:22', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(204, 3, '2025-07-21 06:53:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(205, 5, '2025-07-22 06:45:21', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(206, 3, '2025-07-22 06:45:41', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(207, 3, '2025-07-22 06:46:38', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(208, 3, '2025-07-22 06:57:45', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(209, 5, '2025-07-23 06:44:46', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(210, 3, '2025-07-23 06:44:59', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(211, 3, '2025-07-23 06:59:50', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(212, 5, '2025-07-24 06:36:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(213, 3, '2025-07-24 06:46:42', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(214, 5, '2025-07-25 06:44:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(215, 3, '2025-07-25 06:44:45', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(216, 5, '2025-07-27 21:28:11', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(217, 3, '2025-07-28 06:30:12', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(218, 3, '2025-07-28 06:31:32', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(219, 5, '2025-07-28 06:32:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(220, 3, '2025-07-28 06:54:43', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(221, 3, '2025-07-29 06:38:49', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(222, 1, '2025-07-30 01:57:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(223, 1, '2025-07-30 02:03:46', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(224, 3, '2025-07-30 02:04:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(225, 1, '2025-07-30 02:20:29', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(226, 1, '2025-07-30 02:24:55', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(227, 3, '2025-07-30 05:01:07', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(228, 3, '2025-07-30 06:50:12', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(229, 5, '2025-07-30 06:51:38', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(230, 1, '2025-07-30 22:38:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(231, 5, '2025-07-31 06:42:33', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(232, 3, '2025-07-31 22:23:54', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(233, 5, '2025-08-01 04:56:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(234, 5, '2025-08-01 04:57:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(235, 3, '2025-08-01 05:01:42', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(236, 5, '2025-08-07 06:41:51', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(237, 3, '2025-08-07 06:43:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(238, 3, '2025-08-08 06:44:56', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(239, 3, '2025-08-08 06:55:18', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(240, 5, '2025-08-08 06:58:09', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(241, 3, '2025-08-11 02:06:53', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(242, 1, '2025-08-11 04:16:44', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'failed', 'invalid_password'), +(243, 1, '2025-08-11 04:17:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(244, 3, '2025-08-11 06:27:03', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(245, 5, '2025-08-11 06:45:58', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(246, 3, '2025-08-12 06:46:57', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(247, 6, '2025-08-13 05:14:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(248, 3, '2025-08-13 06:30:59', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(249, 5, '2025-08-13 06:35:40', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(250, 5, '2025-08-14 02:02:04', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(251, 3, '2025-08-14 06:34:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(252, 5, '2025-08-14 06:38:26', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(253, 5, '2025-08-18 06:21:07', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL); +INSERT INTO `login_logs` (`log_id`, `user_id`, `login_time`, `logout_time`, `ip_address`, `user_agent`, `login_status`, `failure_reason`) VALUES +(254, 3, '2025-08-18 06:40:43', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(255, 6, '2025-08-18 06:42:10', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(256, 3, '2025-08-18 06:47:57', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(257, 5, '2025-08-19 08:02:10', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(258, 6, '2025-08-19 08:35:46', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(259, 5, '2025-08-20 06:19:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(260, 3, '2025-08-20 06:42:31', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(261, 6, '2025-08-20 06:43:54', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(262, 3, '2025-08-21 06:29:56', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(263, 5, '2025-08-21 07:50:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(264, 6, '2025-08-21 08:23:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(265, 5, '2025-08-22 06:20:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(266, 5, '2025-08-22 06:22:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(267, 3, '2025-08-22 06:27:17', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(268, 5, '2025-08-23 04:56:25', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(269, 3, '2025-08-25 06:48:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(270, 6, '2025-08-25 06:48:48', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(271, 5, '2025-08-26 07:07:36', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(272, 1, '2025-08-26 07:11:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(273, 5, '2025-08-26 07:27:16', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(274, 6, '2025-08-26 08:21:22', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(275, 3, '2025-08-27 00:51:26', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(276, 3, '2025-08-27 06:43:38', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(277, 5, '2025-08-27 06:44:44', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(278, 1, '2025-08-28 01:48:08', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(279, 3, '2025-08-28 01:49:21', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(280, 3, '2025-08-28 03:28:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(281, 6, '2025-08-28 08:29:27', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(282, 5, '2025-08-28 08:37:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(283, 5, '2025-08-28 08:44:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(284, 3, '2025-08-29 06:45:33', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(285, 6, '2025-08-29 06:46:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(286, 5, '2025-08-29 21:54:56', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(287, 3, '2025-08-30 02:57:31', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(288, 5, '2025-08-30 05:11:35', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(289, 3, '2025-08-30 05:35:51', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(290, 3, '2025-09-01 06:17:50', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(291, 3, '2025-09-01 23:13:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(292, 3, '2025-09-02 03:59:38', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(293, 3, '2025-09-02 07:33:36', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(294, 5, '2025-09-02 08:15:36', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(295, 3, '2025-09-02 23:36:25', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(296, 3, '2025-09-03 01:32:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(297, 3, '2025-09-03 06:32:44', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(298, 5, '2025-09-03 06:43:58', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(299, 6, '2025-09-04 06:40:35', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(300, 5, '2025-09-04 06:48:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(301, 3, '2025-09-05 06:39:03', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(302, 5, '2025-09-05 22:09:08', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(303, 5, '2025-09-06 04:20:51', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(304, 3, '2025-09-06 05:27:55', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(305, 3, '2025-09-08 06:15:03', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(306, 5, '2025-09-08 06:47:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(307, 3, '2025-09-09 06:02:53', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(308, 5, '2025-09-09 06:44:09', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(309, 3, '2025-09-10 06:27:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(310, 5, '2025-09-10 06:48:23', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(311, 5, '2025-09-11 06:36:20', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(312, 6, '2025-09-11 06:40:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(313, 3, '2025-09-12 06:43:55', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(314, 3, '2025-09-13 06:37:35', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(315, 5, '2025-09-13 23:16:18', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(316, 3, '2025-09-14 04:47:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(317, 3, '2025-09-15 06:49:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(318, 5, '2025-09-16 06:50:55', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(319, 5, '2025-09-17 06:42:49', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(320, 3, '2025-09-17 06:44:41', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(321, 1, '2025-09-17 23:51:39', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(322, 3, '2025-09-18 06:43:14', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(323, 3, '2025-09-18 06:46:17', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(324, 5, '2025-09-18 06:54:31', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(325, 5, '2025-09-19 06:51:14', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(326, 5, '2025-09-20 05:30:00', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(327, 3, '2025-09-22 06:46:29', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(328, 5, '2025-09-22 06:50:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(329, 5, '2025-09-23 05:46:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(330, 3, '2025-09-23 06:46:57', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(331, 3, '2025-09-23 06:47:27', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(332, 5, '2025-09-25 01:14:07', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(333, 3, '2025-09-25 06:56:18', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1', 'success', NULL), +(334, 1, '2025-09-28 22:11:51', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(335, 3, '2025-09-29 06:35:29', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(336, 3, '2025-09-30 06:52:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(337, 5, '2025-09-30 06:56:12', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(338, 5, '2025-10-01 06:55:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(339, 1, '2025-10-01 23:48:39', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(340, 3, '2025-10-02 05:25:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(341, 3, '2025-10-02 06:21:56', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(342, 1, '2025-10-06 01:01:56', NULL, '::ffff:172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(343, 1, '2025-10-10 23:13:57', NULL, '::ffff:172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(344, 3, '2025-10-10 23:32:38', NULL, '::ffff:172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `password_change_logs` +-- + +CREATE TABLE `password_change_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) NOT NULL, + `changed_by_user_id` int(11) DEFAULT NULL, + `changed_at` datetime DEFAULT current_timestamp(), + `change_type` enum('self','admin','reset','initial') DEFAULT 'self', + `ip_address` varchar(45) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `password_change_logs` +-- + +INSERT INTO `password_change_logs` (`log_id`, `user_id`, `changed_by_user_id`, `changed_at`, `change_type`, `ip_address`) VALUES +(1, 4, NULL, '2025-06-15 06:03:42', 'admin', NULL), +(2, 3, NULL, '2025-06-15 06:03:52', 'admin', NULL), +(3, 3, 3, '2025-06-15 06:32:30', 'self', NULL), +(4, 3, 1, '2025-06-15 07:40:39', 'admin', NULL), +(5, 5, 1, '2025-06-15 07:41:02', 'initial', NULL), +(6, 6, 1, '2025-06-15 07:41:32', 'initial', NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `PipeSpecs` +-- + +CREATE TABLE `PipeSpecs` ( + `spec_id` int(11) NOT NULL, + `material` varchar(50) NOT NULL COMMENT '재질 (예: SS400, STS304)', + `diameter_in` varchar(10) NOT NULL COMMENT '직경 (inch, 예: 2")', + `schedule` varchar(50) NOT NULL COMMENT '스케줄 (예: STD, SCH10, SCH40)' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `PipeSpecs` +-- + +INSERT INTO `PipeSpecs` (`spec_id`, `material`, `diameter_in`, `schedule`) VALUES +(2, '516-70N', '1', 'SCH80'), +(1, 'A106', '3/4', 'SCH80'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Processes` +-- + +CREATE TABLE `Processes` ( + `process_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `process_name` varchar(255) NOT NULL, + `process_start` date NOT NULL, + `process_end` date DEFAULT NULL, + `planned_worker_count` int(11) NOT NULL, + `process_description` text DEFAULT NULL, + `note` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Projects` +-- + +CREATE TABLE `Projects` ( + `project_id` int(11) NOT NULL, + `job_no` varchar(50) NOT NULL, + `project_name` varchar(255) NOT NULL, + `contract_date` date DEFAULT NULL, + `due_date` date DEFAULT NULL, + `delivery_method` varchar(100) DEFAULT NULL, + `site` varchar(100) DEFAULT NULL, + `pm` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Projects` +-- + +INSERT INTO `Projects` (`project_id`, `job_no`, `project_name`, `contract_date`, `due_date`, `delivery_method`, `site`, `pm`, `created_at`, `updated_at`) VALUES +(1, 'TKO-24008P', 'YHP Project', '2024-05-16', '2025-05-16', 'FOB', 'Quang Ninh(Vietnam)', '장형태', '2025-04-15 22:40:28', '2025-04-15 22:40:28'), +(2, 'TKG-24009P', '한화에어로스페이스 순천', '2024-06-05', '2025-05-31', '.', '순천', '장형태', '2025-04-15 22:42:41', '2025-04-15 22:42:41'), +(3, 'TKG-24011P', '효성화학 에틸렌 탱크 건설공사', '2024-06-22', '2025-12-25', '.', '울산', '김길종', '2025-04-15 22:43:53', '2025-04-15 22:43:53'), +(4, 'TKG-24013P', '김천 솔라 파워 그린 수소 Project', '2024-10-08', '2025-07-25', '.', '김천', '김길종', '2025-04-15 22:44:57', '2025-04-15 22:44:57'), +(5, 'TKG-24016P', 'LG Chem P3RE Project', '2024-11-27', '2025-09-30', '.', '.', '장형태', '2025-04-15 22:46:36', '2025-04-15 22:46:36'), +(7, 'TKO-25003F', '25년 안전보건시설설비', '2025-01-03', '2025-12-31', '.', '.', '.', '2025-04-15 22:47:32', '2025-04-15 22:47:32'), +(8, 'TKG-25007P', 'P Project', '2025-01-16', '2025-10-31', '.', '오창읍', '장형태', '2025-04-15 22:48:50', '2025-04-15 22:48:50'), +(10, 'TKR-25008P', 'DIG Airgas LG CHEM', '2025-01-23', '2025-10-15', '.', '여수', '서태원', '2025-04-15 22:50:05', '2025-04-15 22:50:05'), +(11, 'TKR-25010P', 'FK FISCHER Project', '2025-03-12', '2025-11-30', '.', '울산', '전상신', '2025-04-15 22:51:12', '2025-04-15 22:51:12'), +(12, 'TKO-24007P', 'MP7 Project', '2024-07-03', '2025-01-05', '.', '.', '윤지민', '2025-04-15 23:56:26', '2025-04-15 23:56:26'), +(13, '연차/휴무', '연차/휴무', '2025-01-01', '2025-12-31', '.', '.', '.', '2025-04-16 01:58:23', '2025-04-16 01:58:23'), +(14, 'TKO-25009R', 'M Project', '2025-08-01', '2025-12-31', '', '', '이민후', '2025-09-28 22:13:33', '2025-09-28 22:13:33'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Tasks` +-- + +CREATE TABLE `Tasks` ( + `task_id` int(11) NOT NULL, + `category` varchar(255) NOT NULL, + `subcategory` varchar(255) DEFAULT NULL, + `task_name` varchar(255) NOT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Tasks` +-- + +INSERT INTO `Tasks` (`task_id`, `category`, `subcategory`, `task_name`, `description`, `created_at`, `updated_at`) VALUES +(1, 'Base', 'Fabrication', '용접', '...', '2025-04-15 10:41:43', '2025-04-15 10:41:43'), +(3, 'Vessel', 'MI and Marking', 'Marking', '..', '2025-04-15 22:25:58', '2025-04-15 22:25:58'), +(4, 'Vessel', 'Cutting', '자재 커팅', '..', '2025-04-15 22:26:17', '2025-04-15 22:26:17'), +(5, 'Vessel', 'Fabrication', '용접', '..', '2025-04-15 22:26:43', '2025-04-15 22:26:43'), +(7, 'PKG', 'Pipe Pre-Fabrication', '취부&용접', '배관사 1명\n용접사 1명', '2025-04-15 22:37:14', '2025-04-15 22:37:14'), +(8, 'PKG', '1st Piping Assembly', '1차 조립', '.', '2025-04-15 22:38:49', '2025-04-15 22:38:49'), +(9, 'PKG', 'Re-Assembly', '재조립', '.', '2025-04-15 22:39:18', '2025-04-15 22:39:18'), +(13, '작업지원', '구매팀', '.', '.', '2025-04-16 03:03:40', '2025-04-16 03:03:40'), +(14, '기타', '시설설비제작', '.', '.', '2025-04-16 03:30:53', '2025-04-16 03:30:53'), +(15, '기타', '휴가/연차/휴무', '.', '.', '2025-04-16 05:18:13', '2025-04-16 05:18:13'), +(16, 'PKG', '제품설치', '설치작업', 'Skid, 용기 등 설치', '2025-04-29 04:39:36', '2025-04-29 04:39:36'), +(18, '작업지원', '품질팀', 'test지원', '.', '2025-06-25 07:07:08', '2025-06-25 07:07:08'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `uploaded_documents` +-- + +CREATE TABLE `uploaded_documents` ( + `id` int(11) NOT NULL, + `title` varchar(255) NOT NULL, + `tags` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `original_name` varchar(255) DEFAULT NULL, + `stored_name` varchar(255) NOT NULL, + `file_path` varchar(500) DEFAULT NULL, + `file_type` varchar(50) DEFAULT NULL, + `file_size` int(11) DEFAULT NULL, + `submitted_by` varchar(100) DEFAULT NULL, + `dt_imported` tinyint(1) DEFAULT 0, + `dt_uuid` varchar(100) DEFAULT NULL, + `of_task_created` tinyint(1) DEFAULT 0, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Users` +-- + +CREATE TABLE `Users` ( + `user_id` int(11) NOT NULL, + `username` varchar(100) NOT NULL, + `password` varchar(255) NOT NULL, + `role` varchar(30) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `access_level` varchar(30) DEFAULT NULL, + `worker_id` int(11) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `last_login_at` datetime DEFAULT NULL, + `password_changed_at` datetime DEFAULT NULL, + `failed_login_attempts` int(11) DEFAULT 0, + `locked_until` datetime DEFAULT NULL, + `name` varchar(50) DEFAULT NULL, + `email` varchar(255) DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Users` +-- + +INSERT INTO `Users` (`user_id`, `username`, `password`, `role`, `created_at`, `access_level`, `worker_id`, `is_active`, `last_login_at`, `password_changed_at`, `failed_login_attempts`, `locked_until`, `name`, `email`, `updated_at`) VALUES +(1, 'hyungi', '$2b$10$lwSfKipx0fQ.9nfMUBmzt.WXzerdxuT5MVX4b3YhFeHxyYlUjM7bi', 'admin', '2025-05-06 05:03:02', 'system', NULL, 1, '2025-10-10 23:13:57', '2025-05-06 05:03:02', 0, NULL, NULL, NULL, '2025-10-10 23:13:57'), +(3, '김두수', '$2a$10$z3i2EVOotRFBj.KHzx5LQOKlXD0QHLNFEvJcd6FlO6/1TCYGk6SSu', 'leader', '2025-06-07 23:48:35', 'group_leader', 1, 1, '2025-10-10 23:32:38', '2025-06-15 07:40:39', 0, NULL, '김두수', NULL, '2025-10-10 23:32:38'), +(4, '김아무개', '$2a$10$QAJIoPyi.apz91exp8GsiO/prAD5Xwanht6XImP1jvKsy/7Ba/b8.', 'user', '2025-06-11 08:03:59', 'worker', NULL, 1, '2025-06-15 23:28:04', '2025-06-15 06:03:42', 0, NULL, '김아무개', NULL, '2025-06-15 23:28:04'), +(5, '임영규', '$2a$10$66ps/MEEi4BVABfJc5P0y.yCap09NhTMyd1A/7rFVxESytQGlB3wC', NULL, '2025-06-15 07:41:02', 'group_leader', 3, 1, '2025-10-01 06:55:37', '2025-06-15 07:41:02', 0, NULL, '임영규', NULL, '2025-10-01 06:55:37'), +(6, '반치원', '$2a$10$jcn6f7flRLZlr5yKQcXDIePodRK0rsM4deNnNGjuOlredeTVsRYZ6', NULL, '2025-06-15 07:41:32', 'group_leader', 3, 1, '2025-09-11 06:40:19', '2025-06-15 07:41:32', 0, NULL, '반치원', NULL, '2025-09-11 06:40:19'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Workers` +-- + +CREATE TABLE `Workers` ( + `worker_id` int(11) NOT NULL, + `worker_name` varchar(100) NOT NULL, + `join_date` date DEFAULT NULL, + `job_type` varchar(100) DEFAULT NULL, + `salary` decimal(10,2) DEFAULT NULL, + `annual_leave` int(11) DEFAULT NULL, + `status` text DEFAULT 'active', + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Workers` +-- + +INSERT INTO `Workers` (`worker_id`, `worker_name`, `join_date`, `job_type`, `salary`, `annual_leave`, `status`, `created_at`, `updated_at`) VALUES +(1, '김두수', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:08', '2025-04-15 22:23:08'), +(2, '임영규', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:17', '2025-04-15 22:23:17'), +(3, '반치원', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:22', '2025-04-15 22:23:22'), +(4, '황인용', '2025-04-01', '가공,조공', 220000.00, 15, '..', '2025-04-15 22:23:33', '2025-04-15 22:23:33'), +(5, '표영진', '2025-04-01', '가공,조공', 220000.00, 15, '..', '2025-04-15 22:23:38', '2025-04-15 22:23:38'), +(6, '김윤섭', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:23:46', '2025-04-15 22:23:46'), +(7, '이창호', '2025-04-01', '용접,배관', 220000.00, 15, '..', '2025-04-15 22:23:51', '2025-04-15 22:23:51'), +(8, '최광욱', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:23:57', '2025-04-15 22:23:57'), +(9, '박현수', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:24:01', '2025-04-15 22:24:01'), +(10, '조윤호', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:24:07', '2025-04-15 22:24:07'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `worker_groups` +-- + +CREATE TABLE `worker_groups` ( + `id` int(11) NOT NULL, + `group_leader_id` int(11) NOT NULL, + `worker_id` int(11) NOT NULL, + `group_name` varchar(100) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `WorkReports` +-- + +CREATE TABLE `WorkReports` ( + `id` int(11) NOT NULL, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `morning_task_id` int(11) DEFAULT NULL, + `afternoon_task_id` int(11) DEFAULT NULL, + `overtime_hours` decimal(4,1) DEFAULT 0.0, + `overtime_task_id` int(11) DEFAULT NULL, + `work_details` text DEFAULT NULL, + `note` text DEFAULT NULL, + `memo` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `morning_project_id` int(11) DEFAULT NULL, + `afternoon_project_id` int(11) DEFAULT NULL, + `overtime_project_id` int(11) DEFAULT NULL, + `task_id` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `WorkReports` +-- + +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(176, '2025-01-02', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(177, '2025-01-02', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(178, '2025-01-02', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(179, '2025-01-02', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(180, '2025-01-02', 8, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(181, '2025-01-02', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(182, '2025-01-02', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(183, '2025-01-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 15), +(194, '2025-01-03', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(195, '2025-01-03', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(196, '2025-01-03', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 15), +(197, '2025-01-03', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(198, '2025-01-03', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 15), +(199, '2025-01-03', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(200, '2025-01-03', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(201, '2025-01-03', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(202, '2025-01-03', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(203, '2025-01-04', 7, 12, NULL, NULL, NULL, NULL, '휴일근무', NULL, NULL, '2025-04-16 05:43:25', '2025-04-16 05:43:25', NULL, NULL, NULL, 12), +(204, '2025-01-06', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:03', '2025-04-16 05:44:03', NULL, NULL, NULL, 12), +(205, '2025-01-06', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:03', '2025-04-16 05:44:03', NULL, NULL, NULL, 12), +(206, '2025-01-06', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(207, '2025-01-06', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(208, '2025-01-06', 8, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(209, '2025-01-06', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(210, '2025-01-06', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(211, '2025-01-06', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(212, '2025-01-06', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(213, '2025-01-07', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(214, '2025-01-07', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 1), +(215, '2025-01-07', 3, 12, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(216, '2025-01-07', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(217, '2025-01-07', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 1), +(218, '2025-01-07', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(219, '2025-01-07', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(220, '2025-01-07', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:25', '2025-04-16 05:45:25', NULL, NULL, NULL, 12), +(221, '2025-01-07', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:25', '2025-04-16 05:45:25', NULL, NULL, NULL, 1), +(222, '2025-01-08', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(223, '2025-01-08', 2, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(224, '2025-01-08', 3, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(225, '2025-01-08', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(226, '2025-01-08', 8, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(227, '2025-01-08', 9, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(228, '2025-01-08', 6, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(229, '2025-01-08', 4, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(230, '2025-01-08', 5, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(231, '2025-01-09', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(232, '2025-01-09', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(233, '2025-01-09', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(234, '2025-01-09', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(235, '2025-01-09', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(236, '2025-01-09', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(237, '2025-01-09', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(238, '2025-01-09', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(239, '2025-01-09', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(240, '2025-01-10', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:16', '2025-04-16 05:49:16', NULL, NULL, NULL, 13), +(241, '2025-01-10', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(242, '2025-01-10', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(243, '2025-01-10', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(244, '2025-01-10', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(245, '2025-01-10', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(246, '2025-01-10', 6, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 15), +(247, '2025-01-10', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(248, '2025-01-10', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(249, '2025-01-13', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(250, '2025-01-13', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(251, '2025-01-13', 3, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(252, '2025-01-13', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(253, '2025-01-13', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(254, '2025-01-13', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(255, '2025-01-13', 6, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(256, '2025-01-13', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 15), +(257, '2025-01-13', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(258, '2025-01-14', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(259, '2025-01-14', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(260, '2025-01-14', 3, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(261, '2025-01-14', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(262, '2025-01-14', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(263, '2025-01-14', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(265, '2025-01-14', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(266, '2025-01-14', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(267, '2025-01-14', 6, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(268, '2025-01-15', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(269, '2025-01-15', 2, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 14), +(270, '2025-01-15', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(271, '2025-01-15', 7, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 13), +(272, '2025-01-15', 8, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 14), +(273, '2025-01-15', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(275, '2025-01-15', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(276, '2025-01-15', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:38', '2025-04-16 05:52:38', NULL, NULL, NULL, 1), +(277, '2025-01-15', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:38', '2025-04-16 05:52:38', NULL, NULL, NULL, 1), +(278, '2025-01-16', 1, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(279, '2025-01-16', 2, 7, NULL, NULL, NULL, NULL, '근무', NULL, '볼트 보관함 제작', '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 14), +(280, '2025-01-16', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(281, '2025-01-16', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(282, '2025-01-16', 8, 7, NULL, NULL, NULL, NULL, '근무', NULL, '볼트 보관함 제작', '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 14), +(283, '2025-01-16', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(285, '2025-01-16', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(286, '2025-01-16', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(287, '2025-01-16', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(288, '2025-01-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(289, '2025-01-17', 2, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(290, '2025-01-17', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(291, '2025-01-17', 7, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(292, '2025-01-17', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(293, '2025-01-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(295, '2025-01-17', 4, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(296, '2025-01-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(297, '2025-01-17', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(298, '2025-01-20', 1, 7, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(299, '2025-01-20', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 8), +(300, '2025-01-20', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(301, '2025-01-20', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(302, '2025-01-20', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(303, '2025-01-20', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(304, '2025-01-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(305, '2025-01-20', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(306, '2025-01-20', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(307, '2025-01-21', 1, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 15), +(308, '2025-01-21', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 8), +(309, '2025-01-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(310, '2025-01-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(311, '2025-01-21', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 8), +(312, '2025-01-21', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 15), +(313, '2025-01-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(314, '2025-01-21', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(315, '2025-01-21', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:07', '2025-04-16 05:59:07', NULL, NULL, NULL, 1), +(316, '2025-01-22', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(317, '2025-01-22', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(318, '2025-01-22', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(319, '2025-01-22', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(320, '2025-01-22', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(321, '2025-01-22', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(322, '2025-01-22', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(323, '2025-01-22', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(324, '2025-01-22', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(325, '2025-01-23', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(326, '2025-01-23', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 8), +(327, '2025-01-23', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(328, '2025-01-23', 7, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(329, '2025-01-23', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(330, '2025-01-23', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(331, '2025-01-23', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(332, '2025-01-23', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(333, '2025-01-23', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 8), +(334, '2025-01-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(335, '2025-01-24', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 8), +(336, '2025-01-24', 3, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(337, '2025-01-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(338, '2025-01-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(339, '2025-01-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(340, '2025-01-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(341, '2025-01-24', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 8), +(342, '2025-01-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(343, '2025-02-03', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(344, '2025-02-03', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 8), +(345, '2025-02-03', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(346, '2025-02-03', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(347, '2025-02-03', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(348, '2025-02-03', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(349, '2025-02-03', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(350, '2025-02-03', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 8), +(351, '2025-02-03', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(352, '2025-02-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(353, '2025-02-04', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(354, '2025-02-04', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 8), +(355, '2025-02-04', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(356, '2025-02-04', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(357, '2025-02-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(358, '2025-02-04', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(359, '2025-02-04', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 8), +(360, '2025-02-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(361, '2025-02-05', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 8), +(362, '2025-02-05', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(363, '2025-02-05', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(364, '2025-02-05', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(365, '2025-02-05', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(366, '2025-02-05', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(367, '2025-02-05', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 1), +(368, '2025-02-05', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 8), +(369, '2025-02-05', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 1), +(370, '2025-02-06', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(371, '2025-02-06', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 15), +(372, '2025-02-06', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(373, '2025-02-06', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(374, '2025-02-06', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(375, '2025-02-06', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(376, '2025-02-06', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(377, '2025-02-06', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(378, '2025-02-06', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(379, '2025-02-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(380, '2025-02-07', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 8), +(381, '2025-02-07', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(382, '2025-02-07', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 15), +(383, '2025-02-07', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(384, '2025-02-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(385, '2025-02-07', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(386, '2025-02-07', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 8), +(387, '2025-02-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(388, '2025-02-10', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(389, '2025-02-10', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 8), +(390, '2025-02-10', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(391, '2025-02-10', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(392, '2025-02-10', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(393, '2025-02-10', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(394, '2025-02-10', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(395, '2025-02-10', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 8), +(396, '2025-02-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(397, '2025-02-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(398, '2025-02-11', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 8), +(399, '2025-02-11', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(400, '2025-02-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(401, '2025-02-11', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(402, '2025-02-11', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(403, '2025-02-11', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(404, '2025-02-11', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 8), +(405, '2025-02-11', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(406, '2025-02-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(407, '2025-02-12', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 8), +(408, '2025-02-12', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(409, '2025-02-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(410, '2025-02-12', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(411, '2025-02-12', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(412, '2025-02-12', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 15), +(413, '2025-02-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(414, '2025-02-12', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(415, '2025-02-13', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(416, '2025-02-13', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 7), +(417, '2025-02-13', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(418, '2025-02-13', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(419, '2025-02-13', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(420, '2025-02-13', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(421, '2025-02-13', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(422, '2025-02-13', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 7), +(423, '2025-02-13', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(424, '2025-02-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(425, '2025-02-14', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 7), +(426, '2025-02-14', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(427, '2025-02-14', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(428, '2025-02-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(429, '2025-02-14', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(430, '2025-02-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(431, '2025-02-14', 4, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 7), +(432, '2025-02-14', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(433, '2025-02-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:39', '2025-04-16 06:18:39', NULL, NULL, NULL, 1), +(434, '2025-02-17', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 8), +(435, '2025-02-17', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(436, '2025-02-17', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(437, '2025-02-17', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 15), +(438, '2025-02-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(439, '2025-02-17', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(440, '2025-02-17', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 8), +(441, '2025-02-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(442, '2025-02-18', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(443, '2025-02-18', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 15), +(444, '2025-02-18', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(445, '2025-02-18', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(446, '2025-02-18', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(447, '2025-02-18', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(448, '2025-02-18', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 7), +(449, '2025-02-18', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(450, '2025-02-18', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(451, '2025-02-19', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(452, '2025-02-19', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(453, '2025-02-19', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(454, '2025-02-19', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(455, '2025-02-19', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(456, '2025-02-19', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(457, '2025-02-19', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(458, '2025-02-19', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(459, '2025-02-19', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(460, '2025-02-20', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(461, '2025-02-20', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(462, '2025-02-20', 3, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(463, '2025-02-20', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(464, '2025-02-20', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(465, '2025-02-20', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(466, '2025-02-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(467, '2025-02-20', 7, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(468, '2025-02-20', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(469, '2025-02-21', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(470, '2025-02-21', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(471, '2025-02-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(472, '2025-02-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(473, '2025-02-21', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(474, '2025-02-21', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(475, '2025-02-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(476, '2025-02-21', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(477, '2025-02-21', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(478, '2025-02-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(479, '2025-02-24', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(480, '2025-02-24', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(481, '2025-02-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(482, '2025-02-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(483, '2025-02-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(484, '2025-02-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(485, '2025-02-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(486, '2025-02-24', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:33', '2025-04-16 06:24:33', NULL, NULL, NULL, 7), +(487, '2025-02-24', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, '근무시작', '2025-04-16 06:25:07', '2025-04-16 06:25:07', NULL, NULL, NULL, 7), +(488, '2025-02-25', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(489, '2025-02-25', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(490, '2025-02-25', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(491, '2025-02-25', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(492, '2025-02-25', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(493, '2025-02-25', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(494, '2025-02-25', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(495, '2025-02-25', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(496, '2025-02-25', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(497, '2025-02-25', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(498, '2025-02-26', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '당진출장 건', '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 14), +(499, '2025-02-26', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(500, '2025-02-26', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(501, '2025-02-26', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '당진출장 건', '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 14), +(502, '2025-02-26', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(503, '2025-02-26', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(504, '2025-02-26', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(505, '2025-02-26', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 15), +(506, '2025-02-26', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(507, '2025-02-26', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(508, '2025-02-27', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(509, '2025-02-27', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(510, '2025-02-27', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(511, '2025-02-27', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(512, '2025-02-27', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(513, '2025-02-27', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(514, '2025-02-27', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(515, '2025-02-27', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(516, '2025-02-27', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(517, '2025-02-27', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(518, '2025-02-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 13), +(519, '2025-02-28', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(520, '2025-02-28', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(521, '2025-02-28', 7, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 13), +(522, '2025-02-28', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(523, '2025-02-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(524, '2025-02-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(525, '2025-02-28', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(526, '2025-02-28', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 15), +(527, '2025-02-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(528, '2025-03-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(529, '2025-03-04', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(530, '2025-03-04', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 8), +(531, '2025-03-04', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 15), +(532, '2025-03-04', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(533, '2025-03-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(534, '2025-03-04', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(535, '2025-03-04', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(536, '2025-03-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(537, '2025-03-04', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 8), +(538, '2025-03-05', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(539, '2025-03-05', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(540, '2025-03-05', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 8), +(541, '2025-03-05', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(542, '2025-03-05', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(543, '2025-03-05', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(544, '2025-03-05', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(545, '2025-03-05', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 15), +(546, '2025-03-05', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(547, '2025-03-05', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 8), +(548, '2025-03-06', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(549, '2025-03-06', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(550, '2025-03-06', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 8), +(551, '2025-03-06', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 15), +(552, '2025-03-06', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(553, '2025-03-06', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(554, '2025-03-06', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(555, '2025-03-06', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(556, '2025-03-06', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(557, '2025-03-06', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 8), +(558, '2025-03-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(559, '2025-03-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 13), +(560, '2025-03-07', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 8), +(561, '2025-03-07', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 15), +(562, '2025-03-07', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(563, '2025-03-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(564, '2025-03-07', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(565, '2025-03-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 13), +(566, '2025-03-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(567, '2025-03-07', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 8), +(568, '2025-03-10', 1, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(569, '2025-03-10', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 3), +(570, '2025-03-10', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(571, '2025-03-10', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 15), +(572, '2025-03-10', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 7), +(573, '2025-03-10', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 15), +(574, '2025-03-10', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 7), +(575, '2025-03-10', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 3), +(576, '2025-03-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(577, '2025-03-10', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(578, '2025-03-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:06', '2025-04-16 06:39:06', NULL, NULL, NULL, 8), +(579, '2025-03-11', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(580, '2025-03-11', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(581, '2025-03-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(582, '2025-03-11', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(583, '2025-03-11', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 15), +(584, '2025-03-11', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(585, '2025-03-11', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(586, '2025-03-11', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(587, '2025-03-11', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(588, '2025-03-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(589, '2025-03-12', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(590, '2025-03-12', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(591, '2025-03-12', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(592, '2025-03-12', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(593, '2025-03-12', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 15), +(594, '2025-03-12', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(595, '2025-03-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(596, '2025-03-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(597, '2025-03-12', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(598, '2025-03-13', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(599, '2025-03-13', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(600, '2025-03-13', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(601, '2025-03-13', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(602, '2025-03-13', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(603, '2025-03-13', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 15), +(604, '2025-03-13', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(605, '2025-03-13', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(606, '2025-03-13', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(607, '2025-03-13', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(608, '2025-03-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(609, '2025-03-14', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 4), +(610, '2025-03-14', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(612, '2025-03-14', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(613, '2025-03-14', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 15), +(614, '2025-03-14', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(615, '2025-03-14', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(616, '2025-03-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(617, '2025-03-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(628, '2025-03-18', 1, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(629, '2025-03-18', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(630, '2025-03-18', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(631, '2025-03-18', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(632, '2025-03-18', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(633, '2025-03-18', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 15), +(634, '2025-03-18', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(635, '2025-03-18', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(636, '2025-03-18', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(637, '2025-03-18', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(648, '2025-03-17', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(649, '2025-03-17', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 4), +(650, '2025-03-17', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(651, '2025-03-17', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 4), +(652, '2025-03-17', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(653, '2025-03-17', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 15), +(654, '2025-03-17', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(655, '2025-03-17', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(656, '2025-03-17', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(657, '2025-03-17', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(658, '2025-03-19', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 4), +(659, '2025-03-19', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(660, '2025-03-19', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(661, '2025-03-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 4), +(662, '2025-03-19', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(663, '2025-03-19', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(664, '2025-03-19', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(665, '2025-03-19', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, '용접기 보관함 제작', '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 14), +(666, '2025-03-19', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 4), +(667, '2025-03-19', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(668, '2025-03-20', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(669, '2025-03-20', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(670, '2025-03-20', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(671, '2025-03-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(672, '2025-03-20', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(673, '2025-03-20', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(674, '2025-03-20', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(675, '2025-03-20', 4, 7, NULL, NULL, 2.0, NULL, '근무', NULL, '용접기 보관함 제작', '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 14), +(676, '2025-03-20', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(677, '2025-03-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(678, '2025-03-21', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:27', '2025-04-16 21:34:27', NULL, NULL, NULL, 8), +(679, '2025-03-21', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(680, '2025-03-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(681, '2025-03-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(682, '2025-03-21', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(683, '2025-03-21', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(684, '2025-03-21', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(685, '2025-03-21', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, '용기 보관함 제작', '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 14), +(686, '2025-03-21', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(687, '2025-03-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(688, '2025-03-24', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(689, '2025-03-24', 2, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(690, '2025-03-24', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(691, '2025-03-24', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(692, '2025-03-24', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(693, '2025-03-24', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(694, '2025-03-24', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(695, '2025-03-24', 4, 7, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 보관함 제작', '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 14), +(696, '2025-03-24', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(697, '2025-03-24', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(698, '2025-03-25', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(699, '2025-03-25', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(700, '2025-03-25', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(701, '2025-03-25', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(702, '2025-03-25', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(703, '2025-03-25', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(704, '2025-03-25', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(705, '2025-03-25', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 14), +(706, '2025-03-25', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(707, '2025-03-25', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(708, '2025-03-26', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 13), +(709, '2025-03-26', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 15), +(710, '2025-03-26', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(711, '2025-03-26', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(712, '2025-03-26', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(713, '2025-03-26', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(714, '2025-03-26', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(715, '2025-03-26', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 13), +(716, '2025-03-26', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(717, '2025-03-26', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(718, '2025-03-27', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(719, '2025-03-27', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(720, '2025-03-27', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(721, '2025-03-27', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(722, '2025-03-27', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(723, '2025-03-27', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(724, '2025-03-27', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 15), +(725, '2025-03-27', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(726, '2025-03-27', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(727, '2025-03-27', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(728, '2025-03-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(729, '2025-03-28', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(730, '2025-03-28', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 15), +(731, '2025-03-28', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 15), +(732, '2025-03-28', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(733, '2025-03-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(734, '2025-03-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(735, '2025-03-28', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(736, '2025-03-28', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(737, '2025-03-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(738, '2025-03-31', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(739, '2025-03-31', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 5), +(740, '2025-03-31', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(741, '2025-03-31', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(742, '2025-03-31', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(743, '2025-03-31', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(744, '2025-03-31', 10, 13, NULL, NULL, NULL, NULL, '유급', NULL, '외조모상(2일)', '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 15), +(745, '2025-03-31', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 5), +(746, '2025-03-31', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(747, '2025-03-31', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(748, '2025-03-14', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-17 01:53:24', '2025-04-17 01:53:24', NULL, NULL, NULL, 4), +(749, '2025-04-01', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(750, '2025-04-01', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(751, '2025-04-01', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(752, '2025-04-01', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(753, '2025-04-01', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(754, '2025-04-01', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(755, '2025-04-01', 10, 13, NULL, NULL, NULL, NULL, '유급', NULL, '외조모상', '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 15), +(756, '2025-04-01', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(757, '2025-04-01', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(758, '2025-04-01', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:43', '2025-04-17 04:22:43', NULL, NULL, NULL, 9), +(769, '2025-04-02', 1, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-17 04:25:55', '2025-04-17 04:25:55', NULL, NULL, NULL, 9), +(770, '2025-04-02', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(771, '2025-04-02', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(773, '2025-04-02', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(774, '2025-04-02', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(775, '2025-04-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 15), +(776, '2025-04-02', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 15), +(777, '2025-04-02', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(778, '2025-04-02', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(779, '2025-04-03', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(780, '2025-04-03', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(781, '2025-04-03', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(783, '2025-04-03', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(784, '2025-04-03', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(785, '2025-04-03', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(786, '2025-04-03', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(787, '2025-04-03', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(788, '2025-04-03', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(789, '2025-04-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(790, '2025-04-04', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(791, '2025-04-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(792, '2025-04-04', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(793, '2025-04-04', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(794, '2025-04-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(795, '2025-04-04', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(796, '2025-04-04', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(797, '2025-04-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(798, '2025-04-04', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(799, '2025-04-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(800, '2025-04-07', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(801, '2025-04-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(802, '2025-04-07', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(803, '2025-04-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(804, '2025-04-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(805, '2025-04-07', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(806, '2025-04-07', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(807, '2025-04-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(808, '2025-04-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(809, '2025-04-08', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(811, '2025-04-08', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(812, '2025-04-08', 7, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(813, '2025-04-08', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(814, '2025-04-08', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(815, '2025-04-08', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(816, '2025-04-08', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(817, '2025-04-08', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(818, '2025-04-08', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(819, '2025-04-09', 1, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-17 04:43:02', '2025-04-17 04:43:02', NULL, NULL, NULL, 9), +(820, '2025-04-09', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:02', '2025-04-17 04:43:02', NULL, NULL, NULL, 9), +(821, '2025-04-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(822, '2025-04-09', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(823, '2025-04-09', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(824, '2025-04-09', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(825, '2025-04-09', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(826, '2025-04-09', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(827, '2025-04-09', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(828, '2025-04-09', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(829, '2025-04-10', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(830, '2025-04-10', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(831, '2025-04-10', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(832, '2025-04-10', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(833, '2025-04-10', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(834, '2025-04-10', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(835, '2025-04-10', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(836, '2025-04-10', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(837, '2025-04-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(838, '2025-04-10', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(839, '2025-04-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 9), +(840, '2025-04-11', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 9), +(841, '2025-04-11', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 5), +(842, '2025-04-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(843, '2025-04-11', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 5), +(844, '2025-04-11', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 15), +(845, '2025-04-11', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 5), +(846, '2025-04-11', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(847, '2025-04-11', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 15), +(848, '2025-04-11', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(849, '2025-04-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(850, '2025-04-14', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(851, '2025-04-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 5), +(852, '2025-04-14', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(853, '2025-04-14', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 5), +(854, '2025-04-14', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(855, '2025-04-14', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(856, '2025-04-14', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(857, '2025-04-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(858, '2025-04-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(859, '2025-04-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(860, '2025-04-17', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(861, '2025-04-17', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(862, '2025-04-17', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(863, '2025-04-17', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(864, '2025-04-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(865, '2025-04-17', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(866, '2025-04-17', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(867, '2025-04-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(868, '2025-04-17', 6, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(879, '2025-04-21', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(880, '2025-04-21', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(881, '2025-04-21', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(882, '2025-04-21', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(883, '2025-04-21', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(884, '2025-04-21', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(885, '2025-04-21', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(886, '2025-04-21', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(887, '2025-04-21', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(888, '2025-04-21', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(889, '2025-04-22', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(890, '2025-04-22', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(891, '2025-04-22', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(892, '2025-04-22', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(893, '2025-04-22', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(894, '2025-04-22', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(895, '2025-04-22', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(896, '2025-04-22', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(897, '2025-04-22', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(898, '2025-04-22', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(899, '2025-04-23', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(900, '2025-04-23', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(901, '2025-04-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(902, '2025-04-23', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(903, '2025-04-23', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(904, '2025-04-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(905, '2025-04-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(906, '2025-04-23', 4, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(907, '2025-04-23', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(908, '2025-04-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(909, '2025-04-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, '벨브 부적합 관련 작업 추가', '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(910, '2025-04-24', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(911, '2025-04-24', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(912, '2025-04-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(913, '2025-04-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(914, '2025-04-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(915, '2025-04-24', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(916, '2025-04-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(917, '2025-04-24', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(918, '2025-04-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(919, '2025-04-25', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(920, '2025-04-25', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(921, '2025-04-25', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 5), +(922, '2025-04-25', 7, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(923, '2025-04-25', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(924, '2025-04-25', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(925, '2025-04-25', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(926, '2025-04-25', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '확관 작업', '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 5), +(927, '2025-04-25', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(928, '2025-04-25', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:39', '2025-04-25 04:23:39', NULL, NULL, NULL, 5), +(929, '2025-04-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:22', '2025-04-28 23:20:22', NULL, NULL, NULL, 9), +(930, '2025-04-28', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(931, '2025-04-28', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(932, '2025-04-28', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(934, '2025-04-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(935, '2025-04-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(936, '2025-04-28', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(937, '2025-04-28', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(938, '2025-04-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(939, '2025-04-29', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 9), +(940, '2025-04-29', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(941, '2025-04-29', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(942, '2025-04-29', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 9), +(943, '2025-04-29', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(944, '2025-04-29', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(945, '2025-04-29', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 14), +(946, '2025-04-29', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(947, '2025-04-29', 8, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(948, '2025-04-29', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(949, '2025-04-30', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(950, '2025-04-30', 2, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(951, '2025-04-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(953, '2025-04-30', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 15), +(954, '2025-04-30', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(955, '2025-04-30', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(956, '2025-04-30', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(957, '2025-04-30', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 15), +(958, '2025-04-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(959, '2025-04-30', 4, 7, NULL, NULL, NULL, NULL, '반반차', NULL, '제2공장 공사', '2025-04-30 04:22:04', '2025-04-30 04:22:04', NULL, NULL, NULL, 14), +(1023, '2025-04-15', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1024, '2025-04-15', 2, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1025, '2025-04-15', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1026, '2025-04-15', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1027, '2025-04-15', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1028, '2025-04-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1029, '2025-04-15', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1030, '2025-04-15', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1031, '2025-04-15', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1032, '2025-04-15', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1033, '2025-04-16', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1034, '2025-04-16', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1035, '2025-04-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(1036, '2025-04-16', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1037, '2025-04-16', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1038, '2025-04-16', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1039, '2025-04-16', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1040, '2025-04-16', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 15), +(1041, '2025-04-16', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1042, '2025-04-16', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1043, '2025-04-18', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1044, '2025-04-18', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1045, '2025-04-18', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1046, '2025-04-18', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1047, '2025-04-18', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 15), +(1048, '2025-04-18', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1049, '2025-04-18', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1050, '2025-04-18', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1051, '2025-04-18', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1052, '2025-04-18', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1053, '2025-04-02', 7, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-07 02:19:00', '2025-05-07 02:19:00', NULL, NULL, NULL, 9), +(1054, '2025-04-03', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 02:19:45', '2025-05-07 02:19:45', NULL, NULL, NULL, 9), +(1055, '2025-04-08', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 02:20:22', '2025-05-07 02:20:22', NULL, NULL, NULL, 9), +(1056, '2025-04-28', 8, 1, NULL, NULL, NULL, NULL, '반반차', NULL, 'NCR 벨브라인 설치', '2025-05-07 02:21:44', '2025-05-07 02:21:44', NULL, NULL, NULL, 9), +(1057, '2025-05-02', 1, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1058, '2025-05-02', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1059, '2025-05-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1060, '2025-05-02', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1061, '2025-05-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1062, '2025-05-02', 6, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1063, '2025-05-02', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1064, '2025-05-02', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1065, '2025-05-02', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1066, '2025-05-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1067, '2025-05-07', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1068, '2025-05-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1069, '2025-05-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1070, '2025-05-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1071, '2025-05-07', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1072, '2025-05-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1073, '2025-05-07', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1074, '2025-05-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1075, '2025-05-07', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1076, '2025-05-07', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1078, '2025-05-08', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1079, '2025-05-08', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1080, '2025-05-08', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1081, '2025-05-08', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1082, '2025-05-08', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1083, '2025-05-08', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1084, '2025-05-08', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1085, '2025-05-08', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1086, '2025-05-08', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1087, '2025-05-08', 1, 7, NULL, NULL, NULL, NULL, '반반차', NULL, '작업장 구역 설치', '2025-05-08 06:57:51', '2025-05-08 06:57:51', NULL, NULL, NULL, 14), +(1088, '2025-05-09', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1089, '2025-05-09', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1090, '2025-05-09', 3, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1091, '2025-05-09', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1092, '2025-05-09', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1093, '2025-05-09', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1094, '2025-05-09', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1095, '2025-05-09', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1096, '2025-05-09', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1097, '2025-05-09', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1100, '2025-05-12', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-11 21:52:46', '2025-05-11 21:52:46', NULL, NULL, NULL, 15), +(1108, '2025-05-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1111, '2025-05-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1113, '2025-05-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1115, '2025-05-12', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1116, '2025-05-12', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1117, '2025-05-13', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1118, '2025-05-13', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1119, '2025-05-13', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1120, '2025-05-13', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1121, '2025-05-13', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1122, '2025-05-13', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1123, '2025-05-13', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1124, '2025-05-13', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1125, '2025-05-13', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1126, '2025-05-13', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1127, '2025-05-12', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1128, '2025-05-12', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1129, '2025-05-12', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1130, '2025-05-12', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1131, '2025-05-14', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1132, '2025-05-14', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1133, '2025-05-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1134, '2025-05-14', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1135, '2025-05-14', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1136, '2025-05-14', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1137, '2025-05-14', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1138, '2025-05-14', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1139, '2025-05-14', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1140, '2025-05-14', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1141, '2025-05-15', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 14), +(1142, '2025-05-15', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1143, '2025-05-15', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1144, '2025-05-15', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1145, '2025-05-15', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1146, '2025-05-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1147, '2025-05-15', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 14), +(1148, '2025-05-15', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1149, '2025-05-15', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1150, '2025-05-15', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1151, '2025-05-16', 1, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1152, '2025-05-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1153, '2025-05-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1154, '2025-05-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1155, '2025-05-16', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1156, '2025-05-16', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1157, '2025-05-16', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1158, '2025-05-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1159, '2025-05-16', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1160, '2025-05-16', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1171, '2025-05-19', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1172, '2025-05-19', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 4), +(1173, '2025-05-19', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1174, '2025-05-19', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1175, '2025-05-19', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1176, '2025-05-19', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1177, '2025-05-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1179, '2025-05-19', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1180, '2025-05-19', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1181, '2025-05-21', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1183, '2025-05-21', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1184, '2025-05-21', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1185, '2025-05-21', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1186, '2025-05-21', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1187, '2025-05-21', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1188, '2025-05-21', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1189, '2025-05-21', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1190, '2025-05-21', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1191, '2025-05-20', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1192, '2025-05-20', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 3), +(1193, '2025-05-20', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1194, '2025-05-20', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1195, '2025-05-20', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1196, '2025-05-20', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1197, '2025-05-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1198, '2025-05-20', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1199, '2025-05-20', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1200, '2025-05-20', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1201, '2025-05-22', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1202, '2025-05-22', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 3), +(1203, '2025-05-22', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1204, '2025-05-22', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1205, '2025-05-22', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1206, '2025-05-22', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1207, '2025-05-22', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1208, '2025-05-22', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1209, '2025-05-22', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1210, '2025-05-22', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1211, '2025-05-21', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-22 04:54:12', '2025-05-22 04:54:12', NULL, NULL, NULL, 15), +(1215, '2025-05-26', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-26 06:58:00', '2025-05-26 06:58:00', NULL, NULL, NULL, 15), +(1222, '2025-05-19', 8, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-01 22:34:36', '2025-06-01 22:34:36', NULL, NULL, NULL, 3), +(1223, '2025-05-26', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1224, '2025-05-26', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1225, '2025-05-26', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1226, '2025-05-26', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1227, '2025-05-26', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1228, '2025-05-26', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1229, '2025-05-26', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1230, '2025-05-26', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1231, '2025-05-26', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1232, '2025-05-23', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1233, '2025-05-23', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 3), +(1234, '2025-05-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1235, '2025-05-23', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1236, '2025-05-23', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1237, '2025-05-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1238, '2025-05-23', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1239, '2025-05-23', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1240, '2025-05-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1241, '2025-05-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1242, '2025-05-27', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1243, '2025-05-27', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1244, '2025-05-27', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1245, '2025-05-27', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1246, '2025-05-27', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1247, '2025-05-27', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1248, '2025-05-27', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1249, '2025-05-27', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1250, '2025-05-27', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1251, '2025-05-27', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1252, '2025-05-28', 1, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-06-01 22:46:40', '2025-06-01 22:46:40', NULL, NULL, NULL, 8), +(1258, '2025-05-28', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:46:40', '2025-06-01 22:46:40', NULL, NULL, NULL, 8), +(1262, '2025-05-28', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1263, '2025-05-28', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1264, '2025-05-28', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1265, '2025-05-28', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1266, '2025-05-28', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1267, '2025-05-28', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1268, '2025-05-28', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1269, '2025-05-28', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1270, '2025-05-29', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1271, '2025-05-29', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1272, '2025-05-29', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1273, '2025-05-29', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1274, '2025-05-29', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1275, '2025-05-29', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1276, '2025-05-29', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1277, '2025-05-29', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1278, '2025-05-29', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1279, '2025-05-29', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1281, '2025-05-30', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1282, '2025-05-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1283, '2025-05-30', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1284, '2025-05-30', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1285, '2025-05-30', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1286, '2025-05-30', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1287, '2025-05-30', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1288, '2025-05-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1289, '2025-05-30', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1290, '2025-06-02', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:18', '2025-06-01 22:52:18', NULL, NULL, NULL, 8), +(1291, '2025-06-02', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 5), +(1292, '2025-06-02', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1293, '2025-06-02', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1294, '2025-06-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1295, '2025-06-02', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1296, '2025-06-02', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1297, '2025-06-02', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1298, '2025-06-02', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1299, '2025-06-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1300, '2025-05-30', 1, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-01 23:17:51', '2025-06-01 23:17:51', NULL, NULL, NULL, 8), +(1301, '2025-01-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 23:31:26', '2025-06-01 23:31:26', NULL, NULL, NULL, 15), +(1302, '2025-06-04', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1303, '2025-06-04', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1304, '2025-06-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1305, '2025-06-04', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 15), +(1306, '2025-06-04', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1307, '2025-06-04', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1308, '2025-06-04', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1309, '2025-06-04', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1310, '2025-06-04', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1311, '2025-06-04', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1312, '2025-06-09', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:28', NULL, NULL, NULL, 8), +(1313, '2025-06-09', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1314, '2025-06-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:30', NULL, NULL, NULL, 8), +(1315, '2025-06-09', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1316, '2025-06-09', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:31', NULL, NULL, NULL, 8), +(1317, '2025-06-09', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1318, '2025-06-09', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:32', NULL, NULL, NULL, 8), +(1319, '2025-06-09', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1320, '2025-06-09', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 15), +(1321, '2025-06-09', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:34', NULL, NULL, NULL, 8), +(1322, '2025-06-10', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:03', '2025-06-13 03:43:51', NULL, NULL, NULL, 8), +(1323, '2025-06-10', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:03', '2025-06-10 08:47:03', NULL, NULL, NULL, 5), +(1324, '2025-06-10', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:03', '2025-06-13 03:43:53', NULL, NULL, NULL, 8), +(1325, '2025-06-10', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:54', NULL, NULL, NULL, 8), +(1326, '2025-06-10', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1327, '2025-06-10', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1328, '2025-06-10', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:55', NULL, NULL, NULL, 8), +(1329, '2025-06-10', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1330, '2025-06-10', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:56', NULL, NULL, NULL, 8), +(1331, '2025-06-10', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:56', NULL, NULL, NULL, 8), +(1332, '2025-06-11', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:18', NULL, NULL, NULL, 8), +(1333, '2025-06-11', 2, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1334, '2025-06-11', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:19', NULL, NULL, NULL, 8), +(1335, '2025-06-11', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:20', NULL, NULL, NULL, 8), +(1336, '2025-06-11', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1337, '2025-06-11', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1338, '2025-06-11', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:22', NULL, NULL, NULL, 8), +(1339, '2025-06-11', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1340, '2025-06-11', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:23', NULL, NULL, NULL, 8), +(1341, '2025-06-11', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:23', NULL, NULL, NULL, 8), +(1342, '2025-06-13', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1343, '2025-06-13', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1344, '2025-06-13', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1345, '2025-06-13', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1346, '2025-06-13', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1347, '2025-06-13', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1348, '2025-06-13', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 15), +(1349, '2025-06-13', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1350, '2025-06-13', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1351, '2025-06-13', 10, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1352, '2025-06-05', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1353, '2025-06-05', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1354, '2025-06-05', 3, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1355, '2025-06-05', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1356, '2025-06-05', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1357, '2025-06-05', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1358, '2025-06-05', 7, 4, NULL, NULL, NULL, NULL, '반반차', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1359, '2025-06-05', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1360, '2025-06-05', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1361, '2025-06-05', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1362, '2025-06-12', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1363, '2025-06-12', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1364, '2025-06-12', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1365, '2025-06-12', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1366, '2025-06-12', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1367, '2025-06-12', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1368, '2025-06-12', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1369, '2025-06-12', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1370, '2025-06-12', 9, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1371, '2025-06-12', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1372, '2025-06-16', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:26', '2025-06-16 04:26:26', NULL, NULL, NULL, 8), +(1373, '2025-06-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1374, '2025-06-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1375, '2025-06-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1376, '2025-06-16', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1377, '2025-06-16', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'Vessel NDE 불량 수리', '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1378, '2025-06-16', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 15), +(1379, '2025-06-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'Vessel NDE 불량 수리', '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1380, '2025-06-16', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1381, '2025-06-16', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1382, '2025-06-17', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1383, '2025-06-17', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1384, '2025-06-17', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1385, '2025-06-17', 4, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:36:28', NULL, NULL, NULL, 5), +(1386, '2025-06-17', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1387, '2025-06-17', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 비파괴 불량', '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1388, '2025-06-17', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1389, '2025-06-17', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 비파괴 불량', '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1390, '2025-06-17', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1391, '2025-06-17', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1392, '2025-06-18', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1393, '2025-06-18', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1394, '2025-06-18', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1395, '2025-06-18', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1396, '2025-06-18', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1397, '2025-06-18', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1398, '2025-06-18', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1399, '2025-06-18', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1400, '2025-06-18', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1401, '2025-06-18', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1402, '2025-06-24', 1, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1403, '2025-06-24', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 5), +(1404, '2025-06-24', 3, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1405, '2025-06-24', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1406, '2025-06-24', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1407, '2025-06-24', 6, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1408, '2025-06-24', 7, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1409, '2025-06-24', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 5), +(1410, '2025-06-24', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1411, '2025-06-24', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1412, '2025-06-25', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1413, '2025-06-25', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 5), +(1414, '2025-06-25', 3, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1415, '2025-06-25', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1416, '2025-06-25', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1417, '2025-06-25', 6, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1418, '2025-06-25', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1419, '2025-06-25', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 5), +(1420, '2025-06-25', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1421, '2025-06-25', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1422, '2025-06-26', 1, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1423, '2025-06-26', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1424, '2025-06-26', 3, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1425, '2025-06-26', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1426, '2025-06-26', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1427, '2025-06-26', 6, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1428, '2025-06-26', 7, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1429, '2025-06-26', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1430, '2025-06-26', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1431, '2025-06-26', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1432, '2025-06-27', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1433, '2025-06-27', 2, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1434, '2025-06-27', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1435, '2025-06-27', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1436, '2025-06-27', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1437, '2025-06-27', 6, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1438, '2025-06-27', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1439, '2025-06-27', 8, 3, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1440, '2025-06-27', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1441, '2025-06-27', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1442, '2025-06-19', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1443, '2025-06-19', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 5), +(1444, '2025-06-19', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1445, '2025-06-19', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(1446, '2025-06-19', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 5), +(1447, '2025-06-19', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1448, '2025-06-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1449, '2025-06-19', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 5), +(1450, '2025-06-19', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1451, '2025-06-19', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1452, '2025-06-20', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1453, '2025-06-20', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 5), +(1454, '2025-06-20', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1455, '2025-06-20', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1456, '2025-06-20', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 5), +(1457, '2025-06-20', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1458, '2025-06-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1459, '2025-06-20', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 5), +(1460, '2025-06-20', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1461, '2025-06-20', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1462, '2025-06-23', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1463, '2025-06-23', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 5), +(1464, '2025-06-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1465, '2025-06-23', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1466, '2025-06-23', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 5), +(1467, '2025-06-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1468, '2025-06-23', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1469, '2025-06-23', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 5), +(1470, '2025-06-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1471, '2025-06-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1472, '2025-06-30', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1473, '2025-06-30', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 5), +(1474, '2025-06-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1475, '2025-06-30', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1476, '2025-06-30', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 5), +(1477, '2025-06-30', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 5), +(1478, '2025-06-30', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1479, '2025-06-30', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 5), +(1480, '2025-06-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1481, '2025-06-30', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1482, '2025-07-01', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 8), +(1483, '2025-07-01', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1484, '2025-07-01', 3, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1485, '2025-07-01', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 8), +(1486, '2025-07-01', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 8), +(1487, '2025-07-01', 6, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1488, '2025-07-01', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 8), +(1489, '2025-07-01', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1490, '2025-07-01', 9, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1491, '2025-07-01', 10, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1492, '2025-07-02', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 9), +(1493, '2025-07-02', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1494, '2025-07-02', 3, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1495, '2025-07-02', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 9), +(1496, '2025-07-02', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 9), +(1497, '2025-07-02', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1498, '2025-07-02', 7, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1499, '2025-07-02', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1500, '2025-07-02', 9, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1501, '2025-07-02', 10, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1502, '2025-07-03', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1503, '2025-07-03', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 5), +(1504, '2025-07-03', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1505, '2025-07-03', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1506, '2025-07-03', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1507, '2025-07-03', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 5), +(1508, '2025-07-03', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1509, '2025-07-03', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 5), +(1510, '2025-07-03', 9, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 5), +(1511, '2025-07-03', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1512, '2025-07-04', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1513, '2025-07-04', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1514, '2025-07-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1515, '2025-07-04', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1516, '2025-07-04', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1517, '2025-07-04', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1518, '2025-07-04', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1519, '2025-07-04', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1520, '2025-07-04', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1521, '2025-07-04', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1522, '2025-07-05', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1523, '2025-07-05', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1524, '2025-07-05', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1525, '2025-07-05', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1526, '2025-07-05', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1527, '2025-07-05', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1528, '2025-07-06', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1529, '2025-07-06', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1530, '2025-07-06', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1531, '2025-07-06', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1532, '2025-07-06', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1533, '2025-07-06', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1534, '2025-07-06', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1535, '2025-07-06', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1536, '2025-07-07', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1537, '2025-07-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1538, '2025-07-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1539, '2025-07-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1540, '2025-07-07', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1541, '2025-07-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1542, '2025-07-07', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1543, '2025-07-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1544, '2025-07-07', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1545, '2025-07-07', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1546, '2025-07-08', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1547, '2025-07-08', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1548, '2025-07-08', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1549, '2025-07-08', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1550, '2025-07-08', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1551, '2025-07-08', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1552, '2025-07-08', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1553, '2025-07-08', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1554, '2025-07-08', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1555, '2025-07-08', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1556, '2025-07-09', 1, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1557, '2025-07-09', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1558, '2025-07-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1559, '2025-07-09', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1560, '2025-07-09', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1561, '2025-07-09', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1562, '2025-07-09', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1563, '2025-07-09', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1564, '2025-07-09', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1565, '2025-07-09', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1566, '2025-07-10', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1567, '2025-07-10', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1568, '2025-07-10', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1569, '2025-07-10', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1570, '2025-07-10', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1571, '2025-07-10', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1572, '2025-07-10', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1573, '2025-07-10', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1574, '2025-07-10', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1575, '2025-07-10', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1576, '2025-07-14', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1577, '2025-07-14', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1578, '2025-07-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1579, '2025-07-14', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1580, '2025-07-14', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1581, '2025-07-14', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1582, '2025-07-14', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1583, '2025-07-14', 8, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1584, '2025-07-14', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1585, '2025-07-14', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1586, '2025-07-15', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:41', '2025-07-30 02:23:58', NULL, NULL, NULL, 8), +(1587, '2025-07-15', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:41', '2025-07-30 02:23:58', NULL, NULL, NULL, 8), +(1588, '2025-07-15', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:41', '2025-07-30 02:24:00', NULL, NULL, NULL, 8), +(1589, '2025-07-15', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-07-30 02:08:41', '2025-07-30 02:24:00', NULL, NULL, NULL, 15), +(1590, '2025-07-15', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:01', NULL, NULL, NULL, 5), +(1591, '2025-07-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:02', NULL, NULL, NULL, 8), +(1592, '2025-07-15', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:02', NULL, NULL, NULL, 8), +(1593, '2025-07-15', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:03', NULL, NULL, NULL, 8), +(1594, '2025-07-15', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:03', NULL, NULL, NULL, 5), +(1595, '2025-07-15', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:04', NULL, NULL, NULL, 8), +(1596, '2025-07-16', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:17', '2025-07-30 02:10:17', NULL, NULL, NULL, 8), +(1597, '2025-07-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1598, '2025-07-16', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1599, '2025-07-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 8), +(1600, '2025-07-16', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1601, '2025-07-16', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1602, '2025-07-16', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 8), +(1603, '2025-07-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1604, '2025-07-16', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1605, '2025-07-16', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1606, '2025-07-17', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:24:31', NULL, NULL, NULL, 7), +(1607, '2025-07-17', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1608, '2025-07-17', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1609, '2025-07-17', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1610, '2025-07-17', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1611, '2025-07-17', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1612, '2025-07-17', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1613, '2025-07-17', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1614, '2025-07-17', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1615, '2025-07-17', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1616, '2025-07-18', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 9), +(1617, '2025-07-18', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1618, '2025-07-18', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1619, '2025-07-18', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1620, '2025-07-18', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 9), +(1621, '2025-07-18', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1622, '2025-07-18', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 9), +(1623, '2025-07-18', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1624, '2025-07-18', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1625, '2025-07-18', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1626, '2025-07-21', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 7), +(1627, '2025-07-21', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1628, '2025-07-21', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1629, '2025-07-21', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 9), +(1630, '2025-07-21', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 9), +(1631, '2025-07-21', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1632, '2025-07-21', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1633, '2025-07-21', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1634, '2025-07-21', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1635, '2025-07-21', 10, 3, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1636, '2025-07-22', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 5), +(1637, '2025-07-22', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1638, '2025-07-22', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1639, '2025-07-22', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 7), +(1640, '2025-07-22', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 7), +(1641, '2025-07-22', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1642, '2025-07-22', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1643, '2025-07-22', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1644, '2025-07-22', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1645, '2025-07-22', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1646, '2025-07-23', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 7), +(1647, '2025-07-23', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1648, '2025-07-23', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1649, '2025-07-23', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 7), +(1650, '2025-07-23', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 7), +(1651, '2025-07-23', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1652, '2025-07-23', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1653, '2025-07-23', 8, 13, NULL, NULL, NULL, NULL, '유급', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 22:39:10', NULL, NULL, NULL, 15), +(1654, '2025-07-23', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1655, '2025-07-23', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1656, '2025-07-24', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 7), +(1657, '2025-07-24', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1658, '2025-07-24', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1659, '2025-07-24', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 7), +(1660, '2025-07-24', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 7), +(1661, '2025-07-24', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1662, '2025-07-24', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1663, '2025-07-24', 8, 13, NULL, NULL, NULL, NULL, '유급', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 15), +(1664, '2025-07-24', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1665, '2025-07-24', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1666, '2025-07-25', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 13), +(1667, '2025-07-25', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1668, '2025-07-25', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1669, '2025-07-25', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1670, '2025-07-25', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 13), +(1671, '2025-07-25', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 13), +(1672, '2025-07-25', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 18), +(1673, '2025-07-25', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1674, '2025-07-25', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1675, '2025-07-25', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1676, '2025-07-28', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 7), +(1677, '2025-07-28', 2, 5, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 13), +(1678, '2025-07-28', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1679, '2025-07-28', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 7), +(1680, '2025-07-28', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 7), +(1681, '2025-07-28', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1682, '2025-07-28', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1683, '2025-07-28', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1684, '2025-07-28', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1685, '2025-07-28', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1686, '2025-07-11', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1687, '2025-07-11', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1688, '2025-07-11', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1689, '2025-07-11', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1690, '2025-07-11', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1691, '2025-07-11', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1692, '2025-07-11', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1693, '2025-07-11', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1694, '2025-07-11', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1695, '2025-07-11', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:31', '2025-07-30 22:48:31', NULL, NULL, NULL, 9), +(1696, '2025-07-12', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1697, '2025-07-12', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1698, '2025-07-12', 3, 13, NULL, NULL, NULL, NULL, '휴무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 15), +(1699, '2025-07-12', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1700, '2025-07-12', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1701, '2025-07-12', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1702, '2025-07-12', 7, 13, NULL, NULL, NULL, NULL, '휴무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 15), +(1703, '2025-07-12', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1704, '2025-07-12', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1705, '2025-07-12', 10, 13, NULL, NULL, NULL, NULL, '휴무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 15), +(1706, '2025-07-29', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 7), +(1707, '2025-07-29', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1708, '2025-07-29', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1709, '2025-07-29', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 7), +(1710, '2025-07-29', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 7), +(1711, '2025-07-29', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1712, '2025-07-29', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1713, '2025-07-29', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1714, '2025-07-29', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1715, '2025-07-29', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1716, '2025-07-30', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 7), +(1717, '2025-07-30', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1718, '2025-07-30', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1719, '2025-07-30', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 7), +(1720, '2025-07-30', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 7), +(1721, '2025-07-30', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1722, '2025-07-30', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1723, '2025-07-30', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1724, '2025-07-30', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1725, '2025-07-30', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1726, '2025-07-31', 1, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 7), +(1727, '2025-07-31', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1728, '2025-07-31', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1729, '2025-07-31', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 7), +(1730, '2025-07-31', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 7), +(1731, '2025-07-31', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1732, '2025-07-31', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1733, '2025-07-31', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1734, '2025-07-31', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1735, '2025-07-31', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1736, '2025-09-18', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, '냉동기', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 18), +(1737, '2025-09-18', 2, 8, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 8), +(1738, '2025-09-18', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1739, '2025-09-18', 4, 8, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 8), +(1740, '2025-09-18', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, '냉동기', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 9), +(1741, '2025-09-18', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1742, '2025-09-18', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, '냉동기', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 18), +(1743, '2025-09-18', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1744, '2025-09-18', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1745, '2025-09-18', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1746, '2025-10-01', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 16), +(1747, '2025-10-01', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 16), +(1748, '2025-10-01', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1749, '2025-10-01', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 5), +(1750, '2025-10-01', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 16), +(1751, '2025-10-01', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1752, '2025-10-01', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1753, '2025-10-01', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1754, '2025-10-01', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1755, '2025-10-01', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1756, '2025-10-02', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1757, '2025-10-02', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1758, '2025-10-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 15), +(1759, '2025-10-02', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1760, '2025-10-02', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1761, '2025-10-02', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1762, '2025-10-02', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1763, '2025-10-02', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1764, '2025-10-02', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1765, '2025-10-02', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_report_audit_log` +-- + +CREATE TABLE `work_report_audit_log` ( + `log_id` int(11) NOT NULL, + `action` enum('ADD_ACCUMULATE','DELETE_SINGLE','UPDATE','DELETE','CREATE','DELETE_BATCH') NOT NULL COMMENT '작업 유형', + `report_id` int(11) DEFAULT NULL COMMENT '관련 보고서 ID', + `old_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 전 값' CHECK (json_valid(`old_values`)), + `new_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 후 값' CHECK (json_valid(`new_values`)), + `changed_by` int(11) NOT NULL COMMENT '변경자 ID', + `change_reason` varchar(500) DEFAULT NULL COMMENT '변경 사유', + `ip_address` varchar(45) DEFAULT NULL COMMENT 'IP 주소', + `user_agent` text DEFAULT NULL COMMENT '사용자 에이전트', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '변경 시간' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_report_audit_log` +-- + +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(1, 'ADD_ACCUMULATE', 12, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 02:56:12'), +(2, 'DELETE_SINGLE', 12, '{\"worker_name\":\"김두수\",\"project_name\":\"MP7 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:36'), +(3, 'DELETE_SINGLE', 11, '{\"worker_name\":\"김두수\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:39'), +(4, 'DELETE_SINGLE', 7, '{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:41'), +(5, 'ADD_ACCUMULATE', 13, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":1,\"my_total\":\"1.00\",\"grand_total\":1,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"1.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 03:18:37'), +(6, 'DELETE_SINGLE', 13, '{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:19:23'), +(7, 'ADD_ACCUMULATE', 14, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(8, 'ADD_ACCUMULATE', 15, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(9, 'ADD_ACCUMULATE', 16, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(10, 'ADD_ACCUMULATE', 17, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(11, 'ADD_ACCUMULATE', 18, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(12, 'ADD_ACCUMULATE', 19, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(13, 'ADD_ACCUMULATE', 20, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:47'), +(14, 'ADD_ACCUMULATE', 21, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(15, 'ADD_ACCUMULATE', 22, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(16, 'ADD_ACCUMULATE', 23, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(17, 'ADD_ACCUMULATE', 24, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(18, 'ADD_ACCUMULATE', 25, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(19, 'ADD_ACCUMULATE', 26, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(20, 'ADD_ACCUMULATE', 27, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(21, 'ADD_ACCUMULATE', 28, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(22, 'ADD_ACCUMULATE', 29, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(23, 'ADD_ACCUMULATE', 30, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(24, 'ADD_ACCUMULATE', 31, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(25, 'ADD_ACCUMULATE', 32, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(26, 'ADD_ACCUMULATE', 33, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(27, 'ADD_ACCUMULATE', 34, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(28, 'ADD_ACCUMULATE', 35, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(29, 'ADD_ACCUMULATE', 36, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(30, 'ADD_ACCUMULATE', 37, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(31, 'ADD_ACCUMULATE', 38, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(32, 'ADD_ACCUMULATE', 39, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(33, 'ADD_ACCUMULATE', 40, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(34, 'ADD_ACCUMULATE', 41, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(35, 'ADD_ACCUMULATE', 42, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(36, 'ADD_ACCUMULATE', 43, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(37, 'DELETE_SINGLE', 42, '{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:12:33'), +(38, 'ADD_ACCUMULATE', 44, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:13:02'), +(39, 'ADD_ACCUMULATE', 45, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:13:50'), +(40, 'DELETE_SINGLE', 41, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:14:48'), +(41, 'ADD_ACCUMULATE', 46, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:15:22'), +(42, 'DELETE_SINGLE', 1, '{\"worker_name\":\"김두수\",\"project_name\":\"25년 안전보건시설설비\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-01T00:00:00.000Z\"}', NULL, 1, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:20:38'), +(43, 'ADD_ACCUMULATE', 48, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(44, 'ADD_ACCUMULATE', 49, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(45, 'ADD_ACCUMULATE', 50, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(46, 'DELETE_SINGLE', 49, '{\"worker_name\":\"박현수\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:47:54'), +(47, 'ADD_ACCUMULATE', 51, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:48:29'), +(48, 'ADD_ACCUMULATE', 52, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-16 06:50:09'), +(49, 'ADD_ACCUMULATE', 54, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-16 06:50:09'), +(50, 'ADD_ACCUMULATE', 56, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:23:41'), +(51, 'ADD_ACCUMULATE', 58, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:23:41'), +(52, 'ADD_ACCUMULATE', 60, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:33'), +(53, 'ADD_ACCUMULATE', 62, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:33'), +(54, 'ADD_ACCUMULATE', 64, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:44'), +(55, 'ADD_ACCUMULATE', 65, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:25:24'), +(56, 'DELETE_SINGLE', 64, '{\"worker_name\":\"황인용\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-17T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-17 08:26:17'), +(57, 'ADD_ACCUMULATE', 66, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:27:06'), +(58, 'ADD_ACCUMULATE', 67, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:27:06'), +(59, 'ADD_ACCUMULATE', 68, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(60, 'ADD_ACCUMULATE', 69, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(61, 'ADD_ACCUMULATE', 70, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(62, 'ADD_ACCUMULATE', 71, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(63, 'ADD_ACCUMULATE', 72, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(64, 'ADD_ACCUMULATE', 73, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(65, 'ADD_ACCUMULATE', 74, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-17 08:34:11'), +(66, 'ADD_ACCUMULATE', 76, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-17 08:34:11'), +(67, 'ADD_ACCUMULATE', 78, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(68, 'ADD_ACCUMULATE', 79, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(69, 'ADD_ACCUMULATE', 80, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(70, 'ADD_ACCUMULATE', 81, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:02'), +(71, 'ADD_ACCUMULATE', 82, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:03'), +(72, 'ADD_ACCUMULATE', 83, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:03'), +(73, 'ADD_ACCUMULATE', 84, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:45'), +(74, 'ADD_ACCUMULATE', 86, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-18 08:47:55'), +(75, 'ADD_ACCUMULATE', 88, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-18 08:47:55'), +(76, 'ADD_ACCUMULATE', 90, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(77, 'ADD_ACCUMULATE', 92, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(78, 'ADD_ACCUMULATE', 94, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(79, 'ADD_ACCUMULATE', 96, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 09:00:17'), +(80, 'ADD_ACCUMULATE', 98, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-19 06:37:59'), +(81, 'ADD_ACCUMULATE', 99, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-19 06:37:59'), +(82, 'ADD_ACCUMULATE', 100, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(83, 'ADD_ACCUMULATE', 101, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(84, 'ADD_ACCUMULATE', 102, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(85, 'ADD_ACCUMULATE', 103, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(86, 'ADD_ACCUMULATE', 105, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(87, 'ADD_ACCUMULATE', 107, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(88, 'ADD_ACCUMULATE', 109, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(89, 'ADD_ACCUMULATE', 111, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(90, 'ADD_ACCUMULATE', 113, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(91, 'ADD_ACCUMULATE', 115, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(92, 'ADD_ACCUMULATE', 117, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(93, 'ADD_ACCUMULATE', 119, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(94, 'ADD_ACCUMULATE', 121, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(95, 'ADD_ACCUMULATE', 123, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(96, 'ADD_ACCUMULATE', 125, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-20 06:45:30'), +(97, 'ADD_ACCUMULATE', 126, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-20 06:45:31'), +(98, 'ADD_ACCUMULATE', 127, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-23 06:42:58'), +(99, 'ADD_ACCUMULATE', 128, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-23 06:42:58'), +(100, 'ADD_ACCUMULATE', 129, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(101, 'ADD_ACCUMULATE', 131, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(102, 'ADD_ACCUMULATE', 133, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(103, 'ADD_ACCUMULATE', 135, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(104, 'ADD_ACCUMULATE', 137, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(105, 'ADD_ACCUMULATE', 139, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(106, 'ADD_ACCUMULATE', 141, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-24 11:10:32'), +(107, 'ADD_ACCUMULATE', 142, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-24 11:10:32'), +(108, 'ADD_ACCUMULATE', 143, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(109, 'ADD_ACCUMULATE', 145, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(110, 'ADD_ACCUMULATE', 147, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(111, 'ADD_ACCUMULATE', 149, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(112, 'ADD_ACCUMULATE', 151, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(113, 'ADD_ACCUMULATE', 153, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(114, 'ADD_ACCUMULATE', 155, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:05'), +(115, 'ADD_ACCUMULATE', 157, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:05'), +(116, 'ADD_ACCUMULATE', 159, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-25 11:08:04'), +(117, 'ADD_ACCUMULATE', 161, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-25 11:08:05'), +(118, 'ADD_ACCUMULATE', 163, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(119, 'ADD_ACCUMULATE', 164, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(120, 'ADD_ACCUMULATE', 165, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(121, 'ADD_ACCUMULATE', 166, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(122, 'ADD_ACCUMULATE', 167, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(123, 'ADD_ACCUMULATE', 168, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(124, 'ADD_ACCUMULATE', 169, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(125, 'ADD_ACCUMULATE', 170, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(126, 'ADD_ACCUMULATE', 171, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(127, 'ADD_ACCUMULATE', 172, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:31'), +(128, 'ADD_ACCUMULATE', 174, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:32'), +(129, 'ADD_ACCUMULATE', 176, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:32'), +(130, 'ADD_ACCUMULATE', 178, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-26 11:19:34'), +(131, 'ADD_ACCUMULATE', 179, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-26 11:19:34'), +(132, 'ADD_ACCUMULATE', 180, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:21'), +(133, 'ADD_ACCUMULATE', 181, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:21'), +(134, 'ADD_ACCUMULATE', 182, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:40'), +(135, 'ADD_ACCUMULATE', 183, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(136, 'ADD_ACCUMULATE', 184, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(137, 'ADD_ACCUMULATE', 185, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(138, 'ADD_ACCUMULATE', 186, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(139, 'ADD_ACCUMULATE', 187, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(140, 'ADD_ACCUMULATE', 188, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(141, 'ADD_ACCUMULATE', 189, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:49:08'), +(142, 'ADD_ACCUMULATE', 190, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:49:08'), +(143, 'DELETE_SINGLE', 190, '{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 6, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:58:25'), +(144, 'ADD_ACCUMULATE', 191, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"4.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:58:46'), +(145, 'DELETE_SINGLE', 181, '{\"worker_name\":\"박현수\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:59:37'), +(146, 'DELETE_SINGLE', 180, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:59:42'), +(147, 'ADD_ACCUMULATE', 192, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 07:00:10'), +(148, 'ADD_ACCUMULATE', 193, NULL, '{\"report_date\":\"2025-06-30\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:37:29'), +(149, 'ADD_ACCUMULATE', 195, NULL, '{\"report_date\":\"2025-06-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:38:19'), +(150, 'ADD_ACCUMULATE', 196, NULL, '{\"report_date\":\"2025-06-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:38:19'), +(151, 'ADD_ACCUMULATE', 197, NULL, '{\"report_date\":\"2025-06-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:38:19'), +(152, 'ADD_ACCUMULATE', 198, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(153, 'ADD_ACCUMULATE', 199, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(154, 'ADD_ACCUMULATE', 200, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(155, 'ADD_ACCUMULATE', 201, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(156, 'ADD_ACCUMULATE', 202, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(157, 'ADD_ACCUMULATE', 203, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(158, 'ADD_ACCUMULATE', 204, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:48'), +(159, 'ADD_ACCUMULATE', 205, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:48'), +(160, 'ADD_ACCUMULATE', 206, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:48'), +(161, 'ADD_ACCUMULATE', 207, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:48'), +(162, 'ADD_ACCUMULATE', 208, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:40:10'), +(163, 'ADD_ACCUMULATE', 209, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:40:10'), +(164, 'ADD_ACCUMULATE', 210, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:42:57'), +(165, 'ADD_ACCUMULATE', 212, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:42:57'), +(166, 'ADD_ACCUMULATE', 214, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:42:57'), +(167, 'ADD_ACCUMULATE', 216, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:42:57'), +(168, 'ADD_ACCUMULATE', 218, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(169, 'ADD_ACCUMULATE', 219, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(170, 'ADD_ACCUMULATE', 220, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(171, 'ADD_ACCUMULATE', 221, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(172, 'ADD_ACCUMULATE', 222, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(173, 'ADD_ACCUMULATE', 223, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(174, 'ADD_ACCUMULATE', 224, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(175, 'ADD_ACCUMULATE', 225, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:44:11'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(176, 'ADD_ACCUMULATE', 227, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:44:11'), +(177, 'ADD_ACCUMULATE', 229, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:44:11'), +(178, 'ADD_ACCUMULATE', 231, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:45:44'), +(179, 'ADD_ACCUMULATE', 232, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:45:45'), +(180, 'ADD_ACCUMULATE', 233, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:45:45'), +(181, 'ADD_ACCUMULATE', 234, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:45:45'), +(182, 'ADD_ACCUMULATE', 235, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:07'), +(183, 'ADD_ACCUMULATE', 236, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:07'), +(184, 'ADD_ACCUMULATE', 237, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:08'), +(185, 'ADD_ACCUMULATE', 238, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:08'), +(186, 'ADD_ACCUMULATE', 239, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:08'), +(187, 'ADD_ACCUMULATE', 240, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:08'), +(188, 'ADD_ACCUMULATE', 241, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(189, 'ADD_ACCUMULATE', 243, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(190, 'ADD_ACCUMULATE', 245, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(191, 'ADD_ACCUMULATE', 247, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(192, 'ADD_ACCUMULATE', 249, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(193, 'ADD_ACCUMULATE', 251, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(194, 'ADD_ACCUMULATE', 253, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(195, 'ADD_ACCUMULATE', 255, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(196, 'ADD_ACCUMULATE', 257, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(197, 'ADD_ACCUMULATE', 259, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(198, 'ADD_ACCUMULATE', 261, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:38'), +(199, 'ADD_ACCUMULATE', 262, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:38'), +(200, 'ADD_ACCUMULATE', 263, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:39'), +(201, 'ADD_ACCUMULATE', 264, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:39'), +(202, 'ADD_ACCUMULATE', 265, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:39'), +(203, 'ADD_ACCUMULATE', 266, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:39'), +(204, 'ADD_ACCUMULATE', 267, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(205, 'ADD_ACCUMULATE', 268, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(206, 'ADD_ACCUMULATE', 269, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(207, 'ADD_ACCUMULATE', 270, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(208, 'ADD_ACCUMULATE', 271, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(209, 'ADD_ACCUMULATE', 272, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(210, 'ADD_ACCUMULATE', 273, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(211, 'ADD_ACCUMULATE', 274, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(212, 'ADD_ACCUMULATE', 275, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(213, 'ADD_ACCUMULATE', 276, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(214, 'ADD_ACCUMULATE', 277, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(215, 'ADD_ACCUMULATE', 278, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(216, 'ADD_ACCUMULATE', 279, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(217, 'ADD_ACCUMULATE', 280, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(218, 'ADD_ACCUMULATE', 281, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(219, 'ADD_ACCUMULATE', 282, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(220, 'ADD_ACCUMULATE', 283, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(221, 'ADD_ACCUMULATE', 284, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(222, 'ADD_ACCUMULATE', 285, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:57'), +(223, 'ADD_ACCUMULATE', 286, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(224, 'ADD_ACCUMULATE', 287, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(225, 'ADD_ACCUMULATE', 288, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(226, 'ADD_ACCUMULATE', 289, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(227, 'ADD_ACCUMULATE', 290, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(228, 'ADD_ACCUMULATE', 291, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(229, 'ADD_ACCUMULATE', 292, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(230, 'ADD_ACCUMULATE', 293, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(231, 'ADD_ACCUMULATE', 294, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(232, 'ADD_ACCUMULATE', 295, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:40'), +(233, 'ADD_ACCUMULATE', 296, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:40'), +(234, 'ADD_ACCUMULATE', 297, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:40'), +(235, 'ADD_ACCUMULATE', 298, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:41'), +(236, 'ADD_ACCUMULATE', 299, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:41'), +(237, 'ADD_ACCUMULATE', 300, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:41'), +(238, 'ADD_ACCUMULATE', 301, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:42'), +(239, 'ADD_ACCUMULATE', 302, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:42'), +(240, 'ADD_ACCUMULATE', 303, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:42'), +(241, 'ADD_ACCUMULATE', 304, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:09:10'), +(242, 'ADD_ACCUMULATE', 305, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:58'), +(243, 'ADD_ACCUMULATE', 306, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:58'), +(244, 'ADD_ACCUMULATE', 307, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:58'), +(245, 'ADD_ACCUMULATE', 308, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(246, 'ADD_ACCUMULATE', 309, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(247, 'ADD_ACCUMULATE', 310, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(248, 'ADD_ACCUMULATE', 311, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(249, 'ADD_ACCUMULATE', 312, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(250, 'ADD_ACCUMULATE', 313, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(251, 'ADD_ACCUMULATE', 314, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(252, 'ADD_ACCUMULATE', 315, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(253, 'ADD_ACCUMULATE', 316, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(254, 'ADD_ACCUMULATE', 317, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(255, 'ADD_ACCUMULATE', 318, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(256, 'ADD_ACCUMULATE', 319, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(257, 'ADD_ACCUMULATE', 320, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(258, 'ADD_ACCUMULATE', 321, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(259, 'ADD_ACCUMULATE', 322, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:30'), +(260, 'ADD_ACCUMULATE', 323, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(261, 'ADD_ACCUMULATE', 324, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(262, 'ADD_ACCUMULATE', 325, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(263, 'ADD_ACCUMULATE', 326, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(264, 'ADD_ACCUMULATE', 327, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(265, 'ADD_ACCUMULATE', 328, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(266, 'ADD_ACCUMULATE', 329, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(267, 'ADD_ACCUMULATE', 330, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(268, 'ADD_ACCUMULATE', 331, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:57:06'), +(269, 'ADD_ACCUMULATE', 332, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:57:06'), +(270, 'ADD_ACCUMULATE', 333, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:57:47'), +(271, 'ADD_ACCUMULATE', 335, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(272, 'ADD_ACCUMULATE', 336, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(273, 'ADD_ACCUMULATE', 337, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(274, 'ADD_ACCUMULATE', 338, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(275, 'ADD_ACCUMULATE', 339, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(276, 'ADD_ACCUMULATE', 340, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(277, 'ADD_ACCUMULATE', 341, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-15 06:57:26'), +(278, 'ADD_ACCUMULATE', 342, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":4,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:46:46'), +(279, 'ADD_ACCUMULATE', 345, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":5,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:46:46'), +(280, 'ADD_ACCUMULATE', 348, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":10,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:47:53'), +(281, 'ADD_ACCUMULATE', 351, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":6,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:47:53'), +(282, 'ADD_ACCUMULATE', 354, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:48:32'), +(283, 'ADD_ACCUMULATE', 355, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:48:32'), +(284, 'ADD_ACCUMULATE', 356, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:48:32'), +(285, 'ADD_ACCUMULATE', 357, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:48:32'), +(286, 'ADD_ACCUMULATE', 358, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-16 06:51:31'), +(287, 'ADD_ACCUMULATE', 359, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-16 06:51:31'), +(288, 'ADD_ACCUMULATE', 360, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-17 06:45:22'), +(289, 'ADD_ACCUMULATE', 361, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:46:48'), +(290, 'ADD_ACCUMULATE', 363, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:46:48'), +(291, 'ADD_ACCUMULATE', 365, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:46:48'), +(292, 'ADD_ACCUMULATE', 367, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(293, 'ADD_ACCUMULATE', 368, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(294, 'ADD_ACCUMULATE', 369, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(295, 'ADD_ACCUMULATE', 370, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(296, 'ADD_ACCUMULATE', 371, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(297, 'ADD_ACCUMULATE', 372, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(298, 'ADD_ACCUMULATE', 373, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"2.00\",\"grand_total\":2,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"2.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 05:54:47'), +(299, 'ADD_ACCUMULATE', 374, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"2.00\",\"grand_total\":2,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"2.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 05:54:48'), +(300, 'ADD_ACCUMULATE', 375, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":5,\"work_entries_count\":3,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 05:58:33'), +(301, 'DELETE_SINGLE', 375, '{\"worker_name\":\"표영진\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"2.00\",\"report_date\":\"2025-07-18T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-07-18 05:58:49'), +(302, 'ADD_ACCUMULATE', 378, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 05:59:42'), +(303, 'ADD_ACCUMULATE', 379, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 06:00:15'), +(304, 'ADD_ACCUMULATE', 380, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(305, 'ADD_ACCUMULATE', 381, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(306, 'ADD_ACCUMULATE', 382, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(307, 'ADD_ACCUMULATE', 383, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(308, 'ADD_ACCUMULATE', 384, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(309, 'ADD_ACCUMULATE', 385, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(310, 'ADD_ACCUMULATE', 386, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(311, 'ADD_ACCUMULATE', 387, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:08'), +(312, 'ADD_ACCUMULATE', 389, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:08'), +(313, 'ADD_ACCUMULATE', 391, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(314, 'ADD_ACCUMULATE', 392, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(315, 'ADD_ACCUMULATE', 393, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(316, 'ADD_ACCUMULATE', 394, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(317, 'ADD_ACCUMULATE', 395, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(318, 'ADD_ACCUMULATE', 396, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(319, 'ADD_ACCUMULATE', 397, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(320, 'ADD_ACCUMULATE', 398, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-21 06:53:37'), +(321, 'ADD_ACCUMULATE', 399, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:47'), +(322, 'ADD_ACCUMULATE', 400, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(323, 'ADD_ACCUMULATE', 401, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(324, 'ADD_ACCUMULATE', 402, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(325, 'ADD_ACCUMULATE', 403, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(326, 'ADD_ACCUMULATE', 404, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(327, 'ADD_ACCUMULATE', 405, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(328, 'ADD_ACCUMULATE', 406, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:46:11'), +(329, 'ADD_ACCUMULATE', 407, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-22 06:46:11'), +(330, 'ADD_ACCUMULATE', 408, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-22 06:46:11'), +(331, 'ADD_ACCUMULATE', 409, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:06'), +(332, 'ADD_ACCUMULATE', 410, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:28'), +(333, 'ADD_ACCUMULATE', 411, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:28'), +(334, 'ADD_ACCUMULATE', 412, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(335, 'ADD_ACCUMULATE', 413, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(336, 'ADD_ACCUMULATE', 414, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(337, 'ADD_ACCUMULATE', 415, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(338, 'ADD_ACCUMULATE', 416, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(339, 'ADD_ACCUMULATE', 417, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(340, 'ADD_ACCUMULATE', 418, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:36:55'), +(341, 'ADD_ACCUMULATE', 419, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(342, 'ADD_ACCUMULATE', 420, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(343, 'ADD_ACCUMULATE', 421, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(344, 'ADD_ACCUMULATE', 422, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(345, 'ADD_ACCUMULATE', 423, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(346, 'ADD_ACCUMULATE', 424, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(347, 'ADD_ACCUMULATE', 425, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-24 06:47:04'), +(348, 'ADD_ACCUMULATE', 426, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-24 06:47:04'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(349, 'ADD_ACCUMULATE', 427, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:44:23'), +(350, 'ADD_ACCUMULATE', 428, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(351, 'ADD_ACCUMULATE', 429, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(352, 'ADD_ACCUMULATE', 430, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(353, 'ADD_ACCUMULATE', 431, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(354, 'ADD_ACCUMULATE', 432, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(355, 'ADD_ACCUMULATE', 433, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(356, 'ADD_ACCUMULATE', 434, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:18'), +(357, 'ADD_ACCUMULATE', 435, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:19'), +(358, 'ADD_ACCUMULATE', 436, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:19'), +(359, 'ADD_ACCUMULATE', 437, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-28 06:30:39'), +(360, 'ADD_ACCUMULATE', 438, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-28 06:30:39'), +(361, 'ADD_ACCUMULATE', 439, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-28 06:30:39'), +(362, 'ADD_ACCUMULATE', 440, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:08'), +(363, 'ADD_ACCUMULATE', 442, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(364, 'ADD_ACCUMULATE', 443, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(365, 'ADD_ACCUMULATE', 444, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(366, 'ADD_ACCUMULATE', 445, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(367, 'ADD_ACCUMULATE', 446, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(368, 'ADD_ACCUMULATE', 447, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(369, 'ADD_ACCUMULATE', 448, NULL, '{\"report_date\":\"2025-07-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-29 06:39:13'), +(370, 'ADD_ACCUMULATE', 449, NULL, '{\"report_date\":\"2025-07-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-29 06:39:13'), +(371, 'ADD_ACCUMULATE', 450, NULL, '{\"report_date\":\"2025-07-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-29 06:39:13'), +(372, 'ADD_ACCUMULATE', 451, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-30 06:50:30'), +(373, 'ADD_ACCUMULATE', 452, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-30 06:50:30'), +(374, 'ADD_ACCUMULATE', 453, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-30 06:50:30'), +(375, 'ADD_ACCUMULATE', 454, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(376, 'ADD_ACCUMULATE', 455, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(377, 'ADD_ACCUMULATE', 456, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(378, 'ADD_ACCUMULATE', 457, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(379, 'ADD_ACCUMULATE', 458, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(380, 'ADD_ACCUMULATE', 459, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(381, 'ADD_ACCUMULATE', 460, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(382, 'ADD_ACCUMULATE', 461, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:42:56'), +(383, 'ADD_ACCUMULATE', 462, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:43:32'), +(384, 'ADD_ACCUMULATE', 464, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:43:32'), +(385, 'ADD_ACCUMULATE', 466, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(386, 'ADD_ACCUMULATE', 467, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(387, 'ADD_ACCUMULATE', 468, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(388, 'ADD_ACCUMULATE', 469, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(389, 'ADD_ACCUMULATE', 470, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(390, 'ADD_ACCUMULATE', 471, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(391, 'ADD_ACCUMULATE', 472, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(392, 'ADD_ACCUMULATE', 473, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(393, 'ADD_ACCUMULATE', 474, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(394, 'ADD_ACCUMULATE', 475, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(395, 'ADD_ACCUMULATE', 476, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(396, 'ADD_ACCUMULATE', 477, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(397, 'ADD_ACCUMULATE', 478, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(398, 'ADD_ACCUMULATE', 479, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(399, 'ADD_ACCUMULATE', 480, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(400, 'ADD_ACCUMULATE', 481, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(401, 'ADD_ACCUMULATE', 482, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(402, 'ADD_ACCUMULATE', 483, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(403, 'ADD_ACCUMULATE', 484, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(404, 'ADD_ACCUMULATE', 485, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(405, 'ADD_ACCUMULATE', 486, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(406, 'ADD_ACCUMULATE', 487, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(407, 'ADD_ACCUMULATE', 488, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(408, 'ADD_ACCUMULATE', 489, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:48'), +(409, 'ADD_ACCUMULATE', 490, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-01 05:02:28'), +(410, 'ADD_ACCUMULATE', 492, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-01 05:02:28'), +(411, 'ADD_ACCUMULATE', 494, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:42:39'), +(412, 'ADD_ACCUMULATE', 496, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:42:39'), +(413, 'ADD_ACCUMULATE', 498, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:14'), +(414, 'ADD_ACCUMULATE', 499, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:15'), +(415, 'ADD_ACCUMULATE', 500, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:15'), +(416, 'ADD_ACCUMULATE', 501, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:39'), +(417, 'ADD_ACCUMULATE', 502, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:39'), +(418, 'ADD_ACCUMULATE', 503, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:39'), +(419, 'ADD_ACCUMULATE', 504, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:52'), +(420, 'ADD_ACCUMULATE', 505, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-08 06:45:20'), +(421, 'ADD_ACCUMULATE', 506, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:58:42'), +(422, 'ADD_ACCUMULATE', 507, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:58:42'), +(423, 'ADD_ACCUMULATE', 508, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:18'), +(424, 'ADD_ACCUMULATE', 509, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:19'), +(425, 'ADD_ACCUMULATE', 510, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:19'), +(426, 'ADD_ACCUMULATE', 511, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:19'), +(427, 'ADD_ACCUMULATE', 512, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:19'), +(428, 'ADD_ACCUMULATE', 513, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-11 06:27:37'), +(429, 'ADD_ACCUMULATE', 514, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"16.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"16.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-11 06:27:37'), +(430, 'ADD_ACCUMULATE', 515, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:23'), +(431, 'ADD_ACCUMULATE', 516, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:23'), +(432, 'ADD_ACCUMULATE', 517, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:49'), +(433, 'ADD_ACCUMULATE', 518, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:49'), +(434, 'ADD_ACCUMULATE', 519, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:50'), +(435, 'ADD_ACCUMULATE', 520, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:50'), +(436, 'ADD_ACCUMULATE', 521, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:50'), +(437, 'ADD_ACCUMULATE', 522, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:50'), +(438, 'ADD_ACCUMULATE', 523, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(439, 'ADD_ACCUMULATE', 524, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(440, 'ADD_ACCUMULATE', 525, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(441, 'ADD_ACCUMULATE', 526, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(442, 'ADD_ACCUMULATE', 527, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(443, 'ADD_ACCUMULATE', 528, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(444, 'ADD_ACCUMULATE', 529, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(445, 'ADD_ACCUMULATE', 530, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(446, 'ADD_ACCUMULATE', 531, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-13 06:31:32'), +(447, 'ADD_ACCUMULATE', 532, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:13'), +(448, 'ADD_ACCUMULATE', 534, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(449, 'ADD_ACCUMULATE', 535, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(450, 'ADD_ACCUMULATE', 536, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(451, 'ADD_ACCUMULATE', 537, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(452, 'ADD_ACCUMULATE', 538, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(453, 'ADD_ACCUMULATE', 539, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(454, 'ADD_ACCUMULATE', 540, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(455, 'ADD_ACCUMULATE', 541, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:37:19'), +(456, 'ADD_ACCUMULATE', 542, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-14 06:35:27'), +(457, 'ADD_ACCUMULATE', 544, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:39:03'), +(458, 'ADD_ACCUMULATE', 546, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:39:44'), +(459, 'ADD_ACCUMULATE', 548, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(460, 'ADD_ACCUMULATE', 549, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(461, 'ADD_ACCUMULATE', 550, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(462, 'ADD_ACCUMULATE', 551, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(463, 'ADD_ACCUMULATE', 552, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(464, 'ADD_ACCUMULATE', 553, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(465, 'ADD_ACCUMULATE', 554, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:21:36'), +(466, 'ADD_ACCUMULATE', 555, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:21:36'), +(467, 'ADD_ACCUMULATE', 556, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:22:01'), +(468, 'ADD_ACCUMULATE', 557, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:22:53'), +(469, 'ADD_ACCUMULATE', 559, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:23:34'), +(470, 'ADD_ACCUMULATE', 561, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:41:24'), +(471, 'ADD_ACCUMULATE', 562, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:41:24'), +(472, 'ADD_ACCUMULATE', 563, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:41:24'), +(473, 'ADD_ACCUMULATE', 564, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:10'), +(474, 'ADD_ACCUMULATE', 565, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:10'), +(475, 'ADD_ACCUMULATE', 566, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:10'), +(476, 'ADD_ACCUMULATE', 567, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:35'), +(477, 'ADD_ACCUMULATE', 568, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:35'), +(478, 'ADD_ACCUMULATE', 569, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:02:49'), +(479, 'ADD_ACCUMULATE', 570, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:03:30'), +(480, 'ADD_ACCUMULATE', 571, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:03:30'), +(481, 'ADD_ACCUMULATE', 572, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:03:30'), +(482, 'ADD_ACCUMULATE', 573, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:03:30'), +(483, 'ADD_ACCUMULATE', 574, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(484, 'ADD_ACCUMULATE', 575, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(485, 'ADD_ACCUMULATE', 576, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(486, 'ADD_ACCUMULATE', 577, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(487, 'ADD_ACCUMULATE', 578, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(488, 'ADD_ACCUMULATE', 579, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-19 08:36:51'), +(489, 'ADD_ACCUMULATE', 580, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-19 08:36:51'), +(490, 'ADD_ACCUMULATE', 581, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-19 08:36:51'), +(491, 'ADD_ACCUMULATE', 582, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-20 06:19:36'), +(492, 'ADD_ACCUMULATE', 583, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-20 06:21:28'), +(493, 'ADD_ACCUMULATE', 585, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-20 06:21:28'), +(494, 'ADD_ACCUMULATE', 587, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:43:46'), +(495, 'ADD_ACCUMULATE', 588, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:23'), +(496, 'ADD_ACCUMULATE', 589, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:23'), +(497, 'ADD_ACCUMULATE', 590, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:23'), +(498, 'ADD_ACCUMULATE', 591, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:24'), +(499, 'ADD_ACCUMULATE', 592, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:24'), +(500, 'ADD_ACCUMULATE', 593, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:24'), +(501, 'ADD_ACCUMULATE', 594, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:26'), +(502, 'ADD_ACCUMULATE', 595, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:26'), +(503, 'ADD_ACCUMULATE', 596, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-21 06:30:36'), +(504, 'ADD_ACCUMULATE', 597, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-21 06:30:36'), +(505, 'ADD_ACCUMULATE', 598, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:50:38'), +(506, 'ADD_ACCUMULATE', 599, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:50:38'), +(507, 'ADD_ACCUMULATE', 600, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:51:23'), +(508, 'ADD_ACCUMULATE', 602, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:51:23'), +(509, 'ADD_ACCUMULATE', 604, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:51:23'), +(510, 'ADD_ACCUMULATE', 606, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:51:23'), +(511, 'ADD_ACCUMULATE', 608, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:54:46'), +(512, 'ADD_ACCUMULATE', 610, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:55:25'), +(513, 'ADD_ACCUMULATE', 612, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-21 08:24:50'), +(514, 'ADD_ACCUMULATE', 613, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-21 08:24:50'), +(515, 'ADD_ACCUMULATE', 614, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-22 06:21:15'), +(516, 'ADD_ACCUMULATE', 615, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-22 06:23:12'), +(517, 'ADD_ACCUMULATE', 617, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-22 06:23:55'), +(518, 'ADD_ACCUMULATE', 618, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:27:43'), +(519, 'ADD_ACCUMULATE', 619, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(520, 'ADD_ACCUMULATE', 620, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(521, 'ADD_ACCUMULATE', 621, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(522, 'ADD_ACCUMULATE', 622, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(523, 'ADD_ACCUMULATE', 623, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(524, 'ADD_ACCUMULATE', 624, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(525, 'ADD_ACCUMULATE', 625, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:02'), +(526, 'ADD_ACCUMULATE', 627, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:25'), +(527, 'ADD_ACCUMULATE', 628, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(528, 'ADD_ACCUMULATE', 629, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(529, 'ADD_ACCUMULATE', 630, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(530, 'ADD_ACCUMULATE', 631, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(531, 'ADD_ACCUMULATE', 632, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(532, 'ADD_ACCUMULATE', 633, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(533, 'ADD_ACCUMULATE', 634, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(534, 'ADD_ACCUMULATE', 635, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(535, 'ADD_ACCUMULATE', 636, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(536, 'ADD_ACCUMULATE', 637, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(537, 'ADD_ACCUMULATE', 638, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(538, 'ADD_ACCUMULATE', 639, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(539, 'ADD_ACCUMULATE', 640, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(540, 'ADD_ACCUMULATE', 641, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(541, 'ADD_ACCUMULATE', 642, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(542, 'ADD_ACCUMULATE', 643, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(543, 'ADD_ACCUMULATE', 644, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(544, 'ADD_ACCUMULATE', 645, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-25 06:49:16'), +(545, 'ADD_ACCUMULATE', 646, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-25 06:49:17'), +(546, 'ADD_ACCUMULATE', 647, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:28:03'), +(547, 'ADD_ACCUMULATE', 649, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:28:35'), +(548, 'ADD_ACCUMULATE', 650, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(549, 'ADD_ACCUMULATE', 651, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(550, 'ADD_ACCUMULATE', 652, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(551, 'ADD_ACCUMULATE', 653, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(552, 'ADD_ACCUMULATE', 654, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(553, 'ADD_ACCUMULATE', 655, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(554, 'ADD_ACCUMULATE', 656, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(555, 'ADD_ACCUMULATE', 657, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:03'), +(556, 'ADD_ACCUMULATE', 658, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-26 08:22:12'), +(557, 'ADD_ACCUMULATE', 659, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-26 08:22:12'), +(558, 'ADD_ACCUMULATE', 660, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-26 08:22:12'), +(559, 'ADD_ACCUMULATE', 661, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(560, 'ADD_ACCUMULATE', 662, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(561, 'ADD_ACCUMULATE', 663, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(562, 'ADD_ACCUMULATE', 664, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(563, 'ADD_ACCUMULATE', 665, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(564, 'ADD_ACCUMULATE', 666, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(565, 'ADD_ACCUMULATE', 667, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(566, 'ADD_ACCUMULATE', 668, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:48'), +(567, 'ADD_ACCUMULATE', 669, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-27 06:45:32'), +(568, 'ADD_ACCUMULATE', 671, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-27 06:45:32'), +(569, 'ADD_ACCUMULATE', 673, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-28 08:31:42'), +(570, 'ADD_ACCUMULATE', 675, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-28 08:31:42'), +(571, 'ADD_ACCUMULATE', 677, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-28 08:31:42'), +(572, 'ADD_ACCUMULATE', 679, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-28 08:31:42'), +(573, 'ADD_ACCUMULATE', 681, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:37:46'), +(574, 'ADD_ACCUMULATE', 683, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:38:15'), +(575, 'ADD_ACCUMULATE', 685, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:38:50'), +(576, 'ADD_ACCUMULATE', 687, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:39:24'), +(577, 'ADD_ACCUMULATE', 688, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(578, 'ADD_ACCUMULATE', 689, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(579, 'ADD_ACCUMULATE', 690, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(580, 'ADD_ACCUMULATE', 691, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(581, 'ADD_ACCUMULATE', 692, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(582, 'ADD_ACCUMULATE', 693, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(583, 'ADD_ACCUMULATE', 694, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:44:56'), +(584, 'ADD_ACCUMULATE', 695, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:44:56'), +(585, 'ADD_ACCUMULATE', 696, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:44:56'), +(586, 'ADD_ACCUMULATE', 697, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(587, 'ADD_ACCUMULATE', 698, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(588, 'ADD_ACCUMULATE', 699, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(589, 'ADD_ACCUMULATE', 700, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(590, 'ADD_ACCUMULATE', 701, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(591, 'ADD_ACCUMULATE', 702, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(592, 'DELETE', 693, '{\"id\":693,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:05'), +(593, 'DELETE', 702, '{\"id\":702,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:16'), +(594, 'DELETE', 697, '{\"id\":697,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:26'), +(595, 'DELETE', 688, '{\"id\":688,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:32'), +(596, 'DELETE', 691, '{\"id\":691,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:41'), +(597, 'DELETE', 700, '{\"id\":700,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:48'), +(598, 'DELETE', 692, '{\"id\":692,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:56'), +(599, 'DELETE', 701, '{\"id\":701,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:47:01'), +(600, 'ADD_ACCUMULATE', 703, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(601, 'ADD_ACCUMULATE', 704, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(602, 'ADD_ACCUMULATE', 705, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(603, 'ADD_ACCUMULATE', 706, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(604, 'ADD_ACCUMULATE', 707, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(605, 'ADD_ACCUMULATE', 708, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(606, 'ADD_ACCUMULATE', 709, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(607, 'ADD_ACCUMULATE', 710, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(608, 'ADD_ACCUMULATE', 711, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:35'), +(609, 'ADD_ACCUMULATE', 713, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:35'), +(610, 'ADD_ACCUMULATE', 715, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:35'), +(611, 'ADD_ACCUMULATE', 717, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:35'), +(612, 'DELETE', 705, '{\"id\":705,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":8,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:55:28'), +(613, 'ADD_ACCUMULATE', 719, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-29 21:55:56'), +(614, 'ADD_ACCUMULATE', 720, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-29 21:55:56'), +(615, 'ADD_ACCUMULATE', 721, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-29 21:55:56'), +(616, 'DELETE', 711, '{\"id\":711,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"6.00\",\"created_at\":\"2025-08-29T06:47:35.000Z\",\"updated_at\":\"2025-08-29T06:47:35.000Z\",\"created_by\":6,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:56:26'), +(617, 'DELETE', 712, '{\"id\":712,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":1,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-29T06:47:35.000Z\",\"updated_at\":\"2025-08-29T06:47:35.000Z\",\"created_by\":6,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:56:43'), +(618, 'DELETE', 707, '{\"id\":707,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:57:03'), +(619, 'DELETE', 708, '{\"id\":708,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:57:16'), +(620, 'DELETE', 709, '{\"id\":709,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:57:26'), +(621, 'ADD_ACCUMULATE', 722, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-30 05:12:03'), +(622, 'ADD_ACCUMULATE', 723, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-30 05:12:03'), +(623, 'ADD_ACCUMULATE', 724, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-30 05:12:03'), +(624, 'ADD_ACCUMULATE', 725, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(625, 'ADD_ACCUMULATE', 726, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(626, 'ADD_ACCUMULATE', 727, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(627, 'ADD_ACCUMULATE', 728, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(628, 'ADD_ACCUMULATE', 729, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(629, 'ADD_ACCUMULATE', 730, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(630, 'ADD_ACCUMULATE', 731, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(631, 'ADD_ACCUMULATE', 732, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:18:28'), +(632, 'ADD_ACCUMULATE', 733, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:18:28'), +(633, 'ADD_ACCUMULATE', 734, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:11'), +(634, 'ADD_ACCUMULATE', 735, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:11'), +(635, 'ADD_ACCUMULATE', 736, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:11'), +(636, 'ADD_ACCUMULATE', 737, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:35'), +(637, 'ADD_ACCUMULATE', 738, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:35'), +(638, 'ADD_ACCUMULATE', 739, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:35'), +(639, 'ADD_ACCUMULATE', 740, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:20:03'), +(640, 'DELETE', 650, '{\"id\":650,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:13:55'), +(641, 'DELETE', 654, '{\"id\":654,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:14:02'), +(642, 'DELETE', 656, '{\"id\":656,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:14:11'), +(643, 'DELETE', 572, '{\"id\":572,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":7,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:15:09'), +(644, 'DELETE', 571, '{\"id\":571,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:15:17'), +(645, 'DELETE', 570, '{\"id\":570,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:15:27'), +(646, 'DELETE', 599, '{\"id\":599,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":7,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:50:38.000Z\",\"updated_at\":\"2025-08-21T07:50:38.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:15:59'), +(647, 'DELETE', 604, '{\"id\":604,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:14'), +(648, 'DELETE', 605, '{\"id\":605,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:19'), +(649, 'DELETE', 606, '{\"id\":606,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:28'), +(650, 'DELETE', 607, '{\"id\":607,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:33'), +(651, 'DELETE', 598, '{\"id\":598,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":1,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:50:38.000Z\",\"updated_at\":\"2025-08-21T07:50:38.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:54'), +(652, 'ADD_ACCUMULATE', 741, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 23:18:03'), +(653, 'ADD_ACCUMULATE', 742, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 23:18:03'), +(654, 'DELETE', 588, '{\"id\":588,\"report_date\":\"2025-08-20T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-20T06:44:23.000Z\",\"updated_at\":\"2025-08-20T06:44:23.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:26:52'), +(655, 'DELETE', 592, '{\"id\":592,\"report_date\":\"2025-08-20T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-20T06:44:24.000Z\",\"updated_at\":\"2025-08-20T06:44:24.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:26:58'), +(656, 'DELETE', 639, '{\"id\":639,\"report_date\":\"2025-08-25T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-25T06:48:34.000Z\",\"updated_at\":\"2025-08-25T06:48:34.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:27:26'), +(657, 'DELETE', 642, '{\"id\":642,\"report_date\":\"2025-08-25T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-25T06:48:34.000Z\",\"updated_at\":\"2025-08-25T06:48:34.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:27:31'), +(658, 'ADD_ACCUMULATE', 743, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:34:20'), +(659, 'ADD_ACCUMULATE', 744, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:34:20'), +(660, 'DELETE_SINGLE', 744, '{\"worker_name\":\"이창호\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-09-02T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-09-02 07:35:18'), +(661, 'DELETE_SINGLE', 743, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-09-02T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-09-02 07:35:21'), +(662, 'ADD_ACCUMULATE', 745, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(663, 'ADD_ACCUMULATE', 746, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(664, 'ADD_ACCUMULATE', 747, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(665, 'ADD_ACCUMULATE', 748, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(666, 'ADD_ACCUMULATE', 749, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(667, 'ADD_ACCUMULATE', 750, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(668, 'ADD_ACCUMULATE', 751, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(669, 'ADD_ACCUMULATE', 752, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(670, 'ADD_ACCUMULATE', 753, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(671, 'ADD_ACCUMULATE', 754, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(672, 'ADD_ACCUMULATE', 755, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(673, 'ADD_ACCUMULATE', 756, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(674, 'ADD_ACCUMULATE', 757, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:37:19'), +(675, 'ADD_ACCUMULATE', 758, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:37:19'), +(676, 'ADD_ACCUMULATE', 759, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-02 08:16:14'), +(677, 'ADD_ACCUMULATE', 761, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-02 08:16:14'), +(678, 'ADD_ACCUMULATE', 763, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:47'), +(679, 'ADD_ACCUMULATE', 764, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:47'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(680, 'ADD_ACCUMULATE', 765, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(681, 'ADD_ACCUMULATE', 766, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(682, 'ADD_ACCUMULATE', 767, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(683, 'ADD_ACCUMULATE', 768, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(684, 'ADD_ACCUMULATE', 769, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(685, 'ADD_ACCUMULATE', 770, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(686, 'ADD_ACCUMULATE', 771, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-03 06:44:18'), +(687, 'ADD_ACCUMULATE', 772, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:32'), +(688, 'ADD_ACCUMULATE', 773, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:32'), +(689, 'ADD_ACCUMULATE', 774, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:32'), +(690, 'ADD_ACCUMULATE', 775, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:32'), +(691, 'ADD_ACCUMULATE', 776, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:33'), +(692, 'ADD_ACCUMULATE', 777, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:33'), +(693, 'ADD_ACCUMULATE', 778, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:33'), +(694, 'ADD_ACCUMULATE', 779, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:33'), +(695, 'ADD_ACCUMULATE', 780, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-04 06:48:34'), +(696, 'ADD_ACCUMULATE', 781, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-04 06:48:34'), +(697, 'ADD_ACCUMULATE', 782, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:30'), +(698, 'ADD_ACCUMULATE', 783, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:30'), +(699, 'ADD_ACCUMULATE', 784, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:30'), +(700, 'ADD_ACCUMULATE', 785, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:31'), +(701, 'ADD_ACCUMULATE', 786, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:31'), +(702, 'ADD_ACCUMULATE', 787, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:31'), +(703, 'ADD_ACCUMULATE', 788, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:31'), +(704, 'ADD_ACCUMULATE', 789, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-05 22:09:55'), +(705, 'ADD_ACCUMULATE', 790, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-05 22:09:55'), +(706, 'ADD_ACCUMULATE', 791, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-05 22:09:55'), +(707, 'ADD_ACCUMULATE', 792, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-06 04:21:10'), +(708, 'ADD_ACCUMULATE', 793, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-06 04:21:10'), +(709, 'ADD_ACCUMULATE', 794, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-06 04:21:10'), +(710, 'ADD_ACCUMULATE', 795, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:18'), +(711, 'ADD_ACCUMULATE', 796, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:18'), +(712, 'ADD_ACCUMULATE', 797, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:18'), +(713, 'ADD_ACCUMULATE', 798, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:19'), +(714, 'ADD_ACCUMULATE', 799, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:19'), +(715, 'ADD_ACCUMULATE', 800, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:19'), +(716, 'ADD_ACCUMULATE', 801, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:19'), +(717, 'ADD_ACCUMULATE', 802, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(718, 'ADD_ACCUMULATE', 803, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(719, 'ADD_ACCUMULATE', 804, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(720, 'ADD_ACCUMULATE', 805, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(721, 'ADD_ACCUMULATE', 806, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(722, 'ADD_ACCUMULATE', 807, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(723, 'ADD_ACCUMULATE', 808, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(724, 'ADD_ACCUMULATE', 809, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-08 06:47:37'), +(725, 'ADD_ACCUMULATE', 810, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-08 06:47:37'), +(726, 'ADD_ACCUMULATE', 811, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-08 06:47:37'), +(727, 'ADD_ACCUMULATE', 812, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(728, 'ADD_ACCUMULATE', 813, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(729, 'ADD_ACCUMULATE', 814, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(730, 'ADD_ACCUMULATE', 815, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(731, 'ADD_ACCUMULATE', 816, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(732, 'ADD_ACCUMULATE', 817, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(733, 'ADD_ACCUMULATE', 818, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(734, 'ADD_ACCUMULATE', 819, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-09 06:44:29'), +(735, 'ADD_ACCUMULATE', 820, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-09 06:44:29'), +(736, 'ADD_ACCUMULATE', 821, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-09 06:44:29'), +(737, 'ADD_ACCUMULATE', 822, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(738, 'ADD_ACCUMULATE', 823, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(739, 'ADD_ACCUMULATE', 824, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(740, 'ADD_ACCUMULATE', 825, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(741, 'ADD_ACCUMULATE', 826, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(742, 'ADD_ACCUMULATE', 827, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(743, 'ADD_ACCUMULATE', 828, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(744, 'ADD_ACCUMULATE', 829, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-10 06:48:43'), +(745, 'ADD_ACCUMULATE', 830, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-10 06:48:43'), +(746, 'ADD_ACCUMULATE', 831, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-10 06:48:43'), +(747, 'ADD_ACCUMULATE', 832, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:37:11'), +(748, 'ADD_ACCUMULATE', 834, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":4,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:38:24'), +(749, 'ADD_ACCUMULATE', 837, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:39:38'), +(750, 'ADD_ACCUMULATE', 838, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:40:48'), +(751, 'ADD_ACCUMULATE', 839, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:46'), +(752, 'ADD_ACCUMULATE', 840, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(753, 'ADD_ACCUMULATE', 841, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(754, 'ADD_ACCUMULATE', 842, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(755, 'ADD_ACCUMULATE', 843, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(756, 'ADD_ACCUMULATE', 844, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(757, 'ADD_ACCUMULATE', 845, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:51'), +(758, 'ADD_ACCUMULATE', 847, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:51'), +(759, 'ADD_ACCUMULATE', 849, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:51'), +(760, 'DELETE', 849, '{\"id\":849,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"4.00\",\"created_at\":\"2025-09-11T06:41:51.000Z\",\"updated_at\":\"2025-09-11T06:41:51.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-11 06:42:40'), +(761, 'DELETE', 850, '{\"id\":850,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"4.00\",\"created_at\":\"2025-09-11T06:41:51.000Z\",\"updated_at\":\"2025-09-11T06:41:51.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-11 06:42:49'), +(762, 'DELETE', 839, '{\"id\":839,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-11T06:41:46.000Z\",\"updated_at\":\"2025-09-11T06:41:46.000Z\",\"created_by\":6,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-11 06:43:07'), +(763, 'DELETE', 837, '{\"id\":837,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":8,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-11T06:39:38.000Z\",\"updated_at\":\"2025-09-11T06:39:38.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-11 06:43:16'), +(764, 'ADD_ACCUMULATE', 851, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(765, 'ADD_ACCUMULATE', 852, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(766, 'ADD_ACCUMULATE', 853, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(767, 'ADD_ACCUMULATE', 854, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(768, 'ADD_ACCUMULATE', 855, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(769, 'ADD_ACCUMULATE', 856, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(770, 'ADD_ACCUMULATE', 857, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(771, 'ADD_ACCUMULATE', 858, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(772, 'ADD_ACCUMULATE', 859, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(773, 'ADD_ACCUMULATE', 860, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(774, 'ADD_ACCUMULATE', 861, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(775, 'ADD_ACCUMULATE', 862, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(776, 'ADD_ACCUMULATE', 863, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(777, 'ADD_ACCUMULATE', 864, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(778, 'ADD_ACCUMULATE', 865, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(779, 'ADD_ACCUMULATE', 866, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(780, 'ADD_ACCUMULATE', 867, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(781, 'ADD_ACCUMULATE', 868, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(782, 'ADD_ACCUMULATE', 869, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(783, 'ADD_ACCUMULATE', 870, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:40'), +(784, 'ADD_ACCUMULATE', 871, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:40'), +(785, 'ADD_ACCUMULATE', 872, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:40'), +(786, 'ADD_ACCUMULATE', 873, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:40'), +(787, 'ADD_ACCUMULATE', 874, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(788, 'ADD_ACCUMULATE', 875, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(789, 'ADD_ACCUMULATE', 876, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(790, 'ADD_ACCUMULATE', 877, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(791, 'ADD_ACCUMULATE', 878, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(792, 'ADD_ACCUMULATE', 879, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:00'), +(793, 'ADD_ACCUMULATE', 880, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:00'), +(794, 'ADD_ACCUMULATE', 881, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:00'), +(795, 'ADD_ACCUMULATE', 882, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:00'), +(796, 'ADD_ACCUMULATE', 883, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(797, 'ADD_ACCUMULATE', 884, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(798, 'ADD_ACCUMULATE', 885, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(799, 'ADD_ACCUMULATE', 886, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(800, 'ADD_ACCUMULATE', 887, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(801, 'ADD_ACCUMULATE', 888, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(802, 'ADD_ACCUMULATE', 889, NULL, '{\"report_date\":\"2025-09-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-16 06:51:19'), +(803, 'ADD_ACCUMULATE', 890, NULL, '{\"report_date\":\"2025-09-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-16 06:51:19'), +(804, 'ADD_ACCUMULATE', 891, NULL, '{\"report_date\":\"2025-09-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-16 06:52:12'), +(805, 'ADD_ACCUMULATE', 893, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-17 06:43:08'), +(806, 'ADD_ACCUMULATE', 894, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-17 06:43:08'), +(807, 'ADD_ACCUMULATE', 895, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(808, 'ADD_ACCUMULATE', 896, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(809, 'ADD_ACCUMULATE', 897, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(810, 'ADD_ACCUMULATE', 898, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(811, 'ADD_ACCUMULATE', 899, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(812, 'ADD_ACCUMULATE', 900, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(813, 'ADD_ACCUMULATE', 901, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(814, 'ADD_ACCUMULATE', 902, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(815, 'ADD_ACCUMULATE', 903, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:43:40'), +(816, 'ADD_ACCUMULATE', 904, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:43:40'), +(817, 'ADD_ACCUMULATE', 905, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(818, 'ADD_ACCUMULATE', 906, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(819, 'ADD_ACCUMULATE', 907, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(820, 'ADD_ACCUMULATE', 908, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(821, 'ADD_ACCUMULATE', 909, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(822, 'ADD_ACCUMULATE', 910, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:46:39'), +(823, 'ADD_ACCUMULATE', 911, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-18 06:54:48'), +(824, 'ADD_ACCUMULATE', 912, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-18 06:54:48'), +(825, 'ADD_ACCUMULATE', 913, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:51:40'), +(826, 'ADD_ACCUMULATE', 914, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:51:40'), +(827, 'ADD_ACCUMULATE', 915, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(828, 'ADD_ACCUMULATE', 916, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(829, 'ADD_ACCUMULATE', 917, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(830, 'ADD_ACCUMULATE', 918, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(831, 'ADD_ACCUMULATE', 919, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(832, 'ADD_ACCUMULATE', 920, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:23'), +(833, 'ADD_ACCUMULATE', 921, NULL, '{\"report_date\":\"2025-09-20\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-20 05:30:19'), +(834, 'ADD_ACCUMULATE', 922, NULL, '{\"report_date\":\"2025-09-20\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-20 05:30:19'), +(835, 'ADD_ACCUMULATE', 923, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(836, 'ADD_ACCUMULATE', 924, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(837, 'ADD_ACCUMULATE', 925, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(838, 'ADD_ACCUMULATE', 926, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(839, 'ADD_ACCUMULATE', 927, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(840, 'ADD_ACCUMULATE', 928, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(841, 'ADD_ACCUMULATE', 929, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-22 06:50:29'), +(842, 'ADD_ACCUMULATE', 930, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-22 06:50:29'), +(843, 'ADD_ACCUMULATE', 931, NULL, '{\"report_date\":\"2025-09-23\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-23 05:46:40'), +(844, 'ADD_ACCUMULATE', 932, NULL, '{\"report_date\":\"2025-09-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-23 05:46:40'), +(845, 'ADD_ACCUMULATE', 933, NULL, '{\"report_date\":\"2025-09-24\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-25 01:14:58'), +(846, 'ADD_ACCUMULATE', 934, NULL, '{\"report_date\":\"2025-09-24\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-25 01:14:58'), +(847, 'ADD_ACCUMULATE', 935, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:07'), +(848, 'ADD_ACCUMULATE', 936, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:07'), +(849, 'ADD_ACCUMULATE', 937, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(850, 'ADD_ACCUMULATE', 938, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(851, 'ADD_ACCUMULATE', 939, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(852, 'ADD_ACCUMULATE', 940, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(853, 'ADD_ACCUMULATE', 941, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(854, 'ADD_ACCUMULATE', 942, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(855, 'ADD_ACCUMULATE', 943, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(856, 'ADD_ACCUMULATE', 944, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(857, 'ADD_ACCUMULATE', 945, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(858, 'ADD_ACCUMULATE', 946, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(859, 'ADD_ACCUMULATE', 947, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(860, 'ADD_ACCUMULATE', 948, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(861, 'ADD_ACCUMULATE', 949, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(862, 'ADD_ACCUMULATE', 950, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(863, 'ADD_ACCUMULATE', 951, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:27'), +(864, 'ADD_ACCUMULATE', 952, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:27'), +(865, 'ADD_ACCUMULATE', 953, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:27'), +(866, 'DELETE', 952, '{\"id\":952,\"report_date\":\"2025-09-30T00:00:00.000Z\",\"worker_id\":2,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-30T06:52:27.000Z\",\"updated_at\":\"2025-09-30T06:52:27.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-30 06:56:36'), +(867, 'ADD_ACCUMULATE', 954, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-30 06:56:55'), +(868, 'ADD_ACCUMULATE', 955, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 05:25:58'), +(869, 'ADD_ACCUMULATE', 956, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 05:25:59'), +(870, 'ADD_ACCUMULATE', 957, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:32'), +(871, 'ADD_ACCUMULATE', 958, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:32'), +(872, 'ADD_ACCUMULATE', 959, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:32'), +(873, 'ADD_ACCUMULATE', 960, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:32'), +(874, 'ADD_ACCUMULATE', 961, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:33'), +(875, 'ADD_ACCUMULATE', 962, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:33'), +(876, 'ADD_ACCUMULATE', 963, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:33'), +(877, 'ADD_ACCUMULATE', 964, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-10 23:35:07'), +(878, 'ADD_ACCUMULATE', 965, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-10 23:35:07'), +(879, 'ADD_ACCUMULATE', 966, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-10 23:35:07'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_status_types` +-- + +CREATE TABLE `work_status_types` ( + `id` int(11) NOT NULL, + `name` varchar(50) NOT NULL COMMENT '상태명', + `description` text DEFAULT NULL COMMENT '상태 설명', + `is_error` tinyint(1) DEFAULT 0 COMMENT '에러 상태 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_status_types` +-- + +INSERT INTO `work_status_types` (`id`, `name`, `description`, `is_error`, `created_at`) VALUES +(1, '정규', '정상적으로 완료된 작업', 0, '2025-06-16 02:21:16'), +(2, '에러', '오류가 발생한 작업', 1, '2025-06-16 02:21:16'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_types` +-- + +CREATE TABLE `work_types` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL COMMENT '작업 유형명', + `description` text DEFAULT NULL COMMENT '작업 유형 설명', + `category` varchar(50) DEFAULT NULL COMMENT '작업 카테고리', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_types` +-- + +INSERT INTO `work_types` (`id`, `name`, `description`, `category`, `created_at`, `updated_at`) VALUES +(1, 'Base(구조물)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:42'), +(2, 'Vessel(용기)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:47'), +(3, 'Piping Assembly(배관)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:50'), +(4, '작업대기', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:56'); + +-- +-- 덤프된 테이블의 인덱스 +-- + +-- +-- 테이블의 인덱스 `activity_logs` +-- +ALTER TABLE `activity_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_user_activity` (`user_id`,`activity_type`,`created_at`), + ADD KEY `idx_table_record` (`table_name`,`record_id`); + +-- +-- 테이블의 인덱스 `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + ADD PRIMARY KEY (`cutting_plan_id`), + ADD KEY `project_id` (`project_id`), + ADD KEY `fk_cuttingplan_spec` (`spec_id`); + +-- +-- 테이블의 인덱스 `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + ADD PRIMARY KEY (`id`), + ADD KEY `worker_id` (`worker_id`), + ADD KEY `fk_dird_project` (`project_id`), + ADD KEY `fk_dird_issuetype` (`issue_type_id`); + +-- +-- 테이블의 인덱스 `daily_worker_summary` +-- +ALTER TABLE `daily_worker_summary` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `unique_worker_date` (`worker_id`,`report_date`); + +-- +-- 테이블의 인덱스 `daily_work_reports` +-- +ALTER TABLE `daily_work_reports` + ADD PRIMARY KEY (`id`), + ADD KEY `idx_report_date` (`report_date`), + ADD KEY `idx_worker_date` (`worker_id`,`report_date`), + ADD KEY `idx_project_date` (`project_id`,`report_date`), + ADD KEY `idx_work_type` (`work_type_id`), + ADD KEY `idx_work_status` (`work_status_id`), + ADD KEY `idx_error_type` (`error_type_id`), + ADD KEY `idx_created_by` (`created_by`), + ADD KEY `idx_date_worker_creator` (`report_date`,`worker_id`,`created_by`); + +-- +-- 테이블의 인덱스 `EquipmentList` +-- +ALTER TABLE `EquipmentList` + ADD PRIMARY KEY (`equipment_id`), + ADD KEY `factory_id` (`factory_id`); + +-- +-- 테이블의 인덱스 `error_types` +-- +ALTER TABLE `error_types` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `FactoryInfo` +-- +ALTER TABLE `FactoryInfo` + ADD PRIMARY KEY (`factory_id`); + +-- +-- 테이블의 인덱스 `IssueTypes` +-- +ALTER TABLE `IssueTypes` + ADD PRIMARY KEY (`issue_type_id`); + +-- +-- 테이블의 인덱스 `login_logs` +-- +ALTER TABLE `login_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_user_login` (`user_id`,`login_time`); + +-- +-- 테이블의 인덱스 `password_change_logs` +-- +ALTER TABLE `password_change_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `changed_by_user_id` (`changed_by_user_id`), + ADD KEY `idx_user_changes` (`user_id`,`changed_at`); + +-- +-- 테이블의 인덱스 `PipeSpecs` +-- +ALTER TABLE `PipeSpecs` + ADD PRIMARY KEY (`spec_id`), + ADD UNIQUE KEY `unique_spec` (`material`,`diameter_in`,`schedule`); + +-- +-- 테이블의 인덱스 `Processes` +-- +ALTER TABLE `Processes` + ADD PRIMARY KEY (`process_id`), + ADD KEY `project_id` (`project_id`); + +-- +-- 테이블의 인덱스 `Projects` +-- +ALTER TABLE `Projects` + ADD PRIMARY KEY (`project_id`); + +-- +-- 테이블의 인덱스 `Tasks` +-- +ALTER TABLE `Tasks` + ADD PRIMARY KEY (`task_id`); + +-- +-- 테이블의 인덱스 `uploaded_documents` +-- +ALTER TABLE `uploaded_documents` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `Users` +-- +ALTER TABLE `Users` + ADD PRIMARY KEY (`user_id`), + ADD UNIQUE KEY `username` (`username`), + ADD UNIQUE KEY `email` (`email`), + ADD KEY `fk_worker` (`worker_id`), + ADD KEY `idx_username` (`username`), + ADD KEY `idx_active_users` (`is_active`,`access_level`); + +-- +-- 테이블의 인덱스 `Workers` +-- +ALTER TABLE `Workers` + ADD PRIMARY KEY (`worker_id`); + +-- +-- 테이블의 인덱스 `worker_groups` +-- +ALTER TABLE `worker_groups` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `uk_leader_worker` (`group_leader_id`,`worker_id`), + ADD KEY `idx_group_leader` (`group_leader_id`), + ADD KEY `idx_worker` (`worker_id`), + ADD KEY `idx_is_active` (`is_active`); + +-- +-- 테이블의 인덱스 `WorkReports` +-- +ALTER TABLE `WorkReports` + ADD PRIMARY KEY (`id`), + ADD KEY `worker_id` (`worker_id`), + ADD KEY `project_id` (`project_id`), + ADD KEY `morning_task_id` (`morning_task_id`), + ADD KEY `afternoon_task_id` (`afternoon_task_id`), + ADD KEY `overtime_task_id` (`overtime_task_id`); + +-- +-- 테이블의 인덱스 `work_report_audit_log` +-- +ALTER TABLE `work_report_audit_log` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_action_date` (`action`,`created_at`), + ADD KEY `idx_changed_by` (`changed_by`), + ADD KEY `idx_report_id` (`report_id`); + +-- +-- 테이블의 인덱스 `work_status_types` +-- +ALTER TABLE `work_status_types` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `work_types` +-- +ALTER TABLE `work_types` + ADD PRIMARY KEY (`id`); + +-- +-- 덤프된 테이블의 AUTO_INCREMENT +-- + +-- +-- 테이블의 AUTO_INCREMENT `activity_logs` +-- +ALTER TABLE `activity_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + MODIFY `cutting_plan_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; + +-- +-- 테이블의 AUTO_INCREMENT `daily_worker_summary` +-- +ALTER TABLE `daily_worker_summary` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; + +-- +-- 테이블의 AUTO_INCREMENT `daily_work_reports` +-- +ALTER TABLE `daily_work_reports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=967; + +-- +-- 테이블의 AUTO_INCREMENT `EquipmentList` +-- +ALTER TABLE `EquipmentList` + MODIFY `equipment_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `error_types` +-- +ALTER TABLE `error_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; + +-- +-- 테이블의 AUTO_INCREMENT `FactoryInfo` +-- +ALTER TABLE `FactoryInfo` + MODIFY `factory_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; + +-- +-- 테이블의 AUTO_INCREMENT `IssueTypes` +-- +ALTER TABLE `IssueTypes` + MODIFY `issue_type_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `login_logs` +-- +ALTER TABLE `login_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=345; + +-- +-- 테이블의 AUTO_INCREMENT `password_change_logs` +-- +ALTER TABLE `password_change_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `PipeSpecs` +-- +ALTER TABLE `PipeSpecs` + MODIFY `spec_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; + +-- +-- 테이블의 AUTO_INCREMENT `Processes` +-- +ALTER TABLE `Processes` + MODIFY `process_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `Projects` +-- +ALTER TABLE `Projects` + MODIFY `project_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=15; + +-- +-- 테이블의 AUTO_INCREMENT `Tasks` +-- +ALTER TABLE `Tasks` + MODIFY `task_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19; + +-- +-- 테이블의 AUTO_INCREMENT `uploaded_documents` +-- +ALTER TABLE `uploaded_documents` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `Users` +-- +ALTER TABLE `Users` + MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `Workers` +-- +ALTER TABLE `Workers` + MODIFY `worker_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12; + +-- +-- 테이블의 AUTO_INCREMENT `worker_groups` +-- +ALTER TABLE `worker_groups` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `WorkReports` +-- +ALTER TABLE `WorkReports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1766; + +-- +-- 테이블의 AUTO_INCREMENT `work_report_audit_log` +-- +ALTER TABLE `work_report_audit_log` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=880; + +-- +-- 테이블의 AUTO_INCREMENT `work_status_types` +-- +ALTER TABLE `work_status_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- 테이블의 AUTO_INCREMENT `work_types` +-- +ALTER TABLE `work_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11; + +-- +-- 덤프된 테이블의 제약사항 +-- + +-- +-- 테이블의 제약사항 `activity_logs` +-- +ALTER TABLE `activity_logs` + ADD CONSTRAINT `activity_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE SET NULL; + +-- +-- 테이블의 제약사항 `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + ADD CONSTRAINT `CuttingPlan_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`), + ADD CONSTRAINT `fk_cuttingplan_spec` FOREIGN KEY (`spec_id`) REFERENCES `PipeSpecs` (`spec_id`); + +-- +-- 테이블의 제약사항 `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + ADD CONSTRAINT `dailyissuereports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`), + ADD CONSTRAINT `fk_dird_issuetype` FOREIGN KEY (`issue_type_id`) REFERENCES `IssueTypes` (`issue_type_id`), + ADD CONSTRAINT `fk_dird_project` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`); + +-- +-- 테이블의 제약사항 `EquipmentList` +-- +ALTER TABLE `EquipmentList` + ADD CONSTRAINT `EquipmentList_ibfk_1` FOREIGN KEY (`factory_id`) REFERENCES `FactoryInfo` (`factory_id`); + +-- +-- 테이블의 제약사항 `login_logs` +-- +ALTER TABLE `login_logs` + ADD CONSTRAINT `login_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE; + +-- +-- 테이블의 제약사항 `password_change_logs` +-- +ALTER TABLE `password_change_logs` + ADD CONSTRAINT `password_change_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `password_change_logs_ibfk_2` FOREIGN KEY (`changed_by_user_id`) REFERENCES `Users` (`user_id`) ON DELETE SET NULL; + +-- +-- 테이블의 제약사항 `Processes` +-- +ALTER TABLE `Processes` + ADD CONSTRAINT `Processes_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`); + +-- +-- 테이블의 제약사항 `Users` +-- +ALTER TABLE `Users` + ADD CONSTRAINT `fk_worker` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`); + +-- +-- 테이블의 제약사항 `worker_groups` +-- +ALTER TABLE `worker_groups` + ADD CONSTRAINT `fk_group_leader` FOREIGN KEY (`group_leader_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `fk_group_worker` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`) ON DELETE CASCADE; + +-- +-- 테이블의 제약사항 `WorkReports` +-- +ALTER TABLE `WorkReports` + ADD CONSTRAINT `WorkReports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`), + ADD CONSTRAINT `WorkReports_ibfk_2` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`), + ADD CONSTRAINT `WorkReports_ibfk_3` FOREIGN KEY (`morning_task_id`) REFERENCES `Tasks` (`task_id`), + ADD CONSTRAINT `WorkReports_ibfk_4` FOREIGN KEY (`afternoon_task_id`) REFERENCES `Tasks` (`task_id`), + ADD CONSTRAINT `WorkReports_ibfk_5` FOREIGN KEY (`overtime_task_id`) REFERENCES `Tasks` (`task_id`); +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/99_restore_data.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/99_restore_data.sql new file mode 100644 index 0000000..931114b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations/99_restore_data.sql @@ -0,0 +1,4567 @@ +-- phpMyAdmin SQL Dump +-- version 5.2.2 +-- https://www.phpmyadmin.net/ +-- +-- 호스트: db_hyungi_net +-- 생성 시간: 25-10-11 00:23 +-- 서버 버전: 10.9.8-MariaDB-1:10.9.8+maria~ubu2204 +-- PHP 버전: 8.2.27 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+00:00"; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; + +-- +-- 데이터베이스: `hyungi` +-- + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `activity_logs` +-- + +CREATE TABLE `activity_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `activity_type` varchar(100) DEFAULT NULL, + `table_name` varchar(50) DEFAULT NULL, + `record_id` int(11) DEFAULT NULL, + `action` enum('create','read','update','delete') DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `CuttingPlan` +-- + +CREATE TABLE `CuttingPlan` ( + `cutting_plan_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `drawing_name` varchar(255) NOT NULL, + `area_number` varchar(100) DEFAULT NULL, + `spool_number` varchar(255) DEFAULT NULL, + `length` decimal(10,2) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `spec_id` int(11) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `DailyIssueReports` +-- + +CREATE TABLE `DailyIssueReports` ( + `id` int(11) NOT NULL, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `issue_type_id` int(11) DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `start_time` time NOT NULL, + `end_time` time NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `DailyIssueReports` +-- + +INSERT INTO `DailyIssueReports` (`id`, `date`, `worker_id`, `project_id`, `issue_type_id`, `description`, `created_at`, `start_time`, `end_time`) VALUES +(1, '2025-06-02', 1, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(2, '2025-06-02', 9, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(3, '2025-06-02', 7, 7, 5, NULL, '2025-06-02 05:54:35', '10:00:00', '11:30:00'), +(4, '2025-06-04', 10, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(5, '2025-06-04', 6, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(6, '2025-06-04', 3, 7, 3, NULL, '2025-06-04 01:54:03', '10:00:00', '11:30:00'), +(7, '2025-06-11', 10, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'), +(8, '2025-06-11', 6, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'), +(9, '2025-06-11', 3, 7, 6, NULL, '2025-06-10 08:56:09', '07:30:00', '08:00:00'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `daily_worker_summary` +-- + +CREATE TABLE `daily_worker_summary` ( + `id` int(11) NOT NULL, + `report_date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `total_hours` decimal(4,2) NOT NULL DEFAULT 8.00 COMMENT '총 근무시간', + `work_status` enum('normal','annual_leave','half_leave','overtime') DEFAULT 'normal' COMMENT '근무 상태', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `daily_work_reports` +-- + +CREATE TABLE `daily_work_reports` ( + `id` int(11) NOT NULL, + `report_date` date NOT NULL COMMENT '작업 날짜', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `project_id` int(11) NOT NULL COMMENT '프로젝트 ID', + `work_type_id` int(11) NOT NULL COMMENT '작업 유형 ID', + `work_status_id` int(11) DEFAULT 1 COMMENT '업무 상태 ID (1:정규, 2:에러)', + `error_type_id` int(11) DEFAULT NULL COMMENT '에러 유형 ID (에러일 때만)', + `work_hours` decimal(4,2) NOT NULL COMMENT '작업 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `created_by` int(11) NOT NULL DEFAULT 1 COMMENT '작성자 user_id', + `updated_by` int(11) DEFAULT NULL COMMENT '수정자 user_id' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `daily_work_reports` +-- + +INSERT INTO `daily_work_reports` (`id`, `report_date`, `worker_id`, `project_id`, `work_type_id`, `work_status_id`, `error_type_id`, `work_hours`, `created_at`, `updated_at`, `created_by`, `updated_by`) VALUES +(14, '2025-06-02', 1, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(15, '2025-06-02', 3, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(16, '2025-06-02', 4, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(17, '2025-06-02', 6, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(18, '2025-06-02', 7, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(19, '2025-06-02', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 05:10:23', '2025-06-16 05:10:23', 1, NULL), +(20, '2025-06-02', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:10:47', '2025-06-16 05:10:47', 1, NULL), +(21, '2025-06-04', 1, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(22, '2025-06-04', 3, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(23, '2025-06-04', 5, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(24, '2025-06-04', 7, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(25, '2025-06-04', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(26, '2025-06-04', 10, 4, 3, 1, NULL, 8.00, '2025-06-16 05:11:37', '2025-06-16 05:11:37', 1, NULL), +(27, '2025-06-04', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(28, '2025-06-04', 6, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(29, '2025-06-04', 8, 3, 2, 1, NULL, 8.00, '2025-06-16 05:12:07', '2025-06-16 05:12:07', 1, NULL), +(30, '2025-06-05', 1, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(31, '2025-06-05', 3, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(32, '2025-06-05', 4, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(33, '2025-06-05', 7, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(34, '2025-06-05', 10, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(35, '2025-06-05', 9, 4, 3, 2, 1, 8.00, '2025-06-16 05:12:57', '2025-06-16 05:12:57', 1, NULL), +(36, '2025-06-05', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(37, '2025-06-05', 5, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(38, '2025-06-05', 6, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(39, '2025-06-05', 8, 3, 2, 1, NULL, 8.00, '2025-06-16 05:13:56', '2025-06-16 05:13:56', 1, NULL), +(40, '2025-06-16', 5, 3, 2, 1, NULL, 8.00, '2025-06-16 06:12:01', '2025-06-16 06:12:01', 5, NULL), +(43, '2025-06-16', 2, 3, 2, 1, NULL, 8.00, '2025-06-16 06:12:01', '2025-06-16 06:12:01', 5, NULL), +(44, '2025-06-16', 6, 3, 2, 2, 4, 4.00, '2025-06-16 06:13:02', '2025-06-16 06:13:02', 5, NULL), +(45, '2025-06-16', 6, 3, 2, 1, NULL, 4.00, '2025-06-16 06:13:50', '2025-06-16 06:13:50', 5, NULL), +(46, '2025-06-16', 8, 3, 2, 2, 4, 4.00, '2025-06-16 06:15:22', '2025-06-16 06:15:22', 5, NULL), +(47, '2025-06-16', 8, 3, 2, 1, NULL, 4.00, '2025-06-16 06:15:22', '2025-06-16 06:15:22', 5, NULL), +(48, '2025-06-16', 4, 4, 3, 2, 1, 8.00, '2025-06-16 06:46:44', '2025-06-16 06:46:44', 3, NULL), +(50, '2025-06-16', 1, 4, 3, 2, 1, 8.00, '2025-06-16 06:46:44', '2025-06-16 06:46:44', 3, NULL), +(51, '2025-06-16', 9, 4, 3, 1, NULL, 8.00, '2025-06-16 06:48:29', '2025-06-16 06:48:29', 3, NULL), +(52, '2025-06-16', 10, 4, 3, 1, NULL, 6.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(53, '2025-06-16', 10, 4, 3, 2, 1, 2.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(54, '2025-06-16', 3, 4, 3, 1, NULL, 6.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(55, '2025-06-16', 3, 4, 3, 2, 1, 2.00, '2025-06-16 06:50:09', '2025-06-16 06:50:09', 6, NULL), +(56, '2025-06-17', 2, 3, 2, 1, NULL, 8.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(57, '2025-06-17', 2, 3, 2, 1, NULL, 2.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(58, '2025-06-17', 5, 3, 2, 1, NULL, 8.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(59, '2025-06-17', 5, 3, 2, 1, NULL, 2.00, '2025-06-17 08:23:41', '2025-06-17 08:23:41', 5, NULL), +(60, '2025-06-17', 6, 3, 2, 1, NULL, 8.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(61, '2025-06-17', 6, 3, 2, 2, 4, 2.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(62, '2025-06-17', 8, 3, 2, 1, NULL, 8.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(63, '2025-06-17', 8, 3, 2, 2, 4, 2.00, '2025-06-17 08:24:33', '2025-06-17 08:24:33', 5, NULL), +(65, '2025-06-17', 9, 4, 3, 2, 1, 4.00, '2025-06-17 08:25:24', '2025-06-17 08:25:24', 3, NULL), +(66, '2025-06-17', 1, 4, 3, 2, 1, 4.00, '2025-06-17 08:27:06', '2025-06-17 08:27:06', 3, NULL), +(67, '2025-06-17', 4, 4, 3, 2, 1, 4.00, '2025-06-17 08:27:06', '2025-06-17 08:27:06', 3, NULL), +(68, '2025-06-17', 1, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(69, '2025-06-17', 9, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(70, '2025-06-17', 4, 4, 3, 1, NULL, 4.00, '2025-06-17 08:31:06', '2025-06-17 08:31:06', 3, NULL), +(71, '2025-06-17', 9, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(72, '2025-06-17', 4, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(73, '2025-06-17', 1, 4, 3, 1, NULL, 2.00, '2025-06-17 08:33:06', '2025-06-17 08:33:06', 3, NULL), +(74, '2025-06-17', 10, 4, 3, 1, NULL, 8.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(75, '2025-06-17', 10, 4, 3, 2, 1, 2.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(76, '2025-06-17', 3, 4, 3, 1, NULL, 8.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(77, '2025-06-17', 3, 4, 3, 2, 1, 2.00, '2025-06-17 08:34:11', '2025-06-17 08:34:11', 6, NULL), +(78, '2025-06-18', 6, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(79, '2025-06-18', 2, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(80, '2025-06-18', 8, 3, 2, 1, NULL, 8.00, '2025-06-18 08:40:27', '2025-06-18 08:40:27', 5, NULL), +(81, '2025-06-18', 2, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:02', '2025-06-18 08:41:02', 5, NULL), +(82, '2025-06-18', 6, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:03', '2025-06-18 08:41:03', 5, NULL), +(83, '2025-06-18', 8, 3, 2, 1, NULL, 2.00, '2025-06-18 08:41:03', '2025-06-18 08:41:03', 5, NULL), +(84, '2025-06-18', 5, 4, 3, 1, NULL, 8.00, '2025-06-18 08:41:45', '2025-06-18 08:41:45', 5, NULL), +(85, '2025-06-18', 5, 4, 3, 1, NULL, 2.00, '2025-06-18 08:41:45', '2025-06-18 08:41:45', 5, NULL), +(86, '2025-06-18', 10, 4, 3, 1, NULL, 9.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(87, '2025-06-18', 10, 4, 3, 2, 1, 1.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(88, '2025-06-18', 3, 4, 3, 1, NULL, 9.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(89, '2025-06-18', 3, 4, 3, 2, 1, 1.00, '2025-06-18 08:47:55', '2025-06-18 08:47:55', 6, NULL), +(90, '2025-06-18', 4, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(91, '2025-06-18', 4, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(92, '2025-06-18', 9, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(93, '2025-06-18', 9, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(94, '2025-06-18', 1, 4, 3, 2, 1, 4.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(95, '2025-06-18', 1, 4, 3, 1, NULL, 6.00, '2025-06-18 08:50:19', '2025-06-18 08:50:19', 3, NULL), +(96, '2025-06-18', 7, 4, 3, 2, 1, 4.00, '2025-06-18 09:00:17', '2025-06-18 09:00:17', 3, NULL), +(97, '2025-06-18', 7, 4, 3, 1, NULL, 6.00, '2025-06-18 09:00:17', '2025-06-18 09:00:17', 3, NULL), +(98, '2025-06-19', 8, 3, 2, 1, NULL, 8.00, '2025-06-19 06:37:59', '2025-06-19 06:37:59', 5, NULL), +(99, '2025-06-19', 2, 3, 2, 1, NULL, 8.00, '2025-06-19 06:37:59', '2025-06-19 06:37:59', 5, NULL), +(100, '2025-06-19', 10, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(101, '2025-06-19', 3, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(102, '2025-06-19', 5, 4, 3, 1, NULL, 8.00, '2025-06-19 06:59:36', '2025-06-19 06:59:36', 6, NULL), +(103, '2025-06-19', 9, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(104, '2025-06-19', 9, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(105, '2025-06-19', 4, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(106, '2025-06-19', 4, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(107, '2025-06-19', 1, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(108, '2025-06-19', 1, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(109, '2025-06-19', 7, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(110, '2025-06-19', 7, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(111, '2025-06-19', 6, 4, 3, 1, NULL, 6.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(112, '2025-06-19', 6, 4, 3, 2, 1, 2.00, '2025-06-19 07:01:02', '2025-06-19 07:01:02', 3, NULL), +(113, '2025-06-20', 9, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(114, '2025-06-20', 9, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(115, '2025-06-20', 4, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(116, '2025-06-20', 4, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(117, '2025-06-20', 7, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(118, '2025-06-20', 7, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:01', '2025-06-20 06:44:01', 3, NULL), +(119, '2025-06-20', 6, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(120, '2025-06-20', 6, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(121, '2025-06-20', 1, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(122, '2025-06-20', 1, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(123, '2025-06-20', 5, 4, 3, 2, 1, 2.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(124, '2025-06-20', 5, 4, 3, 1, NULL, 6.00, '2025-06-20 06:44:02', '2025-06-20 06:44:02', 3, NULL), +(125, '2025-06-20', 10, 4, 3, 1, NULL, 8.00, '2025-06-20 06:45:30', '2025-06-20 06:45:30', 6, NULL), +(126, '2025-06-20', 3, 4, 3, 1, NULL, 8.00, '2025-06-20 06:45:31', '2025-06-20 06:45:31', 6, NULL), +(127, '2025-06-23', 10, 4, 3, 1, NULL, 8.00, '2025-06-23 06:42:58', '2025-06-23 06:42:58', 6, NULL), +(128, '2025-06-23', 3, 4, 3, 1, NULL, 8.00, '2025-06-23 06:42:58', '2025-06-23 06:42:58', 6, NULL), +(129, '2025-06-23', 5, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(130, '2025-06-23', 5, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(131, '2025-06-23', 1, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(132, '2025-06-23', 1, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(133, '2025-06-23', 9, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(134, '2025-06-23', 9, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(135, '2025-06-23', 4, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(136, '2025-06-23', 4, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(137, '2025-06-23', 7, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(138, '2025-06-23', 7, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(139, '2025-06-23', 6, 4, 3, 2, 1, 2.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(140, '2025-06-23', 6, 4, 3, 1, NULL, 6.00, '2025-06-23 06:51:28', '2025-06-23 06:51:28', 3, NULL), +(141, '2025-06-24', 10, 4, 3, 1, NULL, 12.00, '2025-06-24 11:10:32', '2025-06-24 11:10:32', 6, NULL), +(142, '2025-06-24', 3, 4, 3, 1, NULL, 12.00, '2025-06-24 11:10:32', '2025-06-24 11:10:32', 6, NULL), +(143, '2025-06-24', 9, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(144, '2025-06-24', 9, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(145, '2025-06-24', 5, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(146, '2025-06-24', 5, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(147, '2025-06-24', 4, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(148, '2025-06-24', 4, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(149, '2025-06-24', 7, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(150, '2025-06-24', 7, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(151, '2025-06-24', 6, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(152, '2025-06-24', 6, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(153, '2025-06-24', 1, 4, 3, 2, 1, 2.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(154, '2025-06-24', 1, 4, 3, 1, NULL, 10.00, '2025-06-24 11:11:00', '2025-06-24 11:11:00', 3, NULL), +(155, '2025-06-24', 8, 3, 2, 1, NULL, 8.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(156, '2025-06-24', 8, 3, 2, 1, NULL, 4.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(157, '2025-06-24', 2, 3, 2, 1, NULL, 8.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(158, '2025-06-24', 2, 3, 2, 1, NULL, 4.00, '2025-06-24 11:11:05', '2025-06-24 11:11:05', 5, NULL), +(159, '2025-06-25', 2, 3, 2, 1, NULL, 8.00, '2025-06-25 11:08:04', '2025-06-25 11:08:04', 5, NULL), +(160, '2025-06-25', 2, 3, 2, 1, NULL, 4.00, '2025-06-25 11:08:04', '2025-06-25 11:08:04', 5, NULL), +(161, '2025-06-25', 8, 3, 2, 1, NULL, 8.00, '2025-06-25 11:08:05', '2025-06-25 11:08:05', 5, NULL), +(162, '2025-06-25', 8, 3, 2, 1, NULL, 4.00, '2025-06-25 11:08:05', '2025-06-25 11:08:05', 5, NULL), +(163, '2025-06-25', 10, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(164, '2025-06-25', 9, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(165, '2025-06-25', 3, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(166, '2025-06-25', 6, 4, 3, 1, NULL, 12.00, '2025-06-25 11:11:30', '2025-06-25 11:11:30', 6, NULL), +(167, '2025-06-26', 10, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(168, '2025-06-26', 5, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(169, '2025-06-26', 7, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(170, '2025-06-26', 1, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(171, '2025-06-26', 4, 4, 3, 1, NULL, 12.00, '2025-06-26 10:29:38', '2025-06-26 10:29:38', 3, NULL), +(172, '2025-06-26', 8, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:31', '2025-06-26 11:11:31', 5, NULL), +(173, '2025-06-26', 8, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:31', '2025-06-26 11:11:31', 5, NULL), +(174, '2025-06-26', 2, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(175, '2025-06-26', 2, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(176, '2025-06-26', 9, 3, 2, 1, NULL, 8.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(177, '2025-06-26', 9, 3, 2, 1, NULL, 4.00, '2025-06-26 11:11:32', '2025-06-26 11:11:32', 5, NULL), +(178, '2025-06-26', 3, 3, 2, 1, NULL, 12.00, '2025-06-26 11:19:34', '2025-06-26 11:19:34', 6, NULL), +(179, '2025-06-26', 6, 3, 2, 1, NULL, 12.00, '2025-06-26 11:19:34', '2025-06-26 11:19:34', 6, NULL), +(182, '2025-06-27', 2, 3, 2, 1, NULL, 4.00, '2025-06-27 01:54:40', '2025-06-27 01:54:40', 5, NULL), +(183, '2025-06-27', 9, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(184, '2025-06-27', 10, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(185, '2025-06-27', 7, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(186, '2025-06-27', 5, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(187, '2025-06-27', 4, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(188, '2025-06-27', 1, 4, 3, 1, NULL, 8.00, '2025-06-27 06:47:43', '2025-06-27 06:47:43', 3, NULL), +(189, '2025-06-27', 3, 3, 2, 1, NULL, 8.00, '2025-06-27 06:49:08', '2025-06-27 06:49:08', 6, NULL), +(191, '2025-06-27', 6, 3, 2, 1, NULL, 4.00, '2025-06-27 06:58:46', '2025-06-27 06:58:46', 6, NULL), +(192, '2025-06-27', 8, 3, 2, 1, NULL, 6.00, '2025-06-27 07:00:10', '2025-06-27 07:00:10', 5, NULL), +(193, '2025-06-30', 6, 3, 2, 2, 4, 2.00, '2025-07-05 01:37:29', '2025-07-05 01:37:29', 3, NULL), +(194, '2025-06-30', 6, 3, 2, 1, NULL, 2.00, '2025-07-05 01:37:29', '2025-07-07 04:15:25', 3, 3), +(195, '2025-06-30', 2, 3, 2, 1, NULL, 4.00, '2025-07-05 01:38:19', '2025-07-07 04:15:40', 3, 3), +(196, '2025-06-30', 3, 3, 2, 1, NULL, 8.00, '2025-07-05 01:38:19', '2025-07-05 01:38:19', 3, NULL), +(197, '2025-06-30', 8, 3, 2, 1, NULL, 6.00, '2025-07-05 01:38:19', '2025-07-07 04:15:02', 3, 3), +(198, '2025-07-01', 3, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(199, '2025-07-01', 2, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(200, '2025-07-01', 6, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(201, '2025-07-01', 8, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(202, '2025-07-01', 10, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(203, '2025-07-01', 9, 3, 2, 1, NULL, 10.00, '2025-07-05 01:39:21', '2025-07-05 01:39:21', 3, NULL), +(204, '2025-07-01', 2, 3, 2, 1, NULL, 2.00, '2025-07-05 01:39:48', '2025-07-05 01:42:08', 3, 3), +(205, '2025-07-01', 3, 3, 2, 1, NULL, 2.00, '2025-07-05 01:39:48', '2025-07-05 01:42:02', 3, 3), +(206, '2025-07-01', 6, 3, 2, 1, NULL, 2.00, '2025-07-05 01:39:48', '2025-07-05 01:41:56', 3, 3), +(207, '2025-07-01', 8, 3, 2, 1, NULL, 2.00, '2025-07-05 01:39:48', '2025-07-05 01:41:48', 3, 3), +(208, '2025-07-01', 9, 3, 2, 2, 4, 2.00, '2025-07-05 01:40:10', '2025-07-05 01:40:10', 3, NULL), +(209, '2025-07-01', 10, 3, 2, 2, 4, 2.00, '2025-07-05 01:40:10', '2025-07-05 01:40:10', 3, NULL), +(210, '2025-07-01', 7, 4, 3, 1, NULL, 5.00, '2025-07-05 01:42:57', '2025-07-05 01:42:57', 3, NULL), +(211, '2025-07-01', 7, 4, 3, 2, 2, 3.00, '2025-07-05 01:42:57', '2025-07-05 01:42:57', 3, NULL), +(212, '2025-07-01', 5, 4, 3, 1, NULL, 8.00, '2025-07-05 01:42:57', '2025-07-07 04:21:24', 3, 3), +(213, '2025-07-01', 5, 4, 3, 2, 2, 4.00, '2025-07-05 01:42:57', '2025-07-07 04:21:10', 3, 3), +(214, '2025-07-01', 4, 4, 3, 1, NULL, 8.00, '2025-07-05 01:42:57', '2025-07-07 04:21:41', 3, 3), +(215, '2025-07-01', 4, 4, 3, 2, 2, 4.00, '2025-07-05 01:42:57', '2025-07-07 04:21:32', 3, 3), +(216, '2025-07-01', 1, 4, 3, 1, NULL, 5.00, '2025-07-05 01:42:57', '2025-07-05 01:42:57', 3, NULL), +(217, '2025-07-01', 1, 4, 3, 2, 2, 3.00, '2025-07-05 01:42:57', '2025-07-05 01:42:57', 3, NULL), +(218, '2025-07-02', 2, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(219, '2025-07-02', 3, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(220, '2025-07-02', 10, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(221, '2025-07-02', 9, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(222, '2025-07-02', 8, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(223, '2025-07-02', 6, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(224, '2025-07-02', 7, 3, 2, 1, NULL, 10.00, '2025-07-05 01:43:36', '2025-07-05 01:43:36', 3, NULL), +(225, '2025-07-02', 5, 4, 3, 2, 2, 4.00, '2025-07-05 01:44:11', '2025-07-05 01:44:11', 3, NULL), +(226, '2025-07-02', 5, 4, 3, 1, NULL, 6.00, '2025-07-05 01:44:11', '2025-07-05 01:44:54', 3, 3), +(227, '2025-07-02', 4, 4, 3, 2, 2, 4.00, '2025-07-05 01:44:11', '2025-07-05 01:44:11', 3, NULL), +(228, '2025-07-02', 4, 4, 3, 1, NULL, 6.00, '2025-07-05 01:44:11', '2025-07-05 01:44:59', 3, 3), +(229, '2025-07-02', 1, 4, 3, 2, 2, 4.00, '2025-07-05 01:44:11', '2025-07-05 01:44:11', 3, NULL), +(230, '2025-07-02', 1, 4, 3, 1, NULL, 6.00, '2025-07-05 01:44:11', '2025-07-05 01:45:05', 3, 3), +(231, '2025-07-03', 2, 3, 2, 1, NULL, 10.00, '2025-07-05 01:45:44', '2025-07-05 01:45:44', 3, NULL), +(232, '2025-07-03', 6, 3, 2, 1, NULL, 10.00, '2025-07-05 01:45:45', '2025-07-05 01:45:45', 3, NULL), +(233, '2025-07-03', 9, 3, 2, 1, NULL, 10.00, '2025-07-05 01:45:45', '2025-07-05 01:45:45', 3, NULL), +(234, '2025-07-03', 8, 3, 2, 1, NULL, 10.00, '2025-07-05 01:45:45', '2025-07-05 01:45:45', 3, NULL), +(235, '2025-07-03', 7, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:07', '2025-07-05 01:46:07', 3, NULL), +(236, '2025-07-03', 1, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:07', '2025-07-05 01:46:07', 3, NULL), +(237, '2025-07-03', 3, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:08', '2025-07-05 01:46:08', 3, NULL), +(238, '2025-07-03', 4, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:08', '2025-07-05 01:46:08', 3, NULL), +(239, '2025-07-03', 5, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:08', '2025-07-05 01:46:08', 3, NULL), +(240, '2025-07-03', 10, 4, 3, 1, NULL, 10.00, '2025-07-05 01:46:08', '2025-07-05 01:46:08', 3, NULL), +(241, '2025-07-04', 10, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(242, '2025-07-04', 10, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(243, '2025-07-04', 5, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(244, '2025-07-04', 5, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(245, '2025-07-04', 4, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(246, '2025-07-04', 4, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(247, '2025-07-04', 9, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(248, '2025-07-04', 9, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(249, '2025-07-04', 8, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(250, '2025-07-04', 8, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(251, '2025-07-04', 3, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(252, '2025-07-04', 3, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(253, '2025-07-04', 2, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(254, '2025-07-04', 2, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(255, '2025-07-04', 7, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(256, '2025-07-04', 7, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(257, '2025-07-04', 6, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(258, '2025-07-04', 6, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(259, '2025-07-04', 1, 4, 3, 2, 2, 2.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(260, '2025-07-04', 1, 4, 3, 1, NULL, 6.00, '2025-07-05 01:51:47', '2025-07-05 01:51:47', 3, NULL), +(261, '2025-07-05', 8, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:38', '2025-07-05 05:36:38', 5, NULL), +(262, '2025-07-05', 5, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:38', '2025-07-05 05:36:38', 5, NULL), +(263, '2025-07-05', 4, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:39', '2025-07-05 05:36:39', 5, NULL), +(264, '2025-07-05', 3, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:39', '2025-07-05 05:36:39', 5, NULL), +(265, '2025-07-05', 2, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:39', '2025-07-05 05:36:39', 5, NULL), +(266, '2025-07-05', 1, 4, 2, 1, NULL, 8.00, '2025-07-05 05:36:39', '2025-07-05 05:36:39', 5, NULL), +(267, '2025-07-06', 10, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:08', 5, 3), +(268, '2025-07-06', 9, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:16', 5, 3), +(269, '2025-07-06', 7, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:22', 5, 3), +(270, '2025-07-06', 6, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:27', 5, 3), +(271, '2025-07-06', 4, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:33', 5, 3), +(272, '2025-07-06', 3, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:39', 5, 3), +(273, '2025-07-06', 2, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:44', 5, 3), +(274, '2025-07-06', 1, 4, 3, 1, NULL, 8.00, '2025-07-06 05:34:32', '2025-07-06 05:46:49', 5, 3), +(275, '2025-07-07', 10, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(276, '2025-07-07', 9, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(277, '2025-07-07', 8, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(278, '2025-07-07', 7, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(279, '2025-07-07', 3, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(280, '2025-07-07', 4, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(281, '2025-07-07', 5, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(282, '2025-07-07', 6, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(283, '2025-07-07', 2, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(284, '2025-07-07', 1, 4, 3, 1, NULL, 8.00, '2025-07-07 06:49:31', '2025-07-07 06:49:31', 6, NULL), +(285, '2025-07-08', 10, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:57', '2025-07-08 06:36:57', 3, NULL), +(286, '2025-07-08', 9, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(287, '2025-07-08', 8, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(288, '2025-07-08', 7, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(289, '2025-07-08', 6, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(290, '2025-07-08', 1, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(291, '2025-07-08', 2, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(292, '2025-07-08', 3, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(293, '2025-07-08', 5, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(294, '2025-07-08', 4, 4, 3, 1, NULL, 8.00, '2025-07-08 06:36:58', '2025-07-08 06:36:58', 3, NULL), +(295, '2025-07-09', 10, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:40', '2025-07-09 22:08:40', 5, NULL), +(296, '2025-07-09', 9, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:40', '2025-07-09 22:08:40', 5, NULL), +(297, '2025-07-09', 8, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:40', '2025-07-09 22:08:40', 5, NULL), +(298, '2025-07-09', 7, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:41', '2025-07-09 22:08:41', 5, NULL), +(299, '2025-07-09', 6, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:41', '2025-07-09 22:08:41', 5, NULL), +(300, '2025-07-09', 2, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:41', '2025-07-09 22:08:41', 5, NULL), +(301, '2025-07-09', 3, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:42', '2025-07-09 22:08:42', 5, NULL), +(302, '2025-07-09', 4, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:42', '2025-07-09 22:08:42', 5, NULL), +(303, '2025-07-09', 5, 4, 3, 1, NULL, 8.00, '2025-07-09 22:08:42', '2025-07-09 22:08:42', 5, NULL), +(304, '2025-07-09', 1, 4, 3, 1, NULL, 4.00, '2025-07-09 22:09:10', '2025-07-09 22:09:10', 5, NULL), +(305, '2025-07-10', 9, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:58', '2025-07-10 06:33:58', 3, NULL), +(306, '2025-07-10', 8, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:58', '2025-07-10 06:33:58', 3, NULL), +(307, '2025-07-10', 5, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:58', '2025-07-10 06:33:58', 3, NULL), +(308, '2025-07-10', 6, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(309, '2025-07-10', 2, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(310, '2025-07-10', 3, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(311, '2025-07-10', 4, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(312, '2025-07-10', 1, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(313, '2025-07-10', 7, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(314, '2025-07-10', 10, 4, 3, 1, NULL, 8.00, '2025-07-10 06:33:59', '2025-07-10 06:33:59', 3, NULL), +(315, '2025-07-12', 9, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(316, '2025-07-12', 8, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(317, '2025-07-12', 6, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(318, '2025-07-12', 5, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(319, '2025-07-12', 4, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(320, '2025-07-12', 2, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(321, '2025-07-12', 1, 4, 3, 1, NULL, 8.00, '2025-07-12 05:41:30', '2025-07-12 05:41:30', 3, NULL), +(322, '2025-07-14', 8, 4, 3, 1, NULL, 6.00, '2025-07-14 06:46:30', '2025-07-14 06:46:30', 3, NULL), +(323, '2025-07-14', 10, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(324, '2025-07-14', 9, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(325, '2025-07-14', 7, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(326, '2025-07-14', 6, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(327, '2025-07-14', 1, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(328, '2025-07-14', 2, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(329, '2025-07-14', 3, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(330, '2025-07-14', 4, 4, 3, 1, NULL, 8.00, '2025-07-14 06:46:57', '2025-07-14 06:46:57', 3, NULL), +(331, '2025-07-15', 3, 3, 2, 1, NULL, 8.00, '2025-07-15 05:57:06', '2025-07-15 05:57:06', 5, NULL), +(332, '2025-07-15', 9, 3, 2, 1, NULL, 8.00, '2025-07-15 05:57:06', '2025-07-15 05:57:06', 5, NULL), +(333, '2025-07-15', 5, 3, 2, 2, 4, 4.00, '2025-07-15 05:57:47', '2025-07-15 05:57:47', 5, NULL), +(334, '2025-07-15', 5, 4, 3, 1, NULL, 4.00, '2025-07-15 05:57:47', '2025-07-15 05:57:47', 5, NULL), +(335, '2025-07-15', 10, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(336, '2025-07-15', 8, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(337, '2025-07-15', 7, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(338, '2025-07-15', 6, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(339, '2025-07-15', 2, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(340, '2025-07-15', 1, 4, 3, 1, NULL, 8.00, '2025-07-15 05:58:19', '2025-07-15 05:58:19', 5, NULL), +(341, '2025-07-14', 5, 4, 3, 1, NULL, 8.00, '2025-07-15 06:57:26', '2025-07-15 06:57:26', 3, NULL), +(342, '2025-07-16', 4, 4, 3, 1, NULL, 2.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(343, '2025-07-16', 4, 3, 2, 1, NULL, 4.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(344, '2025-07-16', 4, 3, 2, 1, NULL, 2.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(345, '2025-07-16', 5, 4, 3, 1, NULL, 2.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(346, '2025-07-16', 5, 3, 2, 1, NULL, 4.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(347, '2025-07-16', 5, 3, 2, 1, NULL, 2.00, '2025-07-16 06:46:46', '2025-07-16 06:46:46', 5, NULL), +(348, '2025-07-16', 10, 4, 3, 1, NULL, 2.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(349, '2025-07-16', 10, 3, 2, 1, NULL, 4.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(350, '2025-07-16', 10, 3, 2, 1, NULL, 2.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(351, '2025-07-16', 6, 4, 3, 1, NULL, 2.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(352, '2025-07-16', 6, 3, 2, 1, NULL, 4.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(353, '2025-07-16', 6, 3, 2, 1, NULL, 2.00, '2025-07-16 06:47:53', '2025-07-16 06:47:53', 5, NULL), +(354, '2025-07-16', 9, 3, 2, 1, NULL, 8.00, '2025-07-16 06:48:32', '2025-07-16 06:48:32', 5, NULL), +(355, '2025-07-16', 8, 3, 2, 1, NULL, 8.00, '2025-07-16 06:48:32', '2025-07-16 06:48:32', 5, NULL), +(356, '2025-07-16', 3, 3, 2, 1, NULL, 8.00, '2025-07-16 06:48:32', '2025-07-16 06:48:32', 5, NULL), +(357, '2025-07-16', 2, 3, 2, 1, NULL, 8.00, '2025-07-16 06:48:32', '2025-07-16 06:48:32', 5, NULL), +(358, '2025-07-16', 1, 4, 3, 1, NULL, 8.00, '2025-07-16 06:51:31', '2025-07-16 06:51:31', 3, NULL), +(359, '2025-07-16', 7, 4, 3, 1, NULL, 8.00, '2025-07-16 06:51:31', '2025-07-16 06:51:31', 3, NULL), +(360, '2025-07-17', 1, 3, 3, 1, NULL, 8.00, '2025-07-17 06:45:22', '2025-07-17 06:45:22', 3, NULL), +(361, '2025-07-17', 5, 3, 2, 1, NULL, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(362, '2025-07-17', 5, 3, 2, 2, 4, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(363, '2025-07-17', 4, 3, 2, 1, NULL, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(364, '2025-07-17', 4, 3, 2, 2, 4, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(365, '2025-07-17', 2, 3, 2, 1, NULL, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(366, '2025-07-17', 2, 3, 2, 2, 4, 4.00, '2025-07-17 06:46:48', '2025-07-17 06:46:48', 5, NULL), +(367, '2025-07-17', 10, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(368, '2025-07-17', 9, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(369, '2025-07-17', 8, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(370, '2025-07-17', 7, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(371, '2025-07-17', 6, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(372, '2025-07-17', 3, 3, 2, 1, NULL, 8.00, '2025-07-17 06:47:19', '2025-07-17 06:47:19', 5, NULL), +(373, '2025-07-18', 7, 4, 3, 2, 1, 2.00, '2025-07-18 05:54:47', '2025-07-18 05:54:47', 3, NULL), +(374, '2025-07-18', 1, 4, 3, 2, 1, 2.00, '2025-07-18 05:54:48', '2025-07-18 05:54:48', 3, NULL), +(376, '2025-07-18', 5, 4, 3, 1, NULL, 2.00, '2025-07-18 05:58:33', '2025-07-18 05:58:33', 3, NULL), +(377, '2025-07-18', 5, 3, 2, 1, NULL, 6.00, '2025-07-18 05:58:33', '2025-07-18 05:58:33', 3, NULL), +(378, '2025-07-18', 7, 3, 2, 1, NULL, 6.00, '2025-07-18 05:59:42', '2025-07-18 05:59:42', 3, NULL), +(379, '2025-07-18', 1, 3, 3, 1, NULL, 6.00, '2025-07-18 06:00:15', '2025-07-18 06:00:15', 3, NULL), +(380, '2025-07-18', 10, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(381, '2025-07-18', 9, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(382, '2025-07-18', 8, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(383, '2025-07-18', 6, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(384, '2025-07-18', 4, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(385, '2025-07-18', 3, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(386, '2025-07-18', 2, 3, 2, 1, NULL, 8.00, '2025-07-18 06:36:13', '2025-07-18 06:36:13', 5, NULL), +(387, '2025-07-21', 5, 4, 3, 2, 1, 4.00, '2025-07-21 06:40:08', '2025-07-21 06:40:08', 5, NULL), +(388, '2025-07-21', 5, 3, 2, 1, NULL, 4.00, '2025-07-21 06:40:08', '2025-07-21 06:40:08', 5, NULL), +(389, '2025-07-21', 4, 4, 3, 2, 1, 4.00, '2025-07-21 06:40:08', '2025-07-21 06:40:08', 5, NULL), +(390, '2025-07-21', 4, 3, 2, 1, NULL, 4.00, '2025-07-21 06:40:08', '2025-07-21 06:40:08', 5, NULL), +(391, '2025-07-21', 10, 3, 2, 1, NULL, 6.00, '2025-07-21 06:40:32', '2025-07-22 06:58:42', 5, 3), +(392, '2025-07-21', 9, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(393, '2025-07-21', 8, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(394, '2025-07-21', 7, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(395, '2025-07-21', 6, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(396, '2025-07-21', 3, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(397, '2025-07-21', 2, 3, 2, 1, NULL, 8.00, '2025-07-21 06:40:32', '2025-07-21 06:40:32', 5, NULL), +(398, '2025-07-21', 1, 3, 3, 1, NULL, 8.00, '2025-07-21 06:53:37', '2025-07-21 06:53:37', 3, NULL), +(399, '2025-07-22', 10, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:47', '2025-07-22 06:45:47', 5, NULL), +(400, '2025-07-22', 9, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(401, '2025-07-22', 8, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(402, '2025-07-22', 7, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(403, '2025-07-22', 6, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(404, '2025-07-22', 4, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(405, '2025-07-22', 3, 3, 2, 1, NULL, 8.00, '2025-07-22 06:45:48', '2025-07-22 06:45:48', 5, NULL), +(406, '2025-07-22', 2, 4, 3, 2, 1, 8.00, '2025-07-22 06:46:11', '2025-07-22 06:46:11', 5, NULL), +(407, '2025-07-22', 5, 3, 3, 1, NULL, 8.00, '2025-07-22 06:46:11', '2025-07-22 06:46:11', 3, NULL), +(408, '2025-07-22', 1, 3, 3, 1, NULL, 8.00, '2025-07-22 06:46:11', '2025-07-22 06:46:11', 3, NULL), +(409, '2025-07-23', 4, 3, 3, 1, NULL, 8.00, '2025-07-23 06:45:06', '2025-07-23 06:45:06', 5, NULL), +(410, '2025-07-23', 5, 3, 3, 1, NULL, 8.00, '2025-07-23 06:45:28', '2025-07-23 06:45:28', 3, NULL), +(411, '2025-07-23', 1, 3, 3, 1, NULL, 8.00, '2025-07-23 06:45:28', '2025-07-23 06:45:28', 3, NULL), +(412, '2025-07-23', 10, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(413, '2025-07-23', 9, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(414, '2025-07-23', 7, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(415, '2025-07-23', 6, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(416, '2025-07-23', 3, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(417, '2025-07-23', 2, 3, 2, 1, NULL, 8.00, '2025-07-23 06:45:30', '2025-07-23 06:45:30', 5, NULL), +(418, '2025-07-24', 4, 3, 3, 1, NULL, 8.00, '2025-07-24 06:36:55', '2025-07-24 06:36:55', 5, NULL), +(419, '2025-07-24', 10, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(420, '2025-07-24', 9, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(421, '2025-07-24', 7, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(422, '2025-07-24', 6, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(423, '2025-07-24', 3, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(424, '2025-07-24', 2, 3, 2, 1, NULL, 8.00, '2025-07-24 06:37:18', '2025-07-24 06:37:18', 5, NULL), +(425, '2025-07-24', 5, 3, 3, 1, NULL, 8.00, '2025-07-24 06:47:04', '2025-07-24 06:47:04', 3, NULL), +(426, '2025-07-24', 1, 3, 3, 1, NULL, 8.00, '2025-07-24 06:47:04', '2025-07-24 06:47:04', 3, NULL), +(427, '2025-07-25', 4, 3, 3, 1, NULL, 8.00, '2025-07-25 06:44:23', '2025-07-25 06:44:23', 5, NULL), +(428, '2025-07-25', 10, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(429, '2025-07-25', 9, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(430, '2025-07-25', 8, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(431, '2025-07-25', 6, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(432, '2025-07-25', 3, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(433, '2025-07-25', 2, 3, 2, 1, NULL, 8.00, '2025-07-25 06:45:15', '2025-07-25 06:45:15', 5, NULL), +(434, '2025-07-25', 5, 4, 3, 1, NULL, 8.00, '2025-07-25 06:45:18', '2025-07-25 06:45:18', 3, NULL), +(435, '2025-07-25', 7, 4, 3, 1, NULL, 8.00, '2025-07-25 06:45:19', '2025-07-25 06:45:19', 3, NULL), +(436, '2025-07-25', 1, 4, 3, 1, NULL, 8.00, '2025-07-25 06:45:19', '2025-07-25 06:45:19', 3, NULL), +(437, '2025-07-28', 5, 3, 3, 1, NULL, 8.00, '2025-07-28 06:30:39', '2025-07-28 06:30:39', 3, NULL), +(438, '2025-07-28', 4, 3, 3, 1, NULL, 8.00, '2025-07-28 06:30:39', '2025-07-28 06:30:39', 3, NULL), +(439, '2025-07-28', 1, 3, 3, 1, NULL, 8.00, '2025-07-28 06:30:39', '2025-07-28 06:30:39', 3, NULL), +(440, '2025-07-28', 2, 5, 2, 1, NULL, 4.00, '2025-07-28 06:33:08', '2025-07-28 06:33:08', 5, NULL), +(441, '2025-07-28', 2, 3, 2, 1, NULL, 4.00, '2025-07-28 06:33:08', '2025-07-28 06:33:08', 5, NULL), +(442, '2025-07-28', 10, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(443, '2025-07-28', 9, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(444, '2025-07-28', 8, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(445, '2025-07-28', 7, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(446, '2025-07-28', 6, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(447, '2025-07-28', 3, 3, 2, 1, NULL, 8.00, '2025-07-28 06:33:34', '2025-07-28 06:33:34', 5, NULL), +(448, '2025-07-29', 5, 3, 3, 1, NULL, 8.00, '2025-07-29 06:39:13', '2025-07-29 06:39:13', 3, NULL), +(449, '2025-07-29', 4, 3, 3, 1, NULL, 8.00, '2025-07-29 06:39:13', '2025-07-29 06:39:13', 3, NULL), +(450, '2025-07-29', 1, 3, 3, 1, NULL, 8.00, '2025-07-29 06:39:13', '2025-07-29 06:39:13', 3, NULL), +(451, '2025-07-30', 5, 3, 3, 1, NULL, 8.00, '2025-07-30 06:50:30', '2025-07-30 06:50:30', 3, NULL), +(452, '2025-07-30', 4, 3, 3, 1, NULL, 8.00, '2025-07-30 06:50:30', '2025-07-30 06:50:30', 3, NULL), +(453, '2025-07-30', 1, 3, 3, 1, NULL, 8.00, '2025-07-30 06:50:30', '2025-07-30 06:50:30', 3, NULL), +(454, '2025-07-30', 10, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(455, '2025-07-30', 9, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(456, '2025-07-30', 8, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(457, '2025-07-30', 7, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(458, '2025-07-30', 6, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(459, '2025-07-30', 3, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(460, '2025-07-30', 2, 3, 2, 1, NULL, 8.00, '2025-07-30 06:52:16', '2025-07-30 06:52:16', 5, NULL), +(461, '2025-07-31', 1, 3, 3, 1, NULL, 4.00, '2025-07-31 06:42:56', '2025-07-31 06:42:56', 5, NULL), +(462, '2025-07-31', 4, 3, 3, 1, NULL, 4.00, '2025-07-31 06:43:32', '2025-07-31 06:43:32', 5, NULL), +(463, '2025-07-31', 4, 3, 2, 1, NULL, 4.00, '2025-07-31 06:43:32', '2025-07-31 06:43:32', 5, NULL), +(464, '2025-07-31', 5, 3, 3, 1, NULL, 4.00, '2025-07-31 06:43:32', '2025-07-31 06:43:32', 5, NULL), +(465, '2025-07-31', 5, 3, 2, 1, NULL, 4.00, '2025-07-31 06:43:32', '2025-07-31 06:43:32', 5, NULL), +(466, '2025-07-31', 10, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(467, '2025-07-31', 9, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(468, '2025-07-31', 8, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(469, '2025-07-31', 7, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(470, '2025-07-31', 6, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(471, '2025-07-31', 3, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(472, '2025-07-31', 2, 3, 2, 1, NULL, 8.00, '2025-07-31 06:44:00', '2025-07-31 06:44:00', 5, NULL), +(473, '2025-07-11', 10, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(474, '2025-07-11', 5, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(475, '2025-07-11', 4, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(476, '2025-07-11', 9, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(477, '2025-07-11', 8, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(478, '2025-07-11', 3, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(479, '2025-07-11', 2, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(480, '2025-07-11', 7, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(481, '2025-07-11', 6, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(482, '2025-07-11', 1, 3, 2, 1, NULL, 8.00, '2025-07-31 22:24:47', '2025-07-31 22:24:47', 3, NULL), +(483, '2025-08-01', 10, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(484, '2025-08-01', 9, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(485, '2025-08-01', 8, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(486, '2025-08-01', 7, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(487, '2025-08-01', 6, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(488, '2025-08-01', 3, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:47', '2025-08-01 04:57:47', 5, NULL), +(489, '2025-08-01', 2, 3, 2, 1, NULL, 8.00, '2025-08-01 04:57:48', '2025-08-01 04:57:48', 5, NULL), +(490, '2025-08-01', 4, 3, 3, 1, NULL, 4.00, '2025-08-01 05:02:28', '2025-08-01 05:02:28', 3, NULL), +(491, '2025-08-01', 4, 5, 1, 1, NULL, 4.00, '2025-08-01 05:02:28', '2025-08-01 05:02:28', 3, NULL), +(492, '2025-08-01', 5, 3, 3, 1, NULL, 4.00, '2025-08-01 05:02:28', '2025-08-01 05:02:28', 3, NULL), +(493, '2025-08-01', 5, 5, 1, 1, NULL, 4.00, '2025-08-01 05:02:28', '2025-08-01 05:02:28', 3, NULL), +(494, '2025-08-07', 9, 3, 2, 2, 4, 4.00, '2025-08-07 06:42:39', '2025-08-07 06:42:39', 5, NULL), +(495, '2025-08-07', 9, 3, 2, 1, NULL, 4.00, '2025-08-07 06:42:39', '2025-08-07 06:42:39', 5, NULL), +(496, '2025-08-07', 7, 3, 2, 2, 4, 4.00, '2025-08-07 06:42:39', '2025-08-07 06:42:39', 5, NULL), +(497, '2025-08-07', 7, 3, 2, 1, NULL, 4.00, '2025-08-07 06:42:39', '2025-08-07 06:42:39', 5, NULL), +(498, '2025-08-07', 10, 5, 2, 1, NULL, 8.00, '2025-08-07 06:43:14', '2025-08-07 06:43:14', 5, NULL), +(499, '2025-08-07', 4, 5, 2, 1, NULL, 8.00, '2025-08-07 06:43:15', '2025-08-07 06:43:15', 5, NULL), +(500, '2025-08-07', 2, 5, 2, 1, NULL, 8.00, '2025-08-07 06:43:15', '2025-08-07 06:43:15', 5, NULL), +(501, '2025-08-07', 6, 3, 2, 1, NULL, 8.00, '2025-08-07 06:43:39', '2025-08-07 06:43:39', 5, NULL), +(502, '2025-08-07', 3, 3, 2, 1, NULL, 8.00, '2025-08-07 06:43:39', '2025-08-07 06:43:39', 5, NULL), +(503, '2025-08-07', 8, 3, 2, 1, NULL, 8.00, '2025-08-07 06:43:39', '2025-08-07 06:43:39', 5, NULL), +(504, '2025-08-07', 1, 3, 3, 1, NULL, 8.00, '2025-08-07 06:43:52', '2025-08-07 06:43:52', 3, NULL), +(505, '2025-08-08', 1, 3, 3, 1, NULL, 8.00, '2025-08-08 06:45:20', '2025-08-08 06:45:20', 3, NULL), +(506, '2025-08-08', 10, 5, 2, 1, NULL, 8.00, '2025-08-08 06:58:42', '2025-08-08 06:58:42', 5, NULL), +(507, '2025-08-08', 2, 5, 2, 1, NULL, 8.00, '2025-08-08 06:58:42', '2025-08-08 06:58:42', 5, NULL), +(508, '2025-08-08', 9, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:18', '2025-08-08 06:59:18', 5, NULL), +(509, '2025-08-08', 8, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:19', '2025-08-08 06:59:19', 5, NULL), +(510, '2025-08-08', 3, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:19', '2025-08-08 06:59:19', 5, NULL), +(511, '2025-08-08', 4, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:19', '2025-08-08 06:59:19', 5, NULL), +(512, '2025-08-08', 6, 3, 2, 1, NULL, 8.00, '2025-08-08 06:59:19', '2025-08-08 06:59:19', 5, NULL), +(513, '2025-08-11', 1, 3, 3, 1, NULL, 8.00, '2025-08-11 06:27:37', '2025-08-11 06:27:37', 3, NULL), +(514, '2025-08-11', 1, 3, 3, 1, NULL, 8.00, '2025-08-11 06:27:37', '2025-08-11 06:27:37', 3, NULL), +(515, '2025-08-11', 10, 5, 2, 1, NULL, 8.00, '2025-08-11 06:46:23', '2025-08-11 06:46:23', 5, NULL), +(516, '2025-08-11', 2, 5, 2, 1, NULL, 8.00, '2025-08-11 06:46:23', '2025-08-11 06:46:23', 5, NULL), +(517, '2025-08-11', 8, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:49', '2025-08-11 06:46:49', 5, NULL), +(518, '2025-08-11', 7, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:49', '2025-08-11 06:46:49', 5, NULL), +(519, '2025-08-11', 6, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:50', '2025-08-11 06:46:50', 5, NULL), +(520, '2025-08-11', 5, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:50', '2025-08-11 06:46:50', 5, NULL), +(521, '2025-08-11', 4, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:50', '2025-08-11 06:46:50', 5, NULL), +(522, '2025-08-11', 3, 3, 2, 1, NULL, 8.00, '2025-08-11 06:46:50', '2025-08-11 06:46:50', 5, NULL), +(523, '2025-08-12', 10, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(524, '2025-08-12', 9, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(525, '2025-08-12', 8, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(526, '2025-08-12', 7, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(527, '2025-08-12', 5, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(528, '2025-08-12', 4, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(529, '2025-08-12', 3, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(530, '2025-08-12', 1, 3, 2, 1, NULL, 8.00, '2025-08-12 06:47:24', '2025-08-12 06:47:24', 3, NULL), +(531, '2025-08-13', 1, 3, 3, 1, NULL, 8.00, '2025-08-13 06:31:32', '2025-08-13 06:31:32', 3, NULL), +(532, '2025-08-13', 2, 3, 2, 1, NULL, 4.00, '2025-08-13 06:36:13', '2025-08-13 06:36:13', 5, NULL); +INSERT INTO `daily_work_reports` (`id`, `report_date`, `worker_id`, `project_id`, `work_type_id`, `work_status_id`, `error_type_id`, `work_hours`, `created_at`, `updated_at`, `created_by`, `updated_by`) VALUES +(533, '2025-08-13', 2, 5, 2, 1, NULL, 4.00, '2025-08-13 06:36:13', '2025-08-13 06:36:13', 5, NULL), +(534, '2025-08-13', 9, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(535, '2025-08-13', 8, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(536, '2025-08-13', 7, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(537, '2025-08-13', 6, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(538, '2025-08-13', 5, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(539, '2025-08-13', 4, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(540, '2025-08-13', 3, 3, 2, 1, NULL, 8.00, '2025-08-13 06:36:48', '2025-08-13 06:36:48', 5, NULL), +(541, '2025-08-13', 10, 5, 2, 1, NULL, 8.00, '2025-08-13 06:37:19', '2025-08-13 06:37:19', 5, NULL), +(542, '2025-08-14', 1, 3, 3, 2, 1, 4.00, '2025-08-14 06:35:27', '2025-08-14 06:35:27', 3, NULL), +(543, '2025-08-14', 1, 3, 3, 1, NULL, 4.00, '2025-08-14 06:35:27', '2025-08-14 06:35:27', 3, NULL), +(544, '2025-08-14', 10, 5, 2, 1, NULL, 4.00, '2025-08-14 06:39:03', '2025-08-14 06:39:03', 5, NULL), +(545, '2025-08-14', 10, 5, 3, 1, NULL, 4.00, '2025-08-14 06:39:03', '2025-08-14 06:39:03', 5, NULL), +(546, '2025-08-14', 2, 5, 2, 1, NULL, 2.00, '2025-08-14 06:39:44', '2025-08-14 06:39:44', 5, NULL), +(547, '2025-08-14', 2, 3, 2, 1, NULL, 6.00, '2025-08-14 06:39:44', '2025-08-14 06:39:44', 5, NULL), +(548, '2025-08-14', 9, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(549, '2025-08-14', 8, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(550, '2025-08-14', 7, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(551, '2025-08-14', 6, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(552, '2025-08-14', 5, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(553, '2025-08-14', 4, 3, 2, 1, NULL, 8.00, '2025-08-14 06:40:10', '2025-08-14 06:40:10', 5, NULL), +(554, '2025-08-18', 2, 3, 2, 1, NULL, 8.00, '2025-08-18 06:21:36', '2025-08-18 06:21:36', 5, NULL), +(555, '2025-08-18', 8, 3, 2, 1, NULL, 8.00, '2025-08-18 06:21:36', '2025-08-18 06:21:36', 5, NULL), +(556, '2025-08-18', 4, 3, 2, 1, NULL, 8.00, '2025-08-18 06:22:01', '2025-08-18 06:22:01', 5, NULL), +(557, '2025-08-18', 10, 5, 3, 1, NULL, 6.00, '2025-08-18 06:22:53', '2025-08-18 06:22:53', 5, NULL), +(558, '2025-08-18', 10, 3, 2, 1, NULL, 2.00, '2025-08-18 06:22:53', '2025-08-18 06:22:53', 5, NULL), +(559, '2025-08-18', 9, 3, 2, 1, NULL, 4.00, '2025-08-18 06:23:34', '2025-08-18 06:23:34', 5, NULL), +(560, '2025-08-18', 9, 3, 3, 1, NULL, 4.00, '2025-08-18 06:23:34', '2025-08-18 06:23:34', 5, NULL), +(561, '2025-08-18', 5, 3, 3, 2, 1, 4.00, '2025-08-18 06:41:24', '2025-08-18 06:41:24', 3, NULL), +(562, '2025-08-18', 1, 3, 3, 2, 1, 4.00, '2025-08-18 06:41:24', '2025-08-18 06:41:24', 3, NULL), +(563, '2025-08-18', 7, 3, 3, 2, 1, 4.00, '2025-08-18 06:41:24', '2025-08-18 06:41:24', 3, NULL), +(564, '2025-08-18', 7, 3, 3, 1, NULL, 4.00, '2025-08-18 06:43:10', '2025-08-18 06:43:10', 3, NULL), +(565, '2025-08-18', 5, 3, 3, 1, NULL, 4.00, '2025-08-18 06:43:10', '2025-08-18 06:43:10', 3, NULL), +(566, '2025-08-18', 1, 3, 3, 1, NULL, 4.00, '2025-08-18 06:43:10', '2025-08-18 06:43:10', 3, NULL), +(567, '2025-08-18', 6, 3, 3, 1, NULL, 8.00, '2025-08-18 06:43:35', '2025-08-18 06:43:35', 6, NULL), +(568, '2025-08-18', 3, 3, 3, 1, NULL, 8.00, '2025-08-18 06:43:35', '2025-08-18 06:43:35', 6, NULL), +(569, '2025-08-19', 1, 3, 3, 1, NULL, 6.00, '2025-08-19 08:02:49', '2025-08-19 08:02:49', 5, NULL), +(573, '2025-08-19', 9, 3, 3, 1, NULL, 10.00, '2025-08-19 08:03:30', '2025-08-19 08:03:30', 5, NULL), +(574, '2025-08-19', 10, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(575, '2025-08-19', 8, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(576, '2025-08-19', 5, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(577, '2025-08-19', 4, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(578, '2025-08-19', 2, 3, 2, 1, NULL, 10.00, '2025-08-19 08:04:05', '2025-08-19 08:04:05', 5, NULL), +(579, '2025-08-19', 3, 3, 3, 1, NULL, 10.00, '2025-08-19 08:36:51', '2025-08-19 08:36:51', 6, NULL), +(580, '2025-08-19', 7, 3, 3, 1, NULL, 10.00, '2025-08-19 08:36:51', '2025-08-19 08:36:51', 6, NULL), +(581, '2025-08-19', 6, 3, 3, 1, NULL, 10.00, '2025-08-19 08:36:51', '2025-08-19 08:36:51', 6, NULL), +(582, '2025-08-20', 2, 3, 2, 1, NULL, 8.00, '2025-08-20 06:19:36', '2025-08-20 06:19:36', 5, NULL), +(583, '2025-08-20', 5, 3, 1, 1, NULL, 2.00, '2025-08-20 06:21:28', '2025-08-20 06:21:28', 5, NULL), +(584, '2025-08-20', 5, 3, 2, 1, NULL, 6.00, '2025-08-20 06:21:28', '2025-08-20 06:21:28', 5, NULL), +(585, '2025-08-20', 4, 3, 1, 1, NULL, 2.00, '2025-08-20 06:21:28', '2025-08-20 06:21:28', 5, NULL), +(586, '2025-08-20', 4, 3, 2, 1, NULL, 6.00, '2025-08-20 06:21:28', '2025-08-20 06:21:28', 5, NULL), +(587, '2025-08-20', 6, 3, 3, 1, NULL, 4.00, '2025-08-20 06:43:46', '2025-08-20 06:43:46', 3, NULL), +(589, '2025-08-20', 9, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:23', '2025-08-20 06:44:23', 3, NULL), +(590, '2025-08-20', 8, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:23', '2025-08-20 06:44:23', 3, NULL), +(591, '2025-08-20', 7, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:24', '2025-08-20 06:44:24', 3, NULL), +(593, '2025-08-20', 1, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:24', '2025-08-20 06:44:24', 3, NULL), +(594, '2025-08-20', 10, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:26', '2025-08-20 06:44:26', 6, NULL), +(595, '2025-08-20', 3, 3, 3, 1, NULL, 8.00, '2025-08-20 06:44:26', '2025-08-20 06:44:26', 6, NULL), +(596, '2025-08-21', 7, 3, 3, 1, NULL, 8.00, '2025-08-21 06:30:36', '2025-08-21 06:30:36', 3, NULL), +(597, '2025-08-21', 1, 3, 3, 1, NULL, 8.00, '2025-08-21 06:30:36', '2025-08-21 06:30:36', 3, NULL), +(600, '2025-08-21', 10, 3, 3, 1, NULL, 8.00, '2025-08-21 07:51:23', '2025-08-21 07:51:23', 5, NULL), +(601, '2025-08-21', 10, 3, 3, 1, NULL, 2.00, '2025-08-21 07:51:23', '2025-08-21 07:51:23', 5, NULL), +(602, '2025-08-21', 9, 3, 3, 1, NULL, 8.00, '2025-08-21 07:51:23', '2025-08-21 07:51:23', 5, NULL), +(603, '2025-08-21', 9, 3, 3, 1, NULL, 2.00, '2025-08-21 07:51:23', '2025-08-21 07:51:23', 5, NULL), +(608, '2025-08-21', 2, 3, 2, 1, NULL, 8.00, '2025-08-21 07:54:46', '2025-08-21 07:54:46', 5, NULL), +(609, '2025-08-21', 2, 5, 2, 1, NULL, 2.00, '2025-08-21 07:54:46', '2025-08-21 07:54:46', 5, NULL), +(610, '2025-08-21', 8, 3, 3, 1, NULL, 4.00, '2025-08-21 07:55:25', '2025-08-21 07:55:25', 5, NULL), +(611, '2025-08-21', 8, 3, 2, 1, NULL, 6.00, '2025-08-21 07:55:25', '2025-08-21 07:55:25', 5, NULL), +(612, '2025-08-21', 6, 3, 3, 1, NULL, 10.00, '2025-08-21 08:24:50', '2025-08-21 08:24:50', 6, NULL), +(613, '2025-08-21', 3, 3, 3, 1, NULL, 10.00, '2025-08-21 08:24:50', '2025-08-21 08:24:50', 6, NULL), +(614, '2025-08-22', 2, 3, 2, 1, NULL, 8.00, '2025-08-22 06:21:15', '2025-08-22 06:21:15', 5, NULL), +(615, '2025-08-22', 8, 3, 2, 1, NULL, 4.00, '2025-08-22 06:23:12', '2025-08-22 06:23:12', 5, NULL), +(616, '2025-08-22', 8, 3, 3, 1, NULL, 4.00, '2025-08-22 06:23:12', '2025-08-22 06:23:12', 5, NULL), +(617, '2025-08-22', 5, 3, 3, 1, NULL, 8.00, '2025-08-22 06:23:55', '2025-08-22 06:23:55', 5, NULL), +(618, '2025-08-22', 6, 3, 2, 1, NULL, 4.00, '2025-08-22 06:27:43', '2025-08-22 06:27:43', 3, NULL), +(619, '2025-08-22', 10, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(620, '2025-08-22', 9, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(621, '2025-08-22', 7, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(622, '2025-08-22', 4, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(623, '2025-08-22', 3, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(624, '2025-08-22', 1, 3, 3, 1, NULL, 8.00, '2025-08-22 06:28:15', '2025-08-22 06:28:15', 3, NULL), +(625, '2025-08-23', 4, 3, 2, 1, NULL, 2.00, '2025-08-23 04:57:02', '2025-08-23 04:57:02', 5, NULL), +(626, '2025-08-23', 4, 3, 3, 1, NULL, 6.00, '2025-08-23 04:57:02', '2025-08-23 04:57:02', 5, NULL), +(627, '2025-08-23', 2, 3, 2, 1, NULL, 8.00, '2025-08-23 04:57:25', '2025-08-23 04:57:25', 5, NULL), +(628, '2025-08-23', 10, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(629, '2025-08-23', 9, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(630, '2025-08-23', 8, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(631, '2025-08-23', 6, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(632, '2025-08-23', 5, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(633, '2025-08-23', 3, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(634, '2025-08-23', 1, 3, 3, 1, NULL, 8.00, '2025-08-23 04:57:54', '2025-08-23 04:57:54', 5, NULL), +(635, '2025-08-25', 10, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(636, '2025-08-25', 9, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(637, '2025-08-25', 8, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(638, '2025-08-25', 7, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(640, '2025-08-25', 5, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(641, '2025-08-25', 4, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(643, '2025-08-25', 2, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(644, '2025-08-25', 1, 3, 3, 1, NULL, 8.00, '2025-08-25 06:48:34', '2025-08-25 06:48:34', 3, NULL), +(645, '2025-08-25', 6, 3, 3, 1, NULL, 8.00, '2025-08-25 06:49:16', '2025-08-25 06:49:16', 6, NULL), +(646, '2025-08-25', 3, 3, 3, 1, NULL, 8.00, '2025-08-25 06:49:17', '2025-08-25 06:49:17', 6, NULL), +(647, '2025-08-26', 4, 8, 3, 1, NULL, 8.00, '2025-08-26 07:28:03', '2025-08-26 07:28:03', 5, NULL), +(648, '2025-08-26', 4, 3, 3, 1, NULL, 2.00, '2025-08-26 07:28:03', '2025-08-26 07:28:03', 5, NULL), +(649, '2025-08-26', 2, 8, 3, 1, NULL, 10.00, '2025-08-26 07:28:35', '2025-08-26 07:28:35', 5, NULL), +(651, '2025-08-26', 9, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:02', '2025-08-26 07:29:02', 5, NULL), +(652, '2025-08-26', 8, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:02', '2025-08-26 07:29:02', 5, NULL), +(653, '2025-08-26', 7, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:02', '2025-08-26 07:29:02', 5, NULL), +(655, '2025-08-26', 5, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:02', '2025-08-26 07:29:02', 5, NULL), +(657, '2025-08-26', 1, 3, 3, 1, NULL, 10.00, '2025-08-26 07:29:03', '2025-08-26 07:29:03', 5, NULL), +(658, '2025-08-26', 6, 3, 3, 1, NULL, 10.00, '2025-08-26 08:22:12', '2025-08-26 08:22:12', 6, NULL), +(659, '2025-08-26', 10, 3, 3, 1, NULL, 10.00, '2025-08-26 08:22:12', '2025-08-26 08:22:12', 6, NULL), +(660, '2025-08-26', 3, 3, 3, 1, NULL, 10.00, '2025-08-26 08:22:12', '2025-08-26 08:22:12', 6, NULL), +(661, '2025-08-27', 10, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(662, '2025-08-27', 9, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(663, '2025-08-27', 7, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(664, '2025-08-27', 6, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(665, '2025-08-27', 5, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(666, '2025-08-27', 4, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(667, '2025-08-27', 3, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:47', '2025-08-27 06:44:47', 3, NULL), +(668, '2025-08-27', 1, 3, 3, 2, 5, 8.00, '2025-08-27 06:44:48', '2025-08-27 06:44:48', 3, NULL), +(669, '2025-08-27', 2, 3, 3, 2, 1, 2.00, '2025-08-27 06:45:32', '2025-08-27 06:45:32', 5, NULL), +(670, '2025-08-27', 2, 8, 2, 1, NULL, 6.00, '2025-08-27 06:45:32', '2025-08-27 06:45:32', 5, NULL), +(671, '2025-08-27', 8, 3, 3, 2, 1, 2.00, '2025-08-27 06:45:32', '2025-08-27 06:45:32', 5, NULL), +(672, '2025-08-27', 8, 8, 2, 1, NULL, 6.00, '2025-08-27 06:45:32', '2025-08-27 06:45:32', 5, NULL), +(673, '2025-08-28', 10, 3, 3, 1, NULL, 6.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(674, '2025-08-28', 10, 3, 3, 2, 1, 4.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(675, '2025-08-28', 5, 3, 3, 1, NULL, 6.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(676, '2025-08-28', 5, 3, 3, 2, 1, 4.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(677, '2025-08-28', 6, 3, 3, 1, NULL, 6.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(678, '2025-08-28', 6, 3, 3, 2, 1, 4.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(679, '2025-08-28', 3, 3, 3, 1, NULL, 6.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(680, '2025-08-28', 3, 3, 3, 2, 1, 4.00, '2025-08-28 08:31:42', '2025-08-28 08:31:42', 6, NULL), +(681, '2025-08-28', 4, 3, 3, 1, NULL, 4.00, '2025-08-28 08:37:46', '2025-08-28 08:37:46', 5, NULL), +(682, '2025-08-28', 4, 5, 3, 1, NULL, 4.00, '2025-08-28 08:37:46', '2025-08-28 08:37:46', 5, NULL), +(683, '2025-08-28', 8, 8, 2, 1, NULL, 4.00, '2025-08-28 08:38:15', '2025-08-28 08:38:15', 5, NULL), +(684, '2025-08-28', 8, 5, 3, 1, NULL, 4.00, '2025-08-28 08:38:15', '2025-08-28 08:38:15', 5, NULL), +(685, '2025-08-28', 2, 3, 3, 2, 1, 2.00, '2025-08-28 08:38:50', '2025-08-28 08:38:50', 5, NULL), +(686, '2025-08-28', 2, 5, 3, 1, NULL, 6.00, '2025-08-28 08:38:50', '2025-08-28 08:38:50', 5, NULL), +(687, '2025-08-28', 1, 3, 3, 2, 1, 8.00, '2025-08-28 08:39:24', '2025-08-28 08:39:24', 5, NULL), +(689, '2025-08-28', 9, 3, 3, 2, 4, 8.00, '2025-08-28 08:40:00', '2025-08-28 08:40:00', 5, NULL), +(690, '2025-08-28', 7, 3, 3, 2, 4, 8.00, '2025-08-28 08:40:00', '2025-08-28 08:40:00', 5, NULL), +(694, '2025-08-28', 4, 5, 3, 1, NULL, 2.00, '2025-08-28 08:44:56', '2025-08-28 08:44:56', 5, NULL), +(695, '2025-08-28', 8, 5, 3, 1, NULL, 2.00, '2025-08-28 08:44:56', '2025-08-28 08:44:56', 5, NULL), +(696, '2025-08-28', 2, 5, 3, 1, NULL, 2.00, '2025-08-28 08:44:56', '2025-08-28 08:44:56', 5, NULL), +(698, '2025-08-28', 9, 3, 3, 1, NULL, 2.00, '2025-08-28 08:45:19', '2025-08-28 08:45:19', 5, NULL), +(699, '2025-08-28', 7, 3, 3, 1, NULL, 2.00, '2025-08-28 08:45:19', '2025-08-28 08:45:19', 5, NULL), +(703, '2025-08-29', 10, 3, 3, 2, 5, 8.00, '2025-08-29 06:47:02', '2025-08-29 06:47:02', 3, NULL), +(704, '2025-08-29', 9, 3, 3, 2, 5, 8.00, '2025-08-29 06:47:02', '2025-08-29 06:47:02', 3, NULL), +(706, '2025-08-29', 7, 3, 3, 2, 5, 8.00, '2025-08-29 06:47:02', '2025-08-29 06:47:02', 3, NULL), +(710, '2025-08-29', 1, 3, 3, 2, 5, 8.00, '2025-08-29 06:47:02', '2025-08-29 06:47:02', 3, NULL), +(713, '2025-08-29', 5, 3, 3, 1, NULL, 6.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(714, '2025-08-29', 5, 3, 3, 2, 1, 2.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(715, '2025-08-29', 3, 3, 3, 1, NULL, 6.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(716, '2025-08-29', 3, 3, 3, 2, 1, 2.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(717, '2025-08-29', 6, 3, 3, 1, NULL, 6.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(718, '2025-08-29', 6, 3, 3, 2, 1, 2.00, '2025-08-29 06:47:35', '2025-08-29 06:47:35', 6, NULL), +(719, '2025-08-29', 8, 5, 3, 1, NULL, 8.00, '2025-08-29 21:55:56', '2025-08-29 21:55:56', 5, NULL), +(720, '2025-08-29', 4, 5, 3, 1, NULL, 8.00, '2025-08-29 21:55:56', '2025-08-29 21:55:56', 5, NULL), +(721, '2025-08-29', 2, 5, 3, 1, NULL, 8.00, '2025-08-29 21:55:56', '2025-08-29 21:55:56', 5, NULL), +(722, '2025-08-30', 2, 5, 3, 1, NULL, 8.00, '2025-08-30 05:12:03', '2025-08-30 05:12:03', 5, NULL), +(723, '2025-08-30', 8, 5, 3, 1, NULL, 8.00, '2025-08-30 05:12:03', '2025-08-30 05:12:03', 5, NULL), +(724, '2025-08-30', 4, 5, 3, 1, NULL, 8.00, '2025-08-30 05:12:03', '2025-08-30 05:12:03', 5, NULL), +(725, '2025-08-30', 10, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(726, '2025-08-30', 9, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(727, '2025-08-30', 7, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(728, '2025-08-30', 6, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(729, '2025-08-30', 5, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(730, '2025-08-30', 3, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(731, '2025-08-30', 1, 3, 3, 2, 1, 8.00, '2025-08-30 05:36:49', '2025-08-30 05:36:49', 3, NULL), +(732, '2025-09-01', 7, 3, 3, 1, NULL, 8.00, '2025-09-01 06:18:28', '2025-09-01 06:18:28', 3, NULL), +(733, '2025-09-01', 9, 3, 3, 1, NULL, 8.00, '2025-09-01 06:18:28', '2025-09-01 06:18:28', 3, NULL), +(734, '2025-09-01', 10, 3, 3, 2, 5, 4.00, '2025-09-01 06:19:11', '2025-09-01 06:19:11', 3, NULL), +(735, '2025-09-01', 3, 3, 3, 2, 5, 4.00, '2025-09-01 06:19:11', '2025-09-01 06:19:11', 3, NULL), +(736, '2025-09-01', 1, 3, 3, 2, 5, 4.00, '2025-09-01 06:19:11', '2025-09-01 06:19:11', 3, NULL), +(737, '2025-09-01', 10, 3, 3, 1, NULL, 4.00, '2025-09-01 06:19:35', '2025-09-01 06:19:35', 3, NULL), +(738, '2025-09-01', 3, 3, 3, 1, NULL, 4.00, '2025-09-01 06:19:35', '2025-09-01 06:19:35', 3, NULL), +(739, '2025-09-01', 1, 3, 3, 1, NULL, 4.00, '2025-09-01 06:19:35', '2025-09-01 06:19:35', 3, NULL), +(740, '2025-09-01', 5, 3, 3, 2, 1, 8.00, '2025-09-01 06:20:03', '2025-09-01 06:20:03', 3, NULL), +(741, '2025-08-21', 4, 3, 3, 1, NULL, 10.00, '2025-09-01 23:18:03', '2025-09-01 23:18:03', 3, NULL), +(742, '2025-08-21', 5, 3, 3, 1, NULL, 10.00, '2025-09-01 23:18:03', '2025-09-01 23:18:03', 3, NULL), +(745, '2025-09-02', 10, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(746, '2025-09-02', 9, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(747, '2025-09-02', 6, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(748, '2025-09-02', 5, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(749, '2025-09-02', 3, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(750, '2025-09-02', 1, 3, 3, 2, 1, 6.00, '2025-09-02 07:36:04', '2025-09-02 07:36:04', 3, NULL), +(751, '2025-09-02', 10, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(752, '2025-09-02', 9, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(753, '2025-09-02', 6, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(754, '2025-09-02', 5, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(755, '2025-09-02', 3, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(756, '2025-09-02', 1, 3, 3, 1, NULL, 4.00, '2025-09-02 07:36:31', '2025-09-02 07:36:31', 3, NULL), +(757, '2025-09-02', 8, 3, 3, 1, NULL, 10.00, '2025-09-02 07:37:19', '2025-09-02 07:37:19', 3, NULL), +(758, '2025-09-02', 7, 3, 3, 1, NULL, 10.00, '2025-09-02 07:37:19', '2025-09-02 07:37:19', 3, NULL), +(759, '2025-09-02', 2, 5, 3, 1, NULL, 8.00, '2025-09-02 08:16:14', '2025-09-02 08:16:14', 5, NULL), +(760, '2025-09-02', 2, 5, 3, 1, NULL, 2.00, '2025-09-02 08:16:14', '2025-09-02 08:16:14', 5, NULL), +(761, '2025-09-02', 4, 5, 3, 1, NULL, 8.00, '2025-09-02 08:16:14', '2025-09-02 08:16:14', 5, NULL), +(762, '2025-09-02', 4, 5, 3, 1, NULL, 2.00, '2025-09-02 08:16:14', '2025-09-02 08:16:14', 5, NULL), +(763, '2025-09-03', 10, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:47', '2025-09-03 06:34:47', 3, NULL), +(764, '2025-09-03', 9, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:47', '2025-09-03 06:34:47', 3, NULL), +(765, '2025-09-03', 8, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(766, '2025-09-03', 7, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(767, '2025-09-03', 6, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(768, '2025-09-03', 5, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(769, '2025-09-03', 3, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(770, '2025-09-03', 1, 3, 3, 1, NULL, 8.00, '2025-09-03 06:34:48', '2025-09-03 06:34:48', 3, NULL), +(771, '2025-09-03', 2, 5, 3, 1, NULL, 8.00, '2025-09-03 06:44:18', '2025-09-03 06:44:18', 5, NULL), +(772, '2025-09-04', 10, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:32', '2025-09-04 06:41:32', 6, NULL), +(773, '2025-09-04', 5, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:32', '2025-09-04 06:41:32', 6, NULL), +(774, '2025-09-04', 9, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:32', '2025-09-04 06:41:32', 6, NULL), +(775, '2025-09-04', 8, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:32', '2025-09-04 06:41:32', 6, NULL), +(776, '2025-09-04', 3, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:33', '2025-09-04 06:41:33', 6, NULL), +(777, '2025-09-04', 7, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:33', '2025-09-04 06:41:33', 6, NULL), +(778, '2025-09-04', 1, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:33', '2025-09-04 06:41:33', 6, NULL), +(779, '2025-09-04', 6, 3, 3, 1, NULL, 8.00, '2025-09-04 06:41:33', '2025-09-04 06:41:33', 6, NULL), +(780, '2025-09-04', 2, 5, 3, 1, NULL, 8.00, '2025-09-04 06:48:34', '2025-09-04 06:48:34', 5, NULL), +(781, '2025-09-04', 4, 5, 3, 1, NULL, 8.00, '2025-09-04 06:48:34', '2025-09-04 06:48:34', 5, NULL), +(782, '2025-09-05', 10, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:30', '2025-09-05 06:39:30', 3, NULL), +(783, '2025-09-05', 9, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:30', '2025-09-05 06:39:30', 3, NULL), +(784, '2025-09-05', 7, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:30', '2025-09-05 06:39:30', 3, NULL), +(785, '2025-09-05', 6, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:31', '2025-09-05 06:39:31', 3, NULL), +(786, '2025-09-05', 5, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:31', '2025-09-05 06:39:31', 3, NULL), +(787, '2025-09-05', 3, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:31', '2025-09-05 06:39:31', 3, NULL), +(788, '2025-09-05', 1, 3, 3, 1, NULL, 8.00, '2025-09-05 06:39:31', '2025-09-05 06:39:31', 3, NULL), +(789, '2025-09-05', 2, 5, 3, 1, NULL, 8.00, '2025-09-05 22:09:55', '2025-09-05 22:09:55', 5, NULL), +(790, '2025-09-05', 8, 5, 3, 1, NULL, 8.00, '2025-09-05 22:09:55', '2025-09-05 22:09:55', 5, NULL), +(791, '2025-09-05', 4, 5, 3, 1, NULL, 8.00, '2025-09-05 22:09:55', '2025-09-05 22:09:55', 5, NULL), +(792, '2025-09-06', 8, 10, 3, 1, NULL, 8.00, '2025-09-06 04:21:10', '2025-09-06 04:21:10', 5, NULL), +(793, '2025-09-06', 4, 10, 3, 1, NULL, 8.00, '2025-09-06 04:21:10', '2025-09-06 04:21:10', 5, NULL), +(794, '2025-09-06', 2, 10, 3, 1, NULL, 8.00, '2025-09-06 04:21:10', '2025-09-06 04:21:10', 5, NULL), +(795, '2025-09-06', 10, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:18', '2025-09-06 05:28:18', 3, NULL), +(796, '2025-09-06', 9, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:18', '2025-09-06 05:28:18', 3, NULL), +(797, '2025-09-06', 7, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:18', '2025-09-06 05:28:18', 3, NULL), +(798, '2025-09-06', 6, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:19', '2025-09-06 05:28:19', 3, NULL), +(799, '2025-09-06', 5, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:19', '2025-09-06 05:28:19', 3, NULL), +(800, '2025-09-06', 3, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:19', '2025-09-06 05:28:19', 3, NULL), +(801, '2025-09-06', 1, 3, 3, 1, NULL, 8.00, '2025-09-06 05:28:19', '2025-09-06 05:28:19', 3, NULL), +(802, '2025-09-08', 10, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(803, '2025-09-08', 9, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(804, '2025-09-08', 7, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(805, '2025-09-08', 6, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(806, '2025-09-08', 5, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(807, '2025-09-08', 3, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(808, '2025-09-08', 1, 3, 3, 1, NULL, 8.00, '2025-09-08 06:15:43', '2025-09-08 06:15:43', 3, NULL), +(809, '2025-09-08', 8, 5, 3, 1, NULL, 8.00, '2025-09-08 06:47:37', '2025-09-08 06:47:37', 5, NULL), +(810, '2025-09-08', 4, 5, 3, 1, NULL, 8.00, '2025-09-08 06:47:37', '2025-09-08 06:47:37', 5, NULL), +(811, '2025-09-08', 2, 5, 3, 1, NULL, 8.00, '2025-09-08 06:47:37', '2025-09-08 06:47:37', 5, NULL), +(812, '2025-09-09', 10, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(813, '2025-09-09', 9, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(814, '2025-09-09', 7, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(815, '2025-09-09', 6, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(816, '2025-09-09', 5, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(817, '2025-09-09', 3, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(818, '2025-09-09', 1, 3, 3, 1, NULL, 8.00, '2025-09-09 06:03:27', '2025-09-09 06:03:27', 3, NULL), +(819, '2025-09-09', 8, 5, 3, 1, NULL, 8.00, '2025-09-09 06:44:29', '2025-09-09 06:44:29', 5, NULL), +(820, '2025-09-09', 4, 5, 3, 1, NULL, 8.00, '2025-09-09 06:44:29', '2025-09-09 06:44:29', 5, NULL), +(821, '2025-09-09', 2, 5, 3, 1, NULL, 8.00, '2025-09-09 06:44:29', '2025-09-09 06:44:29', 5, NULL), +(822, '2025-09-10', 10, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(823, '2025-09-10', 9, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(824, '2025-09-10', 7, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(825, '2025-09-10', 6, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(826, '2025-09-10', 5, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(827, '2025-09-10', 3, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(828, '2025-09-10', 1, 3, 3, 1, NULL, 8.00, '2025-09-10 06:27:52', '2025-09-10 06:27:52', 3, NULL), +(829, '2025-09-10', 8, 5, 3, 1, NULL, 8.00, '2025-09-10 06:48:43', '2025-09-10 06:48:43', 5, NULL), +(830, '2025-09-10', 4, 5, 3, 1, NULL, 8.00, '2025-09-10 06:48:43', '2025-09-10 06:48:43', 5, NULL), +(831, '2025-09-10', 2, 5, 3, 1, NULL, 8.00, '2025-09-10 06:48:43', '2025-09-10 06:48:43', 5, NULL), +(832, '2025-09-11', 2, 5, 3, 1, NULL, 2.00, '2025-09-11 06:37:11', '2025-09-11 06:37:11', 5, NULL), +(833, '2025-09-11', 2, 8, 3, 1, NULL, 6.00, '2025-09-11 06:37:11', '2025-09-11 06:37:11', 5, NULL), +(834, '2025-09-11', 4, 5, 3, 1, NULL, 2.00, '2025-09-11 06:38:24', '2025-09-11 06:38:24', 5, NULL), +(835, '2025-09-11', 4, 8, 3, 1, NULL, 2.00, '2025-09-11 06:38:24', '2025-09-11 06:38:24', 5, NULL), +(836, '2025-09-11', 4, 3, 3, 1, NULL, 4.00, '2025-09-11 06:38:24', '2025-09-11 06:38:24', 5, NULL), +(838, '2025-09-11', 1, 3, 1, 1, NULL, 4.00, '2025-09-11 06:40:48', '2025-09-11 06:40:48', 5, NULL), +(840, '2025-09-11', 5, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(841, '2025-09-11', 8, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(842, '2025-09-11', 3, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(843, '2025-09-11', 7, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(844, '2025-09-11', 6, 3, 2, 1, NULL, 8.00, '2025-09-11 06:41:47', '2025-09-11 06:41:47', 6, NULL), +(845, '2025-09-11', 10, 3, 2, 1, NULL, 4.00, '2025-09-11 06:41:51', '2025-09-11 06:41:51', 5, NULL), +(846, '2025-09-11', 10, 3, 3, 1, NULL, 4.00, '2025-09-11 06:41:51', '2025-09-11 06:41:51', 5, NULL), +(847, '2025-09-11', 9, 3, 2, 1, NULL, 4.00, '2025-09-11 06:41:51', '2025-09-11 06:41:51', 5, NULL), +(848, '2025-09-11', 9, 3, 3, 1, NULL, 4.00, '2025-09-11 06:41:51', '2025-09-11 06:41:51', 5, NULL), +(851, '2025-09-12', 10, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(852, '2025-09-12', 9, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(853, '2025-09-12', 8, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(854, '2025-09-12', 6, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(855, '2025-09-12', 5, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(856, '2025-09-12', 4, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(857, '2025-09-12', 3, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(858, '2025-09-12', 2, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(859, '2025-09-12', 1, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(860, '2025-09-12', 7, 3, 3, 1, NULL, 8.00, '2025-09-12 06:45:29', '2025-09-12 06:45:29', 3, NULL), +(861, '2025-09-13', 10, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(862, '2025-09-13', 8, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(863, '2025-09-13', 7, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(864, '2025-09-13', 6, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(865, '2025-09-13', 5, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(866, '2025-09-13', 4, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(867, '2025-09-13', 3, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(868, '2025-09-13', 2, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(869, '2025-09-13', 1, 3, 3, 1, NULL, 8.00, '2025-09-13 06:38:14', '2025-09-13 06:38:14', 3, NULL), +(870, '2025-09-14', 9, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:40', '2025-09-14 04:47:40', 3, NULL), +(871, '2025-09-14', 8, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:40', '2025-09-14 04:47:40', 3, NULL), +(872, '2025-09-14', 7, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:40', '2025-09-14 04:47:40', 3, NULL), +(873, '2025-09-14', 6, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:40', '2025-09-14 04:47:40', 3, NULL), +(874, '2025-09-14', 5, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(875, '2025-09-14', 4, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(876, '2025-09-14', 3, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(877, '2025-09-14', 2, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(878, '2025-09-14', 1, 3, 3, 1, NULL, 8.00, '2025-09-14 04:47:41', '2025-09-14 04:47:41', 3, NULL), +(879, '2025-09-15', 5, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:00', '2025-09-15 06:50:00', 3, NULL), +(880, '2025-09-15', 10, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:00', '2025-09-15 06:50:00', 3, NULL), +(881, '2025-09-15', 9, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:00', '2025-09-15 06:50:00', 3, NULL), +(882, '2025-09-15', 8, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:00', '2025-09-15 06:50:00', 3, NULL), +(883, '2025-09-15', 7, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(884, '2025-09-15', 6, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(885, '2025-09-15', 4, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(886, '2025-09-15', 3, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(887, '2025-09-15', 2, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(888, '2025-09-15', 1, 3, 3, 1, NULL, 8.00, '2025-09-15 06:50:01', '2025-09-15 06:50:01', 3, NULL), +(889, '2025-09-16', 2, 8, 3, 1, NULL, 8.00, '2025-09-16 06:51:19', '2025-09-16 06:51:19', 5, NULL), +(890, '2025-09-16', 4, 8, 3, 1, NULL, 8.00, '2025-09-16 06:51:19', '2025-09-16 06:51:19', 5, NULL), +(891, '2025-09-16', 8, 8, 2, 1, NULL, 2.00, '2025-09-16 06:52:12', '2025-09-16 06:52:12', 5, NULL), +(892, '2025-09-16', 8, 3, 2, 1, NULL, 6.00, '2025-09-16 06:52:12', '2025-09-16 06:52:12', 5, NULL), +(893, '2025-09-17', 4, 8, 3, 1, NULL, 8.00, '2025-09-17 06:43:08', '2025-09-17 06:43:08', 5, NULL), +(894, '2025-09-17', 2, 8, 3, 1, NULL, 8.00, '2025-09-17 06:43:08', '2025-09-17 06:43:08', 5, NULL), +(895, '2025-09-17', 10, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(896, '2025-09-17', 9, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(897, '2025-09-17', 8, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(898, '2025-09-17', 7, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(899, '2025-09-17', 6, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(900, '2025-09-17', 5, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(901, '2025-09-17', 3, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(902, '2025-09-17', 1, 3, 3, 1, NULL, 8.00, '2025-09-17 06:45:06', '2025-09-17 06:45:06', 3, NULL), +(903, '2025-09-18', 7, 3, 3, 1, NULL, 8.00, '2025-09-18 06:43:40', '2025-09-18 06:43:40', 3, NULL), +(904, '2025-09-18', 1, 3, 3, 1, NULL, 8.00, '2025-09-18 06:43:40', '2025-09-18 06:43:40', 3, NULL), +(905, '2025-09-18', 10, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(906, '2025-09-18', 9, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(907, '2025-09-18', 8, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(908, '2025-09-18', 6, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(909, '2025-09-18', 3, 3, 2, 1, NULL, 8.00, '2025-09-18 06:44:42', '2025-09-18 06:44:42', 3, NULL), +(910, '2025-09-18', 5, 3, 2, 1, NULL, 6.00, '2025-09-18 06:46:39', '2025-09-18 06:46:39', 3, NULL), +(911, '2025-09-18', 2, 8, 3, 1, NULL, 8.00, '2025-09-18 06:54:48', '2025-09-18 06:54:48', 5, NULL), +(912, '2025-09-18', 4, 8, 3, 1, NULL, 8.00, '2025-09-18 06:54:48', '2025-09-18 06:54:48', 5, NULL), +(913, '2025-09-19', 4, 8, 3, 1, NULL, 8.00, '2025-09-19 06:51:40', '2025-09-19 06:51:40', 5, NULL), +(914, '2025-09-19', 2, 8, 3, 1, NULL, 8.00, '2025-09-19 06:51:40', '2025-09-19 06:51:40', 5, NULL), +(915, '2025-09-19', 10, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(916, '2025-09-19', 8, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(917, '2025-09-19', 7, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(918, '2025-09-19', 6, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(919, '2025-09-19', 5, 3, 2, 1, NULL, 8.00, '2025-09-19 06:52:05', '2025-09-19 06:52:05', 5, NULL), +(920, '2025-09-19', 3, 3, 2, 1, NULL, 4.00, '2025-09-19 06:52:23', '2025-09-19 06:52:23', 5, NULL), +(921, '2025-09-20', 4, 8, 3, 1, NULL, 8.00, '2025-09-20 05:30:19', '2025-09-20 05:30:19', 5, NULL), +(922, '2025-09-20', 2, 8, 3, 1, NULL, 8.00, '2025-09-20 05:30:19', '2025-09-20 05:30:19', 5, NULL), +(923, '2025-09-22', 10, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(924, '2025-09-22', 9, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(925, '2025-09-22', 8, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(926, '2025-09-22', 7, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(927, '2025-09-22', 5, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(928, '2025-09-22', 1, 3, 2, 1, NULL, 8.00, '2025-09-22 06:47:25', '2025-09-22 06:47:25', 3, NULL), +(929, '2025-09-22', 4, 8, 3, 1, NULL, 8.00, '2025-09-22 06:50:29', '2025-09-22 06:50:29', 5, NULL), +(930, '2025-09-22', 2, 8, 3, 1, NULL, 8.00, '2025-09-22 06:50:29', '2025-09-22 06:50:29', 5, NULL), +(931, '2025-09-23', 4, 8, 3, 1, NULL, 8.00, '2025-09-23 05:46:40', '2025-09-23 05:46:40', 5, NULL), +(932, '2025-09-23', 2, 8, 3, 1, NULL, 8.00, '2025-09-23 05:46:40', '2025-09-23 05:46:40', 5, NULL), +(933, '2025-09-24', 4, 8, 3, 1, NULL, 8.00, '2025-09-25 01:14:58', '2025-09-25 01:14:58', 5, NULL), +(934, '2025-09-24', 2, 8, 3, 1, NULL, 8.00, '2025-09-25 01:14:58', '2025-09-25 01:14:58', 5, NULL), +(935, '2025-09-29', 7, 14, 1, 1, NULL, 8.00, '2025-09-29 06:36:07', '2025-09-29 06:36:07', 3, NULL), +(936, '2025-09-29', 1, 14, 1, 1, NULL, 8.00, '2025-09-29 06:36:07', '2025-09-29 06:36:07', 3, NULL), +(937, '2025-09-29', 10, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(938, '2025-09-29', 8, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(939, '2025-09-29', 6, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(940, '2025-09-29', 9, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(941, '2025-09-29', 5, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(942, '2025-09-29', 4, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(943, '2025-09-29', 3, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(944, '2025-09-29', 2, 3, 2, 1, NULL, 8.00, '2025-09-29 06:36:47', '2025-09-29 06:36:47', 3, NULL), +(945, '2025-09-30', 10, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(946, '2025-09-30', 9, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(947, '2025-09-30', 8, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(948, '2025-09-30', 6, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(949, '2025-09-30', 5, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(950, '2025-09-30', 4, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:26', '2025-09-30 06:52:26', 3, NULL), +(951, '2025-09-30', 3, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:27', '2025-09-30 06:52:27', 3, NULL), +(953, '2025-09-30', 1, 3, 2, 1, NULL, 8.00, '2025-09-30 06:52:27', '2025-09-30 06:52:27', 3, NULL), +(954, '2025-09-30', 2, 8, 3, 1, NULL, 8.00, '2025-09-30 06:56:55', '2025-09-30 06:56:55', 5, NULL), +(955, '2025-10-02', 5, 3, 2, 1, NULL, 6.00, '2025-10-02 05:25:58', '2025-10-02 05:25:58', 3, NULL), +(956, '2025-10-02', 8, 3, 2, 1, NULL, 6.00, '2025-10-02 05:25:59', '2025-10-02 05:25:59', 3, NULL), +(957, '2025-10-02', 10, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:32', '2025-10-02 06:22:32', 3, NULL), +(958, '2025-10-02', 9, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:32', '2025-10-02 06:22:32', 3, NULL), +(959, '2025-10-02', 7, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:32', '2025-10-02 06:22:32', 3, NULL), +(960, '2025-10-02', 6, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:32', '2025-10-02 06:22:32', 3, NULL), +(961, '2025-10-02', 4, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:33', '2025-10-02 06:22:33', 3, NULL), +(962, '2025-10-02', 2, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:33', '2025-10-02 06:22:33', 3, NULL), +(963, '2025-10-02', 1, 3, 2, 1, NULL, 8.00, '2025-10-02 06:22:33', '2025-10-02 06:22:33', 3, NULL), +(964, '2025-09-01', 8, 5, 3, 1, NULL, 8.00, '2025-10-10 23:35:07', '2025-10-10 23:35:07', 3, NULL), +(965, '2025-09-01', 4, 5, 3, 1, NULL, 8.00, '2025-10-10 23:35:07', '2025-10-10 23:35:07', 3, NULL), +(966, '2025-09-01', 2, 5, 3, 1, NULL, 8.00, '2025-10-10 23:35:07', '2025-10-10 23:35:07', 3, NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `EquipmentList` +-- + +CREATE TABLE `EquipmentList` ( + `equipment_id` int(11) NOT NULL, + `factory_id` int(11) DEFAULT NULL, + `equipment_name` varchar(255) NOT NULL, + `model` varchar(100) DEFAULT NULL, + `status` text DEFAULT 'operational', + `purchase_date` date DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `error_types` +-- + +CREATE TABLE `error_types` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL COMMENT '에러 유형명', + `description` text DEFAULT NULL COMMENT '에러 설명', + `severity` enum('low','medium','high','critical') DEFAULT 'medium' COMMENT '심각도', + `solution_guide` text DEFAULT NULL COMMENT '해결 가이드', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `error_types` +-- + +INSERT INTO `error_types` (`id`, `name`, `description`, `severity`, `solution_guide`, `created_at`, `updated_at`) VALUES +(1, '설계미스', '설계미스', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:03'), +(2, '외주작업 불량', '입고 자재 불량', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:05'), +(3, '입고지연', '자재 미입고', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:11'), +(4, '작업불량', '작업자 실수', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:13'), +(5, '설비고장', '장비없음', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-16 03:02:16'), +(6, '검사불량', '검사불량', 'medium', NULL, '2025-06-16 02:21:32', '2025-06-24 04:36:18'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `FactoryInfo` +-- + +CREATE TABLE `FactoryInfo` ( + `factory_id` int(11) NOT NULL, + `factory_name` varchar(255) NOT NULL, + `address` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `map_image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `FactoryInfo` +-- + +INSERT INTO `FactoryInfo` (`factory_id`, `factory_name`, `address`, `description`, `map_image_url`, `created_at`, `updated_at`) VALUES +(3, '제1공장 휴게공간 및 작업자 사물함', '현대기아로 771-9', '개인 보관함, 컨테이너(휴게공간), 화장실, 흡연장', '/uploads/map_image-1746593523450.png', '2025-05-07 04:52:03', '2025-05-07 04:52:03'), +(4, '제 1공장 공구 및 용접봉 보관 구역', '현대기아로 771-9', '소모품, 공구류, 용접봉 보관 구역', '/uploads/map_image-1746593674259.png', '2025-05-07 04:53:59', '2025-05-07 04:53:59'), +(5, 'ee', 'ee', 'ee', NULL, '2025-06-03 22:13:23', '2025-06-03 22:13:23'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `IssueTypes` +-- + +CREATE TABLE `IssueTypes` ( + `issue_type_id` int(11) NOT NULL, + `category` varchar(100) NOT NULL, + `subcategory` varchar(100) NOT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `IssueTypes` +-- + +INSERT INTO `IssueTypes` (`issue_type_id`, `category`, `subcategory`) VALUES +(1, '구매팀', '자재입고지연'), +(2, '구매팀', '자재전달 미흡'), +(3, '품질', '검사 내용 전달 미흡'), +(4, '품질', '검사오류'), +(5, '설계', '설계미스(치수)'), +(6, '설계', '설계미스(작업불가)'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `login_logs` +-- + +CREATE TABLE `login_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) DEFAULT NULL, + `login_time` datetime DEFAULT current_timestamp(), + `logout_time` datetime DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `login_status` enum('success','failed','locked') DEFAULT 'success', + `failure_reason` varchar(100) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `login_logs` +-- + +INSERT INTO `login_logs` (`log_id`, `user_id`, `login_time`, `logout_time`, `ip_address`, `user_agent`, `login_status`, `failure_reason`) VALUES +(1, 3, '2025-06-15 05:58:39', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(3, 4, '2025-06-15 06:04:06', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(4, 3, '2025-06-15 06:24:53', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(5, 3, '2025-06-15 06:24:55', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(6, 3, '2025-06-15 06:32:41', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(7, 3, '2025-06-15 07:03:19', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(8, 3, '2025-06-15 07:03:21', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(9, 3, '2025-06-15 07:03:25', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(10, 1, '2025-06-15 07:40:16', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(11, 6, '2025-06-15 07:42:02', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(12, 3, '2025-06-15 07:43:30', NULL, '118.235.6.135', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(13, 3, '2025-06-15 22:02:59', NULL, '118.235.6.29', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(14, 4, '2025-06-15 22:15:25', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(15, 3, '2025-06-15 22:15:34', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(16, 6, '2025-06-15 22:15:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'failed', 'invalid_password'), +(17, 6, '2025-06-15 22:15:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(18, 3, '2025-06-15 22:16:39', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(19, 3, '2025-06-15 22:17:14', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(20, 6, '2025-06-15 22:21:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(21, 1, '2025-06-15 22:21:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(22, 6, '2025-06-15 22:22:06', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(23, 5, '2025-06-15 22:22:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(24, 6, '2025-06-15 22:23:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(25, 3, '2025-06-15 22:24:49', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(26, 3, '2025-06-15 22:30:18', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(27, 3, '2025-06-15 22:31:21', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(28, 5, '2025-06-15 22:44:31', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(29, 4, '2025-06-15 22:57:51', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(30, 4, '2025-06-15 22:57:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(31, 4, '2025-06-15 22:57:54', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(32, 4, '2025-06-15 22:57:55', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(33, 4, '2025-06-15 23:11:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(34, 4, '2025-06-15 23:28:04', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(35, 3, '2025-06-15 23:33:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(36, 3, '2025-06-16 00:58:53', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(37, 3, '2025-06-16 01:15:46', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(38, 5, '2025-06-16 01:16:43', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(39, 1, '2025-06-16 01:25:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(40, 1, '2025-06-16 01:26:08', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(41, 3, '2025-06-16 02:27:20', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(42, 3, '2025-06-16 02:45:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(43, 3, '2025-06-16 03:04:13', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(44, 3, '2025-06-16 03:17:28', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(45, 5, '2025-06-16 03:17:55', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(46, 3, '2025-06-16 03:18:56', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(47, 5, '2025-06-16 03:19:13', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(48, 1, '2025-06-16 03:55:56', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(49, 1, '2025-06-16 04:24:37', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(50, 1, '2025-06-16 04:51:36', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(51, 1, '2025-06-16 05:07:05', NULL, '118.235.7.233', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(52, 1, '2025-06-16 05:07:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(53, 1, '2025-06-16 05:43:14', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(54, 5, '2025-06-16 06:11:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(55, 1, '2025-06-16 06:19:46', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(56, 1, '2025-06-16 06:23:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(57, 1, '2025-06-16 06:39:12', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(58, 3, '2025-06-16 06:45:26', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(59, 6, '2025-06-16 06:46:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(60, 1, '2025-06-16 21:18:09', NULL, '118.235.7.45', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(61, 1, '2025-06-17 08:15:45', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(62, 5, '2025-06-17 08:22:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(63, 3, '2025-06-17 08:23:05', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'failed', 'invalid_password'), +(64, 3, '2025-06-17 08:23:21', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(65, 3, '2025-06-17 08:28:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(66, 3, '2025-06-17 08:32:25', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(67, 6, '2025-06-17 08:33:07', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(68, 1, '2025-06-17 08:36:01', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(69, 5, '2025-06-17 09:00:56', NULL, '118.235.7.173', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(70, 3, '2025-06-18 02:30:13', NULL, '118.235.6.77', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(71, 1, '2025-06-18 08:07:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'failed', 'invalid_password'), +(72, 1, '2025-06-18 08:07:47', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(73, 5, '2025-06-18 08:39:59', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(74, 6, '2025-06-18 08:46:53', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(75, 3, '2025-06-18 08:47:03', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(76, 6, '2025-06-18 08:57:48', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(77, 5, '2025-06-18 08:58:14', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(78, 3, '2025-06-18 08:59:12', NULL, '118.235.7.5', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(79, 5, '2025-06-19 06:37:35', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(80, 3, '2025-06-19 06:57:01', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(81, 6, '2025-06-19 06:57:22', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(82, 5, '2025-06-19 06:57:56', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(83, 6, '2025-06-19 06:58:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(84, 3, '2025-06-19 06:59:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(85, 3, '2025-06-20 06:42:26', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(86, 6, '2025-06-20 06:45:06', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(87, 5, '2025-06-20 06:49:26', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(88, 3, '2025-06-20 06:49:47', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(89, 6, '2025-06-20 06:50:17', NULL, '118.235.7.134', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(90, 3, '2025-06-20 22:46:20', NULL, '192.168.1.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(91, 1, '2025-06-23 05:03:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(92, 6, '2025-06-23 06:41:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(93, 3, '2025-06-23 06:49:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(94, 6, '2025-06-23 06:50:01', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(95, 5, '2025-06-23 06:50:28', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(96, 1, '2025-06-24 05:24:17', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(97, 3, '2025-06-24 05:25:52', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(98, 1, '2025-06-24 09:22:29', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(99, 3, '2025-06-24 11:09:38', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(100, 6, '2025-06-24 11:09:48', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(101, 5, '2025-06-24 11:10:23', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(102, 3, '2025-06-24 11:11:29', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(103, 5, '2025-06-24 11:12:06', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(104, 6, '2025-06-24 11:12:31', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(105, 3, '2025-06-24 21:41:01', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(106, 3, '2025-06-25 04:40:44', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(107, 3, '2025-06-25 05:24:57', NULL, '118.235.6.179', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(108, 1, '2025-06-25 07:05:20', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(109, 1, '2025-06-25 07:06:41', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(110, 3, '2025-06-25 07:09:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(111, 3, '2025-06-25 08:49:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(112, 3, '2025-06-25 09:20:05', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(113, 3, '2025-06-25 09:40:11', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(114, 3, '2025-06-25 09:57:27', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(115, 1, '2025-06-25 10:11:03', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(116, 1, '2025-06-25 10:26:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(117, 1, '2025-06-25 10:49:29', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(118, 5, '2025-06-25 11:07:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(119, 6, '2025-06-25 11:10:41', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(120, 6, '2025-06-25 11:13:55', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(121, 5, '2025-06-25 11:14:25', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(122, 6, '2025-06-25 11:20:16', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(123, 1, '2025-06-25 11:24:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(124, 3, '2025-06-26 10:27:57', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(125, 5, '2025-06-26 11:10:47', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(126, 6, '2025-06-26 11:15:57', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(127, 3, '2025-06-26 11:17:07', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(128, 5, '2025-06-26 11:17:40', NULL, '118.235.6.58', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(129, 6, '2025-06-26 11:19:00', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(130, 1, '2025-06-26 22:15:30', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(131, 1, '2025-06-26 22:31:02', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(132, 1, '2025-06-26 22:47:22', NULL, '123.142.67.74', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(133, 5, '2025-06-27 01:52:48', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(134, 5, '2025-06-27 01:53:58', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(135, 3, '2025-06-27 06:47:09', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(136, 6, '2025-06-27 06:48:39', NULL, '123.142.67.74', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0', 'success', NULL), +(137, 3, '2025-06-27 06:57:15', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(138, 5, '2025-06-27 06:57:34', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(139, 6, '2025-06-27 06:57:59', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(140, 3, '2025-06-27 06:59:04', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(141, 5, '2025-06-27 06:59:29', NULL, '123.142.67.74', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(142, 3, '2025-07-05 01:25:41', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(143, 3, '2025-07-05 01:26:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(144, 3, '2025-07-05 01:41:35', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(145, 3, '2025-07-05 01:46:29', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(146, 3, '2025-07-05 01:46:57', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(147, 3, '2025-07-05 01:47:17', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(148, 5, '2025-07-05 01:48:23', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(149, 3, '2025-07-05 01:49:42', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(150, 3, '2025-07-05 01:50:41', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(151, 1, '2025-07-05 01:52:14', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(152, 3, '2025-07-05 02:12:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(153, 3, '2025-07-05 04:48:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(154, 5, '2025-07-05 05:36:08', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(155, 3, '2025-07-05 05:52:08', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(156, 5, '2025-07-06 05:33:53', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(157, 3, '2025-07-06 05:45:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(158, 1, '2025-07-07 01:40:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(159, 1, '2025-07-07 01:40:39', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(160, 3, '2025-07-07 01:54:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(161, 3, '2025-07-07 02:13:32', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(162, 1, '2025-07-07 02:28:26', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(163, 3, '2025-07-07 02:45:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(164, 1, '2025-07-07 03:33:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(165, 1, '2025-07-07 03:51:07', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(166, 1, '2025-07-07 03:56:23', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(167, 1, '2025-07-07 03:57:20', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(168, 1, '2025-07-07 03:58:02', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(169, 1, '2025-07-07 03:58:37', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(170, 3, '2025-07-07 04:00:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(171, 1, '2025-07-07 04:03:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(172, 1, '2025-07-07 04:10:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(173, 3, '2025-07-07 04:13:46', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(174, 1, '2025-07-07 04:23:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(175, 3, '2025-07-07 04:25:09', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(176, 6, '2025-07-07 06:48:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(177, 3, '2025-07-07 06:51:59', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(178, 1, '2025-07-07 23:33:26', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(179, 1, '2025-07-07 23:37:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(180, 3, '2025-07-08 06:36:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(181, 3, '2025-07-08 06:59:17', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(182, 3, '2025-07-09 06:59:29', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(183, 5, '2025-07-09 22:07:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(184, 3, '2025-07-10 02:09:48', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(185, 1, '2025-07-10 02:11:20', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(186, 3, '2025-07-10 06:28:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(187, 3, '2025-07-10 06:57:12', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(188, 3, '2025-07-11 06:59:42', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(189, 3, '2025-07-12 05:39:34', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(190, 3, '2025-07-12 05:41:00', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(191, 3, '2025-07-12 05:58:31', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(192, 3, '2025-07-14 06:45:52', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(193, 3, '2025-07-15 00:09:52', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(194, 5, '2025-07-15 05:56:33', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(195, 3, '2025-07-15 06:56:35', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(196, 5, '2025-07-16 06:45:52', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(197, 3, '2025-07-16 06:51:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(198, 3, '2025-07-17 06:44:45', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(199, 5, '2025-07-17 06:45:54', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(200, 3, '2025-07-17 06:58:06', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(201, 3, '2025-07-18 05:54:03', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(202, 5, '2025-07-18 06:35:45', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(203, 5, '2025-07-21 06:39:22', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(204, 3, '2025-07-21 06:53:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(205, 5, '2025-07-22 06:45:21', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(206, 3, '2025-07-22 06:45:41', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(207, 3, '2025-07-22 06:46:38', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(208, 3, '2025-07-22 06:57:45', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(209, 5, '2025-07-23 06:44:46', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(210, 3, '2025-07-23 06:44:59', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(211, 3, '2025-07-23 06:59:50', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(212, 5, '2025-07-24 06:36:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(213, 3, '2025-07-24 06:46:42', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(214, 5, '2025-07-25 06:44:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(215, 3, '2025-07-25 06:44:45', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(216, 5, '2025-07-27 21:28:11', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(217, 3, '2025-07-28 06:30:12', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(218, 3, '2025-07-28 06:31:32', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(219, 5, '2025-07-28 06:32:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(220, 3, '2025-07-28 06:54:43', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(221, 3, '2025-07-29 06:38:49', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(222, 1, '2025-07-30 01:57:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(223, 1, '2025-07-30 02:03:46', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(224, 3, '2025-07-30 02:04:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(225, 1, '2025-07-30 02:20:29', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(226, 1, '2025-07-30 02:24:55', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(227, 3, '2025-07-30 05:01:07', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(228, 3, '2025-07-30 06:50:12', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(229, 5, '2025-07-30 06:51:38', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(230, 1, '2025-07-30 22:38:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(231, 5, '2025-07-31 06:42:33', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(232, 3, '2025-07-31 22:23:54', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(233, 5, '2025-08-01 04:56:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(234, 5, '2025-08-01 04:57:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(235, 3, '2025-08-01 05:01:42', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(236, 5, '2025-08-07 06:41:51', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(237, 3, '2025-08-07 06:43:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(238, 3, '2025-08-08 06:44:56', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(239, 3, '2025-08-08 06:55:18', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Safari/605.1.15', 'success', NULL), +(240, 5, '2025-08-08 06:58:09', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(241, 3, '2025-08-11 02:06:53', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(242, 1, '2025-08-11 04:16:44', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'failed', 'invalid_password'), +(243, 1, '2025-08-11 04:17:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(244, 3, '2025-08-11 06:27:03', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(245, 5, '2025-08-11 06:45:58', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(246, 3, '2025-08-12 06:46:57', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(247, 6, '2025-08-13 05:14:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(248, 3, '2025-08-13 06:30:59', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(249, 5, '2025-08-13 06:35:40', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(250, 5, '2025-08-14 02:02:04', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/138.0.0.0 Safari/537.36 Edg/138.0.0.0', 'success', NULL), +(251, 3, '2025-08-14 06:34:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(252, 5, '2025-08-14 06:38:26', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(253, 5, '2025-08-18 06:21:07', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL); +INSERT INTO `login_logs` (`log_id`, `user_id`, `login_time`, `logout_time`, `ip_address`, `user_agent`, `login_status`, `failure_reason`) VALUES +(254, 3, '2025-08-18 06:40:43', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(255, 6, '2025-08-18 06:42:10', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(256, 3, '2025-08-18 06:47:57', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(257, 5, '2025-08-19 08:02:10', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(258, 6, '2025-08-19 08:35:46', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(259, 5, '2025-08-20 06:19:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(260, 3, '2025-08-20 06:42:31', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(261, 6, '2025-08-20 06:43:54', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(262, 3, '2025-08-21 06:29:56', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(263, 5, '2025-08-21 07:50:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(264, 6, '2025-08-21 08:23:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(265, 5, '2025-08-22 06:20:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(266, 5, '2025-08-22 06:22:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(267, 3, '2025-08-22 06:27:17', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(268, 5, '2025-08-23 04:56:25', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(269, 3, '2025-08-25 06:48:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(270, 6, '2025-08-25 06:48:48', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(271, 5, '2025-08-26 07:07:36', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(272, 1, '2025-08-26 07:11:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(273, 5, '2025-08-26 07:27:16', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(274, 6, '2025-08-26 08:21:22', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(275, 3, '2025-08-27 00:51:26', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_5 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.5 Mobile/15E148 Safari/604.1', 'success', NULL), +(276, 3, '2025-08-27 06:43:38', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(277, 5, '2025-08-27 06:44:44', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(278, 1, '2025-08-28 01:48:08', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(279, 3, '2025-08-28 01:49:21', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(280, 3, '2025-08-28 03:28:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(281, 6, '2025-08-28 08:29:27', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(282, 5, '2025-08-28 08:37:06', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(283, 5, '2025-08-28 08:44:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(284, 3, '2025-08-29 06:45:33', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(285, 6, '2025-08-29 06:46:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(286, 5, '2025-08-29 21:54:56', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(287, 3, '2025-08-30 02:57:31', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(288, 5, '2025-08-30 05:11:35', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(289, 3, '2025-08-30 05:35:51', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(290, 3, '2025-09-01 06:17:50', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(291, 3, '2025-09-01 23:13:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(292, 3, '2025-09-02 03:59:38', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(293, 3, '2025-09-02 07:33:36', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(294, 5, '2025-09-02 08:15:36', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(295, 3, '2025-09-02 23:36:25', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(296, 3, '2025-09-03 01:32:24', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(297, 3, '2025-09-03 06:32:44', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(298, 5, '2025-09-03 06:43:58', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(299, 6, '2025-09-04 06:40:35', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(300, 5, '2025-09-04 06:48:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(301, 3, '2025-09-05 06:39:03', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(302, 5, '2025-09-05 22:09:08', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(303, 5, '2025-09-06 04:20:51', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(304, 3, '2025-09-06 05:27:55', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(305, 3, '2025-09-08 06:15:03', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(306, 5, '2025-09-08 06:47:15', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(307, 3, '2025-09-09 06:02:53', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(308, 5, '2025-09-09 06:44:09', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(309, 3, '2025-09-10 06:27:30', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(310, 5, '2025-09-10 06:48:23', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(311, 5, '2025-09-11 06:36:20', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(312, 6, '2025-09-11 06:40:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(313, 3, '2025-09-12 06:43:55', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(314, 3, '2025-09-13 06:37:35', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(315, 5, '2025-09-13 23:16:18', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(316, 3, '2025-09-14 04:47:13', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(317, 3, '2025-09-15 06:49:28', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(318, 5, '2025-09-16 06:50:55', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(319, 5, '2025-09-17 06:42:49', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(320, 3, '2025-09-17 06:44:41', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(321, 1, '2025-09-17 23:51:39', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(322, 3, '2025-09-18 06:43:14', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(323, 3, '2025-09-18 06:46:17', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(324, 5, '2025-09-18 06:54:31', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(325, 5, '2025-09-19 06:51:14', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(326, 5, '2025-09-20 05:30:00', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(327, 3, '2025-09-22 06:46:29', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(328, 5, '2025-09-22 06:50:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(329, 5, '2025-09-23 05:46:19', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(330, 3, '2025-09-23 06:46:57', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(331, 3, '2025-09-23 06:47:27', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(332, 5, '2025-09-25 01:14:07', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(333, 3, '2025-09-25 06:56:18', NULL, '172.18.0.1', 'Mozilla/5.0 (iPhone; CPU iPhone OS 18_6 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.0 Mobile/15E148 Safari/604.1', 'success', NULL), +(334, 1, '2025-09-28 22:11:51', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(335, 3, '2025-09-29 06:35:29', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(336, 3, '2025-09-30 06:52:01', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(337, 5, '2025-09-30 06:56:12', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(338, 5, '2025-10-01 06:55:37', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36 Edg/139.0.0.0', 'success', NULL), +(339, 1, '2025-10-01 23:48:39', NULL, '172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(340, 3, '2025-10-02 05:25:11', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(341, 3, '2025-10-02 06:21:56', NULL, '172.18.0.1', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36 Edg/140.0.0.0', 'success', NULL), +(342, 1, '2025-10-06 01:01:56', NULL, '::ffff:172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(343, 1, '2025-10-10 23:13:57', NULL, '::ffff:172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL), +(344, 3, '2025-10-10 23:32:38', NULL, '::ffff:172.18.0.1', 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15', 'success', NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `password_change_logs` +-- + +CREATE TABLE `password_change_logs` ( + `log_id` int(11) NOT NULL, + `user_id` int(11) NOT NULL, + `changed_by_user_id` int(11) DEFAULT NULL, + `changed_at` datetime DEFAULT current_timestamp(), + `change_type` enum('self','admin','reset','initial') DEFAULT 'self', + `ip_address` varchar(45) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `password_change_logs` +-- + +INSERT INTO `password_change_logs` (`log_id`, `user_id`, `changed_by_user_id`, `changed_at`, `change_type`, `ip_address`) VALUES +(1, 4, NULL, '2025-06-15 06:03:42', 'admin', NULL), +(2, 3, NULL, '2025-06-15 06:03:52', 'admin', NULL), +(3, 3, 3, '2025-06-15 06:32:30', 'self', NULL), +(4, 3, 1, '2025-06-15 07:40:39', 'admin', NULL), +(5, 5, 1, '2025-06-15 07:41:02', 'initial', NULL), +(6, 6, 1, '2025-06-15 07:41:32', 'initial', NULL); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `PipeSpecs` +-- + +CREATE TABLE `PipeSpecs` ( + `spec_id` int(11) NOT NULL, + `material` varchar(50) NOT NULL COMMENT '재질 (예: SS400, STS304)', + `diameter_in` varchar(10) NOT NULL COMMENT '직경 (inch, 예: 2")', + `schedule` varchar(50) NOT NULL COMMENT '스케줄 (예: STD, SCH10, SCH40)' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- +-- 테이블의 덤프 데이터 `PipeSpecs` +-- + +INSERT INTO `PipeSpecs` (`spec_id`, `material`, `diameter_in`, `schedule`) VALUES +(2, '516-70N', '1', 'SCH80'), +(1, 'A106', '3/4', 'SCH80'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Processes` +-- + +CREATE TABLE `Processes` ( + `process_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `process_name` varchar(255) NOT NULL, + `process_start` date NOT NULL, + `process_end` date DEFAULT NULL, + `planned_worker_count` int(11) NOT NULL, + `process_description` text DEFAULT NULL, + `note` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Projects` +-- + +CREATE TABLE `Projects` ( + `project_id` int(11) NOT NULL, + `job_no` varchar(50) NOT NULL, + `project_name` varchar(255) NOT NULL, + `contract_date` date DEFAULT NULL, + `due_date` date DEFAULT NULL, + `delivery_method` varchar(100) DEFAULT NULL, + `site` varchar(100) DEFAULT NULL, + `pm` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Projects` +-- + +INSERT INTO `Projects` (`project_id`, `job_no`, `project_name`, `contract_date`, `due_date`, `delivery_method`, `site`, `pm`, `created_at`, `updated_at`) VALUES +(1, 'TKO-24008P', 'YHP Project', '2024-05-16', '2025-05-16', 'FOB', 'Quang Ninh(Vietnam)', '장형태', '2025-04-15 22:40:28', '2025-04-15 22:40:28'), +(2, 'TKG-24009P', '한화에어로스페이스 순천', '2024-06-05', '2025-05-31', '.', '순천', '장형태', '2025-04-15 22:42:41', '2025-04-15 22:42:41'), +(3, 'TKG-24011P', '효성화학 에틸렌 탱크 건설공사', '2024-06-22', '2025-12-25', '.', '울산', '김길종', '2025-04-15 22:43:53', '2025-04-15 22:43:53'), +(4, 'TKG-24013P', '김천 솔라 파워 그린 수소 Project', '2024-10-08', '2025-07-25', '.', '김천', '김길종', '2025-04-15 22:44:57', '2025-04-15 22:44:57'), +(5, 'TKG-24016P', 'LG Chem P3RE Project', '2024-11-27', '2025-09-30', '.', '.', '장형태', '2025-04-15 22:46:36', '2025-04-15 22:46:36'), +(7, 'TKO-25003F', '25년 안전보건시설설비', '2025-01-03', '2025-12-31', '.', '.', '.', '2025-04-15 22:47:32', '2025-04-15 22:47:32'), +(8, 'TKG-25007P', 'P Project', '2025-01-16', '2025-10-31', '.', '오창읍', '장형태', '2025-04-15 22:48:50', '2025-04-15 22:48:50'), +(10, 'TKR-25008P', 'DIG Airgas LG CHEM', '2025-01-23', '2025-10-15', '.', '여수', '서태원', '2025-04-15 22:50:05', '2025-04-15 22:50:05'), +(11, 'TKR-25010P', 'FK FISCHER Project', '2025-03-12', '2025-11-30', '.', '울산', '전상신', '2025-04-15 22:51:12', '2025-04-15 22:51:12'), +(12, 'TKO-24007P', 'MP7 Project', '2024-07-03', '2025-01-05', '.', '.', '윤지민', '2025-04-15 23:56:26', '2025-04-15 23:56:26'), +(13, '연차/휴무', '연차/휴무', '2025-01-01', '2025-12-31', '.', '.', '.', '2025-04-16 01:58:23', '2025-04-16 01:58:23'), +(14, 'TKO-25009R', 'M Project', '2025-08-01', '2025-12-31', '', '', '이민후', '2025-09-28 22:13:33', '2025-09-28 22:13:33'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Tasks` +-- + +CREATE TABLE `Tasks` ( + `task_id` int(11) NOT NULL, + `category` varchar(255) NOT NULL, + `subcategory` varchar(255) DEFAULT NULL, + `task_name` varchar(255) NOT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Tasks` +-- + +INSERT INTO `Tasks` (`task_id`, `category`, `subcategory`, `task_name`, `description`, `created_at`, `updated_at`) VALUES +(1, 'Base', 'Fabrication', '용접', '...', '2025-04-15 10:41:43', '2025-04-15 10:41:43'), +(3, 'Vessel', 'MI and Marking', 'Marking', '..', '2025-04-15 22:25:58', '2025-04-15 22:25:58'), +(4, 'Vessel', 'Cutting', '자재 커팅', '..', '2025-04-15 22:26:17', '2025-04-15 22:26:17'), +(5, 'Vessel', 'Fabrication', '용접', '..', '2025-04-15 22:26:43', '2025-04-15 22:26:43'), +(7, 'PKG', 'Pipe Pre-Fabrication', '취부&용접', '배관사 1명\n용접사 1명', '2025-04-15 22:37:14', '2025-04-15 22:37:14'), +(8, 'PKG', '1st Piping Assembly', '1차 조립', '.', '2025-04-15 22:38:49', '2025-04-15 22:38:49'), +(9, 'PKG', 'Re-Assembly', '재조립', '.', '2025-04-15 22:39:18', '2025-04-15 22:39:18'), +(13, '작업지원', '구매팀', '.', '.', '2025-04-16 03:03:40', '2025-04-16 03:03:40'), +(14, '기타', '시설설비제작', '.', '.', '2025-04-16 03:30:53', '2025-04-16 03:30:53'), +(15, '기타', '휴가/연차/휴무', '.', '.', '2025-04-16 05:18:13', '2025-04-16 05:18:13'), +(16, 'PKG', '제품설치', '설치작업', 'Skid, 용기 등 설치', '2025-04-29 04:39:36', '2025-04-29 04:39:36'), +(18, '작업지원', '품질팀', 'test지원', '.', '2025-06-25 07:07:08', '2025-06-25 07:07:08'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `uploaded_documents` +-- + +CREATE TABLE `uploaded_documents` ( + `id` int(11) NOT NULL, + `title` varchar(255) NOT NULL, + `tags` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `original_name` varchar(255) DEFAULT NULL, + `stored_name` varchar(255) NOT NULL, + `file_path` varchar(500) DEFAULT NULL, + `file_type` varchar(50) DEFAULT NULL, + `file_size` int(11) DEFAULT NULL, + `submitted_by` varchar(100) DEFAULT NULL, + `dt_imported` tinyint(1) DEFAULT 0, + `dt_uuid` varchar(100) DEFAULT NULL, + `of_task_created` tinyint(1) DEFAULT 0, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Users` +-- + +CREATE TABLE `Users` ( + `user_id` int(11) NOT NULL, + `username` varchar(100) NOT NULL, + `password` varchar(255) NOT NULL, + `role` varchar(30) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `access_level` varchar(30) DEFAULT NULL, + `worker_id` int(11) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `last_login_at` datetime DEFAULT NULL, + `password_changed_at` datetime DEFAULT NULL, + `failed_login_attempts` int(11) DEFAULT 0, + `locked_until` datetime DEFAULT NULL, + `name` varchar(50) DEFAULT NULL, + `email` varchar(255) DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Users` +-- + +INSERT INTO `Users` (`user_id`, `username`, `password`, `role`, `created_at`, `access_level`, `worker_id`, `is_active`, `last_login_at`, `password_changed_at`, `failed_login_attempts`, `locked_until`, `name`, `email`, `updated_at`) VALUES +(1, 'hyungi', '$2b$10$lwSfKipx0fQ.9nfMUBmzt.WXzerdxuT5MVX4b3YhFeHxyYlUjM7bi', 'admin', '2025-05-06 05:03:02', 'system', NULL, 1, '2025-10-10 23:13:57', '2025-05-06 05:03:02', 0, NULL, NULL, NULL, '2025-10-10 23:13:57'), +(3, '김두수', '$2a$10$z3i2EVOotRFBj.KHzx5LQOKlXD0QHLNFEvJcd6FlO6/1TCYGk6SSu', 'leader', '2025-06-07 23:48:35', 'group_leader', 1, 1, '2025-10-10 23:32:38', '2025-06-15 07:40:39', 0, NULL, '김두수', NULL, '2025-10-10 23:32:38'), +(4, '김아무개', '$2a$10$QAJIoPyi.apz91exp8GsiO/prAD5Xwanht6XImP1jvKsy/7Ba/b8.', 'user', '2025-06-11 08:03:59', 'worker', NULL, 1, '2025-06-15 23:28:04', '2025-06-15 06:03:42', 0, NULL, '김아무개', NULL, '2025-06-15 23:28:04'), +(5, '임영규', '$2a$10$66ps/MEEi4BVABfJc5P0y.yCap09NhTMyd1A/7rFVxESytQGlB3wC', NULL, '2025-06-15 07:41:02', 'group_leader', 3, 1, '2025-10-01 06:55:37', '2025-06-15 07:41:02', 0, NULL, '임영규', NULL, '2025-10-01 06:55:37'), +(6, '반치원', '$2a$10$jcn6f7flRLZlr5yKQcXDIePodRK0rsM4deNnNGjuOlredeTVsRYZ6', NULL, '2025-06-15 07:41:32', 'group_leader', 3, 1, '2025-09-11 06:40:19', '2025-06-15 07:41:32', 0, NULL, '반치원', NULL, '2025-09-11 06:40:19'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `Workers` +-- + +CREATE TABLE `Workers` ( + `worker_id` int(11) NOT NULL, + `worker_name` varchar(100) NOT NULL, + `join_date` date DEFAULT NULL, + `job_type` varchar(100) DEFAULT NULL, + `salary` decimal(10,2) DEFAULT NULL, + `annual_leave` int(11) DEFAULT NULL, + `status` text DEFAULT 'active', + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `Workers` +-- + +INSERT INTO `Workers` (`worker_id`, `worker_name`, `join_date`, `job_type`, `salary`, `annual_leave`, `status`, `created_at`, `updated_at`) VALUES +(1, '김두수', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:08', '2025-04-15 22:23:08'), +(2, '임영규', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:17', '2025-04-15 22:23:17'), +(3, '반치원', '2025-04-01', '배관', 220000.00, 15, '..', '2025-04-15 22:23:22', '2025-04-15 22:23:22'), +(4, '황인용', '2025-04-01', '가공,조공', 220000.00, 15, '..', '2025-04-15 22:23:33', '2025-04-15 22:23:33'), +(5, '표영진', '2025-04-01', '가공,조공', 220000.00, 15, '..', '2025-04-15 22:23:38', '2025-04-15 22:23:38'), +(6, '김윤섭', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:23:46', '2025-04-15 22:23:46'), +(7, '이창호', '2025-04-01', '용접,배관', 220000.00, 15, '..', '2025-04-15 22:23:51', '2025-04-15 22:23:51'), +(8, '최광욱', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:23:57', '2025-04-15 22:23:57'), +(9, '박현수', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:24:01', '2025-04-15 22:24:01'), +(10, '조윤호', '2025-04-01', '용접', 220000.00, 15, '..', '2025-04-15 22:24:07', '2025-04-15 22:24:07'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `worker_groups` +-- + +CREATE TABLE `worker_groups` ( + `id` int(11) NOT NULL, + `group_leader_id` int(11) NOT NULL, + `worker_id` int(11) NOT NULL, + `group_name` varchar(100) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `WorkReports` +-- + +CREATE TABLE `WorkReports` ( + `id` int(11) NOT NULL, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `morning_task_id` int(11) DEFAULT NULL, + `afternoon_task_id` int(11) DEFAULT NULL, + `overtime_hours` decimal(4,1) DEFAULT 0.0, + `overtime_task_id` int(11) DEFAULT NULL, + `work_details` text DEFAULT NULL, + `note` text DEFAULT NULL, + `memo` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `morning_project_id` int(11) DEFAULT NULL, + `afternoon_project_id` int(11) DEFAULT NULL, + `overtime_project_id` int(11) DEFAULT NULL, + `task_id` int(11) DEFAULT NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `WorkReports` +-- + +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(176, '2025-01-02', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(177, '2025-01-02', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(178, '2025-01-02', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(179, '2025-01-02', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(180, '2025-01-02', 8, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(181, '2025-01-02', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(182, '2025-01-02', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 9), +(183, '2025-01-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:40:56', '2025-04-16 05:40:56', NULL, NULL, NULL, 15), +(194, '2025-01-03', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(195, '2025-01-03', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(196, '2025-01-03', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 15), +(197, '2025-01-03', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(198, '2025-01-03', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 15), +(199, '2025-01-03', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(200, '2025-01-03', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(201, '2025-01-03', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(202, '2025-01-03', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:42:07', '2025-04-16 05:42:07', NULL, NULL, NULL, 9), +(203, '2025-01-04', 7, 12, NULL, NULL, NULL, NULL, '휴일근무', NULL, NULL, '2025-04-16 05:43:25', '2025-04-16 05:43:25', NULL, NULL, NULL, 12), +(204, '2025-01-06', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:03', '2025-04-16 05:44:03', NULL, NULL, NULL, 12), +(205, '2025-01-06', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:03', '2025-04-16 05:44:03', NULL, NULL, NULL, 12), +(206, '2025-01-06', 2, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(207, '2025-01-06', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(208, '2025-01-06', 8, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(209, '2025-01-06', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(210, '2025-01-06', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(211, '2025-01-06', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(212, '2025-01-06', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:44:04', '2025-04-16 05:44:04', NULL, NULL, NULL, 12), +(213, '2025-01-07', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(214, '2025-01-07', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 1), +(215, '2025-01-07', 3, 12, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(216, '2025-01-07', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(217, '2025-01-07', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 1), +(218, '2025-01-07', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(219, '2025-01-07', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:24', '2025-04-16 05:45:24', NULL, NULL, NULL, 12), +(220, '2025-01-07', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:25', '2025-04-16 05:45:25', NULL, NULL, NULL, 12), +(221, '2025-01-07', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:45:25', '2025-04-16 05:45:25', NULL, NULL, NULL, 1), +(222, '2025-01-08', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(223, '2025-01-08', 2, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(224, '2025-01-08', 3, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(225, '2025-01-08', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(226, '2025-01-08', 8, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(227, '2025-01-08', 9, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(228, '2025-01-08', 6, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(229, '2025-01-08', 4, 2, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 1), +(230, '2025-01-08', 5, 12, NULL, NULL, 1.0, NULL, '근무', NULL, NULL, '2025-04-16 05:46:50', '2025-04-16 05:46:50', NULL, NULL, NULL, 13), +(231, '2025-01-09', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(232, '2025-01-09', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(233, '2025-01-09', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(234, '2025-01-09', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(235, '2025-01-09', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(236, '2025-01-09', 6, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(237, '2025-01-09', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 1), +(238, '2025-01-09', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(239, '2025-01-09', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:48:02', '2025-04-16 05:48:02', NULL, NULL, NULL, 13), +(240, '2025-01-10', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:16', '2025-04-16 05:49:16', NULL, NULL, NULL, 13), +(241, '2025-01-10', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(242, '2025-01-10', 3, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(243, '2025-01-10', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(244, '2025-01-10', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(245, '2025-01-10', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(246, '2025-01-10', 6, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 15), +(247, '2025-01-10', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 1), +(248, '2025-01-10', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:49:17', '2025-04-16 05:49:17', NULL, NULL, NULL, 13), +(249, '2025-01-13', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(250, '2025-01-13', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(251, '2025-01-13', 3, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(252, '2025-01-13', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(253, '2025-01-13', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(254, '2025-01-13', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(255, '2025-01-13', 6, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 1), +(256, '2025-01-13', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 15), +(257, '2025-01-13', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:50:22', '2025-04-16 05:50:22', NULL, NULL, NULL, 13), +(258, '2025-01-14', 1, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(259, '2025-01-14', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(260, '2025-01-14', 3, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(261, '2025-01-14', 7, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(262, '2025-01-14', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(263, '2025-01-14', 9, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(265, '2025-01-14', 4, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(266, '2025-01-14', 5, 12, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 13), +(267, '2025-01-14', 6, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:51:24', '2025-04-16 05:51:24', NULL, NULL, NULL, 1), +(268, '2025-01-15', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(269, '2025-01-15', 2, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 14), +(270, '2025-01-15', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(271, '2025-01-15', 7, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 13), +(272, '2025-01-15', 8, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 14), +(273, '2025-01-15', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(275, '2025-01-15', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:37', '2025-04-16 05:52:37', NULL, NULL, NULL, 1), +(276, '2025-01-15', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:38', '2025-04-16 05:52:38', NULL, NULL, NULL, 1), +(277, '2025-01-15', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:52:38', '2025-04-16 05:52:38', NULL, NULL, NULL, 1), +(278, '2025-01-16', 1, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(279, '2025-01-16', 2, 7, NULL, NULL, NULL, NULL, '근무', NULL, '볼트 보관함 제작', '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 14), +(280, '2025-01-16', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(281, '2025-01-16', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 1), +(282, '2025-01-16', 8, 7, NULL, NULL, NULL, NULL, '근무', NULL, '볼트 보관함 제작', '2025-04-16 05:54:11', '2025-04-16 05:54:11', NULL, NULL, NULL, 14), +(283, '2025-01-16', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(285, '2025-01-16', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(286, '2025-01-16', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(287, '2025-01-16', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:54:12', '2025-04-16 05:54:12', NULL, NULL, NULL, 1), +(288, '2025-01-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(289, '2025-01-17', 2, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(290, '2025-01-17', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(291, '2025-01-17', 7, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(292, '2025-01-17', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(293, '2025-01-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(295, '2025-01-17', 4, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(296, '2025-01-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(297, '2025-01-17', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:55:22', '2025-04-16 05:55:22', NULL, NULL, NULL, 1), +(298, '2025-01-20', 1, 7, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(299, '2025-01-20', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 8), +(300, '2025-01-20', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(301, '2025-01-20', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(302, '2025-01-20', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(303, '2025-01-20', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(304, '2025-01-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 1), +(305, '2025-01-20', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(306, '2025-01-20', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:58:05', '2025-04-16 05:58:05', NULL, NULL, NULL, 14), +(307, '2025-01-21', 1, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 15), +(308, '2025-01-21', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 8), +(309, '2025-01-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(310, '2025-01-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(311, '2025-01-21', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 8), +(312, '2025-01-21', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 15), +(313, '2025-01-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(314, '2025-01-21', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:06', '2025-04-16 05:59:06', NULL, NULL, NULL, 1), +(315, '2025-01-21', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 05:59:07', '2025-04-16 05:59:07', NULL, NULL, NULL, 1), +(316, '2025-01-22', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(317, '2025-01-22', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(318, '2025-01-22', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(319, '2025-01-22', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(320, '2025-01-22', 8, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(321, '2025-01-22', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(322, '2025-01-22', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(323, '2025-01-22', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 1), +(324, '2025-01-22', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:00:28', '2025-04-16 06:00:28', NULL, NULL, NULL, 8), +(325, '2025-01-23', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(326, '2025-01-23', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 8), +(327, '2025-01-23', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(328, '2025-01-23', 7, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(329, '2025-01-23', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(330, '2025-01-23', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(331, '2025-01-23', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(332, '2025-01-23', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 1), +(333, '2025-01-23', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:01:57', '2025-04-16 06:01:57', NULL, NULL, NULL, 8), +(334, '2025-01-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(335, '2025-01-24', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 8), +(336, '2025-01-24', 3, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(337, '2025-01-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(338, '2025-01-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(339, '2025-01-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(340, '2025-01-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(341, '2025-01-24', 5, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 8), +(342, '2025-01-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:03:43', '2025-04-16 06:03:43', NULL, NULL, NULL, 1), +(343, '2025-02-03', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(344, '2025-02-03', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 8), +(345, '2025-02-03', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(346, '2025-02-03', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(347, '2025-02-03', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(348, '2025-02-03', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(349, '2025-02-03', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(350, '2025-02-03', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 8), +(351, '2025-02-03', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:07:37', '2025-04-16 06:07:37', NULL, NULL, NULL, 1), +(352, '2025-02-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(353, '2025-02-04', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(354, '2025-02-04', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 8), +(355, '2025-02-04', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(356, '2025-02-04', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(357, '2025-02-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(358, '2025-02-04', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(359, '2025-02-04', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 8), +(360, '2025-02-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:08:43', '2025-04-16 06:08:43', NULL, NULL, NULL, 1), +(361, '2025-02-05', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 8), +(362, '2025-02-05', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(363, '2025-02-05', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(364, '2025-02-05', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(365, '2025-02-05', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(366, '2025-02-05', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:02', '2025-04-16 06:10:02', NULL, NULL, NULL, 1), +(367, '2025-02-05', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 1), +(368, '2025-02-05', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 8), +(369, '2025-02-05', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:03', '2025-04-16 06:10:03', NULL, NULL, NULL, 1), +(370, '2025-02-06', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(371, '2025-02-06', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 15), +(372, '2025-02-06', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(373, '2025-02-06', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(374, '2025-02-06', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(375, '2025-02-06', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(376, '2025-02-06', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(377, '2025-02-06', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(378, '2025-02-06', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:10:55', '2025-04-16 06:10:55', NULL, NULL, NULL, 1), +(379, '2025-02-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(380, '2025-02-07', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 8), +(381, '2025-02-07', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(382, '2025-02-07', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 15), +(383, '2025-02-07', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(384, '2025-02-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(385, '2025-02-07', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(386, '2025-02-07', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 8), +(387, '2025-02-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:11:54', '2025-04-16 06:11:54', NULL, NULL, NULL, 1), +(388, '2025-02-10', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(389, '2025-02-10', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 8), +(390, '2025-02-10', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(391, '2025-02-10', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(392, '2025-02-10', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(393, '2025-02-10', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(394, '2025-02-10', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(395, '2025-02-10', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 8), +(396, '2025-02-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:12:54', '2025-04-16 06:12:54', NULL, NULL, NULL, 1), +(397, '2025-02-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(398, '2025-02-11', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 8), +(399, '2025-02-11', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(400, '2025-02-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(401, '2025-02-11', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(402, '2025-02-11', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(403, '2025-02-11', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(404, '2025-02-11', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 8), +(405, '2025-02-11', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:13:53', '2025-04-16 06:13:53', NULL, NULL, NULL, 1), +(406, '2025-02-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(407, '2025-02-12', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 8), +(408, '2025-02-12', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(409, '2025-02-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(410, '2025-02-12', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(411, '2025-02-12', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(412, '2025-02-12', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 15), +(413, '2025-02-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(414, '2025-02-12', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:14:52', '2025-04-16 06:14:52', NULL, NULL, NULL, 1), +(415, '2025-02-13', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(416, '2025-02-13', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 7), +(417, '2025-02-13', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(418, '2025-02-13', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(419, '2025-02-13', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(420, '2025-02-13', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(421, '2025-02-13', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(422, '2025-02-13', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 7), +(423, '2025-02-13', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:16:00', '2025-04-16 06:16:00', NULL, NULL, NULL, 1), +(424, '2025-02-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(425, '2025-02-14', 2, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 7), +(426, '2025-02-14', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(427, '2025-02-14', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(428, '2025-02-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(429, '2025-02-14', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(430, '2025-02-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(431, '2025-02-14', 4, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 7), +(432, '2025-02-14', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:17:21', '2025-04-16 06:17:21', NULL, NULL, NULL, 1), +(433, '2025-02-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:39', '2025-04-16 06:18:39', NULL, NULL, NULL, 1), +(434, '2025-02-17', 2, 2, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 8), +(435, '2025-02-17', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(436, '2025-02-17', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(437, '2025-02-17', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 15), +(438, '2025-02-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(439, '2025-02-17', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(440, '2025-02-17', 4, 2, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 8), +(441, '2025-02-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:18:40', '2025-04-16 06:18:40', NULL, NULL, NULL, 1), +(442, '2025-02-18', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(443, '2025-02-18', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 15), +(444, '2025-02-18', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(445, '2025-02-18', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(446, '2025-02-18', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(447, '2025-02-18', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(448, '2025-02-18', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 7), +(449, '2025-02-18', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(450, '2025-02-18', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:19:57', '2025-04-16 06:19:57', NULL, NULL, NULL, 1), +(451, '2025-02-19', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(452, '2025-02-19', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(453, '2025-02-19', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(454, '2025-02-19', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(455, '2025-02-19', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(456, '2025-02-19', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(457, '2025-02-19', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(458, '2025-02-19', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(459, '2025-02-19', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:21:01', '2025-04-16 06:21:01', NULL, NULL, NULL, 7), +(460, '2025-02-20', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(461, '2025-02-20', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(462, '2025-02-20', 3, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(463, '2025-02-20', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(464, '2025-02-20', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(465, '2025-02-20', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(466, '2025-02-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(467, '2025-02-20', 7, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(468, '2025-02-20', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:22:23', '2025-04-16 06:22:23', NULL, NULL, NULL, 7), +(469, '2025-02-21', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(470, '2025-02-21', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(471, '2025-02-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(472, '2025-02-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(473, '2025-02-21', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(474, '2025-02-21', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(475, '2025-02-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(476, '2025-02-21', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(477, '2025-02-21', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:23:40', '2025-04-16 06:23:40', NULL, NULL, NULL, 7), +(478, '2025-02-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(479, '2025-02-24', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(480, '2025-02-24', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(481, '2025-02-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(482, '2025-02-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(483, '2025-02-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(484, '2025-02-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(485, '2025-02-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:32', '2025-04-16 06:24:32', NULL, NULL, NULL, 7), +(486, '2025-02-24', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:24:33', '2025-04-16 06:24:33', NULL, NULL, NULL, 7), +(487, '2025-02-24', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, '근무시작', '2025-04-16 06:25:07', '2025-04-16 06:25:07', NULL, NULL, NULL, 7), +(488, '2025-02-25', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(489, '2025-02-25', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(490, '2025-02-25', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(491, '2025-02-25', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(492, '2025-02-25', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(493, '2025-02-25', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(494, '2025-02-25', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(495, '2025-02-25', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(496, '2025-02-25', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(497, '2025-02-25', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:26:02', '2025-04-16 06:26:02', NULL, NULL, NULL, 7), +(498, '2025-02-26', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '당진출장 건', '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 14), +(499, '2025-02-26', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(500, '2025-02-26', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(501, '2025-02-26', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '당진출장 건', '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 14), +(502, '2025-02-26', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(503, '2025-02-26', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(504, '2025-02-26', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(505, '2025-02-26', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 15), +(506, '2025-02-26', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(507, '2025-02-26', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:27:50', '2025-04-16 06:27:50', NULL, NULL, NULL, 7), +(508, '2025-02-27', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(509, '2025-02-27', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(510, '2025-02-27', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(511, '2025-02-27', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(512, '2025-02-27', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(513, '2025-02-27', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(514, '2025-02-27', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(515, '2025-02-27', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(516, '2025-02-27', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(517, '2025-02-27', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:28:41', '2025-04-16 06:28:41', NULL, NULL, NULL, 7), +(518, '2025-02-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 13), +(519, '2025-02-28', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(520, '2025-02-28', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(521, '2025-02-28', 7, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 13), +(522, '2025-02-28', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(523, '2025-02-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(524, '2025-02-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(525, '2025-02-28', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(526, '2025-02-28', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 15), +(527, '2025-02-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:29:53', '2025-04-16 06:29:53', NULL, NULL, NULL, 7), +(528, '2025-03-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(529, '2025-03-04', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(530, '2025-03-04', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 8), +(531, '2025-03-04', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 15), +(532, '2025-03-04', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(533, '2025-03-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(534, '2025-03-04', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(535, '2025-03-04', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(536, '2025-03-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 7), +(537, '2025-03-04', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:32:11', '2025-04-16 06:32:11', NULL, NULL, NULL, 8), +(538, '2025-03-05', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(539, '2025-03-05', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(540, '2025-03-05', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 8), +(541, '2025-03-05', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(542, '2025-03-05', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(543, '2025-03-05', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(544, '2025-03-05', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(545, '2025-03-05', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 15), +(546, '2025-03-05', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 7), +(547, '2025-03-05', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:33:15', '2025-04-16 06:33:15', NULL, NULL, NULL, 8), +(548, '2025-03-06', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(549, '2025-03-06', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(550, '2025-03-06', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 8), +(551, '2025-03-06', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 15), +(552, '2025-03-06', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(553, '2025-03-06', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(554, '2025-03-06', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(555, '2025-03-06', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(556, '2025-03-06', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 7), +(557, '2025-03-06', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:34:18', '2025-04-16 06:34:18', NULL, NULL, NULL, 8), +(558, '2025-03-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(559, '2025-03-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 13), +(560, '2025-03-07', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 8), +(561, '2025-03-07', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 15), +(562, '2025-03-07', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(563, '2025-03-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(564, '2025-03-07', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(565, '2025-03-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 13), +(566, '2025-03-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 7), +(567, '2025-03-07', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:35:36', '2025-04-16 06:35:36', NULL, NULL, NULL, 8), +(568, '2025-03-10', 1, 1, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(569, '2025-03-10', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 3), +(570, '2025-03-10', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(571, '2025-03-10', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 15), +(572, '2025-03-10', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 7), +(573, '2025-03-10', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 15), +(574, '2025-03-10', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 7), +(575, '2025-03-10', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 3), +(576, '2025-03-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(577, '2025-03-10', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:37:11', '2025-04-16 06:37:11', NULL, NULL, NULL, 8), +(578, '2025-03-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:06', '2025-04-16 06:39:06', NULL, NULL, NULL, 8), +(579, '2025-03-11', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(580, '2025-03-11', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(581, '2025-03-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(582, '2025-03-11', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(583, '2025-03-11', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 15), +(584, '2025-03-11', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 7), +(585, '2025-03-11', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(586, '2025-03-11', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(587, '2025-03-11', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:39:07', '2025-04-16 06:39:07', NULL, NULL, NULL, 8), +(588, '2025-03-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(589, '2025-03-12', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(590, '2025-03-12', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(591, '2025-03-12', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(592, '2025-03-12', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(593, '2025-03-12', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 15), +(594, '2025-03-12', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(595, '2025-03-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 7), +(596, '2025-03-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(597, '2025-03-12', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:40:08', '2025-04-16 06:40:08', NULL, NULL, NULL, 8), +(598, '2025-03-13', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(599, '2025-03-13', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(600, '2025-03-13', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 8), +(601, '2025-03-13', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(602, '2025-03-13', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(603, '2025-03-13', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 15), +(604, '2025-03-13', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:07', '2025-04-16 06:41:07', NULL, NULL, NULL, 7), +(605, '2025-03-13', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(606, '2025-03-13', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(607, '2025-03-13', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:41:08', '2025-04-16 06:41:08', NULL, NULL, NULL, 8), +(608, '2025-03-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(609, '2025-03-14', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 4), +(610, '2025-03-14', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(612, '2025-03-14', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(613, '2025-03-14', 9, 13, NULL, NULL, NULL, NULL, '유급', NULL, '결혼(5일)', '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 15), +(614, '2025-03-14', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(615, '2025-03-14', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(616, '2025-03-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 8), +(617, '2025-03-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:42:24', '2025-04-16 06:42:24', NULL, NULL, NULL, 7), +(628, '2025-03-18', 1, 1, NULL, NULL, NULL, NULL, '조퇴', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(629, '2025-03-18', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(630, '2025-03-18', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(631, '2025-03-18', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(632, '2025-03-18', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(633, '2025-03-18', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 15), +(634, '2025-03-18', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(635, '2025-03-18', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 4), +(636, '2025-03-18', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(637, '2025-03-18', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:46:29', '2025-04-16 06:46:29', NULL, NULL, NULL, 8), +(648, '2025-03-17', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(649, '2025-03-17', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 4), +(650, '2025-03-17', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(651, '2025-03-17', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 4), +(652, '2025-03-17', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(653, '2025-03-17', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 15), +(654, '2025-03-17', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(655, '2025-03-17', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(656, '2025-03-17', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 8), +(657, '2025-03-17', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:50:50', '2025-04-16 06:50:50', NULL, NULL, NULL, 7), +(658, '2025-03-19', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 4), +(659, '2025-03-19', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(660, '2025-03-19', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(661, '2025-03-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 4), +(662, '2025-03-19', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:33', '2025-04-16 06:52:33', NULL, NULL, NULL, 8), +(663, '2025-03-19', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(664, '2025-03-19', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(665, '2025-03-19', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, '용접기 보관함 제작', '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 14), +(666, '2025-03-19', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 4), +(667, '2025-03-19', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:52:34', '2025-04-16 06:52:34', NULL, NULL, NULL, 8), +(668, '2025-03-20', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(669, '2025-03-20', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(670, '2025-03-20', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(671, '2025-03-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(672, '2025-03-20', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(673, '2025-03-20', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(674, '2025-03-20', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(675, '2025-03-20', 4, 7, NULL, NULL, 2.0, NULL, '근무', NULL, '용접기 보관함 제작', '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 14), +(676, '2025-03-20', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 4), +(677, '2025-03-20', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 06:54:20', '2025-04-16 06:54:20', NULL, NULL, NULL, 8), +(678, '2025-03-21', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:27', '2025-04-16 21:34:27', NULL, NULL, NULL, 8), +(679, '2025-03-21', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(680, '2025-03-21', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(681, '2025-03-21', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(682, '2025-03-21', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(683, '2025-03-21', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(684, '2025-03-21', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(685, '2025-03-21', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, '용기 보관함 제작', '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 14), +(686, '2025-03-21', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 4), +(687, '2025-03-21', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:34:28', '2025-04-16 21:34:28', NULL, NULL, NULL, 8), +(688, '2025-03-24', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(689, '2025-03-24', 2, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(690, '2025-03-24', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(691, '2025-03-24', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(692, '2025-03-24', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 5), +(693, '2025-03-24', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:47', '2025-04-16 21:39:47', NULL, NULL, NULL, 8), +(694, '2025-03-24', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(695, '2025-03-24', 4, 7, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 보관함 제작', '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 14), +(696, '2025-03-24', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(697, '2025-03-24', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:39:48', '2025-04-16 21:39:48', NULL, NULL, NULL, 8), +(698, '2025-03-25', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(699, '2025-03-25', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(700, '2025-03-25', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(701, '2025-03-25', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(702, '2025-03-25', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(703, '2025-03-25', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(704, '2025-03-25', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(705, '2025-03-25', 4, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 14), +(706, '2025-03-25', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 5), +(707, '2025-03-25', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:42:13', '2025-04-16 21:42:13', NULL, NULL, NULL, 13), +(708, '2025-03-26', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 13), +(709, '2025-03-26', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 15), +(710, '2025-03-26', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(711, '2025-03-26', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(712, '2025-03-26', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(713, '2025-03-26', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(714, '2025-03-26', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(715, '2025-03-26', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 13), +(716, '2025-03-26', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 5), +(717, '2025-03-26', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:43:37', '2025-04-16 21:43:37', NULL, NULL, NULL, 8), +(718, '2025-03-27', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(719, '2025-03-27', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(720, '2025-03-27', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(721, '2025-03-27', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(722, '2025-03-27', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(723, '2025-03-27', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(724, '2025-03-27', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 15), +(725, '2025-03-27', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 5), +(726, '2025-03-27', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(727, '2025-03-27', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-16 21:45:14', '2025-04-16 21:45:14', NULL, NULL, NULL, 8), +(728, '2025-03-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(729, '2025-03-28', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(730, '2025-03-28', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 15), +(731, '2025-03-28', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 15), +(732, '2025-03-28', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(733, '2025-03-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(734, '2025-03-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(735, '2025-03-28', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(736, '2025-03-28', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 5), +(737, '2025-03-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:46:31', '2025-04-16 21:46:31', NULL, NULL, NULL, 8), +(738, '2025-03-31', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(739, '2025-03-31', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 5), +(740, '2025-03-31', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(741, '2025-03-31', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(742, '2025-03-31', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(743, '2025-03-31', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(744, '2025-03-31', 10, 13, NULL, NULL, NULL, NULL, '유급', NULL, '외조모상(2일)', '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 15), +(745, '2025-03-31', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 5), +(746, '2025-03-31', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(747, '2025-03-31', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-16 21:47:37', '2025-04-16 21:47:37', NULL, NULL, NULL, 8), +(748, '2025-03-14', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-17 01:53:24', '2025-04-17 01:53:24', NULL, NULL, NULL, 4), +(749, '2025-04-01', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(750, '2025-04-01', 2, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(751, '2025-04-01', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(752, '2025-04-01', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(753, '2025-04-01', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(754, '2025-04-01', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(755, '2025-04-01', 10, 13, NULL, NULL, NULL, NULL, '유급', NULL, '외조모상', '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 15), +(756, '2025-04-01', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 5), +(757, '2025-04-01', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:42', '2025-04-17 04:22:42', NULL, NULL, NULL, 9), +(758, '2025-04-01', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:22:43', '2025-04-17 04:22:43', NULL, NULL, NULL, 9), +(769, '2025-04-02', 1, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-17 04:25:55', '2025-04-17 04:25:55', NULL, NULL, NULL, 9), +(770, '2025-04-02', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(771, '2025-04-02', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(773, '2025-04-02', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(774, '2025-04-02', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(775, '2025-04-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 15), +(776, '2025-04-02', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 15), +(777, '2025-04-02', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(778, '2025-04-02', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:25:56', '2025-04-17 04:25:56', NULL, NULL, NULL, 9), +(779, '2025-04-03', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(780, '2025-04-03', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(781, '2025-04-03', 3, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(783, '2025-04-03', 8, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(784, '2025-04-03', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(785, '2025-04-03', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(786, '2025-04-03', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(787, '2025-04-03', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(788, '2025-04-03', 6, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:27:12', '2025-04-17 04:27:12', NULL, NULL, NULL, 9), +(789, '2025-04-04', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(790, '2025-04-04', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(791, '2025-04-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(792, '2025-04-04', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(793, '2025-04-04', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(794, '2025-04-04', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(795, '2025-04-04', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(796, '2025-04-04', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(797, '2025-04-04', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 9), +(798, '2025-04-04', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:30:07', '2025-04-17 04:30:07', NULL, NULL, NULL, 5), +(799, '2025-04-07', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(800, '2025-04-07', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(801, '2025-04-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(802, '2025-04-07', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(803, '2025-04-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(804, '2025-04-07', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(805, '2025-04-07', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(806, '2025-04-07', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(807, '2025-04-07', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 9), +(808, '2025-04-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:39:43', '2025-04-17 04:39:43', NULL, NULL, NULL, 5), +(809, '2025-04-08', 1, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(811, '2025-04-08', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(812, '2025-04-08', 7, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(813, '2025-04-08', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(814, '2025-04-08', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(815, '2025-04-08', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(816, '2025-04-08', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(817, '2025-04-08', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 9), +(818, '2025-04-08', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:41:16', '2025-04-17 04:41:16', NULL, NULL, NULL, 5), +(819, '2025-04-09', 1, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-17 04:43:02', '2025-04-17 04:43:02', NULL, NULL, NULL, 9), +(820, '2025-04-09', 2, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:02', '2025-04-17 04:43:02', NULL, NULL, NULL, 9), +(821, '2025-04-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(822, '2025-04-09', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(823, '2025-04-09', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(824, '2025-04-09', 9, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(825, '2025-04-09', 10, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(826, '2025-04-09', 4, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(827, '2025-04-09', 5, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 9), +(828, '2025-04-09', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-04-17 04:43:03', '2025-04-17 04:43:03', NULL, NULL, NULL, 5), +(829, '2025-04-10', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(830, '2025-04-10', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(831, '2025-04-10', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(832, '2025-04-10', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(833, '2025-04-10', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(834, '2025-04-10', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(835, '2025-04-10', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(836, '2025-04-10', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(837, '2025-04-10', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 9), +(838, '2025-04-10', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:44:30', '2025-04-17 04:44:30', NULL, NULL, NULL, 5), +(839, '2025-04-11', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 9), +(840, '2025-04-11', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 9), +(841, '2025-04-11', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:24', '2025-04-17 04:46:24', NULL, NULL, NULL, 5), +(842, '2025-04-11', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(843, '2025-04-11', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 5), +(844, '2025-04-11', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 15), +(845, '2025-04-11', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 5), +(846, '2025-04-11', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(847, '2025-04-11', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 15), +(848, '2025-04-11', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:46:25', '2025-04-17 04:46:25', NULL, NULL, NULL, 9), +(849, '2025-04-14', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(850, '2025-04-14', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(851, '2025-04-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 5), +(852, '2025-04-14', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:37', '2025-04-17 04:47:37', NULL, NULL, NULL, 9), +(853, '2025-04-14', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 5), +(854, '2025-04-14', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(855, '2025-04-14', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(856, '2025-04-14', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(857, '2025-04-14', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(858, '2025-04-14', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:47:38', '2025-04-17 04:47:38', NULL, NULL, NULL, 9), +(859, '2025-04-17', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(860, '2025-04-17', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(861, '2025-04-17', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(862, '2025-04-17', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(863, '2025-04-17', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(864, '2025-04-17', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(865, '2025-04-17', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(866, '2025-04-17', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(867, '2025-04-17', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 9), +(868, '2025-04-17', 6, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-04-17 04:48:39', '2025-04-17 04:48:39', NULL, NULL, NULL, 5), +(879, '2025-04-21', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(880, '2025-04-21', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(881, '2025-04-21', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(882, '2025-04-21', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(883, '2025-04-21', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(884, '2025-04-21', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(885, '2025-04-21', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(886, '2025-04-21', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(887, '2025-04-21', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 14), +(888, '2025-04-21', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-21 06:22:20', '2025-04-21 06:22:20', NULL, NULL, NULL, 5), +(889, '2025-04-22', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(890, '2025-04-22', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(891, '2025-04-22', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(892, '2025-04-22', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(893, '2025-04-22', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(894, '2025-04-22', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(895, '2025-04-22', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(896, '2025-04-22', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(897, '2025-04-22', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, 'ICK 크레인 공사', '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 14), +(898, '2025-04-22', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-22 01:49:11', '2025-04-22 01:49:11', NULL, NULL, NULL, 5), +(899, '2025-04-23', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(900, '2025-04-23', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(901, '2025-04-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(902, '2025-04-23', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(903, '2025-04-23', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(904, '2025-04-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(905, '2025-04-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(906, '2025-04-23', 4, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(907, '2025-04-23', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 14), +(908, '2025-04-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-23 06:57:29', '2025-04-23 06:57:29', NULL, NULL, NULL, 5), +(909, '2025-04-24', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, '벨브 부적합 관련 작업 추가', '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(910, '2025-04-24', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(911, '2025-04-24', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(912, '2025-04-24', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(913, '2025-04-24', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(914, '2025-04-24', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(915, '2025-04-24', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(916, '2025-04-24', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(917, '2025-04-24', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(918, '2025-04-24', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-24 05:42:30', '2025-04-24 05:42:30', NULL, NULL, NULL, 9), +(919, '2025-04-25', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(920, '2025-04-25', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(921, '2025-04-25', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 5), +(922, '2025-04-25', 7, 1, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(923, '2025-04-25', 8, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(924, '2025-04-25', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(925, '2025-04-25', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(926, '2025-04-25', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '확관 작업', '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 5), +(927, '2025-04-25', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:38', '2025-04-25 04:23:38', NULL, NULL, NULL, 9), +(928, '2025-04-25', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-25 04:23:39', '2025-04-25 04:23:39', NULL, NULL, NULL, 5), +(929, '2025-04-28', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:22', '2025-04-28 23:20:22', NULL, NULL, NULL, 9), +(930, '2025-04-28', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(931, '2025-04-28', 3, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(932, '2025-04-28', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(934, '2025-04-28', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(935, '2025-04-28', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(936, '2025-04-28', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(937, '2025-04-28', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(938, '2025-04-28', 6, 1, NULL, NULL, NULL, NULL, '근무', NULL, 'NCR 벨브 라인 설치', '2025-04-28 23:20:23', '2025-04-28 23:20:23', NULL, NULL, NULL, 9), +(939, '2025-04-29', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 9), +(940, '2025-04-29', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(941, '2025-04-29', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(942, '2025-04-29', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 9), +(943, '2025-04-29', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(944, '2025-04-29', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(945, '2025-04-29', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 14), +(946, '2025-04-29', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(947, '2025-04-29', 8, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(948, '2025-04-29', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-29 04:41:11', '2025-04-29 04:41:11', NULL, NULL, NULL, 16), +(949, '2025-04-30', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(950, '2025-04-30', 2, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(951, '2025-04-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(953, '2025-04-30', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 15), +(954, '2025-04-30', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(955, '2025-04-30', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(956, '2025-04-30', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 14), +(957, '2025-04-30', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 15), +(958, '2025-04-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-04-30 03:43:51', '2025-04-30 03:43:51', NULL, NULL, NULL, 16), +(959, '2025-04-30', 4, 7, NULL, NULL, NULL, NULL, '반반차', NULL, '제2공장 공사', '2025-04-30 04:22:04', '2025-04-30 04:22:04', NULL, NULL, NULL, 14), +(1023, '2025-04-15', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1024, '2025-04-15', 2, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1025, '2025-04-15', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1026, '2025-04-15', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1027, '2025-04-15', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1028, '2025-04-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1029, '2025-04-15', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1030, '2025-04-15', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1031, '2025-04-15', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 5), +(1032, '2025-04-15', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:01:35', '2025-05-07 01:01:35', NULL, NULL, NULL, 9), +(1033, '2025-04-16', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1034, '2025-04-16', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1035, '2025-04-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(1036, '2025-04-16', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1037, '2025-04-16', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1038, '2025-04-16', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1039, '2025-04-16', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1040, '2025-04-16', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 15), +(1041, '2025-04-16', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 5), +(1042, '2025-04-16', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:03:57', '2025-05-07 01:03:57', NULL, NULL, NULL, 9), +(1043, '2025-04-18', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1044, '2025-04-18', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1045, '2025-04-18', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1046, '2025-04-18', 4, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1047, '2025-04-18', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 15), +(1048, '2025-04-18', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1049, '2025-04-18', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1050, '2025-04-18', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1051, '2025-04-18', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 5), +(1052, '2025-04-18', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 01:05:17', '2025-05-07 01:05:17', NULL, NULL, NULL, 9), +(1053, '2025-04-02', 7, 1, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-07 02:19:00', '2025-05-07 02:19:00', NULL, NULL, NULL, 9), +(1054, '2025-04-03', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 02:19:45', '2025-05-07 02:19:45', NULL, NULL, NULL, 9), +(1055, '2025-04-08', 2, 1, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 02:20:22', '2025-05-07 02:20:22', NULL, NULL, NULL, 9), +(1056, '2025-04-28', 8, 1, NULL, NULL, NULL, NULL, '반반차', NULL, 'NCR 벨브라인 설치', '2025-05-07 02:21:44', '2025-05-07 02:21:44', NULL, NULL, NULL, 9), +(1057, '2025-05-02', 1, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1058, '2025-05-02', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1059, '2025-05-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1060, '2025-05-02', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1061, '2025-05-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1062, '2025-05-02', 6, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1063, '2025-05-02', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1064, '2025-05-02', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1065, '2025-05-02', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1066, '2025-05-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-07 03:13:26', '2025-05-07 03:13:26', NULL, NULL, NULL, 15), +(1067, '2025-05-07', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1068, '2025-05-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1069, '2025-05-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1070, '2025-05-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1071, '2025-05-07', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1072, '2025-05-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1073, '2025-05-07', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1074, '2025-05-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1075, '2025-05-07', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 14), +(1076, '2025-05-07', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 03:19:18', '2025-05-07 03:19:18', NULL, NULL, NULL, 16), +(1078, '2025-05-08', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1079, '2025-05-08', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1080, '2025-05-08', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1081, '2025-05-08', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1082, '2025-05-08', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1083, '2025-05-08', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1084, '2025-05-08', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1085, '2025-05-08', 9, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 14), +(1086, '2025-05-08', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-07 23:06:52', '2025-05-07 23:06:52', NULL, NULL, NULL, 16), +(1087, '2025-05-08', 1, 7, NULL, NULL, NULL, NULL, '반반차', NULL, '작업장 구역 설치', '2025-05-08 06:57:51', '2025-05-08 06:57:51', NULL, NULL, NULL, 14), +(1088, '2025-05-09', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1089, '2025-05-09', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1090, '2025-05-09', 3, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1091, '2025-05-09', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1092, '2025-05-09', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1093, '2025-05-09', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1094, '2025-05-09', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1095, '2025-05-09', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1096, '2025-05-09', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 16), +(1097, '2025-05-09', 10, 7, NULL, NULL, NULL, NULL, '근무', NULL, '작업장 구역 정리', '2025-05-09 06:12:16', '2025-05-09 06:12:16', NULL, NULL, NULL, 14), +(1100, '2025-05-12', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-11 21:52:46', '2025-05-11 21:52:46', NULL, NULL, NULL, 15), +(1108, '2025-05-12', 1, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1111, '2025-05-12', 5, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1113, '2025-05-12', 7, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1115, '2025-05-12', 9, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1116, '2025-05-12', 10, 1, NULL, NULL, NULL, NULL, '근무', NULL, '포장', '2025-05-12 23:55:17', '2025-05-12 23:55:17', NULL, NULL, NULL, 13), +(1117, '2025-05-13', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1118, '2025-05-13', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1119, '2025-05-13', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1120, '2025-05-13', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1121, '2025-05-13', 5, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1122, '2025-05-13', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1123, '2025-05-13', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 14), +(1124, '2025-05-13', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1125, '2025-05-13', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 3), +(1126, '2025-05-13', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:00:41', '2025-05-13 00:00:41', NULL, NULL, NULL, 7), +(1127, '2025-05-12', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1128, '2025-05-12', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1129, '2025-05-12', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1130, '2025-05-12', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-13 00:01:44', '2025-05-13 00:01:44', NULL, NULL, NULL, 3), +(1131, '2025-05-14', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1132, '2025-05-14', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1133, '2025-05-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1134, '2025-05-14', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1135, '2025-05-14', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1136, '2025-05-14', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1137, '2025-05-14', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 3), +(1138, '2025-05-14', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1139, '2025-05-14', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1140, '2025-05-14', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-14 22:42:17', '2025-05-14 22:42:17', NULL, NULL, NULL, 7), +(1141, '2025-05-15', 1, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 14), +(1142, '2025-05-15', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1143, '2025-05-15', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1144, '2025-05-15', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1145, '2025-05-15', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1146, '2025-05-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1147, '2025-05-15', 7, 7, NULL, NULL, NULL, NULL, '근무', NULL, '제2공장 공사', '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 14), +(1148, '2025-05-15', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1149, '2025-05-15', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 3), +(1150, '2025-05-15', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:53:53', '2025-05-16 02:53:53', NULL, NULL, NULL, 7), +(1151, '2025-05-16', 1, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1152, '2025-05-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1153, '2025-05-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1154, '2025-05-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1155, '2025-05-16', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1156, '2025-05-16', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1157, '2025-05-16', 7, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1158, '2025-05-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1159, '2025-05-16', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 3), +(1160, '2025-05-16', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-16 02:55:12', '2025-05-16 02:55:12', NULL, NULL, NULL, 7), +(1171, '2025-05-19', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1172, '2025-05-19', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 4), +(1173, '2025-05-19', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1174, '2025-05-19', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1175, '2025-05-19', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1176, '2025-05-19', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1177, '2025-05-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1179, '2025-05-19', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1180, '2025-05-19', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:47:56', '2025-05-22 04:47:56', NULL, NULL, NULL, 7), +(1181, '2025-05-21', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1183, '2025-05-21', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1184, '2025-05-21', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1185, '2025-05-21', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1186, '2025-05-21', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1187, '2025-05-21', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1188, '2025-05-21', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1189, '2025-05-21', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1190, '2025-05-21', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:49:38', '2025-05-22 04:49:38', NULL, NULL, NULL, 7), +(1191, '2025-05-20', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1192, '2025-05-20', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 3), +(1193, '2025-05-20', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1194, '2025-05-20', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1195, '2025-05-20', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1196, '2025-05-20', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1197, '2025-05-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1198, '2025-05-20', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1199, '2025-05-20', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1200, '2025-05-20', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-05-22 04:51:34', '2025-05-22 04:51:34', NULL, NULL, NULL, 7), +(1201, '2025-05-22', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1202, '2025-05-22', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 3), +(1203, '2025-05-22', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1204, '2025-05-22', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1205, '2025-05-22', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1206, '2025-05-22', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1207, '2025-05-22', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1208, '2025-05-22', 8, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1209, '2025-05-22', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1210, '2025-05-22', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-05-22 04:53:17', '2025-05-22 04:53:17', NULL, NULL, NULL, 7), +(1211, '2025-05-21', 2, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-22 04:54:12', '2025-05-22 04:54:12', NULL, NULL, NULL, 15), +(1215, '2025-05-26', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-05-26 06:58:00', '2025-05-26 06:58:00', NULL, NULL, NULL, 15), +(1222, '2025-05-19', 8, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-01 22:34:36', '2025-06-01 22:34:36', NULL, NULL, NULL, 3), +(1223, '2025-05-26', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1224, '2025-05-26', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1225, '2025-05-26', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1226, '2025-05-26', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1227, '2025-05-26', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1228, '2025-05-26', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1229, '2025-05-26', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 5), +(1230, '2025-05-26', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1231, '2025-05-26', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:37:29', '2025-06-01 22:37:29', NULL, NULL, NULL, 8), +(1232, '2025-05-23', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1233, '2025-05-23', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 3), +(1234, '2025-05-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1235, '2025-05-23', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1236, '2025-05-23', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1237, '2025-05-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1238, '2025-05-23', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1239, '2025-05-23', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1240, '2025-05-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1241, '2025-05-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:41:30', '2025-06-01 22:41:30', NULL, NULL, NULL, 8), +(1242, '2025-05-27', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1243, '2025-05-27', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1244, '2025-05-27', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1245, '2025-05-27', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1246, '2025-05-27', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1247, '2025-05-27', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1248, '2025-05-27', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1249, '2025-05-27', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 5), +(1250, '2025-05-27', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1251, '2025-05-27', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:45:06', '2025-06-01 22:45:06', NULL, NULL, NULL, 8), +(1252, '2025-05-28', 1, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-06-01 22:46:40', '2025-06-01 22:46:40', NULL, NULL, NULL, 8), +(1258, '2025-05-28', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:46:40', '2025-06-01 22:46:40', NULL, NULL, NULL, 8), +(1262, '2025-05-28', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1263, '2025-05-28', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1264, '2025-05-28', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1265, '2025-05-28', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1266, '2025-05-28', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1267, '2025-05-28', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 5), +(1268, '2025-05-28', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1269, '2025-05-28', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:48:21', '2025-06-01 22:48:21', NULL, NULL, NULL, 8), +(1270, '2025-05-29', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1271, '2025-05-29', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1272, '2025-05-29', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1273, '2025-05-29', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1274, '2025-05-29', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1275, '2025-05-29', 6, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1276, '2025-05-29', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1277, '2025-05-29', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 5), +(1278, '2025-05-29', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1279, '2025-05-29', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-01 22:49:55', '2025-06-01 22:49:55', NULL, NULL, NULL, 8), +(1281, '2025-05-30', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1282, '2025-05-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1283, '2025-05-30', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1284, '2025-05-30', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1285, '2025-05-30', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1286, '2025-05-30', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1287, '2025-05-30', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 5), +(1288, '2025-05-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1289, '2025-05-30', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:50:53', '2025-06-01 22:50:53', NULL, NULL, NULL, 8), +(1290, '2025-06-02', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:18', '2025-06-01 22:52:18', NULL, NULL, NULL, 8), +(1291, '2025-06-02', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 5), +(1292, '2025-06-02', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1293, '2025-06-02', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1294, '2025-06-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1295, '2025-06-02', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1296, '2025-06-02', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1297, '2025-06-02', 8, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1298, '2025-06-02', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 8), +(1299, '2025-06-02', 10, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 22:52:19', '2025-06-01 22:52:19', NULL, NULL, NULL, 15), +(1300, '2025-05-30', 1, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-01 23:17:51', '2025-06-01 23:17:51', NULL, NULL, NULL, 8), +(1301, '2025-01-02', 5, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-01 23:31:26', '2025-06-01 23:31:26', NULL, NULL, NULL, 15), +(1302, '2025-06-04', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1303, '2025-06-04', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1304, '2025-06-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1305, '2025-06-04', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 15), +(1306, '2025-06-04', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1307, '2025-06-04', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1308, '2025-06-04', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1309, '2025-06-04', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 5), +(1310, '2025-06-04', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1311, '2025-06-04', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-04 22:13:30', '2025-06-04 22:13:30', NULL, NULL, NULL, 8), +(1312, '2025-06-09', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:28', NULL, NULL, NULL, 8), +(1313, '2025-06-09', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1314, '2025-06-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:30', NULL, NULL, NULL, 8), +(1315, '2025-06-09', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1316, '2025-06-09', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:31', NULL, NULL, NULL, 8), +(1317, '2025-06-09', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1318, '2025-06-09', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:32', NULL, NULL, NULL, 8), +(1319, '2025-06-09', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 5), +(1320, '2025-06-09', 9, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-09 06:47:48', '2025-06-09 06:47:48', NULL, NULL, NULL, 15), +(1321, '2025-06-09', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-09 06:47:48', '2025-06-13 03:43:34', NULL, NULL, NULL, 8), +(1322, '2025-06-10', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:03', '2025-06-13 03:43:51', NULL, NULL, NULL, 8), +(1323, '2025-06-10', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:03', '2025-06-10 08:47:03', NULL, NULL, NULL, 5), +(1324, '2025-06-10', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:03', '2025-06-13 03:43:53', NULL, NULL, NULL, 8), +(1325, '2025-06-10', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:54', NULL, NULL, NULL, 8), +(1326, '2025-06-10', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1327, '2025-06-10', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1328, '2025-06-10', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:55', NULL, NULL, NULL, 8), +(1329, '2025-06-10', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-10 08:47:04', '2025-06-10 08:47:04', NULL, NULL, NULL, 5), +(1330, '2025-06-10', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:56', NULL, NULL, NULL, 8), +(1331, '2025-06-10', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-10 08:47:04', '2025-06-13 03:43:56', NULL, NULL, NULL, 8), +(1332, '2025-06-11', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:18', NULL, NULL, NULL, 8), +(1333, '2025-06-11', 2, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1334, '2025-06-11', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:19', NULL, NULL, NULL, 8), +(1335, '2025-06-11', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:20', NULL, NULL, NULL, 8), +(1336, '2025-06-11', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1337, '2025-06-11', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1338, '2025-06-11', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:22', NULL, NULL, NULL, 8), +(1339, '2025-06-11', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-11 07:59:16', '2025-06-11 07:59:16', NULL, NULL, NULL, 5), +(1340, '2025-06-11', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:23', NULL, NULL, NULL, 8), +(1341, '2025-06-11', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-11 07:59:16', '2025-06-13 03:44:23', NULL, NULL, NULL, 8), +(1342, '2025-06-13', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1343, '2025-06-13', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1344, '2025-06-13', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1345, '2025-06-13', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1346, '2025-06-13', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1347, '2025-06-13', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1348, '2025-06-13', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 15), +(1349, '2025-06-13', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 5), +(1350, '2025-06-13', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1351, '2025-06-13', 10, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:25:23', '2025-06-13 03:25:23', NULL, NULL, NULL, 8), +(1352, '2025-06-05', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1353, '2025-06-05', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1354, '2025-06-05', 3, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1355, '2025-06-05', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1356, '2025-06-05', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1357, '2025-06-05', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1358, '2025-06-05', 7, 4, NULL, NULL, NULL, NULL, '반반차', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1359, '2025-06-05', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 5), +(1360, '2025-06-05', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1361, '2025-06-05', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:34:20', '2025-06-13 03:34:20', NULL, NULL, NULL, 8), +(1362, '2025-06-12', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1363, '2025-06-12', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1364, '2025-06-12', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1365, '2025-06-12', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1366, '2025-06-12', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1367, '2025-06-12', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1368, '2025-06-12', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1369, '2025-06-12', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 5), +(1370, '2025-06-12', 9, 4, NULL, NULL, NULL, NULL, '반차', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1371, '2025-06-12', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, '라인수정', '2025-06-13 03:36:11', '2025-06-13 03:36:11', NULL, NULL, NULL, 8), +(1372, '2025-06-16', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:26', '2025-06-16 04:26:26', NULL, NULL, NULL, 8), +(1373, '2025-06-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1374, '2025-06-16', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1375, '2025-06-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1376, '2025-06-16', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1377, '2025-06-16', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'Vessel NDE 불량 수리', '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1378, '2025-06-16', 7, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 15), +(1379, '2025-06-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'Vessel NDE 불량 수리', '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 5), +(1380, '2025-06-16', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1381, '2025-06-16', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-16 04:26:27', '2025-06-16 04:26:27', NULL, NULL, NULL, 8), +(1382, '2025-06-17', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1383, '2025-06-17', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1384, '2025-06-17', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1385, '2025-06-17', 4, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:36:28', NULL, NULL, NULL, 5), +(1386, '2025-06-17', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1387, '2025-06-17', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 비파괴 불량', '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1388, '2025-06-17', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1389, '2025-06-17', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, '용기 비파괴 불량', '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 5), +(1390, '2025-06-17', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1391, '2025-06-17', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-17 08:17:30', '2025-06-17 08:17:30', NULL, NULL, NULL, 8), +(1392, '2025-06-18', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1393, '2025-06-18', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1394, '2025-06-18', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1395, '2025-06-18', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1396, '2025-06-18', 5, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1397, '2025-06-18', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1398, '2025-06-18', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1399, '2025-06-18', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 5), +(1400, '2025-06-18', 9, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1401, '2025-06-18', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-06-18 08:16:50', '2025-06-18 08:16:50', NULL, NULL, NULL, 8), +(1402, '2025-06-24', 1, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1403, '2025-06-24', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 5), +(1404, '2025-06-24', 3, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1405, '2025-06-24', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1406, '2025-06-24', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1407, '2025-06-24', 6, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1408, '2025-06-24', 7, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1409, '2025-06-24', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 5), +(1410, '2025-06-24', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1411, '2025-06-24', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-24 09:25:01', '2025-06-24 09:25:01', NULL, NULL, NULL, 8), +(1412, '2025-06-25', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1413, '2025-06-25', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 5), +(1414, '2025-06-25', 3, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1415, '2025-06-25', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1416, '2025-06-25', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1417, '2025-06-25', 6, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1418, '2025-06-25', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1419, '2025-06-25', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 5), +(1420, '2025-06-25', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1421, '2025-06-25', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-25 07:08:25', '2025-06-25 07:08:25', NULL, NULL, NULL, 18), +(1422, '2025-06-26', 1, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1423, '2025-06-26', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1424, '2025-06-26', 3, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1425, '2025-06-26', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1426, '2025-06-26', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1427, '2025-06-26', 6, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1428, '2025-06-26', 7, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1429, '2025-06-26', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 5), +(1430, '2025-06-26', 9, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1431, '2025-06-26', 10, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-06-26 22:45:15', '2025-06-26 22:45:15', NULL, NULL, NULL, 18), +(1432, '2025-06-27', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1433, '2025-06-27', 2, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1434, '2025-06-27', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1435, '2025-06-27', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1436, '2025-06-27', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1437, '2025-06-27', 6, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1438, '2025-06-27', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1439, '2025-06-27', 8, 3, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 5), +(1440, '2025-06-27', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1441, '2025-06-27', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-06-26 22:48:37', '2025-06-26 22:48:37', NULL, NULL, NULL, 18), +(1442, '2025-06-19', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1443, '2025-06-19', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 5), +(1444, '2025-06-19', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1445, '2025-06-19', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8); +INSERT INTO `WorkReports` (`id`, `date`, `worker_id`, `project_id`, `morning_task_id`, `afternoon_task_id`, `overtime_hours`, `overtime_task_id`, `work_details`, `note`, `memo`, `created_at`, `updated_at`, `morning_project_id`, `afternoon_project_id`, `overtime_project_id`, `task_id`) VALUES +(1446, '2025-06-19', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 5), +(1447, '2025-06-19', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1448, '2025-06-19', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1449, '2025-06-19', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 5), +(1450, '2025-06-19', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1451, '2025-06-19', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:53:46', '2025-07-07 03:53:46', NULL, NULL, NULL, 8), +(1452, '2025-06-20', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1453, '2025-06-20', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 5), +(1454, '2025-06-20', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1455, '2025-06-20', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1456, '2025-06-20', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 5), +(1457, '2025-06-20', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1458, '2025-06-20', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1459, '2025-06-20', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 5), +(1460, '2025-06-20', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1461, '2025-06-20', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:54:44', '2025-07-07 03:54:44', NULL, NULL, NULL, 8), +(1462, '2025-06-23', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1463, '2025-06-23', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 5), +(1464, '2025-06-23', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1465, '2025-06-23', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1466, '2025-06-23', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 5), +(1467, '2025-06-23', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1468, '2025-06-23', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1469, '2025-06-23', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 5), +(1470, '2025-06-23', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1471, '2025-06-23', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 03:55:50', '2025-07-07 03:55:50', NULL, NULL, NULL, 8), +(1472, '2025-06-30', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1473, '2025-06-30', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 5), +(1474, '2025-06-30', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1475, '2025-06-30', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1476, '2025-06-30', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 5), +(1477, '2025-06-30', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 5), +(1478, '2025-06-30', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1479, '2025-06-30', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 5), +(1480, '2025-06-30', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1481, '2025-06-30', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:24:36', '2025-07-07 04:24:36', NULL, NULL, NULL, 8), +(1482, '2025-07-01', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 8), +(1483, '2025-07-01', 2, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1484, '2025-07-01', 3, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1485, '2025-07-01', 4, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 8), +(1486, '2025-07-01', 5, 4, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 8), +(1487, '2025-07-01', 6, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1488, '2025-07-01', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 8), +(1489, '2025-07-01', 8, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1490, '2025-07-01', 9, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1491, '2025-07-01', 10, 3, NULL, NULL, 4.0, NULL, '근무', NULL, NULL, '2025-07-07 04:26:44', '2025-07-07 04:26:44', NULL, NULL, NULL, 5), +(1492, '2025-07-02', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 9), +(1493, '2025-07-02', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1494, '2025-07-02', 3, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1495, '2025-07-02', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 9), +(1496, '2025-07-02', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 9), +(1497, '2025-07-02', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1498, '2025-07-02', 7, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1499, '2025-07-02', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1500, '2025-07-02', 9, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1501, '2025-07-02', 10, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:28:16', '2025-07-07 04:28:16', NULL, NULL, NULL, 5), +(1502, '2025-07-03', 1, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1503, '2025-07-03', 2, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 5), +(1504, '2025-07-03', 3, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1505, '2025-07-03', 4, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1506, '2025-07-03', 5, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1507, '2025-07-03', 6, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 5), +(1508, '2025-07-03', 7, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1509, '2025-07-03', 8, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 5), +(1510, '2025-07-03', 9, 3, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 5), +(1511, '2025-07-03', 10, 4, NULL, NULL, 2.0, NULL, '근무', NULL, NULL, '2025-07-07 04:30:04', '2025-07-07 04:30:04', NULL, NULL, NULL, 9), +(1512, '2025-07-04', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1513, '2025-07-04', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1514, '2025-07-04', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1515, '2025-07-04', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1516, '2025-07-04', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1517, '2025-07-04', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1518, '2025-07-04', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1519, '2025-07-04', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1520, '2025-07-04', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1521, '2025-07-04', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:09', '2025-07-07 04:31:09', NULL, NULL, NULL, 9), +(1522, '2025-07-05', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1523, '2025-07-05', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1524, '2025-07-05', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1525, '2025-07-05', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1526, '2025-07-05', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1527, '2025-07-05', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:31:53', '2025-07-07 04:31:53', NULL, NULL, NULL, 9), +(1528, '2025-07-06', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1529, '2025-07-06', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1530, '2025-07-06', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1531, '2025-07-06', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1532, '2025-07-06', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1533, '2025-07-06', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1534, '2025-07-06', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1535, '2025-07-06', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 04:32:52', '2025-07-07 04:32:52', NULL, NULL, NULL, 9), +(1536, '2025-07-07', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1537, '2025-07-07', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1538, '2025-07-07', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1539, '2025-07-07', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1540, '2025-07-07', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:13', '2025-07-07 23:35:13', NULL, NULL, NULL, 9), +(1541, '2025-07-07', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1542, '2025-07-07', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1543, '2025-07-07', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1544, '2025-07-07', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1545, '2025-07-07', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-07 23:35:14', '2025-07-07 23:35:14', NULL, NULL, NULL, 9), +(1546, '2025-07-08', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1547, '2025-07-08', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1548, '2025-07-08', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1549, '2025-07-08', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1550, '2025-07-08', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1551, '2025-07-08', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1552, '2025-07-08', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1553, '2025-07-08', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1554, '2025-07-08', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1555, '2025-07-08', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:12:44', '2025-07-10 02:12:44', NULL, NULL, NULL, 9), +(1556, '2025-07-09', 1, 4, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1557, '2025-07-09', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1558, '2025-07-09', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1559, '2025-07-09', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, 'tubing', '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1560, '2025-07-09', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1561, '2025-07-09', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1562, '2025-07-09', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1563, '2025-07-09', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1564, '2025-07-09', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1565, '2025-07-09', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-10 02:13:45', '2025-07-10 02:13:45', NULL, NULL, NULL, 9), +(1566, '2025-07-10', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1567, '2025-07-10', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1568, '2025-07-10', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1569, '2025-07-10', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1570, '2025-07-10', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1571, '2025-07-10', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1572, '2025-07-10', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1573, '2025-07-10', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1574, '2025-07-10', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1575, '2025-07-10', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:06:02', '2025-07-30 02:06:02', NULL, NULL, NULL, 8), +(1576, '2025-07-14', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1577, '2025-07-14', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1578, '2025-07-14', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1579, '2025-07-14', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1580, '2025-07-14', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1581, '2025-07-14', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1582, '2025-07-14', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1583, '2025-07-14', 8, 4, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1584, '2025-07-14', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1585, '2025-07-14', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:07:29', '2025-07-30 02:07:29', NULL, NULL, NULL, 8), +(1586, '2025-07-15', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:41', '2025-07-30 02:23:58', NULL, NULL, NULL, 8), +(1587, '2025-07-15', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:41', '2025-07-30 02:23:58', NULL, NULL, NULL, 8), +(1588, '2025-07-15', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:41', '2025-07-30 02:24:00', NULL, NULL, NULL, 8), +(1589, '2025-07-15', 4, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-07-30 02:08:41', '2025-07-30 02:24:00', NULL, NULL, NULL, 15), +(1590, '2025-07-15', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:01', NULL, NULL, NULL, 5), +(1591, '2025-07-15', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:02', NULL, NULL, NULL, 8), +(1592, '2025-07-15', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:02', NULL, NULL, NULL, 8), +(1593, '2025-07-15', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:03', NULL, NULL, NULL, 8), +(1594, '2025-07-15', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:03', NULL, NULL, NULL, 5), +(1595, '2025-07-15', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:08:42', '2025-07-30 02:24:04', NULL, NULL, NULL, 8), +(1596, '2025-07-16', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:17', '2025-07-30 02:10:17', NULL, NULL, NULL, 8), +(1597, '2025-07-16', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1598, '2025-07-16', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1599, '2025-07-16', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 8), +(1600, '2025-07-16', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1601, '2025-07-16', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1602, '2025-07-16', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 8), +(1603, '2025-07-16', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1604, '2025-07-16', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1605, '2025-07-16', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:10:18', '2025-07-30 02:10:18', NULL, NULL, NULL, 5), +(1606, '2025-07-17', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:24:31', NULL, NULL, NULL, 7), +(1607, '2025-07-17', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1608, '2025-07-17', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1609, '2025-07-17', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1610, '2025-07-17', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1611, '2025-07-17', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1612, '2025-07-17', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1613, '2025-07-17', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1614, '2025-07-17', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1615, '2025-07-17', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:11:12', '2025-07-30 02:11:12', NULL, NULL, NULL, 18), +(1616, '2025-07-18', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 9), +(1617, '2025-07-18', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1618, '2025-07-18', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1619, '2025-07-18', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1620, '2025-07-18', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 9), +(1621, '2025-07-18', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1622, '2025-07-18', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 9), +(1623, '2025-07-18', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1624, '2025-07-18', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1625, '2025-07-18', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:13:22', '2025-07-30 02:13:22', NULL, NULL, NULL, 5), +(1626, '2025-07-21', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 7), +(1627, '2025-07-21', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1628, '2025-07-21', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1629, '2025-07-21', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 9), +(1630, '2025-07-21', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 9), +(1631, '2025-07-21', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1632, '2025-07-21', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1633, '2025-07-21', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1634, '2025-07-21', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1635, '2025-07-21', 10, 3, NULL, NULL, NULL, NULL, '반반차', NULL, NULL, '2025-07-30 02:14:45', '2025-07-30 02:14:45', NULL, NULL, NULL, 5), +(1636, '2025-07-22', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 5), +(1637, '2025-07-22', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1638, '2025-07-22', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1639, '2025-07-22', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 7), +(1640, '2025-07-22', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 7), +(1641, '2025-07-22', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1642, '2025-07-22', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1643, '2025-07-22', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1644, '2025-07-22', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1645, '2025-07-22', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:16:04', '2025-07-30 02:16:04', NULL, NULL, NULL, 9), +(1646, '2025-07-23', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 7), +(1647, '2025-07-23', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1648, '2025-07-23', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1649, '2025-07-23', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 7), +(1650, '2025-07-23', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 7), +(1651, '2025-07-23', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1652, '2025-07-23', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1653, '2025-07-23', 8, 13, NULL, NULL, NULL, NULL, '유급', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 22:39:10', NULL, NULL, NULL, 15), +(1654, '2025-07-23', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1655, '2025-07-23', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:17:15', '2025-07-30 02:17:15', NULL, NULL, NULL, 5), +(1656, '2025-07-24', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 7), +(1657, '2025-07-24', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1658, '2025-07-24', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1659, '2025-07-24', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 7), +(1660, '2025-07-24', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 7), +(1661, '2025-07-24', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1662, '2025-07-24', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1663, '2025-07-24', 8, 13, NULL, NULL, NULL, NULL, '유급', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 15), +(1664, '2025-07-24', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1665, '2025-07-24', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:18:29', '2025-07-30 02:18:29', NULL, NULL, NULL, 5), +(1666, '2025-07-25', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 13), +(1667, '2025-07-25', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1668, '2025-07-25', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1669, '2025-07-25', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1670, '2025-07-25', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 13), +(1671, '2025-07-25', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 13), +(1672, '2025-07-25', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 18), +(1673, '2025-07-25', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1674, '2025-07-25', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1675, '2025-07-25', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:21:24', '2025-07-30 02:21:24', NULL, NULL, NULL, 5), +(1676, '2025-07-28', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 7), +(1677, '2025-07-28', 2, 5, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 13), +(1678, '2025-07-28', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1679, '2025-07-28', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 7), +(1680, '2025-07-28', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 7), +(1681, '2025-07-28', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1682, '2025-07-28', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1683, '2025-07-28', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1684, '2025-07-28', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1685, '2025-07-28', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 02:22:32', '2025-07-30 02:22:32', NULL, NULL, NULL, 5), +(1686, '2025-07-11', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1687, '2025-07-11', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1688, '2025-07-11', 3, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1689, '2025-07-11', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1690, '2025-07-11', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1691, '2025-07-11', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1692, '2025-07-11', 7, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1693, '2025-07-11', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1694, '2025-07-11', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:30', '2025-07-30 22:48:30', NULL, NULL, NULL, 9), +(1695, '2025-07-11', 10, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:48:31', '2025-07-30 22:48:31', NULL, NULL, NULL, 9), +(1696, '2025-07-12', 1, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1697, '2025-07-12', 2, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1698, '2025-07-12', 3, 13, NULL, NULL, NULL, NULL, '휴무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 15), +(1699, '2025-07-12', 4, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1700, '2025-07-12', 5, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1701, '2025-07-12', 6, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1702, '2025-07-12', 7, 13, NULL, NULL, NULL, NULL, '휴무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 15), +(1703, '2025-07-12', 8, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1704, '2025-07-12', 9, 4, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 9), +(1705, '2025-07-12', 10, 13, NULL, NULL, NULL, NULL, '휴무', NULL, NULL, '2025-07-30 22:49:19', '2025-07-30 22:49:19', NULL, NULL, NULL, 15), +(1706, '2025-07-29', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 7), +(1707, '2025-07-29', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1708, '2025-07-29', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1709, '2025-07-29', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 7), +(1710, '2025-07-29', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 7), +(1711, '2025-07-29', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1712, '2025-07-29', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1713, '2025-07-29', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1714, '2025-07-29', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1715, '2025-07-29', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:50:13', '2025-07-30 22:50:13', NULL, NULL, NULL, 5), +(1716, '2025-07-30', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 7), +(1717, '2025-07-30', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1718, '2025-07-30', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1719, '2025-07-30', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 7), +(1720, '2025-07-30', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 7), +(1721, '2025-07-30', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1722, '2025-07-30', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1723, '2025-07-30', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1724, '2025-07-30', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1725, '2025-07-30', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:05', '2025-07-30 22:51:05', NULL, NULL, NULL, 5), +(1726, '2025-07-31', 1, 3, NULL, NULL, NULL, NULL, '반차', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 7), +(1727, '2025-07-31', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1728, '2025-07-31', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1729, '2025-07-31', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 7), +(1730, '2025-07-31', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 7), +(1731, '2025-07-31', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1732, '2025-07-31', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1733, '2025-07-31', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1734, '2025-07-31', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1735, '2025-07-31', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-07-30 22:51:54', '2025-07-30 22:51:54', NULL, NULL, NULL, 5), +(1736, '2025-09-18', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, '냉동기', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 18), +(1737, '2025-09-18', 2, 8, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 8), +(1738, '2025-09-18', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1739, '2025-09-18', 4, 8, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 8), +(1740, '2025-09-18', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, '냉동기', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 9), +(1741, '2025-09-18', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1742, '2025-09-18', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, '냉동기', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 18), +(1743, '2025-09-18', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1744, '2025-09-18', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1745, '2025-09-18', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, 'BOG', '2025-09-17 23:53:35', '2025-09-17 23:53:35', NULL, NULL, NULL, 5), +(1746, '2025-10-01', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 16), +(1747, '2025-10-01', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 16), +(1748, '2025-10-01', 3, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1749, '2025-10-01', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 5), +(1750, '2025-10-01', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 16), +(1751, '2025-10-01', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1752, '2025-10-01', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1753, '2025-10-01', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1754, '2025-10-01', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1755, '2025-10-01', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:49:56', '2025-10-01 23:49:56', NULL, NULL, NULL, 7), +(1756, '2025-10-02', 1, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1757, '2025-10-02', 2, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1758, '2025-10-02', 3, 13, NULL, NULL, NULL, NULL, '연차', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 15), +(1759, '2025-10-02', 4, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1760, '2025-10-02', 5, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1761, '2025-10-02', 6, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1762, '2025-10-02', 7, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1763, '2025-10-02', 8, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1764, '2025-10-02', 9, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7), +(1765, '2025-10-02', 10, 3, NULL, NULL, NULL, NULL, '근무', NULL, NULL, '2025-10-01 23:50:57', '2025-10-01 23:50:57', NULL, NULL, NULL, 7); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_report_audit_log` +-- + +CREATE TABLE `work_report_audit_log` ( + `log_id` int(11) NOT NULL, + `action` enum('ADD_ACCUMULATE','DELETE_SINGLE','UPDATE','DELETE','CREATE','DELETE_BATCH') NOT NULL COMMENT '작업 유형', + `report_id` int(11) DEFAULT NULL COMMENT '관련 보고서 ID', + `old_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 전 값' CHECK (json_valid(`old_values`)), + `new_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 후 값' CHECK (json_valid(`new_values`)), + `changed_by` int(11) NOT NULL COMMENT '변경자 ID', + `change_reason` varchar(500) DEFAULT NULL COMMENT '변경 사유', + `ip_address` varchar(45) DEFAULT NULL COMMENT 'IP 주소', + `user_agent` text DEFAULT NULL COMMENT '사용자 에이전트', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '변경 시간' +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_report_audit_log` +-- + +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(1, 'ADD_ACCUMULATE', 12, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 02:56:12'), +(2, 'DELETE_SINGLE', 12, '{\"worker_name\":\"김두수\",\"project_name\":\"MP7 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:36'), +(3, 'DELETE_SINGLE', 11, '{\"worker_name\":\"김두수\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:39'), +(4, 'DELETE_SINGLE', 7, '{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:17:41'), +(5, 'ADD_ACCUMULATE', 13, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":1,\"my_total\":\"1.00\",\"grand_total\":1,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"1.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 03:18:37'), +(6, 'DELETE_SINGLE', 13, '{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 03:19:23'), +(7, 'ADD_ACCUMULATE', 14, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(8, 'ADD_ACCUMULATE', 15, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(9, 'ADD_ACCUMULATE', 16, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(10, 'ADD_ACCUMULATE', 17, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(11, 'ADD_ACCUMULATE', 18, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(12, 'ADD_ACCUMULATE', 19, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:23'), +(13, 'ADD_ACCUMULATE', 20, NULL, '{\"report_date\":\"2025-06-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:10:47'), +(14, 'ADD_ACCUMULATE', 21, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(15, 'ADD_ACCUMULATE', 22, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(16, 'ADD_ACCUMULATE', 23, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(17, 'ADD_ACCUMULATE', 24, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(18, 'ADD_ACCUMULATE', 25, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(19, 'ADD_ACCUMULATE', 26, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:11:37'), +(20, 'ADD_ACCUMULATE', 27, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(21, 'ADD_ACCUMULATE', 28, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(22, 'ADD_ACCUMULATE', 29, NULL, '{\"report_date\":\"2025-06-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:07'), +(23, 'ADD_ACCUMULATE', 30, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(24, 'ADD_ACCUMULATE', 31, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(25, 'ADD_ACCUMULATE', 32, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(26, 'ADD_ACCUMULATE', 33, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(27, 'ADD_ACCUMULATE', 34, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(28, 'ADD_ACCUMULATE', 35, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:12:57'), +(29, 'ADD_ACCUMULATE', 36, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(30, 'ADD_ACCUMULATE', 37, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(31, 'ADD_ACCUMULATE', 38, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(32, 'ADD_ACCUMULATE', 39, NULL, '{\"report_date\":\"2025-06-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}', 1, '누적 추가 by hyungi - 삭제 없음', NULL, NULL, '2025-06-16 05:13:56'), +(33, 'ADD_ACCUMULATE', 40, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(34, 'ADD_ACCUMULATE', 41, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(35, 'ADD_ACCUMULATE', 42, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(36, 'ADD_ACCUMULATE', 43, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:12:01'), +(37, 'DELETE_SINGLE', 42, '{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:12:33'), +(38, 'ADD_ACCUMULATE', 44, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:13:02'), +(39, 'ADD_ACCUMULATE', 45, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:13:50'), +(40, 'DELETE_SINGLE', 41, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:14:48'), +(41, 'ADD_ACCUMULATE', 46, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-16 06:15:22'), +(42, 'DELETE_SINGLE', 1, '{\"worker_name\":\"김두수\",\"project_name\":\"25년 안전보건시설설비\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-01T00:00:00.000Z\"}', NULL, 1, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:20:38'), +(43, 'ADD_ACCUMULATE', 48, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(44, 'ADD_ACCUMULATE', 49, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(45, 'ADD_ACCUMULATE', 50, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:46:44'), +(46, 'DELETE_SINGLE', 49, '{\"worker_name\":\"박현수\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-16 06:47:54'), +(47, 'ADD_ACCUMULATE', 51, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-16 06:48:29'), +(48, 'ADD_ACCUMULATE', 52, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-16 06:50:09'), +(49, 'ADD_ACCUMULATE', 54, NULL, '{\"report_date\":\"2025-06-16\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-16 06:50:09'), +(50, 'ADD_ACCUMULATE', 56, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:23:41'), +(51, 'ADD_ACCUMULATE', 58, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:23:41'), +(52, 'ADD_ACCUMULATE', 60, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:33'), +(53, 'ADD_ACCUMULATE', 62, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:33'), +(54, 'ADD_ACCUMULATE', 64, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:24:44'), +(55, 'ADD_ACCUMULATE', 65, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:25:24'), +(56, 'DELETE_SINGLE', 64, '{\"worker_name\":\"황인용\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-17T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-06-17 08:26:17'), +(57, 'ADD_ACCUMULATE', 66, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:27:06'), +(58, 'ADD_ACCUMULATE', 67, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:27:06'), +(59, 'ADD_ACCUMULATE', 68, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(60, 'ADD_ACCUMULATE', 69, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(61, 'ADD_ACCUMULATE', 70, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:31:06'), +(62, 'ADD_ACCUMULATE', 71, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(63, 'ADD_ACCUMULATE', 72, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(64, 'ADD_ACCUMULATE', 73, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-17 08:33:06'), +(65, 'ADD_ACCUMULATE', 74, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-17 08:34:11'), +(66, 'ADD_ACCUMULATE', 76, NULL, '{\"report_date\":\"2025-06-17\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-17 08:34:11'), +(67, 'ADD_ACCUMULATE', 78, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(68, 'ADD_ACCUMULATE', 79, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(69, 'ADD_ACCUMULATE', 80, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:40:27'), +(70, 'ADD_ACCUMULATE', 81, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:02'), +(71, 'ADD_ACCUMULATE', 82, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:03'), +(72, 'ADD_ACCUMULATE', 83, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:03'), +(73, 'ADD_ACCUMULATE', 84, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-18 08:41:45'), +(74, 'ADD_ACCUMULATE', 86, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-18 08:47:55'), +(75, 'ADD_ACCUMULATE', 88, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-18 08:47:55'), +(76, 'ADD_ACCUMULATE', 90, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(77, 'ADD_ACCUMULATE', 92, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(78, 'ADD_ACCUMULATE', 94, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 08:50:19'), +(79, 'ADD_ACCUMULATE', 96, NULL, '{\"report_date\":\"2025-06-18\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-18 09:00:17'), +(80, 'ADD_ACCUMULATE', 98, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-19 06:37:59'), +(81, 'ADD_ACCUMULATE', 99, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-19 06:37:59'), +(82, 'ADD_ACCUMULATE', 100, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(83, 'ADD_ACCUMULATE', 101, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(84, 'ADD_ACCUMULATE', 102, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-19 06:59:36'), +(85, 'ADD_ACCUMULATE', 103, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(86, 'ADD_ACCUMULATE', 105, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(87, 'ADD_ACCUMULATE', 107, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(88, 'ADD_ACCUMULATE', 109, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(89, 'ADD_ACCUMULATE', 111, NULL, '{\"report_date\":\"2025-06-19\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-19 07:01:02'), +(90, 'ADD_ACCUMULATE', 113, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(91, 'ADD_ACCUMULATE', 115, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(92, 'ADD_ACCUMULATE', 117, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:01'), +(93, 'ADD_ACCUMULATE', 119, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(94, 'ADD_ACCUMULATE', 121, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(95, 'ADD_ACCUMULATE', 123, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-20 06:44:02'), +(96, 'ADD_ACCUMULATE', 125, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-20 06:45:30'), +(97, 'ADD_ACCUMULATE', 126, NULL, '{\"report_date\":\"2025-06-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-20 06:45:31'), +(98, 'ADD_ACCUMULATE', 127, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-23 06:42:58'), +(99, 'ADD_ACCUMULATE', 128, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-23 06:42:58'), +(100, 'ADD_ACCUMULATE', 129, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(101, 'ADD_ACCUMULATE', 131, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(102, 'ADD_ACCUMULATE', 133, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(103, 'ADD_ACCUMULATE', 135, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(104, 'ADD_ACCUMULATE', 137, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(105, 'ADD_ACCUMULATE', 139, NULL, '{\"report_date\":\"2025-06-23\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-23 06:51:28'), +(106, 'ADD_ACCUMULATE', 141, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-24 11:10:32'), +(107, 'ADD_ACCUMULATE', 142, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-24 11:10:32'), +(108, 'ADD_ACCUMULATE', 143, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(109, 'ADD_ACCUMULATE', 145, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(110, 'ADD_ACCUMULATE', 147, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(111, 'ADD_ACCUMULATE', 149, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(112, 'ADD_ACCUMULATE', 151, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(113, 'ADD_ACCUMULATE', 153, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:00'), +(114, 'ADD_ACCUMULATE', 155, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:05'), +(115, 'ADD_ACCUMULATE', 157, NULL, '{\"report_date\":\"2025-06-24\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-24 11:11:05'), +(116, 'ADD_ACCUMULATE', 159, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-25 11:08:04'), +(117, 'ADD_ACCUMULATE', 161, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-25 11:08:05'), +(118, 'ADD_ACCUMULATE', 163, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(119, 'ADD_ACCUMULATE', 164, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(120, 'ADD_ACCUMULATE', 165, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(121, 'ADD_ACCUMULATE', 166, NULL, '{\"report_date\":\"2025-06-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-25 11:11:30'), +(122, 'ADD_ACCUMULATE', 167, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(123, 'ADD_ACCUMULATE', 168, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(124, 'ADD_ACCUMULATE', 169, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(125, 'ADD_ACCUMULATE', 170, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(126, 'ADD_ACCUMULATE', 171, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-26 10:29:38'), +(127, 'ADD_ACCUMULATE', 172, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:31'), +(128, 'ADD_ACCUMULATE', 174, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:32'), +(129, 'ADD_ACCUMULATE', 176, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-26 11:11:32'), +(130, 'ADD_ACCUMULATE', 178, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-26 11:19:34'), +(131, 'ADD_ACCUMULATE', 179, NULL, '{\"report_date\":\"2025-06-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-26 11:19:34'), +(132, 'ADD_ACCUMULATE', 180, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:21'), +(133, 'ADD_ACCUMULATE', 181, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:21'), +(134, 'ADD_ACCUMULATE', 182, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 01:54:40'), +(135, 'ADD_ACCUMULATE', 183, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(136, 'ADD_ACCUMULATE', 184, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(137, 'ADD_ACCUMULATE', 185, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(138, 'ADD_ACCUMULATE', 186, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(139, 'ADD_ACCUMULATE', 187, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(140, 'ADD_ACCUMULATE', 188, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-06-27 06:47:43'), +(141, 'ADD_ACCUMULATE', 189, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:49:08'), +(142, 'ADD_ACCUMULATE', 190, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:49:08'), +(143, 'DELETE_SINGLE', 190, '{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 6, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:58:25'), +(144, 'ADD_ACCUMULATE', 191, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"4.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-06-27 06:58:46'), +(145, 'DELETE_SINGLE', 181, '{\"worker_name\":\"박현수\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:59:37'), +(146, 'DELETE_SINGLE', 180, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}', NULL, 5, '개별 항목 삭제', NULL, NULL, '2025-06-27 06:59:42'), +(147, 'ADD_ACCUMULATE', 192, NULL, '{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-06-27 07:00:10'), +(148, 'ADD_ACCUMULATE', 193, NULL, '{\"report_date\":\"2025-06-30\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:37:29'), +(149, 'ADD_ACCUMULATE', 195, NULL, '{\"report_date\":\"2025-06-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:38:19'), +(150, 'ADD_ACCUMULATE', 196, NULL, '{\"report_date\":\"2025-06-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:38:19'), +(151, 'ADD_ACCUMULATE', 197, NULL, '{\"report_date\":\"2025-06-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:38:19'), +(152, 'ADD_ACCUMULATE', 198, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(153, 'ADD_ACCUMULATE', 199, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(154, 'ADD_ACCUMULATE', 200, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(155, 'ADD_ACCUMULATE', 201, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(156, 'ADD_ACCUMULATE', 202, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(157, 'ADD_ACCUMULATE', 203, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:21'), +(158, 'ADD_ACCUMULATE', 204, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:48'), +(159, 'ADD_ACCUMULATE', 205, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:48'), +(160, 'ADD_ACCUMULATE', 206, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:48'), +(161, 'ADD_ACCUMULATE', 207, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:39:48'), +(162, 'ADD_ACCUMULATE', 208, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:40:10'), +(163, 'ADD_ACCUMULATE', 209, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:40:10'), +(164, 'ADD_ACCUMULATE', 210, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:42:57'), +(165, 'ADD_ACCUMULATE', 212, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:42:57'), +(166, 'ADD_ACCUMULATE', 214, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:42:57'), +(167, 'ADD_ACCUMULATE', 216, NULL, '{\"report_date\":\"2025-07-01\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:42:57'), +(168, 'ADD_ACCUMULATE', 218, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(169, 'ADD_ACCUMULATE', 219, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(170, 'ADD_ACCUMULATE', 220, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(171, 'ADD_ACCUMULATE', 221, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(172, 'ADD_ACCUMULATE', 222, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(173, 'ADD_ACCUMULATE', 223, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(174, 'ADD_ACCUMULATE', 224, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:43:36'), +(175, 'ADD_ACCUMULATE', 225, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:44:11'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(176, 'ADD_ACCUMULATE', 227, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:44:11'), +(177, 'ADD_ACCUMULATE', 229, NULL, '{\"report_date\":\"2025-07-02\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:44:11'), +(178, 'ADD_ACCUMULATE', 231, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:45:44'), +(179, 'ADD_ACCUMULATE', 232, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:45:45'), +(180, 'ADD_ACCUMULATE', 233, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:45:45'), +(181, 'ADD_ACCUMULATE', 234, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:45:45'), +(182, 'ADD_ACCUMULATE', 235, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:07'), +(183, 'ADD_ACCUMULATE', 236, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:07'), +(184, 'ADD_ACCUMULATE', 237, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:08'), +(185, 'ADD_ACCUMULATE', 238, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:08'), +(186, 'ADD_ACCUMULATE', 239, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:08'), +(187, 'ADD_ACCUMULATE', 240, NULL, '{\"report_date\":\"2025-07-03\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:46:08'), +(188, 'ADD_ACCUMULATE', 241, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(189, 'ADD_ACCUMULATE', 243, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(190, 'ADD_ACCUMULATE', 245, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(191, 'ADD_ACCUMULATE', 247, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(192, 'ADD_ACCUMULATE', 249, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(193, 'ADD_ACCUMULATE', 251, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(194, 'ADD_ACCUMULATE', 253, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(195, 'ADD_ACCUMULATE', 255, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(196, 'ADD_ACCUMULATE', 257, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(197, 'ADD_ACCUMULATE', 259, NULL, '{\"report_date\":\"2025-07-04\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-05 01:51:47'), +(198, 'ADD_ACCUMULATE', 261, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:38'), +(199, 'ADD_ACCUMULATE', 262, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:38'), +(200, 'ADD_ACCUMULATE', 263, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:39'), +(201, 'ADD_ACCUMULATE', 264, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:39'), +(202, 'ADD_ACCUMULATE', 265, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:39'), +(203, 'ADD_ACCUMULATE', 266, NULL, '{\"report_date\":\"2025-07-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-05 05:36:39'), +(204, 'ADD_ACCUMULATE', 267, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(205, 'ADD_ACCUMULATE', 268, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(206, 'ADD_ACCUMULATE', 269, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(207, 'ADD_ACCUMULATE', 270, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(208, 'ADD_ACCUMULATE', 271, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(209, 'ADD_ACCUMULATE', 272, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(210, 'ADD_ACCUMULATE', 273, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(211, 'ADD_ACCUMULATE', 274, NULL, '{\"report_date\":\"2025-07-06\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-06 05:34:32'), +(212, 'ADD_ACCUMULATE', 275, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(213, 'ADD_ACCUMULATE', 276, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(214, 'ADD_ACCUMULATE', 277, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(215, 'ADD_ACCUMULATE', 278, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(216, 'ADD_ACCUMULATE', 279, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(217, 'ADD_ACCUMULATE', 280, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(218, 'ADD_ACCUMULATE', 281, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(219, 'ADD_ACCUMULATE', 282, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(220, 'ADD_ACCUMULATE', 283, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(221, 'ADD_ACCUMULATE', 284, NULL, '{\"report_date\":\"2025-07-07\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-07-07 06:49:31'), +(222, 'ADD_ACCUMULATE', 285, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:57'), +(223, 'ADD_ACCUMULATE', 286, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(224, 'ADD_ACCUMULATE', 287, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(225, 'ADD_ACCUMULATE', 288, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(226, 'ADD_ACCUMULATE', 289, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(227, 'ADD_ACCUMULATE', 290, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(228, 'ADD_ACCUMULATE', 291, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(229, 'ADD_ACCUMULATE', 292, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(230, 'ADD_ACCUMULATE', 293, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(231, 'ADD_ACCUMULATE', 294, NULL, '{\"report_date\":\"2025-07-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-08 06:36:58'), +(232, 'ADD_ACCUMULATE', 295, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:40'), +(233, 'ADD_ACCUMULATE', 296, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:40'), +(234, 'ADD_ACCUMULATE', 297, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:40'), +(235, 'ADD_ACCUMULATE', 298, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:41'), +(236, 'ADD_ACCUMULATE', 299, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:41'), +(237, 'ADD_ACCUMULATE', 300, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:41'), +(238, 'ADD_ACCUMULATE', 301, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:42'), +(239, 'ADD_ACCUMULATE', 302, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:42'), +(240, 'ADD_ACCUMULATE', 303, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:08:42'), +(241, 'ADD_ACCUMULATE', 304, NULL, '{\"report_date\":\"2025-07-09\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-09 22:09:10'), +(242, 'ADD_ACCUMULATE', 305, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:58'), +(243, 'ADD_ACCUMULATE', 306, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:58'), +(244, 'ADD_ACCUMULATE', 307, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:58'), +(245, 'ADD_ACCUMULATE', 308, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(246, 'ADD_ACCUMULATE', 309, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(247, 'ADD_ACCUMULATE', 310, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(248, 'ADD_ACCUMULATE', 311, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(249, 'ADD_ACCUMULATE', 312, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(250, 'ADD_ACCUMULATE', 313, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(251, 'ADD_ACCUMULATE', 314, NULL, '{\"report_date\":\"2025-07-10\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-10 06:33:59'), +(252, 'ADD_ACCUMULATE', 315, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(253, 'ADD_ACCUMULATE', 316, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(254, 'ADD_ACCUMULATE', 317, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(255, 'ADD_ACCUMULATE', 318, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(256, 'ADD_ACCUMULATE', 319, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(257, 'ADD_ACCUMULATE', 320, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(258, 'ADD_ACCUMULATE', 321, NULL, '{\"report_date\":\"2025-07-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-12 05:41:30'), +(259, 'ADD_ACCUMULATE', 322, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:30'), +(260, 'ADD_ACCUMULATE', 323, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(261, 'ADD_ACCUMULATE', 324, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(262, 'ADD_ACCUMULATE', 325, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(263, 'ADD_ACCUMULATE', 326, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(264, 'ADD_ACCUMULATE', 327, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(265, 'ADD_ACCUMULATE', 328, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(266, 'ADD_ACCUMULATE', 329, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(267, 'ADD_ACCUMULATE', 330, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-14 06:46:57'), +(268, 'ADD_ACCUMULATE', 331, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:57:06'), +(269, 'ADD_ACCUMULATE', 332, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:57:06'), +(270, 'ADD_ACCUMULATE', 333, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:57:47'), +(271, 'ADD_ACCUMULATE', 335, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(272, 'ADD_ACCUMULATE', 336, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(273, 'ADD_ACCUMULATE', 337, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(274, 'ADD_ACCUMULATE', 338, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(275, 'ADD_ACCUMULATE', 339, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(276, 'ADD_ACCUMULATE', 340, NULL, '{\"report_date\":\"2025-07-15\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-15 05:58:19'), +(277, 'ADD_ACCUMULATE', 341, NULL, '{\"report_date\":\"2025-07-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-15 06:57:26'), +(278, 'ADD_ACCUMULATE', 342, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":4,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:46:46'), +(279, 'ADD_ACCUMULATE', 345, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":5,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:46:46'), +(280, 'ADD_ACCUMULATE', 348, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":10,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:47:53'), +(281, 'ADD_ACCUMULATE', 351, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":6,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:47:53'), +(282, 'ADD_ACCUMULATE', 354, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:48:32'), +(283, 'ADD_ACCUMULATE', 355, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:48:32'), +(284, 'ADD_ACCUMULATE', 356, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:48:32'), +(285, 'ADD_ACCUMULATE', 357, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-16 06:48:32'), +(286, 'ADD_ACCUMULATE', 358, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-16 06:51:31'), +(287, 'ADD_ACCUMULATE', 359, NULL, '{\"report_date\":\"2025-07-16\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-16 06:51:31'), +(288, 'ADD_ACCUMULATE', 360, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-17 06:45:22'), +(289, 'ADD_ACCUMULATE', 361, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:46:48'), +(290, 'ADD_ACCUMULATE', 363, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:46:48'), +(291, 'ADD_ACCUMULATE', 365, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:46:48'), +(292, 'ADD_ACCUMULATE', 367, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(293, 'ADD_ACCUMULATE', 368, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(294, 'ADD_ACCUMULATE', 369, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(295, 'ADD_ACCUMULATE', 370, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(296, 'ADD_ACCUMULATE', 371, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(297, 'ADD_ACCUMULATE', 372, NULL, '{\"report_date\":\"2025-07-17\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-17 06:47:19'), +(298, 'ADD_ACCUMULATE', 373, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"2.00\",\"grand_total\":2,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"2.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 05:54:47'), +(299, 'ADD_ACCUMULATE', 374, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"2.00\",\"grand_total\":2,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"2.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 05:54:48'), +(300, 'ADD_ACCUMULATE', 375, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":5,\"work_entries_count\":3,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 05:58:33'), +(301, 'DELETE_SINGLE', 375, '{\"worker_name\":\"표영진\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"2.00\",\"report_date\":\"2025-07-18T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-07-18 05:58:49'), +(302, 'ADD_ACCUMULATE', 378, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 05:59:42'), +(303, 'ADD_ACCUMULATE', 379, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-18 06:00:15'), +(304, 'ADD_ACCUMULATE', 380, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(305, 'ADD_ACCUMULATE', 381, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(306, 'ADD_ACCUMULATE', 382, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(307, 'ADD_ACCUMULATE', 383, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(308, 'ADD_ACCUMULATE', 384, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(309, 'ADD_ACCUMULATE', 385, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(310, 'ADD_ACCUMULATE', 386, NULL, '{\"report_date\":\"2025-07-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-18 06:36:13'), +(311, 'ADD_ACCUMULATE', 387, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:08'), +(312, 'ADD_ACCUMULATE', 389, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:08'), +(313, 'ADD_ACCUMULATE', 391, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(314, 'ADD_ACCUMULATE', 392, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(315, 'ADD_ACCUMULATE', 393, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(316, 'ADD_ACCUMULATE', 394, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(317, 'ADD_ACCUMULATE', 395, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(318, 'ADD_ACCUMULATE', 396, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(319, 'ADD_ACCUMULATE', 397, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-21 06:40:32'), +(320, 'ADD_ACCUMULATE', 398, NULL, '{\"report_date\":\"2025-07-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-21 06:53:37'), +(321, 'ADD_ACCUMULATE', 399, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:47'), +(322, 'ADD_ACCUMULATE', 400, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(323, 'ADD_ACCUMULATE', 401, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(324, 'ADD_ACCUMULATE', 402, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(325, 'ADD_ACCUMULATE', 403, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(326, 'ADD_ACCUMULATE', 404, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(327, 'ADD_ACCUMULATE', 405, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:45:48'), +(328, 'ADD_ACCUMULATE', 406, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-22 06:46:11'), +(329, 'ADD_ACCUMULATE', 407, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-22 06:46:11'), +(330, 'ADD_ACCUMULATE', 408, NULL, '{\"report_date\":\"2025-07-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-22 06:46:11'), +(331, 'ADD_ACCUMULATE', 409, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:06'), +(332, 'ADD_ACCUMULATE', 410, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:28'), +(333, 'ADD_ACCUMULATE', 411, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:28'), +(334, 'ADD_ACCUMULATE', 412, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(335, 'ADD_ACCUMULATE', 413, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(336, 'ADD_ACCUMULATE', 414, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(337, 'ADD_ACCUMULATE', 415, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(338, 'ADD_ACCUMULATE', 416, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(339, 'ADD_ACCUMULATE', 417, NULL, '{\"report_date\":\"2025-07-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-23 06:45:30'), +(340, 'ADD_ACCUMULATE', 418, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:36:55'), +(341, 'ADD_ACCUMULATE', 419, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(342, 'ADD_ACCUMULATE', 420, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(343, 'ADD_ACCUMULATE', 421, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(344, 'ADD_ACCUMULATE', 422, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(345, 'ADD_ACCUMULATE', 423, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(346, 'ADD_ACCUMULATE', 424, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-24 06:37:18'), +(347, 'ADD_ACCUMULATE', 425, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-24 06:47:04'), +(348, 'ADD_ACCUMULATE', 426, NULL, '{\"report_date\":\"2025-07-24\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-24 06:47:04'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(349, 'ADD_ACCUMULATE', 427, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:44:23'), +(350, 'ADD_ACCUMULATE', 428, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(351, 'ADD_ACCUMULATE', 429, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(352, 'ADD_ACCUMULATE', 430, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(353, 'ADD_ACCUMULATE', 431, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(354, 'ADD_ACCUMULATE', 432, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(355, 'ADD_ACCUMULATE', 433, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:15'), +(356, 'ADD_ACCUMULATE', 434, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:18'), +(357, 'ADD_ACCUMULATE', 435, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:19'), +(358, 'ADD_ACCUMULATE', 436, NULL, '{\"report_date\":\"2025-07-25\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-25 06:45:19'), +(359, 'ADD_ACCUMULATE', 437, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-28 06:30:39'), +(360, 'ADD_ACCUMULATE', 438, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-28 06:30:39'), +(361, 'ADD_ACCUMULATE', 439, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-28 06:30:39'), +(362, 'ADD_ACCUMULATE', 440, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:08'), +(363, 'ADD_ACCUMULATE', 442, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(364, 'ADD_ACCUMULATE', 443, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(365, 'ADD_ACCUMULATE', 444, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(366, 'ADD_ACCUMULATE', 445, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(367, 'ADD_ACCUMULATE', 446, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(368, 'ADD_ACCUMULATE', 447, NULL, '{\"report_date\":\"2025-07-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-28 06:33:34'), +(369, 'ADD_ACCUMULATE', 448, NULL, '{\"report_date\":\"2025-07-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-29 06:39:13'), +(370, 'ADD_ACCUMULATE', 449, NULL, '{\"report_date\":\"2025-07-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-29 06:39:13'), +(371, 'ADD_ACCUMULATE', 450, NULL, '{\"report_date\":\"2025-07-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-29 06:39:13'), +(372, 'ADD_ACCUMULATE', 451, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-30 06:50:30'), +(373, 'ADD_ACCUMULATE', 452, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-30 06:50:30'), +(374, 'ADD_ACCUMULATE', 453, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-30 06:50:30'), +(375, 'ADD_ACCUMULATE', 454, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(376, 'ADD_ACCUMULATE', 455, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(377, 'ADD_ACCUMULATE', 456, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(378, 'ADD_ACCUMULATE', 457, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(379, 'ADD_ACCUMULATE', 458, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(380, 'ADD_ACCUMULATE', 459, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(381, 'ADD_ACCUMULATE', 460, NULL, '{\"report_date\":\"2025-07-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-30 06:52:16'), +(382, 'ADD_ACCUMULATE', 461, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:42:56'), +(383, 'ADD_ACCUMULATE', 462, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:43:32'), +(384, 'ADD_ACCUMULATE', 464, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:43:32'), +(385, 'ADD_ACCUMULATE', 466, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(386, 'ADD_ACCUMULATE', 467, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(387, 'ADD_ACCUMULATE', 468, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(388, 'ADD_ACCUMULATE', 469, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(389, 'ADD_ACCUMULATE', 470, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(390, 'ADD_ACCUMULATE', 471, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(391, 'ADD_ACCUMULATE', 472, NULL, '{\"report_date\":\"2025-07-31\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-07-31 06:44:00'), +(392, 'ADD_ACCUMULATE', 473, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(393, 'ADD_ACCUMULATE', 474, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(394, 'ADD_ACCUMULATE', 475, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(395, 'ADD_ACCUMULATE', 476, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(396, 'ADD_ACCUMULATE', 477, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(397, 'ADD_ACCUMULATE', 478, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(398, 'ADD_ACCUMULATE', 479, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(399, 'ADD_ACCUMULATE', 480, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(400, 'ADD_ACCUMULATE', 481, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(401, 'ADD_ACCUMULATE', 482, NULL, '{\"report_date\":\"2025-07-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-07-31 22:24:47'), +(402, 'ADD_ACCUMULATE', 483, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(403, 'ADD_ACCUMULATE', 484, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(404, 'ADD_ACCUMULATE', 485, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(405, 'ADD_ACCUMULATE', 486, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(406, 'ADD_ACCUMULATE', 487, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(407, 'ADD_ACCUMULATE', 488, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:47'), +(408, 'ADD_ACCUMULATE', 489, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-01 04:57:48'), +(409, 'ADD_ACCUMULATE', 490, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-01 05:02:28'), +(410, 'ADD_ACCUMULATE', 492, NULL, '{\"report_date\":\"2025-08-01\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-01 05:02:28'), +(411, 'ADD_ACCUMULATE', 494, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:42:39'), +(412, 'ADD_ACCUMULATE', 496, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:42:39'), +(413, 'ADD_ACCUMULATE', 498, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:14'), +(414, 'ADD_ACCUMULATE', 499, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:15'), +(415, 'ADD_ACCUMULATE', 500, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:15'), +(416, 'ADD_ACCUMULATE', 501, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:39'), +(417, 'ADD_ACCUMULATE', 502, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:39'), +(418, 'ADD_ACCUMULATE', 503, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:39'), +(419, 'ADD_ACCUMULATE', 504, NULL, '{\"report_date\":\"2025-08-07\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-07 06:43:52'), +(420, 'ADD_ACCUMULATE', 505, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-08 06:45:20'), +(421, 'ADD_ACCUMULATE', 506, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:58:42'), +(422, 'ADD_ACCUMULATE', 507, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:58:42'), +(423, 'ADD_ACCUMULATE', 508, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:18'), +(424, 'ADD_ACCUMULATE', 509, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:19'), +(425, 'ADD_ACCUMULATE', 510, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:19'), +(426, 'ADD_ACCUMULATE', 511, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:19'), +(427, 'ADD_ACCUMULATE', 512, NULL, '{\"report_date\":\"2025-08-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-08 06:59:19'), +(428, 'ADD_ACCUMULATE', 513, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-11 06:27:37'), +(429, 'ADD_ACCUMULATE', 514, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"16.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"16.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-11 06:27:37'), +(430, 'ADD_ACCUMULATE', 515, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:23'), +(431, 'ADD_ACCUMULATE', 516, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:23'), +(432, 'ADD_ACCUMULATE', 517, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:49'), +(433, 'ADD_ACCUMULATE', 518, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:49'), +(434, 'ADD_ACCUMULATE', 519, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:50'), +(435, 'ADD_ACCUMULATE', 520, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:50'), +(436, 'ADD_ACCUMULATE', 521, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:50'), +(437, 'ADD_ACCUMULATE', 522, NULL, '{\"report_date\":\"2025-08-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-11 06:46:50'), +(438, 'ADD_ACCUMULATE', 523, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(439, 'ADD_ACCUMULATE', 524, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(440, 'ADD_ACCUMULATE', 525, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(441, 'ADD_ACCUMULATE', 526, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(442, 'ADD_ACCUMULATE', 527, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(443, 'ADD_ACCUMULATE', 528, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(444, 'ADD_ACCUMULATE', 529, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(445, 'ADD_ACCUMULATE', 530, NULL, '{\"report_date\":\"2025-08-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-12 06:47:24'), +(446, 'ADD_ACCUMULATE', 531, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-13 06:31:32'), +(447, 'ADD_ACCUMULATE', 532, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:13'), +(448, 'ADD_ACCUMULATE', 534, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(449, 'ADD_ACCUMULATE', 535, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(450, 'ADD_ACCUMULATE', 536, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(451, 'ADD_ACCUMULATE', 537, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(452, 'ADD_ACCUMULATE', 538, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(453, 'ADD_ACCUMULATE', 539, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(454, 'ADD_ACCUMULATE', 540, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:36:48'), +(455, 'ADD_ACCUMULATE', 541, NULL, '{\"report_date\":\"2025-08-13\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-13 06:37:19'), +(456, 'ADD_ACCUMULATE', 542, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-14 06:35:27'), +(457, 'ADD_ACCUMULATE', 544, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:39:03'), +(458, 'ADD_ACCUMULATE', 546, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:39:44'), +(459, 'ADD_ACCUMULATE', 548, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(460, 'ADD_ACCUMULATE', 549, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(461, 'ADD_ACCUMULATE', 550, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(462, 'ADD_ACCUMULATE', 551, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(463, 'ADD_ACCUMULATE', 552, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(464, 'ADD_ACCUMULATE', 553, NULL, '{\"report_date\":\"2025-08-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-14 06:40:10'), +(465, 'ADD_ACCUMULATE', 554, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:21:36'), +(466, 'ADD_ACCUMULATE', 555, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:21:36'), +(467, 'ADD_ACCUMULATE', 556, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:22:01'), +(468, 'ADD_ACCUMULATE', 557, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:22:53'), +(469, 'ADD_ACCUMULATE', 559, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-18 06:23:34'), +(470, 'ADD_ACCUMULATE', 561, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:41:24'), +(471, 'ADD_ACCUMULATE', 562, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:41:24'), +(472, 'ADD_ACCUMULATE', 563, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:41:24'), +(473, 'ADD_ACCUMULATE', 564, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:10'), +(474, 'ADD_ACCUMULATE', 565, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:10'), +(475, 'ADD_ACCUMULATE', 566, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:10'), +(476, 'ADD_ACCUMULATE', 567, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:35'), +(477, 'ADD_ACCUMULATE', 568, NULL, '{\"report_date\":\"2025-08-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-18 06:43:35'), +(478, 'ADD_ACCUMULATE', 569, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:02:49'), +(479, 'ADD_ACCUMULATE', 570, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:03:30'), +(480, 'ADD_ACCUMULATE', 571, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:03:30'), +(481, 'ADD_ACCUMULATE', 572, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:03:30'), +(482, 'ADD_ACCUMULATE', 573, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:03:30'), +(483, 'ADD_ACCUMULATE', 574, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(484, 'ADD_ACCUMULATE', 575, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(485, 'ADD_ACCUMULATE', 576, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(486, 'ADD_ACCUMULATE', 577, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(487, 'ADD_ACCUMULATE', 578, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-19 08:04:05'), +(488, 'ADD_ACCUMULATE', 579, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-19 08:36:51'), +(489, 'ADD_ACCUMULATE', 580, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-19 08:36:51'), +(490, 'ADD_ACCUMULATE', 581, NULL, '{\"report_date\":\"2025-08-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-19 08:36:51'), +(491, 'ADD_ACCUMULATE', 582, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-20 06:19:36'), +(492, 'ADD_ACCUMULATE', 583, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-20 06:21:28'), +(493, 'ADD_ACCUMULATE', 585, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-20 06:21:28'), +(494, 'ADD_ACCUMULATE', 587, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:43:46'), +(495, 'ADD_ACCUMULATE', 588, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:23'), +(496, 'ADD_ACCUMULATE', 589, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:23'), +(497, 'ADD_ACCUMULATE', 590, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:23'), +(498, 'ADD_ACCUMULATE', 591, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:24'), +(499, 'ADD_ACCUMULATE', 592, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:24'), +(500, 'ADD_ACCUMULATE', 593, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:24'), +(501, 'ADD_ACCUMULATE', 594, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:26'), +(502, 'ADD_ACCUMULATE', 595, NULL, '{\"report_date\":\"2025-08-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-20 06:44:26'), +(503, 'ADD_ACCUMULATE', 596, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-21 06:30:36'), +(504, 'ADD_ACCUMULATE', 597, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-21 06:30:36'), +(505, 'ADD_ACCUMULATE', 598, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:50:38'), +(506, 'ADD_ACCUMULATE', 599, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:50:38'), +(507, 'ADD_ACCUMULATE', 600, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:51:23'), +(508, 'ADD_ACCUMULATE', 602, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:51:23'), +(509, 'ADD_ACCUMULATE', 604, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:51:23'), +(510, 'ADD_ACCUMULATE', 606, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:51:23'), +(511, 'ADD_ACCUMULATE', 608, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:54:46'), +(512, 'ADD_ACCUMULATE', 610, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-21 07:55:25'), +(513, 'ADD_ACCUMULATE', 612, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-21 08:24:50'), +(514, 'ADD_ACCUMULATE', 613, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-21 08:24:50'), +(515, 'ADD_ACCUMULATE', 614, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-22 06:21:15'), +(516, 'ADD_ACCUMULATE', 615, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-22 06:23:12'), +(517, 'ADD_ACCUMULATE', 617, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-22 06:23:55'), +(518, 'ADD_ACCUMULATE', 618, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:27:43'), +(519, 'ADD_ACCUMULATE', 619, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(520, 'ADD_ACCUMULATE', 620, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(521, 'ADD_ACCUMULATE', 621, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(522, 'ADD_ACCUMULATE', 622, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(523, 'ADD_ACCUMULATE', 623, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(524, 'ADD_ACCUMULATE', 624, NULL, '{\"report_date\":\"2025-08-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-22 06:28:15'), +(525, 'ADD_ACCUMULATE', 625, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:02'), +(526, 'ADD_ACCUMULATE', 627, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:25'), +(527, 'ADD_ACCUMULATE', 628, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(528, 'ADD_ACCUMULATE', 629, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(529, 'ADD_ACCUMULATE', 630, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(530, 'ADD_ACCUMULATE', 631, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(531, 'ADD_ACCUMULATE', 632, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(532, 'ADD_ACCUMULATE', 633, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(533, 'ADD_ACCUMULATE', 634, NULL, '{\"report_date\":\"2025-08-23\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-23 04:57:54'), +(534, 'ADD_ACCUMULATE', 635, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(535, 'ADD_ACCUMULATE', 636, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(536, 'ADD_ACCUMULATE', 637, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(537, 'ADD_ACCUMULATE', 638, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(538, 'ADD_ACCUMULATE', 639, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(539, 'ADD_ACCUMULATE', 640, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(540, 'ADD_ACCUMULATE', 641, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(541, 'ADD_ACCUMULATE', 642, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(542, 'ADD_ACCUMULATE', 643, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(543, 'ADD_ACCUMULATE', 644, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-25 06:48:34'), +(544, 'ADD_ACCUMULATE', 645, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-25 06:49:16'), +(545, 'ADD_ACCUMULATE', 646, NULL, '{\"report_date\":\"2025-08-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-25 06:49:17'), +(546, 'ADD_ACCUMULATE', 647, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:28:03'), +(547, 'ADD_ACCUMULATE', 649, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:28:35'), +(548, 'ADD_ACCUMULATE', 650, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(549, 'ADD_ACCUMULATE', 651, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(550, 'ADD_ACCUMULATE', 652, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(551, 'ADD_ACCUMULATE', 653, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(552, 'ADD_ACCUMULATE', 654, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(553, 'ADD_ACCUMULATE', 655, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(554, 'ADD_ACCUMULATE', 656, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:02'), +(555, 'ADD_ACCUMULATE', 657, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-26 07:29:03'), +(556, 'ADD_ACCUMULATE', 658, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-26 08:22:12'), +(557, 'ADD_ACCUMULATE', 659, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-26 08:22:12'), +(558, 'ADD_ACCUMULATE', 660, NULL, '{\"report_date\":\"2025-08-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-26 08:22:12'), +(559, 'ADD_ACCUMULATE', 661, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(560, 'ADD_ACCUMULATE', 662, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(561, 'ADD_ACCUMULATE', 663, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(562, 'ADD_ACCUMULATE', 664, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(563, 'ADD_ACCUMULATE', 665, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(564, 'ADD_ACCUMULATE', 666, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(565, 'ADD_ACCUMULATE', 667, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:47'), +(566, 'ADD_ACCUMULATE', 668, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-27 06:44:48'), +(567, 'ADD_ACCUMULATE', 669, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-27 06:45:32'), +(568, 'ADD_ACCUMULATE', 671, NULL, '{\"report_date\":\"2025-08-27\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-27 06:45:32'), +(569, 'ADD_ACCUMULATE', 673, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-28 08:31:42'), +(570, 'ADD_ACCUMULATE', 675, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-28 08:31:42'), +(571, 'ADD_ACCUMULATE', 677, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-28 08:31:42'), +(572, 'ADD_ACCUMULATE', 679, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-28 08:31:42'), +(573, 'ADD_ACCUMULATE', 681, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:37:46'), +(574, 'ADD_ACCUMULATE', 683, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:38:15'), +(575, 'ADD_ACCUMULATE', 685, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:38:50'), +(576, 'ADD_ACCUMULATE', 687, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:39:24'), +(577, 'ADD_ACCUMULATE', 688, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(578, 'ADD_ACCUMULATE', 689, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(579, 'ADD_ACCUMULATE', 690, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(580, 'ADD_ACCUMULATE', 691, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(581, 'ADD_ACCUMULATE', 692, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(582, 'ADD_ACCUMULATE', 693, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:40:00'), +(583, 'ADD_ACCUMULATE', 694, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:44:56'), +(584, 'ADD_ACCUMULATE', 695, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:44:56'), +(585, 'ADD_ACCUMULATE', 696, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:44:56'), +(586, 'ADD_ACCUMULATE', 697, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(587, 'ADD_ACCUMULATE', 698, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(588, 'ADD_ACCUMULATE', 699, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(589, 'ADD_ACCUMULATE', 700, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(590, 'ADD_ACCUMULATE', 701, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(591, 'ADD_ACCUMULATE', 702, NULL, '{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-28 08:45:19'), +(592, 'DELETE', 693, '{\"id\":693,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:05'), +(593, 'DELETE', 702, '{\"id\":702,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:16'), +(594, 'DELETE', 697, '{\"id\":697,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:26'), +(595, 'DELETE', 688, '{\"id\":688,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:32'), +(596, 'DELETE', 691, '{\"id\":691,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:41'), +(597, 'DELETE', 700, '{\"id\":700,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:48'), +(598, 'DELETE', 692, '{\"id\":692,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:46:56'), +(599, 'DELETE', 701, '{\"id\":701,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-28 08:47:01'), +(600, 'ADD_ACCUMULATE', 703, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(601, 'ADD_ACCUMULATE', 704, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(602, 'ADD_ACCUMULATE', 705, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(603, 'ADD_ACCUMULATE', 706, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(604, 'ADD_ACCUMULATE', 707, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(605, 'ADD_ACCUMULATE', 708, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(606, 'ADD_ACCUMULATE', 709, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(607, 'ADD_ACCUMULATE', 710, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:02'), +(608, 'ADD_ACCUMULATE', 711, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:35'), +(609, 'ADD_ACCUMULATE', 713, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:35'), +(610, 'ADD_ACCUMULATE', 715, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:35'), +(611, 'ADD_ACCUMULATE', 717, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-08-29 06:47:35'), +(612, 'DELETE', 705, '{\"id\":705,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":8,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:55:28'), +(613, 'ADD_ACCUMULATE', 719, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-29 21:55:56'), +(614, 'ADD_ACCUMULATE', 720, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-29 21:55:56'), +(615, 'ADD_ACCUMULATE', 721, NULL, '{\"report_date\":\"2025-08-29\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-29 21:55:56'), +(616, 'DELETE', 711, '{\"id\":711,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"6.00\",\"created_at\":\"2025-08-29T06:47:35.000Z\",\"updated_at\":\"2025-08-29T06:47:35.000Z\",\"created_by\":6,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:56:26'), +(617, 'DELETE', 712, '{\"id\":712,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":1,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-29T06:47:35.000Z\",\"updated_at\":\"2025-08-29T06:47:35.000Z\",\"created_by\":6,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:56:43'), +(618, 'DELETE', 707, '{\"id\":707,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:57:03'), +(619, 'DELETE', 708, '{\"id\":708,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:57:16'), +(620, 'DELETE', 709, '{\"id\":709,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-08-29 21:57:26'), +(621, 'ADD_ACCUMULATE', 722, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-30 05:12:03'), +(622, 'ADD_ACCUMULATE', 723, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-30 05:12:03'), +(623, 'ADD_ACCUMULATE', 724, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-08-30 05:12:03'), +(624, 'ADD_ACCUMULATE', 725, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(625, 'ADD_ACCUMULATE', 726, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(626, 'ADD_ACCUMULATE', 727, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(627, 'ADD_ACCUMULATE', 728, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(628, 'ADD_ACCUMULATE', 729, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(629, 'ADD_ACCUMULATE', 730, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(630, 'ADD_ACCUMULATE', 731, NULL, '{\"report_date\":\"2025-08-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-08-30 05:36:49'), +(631, 'ADD_ACCUMULATE', 732, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:18:28'), +(632, 'ADD_ACCUMULATE', 733, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:18:28'), +(633, 'ADD_ACCUMULATE', 734, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:11'), +(634, 'ADD_ACCUMULATE', 735, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:11'), +(635, 'ADD_ACCUMULATE', 736, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:11'), +(636, 'ADD_ACCUMULATE', 737, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:35'), +(637, 'ADD_ACCUMULATE', 738, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:35'), +(638, 'ADD_ACCUMULATE', 739, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:19:35'), +(639, 'ADD_ACCUMULATE', 740, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 06:20:03'), +(640, 'DELETE', 650, '{\"id\":650,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:13:55'), +(641, 'DELETE', 654, '{\"id\":654,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:14:02'), +(642, 'DELETE', 656, '{\"id\":656,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:14:11'), +(643, 'DELETE', 572, '{\"id\":572,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":7,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:15:09'), +(644, 'DELETE', 571, '{\"id\":571,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:15:17'), +(645, 'DELETE', 570, '{\"id\":570,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:15:27'), +(646, 'DELETE', 599, '{\"id\":599,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":7,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:50:38.000Z\",\"updated_at\":\"2025-08-21T07:50:38.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:15:59'), +(647, 'DELETE', 604, '{\"id\":604,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:14'), +(648, 'DELETE', 605, '{\"id\":605,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:19'), +(649, 'DELETE', 606, '{\"id\":606,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:28'), +(650, 'DELETE', 607, '{\"id\":607,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:33'), +(651, 'DELETE', 598, '{\"id\":598,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":1,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:50:38.000Z\",\"updated_at\":\"2025-08-21T07:50:38.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:16:54'), +(652, 'ADD_ACCUMULATE', 741, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 23:18:03'), +(653, 'ADD_ACCUMULATE', 742, NULL, '{\"report_date\":\"2025-08-21\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-01 23:18:03'), +(654, 'DELETE', 588, '{\"id\":588,\"report_date\":\"2025-08-20T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-20T06:44:23.000Z\",\"updated_at\":\"2025-08-20T06:44:23.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:26:52'), +(655, 'DELETE', 592, '{\"id\":592,\"report_date\":\"2025-08-20T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-20T06:44:24.000Z\",\"updated_at\":\"2025-08-20T06:44:24.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:26:58'), +(656, 'DELETE', 639, '{\"id\":639,\"report_date\":\"2025-08-25T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-25T06:48:34.000Z\",\"updated_at\":\"2025-08-25T06:48:34.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:27:26'), +(657, 'DELETE', 642, '{\"id\":642,\"report_date\":\"2025-08-25T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-25T06:48:34.000Z\",\"updated_at\":\"2025-08-25T06:48:34.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 3, 'Manual deletion', NULL, NULL, '2025-09-01 23:27:31'), +(658, 'ADD_ACCUMULATE', 743, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:34:20'), +(659, 'ADD_ACCUMULATE', 744, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:34:20'), +(660, 'DELETE_SINGLE', 744, '{\"worker_name\":\"이창호\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-09-02T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-09-02 07:35:18'), +(661, 'DELETE_SINGLE', 743, '{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-09-02T00:00:00.000Z\"}', NULL, 3, '개별 항목 삭제', NULL, NULL, '2025-09-02 07:35:21'), +(662, 'ADD_ACCUMULATE', 745, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(663, 'ADD_ACCUMULATE', 746, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(664, 'ADD_ACCUMULATE', 747, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(665, 'ADD_ACCUMULATE', 748, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(666, 'ADD_ACCUMULATE', 749, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(667, 'ADD_ACCUMULATE', 750, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:04'), +(668, 'ADD_ACCUMULATE', 751, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(669, 'ADD_ACCUMULATE', 752, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(670, 'ADD_ACCUMULATE', 753, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(671, 'ADD_ACCUMULATE', 754, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(672, 'ADD_ACCUMULATE', 755, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(673, 'ADD_ACCUMULATE', 756, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:36:31'), +(674, 'ADD_ACCUMULATE', 757, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:37:19'), +(675, 'ADD_ACCUMULATE', 758, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-02 07:37:19'), +(676, 'ADD_ACCUMULATE', 759, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-02 08:16:14'), +(677, 'ADD_ACCUMULATE', 761, NULL, '{\"report_date\":\"2025-09-02\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-02 08:16:14'), +(678, 'ADD_ACCUMULATE', 763, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:47'), +(679, 'ADD_ACCUMULATE', 764, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:47'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(680, 'ADD_ACCUMULATE', 765, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(681, 'ADD_ACCUMULATE', 766, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(682, 'ADD_ACCUMULATE', 767, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(683, 'ADD_ACCUMULATE', 768, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(684, 'ADD_ACCUMULATE', 769, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(685, 'ADD_ACCUMULATE', 770, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-03 06:34:48'), +(686, 'ADD_ACCUMULATE', 771, NULL, '{\"report_date\":\"2025-09-03\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-03 06:44:18'), +(687, 'ADD_ACCUMULATE', 772, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:32'), +(688, 'ADD_ACCUMULATE', 773, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:32'), +(689, 'ADD_ACCUMULATE', 774, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:32'), +(690, 'ADD_ACCUMULATE', 775, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:32'), +(691, 'ADD_ACCUMULATE', 776, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:33'), +(692, 'ADD_ACCUMULATE', 777, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:33'), +(693, 'ADD_ACCUMULATE', 778, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:33'), +(694, 'ADD_ACCUMULATE', 779, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-04 06:41:33'), +(695, 'ADD_ACCUMULATE', 780, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-04 06:48:34'), +(696, 'ADD_ACCUMULATE', 781, NULL, '{\"report_date\":\"2025-09-04\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-04 06:48:34'), +(697, 'ADD_ACCUMULATE', 782, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:30'), +(698, 'ADD_ACCUMULATE', 783, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:30'), +(699, 'ADD_ACCUMULATE', 784, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:30'), +(700, 'ADD_ACCUMULATE', 785, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:31'), +(701, 'ADD_ACCUMULATE', 786, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:31'), +(702, 'ADD_ACCUMULATE', 787, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:31'), +(703, 'ADD_ACCUMULATE', 788, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-05 06:39:31'), +(704, 'ADD_ACCUMULATE', 789, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-05 22:09:55'), +(705, 'ADD_ACCUMULATE', 790, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-05 22:09:55'), +(706, 'ADD_ACCUMULATE', 791, NULL, '{\"report_date\":\"2025-09-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-05 22:09:55'), +(707, 'ADD_ACCUMULATE', 792, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-06 04:21:10'), +(708, 'ADD_ACCUMULATE', 793, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-06 04:21:10'), +(709, 'ADD_ACCUMULATE', 794, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-06 04:21:10'), +(710, 'ADD_ACCUMULATE', 795, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:18'), +(711, 'ADD_ACCUMULATE', 796, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:18'), +(712, 'ADD_ACCUMULATE', 797, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:18'), +(713, 'ADD_ACCUMULATE', 798, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:19'), +(714, 'ADD_ACCUMULATE', 799, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:19'), +(715, 'ADD_ACCUMULATE', 800, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:19'), +(716, 'ADD_ACCUMULATE', 801, NULL, '{\"report_date\":\"2025-09-06\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-06 05:28:19'), +(717, 'ADD_ACCUMULATE', 802, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(718, 'ADD_ACCUMULATE', 803, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(719, 'ADD_ACCUMULATE', 804, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(720, 'ADD_ACCUMULATE', 805, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(721, 'ADD_ACCUMULATE', 806, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(722, 'ADD_ACCUMULATE', 807, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(723, 'ADD_ACCUMULATE', 808, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-08 06:15:43'), +(724, 'ADD_ACCUMULATE', 809, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-08 06:47:37'), +(725, 'ADD_ACCUMULATE', 810, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-08 06:47:37'), +(726, 'ADD_ACCUMULATE', 811, NULL, '{\"report_date\":\"2025-09-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-08 06:47:37'), +(727, 'ADD_ACCUMULATE', 812, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(728, 'ADD_ACCUMULATE', 813, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(729, 'ADD_ACCUMULATE', 814, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(730, 'ADD_ACCUMULATE', 815, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(731, 'ADD_ACCUMULATE', 816, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(732, 'ADD_ACCUMULATE', 817, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(733, 'ADD_ACCUMULATE', 818, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-09 06:03:27'), +(734, 'ADD_ACCUMULATE', 819, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-09 06:44:29'), +(735, 'ADD_ACCUMULATE', 820, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-09 06:44:29'), +(736, 'ADD_ACCUMULATE', 821, NULL, '{\"report_date\":\"2025-09-09\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-09 06:44:29'), +(737, 'ADD_ACCUMULATE', 822, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(738, 'ADD_ACCUMULATE', 823, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(739, 'ADD_ACCUMULATE', 824, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(740, 'ADD_ACCUMULATE', 825, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(741, 'ADD_ACCUMULATE', 826, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(742, 'ADD_ACCUMULATE', 827, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(743, 'ADD_ACCUMULATE', 828, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-10 06:27:52'), +(744, 'ADD_ACCUMULATE', 829, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-10 06:48:43'), +(745, 'ADD_ACCUMULATE', 830, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-10 06:48:43'), +(746, 'ADD_ACCUMULATE', 831, NULL, '{\"report_date\":\"2025-09-10\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-10 06:48:43'), +(747, 'ADD_ACCUMULATE', 832, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:37:11'), +(748, 'ADD_ACCUMULATE', 834, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":4,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:38:24'), +(749, 'ADD_ACCUMULATE', 837, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:39:38'), +(750, 'ADD_ACCUMULATE', 838, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:40:48'), +(751, 'ADD_ACCUMULATE', 839, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:46'), +(752, 'ADD_ACCUMULATE', 840, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(753, 'ADD_ACCUMULATE', 841, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(754, 'ADD_ACCUMULATE', 842, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(755, 'ADD_ACCUMULATE', 843, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(756, 'ADD_ACCUMULATE', 844, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 6, '누적 추가 by 반치원 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:47'), +(757, 'ADD_ACCUMULATE', 845, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:51'), +(758, 'ADD_ACCUMULATE', 847, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:51'), +(759, 'ADD_ACCUMULATE', 849, NULL, '{\"report_date\":\"2025-09-11\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-11 06:41:51'), +(760, 'DELETE', 849, '{\"id\":849,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"4.00\",\"created_at\":\"2025-09-11T06:41:51.000Z\",\"updated_at\":\"2025-09-11T06:41:51.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-11 06:42:40'), +(761, 'DELETE', 850, '{\"id\":850,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"4.00\",\"created_at\":\"2025-09-11T06:41:51.000Z\",\"updated_at\":\"2025-09-11T06:41:51.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-11 06:42:49'), +(762, 'DELETE', 839, '{\"id\":839,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-11T06:41:46.000Z\",\"updated_at\":\"2025-09-11T06:41:46.000Z\",\"created_by\":6,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-11 06:43:07'), +(763, 'DELETE', 837, '{\"id\":837,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":8,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-11T06:39:38.000Z\",\"updated_at\":\"2025-09-11T06:39:38.000Z\",\"created_by\":5,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-11 06:43:16'), +(764, 'ADD_ACCUMULATE', 851, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(765, 'ADD_ACCUMULATE', 852, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(766, 'ADD_ACCUMULATE', 853, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(767, 'ADD_ACCUMULATE', 854, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(768, 'ADD_ACCUMULATE', 855, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(769, 'ADD_ACCUMULATE', 856, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(770, 'ADD_ACCUMULATE', 857, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(771, 'ADD_ACCUMULATE', 858, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(772, 'ADD_ACCUMULATE', 859, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(773, 'ADD_ACCUMULATE', 860, NULL, '{\"report_date\":\"2025-09-12\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-12 06:45:29'), +(774, 'ADD_ACCUMULATE', 861, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(775, 'ADD_ACCUMULATE', 862, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(776, 'ADD_ACCUMULATE', 863, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(777, 'ADD_ACCUMULATE', 864, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(778, 'ADD_ACCUMULATE', 865, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(779, 'ADD_ACCUMULATE', 866, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(780, 'ADD_ACCUMULATE', 867, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(781, 'ADD_ACCUMULATE', 868, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(782, 'ADD_ACCUMULATE', 869, NULL, '{\"report_date\":\"2025-09-13\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-13 06:38:14'), +(783, 'ADD_ACCUMULATE', 870, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:40'), +(784, 'ADD_ACCUMULATE', 871, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:40'), +(785, 'ADD_ACCUMULATE', 872, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:40'), +(786, 'ADD_ACCUMULATE', 873, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:40'), +(787, 'ADD_ACCUMULATE', 874, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(788, 'ADD_ACCUMULATE', 875, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(789, 'ADD_ACCUMULATE', 876, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(790, 'ADD_ACCUMULATE', 877, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(791, 'ADD_ACCUMULATE', 878, NULL, '{\"report_date\":\"2025-09-14\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-14 04:47:41'), +(792, 'ADD_ACCUMULATE', 879, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:00'), +(793, 'ADD_ACCUMULATE', 880, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:00'), +(794, 'ADD_ACCUMULATE', 881, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:00'), +(795, 'ADD_ACCUMULATE', 882, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:00'), +(796, 'ADD_ACCUMULATE', 883, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(797, 'ADD_ACCUMULATE', 884, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(798, 'ADD_ACCUMULATE', 885, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(799, 'ADD_ACCUMULATE', 886, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(800, 'ADD_ACCUMULATE', 887, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(801, 'ADD_ACCUMULATE', 888, NULL, '{\"report_date\":\"2025-09-15\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-15 06:50:01'), +(802, 'ADD_ACCUMULATE', 889, NULL, '{\"report_date\":\"2025-09-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-16 06:51:19'), +(803, 'ADD_ACCUMULATE', 890, NULL, '{\"report_date\":\"2025-09-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-16 06:51:19'), +(804, 'ADD_ACCUMULATE', 891, NULL, '{\"report_date\":\"2025-09-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-16 06:52:12'), +(805, 'ADD_ACCUMULATE', 893, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-17 06:43:08'), +(806, 'ADD_ACCUMULATE', 894, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-17 06:43:08'), +(807, 'ADD_ACCUMULATE', 895, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(808, 'ADD_ACCUMULATE', 896, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(809, 'ADD_ACCUMULATE', 897, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(810, 'ADD_ACCUMULATE', 898, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(811, 'ADD_ACCUMULATE', 899, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(812, 'ADD_ACCUMULATE', 900, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(813, 'ADD_ACCUMULATE', 901, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(814, 'ADD_ACCUMULATE', 902, NULL, '{\"report_date\":\"2025-09-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-17 06:45:06'), +(815, 'ADD_ACCUMULATE', 903, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:43:40'), +(816, 'ADD_ACCUMULATE', 904, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:43:40'), +(817, 'ADD_ACCUMULATE', 905, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(818, 'ADD_ACCUMULATE', 906, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(819, 'ADD_ACCUMULATE', 907, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(820, 'ADD_ACCUMULATE', 908, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(821, 'ADD_ACCUMULATE', 909, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:44:42'), +(822, 'ADD_ACCUMULATE', 910, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-18 06:46:39'), +(823, 'ADD_ACCUMULATE', 911, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-18 06:54:48'), +(824, 'ADD_ACCUMULATE', 912, NULL, '{\"report_date\":\"2025-09-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-18 06:54:48'), +(825, 'ADD_ACCUMULATE', 913, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:51:40'), +(826, 'ADD_ACCUMULATE', 914, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:51:40'), +(827, 'ADD_ACCUMULATE', 915, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(828, 'ADD_ACCUMULATE', 916, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(829, 'ADD_ACCUMULATE', 917, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(830, 'ADD_ACCUMULATE', 918, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(831, 'ADD_ACCUMULATE', 919, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:05'), +(832, 'ADD_ACCUMULATE', 920, NULL, '{\"report_date\":\"2025-09-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-19 06:52:23'), +(833, 'ADD_ACCUMULATE', 921, NULL, '{\"report_date\":\"2025-09-20\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-20 05:30:19'), +(834, 'ADD_ACCUMULATE', 922, NULL, '{\"report_date\":\"2025-09-20\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-20 05:30:19'), +(835, 'ADD_ACCUMULATE', 923, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(836, 'ADD_ACCUMULATE', 924, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(837, 'ADD_ACCUMULATE', 925, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(838, 'ADD_ACCUMULATE', 926, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(839, 'ADD_ACCUMULATE', 927, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(840, 'ADD_ACCUMULATE', 928, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-22 06:47:25'), +(841, 'ADD_ACCUMULATE', 929, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-22 06:50:29'), +(842, 'ADD_ACCUMULATE', 930, NULL, '{\"report_date\":\"2025-09-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-22 06:50:29'), +(843, 'ADD_ACCUMULATE', 931, NULL, '{\"report_date\":\"2025-09-23\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-23 05:46:40'), +(844, 'ADD_ACCUMULATE', 932, NULL, '{\"report_date\":\"2025-09-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-23 05:46:40'), +(845, 'ADD_ACCUMULATE', 933, NULL, '{\"report_date\":\"2025-09-24\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-25 01:14:58'), +(846, 'ADD_ACCUMULATE', 934, NULL, '{\"report_date\":\"2025-09-24\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-25 01:14:58'), +(847, 'ADD_ACCUMULATE', 935, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:07'), +(848, 'ADD_ACCUMULATE', 936, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:07'), +(849, 'ADD_ACCUMULATE', 937, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(850, 'ADD_ACCUMULATE', 938, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'); +INSERT INTO `work_report_audit_log` (`log_id`, `action`, `report_id`, `old_values`, `new_values`, `changed_by`, `change_reason`, `ip_address`, `user_agent`, `created_at`) VALUES +(851, 'ADD_ACCUMULATE', 939, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(852, 'ADD_ACCUMULATE', 940, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(853, 'ADD_ACCUMULATE', 941, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(854, 'ADD_ACCUMULATE', 942, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(855, 'ADD_ACCUMULATE', 943, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(856, 'ADD_ACCUMULATE', 944, NULL, '{\"report_date\":\"2025-09-29\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-29 06:36:47'), +(857, 'ADD_ACCUMULATE', 945, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(858, 'ADD_ACCUMULATE', 946, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(859, 'ADD_ACCUMULATE', 947, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(860, 'ADD_ACCUMULATE', 948, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(861, 'ADD_ACCUMULATE', 949, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(862, 'ADD_ACCUMULATE', 950, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:26'), +(863, 'ADD_ACCUMULATE', 951, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:27'), +(864, 'ADD_ACCUMULATE', 952, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:27'), +(865, 'ADD_ACCUMULATE', 953, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-09-30 06:52:27'), +(866, 'DELETE', 952, '{\"id\":952,\"report_date\":\"2025-09-30T00:00:00.000Z\",\"worker_id\":2,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-30T06:52:27.000Z\",\"updated_at\":\"2025-09-30T06:52:27.000Z\",\"created_by\":3,\"updated_by\":null}', NULL, 5, 'Manual deletion', NULL, NULL, '2025-09-30 06:56:36'), +(867, 'ADD_ACCUMULATE', 954, NULL, '{\"report_date\":\"2025-09-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}', 5, '누적 추가 by 임영규 - 삭제 없음', NULL, NULL, '2025-09-30 06:56:55'), +(868, 'ADD_ACCUMULATE', 955, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 05:25:58'), +(869, 'ADD_ACCUMULATE', 956, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 05:25:59'), +(870, 'ADD_ACCUMULATE', 957, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:32'), +(871, 'ADD_ACCUMULATE', 958, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:32'), +(872, 'ADD_ACCUMULATE', 959, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:32'), +(873, 'ADD_ACCUMULATE', 960, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:32'), +(874, 'ADD_ACCUMULATE', 961, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:33'), +(875, 'ADD_ACCUMULATE', 962, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:33'), +(876, 'ADD_ACCUMULATE', 963, NULL, '{\"report_date\":\"2025-10-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-02 06:22:33'), +(877, 'ADD_ACCUMULATE', 964, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-10 23:35:07'), +(878, 'ADD_ACCUMULATE', 965, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-10 23:35:07'), +(879, 'ADD_ACCUMULATE', 966, NULL, '{\"report_date\":\"2025-09-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}', 3, '누적 추가 by 김두수 - 삭제 없음', NULL, NULL, '2025-10-10 23:35:07'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_status_types` +-- + +CREATE TABLE `work_status_types` ( + `id` int(11) NOT NULL, + `name` varchar(50) NOT NULL COMMENT '상태명', + `description` text DEFAULT NULL COMMENT '상태 설명', + `is_error` tinyint(1) DEFAULT 0 COMMENT '에러 상태 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_status_types` +-- + +INSERT INTO `work_status_types` (`id`, `name`, `description`, `is_error`, `created_at`) VALUES +(1, '정규', '정상적으로 완료된 작업', 0, '2025-06-16 02:21:16'), +(2, '에러', '오류가 발생한 작업', 1, '2025-06-16 02:21:16'); + +-- -------------------------------------------------------- + +-- +-- 테이블 구조 `work_types` +-- + +CREATE TABLE `work_types` ( + `id` int(11) NOT NULL, + `name` varchar(100) NOT NULL COMMENT '작업 유형명', + `description` text DEFAULT NULL COMMENT '작업 유형 설명', + `category` varchar(50) DEFAULT NULL COMMENT '작업 카테고리', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp() +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- +-- 테이블의 덤프 데이터 `work_types` +-- + +INSERT INTO `work_types` (`id`, `name`, `description`, `category`, `created_at`, `updated_at`) VALUES +(1, 'Base(구조물)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:42'), +(2, 'Vessel(용기)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:47'), +(3, 'Piping Assembly(배관)', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:50'), +(4, '작업대기', NULL, NULL, '2025-06-16 02:21:32', '2025-06-16 03:03:56'); + +-- +-- 덤프된 테이블의 인덱스 +-- + +-- +-- 테이블의 인덱스 `activity_logs` +-- +ALTER TABLE `activity_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_user_activity` (`user_id`,`activity_type`,`created_at`), + ADD KEY `idx_table_record` (`table_name`,`record_id`); + +-- +-- 테이블의 인덱스 `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + ADD PRIMARY KEY (`cutting_plan_id`), + ADD KEY `project_id` (`project_id`), + ADD KEY `fk_cuttingplan_spec` (`spec_id`); + +-- +-- 테이블의 인덱스 `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + ADD PRIMARY KEY (`id`), + ADD KEY `worker_id` (`worker_id`), + ADD KEY `fk_dird_project` (`project_id`), + ADD KEY `fk_dird_issuetype` (`issue_type_id`); + +-- +-- 테이블의 인덱스 `daily_worker_summary` +-- +ALTER TABLE `daily_worker_summary` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `unique_worker_date` (`worker_id`,`report_date`); + +-- +-- 테이블의 인덱스 `daily_work_reports` +-- +ALTER TABLE `daily_work_reports` + ADD PRIMARY KEY (`id`), + ADD KEY `idx_report_date` (`report_date`), + ADD KEY `idx_worker_date` (`worker_id`,`report_date`), + ADD KEY `idx_project_date` (`project_id`,`report_date`), + ADD KEY `idx_work_type` (`work_type_id`), + ADD KEY `idx_work_status` (`work_status_id`), + ADD KEY `idx_error_type` (`error_type_id`), + ADD KEY `idx_created_by` (`created_by`), + ADD KEY `idx_date_worker_creator` (`report_date`,`worker_id`,`created_by`); + +-- +-- 테이블의 인덱스 `EquipmentList` +-- +ALTER TABLE `EquipmentList` + ADD PRIMARY KEY (`equipment_id`), + ADD KEY `factory_id` (`factory_id`); + +-- +-- 테이블의 인덱스 `error_types` +-- +ALTER TABLE `error_types` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `FactoryInfo` +-- +ALTER TABLE `FactoryInfo` + ADD PRIMARY KEY (`factory_id`); + +-- +-- 테이블의 인덱스 `IssueTypes` +-- +ALTER TABLE `IssueTypes` + ADD PRIMARY KEY (`issue_type_id`); + +-- +-- 테이블의 인덱스 `login_logs` +-- +ALTER TABLE `login_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_user_login` (`user_id`,`login_time`); + +-- +-- 테이블의 인덱스 `password_change_logs` +-- +ALTER TABLE `password_change_logs` + ADD PRIMARY KEY (`log_id`), + ADD KEY `changed_by_user_id` (`changed_by_user_id`), + ADD KEY `idx_user_changes` (`user_id`,`changed_at`); + +-- +-- 테이블의 인덱스 `PipeSpecs` +-- +ALTER TABLE `PipeSpecs` + ADD PRIMARY KEY (`spec_id`), + ADD UNIQUE KEY `unique_spec` (`material`,`diameter_in`,`schedule`); + +-- +-- 테이블의 인덱스 `Processes` +-- +ALTER TABLE `Processes` + ADD PRIMARY KEY (`process_id`), + ADD KEY `project_id` (`project_id`); + +-- +-- 테이블의 인덱스 `Projects` +-- +ALTER TABLE `Projects` + ADD PRIMARY KEY (`project_id`); + +-- +-- 테이블의 인덱스 `Tasks` +-- +ALTER TABLE `Tasks` + ADD PRIMARY KEY (`task_id`); + +-- +-- 테이블의 인덱스 `uploaded_documents` +-- +ALTER TABLE `uploaded_documents` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `Users` +-- +ALTER TABLE `Users` + ADD PRIMARY KEY (`user_id`), + ADD UNIQUE KEY `username` (`username`), + ADD UNIQUE KEY `email` (`email`), + ADD KEY `fk_worker` (`worker_id`), + ADD KEY `idx_username` (`username`), + ADD KEY `idx_active_users` (`is_active`,`access_level`); + +-- +-- 테이블의 인덱스 `Workers` +-- +ALTER TABLE `Workers` + ADD PRIMARY KEY (`worker_id`); + +-- +-- 테이블의 인덱스 `worker_groups` +-- +ALTER TABLE `worker_groups` + ADD PRIMARY KEY (`id`), + ADD UNIQUE KEY `uk_leader_worker` (`group_leader_id`,`worker_id`), + ADD KEY `idx_group_leader` (`group_leader_id`), + ADD KEY `idx_worker` (`worker_id`), + ADD KEY `idx_is_active` (`is_active`); + +-- +-- 테이블의 인덱스 `WorkReports` +-- +ALTER TABLE `WorkReports` + ADD PRIMARY KEY (`id`), + ADD KEY `worker_id` (`worker_id`), + ADD KEY `project_id` (`project_id`), + ADD KEY `morning_task_id` (`morning_task_id`), + ADD KEY `afternoon_task_id` (`afternoon_task_id`), + ADD KEY `overtime_task_id` (`overtime_task_id`); + +-- +-- 테이블의 인덱스 `work_report_audit_log` +-- +ALTER TABLE `work_report_audit_log` + ADD PRIMARY KEY (`log_id`), + ADD KEY `idx_action_date` (`action`,`created_at`), + ADD KEY `idx_changed_by` (`changed_by`), + ADD KEY `idx_report_id` (`report_id`); + +-- +-- 테이블의 인덱스 `work_status_types` +-- +ALTER TABLE `work_status_types` + ADD PRIMARY KEY (`id`); + +-- +-- 테이블의 인덱스 `work_types` +-- +ALTER TABLE `work_types` + ADD PRIMARY KEY (`id`); + +-- +-- 덤프된 테이블의 AUTO_INCREMENT +-- + +-- +-- 테이블의 AUTO_INCREMENT `activity_logs` +-- +ALTER TABLE `activity_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + MODIFY `cutting_plan_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; + +-- +-- 테이블의 AUTO_INCREMENT `daily_worker_summary` +-- +ALTER TABLE `daily_worker_summary` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; + +-- +-- 테이블의 AUTO_INCREMENT `daily_work_reports` +-- +ALTER TABLE `daily_work_reports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=967; + +-- +-- 테이블의 AUTO_INCREMENT `EquipmentList` +-- +ALTER TABLE `EquipmentList` + MODIFY `equipment_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `error_types` +-- +ALTER TABLE `error_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=10; + +-- +-- 테이블의 AUTO_INCREMENT `FactoryInfo` +-- +ALTER TABLE `FactoryInfo` + MODIFY `factory_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=6; + +-- +-- 테이블의 AUTO_INCREMENT `IssueTypes` +-- +ALTER TABLE `IssueTypes` + MODIFY `issue_type_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `login_logs` +-- +ALTER TABLE `login_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=345; + +-- +-- 테이블의 AUTO_INCREMENT `password_change_logs` +-- +ALTER TABLE `password_change_logs` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `PipeSpecs` +-- +ALTER TABLE `PipeSpecs` + MODIFY `spec_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=3; + +-- +-- 테이블의 AUTO_INCREMENT `Processes` +-- +ALTER TABLE `Processes` + MODIFY `process_id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `Projects` +-- +ALTER TABLE `Projects` + MODIFY `project_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=15; + +-- +-- 테이블의 AUTO_INCREMENT `Tasks` +-- +ALTER TABLE `Tasks` + MODIFY `task_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=19; + +-- +-- 테이블의 AUTO_INCREMENT `uploaded_documents` +-- +ALTER TABLE `uploaded_documents` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `Users` +-- +ALTER TABLE `Users` + MODIFY `user_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=7; + +-- +-- 테이블의 AUTO_INCREMENT `Workers` +-- +ALTER TABLE `Workers` + MODIFY `worker_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=12; + +-- +-- 테이블의 AUTO_INCREMENT `worker_groups` +-- +ALTER TABLE `worker_groups` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; + +-- +-- 테이블의 AUTO_INCREMENT `WorkReports` +-- +ALTER TABLE `WorkReports` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=1766; + +-- +-- 테이블의 AUTO_INCREMENT `work_report_audit_log` +-- +ALTER TABLE `work_report_audit_log` + MODIFY `log_id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=880; + +-- +-- 테이블의 AUTO_INCREMENT `work_status_types` +-- +ALTER TABLE `work_status_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; + +-- +-- 테이블의 AUTO_INCREMENT `work_types` +-- +ALTER TABLE `work_types` + MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=11; + +-- +-- 덤프된 테이블의 제약사항 +-- + +-- +-- 테이블의 제약사항 `activity_logs` +-- +ALTER TABLE `activity_logs` + ADD CONSTRAINT `activity_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE SET NULL; + +-- +-- 테이블의 제약사항 `CuttingPlan` +-- +ALTER TABLE `CuttingPlan` + ADD CONSTRAINT `CuttingPlan_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`), + ADD CONSTRAINT `fk_cuttingplan_spec` FOREIGN KEY (`spec_id`) REFERENCES `PipeSpecs` (`spec_id`); + +-- +-- 테이블의 제약사항 `DailyIssueReports` +-- +ALTER TABLE `DailyIssueReports` + ADD CONSTRAINT `dailyissuereports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`), + ADD CONSTRAINT `fk_dird_issuetype` FOREIGN KEY (`issue_type_id`) REFERENCES `IssueTypes` (`issue_type_id`), + ADD CONSTRAINT `fk_dird_project` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`); + +-- +-- 테이블의 제약사항 `EquipmentList` +-- +ALTER TABLE `EquipmentList` + ADD CONSTRAINT `EquipmentList_ibfk_1` FOREIGN KEY (`factory_id`) REFERENCES `FactoryInfo` (`factory_id`); + +-- +-- 테이블의 제약사항 `login_logs` +-- +ALTER TABLE `login_logs` + ADD CONSTRAINT `login_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE; + +-- +-- 테이블의 제약사항 `password_change_logs` +-- +ALTER TABLE `password_change_logs` + ADD CONSTRAINT `password_change_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `password_change_logs_ibfk_2` FOREIGN KEY (`changed_by_user_id`) REFERENCES `Users` (`user_id`) ON DELETE SET NULL; + +-- +-- 테이블의 제약사항 `Processes` +-- +ALTER TABLE `Processes` + ADD CONSTRAINT `Processes_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`); + +-- +-- 테이블의 제약사항 `Users` +-- +ALTER TABLE `Users` + ADD CONSTRAINT `fk_worker` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`); + +-- +-- 테이블의 제약사항 `worker_groups` +-- +ALTER TABLE `worker_groups` + ADD CONSTRAINT `fk_group_leader` FOREIGN KEY (`group_leader_id`) REFERENCES `Users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `fk_group_worker` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`) ON DELETE CASCADE; + +-- +-- 테이블의 제약사항 `WorkReports` +-- +ALTER TABLE `WorkReports` + ADD CONSTRAINT `WorkReports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `Workers` (`worker_id`), + ADD CONSTRAINT `WorkReports_ibfk_2` FOREIGN KEY (`project_id`) REFERENCES `Projects` (`project_id`), + ADD CONSTRAINT `WorkReports_ibfk_3` FOREIGN KEY (`morning_task_id`) REFERENCES `Tasks` (`task_id`), + ADD CONSTRAINT `WorkReports_ibfk_4` FOREIGN KEY (`afternoon_task_id`) REFERENCES `Tasks` (`task_id`), + ADD CONSTRAINT `WorkReports_ibfk_5` FOREIGN KEY (`overtime_task_id`) REFERENCES `Tasks` (`task_id`); +COMMIT; + +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/002_add_master_tables.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/002_add_master_tables.sql new file mode 100644 index 0000000..8158b2b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/002_add_master_tables.sql @@ -0,0 +1,115 @@ +-- migrations/002_add_master_tables.sql +-- 기존 daily_work_reports 테이블을 유지하면서 필요한 마스터 테이블들만 추가 + +-- 1. 작업 유형 테이블 생성 +CREATE TABLE IF NOT EXISTS work_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL COMMENT '작업 유형명', + description TEXT COMMENT '작업 유형 설명', + category VARCHAR(50) COMMENT '작업 카테고리', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 2. 업무 상태 유형 테이블 생성 +CREATE TABLE IF NOT EXISTS work_status_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(50) NOT NULL COMMENT '상태명', + description TEXT COMMENT '상태 설명', + is_error BOOLEAN DEFAULT FALSE COMMENT '에러 상태 여부', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 3. 에러 유형 테이블 생성 +CREATE TABLE IF NOT EXISTS error_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + name VARCHAR(100) NOT NULL COMMENT '에러 유형명', + description TEXT COMMENT '에러 설명', + severity ENUM('low', 'medium', 'high', 'critical') DEFAULT 'medium' COMMENT '심각도', + solution_guide TEXT COMMENT '해결 가이드', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 4. 감사 로그 테이블 생성 (누적입력 추적용) +CREATE TABLE IF NOT EXISTS work_report_audit_log ( + log_id INT PRIMARY KEY AUTO_INCREMENT, + action ENUM('ADD_ACCUMULATE', 'DELETE_SINGLE', 'UPDATE', 'DELETE', 'CREATE', 'DELETE_BATCH') NOT NULL COMMENT '작업 유형', + report_id INT NULL COMMENT '관련 보고서 ID', + old_values JSON NULL COMMENT '변경 전 값', + new_values JSON NULL COMMENT '변경 후 값', + changed_by INT NOT NULL COMMENT '변경자 ID', + change_reason VARCHAR(500) COMMENT '변경 사유', + ip_address VARCHAR(45) COMMENT 'IP 주소', + user_agent TEXT COMMENT '사용자 에이전트', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '변경 시간', + + INDEX idx_action_date (action, created_at), + INDEX idx_changed_by (changed_by), + INDEX idx_report_id (report_id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 5. 기존 daily_work_reports 테이블에 누적입력을 위한 인덱스만 추가 +ALTER TABLE daily_work_reports +ADD INDEX IF NOT EXISTS idx_created_by (created_by), +ADD INDEX IF NOT EXISTS idx_date_worker_creator (report_date, worker_id, created_by); + +-- 6. 기본 데이터 삽입 (기존 데이터와 호환되도록) + +-- 업무 상태 유형 기본 데이터 +INSERT IGNORE INTO work_status_types (id, name, description, is_error) VALUES +(1, '정규', '정상적으로 완료된 작업', FALSE), +(2, '에러', '오류가 발생한 작업', TRUE); + +-- 작업 유형 기본 데이터 (기존 데이터의 work_type_id=1과 호환) +INSERT IGNORE INTO work_types (id, name, description, category) VALUES +(1, '일반작업', '기본 작업 유형', '생산관리'), +(2, '생산', '제품 생산 작업', '생산관리'), +(3, '품질검사', '제품 품질 검사', '품질관리'), +(4, '안전점검', '안전 상태 점검', '안전관리'), +(5, '자재입고', '원자재 입고 작업', '구매관리'), +(6, '설비점검', '생산 설비 점검', '설비관리'), +(7, '재고관리', '재고 현황 관리', '창고관리'), +(8, '포장', '제품 포장 작업', '생산관리'), +(9, '출하', '제품 출하 작업', '물류관리'); + +-- 에러 유형 기본 데이터 +INSERT IGNORE INTO error_types (id, name, description, severity, solution_guide) VALUES +(1, '설비고장', '생산 설비 고장', 'high', '즉시 설비팀에 연락하여 수리 요청'), +(2, '자재부족', '필요 자재 부족', 'medium', '구매팀에 긴급 주문 요청'), +(3, '품질불량', '제품 품질 기준 미달', 'high', '품질팀에 즉시 보고 및 생산 중단'), +(4, '안전사고', '작업 중 안전사고 발생', 'critical', '즉시 작업 중단 및 안전팀 신고'), +(5, '시스템오류', 'IT 시스템 오류', 'medium', 'IT팀에 장애 신고'); + +-- 7. 기존 데이터 호환성을 위한 뷰 생성 +CREATE OR REPLACE VIEW v_daily_reports_with_names AS +SELECT + dwr.id, + dwr.report_date, + dwr.worker_id, + w.worker_name, + dwr.project_id, + p.project_name, + dwr.work_type_id, + COALESCE(wt.name, '일반작업') as work_type_name, + COALESCE(wt.category, '생산관리') as work_category, + dwr.work_status_id, + COALESCE(wst.name, '정규') as work_status_name, + COALESCE(wst.is_error, FALSE) as is_error, + dwr.error_type_id, + et.name as error_type_name, + et.severity as error_severity, + dwr.work_hours, + dwr.created_by, + u.name as created_by_name, + dwr.created_at, + dwr.updated_at +FROM daily_work_reports dwr +LEFT JOIN Workers w ON dwr.worker_id = w.worker_id +LEFT JOIN Projects p ON dwr.project_id = p.project_id +LEFT JOIN work_types wt ON dwr.work_type_id = wt.id +LEFT JOIN work_status_types wst ON dwr.work_status_id = wst.id +LEFT JOIN error_types et ON dwr.error_type_id = et.id +LEFT JOIN Users u ON dwr.created_by = u.user_id; + +COMMIT; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/003_normalize_table_names.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/003_normalize_table_names.sql new file mode 100644 index 0000000..89bbcf1 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/003_normalize_table_names.sql @@ -0,0 +1,56 @@ +-- migrations/003_normalize_table_names.sql +-- 모든 테이블명을 snake_case로 변경하여 룰 준수 + +-- 기존 PascalCase 테이블들을 snake_case로 변경 + +-- 1. Users -> users +RENAME TABLE Users TO users; + +-- 2. CuttingPlan -> cutting_plan +RENAME TABLE CuttingPlan TO cutting_plan; + +-- 3. DailyIssueReports -> daily_issue_reports +RENAME TABLE DailyIssueReports TO daily_issue_reports; + +-- 4. EquipmentList -> equipment_list +RENAME TABLE EquipmentList TO equipment_list; + +-- 5. FactoryInfo -> factory_info +RENAME TABLE FactoryInfo TO factory_info; + +-- 6. IssueTypes -> issue_types +RENAME TABLE IssueTypes TO issue_types; + +-- 7. PipeSpecs -> pipe_specs +RENAME TABLE PipeSpecs TO pipe_specs; + +-- 8. Processes -> processes (이미 소문자이지만 통일성 위해) +-- RENAME TABLE Processes TO processes; -- 이미 소문자면 스킵 + +-- 9. Projects -> projects +RENAME TABLE Projects TO projects; + +-- 10. Tasks -> tasks +RENAME TABLE Tasks TO tasks; + +-- 11. WorkReports -> work_reports +RENAME TABLE WorkReports TO work_reports; + +-- 12. Workers -> workers +RENAME TABLE Workers TO workers; + +-- 이미 snake_case인 테이블들은 그대로 유지: +-- activity_logs +-- daily_work_reports +-- daily_worker_summary +-- error_types +-- login_logs +-- password_change_logs +-- uploaded_documents +-- work_report_audit_log +-- work_status_types +-- work_types +-- worker_groups + +-- 변경 완료 로그 +SELECT 'Table names normalized to snake_case according to project rules' as migration_status; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/01_schema.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/01_schema.sql new file mode 100644 index 0000000..e69de29 diff --git a/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/update_hyungi_system_role.sql b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/update_hyungi_system_role.sql new file mode 100644 index 0000000..a864eb9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/db_archive/migrations_backup/update_hyungi_system_role.sql @@ -0,0 +1,45 @@ +-- hyungi 계정을 시스템 권한으로 업데이트 +-- 실행 날짜: 2025-01-XX + +-- hyungi 계정의 role을 system으로 변경 +UPDATE Users +SET + role = 'system', + access_level = 'system', + name = '시스템 관리자', + updated_at = NOW() +WHERE username = 'hyungi'; + +-- 변경 결과 확인 +SELECT + user_id, + username, + name, + role, + access_level, + is_active, + updated_at +FROM Users +WHERE username = 'hyungi'; + +-- 시스템 권한 확인을 위한 쿼리 +SELECT + username, + name, + role, + access_level, + CASE + WHEN role = 'system' THEN '✅ 시스템 관리자' + WHEN role = 'admin' THEN '🔧 관리자' + WHEN role = 'leader' THEN '👨‍🏫 그룹장' + ELSE '👤 일반 사용자' + END as permission_level +FROM Users +ORDER BY + CASE role + WHEN 'system' THEN 1 + WHEN 'admin' THEN 2 + WHEN 'leader' THEN 3 + ELSE 4 + END, + username; diff --git a/deploy/tkfb-package/api.hyungi.net/deploy.sh b/deploy/tkfb-package/api.hyungi.net/deploy.sh new file mode 100755 index 0000000..5983d8e --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/deploy.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# 색상 정의 +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +NC='\033[0m' # No Color + +echo -e "${BLUE}========================================${NC}" +echo -e "${BLUE} API 서버 배포 스크립트${NC}" +echo -e "${BLUE}========================================${NC}" +echo "" + +# 현재 디렉토리 확인 +if [ ! -f "package.json" ]; then + echo -e "${RED}❌ 오류: package.json을 찾을 수 없습니다.${NC}" + echo -e "${RED} api.hyungi.net 디렉토리에서 실행해주세요.${NC}" + exit 1 +fi + +echo -e "${BLUE}📂 현재 디렉토리:${NC} $(pwd)" +echo "" + +# 1. Git Pull +echo -e "${YELLOW}1️⃣ Git Pull 시작...${NC}" +git pull +if [ $? -ne 0 ]; then + echo -e "${RED}❌ Git Pull 실패${NC}" + exit 1 +fi +echo -e "${GREEN}✅ Git Pull 완료${NC}" +echo "" + +# 2. NPM Install (package.json 변경 확인) +echo -e "${YELLOW}2️⃣ 의존성 확인 중...${NC}" +if git diff HEAD@{1} HEAD --name-only | grep -q "package.json"; then + echo -e "${YELLOW}📦 package.json 변경 감지 - npm install 실행${NC}" + npm install + if [ $? -ne 0 ]; then + echo -e "${RED}❌ npm install 실패${NC}" + exit 1 + fi + echo -e "${GREEN}✅ npm install 완료${NC}" +else + echo -e "${GREEN}✅ package.json 변경 없음 - 건너뜀${NC}" +fi +echo "" + +# 3. 데이터베이스 마이그레이션 +echo -e "${YELLOW}3️⃣ 데이터베이스 마이그레이션 시작...${NC}" +echo -e "${YELLOW}⚠️ 주의: 마이그레이션 전 데이터베이스 백업을 권장합니다.${NC}" +echo "" +read -p "마이그레이션을 실행하시겠습니까? (y/n): " -n 1 -r +echo +if [[ $REPLY =~ ^[Yy]$ ]]; then + npm run db:migrate + if [ $? -ne 0 ]; then + echo -e "${RED}❌ 마이그레이션 실패${NC}" + echo -e "${YELLOW}💡 롤백이 필요하면 다음 명령어를 실행하세요:${NC}" + echo -e "${YELLOW} npm run db:rollback${NC}" + exit 1 + fi + echo -e "${GREEN}✅ 마이그레이션 완료${NC}" +else + echo -e "${YELLOW}⏭️ 마이그레이션 건너뜀${NC}" +fi +echo "" + +# 4. PM2 재시작 +echo -e "${YELLOW}4️⃣ PM2 서버 재시작...${NC}" +if command -v pm2 &> /dev/null; then + pm2 reload ecosystem.config.js --env production + if [ $? -ne 0 ]; then + echo -e "${RED}❌ PM2 reload 실패${NC}" + exit 1 + fi + echo -e "${GREEN}✅ PM2 reload 완료${NC}" + echo "" + + # PM2 상태 확인 + echo -e "${BLUE}📊 PM2 프로세스 상태:${NC}" + pm2 list +else + echo -e "${YELLOW}⚠️ PM2가 설치되지 않았습니다. 수동으로 서버를 재시작해주세요.${NC}" +fi +echo "" + +echo -e "${GREEN}========================================${NC}" +echo -e "${GREEN} ✅ 배포 완료!${NC}" +echo -e "${GREEN}========================================${NC}" +echo "" +echo -e "${BLUE}📝 배포 후 확인사항:${NC}" +echo -e " 1. API 서버 응답 확인: curl http://localhost:20005/health" +echo -e " 2. 로그 확인: pm2 logs hyungi-api" +echo -e " 3. 에러 발생 시: pm2 logs hyungi-api --err" +echo "" diff --git a/deploy/tkfb-package/api.hyungi.net/docker-compose.yml b/deploy/tkfb-package/api.hyungi.net/docker-compose.yml new file mode 100644 index 0000000..5c4cf6d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/docker-compose.yml @@ -0,0 +1,113 @@ +version: "3.8" + +services: + db: + image: mariadb:10.9 + container_name: db_hyungi_net + restart: unless-stopped + env_file: + - ./.env + environment: + - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD} + - MYSQL_DATABASE=${DB_NAME} + - MYSQL_USER=${DB_USER} + - MYSQL_PASSWORD=${DB_PASSWORD} + volumes: + - db_data:/var/lib/mysql + - ./migrations:/docker-entrypoint-initdb.d # SQL 마이그레이션 자동 실행 + ports: + - "20306:3306" # RULES.md 준수: DB 포트 20306 + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + timeout: 20s + retries: 10 + + api: + build: + context: . + dockerfile: Dockerfile + container_name: api_hyungi_net + depends_on: + db: + condition: service_healthy # DB가 준비된 후 시작 + redis: + condition: service_healthy # Redis가 준비된 후 시작 + restart: unless-stopped + ports: + - "20005:3005" # RULES.md 준수: API 포트 20005 + env_file: + - ./.env + environment: + - NODE_ENV=production + - REDIS_HOST=redis + - REDIS_PORT=6379 + volumes: + - ./public/img:/usr/src/app/public/img:ro + - ./uploads:/usr/src/app/uploads + - ./logs:/usr/src/app/logs # 로그 파일 저장 + - ./routes:/usr/src/app/routes + - ./controllers:/usr/src/app/controllers + - ./models:/usr/src/app/models + - ./index.js:/usr/src/app/index.js + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + + phpmyadmin: + image: phpmyadmin/phpmyadmin:latest + container_name: pma_hyungi_net + depends_on: + - db + restart: unless-stopped + ports: + - "20080:80" # RULES.md 준수: phpMyAdmin 포트 20080 + env_file: + - ./.env + environment: + - PMA_HOST=${DB_HOST:-db} + - PMA_USER=${DB_ROOT_USER:-root} + - PMA_PASSWORD=${DB_ROOT_PASSWORD} + - UPLOAD_LIMIT=50M + + # Redis 캐시 서버 (세션 관리 및 속도 제한용) + redis: + image: redis:7-alpine + container_name: redis_hyungi_net + restart: unless-stopped + ports: + - "20379:6379" # RULES.md 준수: Redis 포트 20379 + volumes: + - redis_data:/data + command: redis-server --appendonly yes + healthcheck: + test: ["CMD", "redis-cli", "ping"] + timeout: 3s + retries: 5 + networks: + - default + + # Nginx 리버스 프록시 (선택사항 - HTTPS 및 로드밸런싱용) + # nginx: + # image: nginx:alpine + # container_name: nginx_hyungi_net + # restart: unless-stopped + # ports: + # - "80:80" + # - "443:443" + # volumes: + # - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro + # - ./nginx/ssl:/etc/nginx/ssl:ro + # depends_on: + # - api + +volumes: + db_data: + driver: local + redis_data: + driver: local + +networks: + default: + name: hyungi_network \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/ecosystem.config.js b/deploy/tkfb-package/api.hyungi.net/ecosystem.config.js new file mode 100644 index 0000000..031b363 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/ecosystem.config.js @@ -0,0 +1,16 @@ +module.exports = { + apps: [ + { + name: 'hyungi-api', + script: './index.js', + env: { + NODE_ENV: 'development' + }, + env_production: { + NODE_ENV: 'production' + }, + // 메모리 200MB 이상일 때 자동 재시작 + max_memory_restart: '200M' + } + ] +} \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/hyungi_schema_v2.sql b/deploy/tkfb-package/api.hyungi.net/hyungi_schema_v2.sql new file mode 100644 index 0000000..d2ff224 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/hyungi_schema_v2.sql @@ -0,0 +1,297 @@ +-- Hyungi Technical Korea - Database Schema v2 +-- 개선 사항: +-- 1. 모든 테이블 및 컬럼 이름을 snake_case로 통일 +-- 2. 데이터 무결성 강화를 위한 외래 키(Foreign Key) 제약조건 추가 +-- 3. 유사/중복 테이블 통합 및 정리 제안 (예: tasks, work_types) +-- 4. 컬럼의 기본값(Default), 코멘트 등 명확화 + +SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO"; +START TRANSACTION; +SET time_zone = "+09:00"; + +-- ================================================================= +-- 1. 인증 및 사용자 관련 (Auth Domain) +-- ================================================================= + +-- 사용자 계정 정보 +CREATE TABLE `users` ( + `user_id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(100) NOT NULL, + `password` varchar(255) NOT NULL, + `name` varchar(50) DEFAULT NULL, + `email` varchar(255) DEFAULT NULL, + `role` varchar(30) DEFAULT 'user' COMMENT '역할 (system, admin, leader, user)', + `access_level` varchar(30) DEFAULT NULL COMMENT '접근 레벨 (레거시 필드, role로 통합 고려)', + `worker_id` int(11) DEFAULT NULL COMMENT '연결된 작업자 ID', + `is_active` tinyint(1) DEFAULT 1 COMMENT '계정 활성화 여부', + `last_login_at` datetime DEFAULT NULL COMMENT '마지막 로그인 시간', + `password_changed_at` datetime DEFAULT NULL, + `failed_login_attempts` int(11) DEFAULT 0, + `locked_until` datetime DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`user_id`), + UNIQUE KEY `username` (`username`), + KEY `fk_users_worker_id` (`worker_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 로그인 이력 +CREATE TABLE `login_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL, + `login_time` datetime DEFAULT current_timestamp(), + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `login_status` enum('success','failed','locked') DEFAULT 'success', + `failure_reason` varchar(100) DEFAULT NULL, + PRIMARY KEY (`log_id`), + KEY `fk_login_logs_user_id` (`user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 비밀번호 변경 이력 +CREATE TABLE `password_change_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `changed_by_user_id` int(11) DEFAULT NULL COMMENT '누가 변경했는지 (관리자)', + `changed_at` datetime DEFAULT current_timestamp(), + `change_type` enum('self','admin','reset','initial') DEFAULT 'self', + `ip_address` varchar(45) DEFAULT NULL, + PRIMARY KEY (`log_id`), + KEY `fk_pw_change_user_id` (`user_id`), + KEY `fk_pw_change_changed_by` (`changed_by_user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + +-- ================================================================= +-- 2. 기초 정보 (Master Data) +-- ================================================================= + +-- 프로젝트 정보 +CREATE TABLE `projects` ( + `project_id` int(11) NOT NULL AUTO_INCREMENT, + `job_no` varchar(50) NOT NULL, + `project_name` varchar(255) NOT NULL, + `contract_date` date DEFAULT NULL, + `due_date` date DEFAULT NULL, + `delivery_method` varchar(100) DEFAULT NULL, + `site` varchar(100) DEFAULT NULL, + `pm` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`project_id`), + UNIQUE KEY `job_no` (`job_no`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 작업자(인력) 정보 +CREATE TABLE `workers` ( + `worker_id` int(11) NOT NULL AUTO_INCREMENT, + `worker_name` varchar(100) NOT NULL, + `job_type` varchar(100) DEFAULT NULL COMMENT '직종', + `join_date` date DEFAULT NULL COMMENT '입사일', + `status` varchar(20) DEFAULT 'active' COMMENT '상태 (active, inactive)', + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`worker_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 작업자 그룹 (팀) +CREATE TABLE `worker_groups` ( + `group_id` int(11) NOT NULL AUTO_INCREMENT, + `group_name` varchar(100) DEFAULT NULL, + `group_leader_id` int(11) NOT NULL COMMENT '그룹장 user_id', + `worker_id` int(11) NOT NULL COMMENT '소속 작업자 worker_id', + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`group_id`), + KEY `fk_w_groups_leader_id` (`group_leader_id`), + KEY `fk_w_groups_worker_id` (`worker_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 표준 작업(공수) 종류 (기존 Tasks 와 work_types 통합 제안) +CREATE TABLE `tasks` ( + `task_id` int(11) NOT NULL AUTO_INCREMENT, + `task_category` varchar(255) NOT NULL COMMENT '작업 대분류 (예: PKG, Vessel)', + `task_subcategory` varchar(255) DEFAULT NULL COMMENT '작업 중분류 (예: Pipe Pre-Fabrication)', + `task_name` varchar(255) NOT NULL COMMENT '실제 작업명 (예: 취부&용접)', + `description` text DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`task_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 파이프 사양(Spec) 정보 +CREATE TABLE `pipe_specs` ( + `spec_id` int(11) NOT NULL AUTO_INCREMENT, + `material` varchar(50) NOT NULL COMMENT '재질 (예: SS400, STS304)', + `diameter_in` varchar(10) NOT NULL COMMENT '직경 (inch, 예: 2")', + `schedule` varchar(50) NOT NULL COMMENT '스케줄 (예: STD, SCH10, SCH40)', + PRIMARY KEY (`spec_id`), + UNIQUE KEY `uk_pipe_specs` (`material`,`diameter_in`,`schedule`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- 공장 설비/장비 목록 +CREATE TABLE `equipment_list` ( + `equipment_id` int(11) NOT NULL AUTO_INCREMENT, + `factory_id` int(11) DEFAULT NULL COMMENT '소속 공장 ID', + `equipment_name` varchar(255) NOT NULL, + `model` varchar(100) DEFAULT NULL, + `status` varchar(50) DEFAULT 'operational', + `purchase_date` date DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`equipment_id`), + KEY `fk_equip_factory_id` (`factory_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 공장 구역 정보 +CREATE TABLE `factory_info` ( + `factory_id` int(11) NOT NULL AUTO_INCREMENT, + `factory_name` varchar(255) NOT NULL, + `address` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `map_image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`factory_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 코드 정의 (기존 IssueTypes, error_types 등을 통합 관리) +CREATE TABLE `code_types` ( + `code_type_id` VARCHAR(50) NOT NULL COMMENT '코드 타입 ID (예: ISSUE_TYPE, ERROR_TYPE)', + `code_type_name` VARCHAR(100) NOT NULL COMMENT '코드 타입명 (예: 이슈 유형, 에러 유형)', + `description` TEXT, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`code_type_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +CREATE TABLE `codes` ( + `code_id` INT NOT NULL AUTO_INCREMENT, + `code_type_id` VARCHAR(50) NOT NULL COMMENT '참조하는 코드 타입 ID', + `code_value` VARCHAR(100) NOT NULL COMMENT '코드 값 (예: design_miss)', + `code_name` VARCHAR(100) NOT NULL COMMENT '코드 표시명 (예: 설계 미스)', + `code_order` INT DEFAULT 0 COMMENT '정렬 순서', + `is_active` TINYINT(1) DEFAULT 1, + `description` TEXT, + `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (`code_id`), + UNIQUE KEY `uk_code` (`code_type_id`, `code_value`), + KEY `fk_codes_code_type_id` (`code_type_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + + +-- ================================================================= +-- 3. 업무 데이터 (Transactional Data) +-- ================================================================= + +-- 일일 작업 보고 +CREATE TABLE `daily_work_reports` ( + `report_id` int(11) NOT NULL AUTO_INCREMENT, + `report_date` date NOT NULL COMMENT '작업 날짜', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `project_id` int(11) NOT NULL COMMENT '프로젝트 ID', + `task_id` int(11) NOT NULL COMMENT '작업 ID', + `work_hours` decimal(4,2) NOT NULL COMMENT '작업 시간', + `is_error` tinyint(1) NOT NULL DEFAULT 0 COMMENT '에러 여부 (0: 정상, 1: 에러)', + `error_type_code_id` int(11) DEFAULT NULL COMMENT '에러 유형 코드 ID (codes 테이블 참조)', + `created_by_user_id` int(11) NOT NULL COMMENT '작성자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`report_id`), + KEY `fk_dwr_worker_id` (`worker_id`), + KEY `fk_dwr_project_id` (`project_id`), + KEY `fk_dwr_task_id` (`task_id`), + KEY `fk_dwr_error_type` (`error_type_code_id`), + KEY `fk_dwr_created_by` (`created_by_user_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- 일일 이슈 보고 +CREATE TABLE `daily_issue_reports` ( + `issue_report_id` int(11) NOT NULL AUTO_INCREMENT, + `report_date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `issue_type_code_id` int(11) DEFAULT NULL COMMENT '이슈 유형 코드 ID (codes 테이블 참조)', + `description` text DEFAULT NULL, + `start_time` time NOT NULL, + `end_time` time NOT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`issue_report_id`), + KEY `fk_dir_worker_id` (`worker_id`), + KEY `fk_dir_project_id` (`project_id`), + KEY `fk_dir_issue_type` (`issue_type_code_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; + +-- 절단 계획 +CREATE TABLE `cutting_plans` ( + `cutting_plan_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int(11) NOT NULL, + `spec_id` int(11) NOT NULL COMMENT '파이프 사양 ID', + `drawing_name` varchar(255) NOT NULL, + `area_number` varchar(100) DEFAULT NULL, + `spool_number` varchar(255) DEFAULT NULL, + `length` decimal(10,2) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`cutting_plan_id`), + KEY `fk_cp_project_id` (`project_id`), + KEY `fk_cp_spec_id` (`spec_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; + +-- ================================================================= +-- 외래 키(Foreign Key) 제약조건 설정 +-- ================================================================= + +-- Auth Domain +ALTER TABLE `users` + ADD CONSTRAINT `fk_users_worker_id` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE SET NULL; +ALTER TABLE `login_logs` + ADD CONSTRAINT `fk_login_logs_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL; +ALTER TABLE `password_change_logs` + ADD CONSTRAINT `fk_pw_change_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `fk_pw_change_changed_by` FOREIGN KEY (`changed_by_user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL; + +-- Master Data +ALTER TABLE `worker_groups` + ADD CONSTRAINT `fk_w_groups_leader_id` FOREIGN KEY (`group_leader_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE, + ADD CONSTRAINT `fk_w_groups_worker_id` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE; +ALTER TABLE `equipment_list` + ADD CONSTRAINT `fk_equip_factory_id` FOREIGN KEY (`factory_id`) REFERENCES `factory_info` (`factory_id`) ON DELETE SET NULL; +ALTER TABLE `codes` + ADD CONSTRAINT `fk_codes_code_type_id` FOREIGN KEY (`code_type_id`) REFERENCES `code_types` (`code_type_id`) ON DELETE CASCADE; + +-- Transactional Data +ALTER TABLE `daily_work_reports` + ADD CONSTRAINT `fk_dwr_worker_id` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE RESTRICT, + ADD CONSTRAINT `fk_dwr_project_id` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE RESTRICT, + ADD CONSTRAINT `fk_dwr_task_id` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`task_id`) ON DELETE RESTRICT, + ADD CONSTRAINT `fk_dwr_error_type` FOREIGN KEY (`error_type_code_id`) REFERENCES `codes` (`code_id`) ON DELETE SET NULL, + ADD CONSTRAINT `fk_dwr_created_by` FOREIGN KEY (`created_by_user_id`) REFERENCES `users` (`user_id`) ON DELETE RESTRICT; +ALTER TABLE `daily_issue_reports` + ADD CONSTRAINT `fk_dir_worker_id` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE RESTRICT, + ADD CONSTRAINT `fk_dir_project_id` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE RESTRICT, + ADD CONSTRAINT `fk_dir_issue_type` FOREIGN KEY (`issue_type_code_id`) REFERENCES `codes` (`code_id`) ON DELETE SET NULL; +ALTER TABLE `cutting_plans` + ADD CONSTRAINT `fk_cp_project_id` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE CASCADE, + ADD CONSTRAINT `fk_cp_spec_id` FOREIGN KEY (`spec_id`) REFERENCES `pipe_specs` (`spec_id`) ON DELETE RESTRICT; + + +COMMIT; + +-- ================================================================= +-- 기존 테이블 (Legacy) - 검토 후 마이그레이션 및 삭제 필요 +-- ================================================================= +/* +-- 기존 Tasks, IssueTypes, error_types 등은 `codes` 와 `code_types`로 통합 제안 +-- 아래 테이블들은 `codes` 테이블로 데이터 마이그레이션 후 삭제 고려 +CREATE TABLE `IssueTypes` ( ... ); +CREATE TABLE `error_types` ( ... ); +CREATE TABLE `work_status_types` ( ... ); +CREATE TABLE `work_types` ( ... ); + +-- daily_work_reports 로 통합된 것으로 추정되는 레거시 테이블 +CREATE TABLE `WorkReports` ( ... ); +CREATE TABLE `daily_worker_summary` ( ... ); +*/ \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/index.js b/deploy/tkfb-package/api.hyungi.net/index.js new file mode 100644 index 0000000..fded5b8 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/index.js @@ -0,0 +1,344 @@ +/** + * TK-FB-Project API Server + * + * 작업 관리 시스템의 메인 서버 애플리케이션 + * + * @author TK-FB-Project + * @since 2025-12-11 + * @version 2.2.0 + */ + +require('dotenv').config(); +const express = require('express'); +const setupMiddlewares = require('./config/middleware'); +const setupRoutes = require('./config/routes'); +const { errorHandler } = require('./middlewares/errorHandler'); +const logger = require('./utils/logger'); +const cache = require('./utils/cache'); + +const app = express(); +const PORT = process.env.PORT || 20005; + +// Trust proxy for accurate IP addresses +app.set('trust proxy', 1); + +// JSON body parser 미리 적용 (마이그레이션용) +app.use(express.json()); + +// 임시 분석 테스트 엔드포인트 - 실행 후 삭제! +app.get('/api/test-analysis', async (req, res) => { + try { + const { getDb } = require('./dbPool'); + const db = await getDb(); + + // 수정된 COALESCE 로직 테스트 (tasks 우선) + const [results] = await db.query(` + SELECT + dwr.id, + w.worker_name, + dwr.report_date, + dwr.work_type_id as original_work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN t.work_type_id ELSE NULL END, + wt.id + ) as resolved_work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN wt2.name ELSE NULL END, + wt.name + ) as work_type_name, + t.task_name, + wt.name as direct_match_work_type, + wt2.name as task_work_type + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id + WHERE w.worker_name LIKE '%조승민%' OR w.worker_name LIKE '%최광욱%' + ORDER BY dwr.report_date DESC + LIMIT 20 + `); + + res.json({ + success: true, + message: 'tasks 테이블 우선 조회 결과', + data: results.map(r => ({ + id: r.id, + worker: r.worker_name, + date: r.report_date, + original_id: r.original_work_type_id, + resolved_work_type: r.work_type_name, + task: r.task_name, + note: `원래 ID ${r.original_work_type_id} → ${r.work_type_name}` + })) + }); + + } catch (error) { + console.error('테스트 실패:', error); + res.status(500).json({ success: false, error: error.message }); + } +}); + +// 임시 진단 엔드포인트 - 실행 후 삭제! +app.get('/api/diagnose-work-type-id', async (req, res) => { + try { + const { getDb } = require('./dbPool'); + const db = await getDb(); + + // 1. 전체 작업보고서 현황 + const [totalStats] = await db.query(` + SELECT + COUNT(*) as total_reports, + COUNT(tbm_assignment_id) as tbm_reports, + COUNT(CASE WHEN tbm_assignment_id IS NULL THEN 1 END) as non_tbm_reports + FROM daily_work_reports + `); + + // 2. work_type_id 값 분포 (상위 20개) + const [workTypeDistribution] = await db.query(` + SELECT + dwr.work_type_id, + COUNT(*) as count, + wt.name as if_work_type, + t.task_name as if_task, + wt2.name as task_work_type + FROM daily_work_reports dwr + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id + GROUP BY dwr.work_type_id + ORDER BY count DESC + LIMIT 20 + `); + + // 3. 특정 작업자 데이터 확인 (조승민, 최광욱) + const [workerSamples] = await db.query(` + SELECT + dwr.id, + w.worker_name, + dwr.work_type_id, + dwr.tbm_assignment_id, + wt.name as direct_work_type, + t.task_name, + wt2.name as task_work_type, + dwr.report_date + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id + WHERE w.worker_name LIKE '%조승민%' OR w.worker_name LIKE '%최광욱%' + ORDER BY dwr.report_date DESC + LIMIT 20 + `); + + res.json({ + success: true, + data: { + total_stats: totalStats[0], + work_type_distribution: workTypeDistribution, + worker_samples: workerSamples + } + }); + + } catch (error) { + console.error('진단 실패:', error); + res.status(500).json({ success: false, error: error.message }); + } +}); + +// 임시 마이그레이션 엔드포인트 (인증 없이 실행) - 실행 후 삭제! +app.post('/api/migrate-work-type-id', async (req, res) => { + try { + const { getDb } = require('./dbPool'); + const db = await getDb(); + + console.log('🔄 TBM 기반 작업보고서 work_type_id 수정 시작...'); + + // 1. 수정 대상 확인 + const [checkResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id as current_work_type_id, + ta.task_id as correct_task_id, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + INNER JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + ORDER BY dwr.report_date DESC + `); + + console.log('📊 수정 대상:', checkResult.length, '개 레코드'); + + if (checkResult.length === 0) { + return res.json({ + success: true, + message: '수정할 데이터가 없습니다.', + data: { affected_rows: 0 } + }); + } + + // 2. 업데이트 실행 + const [updateResult] = await db.query(` + UPDATE daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + SET dwr.work_type_id = ta.task_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + `); + + console.log('✅ 업데이트 완료:', updateResult.affectedRows, '개 레코드 수정됨'); + + // 3. 수정 후 확인 + const [samples] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id, + t.task_name, + wt.name as work_type_name, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + ORDER BY dwr.report_date DESC + LIMIT 10 + `); + + res.json({ + success: true, + message: updateResult.affectedRows + '개 레코드가 수정되었습니다.', + data: { + affected_rows: updateResult.affectedRows, + before_count: checkResult.length, + samples: samples.map(s => ({ + id: s.id, + worker: s.worker_name, + date: s.report_date, + task: s.task_name, + work_type: s.work_type_name + })) + } + }); + + } catch (error) { + console.error('마이그레이션 실패:', error); + res.status(500).json({ + success: false, + error: '마이그레이션 실패: ' + error.message + }); + } +}); + +// 미들웨어 설정 +setupMiddlewares(app); + +// 라우트 설정 +setupRoutes(app); + +// 에러 핸들러 (모든 라우트 이후에 위치) +app.use(errorHandler); + +// 404 핸들러 +app.use((req, res) => { + logger.warn('404 Not Found', { url: req.originalUrl, method: req.method }); + res.status(404).json({ + success: false, + error: '요청하신 경로를 찾을 수 없습니다', + path: req.originalUrl + }); +}); + +// 서버 시작 +const server = app.listen(PORT, () => { + logger.info(`서버 시작 완료`, { + port: PORT, + env: process.env.NODE_ENV || 'development', + nodeVersion: process.version + }); + console.log(`\n🚀 서버가 포트 ${PORT}에서 실행 중입니다.`); + console.log(`📚 API 문서: http://localhost:${PORT}/api-docs\n`); +}); + +// Graceful Shutdown +const gracefulShutdown = (signal) => { + logger.info(`${signal} 신호 수신 - 서버 종료 시작`); + console.log(`\n🛑 ${signal} 신호를 받았습니다. 서버를 종료합니다...`); + + server.close(async () => { + logger.info('HTTP 서버 종료 완료'); + console.log('✅ HTTP 서버가 정상적으로 종료되었습니다.'); + + // 리소스 정리 + try { + // DB 연결 종료는 각 요청에서 pool을 사용하므로 불필요 + // Redis 종료 (사용 중인 경우) + if (cache.redis) { + await cache.redis.quit(); + logger.info('캐시 시스템 종료 완료'); + } + } catch (error) { + logger.error('리소스 정리 중 오류 발생', { error: error.message }); + } + + process.exit(0); + }); + + // 30초 후 강제 종료 + setTimeout(() => { + logger.error('강제 종료 - 정상 종료 시간 초과'); + console.error('❌ 정상 종료 실패, 강제 종료합니다.'); + process.exit(1); + }, 30000); +}; + +// 시그널 핸들러 등록 +process.on('SIGTERM', () => gracefulShutdown('SIGTERM')); +process.on('SIGINT', () => gracefulShutdown('SIGINT')); + +// 처리되지 않은 Promise 거부 +process.on('unhandledRejection', (reason, promise) => { + logger.error('처리되지 않은 Promise 거부', { + reason: reason, + promise: promise + }); + console.error('⚠️ 처리되지 않은 Promise 거부:', reason); + + if (process.env.NODE_ENV === 'development') { + process.exit(1); + } +}); + +// 처리되지 않은 예외 +process.on('uncaughtException', (error) => { + logger.error('처리되지 않은 예외', { + error: error.message, + stack: error.stack + }); + console.error('💥 처리되지 않은 예외:', error); + gracefulShutdown('UNCAUGHT_EXCEPTION'); +}); + +// 캐시 시스템 초기화 (선택적) +(async () => { + try { + if (cache.initRedis) { + await cache.initRedis(); + logger.info('캐시 시스템 초기화 완료'); + console.log('✅ 캐시 시스템 초기화 완료'); + } + } catch (error) { + logger.warn('캐시 시스템 초기화 실패 - 계속 진행', { error: error.message }); + console.warn('⚠️ 캐시 시스템 초기화 실패:', error.message); + } +})(); + +module.exports = app; diff --git a/deploy/tkfb-package/api.hyungi.net/jest.config.js b/deploy/tkfb-package/api.hyungi.net/jest.config.js new file mode 100644 index 0000000..89a2a5c --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/jest.config.js @@ -0,0 +1,91 @@ +/** + * Jest 설정 파일 + * + * TK-FB-Project 테스트 환경 설정 + */ + +module.exports = { + // Node.js 환경에서 테스트 실행 + testEnvironment: 'node', + + // 커버리지 리포트 저장 디렉토리 + coverageDirectory: 'coverage', + + // 커버리지 수집 대상 파일 + collectCoverageFrom: [ + 'controllers/**/*.js', + 'services/**/*.js', + 'models/**/*.js', + 'middlewares/**/*.js', + 'utils/**/*.js', + '!**/node_modules/**', + '!**/coverage/**', + '!**/tests/**', + '!index.js' // 서버 시작 파일 제외 + ], + + // 테스트 파일 패턴 + testMatch: [ + '**/tests/**/*.test.js', + '**/tests/**/*.spec.js' + ], + + // 테스트 실행 전 설정 파일 + setupFilesAfterEnv: ['/tests/setup.js'], + + // 상세 출력 모드 + verbose: true, + + // 커버리지 수집 활성화 + collectCoverage: false, // 기본은 false, npm run test:coverage에서만 true + + // 커버리지 리포트 형식 + coverageReporters: ['text', 'lcov', 'html', 'json-summary'], + + // 커버리지 임계값 (이 값 이하면 테스트 실패) + coverageThreshold: { + global: { + branches: 50, + functions: 50, + lines: 50, + statements: 50 + } + }, + + // 테스트 타임아웃 (밀리초) + testTimeout: 10000, + + // 모듈 경로 매핑 (선택사항) + moduleNameMapper: { + '^@/(.*)$': '/$1', + '^@controllers/(.*)$': '/controllers/$1', + '^@services/(.*)$': '/services/$1', + '^@models/(.*)$': '/models/$1', + '^@utils/(.*)$': '/utils/$1', + '^@middlewares/(.*)$': '/middlewares/$1' + }, + + // 무시할 경로 + testPathIgnorePatterns: [ + '/node_modules/', + '/coverage/', + '/dist/' + ], + + // 병렬 테스트 실행 워커 수 (기본값: CPU 코어 수 - 1) + // maxWorkers: 4, + + // 실패한 테스트만 재실행 옵션 + // bail: 1, // 첫 번째 실패 시 중단 + + // 테스트 결과 리포터 + reporters: [ + 'default', + // ['jest-junit', { outputDirectory: 'coverage', outputName: 'junit.xml' }] + ], + + // 글로벌 설정 + globals: { + 'NODE_ENV': 'test' + } +}; diff --git a/deploy/tkfb-package/api.hyungi.net/knexfile.js b/deploy/tkfb-package/api.hyungi.net/knexfile.js new file mode 100644 index 0000000..09a7d08 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/knexfile.js @@ -0,0 +1,57 @@ +require('dotenv').config(); + +module.exports = { + development: { + client: 'mysql2', + connection: { + host: process.env.DB_HOST, + port: process.env.DB_PORT, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + socketPath: process.env.DB_SOCKET + }, + migrations: { + directory: './db/migrations' + }, + seeds: { + directory: './db/seeds' + } + }, + + staging: { + client: 'mysql2', + connection: { + host: process.env.DB_HOST, + port: process.env.DB_PORT, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + socketPath: process.env.DB_SOCKET + }, + migrations: { + directory: './db/migrations' + }, + seeds: { + directory: './db/seeds' + } + }, + + production: { + client: 'mysql2', + connection: { + host: process.env.DB_HOST, + port: process.env.DB_PORT, + user: process.env.DB_USER, + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME, + socketPath: process.env.DB_SOCKET + }, + migrations: { + directory: './db/migrations' + }, + seeds: { + directory: './db/seeds' + } + } +}; diff --git a/deploy/tkfb-package/api.hyungi.net/middlewares/access.js b/deploy/tkfb-package/api.hyungi.net/middlewares/access.js new file mode 100644 index 0000000..2e12395 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/middlewares/access.js @@ -0,0 +1,9 @@ +// utils/access.js +exports.requireAccess = (...allowed) => { + return (req, res, next) => { + if (!req.user || !allowed.includes(req.user.access_level)) { + return res.status(403).json({ error: '접근 권한이 없습니다' }); + } + next(); + }; +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/middlewares/accessMiddleware.js b/deploy/tkfb-package/api.hyungi.net/middlewares/accessMiddleware.js new file mode 100644 index 0000000..d774915 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/middlewares/accessMiddleware.js @@ -0,0 +1,29 @@ +/** + * @deprecated 이 파일은 하위 호환성을 위해 유지됩니다. + * 새로운 코드에서는 '../middlewares/auth'의 requireMinLevel을 사용하세요. + * + * @example + * // 이전 방식 (deprecated) + * const { requireAccess, ACCESS_LEVELS } = require('../middlewares/accessMiddleware'); + * router.get('/admin', requireAccess('admin'), handler); + * + * // 새로운 방식 (권장) + * const { requireMinLevel, ACCESS_LEVELS } = require('../middlewares/auth'); + * router.get('/admin', requireAuth, requireMinLevel('admin'), handler); + */ + +const { requireMinLevel, ACCESS_LEVELS } = require('./auth'); + +/** + * @deprecated requireMinLevel을 사용하세요 + */ +const requireAccess = (requiredLevel) => { + return requireMinLevel(requiredLevel); +}; + +module.exports = { + requireAccess, + ACCESS_LEVELS, + // 새로운 API + requireMinLevel +}; diff --git a/deploy/tkfb-package/api.hyungi.net/middlewares/activityLogger.js b/deploy/tkfb-package/api.hyungi.net/middlewares/activityLogger.js new file mode 100644 index 0000000..7008cbd --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/middlewares/activityLogger.js @@ -0,0 +1,71 @@ +/** + * 활동 로깅 미들웨어 + * + * HTTP 요청/응답 활동을 기록하는 미들웨어 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const logger = require('../utils/logger'); + +/** + * 활동 로거 미들웨어 + * 모든 HTTP 요청의 시작과 완료를 기록 + */ +const activityLogger = (req, res, next) => { + const start = Date.now(); + + // 응답 완료 시 로깅 + res.on('finish', () => { + const duration = Date.now() - start; + const username = req.user?.username || 'anonymous'; + + const logData = { + method: req.method, + url: req.originalUrl, + statusCode: res.statusCode, + duration: `${duration}ms`, + ip: req.ip, + user: username, + userAgent: req.get('User-Agent') + }; + + // 상태 코드에 따른 로그 레벨 분기 + if (res.statusCode >= 500) { + logger.error('HTTP Request - Server Error', logData); + } else if (res.statusCode >= 400) { + logger.warn('HTTP Request - Client Error', logData); + } else if (res.statusCode >= 300) { + logger.info('HTTP Request - Redirect', logData); + } else { + logger.info('HTTP Request - Success', logData); + } + }); + + next(); +}; + +/** + * 민감한 경로 필터 미들웨어 + * 로그에서 민감한 정보를 제외 + */ +const sensitivePathFilter = (req, res, next) => { + const sensitivePaths = [ + '/api/auth/login', + '/api/auth/refresh-token', + '/api/users/password' + ]; + + // 민감한 경로의 경우 바디 로깅 스킵 + if (sensitivePaths.some(path => req.originalUrl.includes(path))) { + req.skipBodyLog = true; + } + + next(); +}; + +module.exports = { + activityLogger, + sensitivePathFilter +}; diff --git a/deploy/tkfb-package/api.hyungi.net/middlewares/auth.js b/deploy/tkfb-package/api.hyungi.net/middlewares/auth.js new file mode 100644 index 0000000..e956724 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/middlewares/auth.js @@ -0,0 +1,357 @@ +/** + * 통합 인증/인가 미들웨어 + * + * JWT 토큰 검증 및 권한 체크를 위한 미들웨어 모음 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const jwt = require('jsonwebtoken'); +const { AuthenticationError, ForbiddenError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 권한 레벨 계층 구조 + * 숫자가 높을수록 상위 권한 + */ +const ACCESS_LEVELS = { + worker: 1, + group_leader: 2, + support_team: 3, + admin: 4, + system: 5 +}; + +/** + * JWT 토큰 검증 미들웨어 + * + * Authorization 헤더에서 Bearer 토큰을 추출하고 검증합니다. + * 검증 성공 시 req.user에 디코딩된 사용자 정보를 저장합니다. + * + * @throws {AuthenticationError} 토큰이 없거나 유효하지 않을 때 + * + * @example + * router.get('/profile', requireAuth, getProfile); + */ +const requireAuth = (req, res, next) => { + try { + const authHeader = req.headers['authorization']; + + if (!authHeader) { + logger.warn('인증 실패: Authorization 헤더 없음', { + path: req.path, + method: req.method, + ip: req.ip + }); + throw new AuthenticationError('Authorization 헤더가 필요합니다'); + } + + const token = authHeader.split(' ')[1]; + + if (!token) { + logger.warn('인증 실패: Bearer 토큰 누락', { + path: req.path, + method: req.method, + ip: req.ip + }); + throw new AuthenticationError('Bearer 토큰이 필요합니다'); + } + + // JWT 검증 + const decoded = jwt.verify(token, process.env.JWT_SECRET); + req.user = decoded; + + logger.debug('인증 성공', { + user_id: decoded.user_id || decoded.id, + username: decoded.username, + role: decoded.role, + access_level: decoded.access_level + }); + + next(); + } catch (err) { + if (err.name === 'JsonWebTokenError') { + logger.warn('인증 실패: 유효하지 않은 토큰', { + error: err.message, + path: req.path, + ip: req.ip + }); + throw new AuthenticationError('유효하지 않은 토큰입니다'); + } else if (err.name === 'TokenExpiredError') { + logger.warn('인증 실패: 만료된 토큰', { + error: err.message, + path: req.path, + ip: req.ip + }); + throw new AuthenticationError('토큰이 만료되었습니다'); + } else if (err instanceof AuthenticationError) { + // 이미 AuthenticationError인 경우 그대로 throw + throw err; + } else { + logger.error('인증 처리 중 예상치 못한 오류', { + error: err.message, + stack: err.stack + }); + throw new AuthenticationError('인증 처리 중 오류가 발생했습니다'); + } + } +}; + +/** + * 특정 역할(들) 권한 체크 미들웨어 + * + * 사용자가 지정된 역할 중 하나를 가지고 있는지 확인합니다. + * requireAuth 미들웨어가 먼저 실행되어야 합니다. + * + * @param {...string} roles - 허용할 역할 목록 + * @returns {Function} Express 미들웨어 함수 + * @throws {AuthenticationError} 인증되지 않은 경우 + * @throws {ForbiddenError} 권한이 없는 경우 + * + * @example + * // 단일 역할 + * router.post('/admin/users', requireAuth, requireRole('admin'), createUser); + * + * // 여러 역할 + * router.get('/reports', requireAuth, requireRole('admin', 'support_team'), getReports); + */ +const requireRole = (...roles) => { + return (req, res, next) => { + try { + if (!req.user) { + logger.warn('권한 체크 실패: 인증되지 않은 요청', { + path: req.path, + method: req.method, + ip: req.ip + }); + throw new AuthenticationError('인증이 필요합니다'); + } + + const userRole = req.user.role; + const userRoleLower = userRole ? userRole.toLowerCase() : ''; + const rolesLower = roles.map(r => r.toLowerCase()); + + if (!rolesLower.includes(userRoleLower)) { + logger.warn('권한 체크 실패: 역할 불일치', { + user_id: req.user.user_id || req.user.id, + username: req.user.username, + current_role: userRole, + required_roles: roles, + path: req.path + }); + throw new ForbiddenError( + `이 기능을 사용하려면 ${roles.join(' 또는 ')} 권한이 필요합니다` + ); + } + + logger.debug('역할 권한 확인 성공', { + user_id: req.user.user_id || req.user.id, + username: req.user.username, + role: userRole, + required_roles: roles + }); + + next(); + } catch (err) { + next(err); + } + }; +}; + +/** + * 최소 권한 레벨 체크 미들웨어 (계층적) + * + * 사용자가 요구되는 최소 권한 레벨 이상인지 확인합니다. + * worker(1) < group_leader(2) < support_team(3) < admin(4) < system(5) + * requireAuth 미들웨어가 먼저 실행되어야 합니다. + * + * @param {string} minLevel - 최소 권한 레벨 (worker, group_leader, support_team, admin, system) + * @returns {Function} Express 미들웨어 함수 + * @throws {AuthenticationError} 인증되지 않은 경우 + * @throws {ForbiddenError} 권한이 부족한 경우 + * + * @example + * // admin 이상 필요 (admin, system만 허용) + * router.delete('/users/:id', requireAuth, requireMinLevel('admin'), deleteUser); + * + * // group_leader 이상 필요 (group_leader, support_team, admin, system 허용) + * router.get('/team-reports', requireAuth, requireMinLevel('group_leader'), getTeamReports); + */ +const requireMinLevel = (minLevel) => { + return (req, res, next) => { + try { + if (!req.user) { + logger.warn('권한 레벨 체크 실패: 인증되지 않은 요청', { + path: req.path, + method: req.method, + ip: req.ip + }); + throw new AuthenticationError('인증이 필요합니다'); + } + + const userLevel = ACCESS_LEVELS[req.user.access_level] || 0; + const requiredLevel = ACCESS_LEVELS[minLevel] || 999; + + if (userLevel < requiredLevel) { + logger.warn('권한 레벨 체크 실패: 권한 부족', { + user_id: req.user.user_id || req.user.id, + username: req.user.username, + current_level: req.user.access_level, + current_level_value: userLevel, + required_level: minLevel, + required_level_value: requiredLevel, + path: req.path + }); + throw new ForbiddenError( + `이 기능을 사용하려면 ${minLevel} 이상의 권한이 필요합니다 (현재: ${req.user.access_level})` + ); + } + + logger.debug('권한 레벨 확인 성공', { + user_id: req.user.user_id || req.user.id, + username: req.user.username, + access_level: req.user.access_level, + required_level: minLevel + }); + + next(); + } catch (err) { + next(err); + } + }; +}; + +/** + * 리소스 소유자 또는 관리자 권한 체크 미들웨어 + * + * 요청한 사용자가 리소스의 소유자이거나 관리자 권한이 있는지 확인합니다. + * requireAuth 미들웨어가 먼저 실행되어야 합니다. + * + * @param {Object} options - 옵션 객체 + * @param {string} options.resourceField - 리소스 ID를 가져올 req 필드 (예: 'params.user_id', 'body.worker_id') + * @param {string} options.userField - 사용자 ID 필드명 (기본값: 'user_id', 'id'도 자동 시도) + * @param {string[]} options.adminRoles - 관리자로 인정할 역할들 (기본값: ['admin', 'system']) + * @returns {Function} Express 미들웨어 함수 + * @throws {AuthenticationError} 인증되지 않은 경우 + * @throws {ForbiddenError} 소유자도 아니고 관리자도 아닌 경우 + * + * @example + * // URL 파라미터의 user_id로 체크 + * router.put('/users/:user_id', requireAuth, requireOwnerOrAdmin({ + * resourceField: 'params.user_id' + * }), updateUser); + * + * // 요청 body의 worker_id로 체크, support_team도 관리자로 인정 + * router.delete('/reports/:id', requireAuth, requireOwnerOrAdmin({ + * resourceField: 'body.worker_id', + * adminRoles: ['admin', 'system', 'support_team'] + * }), deleteReport); + */ +const requireOwnerOrAdmin = (options = {}) => { + const { + resourceField = 'params.id', + userField = 'user_id', + adminRoles = ['admin', 'system'] + } = options; + + return (req, res, next) => { + try { + if (!req.user) { + logger.warn('소유자/관리자 체크 실패: 인증되지 않은 요청', { + path: req.path, + method: req.method, + ip: req.ip + }); + throw new AuthenticationError('인증이 필요합니다'); + } + + // 관리자 권한 체크 + const userRole = req.user.role; + const isAdmin = adminRoles.includes(userRole); + + if (isAdmin) { + logger.debug('관리자 권한으로 접근 허용', { + user_id: req.user.user_id || req.user.id, + username: req.user.username, + role: userRole, + path: req.path + }); + return next(); + } + + // 리소스 ID 추출 + const fieldParts = resourceField.split('.'); + let resourceId = req; + for (const part of fieldParts) { + resourceId = resourceId[part]; + if (resourceId === undefined) break; + } + + // 사용자 ID (user_id 또는 id) + const userId = req.user[userField] || req.user.id || req.user.user_id; + + // 소유자 체크 + const isOwner = resourceId && String(resourceId) === String(userId); + + if (!isOwner) { + logger.warn('소유자/관리자 체크 실패: 권한 부족', { + user_id: userId, + username: req.user.username, + role: userRole, + resource_id: resourceId, + resource_field: resourceField, + is_admin: isAdmin, + is_owner: isOwner, + path: req.path + }); + throw new ForbiddenError('본인의 리소스이거나 관리자 권한이 필요합니다'); + } + + logger.debug('리소스 소유자로 접근 허용', { + user_id: userId, + username: req.user.username, + resource_id: resourceId, + path: req.path + }); + + next(); + } catch (err) { + next(err); + } + }; +}; + +/** + * 레거시 호환성을 위한 별칭 + * @deprecated requireAuth를 사용하세요 + */ +const verifyToken = requireAuth; + +/** + * 레거시 호환성을 위한 별칭 + * @deprecated requireRole('admin', 'system')을 사용하세요 + */ +const requireAdmin = requireRole('admin', 'system'); + +/** + * 레거시 호환성을 위한 별칭 + * @deprecated requireRole('system')을 사용하세요 + */ +const requireSystem = requireRole('system'); + +module.exports = { + // 주요 미들웨어 + requireAuth, + requireRole, + requireMinLevel, + requireOwnerOrAdmin, + + // 레거시 호환성 + verifyToken, + requireAdmin, + requireSystem, + + // 상수 + ACCESS_LEVELS +}; diff --git a/deploy/tkfb-package/api.hyungi.net/middlewares/authMiddleware.js b/deploy/tkfb-package/api.hyungi.net/middlewares/authMiddleware.js new file mode 100644 index 0000000..6fded28 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/middlewares/authMiddleware.js @@ -0,0 +1,36 @@ +/** + * @deprecated 이 파일은 하위 호환성을 위해 유지됩니다. + * 새로운 코드에서는 './auth'를 직접 import하세요. + * + * @example + * // 이전 방식 (deprecated) + * const { verifyToken, requireAdmin } = require('../middlewares/authMiddleware'); + * + * // 새로운 방식 (권장) + * const { requireAuth, requireRole } = require('../middlewares/auth'); + */ + +const { + requireAuth, + requireRole, + requireMinLevel, + requireOwnerOrAdmin, + verifyToken, + requireAdmin, + requireSystem, + ACCESS_LEVELS +} = require('./auth'); + +module.exports = { + // 레거시 별칭 (하위 호환성) + verifyToken, + requireAdmin, + requireSystem, + + // 새로운 API (권장) + requireAuth, + requireRole, + requireMinLevel, + requireOwnerOrAdmin, + ACCESS_LEVELS +}; diff --git a/deploy/tkfb-package/api.hyungi.net/middlewares/csrf.js b/deploy/tkfb-package/api.hyungi.net/middlewares/csrf.js new file mode 100644 index 0000000..ef2bca6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/middlewares/csrf.js @@ -0,0 +1,201 @@ +/** + * CSRF Protection Middleware + * + * Cross-Site Request Forgery 방지를 위한 토큰 기반 보호 + * + * 구현 방식: + * 1. 서버에서 CSRF 토큰 생성 및 응답 헤더로 전송 + * 2. 클라이언트는 state-changing 요청 시 토큰을 헤더에 포함 + * 3. 서버에서 토큰 검증 + * + * @author TK-FB-Project + * @since 2026-02-04 + */ + +const crypto = require('crypto'); +const logger = require('../utils/logger'); + +// 토큰 저장소 (프로덕션에서는 Redis 사용 권장) +const tokenStore = new Map(); + +// 토큰 유효 시간 (1시간) +const TOKEN_EXPIRY = 60 * 60 * 1000; + +// 토큰 정리 주기 (5분) +const CLEANUP_INTERVAL = 5 * 60 * 1000; + +/** + * 만료된 토큰 정리 + */ +const cleanupExpiredTokens = () => { + const now = Date.now(); + for (const [token, data] of tokenStore.entries()) { + if (now > data.expiresAt) { + tokenStore.delete(token); + } + } +}; + +// 주기적 정리 +setInterval(cleanupExpiredTokens, CLEANUP_INTERVAL); + +/** + * CSRF 토큰 생성 + * + * @param {string} sessionId - 세션 ID 또는 사용자 식별자 + * @returns {string} 생성된 CSRF 토큰 + */ +const generateToken = (sessionId) => { + const token = crypto.randomBytes(32).toString('hex'); + const expiresAt = Date.now() + TOKEN_EXPIRY; + + tokenStore.set(token, { + sessionId, + expiresAt, + createdAt: Date.now() + }); + + return token; +}; + +/** + * CSRF 토큰 검증 + * + * @param {string} token - 검증할 토큰 + * @param {string} sessionId - 세션 ID + * @returns {boolean} 유효 여부 + */ +const validateToken = (token, sessionId) => { + if (!token || !tokenStore.has(token)) { + return false; + } + + const data = tokenStore.get(token); + + // 만료 체크 + if (Date.now() > data.expiresAt) { + tokenStore.delete(token); + return false; + } + + // 세션 일치 체크 + if (data.sessionId !== sessionId) { + return false; + } + + return true; +}; + +/** + * CSRF 토큰을 응답 헤더에 설정하는 미들웨어 + * + * @param {Object} req - Express request + * @param {Object} res - Express response + * @param {Function} next - Next middleware + */ +const setCsrfToken = (req, res, next) => { + // 세션 ID 또는 사용자 ID 사용 + const sessionId = req.user?.user_id?.toString() || req.sessionID || req.ip; + + // 새 토큰 생성 + const token = generateToken(sessionId); + + // 응답 헤더에 토큰 설정 + res.setHeader('X-CSRF-Token', token); + + // 요청 객체에 저장 (다른 미들웨어에서 사용 가능) + req.csrfToken = token; + + next(); +}; + +/** + * CSRF 토큰 검증 미들웨어 + * POST, PUT, DELETE, PATCH 요청에 적용 + * + * @param {Object} options - 옵션 + * @param {string[]} options.ignoreMethods - 검증 제외 메서드 (기본: GET, HEAD, OPTIONS) + * @param {string[]} options.ignorePaths - 검증 제외 경로 (정규식 패턴 가능) + * @returns {Function} Express 미들웨어 + */ +const verifyCsrfToken = (options = {}) => { + const { + ignoreMethods = ['GET', 'HEAD', 'OPTIONS'], + ignorePaths = ['/api/auth/login', '/api/auth/register', '/api/health'] + } = options; + + return (req, res, next) => { + // 제외 메서드 체크 + if (ignoreMethods.includes(req.method)) { + return next(); + } + + // 제외 경로 체크 + for (const pattern of ignorePaths) { + if (typeof pattern === 'string' && req.path === pattern) { + return next(); + } + if (pattern instanceof RegExp && pattern.test(req.path)) { + return next(); + } + } + + // 토큰 추출 (헤더 또는 body에서) + const token = req.headers['x-csrf-token'] || + req.headers['csrf-token'] || + req.body?._csrf || + req.query?._csrf; + + // 세션 ID + const sessionId = req.user?.user_id?.toString() || req.sessionID || req.ip; + + // 토큰 검증 + if (!validateToken(token, sessionId)) { + logger.warn('CSRF 토큰 검증 실패', { + path: req.path, + method: req.method, + ip: req.ip, + hasToken: !!token + }); + + return res.status(403).json({ + success: false, + error: 'CSRF 토큰이 유효하지 않습니다. 페이지를 새로고침 후 다시 시도해주세요.', + code: 'CSRF_TOKEN_INVALID' + }); + } + + // 사용된 토큰 제거 (일회성 사용) + tokenStore.delete(token); + + // 새 토큰 발급 + const newToken = generateToken(sessionId); + res.setHeader('X-CSRF-Token', newToken); + req.csrfToken = newToken; + + next(); + }; +}; + +/** + * CSRF 토큰 발급 엔드포인트 핸들러 + * GET /api/csrf-token + */ +const getCsrfToken = (req, res) => { + const sessionId = req.user?.user_id?.toString() || req.sessionID || req.ip; + const token = generateToken(sessionId); + + res.json({ + success: true, + csrfToken: token, + expiresIn: TOKEN_EXPIRY / 1000 // 초 단위 + }); +}; + +module.exports = { + generateToken, + validateToken, + setCsrfToken, + verifyCsrfToken, + getCsrfToken +}; diff --git a/deploy/tkfb-package/api.hyungi.net/middlewares/errorHandler.js b/deploy/tkfb-package/api.hyungi.net/middlewares/errorHandler.js new file mode 100644 index 0000000..646926d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/middlewares/errorHandler.js @@ -0,0 +1,102 @@ +/** + * 에러 핸들러 미들웨어 + * + * 애플리케이션 전역 에러를 처리하는 Express 미들웨어 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const { AppError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 에러 응답 포맷터 + */ +const formatErrorResponse = (error, req) => { + const response = { + success: false, + error: { + message: error.message || '알 수 없는 오류가 발생했습니다', + code: error.code || 'INTERNAL_ERROR' + }, + timestamp: new Date().toISOString() + }; + + // 검증 에러의 경우 상세 정보 포함 + if (error.details) { + response.error.details = error.details; + } + + // 개발 환경에서만 스택 트레이스 포함 + if (process.env.NODE_ENV === 'development') { + response.error.stack = error.stack; + response.request = { + method: req.method, + url: req.originalUrl, + ip: req.ip, + user: req.user?.username || 'anonymous' + }; + } + + return response; +}; + +/** + * 에러 핸들러 미들웨어 + */ +const errorHandler = (error, req, res, next) => { + // AppError가 아닌 경우 변환 + if (!(error instanceof AppError)) { + error = new AppError( + error.message || '서버 내부 오류가 발생했습니다', + 500, + 'INTERNAL_ERROR' + ); + } + + // 로깅 + if (error.statusCode >= 500) { + logger.error(error.message, { + code: error.code, + stack: error.stack, + url: req.originalUrl, + method: req.method, + user: req.user?.username || 'anonymous' + }); + } else { + logger.warn(error.message, { + code: error.code, + url: req.originalUrl, + method: req.method, + user: req.user?.username || 'anonymous' + }); + } + + // 응답 + const response = formatErrorResponse(error, req); + res.status(error.statusCode).json(response); +}; + +/** + * 비동기 함수 래퍼 (에러 자동 처리) + */ +const asyncHandler = (fn) => { + return (req, res, next) => { + Promise.resolve(fn(req, res, next)).catch(next); + }; +}; + +/** + * 404 Not Found 핸들러 + */ +const notFoundHandler = (req, res, next) => { + const { NotFoundError } = require('../utils/errors'); + next(new NotFoundError(`경로를 찾을 수 없습니다: ${req.originalUrl}`)); +}; + +module.exports = { + errorHandler, + asyncHandler, + notFoundHandler +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/models/WorkAnalysis.js b/deploy/tkfb-package/api.hyungi.net/models/WorkAnalysis.js new file mode 100644 index 0000000..8513ace --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/WorkAnalysis.js @@ -0,0 +1,519 @@ +// models/WorkAnalysis.js - 향상된 버전 + +class WorkAnalysis { + constructor(db) { + this.db = db; + } + + // 기본 통계 조회 + async getBasicStats(startDate, endDate) { + const query = ` + SELECT + COALESCE(SUM(work_hours), 0) as total_hours, + COUNT(*) as total_reports, + COUNT(DISTINCT project_id) as active_projects, + COUNT(DISTINCT worker_id) as active_workers, + SUM(CASE WHEN work_status_id = 2 THEN 1 ELSE 0 END) as error_reports, + ROUND(AVG(work_hours), 2) as avg_hours_per_report + FROM daily_work_reports + WHERE report_date BETWEEN ? AND ? + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate]); + const stats = results[0]; + + const errorRate = stats.total_reports > 0 + ? (stats.error_reports / stats.total_reports) * 100 + : 0; + + return { + totalHours: parseFloat(stats.total_hours) || 0, + totalReports: parseInt(stats.total_reports) || 0, + activeProjects: parseInt(stats.active_projects) || 0, + activeworkers: parseInt(stats.active_workers) || 0, + errorRate: parseFloat(errorRate.toFixed(2)) || 0, + avgHoursPerReport: parseFloat(stats.avg_hours_per_report) || 0 + }; + } catch (error) { + throw new Error(`기본 통계 조회 실패: ${error.message}`); + } + } + + // 일별 작업시간 추이 + async getDailyTrend(startDate, endDate) { + const query = ` + SELECT + report_date as date, + SUM(work_hours) as hours, + COUNT(*) as reports, + COUNT(DISTINCT worker_id) as workers, + SUM(CASE WHEN work_status_id = 2 THEN 1 ELSE 0 END) as errors + FROM daily_work_reports + WHERE report_date BETWEEN ? AND ? + GROUP BY report_date + ORDER BY report_date + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate]); + return results.map(row => ({ + date: row.date, + hours: parseFloat(row.hours) || 0, + reports: parseInt(row.reports) || 0, + workers: parseInt(row.workers) || 0, + errors: parseInt(row.errors) || 0 + })); + } catch (error) { + throw new Error(`일별 추이 조회 실패: ${error.message}`); + } + } + + // 작업자별 통계 + async getWorkerStats(startDate, endDate) { + const query = ` + SELECT + dwr.worker_id, + w.worker_name, + SUM(dwr.work_hours) as totalHours, + COUNT(*) as totalReports, + ROUND(AVG(dwr.work_hours), 2) as avgHours, + COUNT(DISTINCT dwr.project_id) as projectCount, + SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as errorCount, + COUNT(DISTINCT dwr.report_date) as workingDays + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.report_date BETWEEN ? AND ? + GROUP BY dwr.worker_id, w.worker_name + ORDER BY totalHours DESC + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate]); + return results.map(row => ({ + worker_id: row.worker_id, + worker_name: row.worker_name || `작업자 ${row.worker_id}`, + totalHours: parseFloat(row.totalHours) || 0, + totalReports: parseInt(row.totalReports) || 0, + avgHours: parseFloat(row.avgHours) || 0, + projectCount: parseInt(row.projectCount) || 0, + errorCount: parseInt(row.errorCount) || 0, + workingDays: parseInt(row.workingDays) || 0, + errorRate: row.totalReports > 0 ? parseFloat(((row.errorCount / row.totalReports) * 100).toFixed(2)) : 0 + })); + } catch (error) { + throw new Error(`작업자별 통계 조회 실패: ${error.message}`); + } + } + + // 프로젝트별 통계 + async getProjectStats(startDate, endDate) { + const query = ` + SELECT + dwr.project_id, + p.project_name, + SUM(dwr.work_hours) as totalHours, + COUNT(*) as totalReports, + COUNT(DISTINCT dwr.worker_id) as workerCount, + ROUND(AVG(dwr.work_hours), 2) as avgHours, + SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as errorCount, + COUNT(DISTINCT dwr.report_date) as activeDays + FROM daily_work_reports dwr + LEFT JOIN projects p ON dwr.project_id = p.project_id + WHERE dwr.report_date BETWEEN ? AND ? + GROUP BY dwr.project_id, p.project_name + ORDER BY totalHours DESC + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate]); + return results.map(row => ({ + project_id: row.project_id, + project_name: row.project_name || `프로젝트 ${row.project_id}`, + totalHours: parseFloat(row.totalHours) || 0, + totalReports: parseInt(row.totalReports) || 0, + workerCount: parseInt(row.workerCount) || 0, + avgHours: parseFloat(row.avgHours) || 0, + errorCount: parseInt(row.errorCount) || 0, + activeDays: parseInt(row.activeDays) || 0, + errorRate: row.totalReports > 0 ? parseFloat(((row.errorCount / row.totalReports) * 100).toFixed(2)) : 0 + })); + } catch (error) { + throw new Error(`프로젝트별 통계 조회 실패: ${error.message}`); + } + } + + // 작업유형별 통계 + async getWorkTypeStats(startDate, endDate) { + const query = ` + SELECT + dwr.work_type_id, + wt.name as work_type_name, + SUM(dwr.work_hours) as totalHours, + COUNT(*) as totalReports, + ROUND(AVG(dwr.work_hours), 2) as avgHours, + COUNT(DISTINCT dwr.worker_id) as workerCount, + SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as errorCount, + COUNT(DISTINCT dwr.project_id) as projectCount + FROM daily_work_reports dwr + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + WHERE dwr.report_date BETWEEN ? AND ? + GROUP BY dwr.work_type_id, wt.name + ORDER BY totalHours DESC + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate]); + return results.map(row => ({ + work_type_id: row.work_type_id, + work_type_name: row.work_type_name || `작업유형 ${row.work_type_id}`, + totalHours: parseFloat(row.totalHours) || 0, + totalReports: parseInt(row.totalReports) || 0, + avgHours: parseFloat(row.avgHours) || 0, + workerCount: parseInt(row.workerCount) || 0, + errorCount: parseInt(row.errorCount) || 0, + projectCount: parseInt(row.projectCount) || 0, + errorRate: row.totalReports > 0 ? parseFloat(((row.errorCount / row.totalReports) * 100).toFixed(2)) : 0 + })); + } catch (error) { + throw new Error(`작업유형별 통계 조회 실패: ${error.message}`); + } + } + + // 최근 작업 현황 + async getRecentWork(startDate, endDate, limit = 50) { + // work_type_id 컬럼에는 task_id가 저장됨 (tasks 테이블 우선 조회) + // task_id로 매칭되면 해당 task의 work_type_id로 공정(대분류) 조회 + // 매칭 안 되면 직접 work_types 테이블 조회 (레거시 데이터 호환) + // error_type_id는 issue_report_items 테이블 참조 (issue-categories.html에서 관리) + const query = ` + SELECT + dwr.id, + dwr.report_date, + dwr.worker_id, + w.worker_name, + dwr.project_id, + p.project_name, + p.job_no, + dwr.work_type_id as original_work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN t.work_type_id ELSE NULL END, + wt.id + ) as work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN wt2.name ELSE NULL END, + wt.name + ) as work_type_name, + t.task_name as task_name, + dwr.work_status_id, + wst.name as work_status_name, + dwr.error_type_id, + iri.item_name as error_type_name, + irc.category_name as error_category_name, + dwr.work_hours, + dwr.created_by, + u.name as created_by_name, + dwr.created_at + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN projects p ON dwr.project_id = p.project_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id + LEFT JOIN work_status_types wst ON dwr.work_status_id = wst.id + LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id + LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id + LEFT JOIN users u ON dwr.created_by = u.user_id + WHERE dwr.report_date BETWEEN ? AND ? + ORDER BY dwr.created_at DESC + LIMIT ? + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate, parseInt(limit)]); + return results.map(row => ({ + id: row.id, + report_date: row.report_date, + worker_id: row.worker_id, + worker_name: row.worker_name || `작업자 ${row.worker_id}`, + project_id: row.project_id, + project_name: row.project_name || `프로젝트 ${row.project_id}`, + job_no: row.job_no || 'N/A', + work_type_id: row.work_type_id, + work_type_name: row.work_type_name || `작업유형 ${row.original_work_type_id}`, + task_name: row.task_name || null, + work_status_id: row.work_status_id, + work_status_name: row.work_status_name || '정상', + error_type_id: row.error_type_id, + error_type_name: row.error_type_name || null, + error_category_name: row.error_category_name || null, + work_hours: parseFloat(row.work_hours) || 0, + created_by: row.created_by, + created_by_name: row.created_by_name || '미지정', + created_at: row.created_at + })); + } catch (error) { + throw new Error(`최근 작업 현황 조회 실패: ${error.message}`); + } + } + + // 요일별 패턴 분석 + async getWeekdayPattern(startDate, endDate) { + const query = ` + SELECT + DAYOFWEEK(report_date) as day_of_week, + CASE DAYOFWEEK(report_date) + WHEN 1 THEN '일요일' + WHEN 2 THEN '월요일' + WHEN 3 THEN '화요일' + WHEN 4 THEN '수요일' + WHEN 5 THEN '목요일' + WHEN 6 THEN '금요일' + WHEN 7 THEN '토요일' + END as day_name, + SUM(work_hours) as total_hours, + COUNT(*) as total_reports, + ROUND(AVG(work_hours), 2) as avg_hours, + COUNT(DISTINCT worker_id) as active_workers + FROM daily_work_reports + WHERE report_date BETWEEN ? AND ? + GROUP BY DAYOFWEEK(report_date) + ORDER BY day_of_week + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate]); + return results.map(row => ({ + dayOfWeek: row.day_of_week, + dayName: row.day_name, + totalHours: parseFloat(row.total_hours) || 0, + totalReports: parseInt(row.total_reports) || 0, + avgHours: parseFloat(row.avg_hours) || 0, + activeworkers: parseInt(row.active_workers) || 0 + })); + } catch (error) { + throw new Error(`요일별 패턴 분석 실패: ${error.message}`); + } + } + + // 에러 분석 + // error_type_id는 issue_report_items 테이블 참조 (issue-categories.html에서 관리) + async getErrorAnalysis(startDate, endDate) { + const query = ` + SELECT + dwr.error_type_id, + iri.item_name as error_type_name, + irc.category_name as error_category_name, + COUNT(*) as error_count, + SUM(dwr.work_hours) as total_hours, + COUNT(DISTINCT dwr.worker_id) as affected_workers, + COUNT(DISTINCT dwr.project_id) as affected_projects + FROM daily_work_reports dwr + LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id + LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id + WHERE dwr.report_date BETWEEN ? AND ? + AND dwr.work_status_id = 2 + GROUP BY dwr.error_type_id, iri.item_name, irc.category_name + ORDER BY error_count DESC + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate]); + return results.map(row => ({ + error_type_id: row.error_type_id, + error_type_name: row.error_type_name || `에러유형 ${row.error_type_id}`, + error_category_name: row.error_category_name || null, + errorCount: parseInt(row.error_count) || 0, + totalHours: parseFloat(row.total_hours) || 0, + affectedworkers: parseInt(row.affected_workers) || 0, + affectedProjects: parseInt(row.affected_projects) || 0 + })); + } catch (error) { + throw new Error(`에러 분석 실패: ${error.message}`); + } + } + + // 월별 비교 분석 + async getMonthlyComparison(year) { + const query = ` + SELECT + MONTH(report_date) as month, + MONTHNAME(report_date) as month_name, + SUM(work_hours) as total_hours, + COUNT(*) as total_reports, + COUNT(DISTINCT worker_id) as active_workers, + COUNT(DISTINCT project_id) as active_projects, + SUM(CASE WHEN work_status_id = 2 THEN 1 ELSE 0 END) as error_count + FROM daily_work_reports + WHERE YEAR(report_date) = ? + GROUP BY MONTH(report_date), MONTHNAME(report_date) + ORDER BY month + `; + + try { + const [results] = await this.db.execute(query, [year]); + return results.map(row => ({ + month: row.month, + monthName: row.month_name, + totalHours: parseFloat(row.total_hours) || 0, + totalReports: parseInt(row.total_reports) || 0, + activeworkers: parseInt(row.active_workers) || 0, + activeProjects: parseInt(row.active_projects) || 0, + errorCount: parseInt(row.error_count) || 0, + errorRate: row.total_reports > 0 ? parseFloat(((row.error_count / row.total_reports) * 100).toFixed(2)) : 0 + })); + } catch (error) { + throw new Error(`월별 비교 분석 실패: ${error.message}`); + } + } + + // 작업자별 전문분야 분석 + async getWorkerSpecialization(startDate, endDate) { + const query = ` + SELECT + dwr.worker_id, + w.worker_name, + dwr.work_type_id, + wt.name as work_type_name, + dwr.project_id, + p.project_name, + SUM(dwr.work_hours) as totalHours, + COUNT(*) as totalReports, + ROUND((SUM(dwr.work_hours) / ( + SELECT SUM(work_hours) + FROM daily_work_reports + WHERE worker_id = dwr.worker_id + AND report_date BETWEEN ? AND ? + )) * 100, 2) as percentage + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN projects p ON dwr.project_id = p.project_id + WHERE dwr.report_date BETWEEN ? AND ? + GROUP BY dwr.worker_id, w.worker_name, dwr.work_type_id, wt.name, dwr.project_id, p.project_name + HAVING totalHours > 0 + ORDER BY dwr.worker_id, totalHours DESC + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate, startDate, endDate]); + return results.map(row => ({ + worker_id: row.worker_id, + worker_name: row.worker_name || `작업자 ${row.worker_id}`, + work_type_id: row.work_type_id, + work_type_name: row.work_type_name || `작업유형 ${row.work_type_id}`, + project_id: row.project_id, + project_name: row.project_name || `프로젝트 ${row.project_id}`, + totalHours: parseFloat(row.totalHours) || 0, + totalReports: parseInt(row.totalReports) || 0, + percentage: parseFloat(row.percentage) || 0 + })); + } catch (error) { + throw new Error(`작업자별 전문분야 분석 실패: ${error.message}`); + } + } + + // 대시보드용 종합 데이터 + async getDashboardData(startDate, endDate) { + try { + // 병렬로 모든 데이터 조회 + const [ + stats, + dailyTrend, + workerStats, + projectStats, + workTypeStats, + recentWork + ] = await Promise.all([ + this.getBasicStats(startDate, endDate), + this.getDailyTrend(startDate, endDate), + this.getWorkerStats(startDate, endDate), + this.getProjectStats(startDate, endDate), + this.getWorkTypeStats(startDate, endDate), + this.getRecentWork(startDate, endDate, 20) + ]); + + return { + stats, + dailyTrend, + workerStats, + projectStats, + workTypeStats, + recentWork, + metadata: { + period: `${startDate} ~ ${endDate}`, + timestamp: new Date().toISOString() + } + }; + } catch (error) { + throw new Error(`대시보드 데이터 조회 실패: ${error.message}`); + } + } + // 프로젝트별-작업별 시간 분석용 데이터 조회 (공정/대분류 기준) + async getProjectWorkTypeRawData(startDate, endDate) { + // work_type_id 컬럼에는 task_id가 저장됨 (tasks 테이블 우선 조회) + // task_id로 매칭되면 해당 task의 work_type_id로 공정 조회 + // 매칭 안 되면 직접 work_types 조회 (레거시 데이터 호환) + const query = ` + SELECT + COALESCE(p.project_id, dwr.project_id) as project_id, + COALESCE(p.project_name, CONCAT('프로젝트 ', dwr.project_id)) as project_name, + COALESCE(p.job_no, 'N/A') as job_no, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN t.work_type_id ELSE NULL END, + wt.id + ) as work_type_id, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN wt2.name ELSE NULL END, + wt.name, + CONCAT('작업유형 ', dwr.work_type_id) + ) as work_type_name, + + -- 총 시간 + SUM(dwr.work_hours) as total_hours, + + -- 정규 시간 (work_status_id = 1) + SUM(CASE WHEN dwr.work_status_id = 1 THEN dwr.work_hours ELSE 0 END) as regular_hours, + + -- 에러 시간 (work_status_id = 2) + SUM(CASE WHEN dwr.work_status_id = 2 THEN dwr.work_hours ELSE 0 END) as error_hours, + + -- 작업 건수 + COUNT(*) as total_reports, + COUNT(CASE WHEN dwr.work_status_id = 1 THEN 1 END) as regular_reports, + COUNT(CASE WHEN dwr.work_status_id = 2 THEN 1 END) as error_reports, + + -- 에러율 계산 + ROUND( + (SUM(CASE WHEN dwr.work_status_id = 2 THEN dwr.work_hours ELSE 0 END) / + SUM(dwr.work_hours)) * 100, 2 + ) as error_rate_percent + + FROM daily_work_reports dwr + LEFT JOIN projects p ON dwr.project_id = p.project_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt2 ON t.work_type_id = wt2.id + WHERE dwr.report_date BETWEEN ? AND ? + GROUP BY dwr.project_id, p.project_name, p.job_no, + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN t.work_type_id ELSE NULL END, + wt.id + ), + COALESCE( + CASE WHEN t.task_id IS NOT NULL THEN wt2.name ELSE NULL END, + wt.name + ) + ORDER BY p.project_name, work_type_name + `; + + try { + const [results] = await this.db.execute(query, [startDate, endDate]); + return results; + } catch (error) { + throw new Error(`프로젝트-작업유형별 원본 데이터 조회 실패: ${error.message}`); + } + } +} + +module.exports = WorkAnalysis; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/models/analysisModel.js b/deploy/tkfb-package/api.hyungi.net/models/analysisModel.js new file mode 100644 index 0000000..c0b5b84 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/analysisModel.js @@ -0,0 +1,115 @@ +// /models/analysisModel.js +const { getDb } = require('../dbPool'); + +/** + * 지정된 기간 동안의 작업 보고서 데이터를 집계하여 분석합니다. + * 이 함수는 여러 개의 SQL 쿼리를 병렬로 실행하여 효율성을 높입니다. + * @param {string} startDate - 시작일 (YYYY-MM-DD) + * @param {string} endDate - 종료일 (YYYY-MM-DD) + * @returns {Promise} - 요약, 프로젝트별, 작업자별, 작업별 집계 데이터 및 상세 내역 + */ +const getAnalysis = async (startDate, endDate) => { + try { + const db = await getDb(); + + // SQL 쿼리에서 반복적으로 사용될 WHERE 조건과 실제 투입 시간 계산 로직 + const whereClause = `WHERE dwr.report_date BETWEEN ? AND ?`; + const workHoursCalc = ` + CASE dwr.work_details + WHEN '연차' THEN 0 WHEN '반차' THEN 4 WHEN '반반차' THEN 6 + WHEN '조퇴' THEN 2 WHEN '휴무' THEN 0 WHEN '유급' THEN 0 + ELSE 8 + END + (COALESCE(dwr.overtime_hours, 0) * 1.5) + `; + + // 1. 요약 정보 쿼리 + const summarySql = ` + SELECT + COUNT(DISTINCT dwr.project_id) as totalProjects, + COUNT(DISTINCT dwr.worker_id) as totalworkers, + COUNT(DISTINCT dwr.task_id) as totalTasks, + SUM(${workHoursCalc}) as totalHours + FROM DailyWorkReports dwr + ${whereClause} AND (${workHoursCalc}) > 0 + `; + + // 2. 프로젝트별 집계 쿼리 + const byProjectSql = ` + SELECT p.project_name as name, SUM(${workHoursCalc}) as hours, COUNT(DISTINCT dwr.worker_id) as participants + FROM DailyWorkReports dwr + JOIN projects p ON dwr.project_id = p.project_id + ${whereClause} + GROUP BY p.project_name + HAVING hours > 0 + ORDER BY hours DESC; + `; + + // 3. 작업자별 집계 쿼리 + const byWorkerSql = ` + SELECT w.worker_name as name, SUM(${workHoursCalc}) as hours, COUNT(DISTINCT dwr.project_id) as participants + FROM DailyWorkReports dwr + JOIN workers w ON dwr.worker_id = w.worker_id + ${whereClause} + GROUP BY w.worker_name + HAVING hours > 0 + ORDER BY hours DESC; + `; + + // 4. 작업별 집계 쿼리 + const byTaskSql = ` + SELECT t.category as name, SUM(${workHoursCalc}) as hours, COUNT(DISTINCT dwr.worker_id) as participants + FROM DailyWorkReports dwr + JOIN Tasks t ON dwr.task_id = t.task_id + ${whereClause} + GROUP BY t.category + HAVING hours > 0 + ORDER BY hours DESC; + `; + + // 5. 상세 내역 쿼리 + const detailsSql = ` + SELECT + dwr.report_date as date, p.project_name, w.worker_name, + t.category as task_category, dwr.work_details, + (${workHoursCalc}) as work_hours, dwr.memo + FROM DailyWorkReports dwr + JOIN projects p ON dwr.project_id = p.project_id + JOIN workers w ON dwr.worker_id = w.worker_id + JOIN Tasks t ON dwr.task_id = t.task_id + ${whereClause} + HAVING work_hours > 0 + ORDER BY dwr.report_date DESC; + `; + + // 모든 쿼리를 병렬로 실행 + const [ + [summaryResult], + [byProject], + [byWorker], + [byTask], + [details] + ] = await Promise.all([ + db.query(summarySql, [startDate, endDate]), + db.query(byProjectSql, [startDate, endDate]), + db.query(byWorkerSql, [startDate, endDate]), + db.query(byTaskSql, [startDate, endDate]), + db.query(detailsSql, [startDate, endDate]) + ]); + + return { + summary: summaryResult[0], + byProject, + byWorker, + byTask, + details + }; + + } catch (err) { + console.error('[Model] 분석 데이터 조회 오류:', err); + throw new Error('데이터베이스에서 분석 데이터를 조회하는 중 오류가 발생했습니다.'); + } +}; + +module.exports = { + getAnalysis +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/models/attendanceModel.js b/deploy/tkfb-package/api.hyungi.net/models/attendanceModel.js new file mode 100644 index 0000000..a14c411 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/attendanceModel.js @@ -0,0 +1,530 @@ +const { getDb } = require('../dbPool'); + +class AttendanceModel { + // 일일 근태 기록 조회 + static async getDailyAttendanceRecords(date, workerId = null) { + const db = await getDb(); + let query = ` + SELECT + dar.*, + w.worker_name, + w.job_type, + wat.type_name as attendance_type_name, + wat.type_code as attendance_type_code, + vt.type_name as vacation_type_name, + vt.type_code as vacation_type_code, + vt.deduct_days as vacation_days + FROM daily_attendance_records dar + LEFT JOIN workers w ON dar.worker_id = w.worker_id + LEFT JOIN work_attendance_types wat ON dar.attendance_type_id = wat.id + LEFT JOIN vacation_types vt ON dar.vacation_type_id = vt.id + WHERE dar.record_date = ? + `; + + const params = [date]; + + if (workerId) { + query += ' AND dar.worker_id = ?'; + params.push(workerId); + } + + query += ' ORDER BY w.worker_name'; + + const [rows] = await db.execute(query, params); + return rows; + } + + // 기간별 근태 기록 조회 (월별 조회용) + static async getDailyRecords(startDate, endDate, workerId = null) { + const db = await getDb(); + let query = ` + SELECT + dar.*, + w.worker_name, + w.job_type, + wat.type_name as attendance_type_name, + wat.type_code as attendance_type_code, + vt.type_name as vacation_type_name, + vt.type_code as vacation_type_code, + vt.deduct_days as vacation_days + FROM daily_attendance_records dar + LEFT JOIN workers w ON dar.worker_id = w.worker_id + LEFT JOIN work_attendance_types wat ON dar.attendance_type_id = wat.id + LEFT JOIN vacation_types vt ON dar.vacation_type_id = vt.id + WHERE dar.record_date BETWEEN ? AND ? + `; + + const params = [startDate, endDate]; + + if (workerId) { + query += ' AND dar.worker_id = ?'; + params.push(workerId); + } + + query += ' ORDER BY dar.record_date ASC'; + + const [rows] = await db.execute(query, params); + return rows; + } + + // 작업 보고서와 근태 기록 동기화 (시간 합산 및 상태 업데이트) + static async syncWithWorkReports(workerId, date) { + const db = await getDb(); + + // 1. 해당 날짜의 총 작업 시간 계산 + const [reportStats] = await db.execute(` + SELECT + COALESCE(SUM(work_hours), 0) as total_hours, + COUNT(*) as report_count + FROM daily_work_reports + WHERE worker_id = ? AND report_date = ? + `, [workerId, date]); + + const totalHours = parseFloat(reportStats[0].total_hours || 0); + const reportCount = reportStats[0].report_count; + + // 2. 근태 유형 및 상태 결정 + // 기본 규칙: 0시간 -> incomplete, <8시간 -> partial, 8시간 -> complete, >8시간 -> overtime + // (휴가는 별도 로직이지만 여기서 덮어쓰지 않도록 주의해야 함. 하지만 작업보고서가 추가되면 실 근무로 간주) + + let status = 'incomplete'; + let typeCode = 'REGULAR'; // 기본값 + + if (totalHours === 0) { + status = 'incomplete'; + } else if (totalHours < 8) { + status = 'partial'; + typeCode = 'PARTIAL'; + } else if (totalHours === 8) { + status = 'complete'; + typeCode = 'REGULAR'; + } else { + status = 'overtime'; + typeCode = 'OVERTIME'; + } + + // 근태 유형 ID 조회 + const [types] = await db.execute('SELECT id FROM work_attendance_types WHERE type_code = ?', [typeCode]); + const typeId = types[0]?.id; + + // 3. 기록 업데이트 (휴가 정보는 유지) + // 기존 기록 조회 + const [existing] = await db.execute( + 'SELECT id, vacation_type_id FROM daily_attendance_records WHERE worker_id = ? AND record_date = ?', + [workerId, date] + ); + + if (existing.length > 0) { + // 휴가가 설정되어 있고 시간이 0이면 휴가 상태 유지, 시간이 있으면 근무+휴가 복합 상태일 수 있음 + // 여기서는 단순화하여 근무 시간이 있으면 근무 상태로 업데이트 (단, vacation_type_id는 유지) + + const recordId = existing[0].id; + // 만약 기존 상태가 'vacation'이고 근무시간이 0이면 업데이트 건너뛸 수도 있지만, + // 작업보고서가 삭제되어 0이 된 경우도 있으므로 업데이트는 수행해야 함. + + await db.execute(` + UPDATE daily_attendance_records + SET + total_work_hours = ?, + attendance_type_id = ?, + status = ?, + updated_at = CURRENT_TIMESTAMP + WHERE id = ? + `, [totalHours, typeId, status, recordId]); + + return { synced: true, totalHours, status }; + } else { + // 기록이 없으면 생성 (일반적으로는 initializeDailyRecords로 생성되어 있어야 함) + // 생성자가 명확하지 않으므로 시스템(1) 또는 알 수 없음 처리 + await db.execute(` + INSERT INTO daily_attendance_records + (record_date, worker_id, total_work_hours, attendance_type_id, status, created_by) + VALUES (?, ?, ?, ?, ?, 1) + `, [date, workerId, totalHours, typeId, status]); + + return { synced: true, totalHours, status, created: true }; + } + } + + // 일일 근태 기록 초기화 (모든 활성 작업자에 대한 기본 레코드 생성) + static async initializeDailyRecords(date, createdBy) { + const db = await getDb(); + + // 1. 활성 작업자 조회 + const [workers] = await db.execute( + 'SELECT worker_id FROM workers WHERE status = "active"' // is_active check not needed as status covers it based on previous fix? Wait, previous fix used status='active'. + ); + + if (workers.length === 0) return { inserted: 0 }; + + // 2. 일일 근태 레코드 일괄 생성 (이미 존재하면 무시) + // VALUES (...), (...), ... + const values = workers.map(w => [date, w.worker_id, 'incomplete', createdBy]); + + // Bulk INSERT IGNORE + // Note: mysql2 execute doesn't support nested arrays for bulk insert easily with placeholder ? + // We should build the query or use query method for pool? + // Using simple loop for safety and compatibility or building string. + + let insertedCount = 0; + + // 트랜잭션 사용 권장 + const conn = await db.getConnection(); + try { + await conn.beginTransaction(); + + for (const w of workers) { + const [result] = await conn.execute(` + INSERT IGNORE INTO daily_attendance_records + (record_date, worker_id, status, created_by) + VALUES (?, ?, 'incomplete', ?) + `, [date, w.worker_id, createdBy]); + + insertedCount += result.affectedRows; + } + + await conn.commit(); + } catch (err) { + await conn.rollback(); + throw err; + } finally { + conn.release(); + } + + return { inserted: insertedCount, total_active_workers: workers.length }; + } + + // 근태 기록 생성 또는 업데이트 + static async upsertAttendanceRecord(recordData) { + const db = await getDb(); + + const { + record_date, + worker_id, + total_work_hours = 8, + work_attendance_type_id = 1, + vacation_type_id = null, + is_overtime_approved = false, + created_by = 1 + } = recordData; + + const attendance_type_id = work_attendance_type_id; + + // 기존 기록 확인 + const [existing] = await db.execute( + 'SELECT id FROM daily_attendance_records WHERE worker_id = ? AND record_date = ?', + [worker_id, record_date] + ); + + if (existing.length > 0) { + // 업데이트 + const [result] = await db.execute(` + UPDATE daily_attendance_records + SET + total_work_hours = ?, + attendance_type_id = ?, + vacation_type_id = ?, + is_overtime_approved = ?, + updated_at = CURRENT_TIMESTAMP + WHERE id = ? + `, [ + total_work_hours, + attendance_type_id, + vacation_type_id, + is_overtime_approved, + existing[0].id + ]); + + return { id: existing[0].id, affected: result.affectedRows }; + } else { + // 생성 + const [result] = await db.execute(` + INSERT INTO daily_attendance_records ( + record_date, worker_id, total_work_hours, attendance_type_id, + vacation_type_id, is_overtime_approved, created_by + ) VALUES (?, ?, ?, ?, ?, ?, ?) + `, [ + record_date, + worker_id, + total_work_hours, + attendance_type_id, + vacation_type_id, + is_overtime_approved, + created_by + ]); + + return { id: result.insertId, affected: result.affectedRows }; + } + } + + // 작업자별 근태 현황 조회 (대시보드용) + static async getWorkerAttendanceStatus(date) { + const db = await getDb(); + + // 모든 작업자와 해당 날짜의 근태 기록을 조회 + const [rows] = await db.execute(` + SELECT + w.worker_id, + w.worker_name, + w.job_type, + COALESCE(dar.total_work_hours, 0) as total_work_hours, + COALESCE(dar.status, 'incomplete') as status, + dar.is_vacation_processed, + dar.overtime_approved, + wat.type_name as attendance_type_name, + wat.type_code as attendance_type_code, + vt.type_name as vacation_type_name, + vt.type_code as vacation_type_code, + dar.notes, + -- 작업 건수 계산 + (SELECT COUNT(*) FROM daily_work_reports dwr + WHERE dwr.worker_id = w.worker_id AND dwr.report_date = ?) as work_count, + -- 오류 건수 계산 + (SELECT COUNT(*) FROM daily_work_reports dwr + WHERE dwr.worker_id = w.worker_id AND dwr.report_date = ? AND dwr.work_status_id = 2) as error_count + FROM workers w + LEFT JOIN daily_attendance_records dar ON w.worker_id = dar.worker_id AND dar.record_date = ? + LEFT JOIN work_attendance_types wat ON dar.attendance_type_id = wat.id + LEFT JOIN vacation_types vt ON dar.vacation_type_id = vt.id + WHERE w.is_active = TRUE + ORDER BY w.worker_name + `, [date, date, date]); + + return rows; + } + + // 휴가 처리 + static async processVacation(workerId, date, vacationType, createdBy) { + const db = await getDb(); + + // 휴가 유형 정보 조회 + const [vacationTypes] = await db.execute( + 'SELECT id, type_code, type_name, deduct_days, is_active, created_at, updated_at FROM vacation_types WHERE type_code = ?', + [vacationType] + ); + + if (vacationTypes.length === 0) { + throw new Error('유효하지 않은 휴가 유형입니다.'); + } + + const vacationTypeInfo = vacationTypes[0]; + + // 현재 작업 시간 조회 + const [workHours] = await db.execute(` + SELECT COALESCE(SUM(work_hours), 0) as total_hours + FROM daily_work_reports + WHERE worker_id = ? AND report_date = ? + `, [workerId, date]); + + const currentHours = parseFloat(workHours[0].total_hours); + // deduct_days를 시간으로 변환 (1일 = 8시간) + const vacationHours = parseFloat(vacationTypeInfo.deduct_days) * 8; + const totalHours = currentHours + vacationHours; + + // 근로 유형 결정 + let attendanceTypeCode = 'VACATION'; + let status = 'vacation'; + + if (totalHours >= 8) { + attendanceTypeCode = totalHours > 8 ? 'OVERTIME' : 'REGULAR'; + status = totalHours > 8 ? 'overtime' : 'complete'; + } + + const [attendanceTypes] = await db.execute( + 'SELECT id FROM work_attendance_types WHERE type_code = ?', + [attendanceTypeCode] + ); + + // 휴가 작업 기록 생성 (프로젝트 ID 13 = "연차/휴무", work_type_id 1 = 기본) + await db.execute(` + INSERT INTO daily_work_reports ( + report_date, worker_id, project_id, work_type_id, work_status_id, + work_hours, description, created_by + ) VALUES (?, ?, 13, 1, 1, ?, ?, ?) + `, [ + date, + workerId, + vacationHours, + `${vacationTypeInfo.type_name} 처리`, + createdBy + ]); + + // 근태 기록 업데이트 + const attendanceData = { + record_date: date, + worker_id: workerId, + total_work_hours: totalHours, + work_attendance_type_id: attendanceTypes[0]?.id, + vacation_type_id: vacationTypeInfo.id, + is_overtime_approved: false, + created_by: createdBy + }; + + return await this.upsertAttendanceRecord(attendanceData); + } + + // 초과근무 승인 + static async approveOvertime(workerId, date, approvedBy) { + const db = await getDb(); + + const [result] = await db.execute(` + UPDATE daily_attendance_records + SET + overtime_approved = TRUE, + overtime_approved_by = ?, + overtime_approved_at = CURRENT_TIMESTAMP, + updated_by = ?, + updated_at = CURRENT_TIMESTAMP + WHERE worker_id = ? AND record_date = ? + `, [approvedBy, approvedBy, workerId, date]); + + return result.affectedRows > 0; + } + + // 근로 유형 목록 조회 + static async getAttendanceTypes() { + const db = await getDb(); + const [rows] = await db.execute( + 'SELECT id, type_code, type_name, description, is_active, created_at, updated_at FROM work_attendance_types WHERE is_active = TRUE ORDER BY id' + ); + return rows; + } + + // 휴가 유형 목록 조회 + static async getVacationTypes() { + const db = await getDb(); + const [rows] = await db.execute( + 'SELECT id, type_code, type_name, deduct_days, is_active, created_at, updated_at FROM vacation_types WHERE is_active = TRUE ORDER BY deduct_days DESC' + ); + return rows; + } + + // 작업자 휴가 잔여 조회 + static async getWorkerVacationBalance(workerId, year = null) { + const db = await getDb(); + const currentYear = year || new Date().getFullYear(); + + const [rows] = await db.execute(` + SELECT id, worker_id, year, total_annual_leave, used_annual_leave, notes, created_at, updated_at FROM worker_vacation_balance + WHERE worker_id = ? AND year = ? + `, [workerId, currentYear]); + + if (rows.length === 0) { + // 기본 연차 생성 (15일) + await db.execute(` + INSERT INTO worker_vacation_balance (worker_id, year, total_annual_leave) + VALUES (?, ?, 15.0) + `, [workerId, currentYear]); + + return { + worker_id: workerId, + year: currentYear, + total_annual_leave: 15.0, + used_annual_leave: 0, + remaining_annual_leave: 15.0 + }; + } + + return rows[0]; + } + + // 월별 근태 통계 + static async getMonthlyAttendanceStats(year, month, workerId = null) { + const db = await getDb(); + + // work_attendance_types: 1=NORMAL, 2=LATE, 3=EARLY_LEAVE, 4=ABSENT, 5=VACATION + // vacation_types: 1=ANNUAL(연차), 2=HALF_ANNUAL(반차), 3=SICK(병가), 4=SPECIAL(경조사) + let query = ` + SELECT + w.worker_id, + w.worker_name, + COUNT(CASE WHEN dar.attendance_type_id = 1 AND (dar.is_overtime_approved = 0 OR dar.is_overtime_approved IS NULL) THEN 1 END) as regular_days, + COUNT(CASE WHEN dar.is_overtime_approved = 1 OR dar.total_work_hours > 8 THEN 1 END) as overtime_days, + COUNT(CASE WHEN dar.attendance_type_id = 5 AND dar.vacation_type_id = 1 THEN 1 END) as vacation_days, + COUNT(CASE WHEN dar.vacation_type_id = 2 THEN 1 END) as partial_days, + COUNT(CASE WHEN dar.attendance_type_id = 4 THEN 1 END) as incomplete_days, + COALESCE(SUM(dar.total_work_hours), 0) as total_work_hours, + COALESCE(AVG(dar.total_work_hours), 0) as avg_work_hours + FROM workers w + LEFT JOIN daily_attendance_records dar ON w.worker_id = dar.worker_id + AND YEAR(dar.record_date) = ? AND MONTH(dar.record_date) = ? + WHERE w.employment_status = 'employed' + `; + + const params = [year, month]; + + if (workerId) { + query += ' AND w.worker_id = ?'; + params.push(workerId); + } + + query += ' GROUP BY w.worker_id, w.worker_name ORDER BY w.worker_name'; + + const [rows] = await db.execute(query, params); + return rows; + } + + // 출근 체크 기록 생성 또는 업데이트 + static async upsertCheckin(checkinData) { + const db = await getDb(); + const { worker_id, record_date, is_present } = checkinData; + + // 해당 날짜에 기록이 있는지 확인 + const [existing] = await db.execute( + 'SELECT id FROM daily_attendance_records WHERE worker_id = ? AND record_date = ?', + [worker_id, record_date] + ); + + if (existing.length > 0) { + // 업데이트 + await db.execute( + 'UPDATE daily_attendance_records SET is_present = ? WHERE id = ?', + [is_present, existing[0].id] + ); + return existing[0].id; + } else { + // 새로 생성 (기본값으로) + const [result] = await db.execute( + `INSERT INTO daily_attendance_records + (worker_id, record_date, is_present, attendance_type_id, created_by) + VALUES (?, ?, ?, 1, 1)`, + [worker_id, record_date, is_present] + ); + return result.insertId; + } + } + + // 특정 날짜의 출근 체크 목록 조회 (휴가 정보 포함) + static async getCheckinList(date) { + const db = await getDb(); + const query = ` + SELECT + w.worker_id, + w.worker_name, + w.job_type, + w.employment_status, + COALESCE(dar.is_present, TRUE) as is_present, + dar.id as record_id, + vr.request_id as vacation_request_id, + vr.status as vacation_status, + vt.type_name as vacation_type_name, + vt.type_code as vacation_type_code, + vr.days_used as vacation_days + FROM workers w + LEFT JOIN daily_attendance_records dar + ON w.worker_id = dar.worker_id AND dar.record_date = ? + LEFT JOIN vacation_requests vr + ON w.worker_id = vr.worker_id + AND ? BETWEEN vr.start_date AND vr.end_date + AND vr.status = 'approved' + LEFT JOIN vacation_types vt ON vr.vacation_type_id = vt.id + WHERE w.employment_status = 'employed' + ORDER BY w.worker_name + `; + + const [rows] = await db.execute(query, [date, date]); + return rows; + } +} + +module.exports = AttendanceModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/dailyIssueReportModel.js b/deploy/tkfb-package/api.hyungi.net/models/dailyIssueReportModel.js new file mode 100644 index 0000000..8d7f119 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/dailyIssueReportModel.js @@ -0,0 +1,154 @@ +const { getDb } = require('../dbPool'); + +/** + * 1. 여러 개의 이슈 보고서를 트랜잭션으로 생성합니다. + * @param {Array} reports - 생성할 보고서 데이터 배열 + * @returns {Promise>} - 삽입된 ID 배열 + */ +const createMany = async (reports) => { + const db = await getDb(); + const conn = await db.getConnection(); + try { + await conn.beginTransaction(); + + const insertedIds = []; + const sql = ` + INSERT INTO DailyIssueReports + (date, worker_id, project_id, start_time, end_time, issue_type_id) + VALUES (?, ?, ?, ?, ?, ?) + `; + + for (const report of reports) { + const { date, worker_id, project_id, start_time, end_time, issue_type_id } = report; + const [result] = await conn.query(sql, [date, worker_id, project_id, start_time, end_time, issue_type_id]); + insertedIds.push(result.insertId); + } + + await conn.commit(); + return insertedIds; + } catch (err) { + await conn.rollback(); + console.error('[Model] 여러 이슈 보고서 생성 중 오류:', err); + throw new Error('데이터베이스에 이슈 보고서를 생성하는 중 오류가 발생했습니다.'); + } finally { + conn.release(); + } +}; + +/** + * 2. 특정 날짜의 전체 이슈 목록 조회 (Promise 기반) + */ +const getAllByDate = async (date) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT + d.id, d.date, w.worker_name, p.project_name, d.start_time, d.end_time, + t.category, t.subcategory, d.description + FROM DailyIssueReports d + LEFT JOIN workers w ON d.worker_id = w.worker_id + LEFT JOIN projects p ON d.project_id = p.project_id + LEFT JOIN IssueTypes t ON d.issue_type_id = t.issue_type_id + WHERE d.date = ? + ORDER BY d.start_time ASC`, + [date] + ); + return rows; + } catch (err) { + console.error(`[Model] ${date} 이슈 목록 조회 오류:`, err); + throw new Error('데이터베이스에서 이슈 목록을 조회하는 중 오류가 발생했습니다.'); + } +}; + +/** + * 3. 단일 조회 (선택사항: 컨트롤러에서 사용 중) + */ +const getById = async (id, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query(`SELECT id, date, worker_id, project_id, issue_type_id, description, created_at, start_time, end_time FROM DailyIssueReports WHERE id = ?`, [id]); + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 4. 수정 + */ +const update = async (id, data, callback) => { + try { + const db = await getDb(); + + const fields = []; + const values = []; + + for (const key in data) { + fields.push(`${key} = ?`); + values.push(data[key]); + } + + values.push(id); // 마지막에 id + + const [result] = await db.query( + `UPDATE DailyIssueReports SET ${fields.join(', ')} WHERE id = ?`, + values + ); + + callback(null, result.affectedRows); + } catch (err) { + callback(err); + } +}; + +/** + * 5. 삭제 (Promise 기반) + */ +const remove = async (id) => { + try { + const db = await getDb(); + const [result] = await db.query(`DELETE FROM DailyIssueReports WHERE id = ?`, [id]); + return result.affectedRows; + } catch (err) { + console.error(`[Model] 이슈(id: ${id}) 삭제 오류:`, err); + throw new Error('데이터베이스에서 이슈를 삭제하는 중 오류가 발생했습니다.'); + } +}; + +// V1 함수들은 점진적으로 제거 예정 +const create = async (report, callback) => { + try { + const db = await getDb(); + const { + date, + worker_id, + project_id, + start_time, + end_time, + issue_type_id, + description = null // 선택값 처리 + } = report; + + const [result] = await db.query( + `INSERT INTO DailyIssueReports + (date, worker_id, project_id, start_time, end_time, issue_type_id, description) + VALUES (?, ?, ?, ?, ?, ?, ?)`, + [date, worker_id, project_id, start_time, end_time, issue_type_id, description] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + + +module.exports = { + createMany, // 신규 + getAllByDate, + remove, + // 레거시 호환성을 위해 V1 함수들 임시 유지 + create: (report, callback) => createMany([report]).then(ids => callback(null, ids[0])).catch(err => callback(err)), + getById, + update, +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/models/dailyWorkReportModel.js b/deploy/tkfb-package/api.hyungi.net/models/dailyWorkReportModel.js new file mode 100644 index 0000000..8cf266a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/dailyWorkReportModel.js @@ -0,0 +1,1388 @@ +// models/dailyWorkReportModel.js - 누적입력 방식 + 모든 기존 기능 포함 +const { getDb } = require('../dbPool'); + +/** + * 📋 마스터 데이터 조회 함수들 + */ +const getAllWorkTypes = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query('SELECT id, name, description, category, created_at, updated_at FROM work_types ORDER BY name ASC'); + callback(null, rows); + } catch (err) { + console.error('작업 유형 조회 오류:', err); + callback(err); + } +}; + +const getAllWorkStatusTypes = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query('SELECT id, name, description, is_error, created_at FROM work_status_types ORDER BY id ASC'); + callback(null, rows); + } catch (err) { + console.error('업무 상태 유형 조회 오류:', err); + callback(err); + } +}; + +const getAllErrorTypes = async (callback) => { + try { + const db = await getDb(); + // issue_report_items에서 부적합(nonconformity) 타입의 항목만 조회 + const [rows] = await db.query(` + SELECT + iri.item_id as id, + iri.item_name as name, + iri.description, + iri.severity, + irc.category_name as category, + iri.display_order, + iri.created_at + FROM issue_report_items iri + INNER JOIN issue_report_categories irc ON iri.category_id = irc.category_id + WHERE irc.category_type = 'nonconformity' AND iri.is_active = TRUE + ORDER BY irc.display_order, iri.display_order, iri.item_name ASC + `); + callback(null, rows); + } catch (err) { + console.error('에러 유형 조회 오류:', err); + callback(err); + } +}; + +/** + * 🔄 누적 추가 전용 함수 (createDailyReport 대체) - 절대 삭제 안함! + */ +const createDailyReport = async (reportData, callback) => { + const { report_date, worker_id, work_entries, created_by, created_by_name, total_hours } = reportData; + const db = await getDb(); + const conn = await db.getConnection(); + + try { + await conn.beginTransaction(); + + console.log(`📝 ${created_by_name}이 ${report_date} ${worker_id}번 작업자에게 데이터 추가 중...`); + + // ✅ 수정된 쿼리 (테이블 alias 추가): + const [existingReports] = await conn.query( + `SELECT dwr.created_by, u.name as created_by_name, COUNT(*) as count, SUM(dwr.work_hours) as total_hours + FROM daily_work_reports dwr + LEFT JOIN users u ON dwr.created_by = u.user_id + WHERE dwr.report_date = ? AND dwr.worker_id = ? + GROUP BY dwr.created_by`, + [report_date, worker_id] + ); + + + console.log('기존 데이터 (삭제하지 않음):', existingReports); + + // 2. ✅ 삭제 없이 새로운 데이터만 추가! + const insertedIds = []; + for (const entry of work_entries) { + const { project_id, work_type_id, work_status_id, error_type_id, work_hours } = entry; + + const [insertResult] = await conn.query( + `INSERT INTO daily_work_reports + (report_date, worker_id, project_id, work_type_id, work_status_id, error_type_id, work_hours, created_by, created_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, NOW())`, + [report_date, worker_id, project_id, work_type_id, work_status_id || 1, error_type_id || null, work_hours, created_by] + ); + + insertedIds.push(insertResult.insertId); + } + + // ✅ 수정된 쿼리: + const [finalReports] = await conn.query( + `SELECT dwr.created_by, u.name as created_by_name, COUNT(*) as count, SUM(dwr.work_hours) as total_hours + FROM daily_work_reports dwr + LEFT JOIN users u ON dwr.created_by = u.user_id + WHERE dwr.report_date = ? AND dwr.worker_id = ? + GROUP BY dwr.created_by`, + [report_date, worker_id] + ); + + const grandTotal = finalReports.reduce((sum, report) => sum + parseFloat(report.total_hours || 0), 0); + const myTotal = finalReports.find(r => r.created_by === created_by)?.total_hours || 0; + + console.log('최종 결과:'); + finalReports.forEach(report => { + console.log(` - ${report.created_by_name}: ${report.total_hours}시간 (${report.count}개 항목)`); + }); + console.log(` 📊 총합: ${grandTotal}시간`); + + // 4. 감사 로그 추가 + try { + await conn.query( + `INSERT INTO work_report_audit_log + (action, report_id, new_values, changed_by, change_reason, created_at) + VALUES (?, ?, ?, ?, ?, NOW())`, + [ + 'ADD_ACCUMULATE', + insertedIds[0] || null, + JSON.stringify({ + report_date, + worker_id, + work_entries_count: work_entries.length, + added_hours: total_hours, + my_total: myTotal, + grand_total: grandTotal, + contributors: finalReports.map(r => ({ name: r.created_by_name, hours: r.total_hours })) + }), + created_by, + `누적 추가 by ${created_by_name} - 삭제 없음` + ] + ); + } catch (auditErr) { + console.warn('감사 로그 추가 실패:', auditErr.message); + } + + await conn.commit(); + + // 5. 근태 기록 동기화 (추가) + try { + const AttendanceModel = require('./attendanceModel'); + await AttendanceModel.syncWithWorkReports(worker_id, report_date); + } catch (syncErr) { + console.error('근태 기록 동기화 실패:', syncErr); + // 메인 트랜잭션은 성공했으므로 동기화 실패로 롤백하지 않음 (비동기 처리 또는 무시) + } + + callback(null, { + success: true, + inserted_count: insertedIds.length, + deleted_count: 0, // 항상 0 (삭제 안함) + action: 'accumulated', + message: `${created_by_name}이 ${total_hours}시간 추가했습니다. (개인 총 ${myTotal}시간, 전체 총 ${grandTotal}시간)`, + final_summary: { + my_total: parseFloat(myTotal), + grand_total: grandTotal, + total_contributors: finalReports.length, + contributors: finalReports + } + }); + + } catch (err) { + await conn.rollback(); + console.error('작업보고서 누적 추가 오류:', err); + callback(err); + } finally { + conn.release(); + } +}; + +/** + * 📊 특정 날짜 + 작업자 + 작성자의 누적 현황 조회 + */ +const getMyAccumulatedHours = async (date, worker_id, created_by, callback) => { + try { + const db = await getDb(); + + const sql = ` + SELECT + SUM(work_hours) as my_total_hours, + COUNT(*) as my_entry_count, + GROUP_CONCAT( + CONCAT(p.project_name, ':', work_hours, 'h') + ORDER BY created_at + ) as my_entries + FROM daily_work_reports dwr + LEFT JOIN projects p ON dwr.project_id = p.project_id + WHERE dwr.report_date = ? AND dwr.worker_id = ? AND dwr.created_by = ? + `; + + const [rows] = await db.query(sql, [date, worker_id, created_by]); + callback(null, rows[0] || { my_total_hours: 0, my_entry_count: 0, my_entries: null }); + } catch (err) { + console.error('개인 누적 현황 조회 오류:', err); + callback(err); + } +}; + +/** + * 📊 누적 현황 조회 - 날짜+작업자별 (모든 기여자) + */ +const getAccumulatedReportsByDate = async (date, worker_id, callback) => { + try { + const db = await getDb(); + + const sql = getSelectQuery() + ` + WHERE dwr.report_date = ? AND dwr.worker_id = ? + ORDER BY dwr.created_by, dwr.created_at ASC + `; + + const [rows] = await db.query(sql, [date, worker_id]); + callback(null, rows); + } catch (err) { + console.error('누적 현황 조회 오류:', err); + callback(err); + } +}; + +/** + * 📊 기여자별 요약 조회 + */ +const getContributorsByDate = async (date, worker_id, callback) => { + try { + const db = await getDb(); + + const sql = ` + SELECT + dwr.created_by, + u.name as created_by_name, + COUNT(*) as entry_count, + SUM(dwr.work_hours) as total_hours, + MIN(dwr.created_at) as first_entry, + MAX(dwr.created_at) as last_entry, + GROUP_CONCAT( + CONCAT(p.project_name, ':', dwr.work_hours, 'h') + ORDER BY dwr.created_at SEPARATOR ', ' + ) as entry_details + FROM daily_work_reports dwr + LEFT JOIN users u ON dwr.created_by = u.user_id + LEFT JOIN projects p ON dwr.project_id = p.project_id + WHERE dwr.report_date = ? AND dwr.worker_id = ? + GROUP BY dwr.created_by + ORDER BY total_hours DESC, first_entry ASC + `; + + const [rows] = await db.query(sql, [date, worker_id]); + callback(null, rows); + } catch (err) { + console.error('기여자별 요약 조회 오류:', err); + callback(err); + } +}; + +/** + * 🗑️ 특정 작업 항목만 삭제 (개별 삭제) + */ +const removeSpecificEntry = async (entry_id, deleted_by, callback) => { + const db = await getDb(); + const conn = await db.getConnection(); + + try { + await conn.beginTransaction(); + + // 삭제 전 정보 확인 + const [entryInfo] = await conn.query( + `SELECT dwr.*, w.worker_name, p.project_name, u.name as created_by_name + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN projects p ON dwr.project_id = p.project_id + LEFT JOIN users u ON dwr.created_by = u.user_id + WHERE dwr.id = ?`, + [entry_id] + ); + + if (entryInfo.length === 0) { + await conn.rollback(); + return callback(new Error('삭제할 항목을 찾을 수 없습니다.')); + } + + const entry = entryInfo[0]; + + // 권한 확인: 본인이 작성한 것만 삭제 가능 + if (entry.created_by !== deleted_by) { + await conn.rollback(); + return callback(new Error('본인이 작성한 항목만 삭제할 수 있습니다.')); + } + + // 개별 항목 삭제 + const [result] = await conn.query('DELETE FROM daily_work_reports WHERE id = ?', [entry_id]); + + // 감사 로그 (삭제된 테이블이므로 콘솔 로그로 대체) + console.log(`[삭제 로그] 작업자: ${entry.worker_name}, 프로젝트: ${entry.project_name}, 작업시간: ${entry.work_hours}시간, 삭제자: ${deleted_by}`); + + await conn.commit(); + callback(null, { + success: true, + deleted_entry: { + worker_name: entry.worker_name, + project_name: entry.project_name, + work_hours: entry.work_hours + } + }); + + } catch (err) { + await conn.rollback(); + console.error('개별 항목 삭제 오류:', err); + callback(err); + } finally { + conn.release(); + } +}; + +/** + * 공통 SELECT 쿼리 부분 + * error_type_id는 issue_report_items 테이블 참조 (issue-categories.html에서 관리) + */ +const getSelectQuery = () => ` + SELECT + dwr.id, + dwr.report_date, + dwr.worker_id, + dwr.project_id, + dwr.work_type_id, + dwr.work_status_id, + dwr.error_type_id, + dwr.work_hours, + dwr.created_by, + w.worker_name, + p.project_name, + wt.name as work_type_name, + wst.name as work_status_name, + iri.item_name as error_type_name, + irc.category_name as error_category_name, + u.name as created_by_name, + dwr.created_at, + dwr.updated_at + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN projects p ON dwr.project_id = p.project_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN work_status_types wst ON dwr.work_status_id = wst.id + LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id + LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id + LEFT JOIN users u ON dwr.created_by = u.user_id +`; + +/** + * 7. ID로 작업보고서 조회 + */ +const getById = async (id, callback) => { + try { + const db = await getDb(); + const sql = getSelectQuery() + 'WHERE dwr.id = ?'; + const [rows] = await db.query(sql, [id]); + callback(null, rows[0] || null); + } catch (err) { + console.error('ID로 작업보고서 조회 오류:', err); + callback(err); + } +}; + +/** + * 8. 일일 작업보고서 조회 (날짜별) + */ +const getByDate = async (date, callback) => { + try { + const db = await getDb(); + const sql = getSelectQuery() + ` + WHERE dwr.report_date = ? + ORDER BY w.worker_name ASC, p.project_name ASC, dwr.id ASC + `; + const [rows] = await db.query(sql, [date]); + callback(null, rows); + } catch (err) { + console.error('날짜별 작업보고서 조회 오류:', err); + callback(err); + } +}; + +/** + * 9. 일일 작업보고서 조회 (날짜 + 작성자별) + */ +const getByDateAndCreator = async (date, created_by, callback) => { + try { + const db = await getDb(); + const sql = getSelectQuery() + ` + WHERE dwr.report_date = ? AND dwr.created_by = ? + ORDER BY w.worker_name ASC, p.project_name ASC, dwr.id ASC + `; + const [rows] = await db.query(sql, [date, created_by]); + callback(null, rows); + } catch (err) { + console.error('날짜+작성자별 작업보고서 조회 오류:', err); + callback(err); + } +}; + +/** + * 10. 일일 작업보고서 조회 (작업자별) + */ +const getByWorker = async (worker_id, callback) => { + try { + const db = await getDb(); + const sql = getSelectQuery() + ` + WHERE dwr.worker_id = ? + ORDER BY dwr.report_date DESC, dwr.id ASC + `; + const [rows] = await db.query(sql, [worker_id]); + callback(null, rows); + } catch (err) { + console.error('작업자별 작업보고서 조회 오류:', err); + callback(err); + } +}; + +/** + * 11. 일일 작업보고서 조회 (날짜 + 작업자) + */ +const getByDateAndWorker = async (date, worker_id, callback) => { + try { + const db = await getDb(); + const sql = getSelectQuery() + ` + WHERE dwr.report_date = ? AND dwr.worker_id = ? + ORDER BY dwr.id ASC + `; + const [rows] = await db.query(sql, [date, worker_id]); + callback(null, rows); + } catch (err) { + console.error('날짜+작업자별 작업보고서 조회 오류:', err); + callback(err); + } +}; + +/** + * 12. 기간별 조회 + */ +const getByRange = async (start_date, end_date, callback) => { + try { + const db = await getDb(); + const sql = getSelectQuery() + ` + WHERE dwr.report_date BETWEEN ? AND ? + ORDER BY dwr.report_date DESC, w.worker_name ASC, dwr.id ASC + `; + const [rows] = await db.query(sql, [start_date, end_date]); + callback(null, rows); + } catch (err) { + console.error('기간별 작업보고서 조회 오류:', err); + callback(err); + } +}; + +/** + * 13. 상세 검색 (페이지네이션 포함) + */ +const searchWithDetails = async (params, callback) => { + const { start_date, end_date, worker_id, project_id, work_status_id, created_by, page, limit } = params; + + try { + const db = await getDb(); + + // 조건 구성 + let whereConditions = ['dwr.report_date BETWEEN ? AND ?']; + let queryParams = [start_date, end_date]; + + if (worker_id) { + whereConditions.push('dwr.worker_id = ?'); + queryParams.push(worker_id); + } + + if (project_id) { + whereConditions.push('dwr.project_id = ?'); + queryParams.push(project_id); + } + + if (work_status_id) { + whereConditions.push('dwr.work_status_id = ?'); + queryParams.push(work_status_id); + } + + if (created_by) { + whereConditions.push('dwr.created_by = ?'); + queryParams.push(created_by); + } + + const whereClause = whereConditions.join(' AND '); + + // 총 개수 조회 + const countQuery = ` + SELECT COUNT(*) as total + FROM daily_work_reports dwr + WHERE ${whereClause} + `; + const [countResult] = await db.query(countQuery, queryParams); + const total = countResult[0].total; + + // 데이터 조회 (JOIN 포함) + const offset = (page - 1) * limit; + const dataQuery = getSelectQuery() + ` + WHERE ${whereClause} + ORDER BY dwr.report_date DESC, w.worker_name ASC, dwr.created_at DESC + LIMIT ? OFFSET ? + `; + + const dataParams = [...queryParams, limit, offset]; + const [rows] = await db.query(dataQuery, dataParams); + + callback(null, { reports: rows, total }); + } catch (err) { + console.error('상세 검색 오류:', err); + callback(err); + } +}; + +/** + * 14. 일일 근무 요약 조회 (날짜별) + */ +const getSummaryByDate = async (date, callback) => { + try { + const db = await getDb(); + + const sql = ` + SELECT + dwr.worker_id, + w.worker_name, + dwr.report_date, + SUM(dwr.work_hours) as total_hours, + COUNT(*) as work_entries_count, + SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as error_count + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.report_date = ? + GROUP BY dwr.worker_id, dwr.report_date + ORDER BY w.worker_name ASC + `; + const [rows] = await db.query(sql, [date]); + callback(null, rows); + } catch (err) { + console.error('일일 근무 요약 조회 오류:', err); + callback(err); + } +}; + +/** + * 15. 일일 근무 요약 조회 (작업자별) + */ +const getSummaryByWorker = async (worker_id, callback) => { + try { + const db = await getDb(); + + const sql = ` + SELECT + dwr.report_date, + dwr.worker_id, + w.worker_name, + SUM(dwr.work_hours) as total_hours, + COUNT(*) as work_entries_count, + SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as error_count + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.worker_id = ? + GROUP BY dwr.report_date, dwr.worker_id + ORDER BY dwr.report_date DESC + `; + const [rows] = await db.query(sql, [worker_id]); + callback(null, rows); + } catch (err) { + console.error('작업자별 근무 요약 조회 오류:', err); + callback(err); + } +}; + +/** + * 16. 월간 요약 + */ +const getMonthlySummary = async (year, month, callback) => { + try { + const db = await getDb(); + const start = `${year.padStart(4, '0')}-${month.padStart(2, '0')}-01`; + const end = `${year.padStart(4, '0')}-${month.padStart(2, '0')}-31`; + + const sql = ` + SELECT + dwr.report_date, + dwr.worker_id, + w.worker_name, + SUM(dwr.work_hours) as total_work_hours, + COUNT(DISTINCT dwr.project_id) as project_count, + COUNT(*) as work_entries_count, + SUM(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as error_count, + GROUP_CONCAT(DISTINCT p.project_name ORDER BY p.project_name) as projects, + GROUP_CONCAT(DISTINCT wt.name ORDER BY wt.name) as work_types + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN projects p ON dwr.project_id = p.project_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + WHERE dwr.report_date BETWEEN ? AND ? + GROUP BY dwr.report_date, dwr.worker_id + ORDER BY dwr.report_date DESC, w.worker_name ASC + `; + const [rows] = await db.query(sql, [start, end]); + callback(null, rows); + } catch (err) { + console.error('월간 요약 조회 오류:', err); + callback(err); + } +}; + +/** + * 17. 작업보고서 수정 + */ +const updateById = async (id, updateData, callback) => { + try { + const db = await getDb(); + + const setFields = []; + const values = []; + + if (updateData.work_hours !== undefined) { + setFields.push('work_hours = ?'); + values.push(updateData.work_hours); + } + + if (updateData.work_status_id !== undefined) { + setFields.push('work_status_id = ?'); + values.push(updateData.work_status_id); + } + + if (updateData.error_type_id !== undefined) { + setFields.push('error_type_id = ?'); + values.push(updateData.error_type_id); + } + + if (updateData.project_id !== undefined) { + setFields.push('project_id = ?'); + values.push(updateData.project_id); + } + + if (updateData.work_type_id !== undefined) { + setFields.push('work_type_id = ?'); + values.push(updateData.work_type_id); + } + + setFields.push('updated_at = NOW()'); + + if (updateData.updated_by) { + setFields.push('updated_by = ?'); + values.push(updateData.updated_by); + } + + values.push(id); + + const sql = `UPDATE daily_work_reports SET ${setFields.join(', ')} WHERE id = ?`; + const [result] = await db.query(sql, values); + + + + // [Sync] 근태 기록 동기화 + try { + const [targetReport] = await db.query('SELECT worker_id, report_date FROM daily_work_reports WHERE id = ?', [id]); + if (targetReport.length > 0) { + const { worker_id, report_date } = targetReport[0]; + const AttendanceModel = require('./attendanceModel'); + await AttendanceModel.syncWithWorkReports(worker_id, report_date); + } + } catch (syncErr) { + console.error('근태 기록 동기화 실패 (Update):', syncErr); + } + + callback(null, result.affectedRows); + } catch (err) { + console.error('작업보고서 수정 오류:', err); + callback(err); + } +}; + +/** + * 18. 특정 작업보고서 삭제 + */ +const removeById = async (id, deletedBy, callback) => { + const db = await getDb(); + const conn = await db.getConnection(); + + try { + await conn.beginTransaction(); + + // 삭제 전 정보 저장 (감사 로그용) + const [reportInfo] = await conn.query('SELECT * FROM daily_work_reports WHERE id = ?', [id]); + + // 작업보고서 삭제 + const [result] = await conn.query('DELETE FROM daily_work_reports WHERE id = ?', [id]); + + // 감사 로그 추가 + if (reportInfo.length > 0 && deletedBy) { + try { + await conn.query( + `INSERT INTO work_report_audit_log + (action, report_id, old_values, changed_by, change_reason, created_at) + VALUES ('DELETE', ?, ?, ?, 'Manual deletion', NOW())`, + [id, JSON.stringify(reportInfo[0]), deletedBy] + ); + } catch (auditErr) { + console.warn('감사 로그 추가 실패:', auditErr.message); + } + } + + await conn.commit(); + + + // [Sync] 근태 기록 동기화 + if (reportInfo.length > 0) { + try { + const { worker_id, report_date } = reportInfo[0]; + const AttendanceModel = require('./attendanceModel'); + await AttendanceModel.syncWithWorkReports(worker_id, report_date); + } catch (syncErr) { + console.error('근태 기록 동기화 실패 (Delete):', syncErr); + } + } + + callback(null, result.affectedRows); + } catch (err) { + await conn.rollback(); + console.error('작업보고서 삭제 오류:', err); + callback(err); + } finally { + conn.release(); + } +}; + +/** + * 19. 작업자의 특정 날짜 전체 삭제 + */ +const removeByDateAndWorker = async (date, worker_id, deletedBy, callback) => { + const db = await getDb(); + const conn = await db.getConnection(); + + try { + await conn.beginTransaction(); + + // 삭제 전 정보 저장 (감사 로그용) + const [reportInfos] = await conn.query( + 'SELECT id, report_date, worker_id, project_id, work_type_id, work_status_id, error_type_id, work_hours, created_at, updated_at, created_by, updated_by FROM daily_work_reports WHERE report_date = ? AND worker_id = ?', + [date, worker_id] + ); + + // 작업보고서 삭제 + const [result] = await conn.query( + 'DELETE FROM daily_work_reports WHERE report_date = ? AND worker_id = ?', + [date, worker_id] + ); + + // 감사 로그 추가 + if (reportInfos.length > 0 && deletedBy) { + try { + await conn.query( + `INSERT INTO work_report_audit_log + (action, old_values, changed_by, change_reason, created_at) + VALUES ('DELETE_BATCH', ?, ?, 'Batch deletion by date and worker', NOW())`, + [JSON.stringify({ deleted_reports: reportInfos, count: reportInfos.length }), deletedBy] + ); + } catch (auditErr) { + console.warn('감사 로그 추가 실패:', auditErr.message); + } + } + + await conn.commit(); + + + // [Sync] 근태 기록 동기화 + try { + const AttendanceModel = require('./attendanceModel'); + await AttendanceModel.syncWithWorkReports(worker_id, date); + } catch (syncErr) { + console.error('근태 기록 동기화 실패 (Batch Delete):', syncErr); + } + + callback(null, result.affectedRows); + } catch (err) { + await conn.rollback(); + console.error('작업보고서 전체 삭제 오류:', err); + callback(err); + } finally { + conn.release(); + } +}; + +/** + * 20. 통계 조회 (Promise 기반) + */ +const getStatistics = async (start_date, end_date) => { + try { + const db = await getDb(); + + const overallSql = ` + SELECT + COUNT(*) as total_reports, + SUM(work_hours) as total_hours, + COUNT(DISTINCT worker_id) as unique_workers, + COUNT(DISTINCT project_id) as unique_projects + FROM daily_work_reports + WHERE report_date BETWEEN ? AND ? + `; + const [overallRows] = await db.query(overallSql, [start_date, end_date]); + + const dailyStatsSql = ` + SELECT + report_date, + SUM(work_hours) as daily_hours, + COUNT(DISTINCT worker_id) as daily_workers + FROM daily_work_reports + WHERE report_date BETWEEN ? AND ? + GROUP BY report_date + ORDER BY report_date DESC + `; + const [dailyStats] = await db.query(dailyStatsSql, [start_date, end_date]); + + return { + overall: overallRows[0], + daily_breakdown: dailyStats + }; + } catch (err) { + console.error('통계 조회 오류:', err); + throw new Error('데이터베이스에서 통계 정보를 조회하는 중 오류가 발생했습니다.'); + } +}; + +/** + * [V2] 여러 작업 보고서 항목을 트랜잭션으로 생성합니다. (Promise 기반) + * @param {object} modelData - 서비스 레이어에서 전달된 데이터 + * @returns {Promise} 삽입된 항목의 ID 배열과 개수 + */ +const createReportEntries = async ({ report_date, worker_id, entries }) => { + const db = await getDb(); + const conn = await db.getConnection(); + try { + await conn.beginTransaction(); + + const insertedIds = []; + const sql = ` + INSERT INTO daily_work_reports + (report_date, worker_id, project_id, work_type_id, work_hours, work_status_id, error_type_id, created_by) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + `; + + for (const entry of entries) { + const { project_id, work_type_id, work_hours, work_status_id, error_type_id, created_by } = entry; + const [result] = await conn.query(sql, [ + report_date, + worker_id, + project_id, + work_type_id, + work_hours, + work_status_id || 1, + error_type_id, + created_by + ]); + insertedIds.push(result.insertId); + } + + await conn.commit(); + + + + // [Sync] 근태 기록 동기화 + try { + const AttendanceModel = require('./attendanceModel'); + await AttendanceModel.syncWithWorkReports(worker_id, report_date); + } catch (syncErr) { + console.error('근태 기록 동기화 실패 (V2 Create):', syncErr); + } + + console.log(`[Model] ${insertedIds.length}개 작업 항목 생성 완료.`); + return { + inserted_ids: insertedIds, + inserted_count: insertedIds.length + }; + + } catch (err) { + await conn.rollback(); + console.error('[Model] 작업 보고서 생성 중 오류 발생:', err); + // 여기서 발생한 에러는 서비스 레이어로 전파됩니다. + throw new Error('데이터베이스에 작업 보고서를 생성하는 중 오류가 발생했습니다.'); + } finally { + conn.release(); + } +}; + +/** + * [V2] 공통 SELECT 쿼리 (새로운 스키마 기준) + * 주의: work_type_id 컬럼에는 실제로 task_id가 저장됨 + * error_type_id는 issue_report_items 테이블 참조 (issue-categories.html에서 관리) + */ +const getSelectQueryV2 = () => ` + SELECT + dwr.id, + dwr.report_date, + dwr.worker_id, + dwr.project_id, + dwr.work_type_id, + dwr.work_status_id, + dwr.error_type_id, + dwr.work_hours, + dwr.created_by, + w.worker_name, + p.project_name, + t.task_name, + wt.name as work_type_name, + wst.name as work_status_name, + iri.item_name as error_type_name, + irc.category_name as error_category_name, + u.name as created_by_name, + dwr.created_at + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN projects p ON dwr.project_id = p.project_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN work_status_types wst ON dwr.work_status_id = wst.id + LEFT JOIN issue_report_items iri ON dwr.error_type_id = iri.item_id + LEFT JOIN issue_report_categories irc ON iri.category_id = irc.category_id + LEFT JOIN users u ON dwr.created_by = u.user_id +`; + +/** + * [V2] 옵션 기반으로 작업 보고서를 조회합니다. (Promise 기반) + * @param {object} options - 조회 조건 (date, worker_id, created_by_user_id 등) + * @returns {Promise} 조회된 작업 보고서 배열 + */ +const getReportsWithOptions = async (options) => { + const db = await getDb(); + let whereConditions = []; + let queryParams = []; + + // 날짜 조건 처리 (단일 날짜 또는 날짜 범위) + if (options.date) { + whereConditions.push('dwr.report_date = ?'); + queryParams.push(options.date); + } else if (options.start_date && options.end_date) { + whereConditions.push('dwr.report_date BETWEEN ? AND ?'); + queryParams.push(options.start_date, options.end_date); + } + + if (options.worker_id) { + whereConditions.push('dwr.worker_id = ?'); + queryParams.push(options.worker_id); + } + if (options.created_by_user_id) { + whereConditions.push('dwr.created_by = ?'); + queryParams.push(options.created_by_user_id); + } + // 필요에 따라 다른 조건 추가 가능 (project_id 등) + + if (whereConditions.length === 0) { + throw new Error('조회 조건이 하나 이상 필요합니다.'); + } + + const whereClause = whereConditions.join(' AND '); + const sql = `${getSelectQueryV2()} WHERE ${whereClause} ORDER BY w.worker_name ASC, p.project_name ASC`; + + try { + const [rows] = await db.query(sql, queryParams); + return rows; + } catch (err) { + console.error('[Model] 작업 보고서 조회 오류:', err); + throw new Error('데이터베이스에서 작업 보고서를 조회하는 중 오류가 발생했습니다.'); + } +}; + +/** + * [V2] ID를 기준으로 특정 작업 보고서 항목을 수정합니다. (Promise 기반) + * @param {string} reportId - 수정할 보고서의 ID + * @param {object} updateData - 수정할 필드와 값 + * @returns {Promise} 영향을 받은 행의 수 + */ +const updateReportById = async (reportId, updateData) => { + const db = await getDb(); + + // 허용된 필드 목록 (보안 및 안정성) - 실제 테이블 컬럼명 사용 + const allowedFields = ['project_id', 'work_type_id', 'work_hours', 'work_status_id', 'error_type_id']; + const setClauses = []; + const queryParams = []; + + for (const field of allowedFields) { + if (updateData[field] !== undefined) { + setClauses.push(`${field} = ?`); + queryParams.push(updateData[field]); + } + } + + // updated_by는 항상 업데이트 + if (updateData.updated_by_user_id) { + setClauses.push('updated_by = ?'); + queryParams.push(updateData.updated_by_user_id); + } + + if (setClauses.length === 0) { + throw new Error('수정할 데이터가 없습니다.'); + } + + queryParams.push(reportId); + + // [Sync] 업데이트 전 정보 조회 (동기화를 위해) + let targetInfo = null; + try { + const [rows] = await db.query('SELECT worker_id, report_date FROM daily_work_reports WHERE id = ?', [reportId]); + if (rows.length > 0) targetInfo = rows[0]; + } catch (e) { console.warn('Sync fetch failed', e); } + + const sql = `UPDATE daily_work_reports SET ${setClauses.join(', ')} WHERE id = ?`; + + try { + const [result] = await db.query(sql, queryParams); + + // [Sync] 근태 기록 동기화 + if (targetInfo) { + try { + const AttendanceModel = require('./attendanceModel'); + await AttendanceModel.syncWithWorkReports(targetInfo.worker_id, targetInfo.report_date); + } catch (syncErr) { + console.error('근태 기록 동기화 실패 (V2 Update):', syncErr); + } + } + + return result.affectedRows; + } catch (err) { + console.error(`[Model] 작업 보고서 수정 오류 (id: ${reportId}):`, err); + throw new Error('데이터베이스에서 작업 보고서를 수정하는 중 오류가 발생했습니다.'); + } +}; + +/** + * [V2] ID를 기준으로 특정 작업 보고서를 삭제합니다. (Promise 기반) + * @param {string} reportId - 삭제할 보고서 ID + * @param {number} deletedByUserId - 삭제를 수행하는 사용자 ID + * @returns {Promise} 영향을 받은 행의 수 + */ +const removeReportById = async (reportId, deletedByUserId) => { + const db = await getDb(); + const conn = await db.getConnection(); + + try { + await conn.beginTransaction(); + + // 감사 로그를 위해 삭제 전 정보 조회 + const [reportInfo] = await conn.query('SELECT id, report_date, worker_id, project_id, work_type_id, work_status_id, error_type_id, work_hours, created_at, updated_at, created_by, updated_by FROM daily_work_reports WHERE id = ?', [reportId]); + + // 실제 삭제 작업 + const [result] = await conn.query('DELETE FROM daily_work_reports WHERE id = ?', [reportId]); + + // 감사 로그 (삭제된 테이블이므로 콘솔 로그로 대체) + if (reportInfo.length > 0 && deletedByUserId) { + console.log(`[삭제 로그] 보고서 ID: ${reportId}, 삭제자: ${deletedByUserId}, 사유: Manual deletion by user`); + } + + await conn.commit(); + + // [Sync] 근태 기록 동기화 + if (reportInfo.length > 0) { + try { + const { worker_id, report_date } = reportInfo[0]; + const AttendanceModel = require('./attendanceModel'); + await AttendanceModel.syncWithWorkReports(worker_id, report_date); + } catch (syncErr) { + console.error('근태 기록 동기화 실패 (V2 Delete):', syncErr); + } + } + + return result.affectedRows; + + } catch (err) { + await conn.rollback(); + console.error(`[Model] 작업 보고서 삭제 오류 (id: ${reportId}):`, err); + throw new Error('데이터베이스에서 작업 보고서를 삭제하는 중 오류가 발생했습니다.'); + } finally { + conn.release(); + } +}; + +// ========== 마스터 데이터 CRUD 메서드들 ========== + +/** + * 📝 작업 유형 생성 + */ +const createWorkType = async (data, callback) => { + try { + const db = await getDb(); + const { name, description, category } = data; + const [result] = await db.query( + 'INSERT INTO work_types (name, description, category) VALUES (?, ?, ?)', + [name, description, category] + ); + callback(null, { id: result.insertId, ...data }); + } catch (err) { + console.error('작업 유형 생성 오류:', err); + callback(err); + } +}; + +/** + * ✏️ 작업 유형 수정 + */ +const updateWorkType = async (id, data, callback) => { + try { + const db = await getDb(); + const { name, description, category } = data; + const [result] = await db.query( + 'UPDATE work_types SET name = ?, description = ?, category = ? WHERE id = ?', + [name, description, category, id] + ); + callback(null, result); + } catch (err) { + console.error('작업 유형 수정 오류:', err); + callback(err); + } +}; + +/** + * 🗑️ 작업 유형 삭제 + */ +const deleteWorkType = async (id, callback) => { + try { + const db = await getDb(); + const [result] = await db.query('DELETE FROM work_types WHERE id = ?', [id]); + callback(null, result); + } catch (err) { + console.error('작업 유형 삭제 오류:', err); + callback(err); + } +}; + +/** + * 📝 작업 상태 생성 + */ +const createWorkStatus = async (data, callback) => { + try { + const db = await getDb(); + const { name, description, is_error } = data; + const [result] = await db.query( + 'INSERT INTO work_status_types (name, description, is_error) VALUES (?, ?, ?)', + [name, description, is_error || 0] + ); + callback(null, { id: result.insertId, ...data }); + } catch (err) { + console.error('작업 상태 생성 오류:', err); + callback(err); + } +}; + +/** + * ✏️ 작업 상태 수정 + */ +const updateWorkStatus = async (id, data, callback) => { + try { + const db = await getDb(); + const { name, description, is_error } = data; + const [result] = await db.query( + 'UPDATE work_status_types SET name = ?, description = ?, is_error = ? WHERE id = ?', + [name, description, is_error || 0, id] + ); + callback(null, result); + } catch (err) { + console.error('작업 상태 수정 오류:', err); + callback(err); + } +}; + +/** + * 🗑️ 작업 상태 삭제 + */ +const deleteWorkStatus = async (id, callback) => { + try { + const db = await getDb(); + const [result] = await db.query('DELETE FROM work_status_types WHERE id = ?', [id]); + callback(null, result); + } catch (err) { + console.error('작업 상태 삭제 오류:', err); + callback(err); + } +}; + +/** + * 📝 오류 유형 생성 + */ +const createErrorType = async (data, callback) => { + try { + const db = await getDb(); + const { name, description, severity } = data; + const [result] = await db.query( + 'INSERT INTO error_types (name, description, severity) VALUES (?, ?, ?)', + [name, description, severity || 'medium'] + ); + callback(null, { id: result.insertId, ...data }); + } catch (err) { + console.error('오류 유형 생성 오류:', err); + callback(err); + } +}; + +/** + * ✏️ 오류 유형 수정 + */ +const updateErrorType = async (id, data, callback) => { + try { + const db = await getDb(); + const { name, description, severity } = data; + const [result] = await db.query( + 'UPDATE error_types SET name = ?, description = ?, severity = ? WHERE id = ?', + [name, description, severity || 'medium', id] + ); + callback(null, result); + } catch (err) { + console.error('오류 유형 수정 오류:', err); + callback(err); + } +}; + +/** + * 🗑️ 오류 유형 삭제 + */ +const deleteErrorType = async (id, callback) => { + try { + const db = await getDb(); + const [result] = await db.query('DELETE FROM error_types WHERE id = ?', [id]); + callback(null, result); + } catch (err) { + console.error('오류 유형 삭제 오류:', err); + callback(err); + } +}; + + +/** + * TBM 기반 작업보고서 생성 및 TBM 세션 완료 처리 + * @param {object} reportData - TBM 작업보고서 데이터 + * @returns {Promise} 생성 결과 + */ +const createFromTbmAssignment = async (reportData) => { + const { + tbm_assignment_id, + tbm_session_id, + worker_id, + project_id, + work_type_id, + report_date, + start_time, + end_time, + total_hours, + error_hours, + regular_hours, + work_status_id, + error_type_id, + created_by + } = reportData; + + const db = await getDb(); + const conn = await db.getConnection(); + + try { + await conn.beginTransaction(); + + // 1. 작업보고서 생성 + const sql = ` + INSERT INTO daily_work_reports + (tbm_session_id, tbm_assignment_id, report_date, worker_id, project_id, work_type_id, + start_time, end_time, work_hours, total_hours, regular_hours, error_hours, + work_status_id, error_type_id, created_by, created_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, NOW()) + `; + + const [result] = await conn.query(sql, [ + tbm_session_id, + tbm_assignment_id, + report_date, + worker_id, + project_id, + work_type_id, + start_time || null, + end_time || null, + total_hours, // work_hours는 TBM에서 total_hours와 동일 + total_hours, + regular_hours, + error_hours || 0, + work_status_id || 1, + error_type_id || null, + created_by + ]); + + const reportId = result.insertId; + + // 2. TBM 세션의 모든 팀 배정이 작업보고서를 제출했는지 확인 + const [assignmentCheck] = await conn.query(` + SELECT + COUNT(*) as total_assignments, + COUNT(dwr.tbm_assignment_id) as completed_assignments + FROM tbm_team_assignments ta + LEFT JOIN daily_work_reports dwr ON ta.assignment_id = dwr.tbm_assignment_id + WHERE ta.session_id = ? + `, [tbm_session_id]); + + const { total_assignments, completed_assignments } = assignmentCheck[0]; + + // 3. 모든 팀원이 작업보고서를 제출했으면 TBM 세션을 완료로 표시 + if (total_assignments === completed_assignments) { + await conn.query(` + UPDATE tbm_sessions + SET status = 'completed', updated_at = NOW() + WHERE session_id = ? + `, [tbm_session_id]); + } + + await conn.commit(); + + // 4. 근태 기록 동기화 + try { + const AttendanceModel = require('./attendanceModel'); + await AttendanceModel.syncWithWorkReports(worker_id, report_date); + } catch (syncErr) { + console.error('근태 기록 동기화 실패 (TBM Report):', syncErr); + } + + console.log(`[Model] TBM 작업보고서 생성 완료: report_id=${reportId}, session=${tbm_session_id}, assignment=${tbm_assignment_id}`); + + return { + success: true, + report_id: reportId, + tbm_completed: total_assignments === completed_assignments, + completion_status: `${completed_assignments}/${total_assignments} 작업 완료` + }; + + } catch (err) { + await conn.rollback(); + console.error('[Model] TBM 작업보고서 생성 중 오류 발생:', err); + throw new Error('TBM 작업보고서 생성 중 오류가 발생했습니다.'); + } finally { + conn.release(); + } +}; + +// 모든 함수 내보내기 (Promise 기반 함수 위주로 재구성) +module.exports = { + // 새로 추가된 V2 함수 (Promise 기반) + createReportEntries, + getReportsWithOptions, + updateReportById, + removeReportById, + createFromTbmAssignment, + + // Promise 기반으로 리팩토링된 함수 + getStatistics, + getSummaryByDate, + getSummaryByWorker, + + // 아직 리팩토링되지 않았지만 필요한 기존 함수들... + // (점진적으로 아래 함수들도 Promise 기반으로 전환해야 함) + getAllWorkTypes, + getAllWorkStatusTypes, + getAllErrorTypes, + + // 마스터 데이터 CRUD + createWorkType, + updateWorkType, + deleteWorkType, + createWorkStatus, + updateWorkStatus, + deleteWorkStatus, + createErrorType, + updateErrorType, + deleteErrorType, + createDailyReport, + getMyAccumulatedHours, + getAccumulatedReportsByDate, + getContributorsByDate, + removeSpecificEntry, + getById, + getByDate, + getByDateAndCreator, + getByWorker, + getByDateAndWorker, + getByRange, + searchWithDetails, + getMonthlySummary, + updateById, + removeById, + removeByDateAndWorker, +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/models/departmentModel.js b/deploy/tkfb-package/api.hyungi.net/models/departmentModel.js new file mode 100644 index 0000000..e9c329b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/departmentModel.js @@ -0,0 +1,120 @@ +// models/departmentModel.js +const { getDb } = require('../dbPool'); + +const departmentModel = { + // 모든 부서 조회 (계층 구조 포함) + async getAll() { + const db = await getDb(); + const [rows] = await db.query(` + SELECT d.*, + p.department_name as parent_name, + (SELECT COUNT(*) FROM workers w WHERE w.department_id = d.department_id AND w.status = 'active') as worker_count + FROM departments d + LEFT JOIN departments p ON d.parent_id = p.department_id + ORDER BY d.display_order, d.department_name + `); + return rows; + }, + + // 활성 부서만 조회 + async getActive() { + const db = await getDb(); + const [rows] = await db.query(` + SELECT d.*, + p.department_name as parent_name, + (SELECT COUNT(*) FROM workers w WHERE w.department_id = d.department_id AND w.status = 'active') as worker_count + FROM departments d + LEFT JOIN departments p ON d.parent_id = p.department_id + WHERE d.is_active = TRUE + ORDER BY d.display_order, d.department_name + `); + return rows; + }, + + // 부서 ID로 조회 + async getById(departmentId) { + const db = await getDb(); + const [rows] = await db.query(` + SELECT d.*, + p.department_name as parent_name + FROM departments d + LEFT JOIN departments p ON d.parent_id = p.department_id + WHERE d.department_id = ? + `, [departmentId]); + return rows[0]; + }, + + // 부서 생성 + async create(data) { + const db = await getDb(); + const { department_name, parent_id, description, is_active, display_order } = data; + const [result] = await db.query(` + INSERT INTO departments (department_name, parent_id, description, is_active, display_order) + VALUES (?, ?, ?, ?, ?) + `, [department_name, parent_id || null, description || null, is_active !== false, display_order || 0]); + return result.insertId; + }, + + // 부서 수정 + async update(departmentId, data) { + const db = await getDb(); + const { department_name, parent_id, description, is_active, display_order } = data; + const [result] = await db.query(` + UPDATE departments + SET department_name = ?, parent_id = ?, description = ?, is_active = ?, display_order = ? + WHERE department_id = ? + `, [department_name, parent_id || null, description || null, is_active, display_order || 0, departmentId]); + return result.affectedRows > 0; + }, + + // 부서 삭제 + async delete(departmentId) { + const db = await getDb(); + // 하위 부서가 있는지 확인 + const [children] = await db.query('SELECT COUNT(*) as count FROM departments WHERE parent_id = ?', [departmentId]); + if (children[0].count > 0) { + throw new Error('하위 부서가 있어 삭제할 수 없습니다.'); + } + // 소속 작업자가 있는지 확인 + const [workers] = await db.query('SELECT COUNT(*) as count FROM workers WHERE department_id = ?', [departmentId]); + if (workers[0].count > 0) { + throw new Error('소속 작업자가 있어 삭제할 수 없습니다. 먼저 작업자를 다른 부서로 이동하세요.'); + } + const [result] = await db.query('DELETE FROM departments WHERE department_id = ?', [departmentId]); + return result.affectedRows > 0; + }, + + // 부서별 작업자 조회 + async getWorkersByDepartment(departmentId) { + const db = await getDb(); + const [rows] = await db.query(` + SELECT w.*, d.department_name, u.user_id, u.username + FROM workers w + LEFT JOIN departments d ON w.department_id = d.department_id + LEFT JOIN users u ON u.worker_id = w.worker_id + WHERE w.department_id = ? + ORDER BY w.worker_name + `, [departmentId]); + return rows; + }, + + // 작업자 부서 변경 + async moveWorker(workerId, departmentId) { + const db = await getDb(); + const [result] = await db.query(` + UPDATE workers SET department_id = ? WHERE worker_id = ? + `, [departmentId, workerId]); + return result.affectedRows > 0; + }, + + // 여러 작업자 부서 일괄 변경 + async moveWorkers(workerIds, departmentId) { + const db = await getDb(); + const [result] = await db.query(` + UPDATE workers SET department_id = ? WHERE worker_id IN (?) + `, [departmentId, workerIds]); + return result.affectedRows; + } +}; + +module.exports = departmentModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/equipmentModel.js b/deploy/tkfb-package/api.hyungi.net/models/equipmentModel.js new file mode 100644 index 0000000..ec0bd15 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/equipmentModel.js @@ -0,0 +1,949 @@ +// models/equipmentModel.js +const { getDb } = require('../dbPool'); +const notificationModel = require('./notificationModel'); + +const EquipmentModel = { + // CREATE - 설비 생성 + create: async (equipmentData, callback) => { + try { + const db = await getDb(); + const query = ` + INSERT INTO equipments ( + equipment_code, equipment_name, equipment_type, model_name, + manufacturer, supplier, purchase_price, installation_date, serial_number, specifications, + status, notes, workplace_id, map_x_percent, map_y_percent, + map_width_percent, map_height_percent + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `; + + const values = [ + equipmentData.equipment_code, + equipmentData.equipment_name, + equipmentData.equipment_type || null, + equipmentData.model_name || null, + equipmentData.manufacturer || null, + equipmentData.supplier || null, + equipmentData.purchase_price || null, + equipmentData.installation_date || null, + equipmentData.serial_number || null, + equipmentData.specifications || null, + equipmentData.status || 'active', + equipmentData.notes || null, + equipmentData.workplace_id || null, + equipmentData.map_x_percent || null, + equipmentData.map_y_percent || null, + equipmentData.map_width_percent || null, + equipmentData.map_height_percent || null + ]; + + const [result] = await db.query(query, values); + callback(null, { + equipment_id: result.insertId, + ...equipmentData + }); + } catch (error) { + callback(error); + } + }, + + // READ ALL - 모든 설비 조회 (필터링 옵션 포함) + getAll: async (filters, callback) => { + try { + const db = await getDb(); + let query = ` + SELECT + e.*, + w.workplace_name, + wc.category_name + FROM equipments e + LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + WHERE 1=1 + `; + + const values = []; + + // 필터링: 작업장 ID + if (filters.workplace_id) { + query += ' AND e.workplace_id = ?'; + values.push(filters.workplace_id); + } + + // 필터링: 설비 유형 + if (filters.equipment_type) { + query += ' AND e.equipment_type = ?'; + values.push(filters.equipment_type); + } + + // 필터링: 상태 + if (filters.status) { + query += ' AND e.status = ?'; + values.push(filters.status); + } + + // 필터링: 검색어 (설비명, 설비코드) + if (filters.search) { + query += ' AND (e.equipment_name LIKE ? OR e.equipment_code LIKE ?)'; + const searchTerm = `%${filters.search}%`; + values.push(searchTerm, searchTerm); + } + + query += ' ORDER BY e.equipment_code ASC'; + + const [rows] = await db.query(query, values); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // READ ONE - 특정 설비 조회 + getById: async (equipmentId, callback) => { + try { + const db = await getDb(); + const query = ` + SELECT + e.*, + w.workplace_name, + wc.category_name + FROM equipments e + LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + WHERE e.equipment_id = ? + `; + + const [rows] = await db.query(query, [equipmentId]); + callback(null, rows[0]); + } catch (error) { + callback(error); + } + }, + + // READ BY WORKPLACE - 특정 작업장의 설비 조회 + getByWorkplace: async (workplaceId, callback) => { + try { + const db = await getDb(); + const query = ` + SELECT e.* + FROM equipments e + WHERE e.workplace_id = ? + ORDER BY e.equipment_code ASC + `; + + const [rows] = await db.query(query, [workplaceId]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // READ ACTIVE - 활성 설비만 조회 + getActive: async (callback) => { + try { + const db = await getDb(); + const query = ` + SELECT + e.*, + w.workplace_name, + wc.category_name + FROM equipments e + LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + WHERE e.status = 'active' + ORDER BY e.equipment_code ASC + `; + + const [rows] = await db.query(query); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // UPDATE - 설비 수정 + update: async (equipmentId, equipmentData, callback) => { + try { + const db = await getDb(); + const query = ` + UPDATE equipments SET + equipment_code = ?, + equipment_name = ?, + equipment_type = ?, + model_name = ?, + manufacturer = ?, + supplier = ?, + purchase_price = ?, + installation_date = ?, + serial_number = ?, + specifications = ?, + status = ?, + notes = ?, + workplace_id = ?, + map_x_percent = ?, + map_y_percent = ?, + map_width_percent = ?, + map_height_percent = ?, + updated_at = NOW() + WHERE equipment_id = ? + `; + + const values = [ + equipmentData.equipment_code, + equipmentData.equipment_name, + equipmentData.equipment_type || null, + equipmentData.model_name || null, + equipmentData.manufacturer || null, + equipmentData.supplier || null, + equipmentData.purchase_price || null, + equipmentData.installation_date || null, + equipmentData.serial_number || null, + equipmentData.specifications || null, + equipmentData.status || 'active', + equipmentData.notes || null, + equipmentData.workplace_id || null, + equipmentData.map_x_percent || null, + equipmentData.map_y_percent || null, + equipmentData.map_width_percent || null, + equipmentData.map_height_percent || null, + equipmentId + ]; + + const [result] = await db.query(query, values); + if (result.affectedRows === 0) { + return callback(new Error('Equipment not found')); + } + callback(null, { equipment_id: equipmentId, ...equipmentData }); + } catch (error) { + callback(error); + } + }, + + // UPDATE MAP POSITION - 지도상 위치 업데이트 (선택적으로 workplace_id도 업데이트) + updateMapPosition: async (equipmentId, positionData, callback) => { + try { + const db = await getDb(); + + // workplace_id가 포함된 경우 함께 업데이트 + const hasWorkplaceId = positionData.workplace_id !== undefined; + + const query = hasWorkplaceId ? ` + UPDATE equipments SET + workplace_id = ?, + map_x_percent = ?, + map_y_percent = ?, + map_width_percent = ?, + map_height_percent = ?, + updated_at = NOW() + WHERE equipment_id = ? + ` : ` + UPDATE equipments SET + map_x_percent = ?, + map_y_percent = ?, + map_width_percent = ?, + map_height_percent = ?, + updated_at = NOW() + WHERE equipment_id = ? + `; + + const values = hasWorkplaceId ? [ + positionData.workplace_id, + positionData.map_x_percent, + positionData.map_y_percent, + positionData.map_width_percent, + positionData.map_height_percent, + equipmentId + ] : [ + positionData.map_x_percent, + positionData.map_y_percent, + positionData.map_width_percent, + positionData.map_height_percent, + equipmentId + ]; + + const [result] = await db.query(query, values); + if (result.affectedRows === 0) { + return callback(new Error('Equipment not found')); + } + callback(null, { equipment_id: equipmentId, ...positionData }); + } catch (error) { + callback(error); + } + }, + + // DELETE - 설비 삭제 + delete: async (equipmentId, callback) => { + try { + const db = await getDb(); + const query = 'DELETE FROM equipments WHERE equipment_id = ?'; + + const [result] = await db.query(query, [equipmentId]); + if (result.affectedRows === 0) { + return callback(new Error('Equipment not found')); + } + callback(null, { equipment_id: equipmentId }); + } catch (error) { + callback(error); + } + }, + + // CHECK DUPLICATE CODE - 설비 코드 중복 확인 + checkDuplicateCode: async (equipmentCode, excludeEquipmentId, callback) => { + try { + const db = await getDb(); + let query = 'SELECT equipment_id FROM equipments WHERE equipment_code = ?'; + const values = [equipmentCode]; + + if (excludeEquipmentId) { + query += ' AND equipment_id != ?'; + values.push(excludeEquipmentId); + } + + const [rows] = await db.query(query, values); + callback(null, rows.length > 0); + } catch (error) { + callback(error); + } + }, + + // GET EQUIPMENT TYPES - 사용 중인 설비 유형 목록 조회 + getEquipmentTypes: async (callback) => { + try { + const db = await getDb(); + const query = ` + SELECT DISTINCT equipment_type + FROM equipments + WHERE equipment_type IS NOT NULL + ORDER BY equipment_type ASC + `; + + const [rows] = await db.query(query); + callback(null, rows.map(row => row.equipment_type)); + } catch (error) { + callback(error); + } + }, + + // GET NEXT EQUIPMENT CODE - 다음 관리번호 자동 생성 (TKP-001 형식) + getNextEquipmentCode: async (prefix = 'TKP', callback) => { + try { + const db = await getDb(); + // 해당 접두사로 시작하는 가장 큰 번호 찾기 + const query = ` + SELECT equipment_code + FROM equipments + WHERE equipment_code LIKE ? + ORDER BY equipment_code DESC + LIMIT 1 + `; + + const [rows] = await db.query(query, [`${prefix}-%`]); + + let nextNumber = 1; + if (rows.length > 0) { + // TKP-001 형식에서 숫자 부분 추출 + const lastCode = rows[0].equipment_code; + const match = lastCode.match(new RegExp(`^${prefix}-(\\d+)$`)); + if (match) { + nextNumber = parseInt(match[1], 10) + 1; + } + } + + // 3자리로 패딩 (001, 002, ...) + const nextCode = `${prefix}-${String(nextNumber).padStart(3, '0')}`; + callback(null, nextCode); + } catch (error) { + callback(error); + } + }, + + // ========================================== + // 설비 사진 관리 + // ========================================== + + // ADD PHOTO - 설비 사진 추가 + addPhoto: async (equipmentId, photoData, callback) => { + try { + const db = await getDb(); + const query = ` + INSERT INTO equipment_photos ( + equipment_id, photo_path, description, display_order, uploaded_by + ) VALUES (?, ?, ?, ?, ?) + `; + + const values = [ + equipmentId, + photoData.photo_path, + photoData.description || null, + photoData.display_order || 0, + photoData.uploaded_by || null + ]; + + const [result] = await db.query(query, values); + callback(null, { + photo_id: result.insertId, + equipment_id: equipmentId, + ...photoData + }); + } catch (error) { + callback(error); + } + }, + + // GET PHOTOS - 설비 사진 조회 + getPhotos: async (equipmentId, callback) => { + try { + const db = await getDb(); + const query = ` + SELECT ep.*, u.name AS uploaded_by_name + FROM equipment_photos ep + LEFT JOIN users u ON ep.uploaded_by = u.user_id + WHERE ep.equipment_id = ? + ORDER BY ep.display_order ASC, ep.created_at ASC + `; + + const [rows] = await db.query(query, [equipmentId]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // DELETE PHOTO - 설비 사진 삭제 + deletePhoto: async (photoId, callback) => { + try { + const db = await getDb(); + + // 먼저 사진 정보 조회 (파일 삭제용) + const [photo] = await db.query( + 'SELECT photo_path FROM equipment_photos WHERE photo_id = ?', + [photoId] + ); + + const query = 'DELETE FROM equipment_photos WHERE photo_id = ?'; + const [result] = await db.query(query, [photoId]); + + if (result.affectedRows === 0) { + return callback(new Error('Photo not found')); + } + + callback(null, { photo_id: photoId, photo_path: photo[0]?.photo_path }); + } catch (error) { + callback(error); + } + }, + + // ========================================== + // 설비 임시 이동 + // ========================================== + + // MOVE TEMPORARILY - 설비 임시 이동 + moveTemporarily: async (equipmentId, moveData, callback) => { + try { + const db = await getDb(); + + // 1. 설비 현재 위치 업데이트 + const updateQuery = ` + UPDATE equipments SET + current_workplace_id = ?, + current_map_x_percent = ?, + current_map_y_percent = ?, + current_map_width_percent = ?, + current_map_height_percent = ?, + is_temporarily_moved = TRUE, + moved_at = NOW(), + moved_by = ?, + updated_at = NOW() + WHERE equipment_id = ? + `; + + const updateValues = [ + moveData.target_workplace_id, + moveData.target_x_percent, + moveData.target_y_percent, + moveData.target_width_percent || null, + moveData.target_height_percent || null, + moveData.moved_by || null, + equipmentId + ]; + + const [result] = await db.query(updateQuery, updateValues); + + if (result.affectedRows === 0) { + return callback(new Error('Equipment not found')); + } + + // 2. 이동 이력 기록 + const logQuery = ` + INSERT INTO equipment_move_logs ( + equipment_id, move_type, + from_workplace_id, to_workplace_id, + from_x_percent, from_y_percent, + to_x_percent, to_y_percent, + reason, moved_by + ) VALUES (?, 'temporary', ?, ?, ?, ?, ?, ?, ?, ?) + `; + + await db.query(logQuery, [ + equipmentId, + moveData.from_workplace_id || null, + moveData.target_workplace_id, + moveData.from_x_percent || null, + moveData.from_y_percent || null, + moveData.target_x_percent, + moveData.target_y_percent, + moveData.reason || null, + moveData.moved_by || null + ]); + + callback(null, { equipment_id: equipmentId, moved: true }); + } catch (error) { + callback(error); + } + }, + + // RETURN TO ORIGINAL - 설비 원위치 복귀 + returnToOriginal: async (equipmentId, userId, callback) => { + try { + const db = await getDb(); + + // 1. 현재 임시 위치 정보 조회 + const [equipment] = await db.query( + 'SELECT current_workplace_id, current_map_x_percent, current_map_y_percent FROM equipments WHERE equipment_id = ?', + [equipmentId] + ); + + if (!equipment[0]) { + return callback(new Error('Equipment not found')); + } + + // 2. 임시 위치 필드 초기화 + const updateQuery = ` + UPDATE equipments SET + current_workplace_id = NULL, + current_map_x_percent = NULL, + current_map_y_percent = NULL, + current_map_width_percent = NULL, + current_map_height_percent = NULL, + is_temporarily_moved = FALSE, + moved_at = NULL, + moved_by = NULL, + updated_at = NOW() + WHERE equipment_id = ? + `; + + await db.query(updateQuery, [equipmentId]); + + // 3. 복귀 이력 기록 + const logQuery = ` + INSERT INTO equipment_move_logs ( + equipment_id, move_type, + from_workplace_id, from_x_percent, from_y_percent, + reason, moved_by + ) VALUES (?, 'return', ?, ?, ?, '원위치 복귀', ?) + `; + + await db.query(logQuery, [ + equipmentId, + equipment[0].current_workplace_id, + equipment[0].current_map_x_percent, + equipment[0].current_map_y_percent, + userId || null + ]); + + callback(null, { equipment_id: equipmentId, returned: true }); + } catch (error) { + callback(error); + } + }, + + // GET TEMPORARILY MOVED - 임시 이동된 설비 목록 + getTemporarilyMoved: async (callback) => { + try { + const db = await getDb(); + const query = ` + SELECT + e.*, + w_orig.workplace_name AS original_workplace_name, + w_curr.workplace_name AS current_workplace_name, + u.name AS moved_by_name + FROM equipments e + LEFT JOIN workplaces w_orig ON e.workplace_id = w_orig.workplace_id + LEFT JOIN workplaces w_curr ON e.current_workplace_id = w_curr.workplace_id + LEFT JOIN users u ON e.moved_by = u.user_id + WHERE e.is_temporarily_moved = TRUE + ORDER BY e.moved_at DESC + `; + + const [rows] = await db.query(query); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // GET MOVE LOGS - 설비 이동 이력 조회 + getMoveLogs: async (equipmentId, callback) => { + try { + const db = await getDb(); + const query = ` + SELECT + eml.*, + w_from.workplace_name AS from_workplace_name, + w_to.workplace_name AS to_workplace_name, + u.name AS moved_by_name + FROM equipment_move_logs eml + LEFT JOIN workplaces w_from ON eml.from_workplace_id = w_from.workplace_id + LEFT JOIN workplaces w_to ON eml.to_workplace_id = w_to.workplace_id + LEFT JOIN users u ON eml.moved_by = u.user_id + WHERE eml.equipment_id = ? + ORDER BY eml.moved_at DESC + `; + + const [rows] = await db.query(query, [equipmentId]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // ========================================== + // 설비 외부 반출/반입 + // ========================================== + + // EXPORT EQUIPMENT - 설비 외부 반출 + exportEquipment: async (exportData, callback) => { + try { + const db = await getDb(); + + // 1. 반출 로그 생성 + const logQuery = ` + INSERT INTO equipment_external_logs ( + equipment_id, log_type, export_date, expected_return_date, + destination, reason, notes, exported_by + ) VALUES (?, 'export', ?, ?, ?, ?, ?, ?) + `; + + const logValues = [ + exportData.equipment_id, + exportData.export_date || new Date().toISOString().slice(0, 10), + exportData.expected_return_date || null, + exportData.destination || null, + exportData.reason || null, + exportData.notes || null, + exportData.exported_by || null + ]; + + const [logResult] = await db.query(logQuery, logValues); + + // 2. 설비 상태 업데이트 + const status = exportData.is_repair ? 'repair_external' : 'external'; + await db.query( + 'UPDATE equipments SET status = ?, updated_at = NOW() WHERE equipment_id = ?', + [status, exportData.equipment_id] + ); + + callback(null, { + log_id: logResult.insertId, + equipment_id: exportData.equipment_id, + exported: true + }); + } catch (error) { + callback(error); + } + }, + + // RETURN EQUIPMENT - 설비 반입 (외부에서 복귀) + returnEquipment: async (logId, returnData, callback) => { + try { + const db = await getDb(); + + // 1. 반출 로그 조회 + const [logs] = await db.query( + 'SELECT equipment_id FROM equipment_external_logs WHERE log_id = ?', + [logId] + ); + + if (!logs[0]) { + return callback(new Error('Export log not found')); + } + + const equipmentId = logs[0].equipment_id; + + // 2. 반출 로그 업데이트 + await db.query( + `UPDATE equipment_external_logs SET + actual_return_date = ?, + returned_by = ?, + notes = CONCAT(IFNULL(notes, ''), '\n반입: ', IFNULL(?, '')), + updated_at = NOW() + WHERE log_id = ?`, + [ + returnData.return_date || new Date().toISOString().slice(0, 10), + returnData.returned_by || null, + returnData.notes || '', + logId + ] + ); + + // 3. 설비 상태 복원 + await db.query( + 'UPDATE equipments SET status = ?, updated_at = NOW() WHERE equipment_id = ?', + [returnData.new_status || 'active', equipmentId] + ); + + callback(null, { + log_id: logId, + equipment_id: equipmentId, + returned: true + }); + } catch (error) { + callback(error); + } + }, + + // GET EXTERNAL LOGS - 설비 외부 반출 이력 조회 + getExternalLogs: async (equipmentId, callback) => { + try { + const db = await getDb(); + const query = ` + SELECT + eel.*, + u_exp.name AS exported_by_name, + u_ret.name AS returned_by_name + FROM equipment_external_logs eel + LEFT JOIN users u_exp ON eel.exported_by = u_exp.user_id + LEFT JOIN users u_ret ON eel.returned_by = u_ret.user_id + WHERE eel.equipment_id = ? + ORDER BY eel.created_at DESC + `; + + const [rows] = await db.query(query, [equipmentId]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // GET EXPORTED EQUIPMENTS - 현재 외부 반출 중인 설비 목록 + getExportedEquipments: async (callback) => { + try { + const db = await getDb(); + const query = ` + SELECT + e.*, + w.workplace_name, + eel.export_date, + eel.expected_return_date, + eel.destination, + eel.reason, + u.name AS exported_by_name + FROM equipments e + INNER JOIN ( + SELECT equipment_id, MAX(log_id) AS latest_log_id + FROM equipment_external_logs + WHERE actual_return_date IS NULL + GROUP BY equipment_id + ) latest ON e.equipment_id = latest.equipment_id + INNER JOIN equipment_external_logs eel ON eel.log_id = latest.latest_log_id + LEFT JOIN workplaces w ON e.workplace_id = w.workplace_id + LEFT JOIN users u ON eel.exported_by = u.user_id + WHERE e.status IN ('external', 'repair_external') + ORDER BY eel.export_date DESC + `; + + const [rows] = await db.query(query); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // ========================================== + // 설비 수리 신청 (work_issue_reports 연동) + // ========================================== + + // CREATE REPAIR REQUEST - 수리 신청 (신고 시스템 활용) + createRepairRequest: async (requestData, callback) => { + try { + const db = await getDb(); + + // 설비 수리 카테고리 ID 조회 + const [categories] = await db.query( + "SELECT category_id FROM issue_report_categories WHERE category_name = '설비 수리' LIMIT 1" + ); + + if (!categories[0]) { + return callback(new Error('설비 수리 카테고리가 없습니다')); + } + + const categoryId = categories[0].category_id; + + // 항목 ID 조회 (지정된 항목이 없으면 첫번째 항목 사용) + let itemId = requestData.item_id; + if (!itemId) { + const [items] = await db.query( + 'SELECT item_id FROM issue_report_items WHERE category_id = ? LIMIT 1', + [categoryId] + ); + itemId = items[0]?.item_id; + } + + // 사진 경로 분리 (최대 5장) + const photos = requestData.photo_paths || []; + + // work_issue_reports에 삽입 + const query = ` + INSERT INTO work_issue_reports ( + reporter_id, issue_category_id, issue_item_id, + workplace_id, equipment_id, + additional_description, + photo_path1, photo_path2, photo_path3, photo_path4, photo_path5, + status + ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'reported') + `; + + const values = [ + requestData.reported_by || null, + categoryId, + itemId, + requestData.workplace_id || null, + requestData.equipment_id, + requestData.description || null, + photos[0] || null, + photos[1] || null, + photos[2] || null, + photos[3] || null, + photos[4] || null + ]; + + const [result] = await db.query(query, values); + + // 설비 상태를 repair_needed로 업데이트 + await db.query( + 'UPDATE equipments SET status = ?, updated_at = NOW() WHERE equipment_id = ?', + ['repair_needed', requestData.equipment_id] + ); + + // 알림 생성 + try { + await notificationModel.createRepairNotification({ + equipment_id: requestData.equipment_id, + equipment_name: requestData.equipment_name || '설비', + repair_type: requestData.repair_type || '일반 수리', + request_id: result.insertId, + created_by: requestData.reported_by + }); + } catch (notifError) { + console.error('알림 생성 실패:', notifError); + // 알림 생성 실패해도 수리 신청은 성공으로 처리 + } + + callback(null, { + report_id: result.insertId, + equipment_id: requestData.equipment_id, + created: true + }); + } catch (error) { + callback(error); + } + }, + + // GET REPAIR HISTORY - 설비 수리 이력 조회 + getRepairHistory: async (equipmentId, callback) => { + try { + const db = await getDb(); + const query = ` + SELECT + wir.*, + irc.category_name, + iri.item_name, + u_rep.name AS reported_by_name, + u_res.name AS resolved_by_name, + w.workplace_name + FROM work_issue_reports wir + LEFT JOIN issue_report_categories irc ON wir.issue_category_id = irc.category_id + LEFT JOIN issue_report_items iri ON wir.issue_item_id = iri.item_id + LEFT JOIN users u_rep ON wir.reporter_id = u_rep.user_id + LEFT JOIN users u_res ON wir.resolved_by = u_res.user_id + LEFT JOIN workplaces w ON wir.workplace_id = w.workplace_id + WHERE wir.equipment_id = ? + ORDER BY wir.created_at DESC + `; + + const [rows] = await db.query(query, [equipmentId]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // GET REPAIR CATEGORIES - 설비 수리 항목 목록 조회 + getRepairCategories: async (callback) => { + try { + const db = await getDb(); + + // 설비 수리 카테고리의 항목들 조회 + const query = ` + SELECT iri.item_id, iri.item_name, iri.description, iri.severity + FROM issue_report_items iri + INNER JOIN issue_report_categories irc ON iri.category_id = irc.category_id + WHERE irc.category_name = '설비 수리' AND iri.is_active = 1 + ORDER BY iri.display_order ASC + `; + + const [rows] = await db.query(query); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + // ADD REPAIR CATEGORY - 새 수리 항목 추가 + addRepairCategory: async (itemName, callback) => { + try { + const db = await getDb(); + + // 설비 수리 카테고리 ID 조회 + const [categories] = await db.query( + "SELECT category_id FROM issue_report_categories WHERE category_name = '설비 수리'" + ); + + if (categories.length === 0) { + return callback(new Error('설비 수리 카테고리가 없습니다.')); + } + + const categoryId = categories[0].category_id; + + // 중복 확인 + const [existing] = await db.query( + 'SELECT item_id FROM issue_report_items WHERE category_id = ? AND item_name = ?', + [categoryId, itemName] + ); + + if (existing.length > 0) { + // 이미 존재하면 해당 ID 반환 + return callback(null, { item_id: existing[0].item_id, item_name: itemName, isNew: false }); + } + + // 다음 display_order 구하기 + const [maxOrder] = await db.query( + 'SELECT MAX(display_order) as max_order FROM issue_report_items WHERE category_id = ?', + [categoryId] + ); + const nextOrder = (maxOrder[0].max_order || 0) + 1; + + // 새 항목 추가 + const [result] = await db.query( + `INSERT INTO issue_report_items (category_id, item_name, display_order, is_active) + VALUES (?, ?, ?, 1)`, + [categoryId, itemName, nextOrder] + ); + + callback(null, { item_id: result.insertId, item_name: itemName, isNew: true }); + } catch (error) { + callback(error); + } + } +}; + +module.exports = EquipmentModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/issueTypeModel.js b/deploy/tkfb-package/api.hyungi.net/models/issueTypeModel.js new file mode 100644 index 0000000..b00f94d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/issueTypeModel.js @@ -0,0 +1,42 @@ +const { getDb } = require('../dbPool'); + +// CREATE +const create = async (type) => { + const db = await getDb(); + const [result] = await db.query( + `INSERT INTO IssueTypes (category, subcategory) VALUES (?, ?)`, + [type.category, type.subcategory] + ); + return result.insertId; +}; + +// READ ALL +const getAll = async () => { + const db = await getDb(); + const [rows] = await db.query(`SELECT issue_type_id, category, subcategory FROM IssueTypes ORDER BY category, subcategory`); + return rows; +}; + +// UPDATE +const update = async (id, type) => { + const db = await getDb(); + const [result] = await db.query( + `UPDATE IssueTypes SET category = ?, subcategory = ? WHERE id = ?`, + [type.category, type.subcategory, id] + ); + return result.affectedRows; +}; + +// DELETE +const remove = async (id) => { + const db = await getDb(); + const [result] = await db.query(`DELETE FROM IssueTypes WHERE id = ?`, [id]); + return result.affectedRows; +}; + +module.exports = { + create, + getAll, + update, + remove +}; diff --git a/deploy/tkfb-package/api.hyungi.net/models/monthlyStatusModel.js b/deploy/tkfb-package/api.hyungi.net/models/monthlyStatusModel.js new file mode 100644 index 0000000..d7e86e4 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/monthlyStatusModel.js @@ -0,0 +1,183 @@ +// models/monthlyStatusModel.js +// 월별 작업자 상태 집계 모델 + +const { getDb } = require('../dbPool'); + +class MonthlyStatusModel { + // 월별 일자별 요약 조회 (캘린더용) + static async getMonthlySummary(year, month) { + const db = await getDb(); + + try { + const [rows] = await db.execute(` + SELECT + date, + total_workers, + working_workers, + incomplete_workers, + partial_workers, + complete_workers, + overtime_workers, + vacation_workers, + error_workers, + overtime_warning_workers, + total_work_hours, + total_work_count, + total_error_count, + has_issues, + has_errors, + has_overtime_warning, + last_updated + FROM monthly_summary + WHERE year = ? AND month = ? + ORDER BY date ASC + `, [year, month]); + + return rows; + } catch (error) { + console.error('월별 요약 조회 오류:', error); + throw error; + } + } + + // 특정 날짜의 작업자별 상태 조회 (모달용) + // ✅ 리팩토링: 집계 테이블 대신 daily_work_reports에서 직접 조회 (중복 문제 완전 해결) + static async getDailyWorkerStatus(date) { + const db = await getDb(); + + try { + // daily_work_reports에서 직접 집계하여 조회 (중복 없음 보장) + const [rows] = await db.query(` + SELECT + w.worker_id, + w.worker_name, + w.job_type, + YEAR(?) as year, + MONTH(?) as month, + ? as date, + COALESCE(SUM(dwr.work_hours), 0) as total_work_hours, + COALESCE(SUM(CASE WHEN dwr.project_id != 13 THEN dwr.work_hours ELSE 0 END), 0) as actual_work_hours, + COALESCE(SUM(CASE WHEN dwr.project_id = 13 THEN dwr.work_hours ELSE 0 END), 0) as vacation_hours, + COUNT(dwr.id) as total_work_count, + COUNT(CASE WHEN dwr.project_id != 13 AND dwr.work_status_id != 2 THEN 1 END) as regular_work_count, + COUNT(CASE WHEN dwr.work_status_id = 2 THEN 1 END) as error_work_count, + CASE + WHEN MAX(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) = 1 THEN 'error' + WHEN SUM(dwr.work_hours) > 12 THEN 'overtime-warning' + WHEN SUM(dwr.work_hours) > 8 THEN 'overtime' + WHEN SUM(dwr.work_hours) = 8 THEN 'complete' + WHEN SUM(dwr.work_hours) > 0 THEN 'partial' + ELSE 'incomplete' + END as work_status, + MAX(CASE WHEN dwr.project_id = 13 THEN 1 ELSE 0 END) as has_vacation, + MAX(CASE WHEN dwr.work_status_id = 2 THEN 1 ELSE 0 END) as has_error, + CASE + WHEN SUM(dwr.work_hours) < 8 AND SUM(dwr.work_hours) > 0 THEN 1 + ELSE 0 + END as has_issues, + MAX(dwr.created_at) as last_updated + FROM workers w + LEFT JOIN daily_work_reports dwr ON w.worker_id = dwr.worker_id AND dwr.report_date = ? + WHERE w.status = 'active' + GROUP BY w.worker_id, w.worker_name, w.job_type + ORDER BY w.worker_name ASC + `, [date, date, date, date]); + + return rows; + } catch (error) { + console.error('일별 작업자 상태 조회 오류:', error); + throw error; + } + } + + // 월별 집계 데이터 강제 재계산 (관리용) + static async recalculateMonth(year, month) { + const db = await getDb(); + + try { + // 해당 월의 모든 날짜와 작업자 조합을 찾아서 재계산 + const [workDates] = await db.execute(` + SELECT DISTINCT report_date, worker_id + FROM daily_work_reports + WHERE YEAR(report_date) = ? AND MONTH(report_date) = ? + `, [year, month]); + + let updatedCount = 0; + + for (const { report_date, worker_id } of workDates) { + await db.execute('CALL UpdateMonthlyWorkerStatus(?, ?)', [report_date, worker_id]); + updatedCount++; + } + + console.log(`✅ ${year}년 ${month}월 집계 재계산 완료: ${updatedCount}건`); + return { success: true, updatedCount }; + + } catch (error) { + console.error('월별 집계 재계산 오류:', error); + throw error; + } + } + + // 특정 날짜 집계 강제 업데이트 + static async updateDateSummary(date, workerId = null) { + const db = await getDb(); + + try { + if (workerId) { + // 특정 작업자만 업데이트 + await db.execute('CALL UpdateMonthlyWorkerStatus(?, ?)', [date, workerId]); + } else { + // 해당 날짜의 모든 작업자 업데이트 + const [workers] = await db.execute(` + SELECT DISTINCT worker_id + FROM daily_work_reports + WHERE report_date = ? + `, [date]); + + for (const { worker_id } of workers) { + await db.execute('CALL UpdateMonthlyWorkerStatus(?, ?)', [date, worker_id]); + } + } + + return { success: true }; + } catch (error) { + console.error('날짜별 집계 업데이트 오류:', error); + throw error; + } + } + + // 집계 테이블 상태 확인 + static async getStatusInfo() { + const db = await getDb(); + + try { + const [summaryCount] = await db.execute(` + SELECT + COUNT(*) as total_days, + MIN(date) as earliest_date, + MAX(date) as latest_date, + MAX(last_updated) as last_update + FROM monthly_summary + `); + + const [workerStatusCount] = await db.execute(` + SELECT + COUNT(*) as total_records, + COUNT(DISTINCT worker_id) as unique_workers, + COUNT(DISTINCT date) as unique_dates, + MAX(last_updated) as last_update + FROM monthly_worker_status + `); + + return { + summary: summaryCount[0], + workerStatus: workerStatusCount[0] + }; + } catch (error) { + console.error('집계 테이블 상태 확인 오류:', error); + throw error; + } + } +} + +module.exports = MonthlyStatusModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/notificationModel.js b/deploy/tkfb-package/api.hyungi.net/models/notificationModel.js new file mode 100644 index 0000000..a3a52af --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/notificationModel.js @@ -0,0 +1,197 @@ +// models/notificationModel.js +const { getDb } = require('../dbPool'); + +// 순환 참조를 피하기 위해 함수 내에서 require +async function getRecipientIds(notificationType) { + const db = await getDb(); + const [rows] = await db.query( + `SELECT user_id FROM notification_recipients + WHERE notification_type = ? AND is_active = 1`, + [notificationType] + ); + return rows.map(r => r.user_id); +} + +const notificationModel = { + // 알림 생성 + async create(notificationData) { + const db = await getDb(); + const { user_id, type, title, message, link_url, reference_type, reference_id, created_by } = notificationData; + + const [result] = await db.query( + `INSERT INTO notifications (user_id, type, title, message, link_url, reference_type, reference_id, created_by) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + [user_id || null, type || 'system', title, message || null, link_url || null, reference_type || null, reference_id || null, created_by || null] + ); + + return result.insertId; + }, + + // 읽지 않은 알림 조회 (특정 사용자 또는 전체) + async getUnread(userId = null) { + const db = await getDb(); + const [rows] = await db.query( + `SELECT * FROM notifications + WHERE is_read = 0 + AND (user_id IS NULL OR user_id = ?) + ORDER BY created_at DESC + LIMIT 50`, + [userId || 0] + ); + return rows; + }, + + // 전체 알림 조회 (페이징) + async getAll(userId = null, page = 1, limit = 20) { + const db = await getDb(); + const offset = (page - 1) * limit; + + const [rows] = await db.query( + `SELECT * FROM notifications + WHERE (user_id IS NULL OR user_id = ?) + ORDER BY created_at DESC + LIMIT ? OFFSET ?`, + [userId || 0, limit, offset] + ); + + const [[{ total }]] = await db.query( + `SELECT COUNT(*) as total FROM notifications + WHERE (user_id IS NULL OR user_id = ?)`, + [userId || 0] + ); + + return { notifications: rows, total, page, limit }; + }, + + // 알림 읽음 처리 + async markAsRead(notificationId) { + const db = await getDb(); + const [result] = await db.query( + `UPDATE notifications SET is_read = 1, read_at = NOW() WHERE notification_id = ?`, + [notificationId] + ); + return result.affectedRows > 0; + }, + + // 모든 알림 읽음 처리 + async markAllAsRead(userId = null) { + const db = await getDb(); + const [result] = await db.query( + `UPDATE notifications SET is_read = 1, read_at = NOW() + WHERE is_read = 0 AND (user_id IS NULL OR user_id = ?)`, + [userId || 0] + ); + return result.affectedRows; + }, + + // 알림 삭제 + async delete(notificationId) { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM notifications WHERE notification_id = ?`, + [notificationId] + ); + return result.affectedRows > 0; + }, + + // 오래된 알림 삭제 (30일 이상) + async deleteOld(days = 30) { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM notifications WHERE created_at < DATE_SUB(NOW(), INTERVAL ? DAY)`, + [days] + ); + return result.affectedRows; + }, + + // 읽지 않은 알림 개수 + async getUnreadCount(userId = null) { + const db = await getDb(); + const [[{ count }]] = await db.query( + `SELECT COUNT(*) as count FROM notifications + WHERE is_read = 0 AND (user_id IS NULL OR user_id = ?)`, + [userId || 0] + ); + return count; + }, + + // 수리 신청 알림 생성 헬퍼 (지정된 수신자에게 전송) + async createRepairNotification(repairData) { + const { equipment_id, equipment_name, repair_type, request_id, created_by } = repairData; + + // 수리 알림 수신자 목록 가져오기 + const recipientIds = await getRecipientIds('repair'); + + if (recipientIds.length === 0) { + // 수신자가 지정되지 않은 경우 전체 알림 (user_id = null) + return await this.create({ + type: 'repair', + title: `수리 신청: ${equipment_name || '설비'}`, + message: `${repair_type} 수리가 신청되었습니다.`, + link_url: `/pages/admin/repair-management.html`, + reference_type: 'work_issue_reports', + reference_id: request_id, + created_by + }); + } + + // 지정된 수신자 각각에게 알림 생성 + const results = []; + for (const userId of recipientIds) { + const notificationId = await this.create({ + user_id: userId, + type: 'repair', + title: `수리 신청: ${equipment_name || '설비'}`, + message: `${repair_type} 수리가 신청되었습니다.`, + link_url: `/pages/admin/repair-management.html`, + reference_type: 'work_issue_reports', + reference_id: request_id, + created_by + }); + results.push(notificationId); + } + + return results; + }, + + // 일반 알림 생성 (유형별 지정된 수신자에게 전송) + async createTypedNotification(notificationData) { + const { type, title, message, link_url, reference_type, reference_id, created_by } = notificationData; + + // 해당 유형의 수신자 목록 가져오기 + const recipientIds = await getRecipientIds(type); + + if (recipientIds.length === 0) { + // 수신자가 지정되지 않은 경우 전체 알림 + return await this.create({ + type, + title, + message, + link_url, + reference_type, + reference_id, + created_by + }); + } + + // 지정된 수신자 각각에게 알림 생성 + const results = []; + for (const userId of recipientIds) { + const notificationId = await this.create({ + user_id: userId, + type, + title, + message, + link_url, + reference_type, + reference_id, + created_by + }); + results.push(notificationId); + } + + return results; + } +}; + +module.exports = notificationModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/notificationRecipientModel.js b/deploy/tkfb-package/api.hyungi.net/models/notificationRecipientModel.js new file mode 100644 index 0000000..0867e07 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/notificationRecipientModel.js @@ -0,0 +1,146 @@ +// models/notificationRecipientModel.js +const { getDb } = require('../dbPool'); + +const NOTIFICATION_TYPES = { + repair: '설비 수리', + safety: '안전 신고', + nonconformity: '부적합 신고', + equipment: '설비 관련', + maintenance: '정기점검', + system: '시스템' +}; + +const notificationRecipientModel = { + // 알림 유형 목록 가져오기 + getTypes() { + return NOTIFICATION_TYPES; + }, + + // 유형별 수신자 목록 조회 + async getByType(notificationType) { + const db = await getDb(); + const [rows] = await db.query( + `SELECT nr.*, u.username, u.name as user_name, r.name as role + FROM notification_recipients nr + JOIN users u ON nr.user_id = u.user_id + LEFT JOIN roles r ON u.role_id = r.id + WHERE nr.notification_type = ? AND nr.is_active = 1 + ORDER BY u.name`, + [notificationType] + ); + return rows; + }, + + // 전체 수신자 목록 조회 (유형별 그룹화) + async getAll() { + const db = await getDb(); + const [rows] = await db.query( + `SELECT nr.*, u.username, u.name as user_name, r.name as role + FROM notification_recipients nr + JOIN users u ON nr.user_id = u.user_id + LEFT JOIN roles r ON u.role_id = r.id + WHERE nr.is_active = 1 + ORDER BY nr.notification_type, u.name` + ); + + // 유형별로 그룹화 + const grouped = {}; + for (const type in NOTIFICATION_TYPES) { + grouped[type] = { + label: NOTIFICATION_TYPES[type], + recipients: [] + }; + } + + rows.forEach(row => { + if (grouped[row.notification_type]) { + grouped[row.notification_type].recipients.push(row); + } + }); + + return grouped; + }, + + // 수신자 추가 + async add(notificationType, userId, createdBy = null) { + const db = await getDb(); + const [result] = await db.query( + `INSERT INTO notification_recipients (notification_type, user_id, created_by) + VALUES (?, ?, ?) + ON DUPLICATE KEY UPDATE is_active = 1`, + [notificationType, userId, createdBy] + ); + return result.insertId || result.affectedRows > 0; + }, + + // 수신자 제거 (soft delete) + async remove(notificationType, userId) { + const db = await getDb(); + const [result] = await db.query( + `UPDATE notification_recipients SET is_active = 0 + WHERE notification_type = ? AND user_id = ?`, + [notificationType, userId] + ); + return result.affectedRows > 0; + }, + + // 수신자 완전 삭제 + async delete(notificationType, userId) { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM notification_recipients + WHERE notification_type = ? AND user_id = ?`, + [notificationType, userId] + ); + return result.affectedRows > 0; + }, + + // 유형별 수신자 user_id 목록만 가져오기 (알림 생성용) + async getRecipientIds(notificationType) { + const db = await getDb(); + const [rows] = await db.query( + `SELECT user_id FROM notification_recipients + WHERE notification_type = ? AND is_active = 1`, + [notificationType] + ); + return rows.map(r => r.user_id); + }, + + // 사용자가 특정 유형의 수신자인지 확인 + async isRecipient(notificationType, userId) { + const db = await getDb(); + const [[row]] = await db.query( + `SELECT 1 FROM notification_recipients + WHERE notification_type = ? AND user_id = ? AND is_active = 1`, + [notificationType, userId] + ); + return !!row; + }, + + // 유형별 수신자 일괄 설정 + async setRecipients(notificationType, userIds, createdBy = null) { + const db = await getDb(); + + // 기존 수신자 비활성화 + await db.query( + `UPDATE notification_recipients SET is_active = 0 + WHERE notification_type = ?`, + [notificationType] + ); + + // 새 수신자 추가 + if (userIds && userIds.length > 0) { + const values = userIds.map(userId => [notificationType, userId, createdBy]); + await db.query( + `INSERT INTO notification_recipients (notification_type, user_id, created_by) + VALUES ? + ON DUPLICATE KEY UPDATE is_active = 1`, + [values] + ); + } + + return true; + } +}; + +module.exports = notificationRecipientModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/pageAccessModel.js b/deploy/tkfb-package/api.hyungi.net/models/pageAccessModel.js new file mode 100644 index 0000000..f6801f6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/pageAccessModel.js @@ -0,0 +1,160 @@ +// models/pageAccessModel.js +const db = require('../db/connection'); + +const PageAccessModel = { + // 사용자의 페이지 권한 조회 + getUserPageAccess: (userId, callback) => { + const sql = ` + SELECT + p.id, + p.page_key, + p.page_name, + p.page_path, + p.category, + p.is_admin_only, + COALESCE(upa.can_access, 0) as can_access, + upa.granted_at, + upa.granted_by, + granter.username as granted_by_username + FROM pages p + LEFT JOIN user_page_access upa ON p.id = upa.page_id AND upa.user_id = ? + LEFT JOIN users granter ON upa.granted_by = granter.user_id + WHERE p.is_admin_only = 0 + ORDER BY p.category, p.display_order + `; + + db.query(sql, [userId], callback); + }, + + // 모든 페이지 목록 조회 + getAllPages: (callback) => { + const sql = ` + SELECT + id, + page_key, + page_name, + page_path, + category, + description, + is_admin_only, + display_order + FROM pages + WHERE is_admin_only = 0 + ORDER BY category, display_order + `; + + db.query(sql, callback); + }, + + // 페이지 권한 부여 + grantPageAccess: (userId, pageId, grantedBy, callback) => { + const sql = ` + INSERT INTO user_page_access (user_id, page_id, can_access, granted_by, granted_at) + VALUES (?, ?, 1, ?, NOW()) + ON DUPLICATE KEY UPDATE + can_access = 1, + granted_by = ?, + granted_at = NOW() + `; + + db.query(sql, [userId, pageId, grantedBy, grantedBy], callback); + }, + + // 페이지 권한 회수 + revokePageAccess: (userId, pageId, callback) => { + const sql = ` + DELETE FROM user_page_access + WHERE user_id = ? AND page_id = ? + `; + + db.query(sql, [userId, pageId], callback); + }, + + // 여러 페이지 권한 일괄 설정 + setUserPageAccess: (userId, pageIds, grantedBy, callback) => { + db.beginTransaction((err) => { + if (err) return callback(err); + + // 기존 권한 모두 삭제 + const deleteSql = 'DELETE FROM user_page_access WHERE user_id = ?'; + + db.query(deleteSql, [userId], (err) => { + if (err) { + return db.rollback(() => callback(err)); + } + + // 새 권한이 없으면 커밋하고 종료 + if (!pageIds || pageIds.length === 0) { + return db.commit((err) => { + if (err) return db.rollback(() => callback(err)); + callback(null, { affectedRows: 0 }); + }); + } + + // 새 권한 추가 + const values = pageIds.map(pageId => [userId, pageId, 1, grantedBy]); + const insertSql = ` + INSERT INTO user_page_access (user_id, page_id, can_access, granted_by, granted_at) + VALUES ? + `; + + db.query(insertSql, [values], (err, result) => { + if (err) { + return db.rollback(() => callback(err)); + } + + db.commit((err) => { + if (err) return db.rollback(() => callback(err)); + callback(null, result); + }); + }); + }); + }); + }, + + // 특정 페이지 접근 권한 확인 + checkPageAccess: (userId, pageKey, callback) => { + const sql = ` + SELECT + COALESCE(upa.can_access, 0) as can_access, + p.is_admin_only + FROM pages p + LEFT JOIN user_page_access upa ON p.id = upa.page_id AND upa.user_id = ? + WHERE p.page_key = ? + `; + + db.query(sql, [userId, pageKey], (err, results) => { + if (err) return callback(err); + if (results.length === 0) return callback(null, { can_access: false }); + callback(null, results[0]); + }); + }, + + // 계정이 있는 작업자 목록 조회 (권한 관리용) + getUsersWithAccounts: (callback) => { + const sql = ` + SELECT + u.user_id, + u.username, + u.name, + u.role_id, + r.name as role_name, + u.worker_id, + w.worker_name, + w.job_type, + COUNT(upa.page_id) as granted_pages_count + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + LEFT JOIN workers w ON u.worker_id = w.worker_id + LEFT JOIN user_page_access upa ON u.user_id = upa.user_id AND upa.can_access = 1 + WHERE u.is_active = 1 + AND u.role_id IN (4, 5) + GROUP BY u.user_id + ORDER BY w.worker_name, u.username + `; + + db.query(sql, callback); + } +}; + +module.exports = PageAccessModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/patrolModel.js b/deploy/tkfb-package/api.hyungi.net/models/patrolModel.js new file mode 100644 index 0000000..c6f052e --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/patrolModel.js @@ -0,0 +1,358 @@ +// patrolModel.js +// 일일순회점검 시스템 모델 + +const { getDb } = require('../dbPool'); + +const PatrolModel = { + // ==================== 순회점검 세션 ==================== + + // 세션 생성 또는 조회 + getOrCreateSession: async (patrolDate, patrolTime, categoryId, inspectorId) => { + const db = await getDb(); + + // 기존 세션 확인 + const [existingRows] = await db.query(` + SELECT session_id, status, started_at, completed_at + FROM daily_patrol_sessions + WHERE patrol_date = ? AND patrol_time = ? AND category_id = ? + `, [patrolDate, patrolTime, categoryId]); + + if (existingRows.length > 0) { + return existingRows[0]; + } + + // 새 세션 생성 + const [result] = await db.query(` + INSERT INTO daily_patrol_sessions (patrol_date, patrol_time, category_id, inspector_id, started_at) + VALUES (?, ?, ?, ?, CURTIME()) + `, [patrolDate, patrolTime, categoryId, inspectorId]); + + return { + session_id: result.insertId, + status: 'in_progress', + started_at: new Date().toTimeString().slice(0, 8) + }; + }, + + // 세션 조회 + getSession: async (sessionId) => { + const db = await getDb(); + const [rows] = await db.query(` + SELECT s.*, u.name AS inspector_name, wc.category_name + FROM daily_patrol_sessions s + LEFT JOIN users u ON s.inspector_id = u.user_id + LEFT JOIN workplace_categories wc ON s.category_id = wc.category_id + WHERE s.session_id = ? + `, [sessionId]); + return rows[0] || null; + }, + + // 세션 목록 조회 + getSessions: async (filters = {}) => { + const db = await getDb(); + let query = ` + SELECT s.*, u.name AS inspector_name, wc.category_name, + (SELECT COUNT(*) FROM patrol_check_records WHERE session_id = s.session_id AND is_checked = 1) AS checked_count, + (SELECT COUNT(*) FROM patrol_check_records WHERE session_id = s.session_id) AS total_count + FROM daily_patrol_sessions s + LEFT JOIN users u ON s.inspector_id = u.user_id + LEFT JOIN workplace_categories wc ON s.category_id = wc.category_id + WHERE 1=1 + `; + const params = []; + + if (filters.patrol_date) { + query += ' AND s.patrol_date = ?'; + params.push(filters.patrol_date); + } + if (filters.patrol_time) { + query += ' AND s.patrol_time = ?'; + params.push(filters.patrol_time); + } + if (filters.category_id) { + query += ' AND s.category_id = ?'; + params.push(filters.category_id); + } + if (filters.status) { + query += ' AND s.status = ?'; + params.push(filters.status); + } + + query += ' ORDER BY s.patrol_date DESC, s.patrol_time DESC'; + + if (filters.limit) { + query += ' LIMIT ?'; + params.push(parseInt(filters.limit)); + } + + const [rows] = await db.query(query, params); + return rows; + }, + + // 세션 완료 처리 + completeSession: async (sessionId) => { + const db = await getDb(); + await db.query(` + UPDATE daily_patrol_sessions + SET status = 'completed', completed_at = CURTIME(), updated_at = NOW() + WHERE session_id = ? + `, [sessionId]); + return true; + }, + + // 세션 메모 업데이트 + updateSessionNotes: async (sessionId, notes) => { + const db = await getDb(); + await db.query(` + UPDATE daily_patrol_sessions + SET notes = ?, updated_at = NOW() + WHERE session_id = ? + `, [notes, sessionId]); + return true; + }, + + // ==================== 체크리스트 항목 ==================== + + // 체크리스트 항목 조회 (공장/작업장별 필터링) + getChecklistItems: async (categoryId = null, workplaceId = null) => { + const db = await getDb(); + let query = ` + SELECT * + FROM patrol_checklist_items + WHERE is_active = 1 + AND (workplace_id IS NULL OR workplace_id = ?) + AND (category_id IS NULL OR category_id = ?) + ORDER BY check_category, display_order, check_item + `; + const [rows] = await db.query(query, [workplaceId, categoryId]); + return rows; + }, + + // 체크리스트 항목 CRUD + createChecklistItem: async (data) => { + const db = await getDb(); + const [result] = await db.query(` + INSERT INTO patrol_checklist_items (workplace_id, category_id, check_category, check_item, description, display_order, is_required) + VALUES (?, ?, ?, ?, ?, ?, ?) + `, [data.workplace_id, data.category_id, data.check_category, data.check_item, data.description, data.display_order || 0, data.is_required !== false]); + return result.insertId; + }, + + updateChecklistItem: async (itemId, data) => { + const db = await getDb(); + const fields = []; + const params = []; + + ['workplace_id', 'category_id', 'check_category', 'check_item', 'description', 'display_order', 'is_required', 'is_active'].forEach(key => { + if (data[key] !== undefined) { + fields.push(`${key} = ?`); + params.push(data[key]); + } + }); + + if (fields.length === 0) return false; + + params.push(itemId); + await db.query(`UPDATE patrol_checklist_items SET ${fields.join(', ')}, updated_at = NOW() WHERE item_id = ?`, params); + return true; + }, + + deleteChecklistItem: async (itemId) => { + const db = await getDb(); + await db.query('UPDATE patrol_checklist_items SET is_active = 0, updated_at = NOW() WHERE item_id = ?', [itemId]); + return true; + }, + + // ==================== 체크 기록 ==================== + + // 작업장별 체크 기록 조회 + getCheckRecords: async (sessionId, workplaceId = null) => { + const db = await getDb(); + let query = ` + SELECT r.*, ci.check_category, ci.check_item, ci.is_required + FROM patrol_check_records r + JOIN patrol_checklist_items ci ON r.check_item_id = ci.item_id + WHERE r.session_id = ? + `; + const params = [sessionId]; + + if (workplaceId) { + query += ' AND r.workplace_id = ?'; + params.push(workplaceId); + } + + query += ' ORDER BY ci.check_category, ci.display_order'; + + const [rows] = await db.query(query, params); + return rows; + }, + + // 체크 기록 저장 (upsert) + saveCheckRecord: async (sessionId, workplaceId, checkItemId, isChecked, checkResult = null, note = null) => { + const db = await getDb(); + await db.query(` + INSERT INTO patrol_check_records (session_id, workplace_id, check_item_id, is_checked, check_result, note, checked_at) + VALUES (?, ?, ?, ?, ?, ?, NOW()) + ON DUPLICATE KEY UPDATE + is_checked = VALUES(is_checked), + check_result = VALUES(check_result), + note = VALUES(note), + checked_at = NOW() + `, [sessionId, workplaceId, checkItemId, isChecked, checkResult, note]); + return true; + }, + + // 여러 체크 기록 일괄 저장 + saveCheckRecords: async (sessionId, workplaceId, records) => { + const db = await getDb(); + for (const record of records) { + await db.query(` + INSERT INTO patrol_check_records (session_id, workplace_id, check_item_id, is_checked, check_result, note, checked_at) + VALUES (?, ?, ?, ?, ?, ?, NOW()) + ON DUPLICATE KEY UPDATE + is_checked = VALUES(is_checked), + check_result = VALUES(check_result), + note = VALUES(note), + checked_at = NOW() + `, [sessionId, workplaceId, record.check_item_id, record.is_checked, record.check_result, record.note]); + } + return true; + }, + + // ==================== 작업장 물품 현황 ==================== + + // 작업장 물품 조회 + getWorkplaceItems: async (workplaceId, activeOnly = true) => { + const db = await getDb(); + let query = ` + SELECT wi.*, u.name AS created_by_name, it.type_name, it.icon, it.color + FROM workplace_items wi + LEFT JOIN users u ON wi.created_by = u.user_id + LEFT JOIN item_types it ON wi.item_type = it.type_code + WHERE wi.workplace_id = ? + `; + if (activeOnly) { + query += ' AND wi.is_active = 1'; + } + query += ' ORDER BY wi.created_at DESC'; + + const [rows] = await db.query(query, [workplaceId]); + return rows; + }, + + // 물품 추가 + createWorkplaceItem: async (data) => { + const db = await getDb(); + const [result] = await db.query(` + INSERT INTO workplace_items + (workplace_id, patrol_session_id, project_id, item_type, item_name, quantity, x_percent, y_percent, width_percent, height_percent, created_by) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + `, [ + data.workplace_id, + data.patrol_session_id, + data.project_id, + data.item_type, + data.item_name, + data.quantity || 1, + data.x_percent, + data.y_percent, + data.width_percent, + data.height_percent, + data.created_by + ]); + return result.insertId; + }, + + // 물품 수정 + updateWorkplaceItem: async (itemId, data, userId) => { + const db = await getDb(); + const fields = []; + const params = []; + + ['item_type', 'item_name', 'quantity', 'x_percent', 'y_percent', 'width_percent', 'height_percent', 'is_active', 'project_id'].forEach(key => { + if (data[key] !== undefined) { + fields.push(`${key} = ?`); + params.push(data[key]); + } + }); + + if (fields.length === 0) return false; + + fields.push('updated_by = ?', 'updated_at = NOW()'); + params.push(userId, itemId); + + await db.query(`UPDATE workplace_items SET ${fields.join(', ')} WHERE item_id = ?`, params); + return true; + }, + + // 물품 삭제 (비활성화) + deleteWorkplaceItem: async (itemId, userId) => { + const db = await getDb(); + await db.query('UPDATE workplace_items SET is_active = 0, updated_by = ?, updated_at = NOW() WHERE item_id = ?', [userId, itemId]); + return true; + }, + + // 물품 영구 삭제 + hardDeleteWorkplaceItem: async (itemId) => { + const db = await getDb(); + await db.query('DELETE FROM workplace_items WHERE item_id = ?', [itemId]); + return true; + }, + + // ==================== 물품 유형 ==================== + + // 물품 유형 목록 조회 + getItemTypes: async () => { + const db = await getDb(); + const [rows] = await db.query('SELECT * FROM item_types WHERE is_active = 1 ORDER BY display_order'); + return rows; + }, + + // ==================== 대시보드/통계 ==================== + + // 오늘 순회점검 현황 + getTodayPatrolStatus: async (categoryId = null) => { + const db = await getDb(); + const today = new Date().toISOString().slice(0, 10); + + let query = ` + SELECT s.session_id, s.patrol_time, s.status, s.inspector_id, u.name AS inspector_name, + s.started_at, s.completed_at, + (SELECT COUNT(*) FROM patrol_check_records WHERE session_id = s.session_id AND is_checked = 1) AS checked_count, + (SELECT COUNT(*) FROM patrol_check_records WHERE session_id = s.session_id) AS total_count + FROM daily_patrol_sessions s + LEFT JOIN users u ON s.inspector_id = u.user_id + WHERE s.patrol_date = ? + `; + const params = [today]; + + if (categoryId) { + query += ' AND s.category_id = ?'; + params.push(categoryId); + } + + query += ' ORDER BY s.patrol_time'; + + const [rows] = await db.query(query, params); + return rows; + }, + + // 작업장별 점검 현황 (세션 기준) + getWorkplaceCheckStatus: async (sessionId) => { + const db = await getDb(); + const [rows] = await db.query(` + SELECT w.workplace_id, w.workplace_name, + COUNT(DISTINCT r.check_item_id) AS checked_count, + (SELECT COUNT(*) FROM patrol_checklist_items WHERE is_active = 1) AS total_items, + MAX(r.checked_at) AS last_check_time + FROM workplaces w + LEFT JOIN patrol_check_records r ON w.workplace_id = r.workplace_id AND r.session_id = ? + WHERE w.is_active = 1 + GROUP BY w.workplace_id + ORDER BY w.workplace_name + `, [sessionId]); + return rows; + } +}; + +module.exports = PatrolModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/projectModel.js b/deploy/tkfb-package/api.hyungi.net/models/projectModel.js new file mode 100644 index 0000000..01e008b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/projectModel.js @@ -0,0 +1,96 @@ +const { getDb } = require('../dbPool'); + +const create = async (project) => { + const db = await getDb(); + const { + job_no, project_name, + contract_date, due_date, + delivery_method, site, pm, + is_active = true, + project_status = 'active', + completed_date = null + } = project; + + const [result] = await db.query( + `INSERT INTO projects + (job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date] + ); + + return result.insertId; +}; + +const getAll = async () => { + const db = await getDb(); + const [rows] = await db.query( + `SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects ORDER BY project_id DESC` + ); + return rows; +}; + +// 활성 프로젝트만 조회 (작업보고서용) +const getActiveProjects = async () => { + const db = await getDb(); + const [rows] = await db.query( + `SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects + WHERE is_active = TRUE + ORDER BY project_name ASC` + ); + return rows; +}; + +const getById = async (project_id) => { + const db = await getDb(); + const [rows] = await db.query( + `SELECT project_id, job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, created_at, updated_at FROM projects WHERE project_id = ?`, + [project_id] + ); + return rows[0]; +}; + +const update = async (project) => { + const db = await getDb(); + const { + project_id, job_no, project_name, + contract_date, due_date, + delivery_method, site, pm, + is_active, project_status, completed_date + } = project; + + const [result] = await db.query( + `UPDATE projects + SET job_no = ?, + project_name = ?, + contract_date = ?, + due_date = ?, + delivery_method= ?, + site = ?, + pm = ?, + is_active = ?, + project_status = ?, + completed_date = ? + WHERE project_id = ?`, + [job_no, project_name, contract_date, due_date, delivery_method, site, pm, is_active, project_status, completed_date, project_id] + ); + + return result.affectedRows; +}; + +const remove = async (project_id) => { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM projects WHERE project_id = ?`, + [project_id] + ); + return result.affectedRows; +}; + +module.exports = { + create, + getAll, + getActiveProjects, + getById, + update, + remove +}; diff --git a/deploy/tkfb-package/api.hyungi.net/models/roleModel.js b/deploy/tkfb-package/api.hyungi.net/models/roleModel.js new file mode 100644 index 0000000..5224eae --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/roleModel.js @@ -0,0 +1,43 @@ +const { getDb } = require('../dbPool'); + +class RoleModel { + /** + * 모든 역할 목록을 조회합니다. + * @returns {Promise} 역할 목록 + */ + static async findAll() { + const db = await getDb(); + const [rows] = await db.query('SELECT id, name, description FROM roles ORDER BY id'); + return rows; + } + + /** + * ID로 특정 역할을 조회합니다. + * @param {number} id - 역할 ID + * @returns {Promise} 역할 객체 + */ + static async findById(id) { + const db = await getDb(); + const [rows] = await db.query('SELECT id, name, description FROM roles WHERE id = ?', [id]); + return rows[0]; + } + + /** + * 역할에 속한 모든 권한을 조회합니다. + * @param {number} roleId - 역할 ID + * @returns {Promise} 권한 이름 목록 + */ + static async findPermissionsByRoleId(roleId) { + const db = await getDb(); + const [rows] = await db.query( + `SELECT p.name + FROM permissions p + JOIN role_permissions rp ON p.id = rp.permission_id + WHERE rp.role_id = ?`, + [roleId] + ); + return rows.map(p => p.name); + } +} + +module.exports = RoleModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/taskModel.js b/deploy/tkfb-package/api.hyungi.net/models/taskModel.js new file mode 100644 index 0000000..432d431 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/taskModel.js @@ -0,0 +1,142 @@ +/** + * 작업 모델 + * + * @author TK-FB-Project + * @since 2026-01-26 + */ + +const { getDb } = require('../dbPool'); + +// ==================== 작업 CRUD ==================== + +/** + * 작업 생성 + */ +const createTask = async (taskData) => { + const db = await getDb(); + const { work_type_id, task_name, description } = taskData; + + const [result] = await db.query( + `INSERT INTO tasks (work_type_id, task_name, description, is_active) + VALUES (?, ?, ?, 1)`, + [work_type_id || null, task_name, description || null] + ); + + return result.insertId; +}; + +/** + * 전체 작업 목록 조회 (공정 정보 포함) + */ +const getAllTasks = async () => { + const db = await getDb(); + const [rows] = await db.query( + `SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active, + t.created_at, t.updated_at, + wt.name as work_type_name, wt.category + FROM tasks t + LEFT JOIN work_types wt ON t.work_type_id = wt.id + ORDER BY wt.category ASC, t.task_id DESC` + ); + return rows; +}; + +/** + * 활성 작업만 조회 + */ +const getActiveTasks = async () => { + const db = await getDb(); + const [rows] = await db.query( + `SELECT t.task_id, t.work_type_id, t.task_name, t.description, + wt.name as work_type_name, wt.category + FROM tasks t + LEFT JOIN work_types wt ON t.work_type_id = wt.id + WHERE t.is_active = 1 + ORDER BY wt.category ASC, t.task_name ASC` + ); + return rows; +}; + +/** + * 공정별 작업 목록 조회 (활성 작업만) + */ +const getTasksByWorkType = async (workTypeId) => { + const db = await getDb(); + const [rows] = await db.query( + `SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active, + t.created_at, t.updated_at, + wt.name as work_type_name, wt.category + FROM tasks t + LEFT JOIN work_types wt ON t.work_type_id = wt.id + WHERE t.work_type_id = ? AND t.is_active = 1 + ORDER BY t.task_name ASC`, + [workTypeId] + ); + return rows; +}; + +/** + * 단일 작업 조회 + */ +const getTaskById = async (taskId) => { + const db = await getDb(); + const [rows] = await db.query( + `SELECT t.task_id, t.work_type_id, t.task_name, t.description, t.is_active, + t.created_at, t.updated_at, + wt.name as work_type_name, wt.category + FROM tasks t + LEFT JOIN work_types wt ON t.work_type_id = wt.id + WHERE t.task_id = ?`, + [taskId] + ); + return rows[0] || null; +}; + +/** + * 작업 수정 + */ +const updateTask = async (taskId, taskData) => { + const db = await getDb(); + const { work_type_id, task_name, description, is_active } = taskData; + + const [result] = await db.query( + `UPDATE tasks + SET work_type_id = ?, + task_name = ?, + description = ?, + is_active = ?, + updated_at = NOW() + WHERE task_id = ?`, + [ + work_type_id || null, + task_name, + description || null, + is_active !== undefined ? is_active : 1, + taskId + ] + ); + + return result; +}; + +/** + * 작업 삭제 + */ +const deleteTask = async (taskId) => { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM tasks WHERE task_id = ?`, + [taskId] + ); + return result; +}; + +module.exports = { + createTask, + getAllTasks, + getActiveTasks, + getTasksByWorkType, + getTaskById, + updateTask, + deleteTask +}; diff --git a/deploy/tkfb-package/api.hyungi.net/models/tbmModel.js b/deploy/tkfb-package/api.hyungi.net/models/tbmModel.js new file mode 100644 index 0000000..a191243 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/tbmModel.js @@ -0,0 +1,994 @@ +// models/tbmModel.js - TBM 시스템 모델 +const { getDb } = require('../dbPool'); + +const TbmModel = { + // ==================== TBM 세션 관련 ==================== + + /** + * TBM 세션 생성 + */ + createSession: async (sessionData, callback) => { + try { + const db = await getDb(); + const sql = ` + INSERT INTO tbm_sessions + (session_date, leader_id, project_id, work_type_id, task_id, work_location, created_by) + VALUES (?, ?, ?, ?, ?, ?, ?) + `; + + const values = [ + sessionData.session_date, + sessionData.leader_id, + sessionData.project_id || null, + sessionData.work_type_id || null, + sessionData.task_id || null, + sessionData.work_location || null, + sessionData.created_by + ]; + + const [result] = await db.query(sql, values); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * 특정 날짜의 TBM 세션 조회 + */ + getSessionsByDate: async (date, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + s.*, + w.worker_name as leader_name, + w.job_type as leader_job_type, + u.username as created_by_username, + u.name as created_by_name, + COUNT(DISTINCT ta.worker_id) as team_member_count, + -- 첫 번째 팀원의 작업 정보 가져오기 + first_ta.project_id, + first_ta.work_type_id, + first_ta.task_id, + first_ta.workplace_id, + first_p.project_name, + first_wt.name as work_type_name, + first_t.task_name, + first_wp.workplace_name as work_location + FROM tbm_sessions s + LEFT JOIN workers w ON s.leader_id = w.worker_id + LEFT JOIN users u ON s.created_by = u.user_id + LEFT JOIN tbm_team_assignments ta ON s.session_id = ta.session_id + -- 첫 번째 팀원 정보 (가장 먼저 등록된 작업) + LEFT JOIN ( + SELECT * FROM tbm_team_assignments + WHERE (session_id, assignment_id) IN ( + SELECT session_id, MIN(assignment_id) + FROM tbm_team_assignments + GROUP BY session_id + ) + ) first_ta ON s.session_id = first_ta.session_id + LEFT JOIN projects first_p ON first_ta.project_id = first_p.project_id + LEFT JOIN work_types first_wt ON first_ta.work_type_id = first_wt.id + LEFT JOIN tasks first_t ON first_ta.task_id = first_t.task_id + LEFT JOIN workplaces first_wp ON first_ta.workplace_id = first_wp.workplace_id + WHERE s.session_date = ? + GROUP BY s.session_id + ORDER BY s.session_id DESC + `; + + const [rows] = await db.query(sql, [date]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * TBM 세션 상세 조회 + */ + getSessionById: async (sessionId, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + s.*, + w.worker_name as leader_name, + w.job_type as leader_job_type, + w.phone_number as leader_phone, + p.project_name, + p.job_no, + p.site, + wt.name as work_type_name, + wt.category as work_type_category, + t.task_name, + t.description as task_description, + u.username as created_by_username, + u.name as created_by_name + FROM tbm_sessions s + LEFT JOIN workers w ON s.leader_id = w.worker_id + LEFT JOIN projects p ON s.project_id = p.project_id + LEFT JOIN work_types wt ON s.work_type_id = wt.id + LEFT JOIN tasks t ON s.task_id = t.task_id + LEFT JOIN users u ON s.created_by = u.user_id + WHERE s.session_id = ? + `; + + const [rows] = await db.query(sql, [sessionId]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * TBM 세션 수정 + */ + updateSession: async (sessionId, sessionData, callback) => { + try { + const db = await getDb(); + const sql = ` + UPDATE tbm_sessions + SET + project_id = ?, + work_location = ?, + status = ?, + updated_at = NOW() + WHERE session_id = ? + `; + + const values = [ + sessionData.project_id, + sessionData.work_location, + sessionData.status, + sessionId + ]; + + const [result] = await db.query(sql, values); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * TBM 세션 완료 처리 + */ + completeSession: async (sessionId, endTime, callback) => { + try { + const db = await getDb(); + const sql = ` + UPDATE tbm_sessions + SET + status = 'completed', + end_time = ?, + updated_at = NOW() + WHERE session_id = ? + `; + + const [result] = await db.query(sql, [endTime, sessionId]); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + // ==================== 팀 구성 관련 ==================== + + /** + * 팀원 추가 (작업자별 상세 정보 포함) + */ + addTeamMember: async (assignmentData, callback) => { + try { + const db = await getDb(); + const sql = ` + INSERT INTO tbm_team_assignments + (session_id, worker_id, assigned_role, work_detail, is_present, absence_reason, + project_id, work_type_id, task_id, workplace_category_id, workplace_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + ON DUPLICATE KEY UPDATE + assigned_role = VALUES(assigned_role), + work_detail = VALUES(work_detail), + is_present = VALUES(is_present), + absence_reason = VALUES(absence_reason), + project_id = VALUES(project_id), + work_type_id = VALUES(work_type_id), + task_id = VALUES(task_id), + workplace_category_id = VALUES(workplace_category_id), + workplace_id = VALUES(workplace_id) + `; + + const values = [ + assignmentData.session_id, + assignmentData.worker_id, + assignmentData.assigned_role, + assignmentData.work_detail, + assignmentData.is_present !== undefined ? assignmentData.is_present : true, + assignmentData.absence_reason, + assignmentData.project_id || null, + assignmentData.work_type_id || null, + assignmentData.task_id || null, + assignmentData.workplace_category_id || null, + assignmentData.workplace_id || null + ]; + + const [result] = await db.query(sql, values); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * 팀 구성 일괄 추가 (작업자별 상세 정보 포함) + */ + addTeamMembers: async (sessionId, members, callback) => { + try { + if (!members || members.length === 0) { + return callback(null, { affectedRows: 0 }); + } + + const db = await getDb(); + const values = members.map(m => [ + sessionId, + m.worker_id, + m.assigned_role || null, + m.work_detail || null, + m.is_present !== undefined ? m.is_present : true, + m.absence_reason || null, + m.project_id || null, + m.work_type_id || null, + m.task_id || null, + m.workplace_category_id || null, + m.workplace_id || null + ]); + + const sql = ` + INSERT INTO tbm_team_assignments + (session_id, worker_id, assigned_role, work_detail, is_present, absence_reason, + project_id, work_type_id, task_id, workplace_category_id, workplace_id) + VALUES ? + `; + + const [result] = await db.query(sql, [values]); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * TBM 세션의 팀 구성 조회 (작업자별 상세 정보 포함) + */ + getTeamMembers: async (sessionId, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + ta.*, + w.worker_name, + w.job_type, + w.phone_number, + w.department, + p.project_name, + wt.name as work_type_name, + t.task_name, + wc.category_name AS workplace_category_name, + wp.workplace_name + FROM tbm_team_assignments ta + INNER JOIN workers w ON ta.worker_id = w.worker_id + LEFT JOIN projects p ON ta.project_id = p.project_id + LEFT JOIN work_types wt ON ta.work_type_id = wt.id + LEFT JOIN tasks t ON ta.task_id = t.task_id + LEFT JOIN workplace_categories wc ON ta.workplace_category_id = wc.category_id + LEFT JOIN workplaces wp ON ta.workplace_id = wp.workplace_id + WHERE ta.session_id = ? + ORDER BY ta.assigned_at DESC + `; + + const [rows] = await db.query(sql, [sessionId]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * 팀원 제거 + */ + removeTeamMember: async (sessionId, workerId, callback) => { + try { + const db = await getDb(); + const sql = ` + DELETE FROM tbm_team_assignments + WHERE session_id = ? AND worker_id = ? + `; + + const [result] = await db.query(sql, [sessionId, workerId]); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * 세션의 모든 팀원 삭제 + */ + clearAllTeamMembers: async (sessionId, callback) => { + try { + const db = await getDb(); + const sql = ` + DELETE FROM tbm_team_assignments + WHERE session_id = ? + `; + + const [result] = await db.query(sql, [sessionId]); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + // ==================== 안전 체크리스트 관련 ==================== + + /** + * 모든 안전 체크 항목 조회 + */ + getAllSafetyChecks: async (callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT * + FROM tbm_safety_checks + WHERE is_active = 1 + ORDER BY check_category, display_order + `; + + const [rows] = await db.query(sql); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * 카테고리별 안전 체크 항목 조회 + */ + getSafetyChecksByCategory: async (category, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT * + FROM tbm_safety_checks + WHERE check_category = ? AND is_active = 1 + ORDER BY display_order + `; + + const [rows] = await db.query(sql, [category]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * TBM 세션의 안전 체크 기록 조회 + */ + getSafetyRecords: async (sessionId, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + sr.*, + sc.check_category, + sc.check_item, + sc.description, + sc.is_required, + u.username as checked_by_username, + u.name as checked_by_name + FROM tbm_safety_records sr + INNER JOIN tbm_safety_checks sc ON sr.check_id = sc.check_id + LEFT JOIN users u ON sr.checked_by = u.user_id + WHERE sr.session_id = ? + ORDER BY sc.check_category, sc.display_order + `; + + const [rows] = await db.query(sql, [sessionId]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * 안전 체크 기록 저장/업데이트 + */ + saveSafetyRecord: async (recordData, callback) => { + try { + const db = await getDb(); + const sql = ` + INSERT INTO tbm_safety_records + (session_id, check_id, is_checked, notes, checked_by, checked_at) + VALUES (?, ?, ?, ?, ?, NOW()) + ON DUPLICATE KEY UPDATE + is_checked = VALUES(is_checked), + notes = VALUES(notes), + checked_by = VALUES(checked_by), + checked_at = NOW() + `; + + const values = [ + recordData.session_id, + recordData.check_id, + recordData.is_checked, + recordData.notes, + recordData.checked_by + ]; + + const [result] = await db.query(sql, values); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * 안전 체크 일괄 저장 + */ + saveSafetyRecords: async (sessionId, records, checkedBy, callback) => { + try { + if (!records || records.length === 0) { + return callback(null, { affectedRows: 0 }); + } + + const db = await getDb(); + const values = records.map(r => [ + sessionId, + r.check_id, + r.is_checked, + r.notes || null, + checkedBy + ]); + + const sql = ` + INSERT INTO tbm_safety_records + (session_id, check_id, is_checked, notes, checked_by, checked_at) + VALUES ? + ON DUPLICATE KEY UPDATE + is_checked = VALUES(is_checked), + notes = VALUES(notes), + checked_by = VALUES(checked_by), + checked_at = NOW() + `; + + const [result] = await db.query(sql, [values]); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + // ==================== 작업 인계 관련 ==================== + + /** + * 작업 인계 생성 + */ + createHandover: async (handoverData, callback) => { + try { + const db = await getDb(); + const sql = ` + INSERT INTO team_handovers + (session_id, from_leader_id, to_leader_id, handover_date, handover_time, + reason, handover_notes, worker_ids) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + `; + + const values = [ + handoverData.session_id, + handoverData.from_leader_id, + handoverData.to_leader_id, + handoverData.handover_date, + handoverData.handover_time, + handoverData.reason, + handoverData.handover_notes, + JSON.stringify(handoverData.worker_ids || []) + ]; + + const [result] = await db.query(sql, values); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * 작업 인계 확인 + */ + confirmHandover: async (handoverId, confirmedBy, callback) => { + try { + const db = await getDb(); + const sql = ` + UPDATE team_handovers + SET + is_confirmed = 1, + confirmed_at = NOW(), + confirmed_by = ? + WHERE handover_id = ? + `; + + const [result] = await db.query(sql, [confirmedBy, handoverId]); + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * 특정 날짜의 작업 인계 목록 조회 + */ + getHandoversByDate: async (date, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + h.*, + w1.worker_name as from_leader_name, + w2.worker_name as to_leader_name, + u.username as confirmed_by_username, + u.name as confirmed_by_name + FROM team_handovers h + INNER JOIN workers w1 ON h.from_leader_id = w1.worker_id + INNER JOIN workers w2 ON h.to_leader_id = w2.worker_id + LEFT JOIN users u ON h.confirmed_by = u.user_id + WHERE h.handover_date = ? + ORDER BY h.handover_time DESC + `; + + const [rows] = await db.query(sql, [date]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * 인수자가 받은 미확인 인계 건 조회 + */ + getPendingHandovers: async (toLeaderId, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + h.*, + w1.worker_name as from_leader_name, + w1.phone_number as from_leader_phone, + s.work_location + FROM team_handovers h + INNER JOIN workers w1 ON h.from_leader_id = w1.worker_id + LEFT JOIN tbm_sessions s ON h.session_id = s.session_id + WHERE h.to_leader_id = ? AND h.is_confirmed = 0 + ORDER BY h.handover_date DESC, h.handover_time DESC + `; + + const [rows] = await db.query(sql, [toLeaderId]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + // ==================== 통계 및 리포트 ==================== + + /** + * 특정 기간의 TBM 통계 + */ + getTbmStatistics: async (startDate, endDate, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + DATE(session_date) as date, + COUNT(DISTINCT session_id) as session_count, + COUNT(DISTINCT leader_id) as leader_count, + SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed_count + FROM tbm_sessions + WHERE session_date BETWEEN ? AND ? + GROUP BY DATE(session_date) + ORDER BY date DESC + `; + + const [rows] = await db.query(sql, [startDate, endDate]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * 리더별 TBM 진행 현황 + */ + getLeaderStatistics: async (startDate, endDate, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + s.leader_id, + w.worker_name as leader_name, + COUNT(DISTINCT s.session_id) as total_sessions, + SUM(CASE WHEN s.status = 'completed' THEN 1 ELSE 0 END) as completed_sessions, + COUNT(DISTINCT ta.worker_id) as total_team_members + FROM tbm_sessions s + INNER JOIN workers w ON s.leader_id = w.worker_id + LEFT JOIN tbm_team_assignments ta ON s.session_id = ta.session_id + WHERE s.session_date BETWEEN ? AND ? + GROUP BY s.leader_id + ORDER BY total_sessions DESC + `; + + const [rows] = await db.query(sql, [startDate, endDate]); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * 작업보고서가 작성되지 않은 TBM 세션의 팀 배정 조회 + * @param {number|null} userId - 조회할 사용자 ID (null이면 모든 TBM 조회 - 관리자용) + */ + getIncompleteWorkReports: async (userId, callback) => { + try { + const db = await getDb(); + + // WHERE 조건 동적 생성 + let whereClause = ` + WHERE dwr.id IS NULL + AND s.status = 'draft' + `; + const params = []; + + // userId가 있으면 created_by 조건 추가 (일반 사용자) + if (userId !== null && userId !== undefined) { + whereClause = ` + WHERE s.created_by = ? + AND dwr.id IS NULL + AND s.status = 'draft' + `; + params.push(userId); + } + + const sql = ` + SELECT + ta.assignment_id, + ta.session_id, + ta.worker_id, + ta.project_id, + ta.work_type_id, + ta.task_id, + ta.workplace_category_id, + ta.workplace_id, + s.session_date, + s.status as session_status, + s.created_by, + w.worker_name, + w.job_type, + p.project_name, + wt.name as work_type_name, + t.task_name, + wp.workplace_name, + wc.category_name, + creator.name as created_by_name + FROM tbm_team_assignments ta + INNER JOIN tbm_sessions s ON ta.session_id = s.session_id + INNER JOIN workers w ON ta.worker_id = w.worker_id + LEFT JOIN users creator ON s.created_by = creator.user_id + LEFT JOIN projects p ON ta.project_id = p.project_id + LEFT JOIN work_types wt ON ta.work_type_id = wt.id + LEFT JOIN tasks t ON ta.task_id = t.task_id + LEFT JOIN workplaces wp ON ta.workplace_id = wp.workplace_id + LEFT JOIN workplace_categories wc ON ta.workplace_category_id = wc.category_id + LEFT JOIN daily_work_reports dwr ON ta.assignment_id = dwr.tbm_assignment_id + ${whereClause} + ORDER BY s.session_date DESC, ta.assignment_id ASC + `; + + const [rows] = await db.query(sql, params); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + // ========== 안전 체크리스트 확장 메서드 ========== + + /** + * 유형별 안전 체크 항목 조회 + * @param {string} checkType - 체크 유형 (basic, weather, task) + * @param {Object} options - 추가 옵션 (weatherCondition, taskId) + */ + getSafetyChecksByType: async (checkType, options = {}, callback) => { + try { + const db = await getDb(); + let sql = ` + SELECT sc.*, + wc.condition_name as weather_condition_name, + wc.icon as weather_icon, + t.task_name + FROM tbm_safety_checks sc + LEFT JOIN weather_conditions wc ON sc.weather_condition = wc.condition_code + LEFT JOIN tasks t ON sc.task_id = t.task_id + WHERE sc.is_active = 1 AND sc.check_type = ? + `; + const params = [checkType]; + + if (checkType === 'weather' && options.weatherCondition) { + sql += ' AND sc.weather_condition = ?'; + params.push(options.weatherCondition); + } + + if (checkType === 'task' && options.taskId) { + sql += ' AND sc.task_id = ?'; + params.push(options.taskId); + } + + sql += ' ORDER BY sc.check_category, sc.display_order'; + + const [rows] = await db.query(sql, params); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * 날씨 조건별 안전 체크 항목 조회 (복수 조건) + * @param {string[]} conditions - 날씨 조건 배열 ['rain', 'wind'] + */ + getSafetyChecksByWeather: async (conditions, callback) => { + try { + const db = await getDb(); + + if (!conditions || conditions.length === 0) { + return callback(null, []); + } + + const placeholders = conditions.map(() => '?').join(','); + const sql = ` + SELECT sc.*, + wc.condition_name as weather_condition_name, + wc.icon as weather_icon + FROM tbm_safety_checks sc + LEFT JOIN weather_conditions wc ON sc.weather_condition = wc.condition_code + WHERE sc.is_active = 1 + AND sc.check_type = 'weather' + AND sc.weather_condition IN (${placeholders}) + ORDER BY sc.weather_condition, sc.display_order + `; + + const [rows] = await db.query(sql, conditions); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * 작업별 안전 체크 항목 조회 (복수 작업) + * @param {number[]} taskIds - 작업 ID 배열 + */ + getSafetyChecksByTasks: async (taskIds, callback) => { + try { + const db = await getDb(); + + if (!taskIds || taskIds.length === 0) { + return callback(null, []); + } + + const placeholders = taskIds.map(() => '?').join(','); + const sql = ` + SELECT sc.*, + t.task_name, + wt.name as work_type_name + FROM tbm_safety_checks sc + LEFT JOIN tasks t ON sc.task_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + WHERE sc.is_active = 1 + AND sc.check_type = 'task' + AND sc.task_id IN (${placeholders}) + ORDER BY sc.task_id, sc.display_order + `; + + const [rows] = await db.query(sql, taskIds); + callback(null, rows); + } catch (err) { + callback(err); + } + }, + + /** + * TBM 세션에 맞는 필터링된 안전 체크 항목 조회 + * 기본 + 날씨 + 작업별 체크항목 통합 조회 + * @param {number} sessionId - TBM 세션 ID + * @param {string[]} weatherConditions - 날씨 조건 배열 (optional) + */ + getFilteredSafetyChecks: async (sessionId, weatherConditions = [], callback) => { + try { + const db = await getDb(); + + // 1. 세션 정보에서 작업 ID 목록 조회 + const [assignments] = await db.query(` + SELECT DISTINCT task_id + FROM tbm_team_assignments + WHERE session_id = ? AND task_id IS NOT NULL + `, [sessionId]); + + const taskIds = assignments.map(a => a.task_id); + + // 2. 기본 체크항목 조회 + const [basicChecks] = await db.query(` + SELECT sc.*, 'basic' as section_type + FROM tbm_safety_checks sc + WHERE sc.is_active = 1 AND sc.check_type = 'basic' + ORDER BY sc.check_category, sc.display_order + `); + + // 3. 날씨별 체크항목 조회 + let weatherChecks = []; + if (weatherConditions && weatherConditions.length > 0) { + const wcPlaceholders = weatherConditions.map(() => '?').join(','); + const [rows] = await db.query(` + SELECT sc.*, wc.condition_name as weather_condition_name, wc.icon as weather_icon, + 'weather' as section_type + FROM tbm_safety_checks sc + LEFT JOIN weather_conditions wc ON sc.weather_condition = wc.condition_code + WHERE sc.is_active = 1 + AND sc.check_type = 'weather' + AND sc.weather_condition IN (${wcPlaceholders}) + ORDER BY sc.weather_condition, sc.display_order + `, weatherConditions); + weatherChecks = rows; + } + + // 4. 작업별 체크항목 조회 + let taskChecks = []; + if (taskIds.length > 0) { + const taskPlaceholders = taskIds.map(() => '?').join(','); + const [rows] = await db.query(` + SELECT sc.*, t.task_name, wt.name as work_type_name, + 'task' as section_type + FROM tbm_safety_checks sc + LEFT JOIN tasks t ON sc.task_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + WHERE sc.is_active = 1 + AND sc.check_type = 'task' + AND sc.task_id IN (${taskPlaceholders}) + ORDER BY sc.task_id, sc.display_order + `, taskIds); + taskChecks = rows; + } + + // 5. 기존 체크 기록 조회 + const [existingRecords] = await db.query(` + SELECT check_id, is_checked, notes + FROM tbm_safety_records + WHERE session_id = ? + `, [sessionId]); + + const recordMap = {}; + existingRecords.forEach(r => { + recordMap[r.check_id] = { is_checked: r.is_checked, notes: r.notes }; + }); + + // 6. 기록과 병합 + const mergeWithRecords = (checks) => { + return checks.map(check => ({ + ...check, + is_checked: recordMap[check.check_id]?.is_checked || false, + notes: recordMap[check.check_id]?.notes || null + })); + }; + + const result = { + basic: mergeWithRecords(basicChecks), + weather: mergeWithRecords(weatherChecks), + task: mergeWithRecords(taskChecks), + totalCount: basicChecks.length + weatherChecks.length + taskChecks.length, + weatherConditions: weatherConditions + }; + + callback(null, result); + } catch (err) { + callback(err); + } + }, + + /** + * 안전 체크 항목 생성 (관리자용) + */ + createSafetyCheck: async (checkData, callback) => { + try { + const db = await getDb(); + const sql = ` + INSERT INTO tbm_safety_checks + (check_category, check_type, weather_condition, task_id, check_item, description, is_required, display_order) + VALUES (?, ?, ?, ?, ?, ?, ?, ?) + `; + + const values = [ + checkData.check_category, + checkData.check_type || 'basic', + checkData.weather_condition || null, + checkData.task_id || null, + checkData.check_item, + checkData.description || null, + checkData.is_required !== false, + checkData.display_order || 0 + ]; + + const [result] = await db.query(sql, values); + callback(null, { insertId: result.insertId }); + } catch (err) { + callback(err); + } + }, + + /** + * 안전 체크 항목 수정 (관리자용) + */ + updateSafetyCheck: async (checkId, checkData, callback) => { + try { + const db = await getDb(); + const sql = ` + UPDATE tbm_safety_checks + SET check_category = ?, + check_type = ?, + weather_condition = ?, + task_id = ?, + check_item = ?, + description = ?, + is_required = ?, + display_order = ?, + is_active = ?, + updated_at = NOW() + WHERE check_id = ? + `; + + const values = [ + checkData.check_category, + checkData.check_type || 'basic', + checkData.weather_condition || null, + checkData.task_id || null, + checkData.check_item, + checkData.description || null, + checkData.is_required !== false, + checkData.display_order || 0, + checkData.is_active !== false, + checkId + ]; + + const [result] = await db.query(sql, values); + callback(null, { affectedRows: result.affectedRows }); + } catch (err) { + callback(err); + } + }, + + /** + * 안전 체크 항목 삭제 (비활성화) + */ + deleteSafetyCheck: async (checkId, callback) => { + try { + const db = await getDb(); + // 실제 삭제 대신 비활성화 + const sql = `UPDATE tbm_safety_checks SET is_active = 0 WHERE check_id = ?`; + + const [result] = await db.query(sql, [checkId]); + callback(null, { affectedRows: result.affectedRows }); + } catch (err) { + callback(err); + } + } +}; + +module.exports = TbmModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/toolsModel.js b/deploy/tkfb-package/api.hyungi.net/models/toolsModel.js new file mode 100644 index 0000000..957ac3b --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/toolsModel.js @@ -0,0 +1,68 @@ +const { getDb } = require('../dbPool'); + +// 1. 전체 도구 조회 +const getAll = async () => { + const db = await getDb(); + const [rows] = await db.query('SELECT id, name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note FROM Tools'); + return rows; +}; + +// 2. 단일 도구 조회 +const getById = async (id) => { + const db = await getDb(); + const [rows] = await db.query('SELECT id, name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note FROM Tools WHERE id = ?', [id]); + return rows[0]; +}; + +// 3. 도구 생성 +const create = async (tool) => { + const db = await getDb(); + const { name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note } = tool; + + const [result] = await db.query( + `INSERT INTO Tools + (name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note] + ); + + return result.insertId; +}; + +// 4. 도구 수정 +const update = async (id, tool) => { + const db = await getDb(); + const { name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note } = tool; + + const [result] = await db.query( + `UPDATE Tools + SET name = ?, + location = ?, + stock = ?, + status = ?, + factory_id = ?, + map_x = ?, + map_y = ?, + map_zone = ?, + map_note = ? + WHERE id = ?`, + [name, location, stock, status, factory_id, map_x, map_y, map_zone, map_note, id] + ); + + return result.affectedRows; +}; + +// 5. 도구 삭제 +const remove = async (id) => { + const db = await getDb(); + const [result] = await db.query('DELETE FROM Tools WHERE id = ?', [id]); + return result.affectedRows; +}; + +module.exports = { + getAll, + getById, + create, + update, + remove +}; diff --git a/deploy/tkfb-package/api.hyungi.net/models/uploadModel.js b/deploy/tkfb-package/api.hyungi.net/models/uploadModel.js new file mode 100644 index 0000000..24ae0ab --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/uploadModel.js @@ -0,0 +1,36 @@ +const { getDb } = require('../dbPool'); + +// 1. 문서 업로드 +const create = async (doc) => { + const db = await getDb(); + const sql = ` + INSERT INTO uploaded_documents + (title, tags, description, original_name, stored_name, file_path, file_type, file_size, submitted_by) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) + `; + const values = [ + doc.title, + doc.tags, + doc.description, + doc.original_name, + doc.stored_name, + doc.file_path, + doc.file_type, + doc.file_size, + doc.submitted_by + ]; + const [result] = await db.query(sql, values); + return result.insertId; +}; + +// 2. 전체 문서 목록 조회 +const getAll = async () => { + const db = await getDb(); + const [rows] = await db.query(`SELECT * FROM uploaded_documents ORDER BY created_at DESC`); + return rows; +}; + +module.exports = { + create, + getAll +}; diff --git a/deploy/tkfb-package/api.hyungi.net/models/userModel.js b/deploy/tkfb-package/api.hyungi.net/models/userModel.js new file mode 100644 index 0000000..bd4c54f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/userModel.js @@ -0,0 +1,82 @@ +const { getDb } = require('../dbPool'); + +// 사용자 조회 +const findByUsername = async (username) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT u.user_id, u.username, u.password, u.name, u.email, + u.role_id, r.name as role_name, + u._access_level_old as access_level, u.worker_id, u.is_active, + u.last_login_at, u.password_changed_at, u.failed_login_attempts, + u.locked_until, u.created_at, u.updated_at + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + WHERE u.username = ?`, [username] + ); + return rows[0]; + } catch (err) { + console.error('DB 오류 - 사용자 조회 실패:', err); + throw err; + } +}; + +/** + * 로그인 실패 횟수를 1 증가시킵니다. + * @param {number} userId - 사용자 ID + */ +const incrementFailedLoginAttempts = async (userId) => { + try { + const db = await getDb(); + await db.query( + 'UPDATE users SET failed_login_attempts = failed_login_attempts + 1 WHERE user_id = ?', + [userId] + ); + } catch (err) { + console.error('DB 오류 - 로그인 실패 횟수 증가 실패:', err); + throw err; + } +}; + +/** + * 특정 사용자의 계정을 잠급니다. + * @param {number} userId - 사용자 ID + */ +const lockUserAccount = async (userId) => { + try { + const db = await getDb(); + await db.query( + 'UPDATE users SET locked_until = DATE_ADD(NOW(), INTERVAL 15 MINUTE) WHERE user_id = ?', + [userId] + ); + } catch (err) { + console.error('DB 오류 - 계정 잠금 실패:', err); + throw err; + } +}; + +/** + * 로그인 성공 시, 마지막 로그인 시간을 업데이트하고 실패 횟수와 잠금 상태를 초기화합니다. + * @param {number} userId - 사용자 ID + */ +const resetLoginAttempts = async (userId) => { + try { + const db = await getDb(); + await db.query( + 'UPDATE users SET last_login_at = NOW(), failed_login_attempts = 0, locked_until = NULL WHERE user_id = ?', + [userId] + ); + } catch (err) { + console.error('DB 오류 - 로그인 상태 초기화 실패:', err); + throw err; + } +}; + + +// 명확한 내보내기 +module.exports = { + findByUsername, + incrementFailedLoginAttempts, + lockUserAccount, + resetLoginAttempts +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/models/vacationBalanceModel.js b/deploy/tkfb-package/api.hyungi.net/models/vacationBalanceModel.js new file mode 100644 index 0000000..d342417 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/vacationBalanceModel.js @@ -0,0 +1,400 @@ +/** + * vacationBalanceModel.js + * 휴가 잔액 관련 데이터베이스 쿼리 모델 + */ + +const { getDb } = require('../dbPool'); + +const vacationBalanceModel = { + /** + * 특정 작업자의 모든 휴가 잔액 조회 (특정 연도) + */ + async getByWorkerAndYear(workerId, year, callback) { + try { + const db = await getDb(); + const query = ` + SELECT + vbd.*, + vt.type_name, + vt.type_code, + vt.priority, + vt.is_special + FROM vacation_balance_details vbd + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.worker_id = ? AND vbd.year = ? + ORDER BY vt.priority ASC, vt.type_name ASC + `; + const [rows] = await db.query(query, [workerId, year]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 특정 작업자의 특정 휴가 유형 잔액 조회 + */ + async getByWorkerTypeYear(workerId, vacationTypeId, year, callback) { + try { + const db = await getDb(); + const query = ` + SELECT + vbd.*, + vt.type_name, + vt.type_code + FROM vacation_balance_details vbd + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.worker_id = ? + AND vbd.vacation_type_id = ? + AND vbd.year = ? + `; + const [rows] = await db.query(query, [workerId, vacationTypeId, year]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 모든 작업자의 휴가 잔액 조회 (특정 연도) + * - 연간 연차 현황 차트용 + */ + async getAllByYear(year, callback) { + try { + const db = await getDb(); + const query = ` + SELECT + vbd.*, + w.worker_name, + w.employment_status, + vt.type_name, + vt.type_code, + vt.priority + FROM vacation_balance_details vbd + INNER JOIN workers w ON vbd.worker_id = w.worker_id + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.year = ? + AND w.employment_status = 'employed' + ORDER BY w.worker_name ASC, vt.priority ASC + `; + const [rows] = await db.query(query, [year]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 잔액 생성 + */ + async create(balanceData, callback) { + try { + const db = await getDb(); + const query = `INSERT INTO vacation_balance_details SET ?`; + const [rows] = await db.query(query, balanceData); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 잔액 수정 + */ + async update(id, updateData, callback) { + try { + const db = await getDb(); + const query = `UPDATE vacation_balance_details SET ? WHERE id = ?`; + const [rows] = await db.query(query, [updateData, id]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 잔액 삭제 + */ + async delete(id, callback) { + try { + const db = await getDb(); + const query = `DELETE FROM vacation_balance_details WHERE id = ?`; + const [rows] = await db.query(query, [id]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 작업자의 휴가 사용 일수 업데이트 (차감) + * - 휴가 신청 승인 시 호출 + */ + async deductDays(workerId, vacationTypeId, year, daysToDeduct, callback) { + try { + const db = await getDb(); + const query = ` + UPDATE vacation_balance_details + SET used_days = used_days + ?, + updated_at = NOW() + WHERE worker_id = ? + AND vacation_type_id = ? + AND year = ? + `; + const [rows] = await db.query(query, [daysToDeduct, workerId, vacationTypeId, year]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 작업자의 휴가 사용 일수 복구 (취소) + * - 휴가 신청 취소/거부 시 호출 + */ + async restoreDays(workerId, vacationTypeId, year, daysToRestore, callback) { + try { + const db = await getDb(); + const query = ` + UPDATE vacation_balance_details + SET used_days = GREATEST(0, used_days - ?), + updated_at = NOW() + WHERE worker_id = ? + AND vacation_type_id = ? + AND year = ? + `; + const [rows] = await db.query(query, [daysToRestore, workerId, vacationTypeId, year]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 특정 작업자의 사용 가능한 휴가 일수 확인 + * - 우선순위가 높은 순서대로 차감 가능 여부 확인 + */ + async getAvailableVacationDays(workerId, year, callback) { + try { + const db = await getDb(); + const query = ` + SELECT + vbd.id, + vbd.vacation_type_id, + vt.type_name, + vt.type_code, + vt.priority, + vbd.total_days, + vbd.used_days, + vbd.remaining_days + FROM vacation_balance_details vbd + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.worker_id = ? + AND vbd.year = ? + AND vbd.remaining_days > 0 + ORDER BY vt.priority ASC + `; + const [rows] = await db.query(query, [workerId, year]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 작업자별 휴가 잔액 일괄 생성 (연도별) + * - 매년 초 또는 입사 시 사용 + */ + async bulkCreate(balances, callback) { + try { + const db = await getDb(); + + if (!balances || balances.length === 0) { + return callback(new Error('생성할 휴가 잔액 데이터가 없습니다')); + } + + const query = `INSERT INTO vacation_balance_details + (worker_id, vacation_type_id, year, total_days, used_days, notes, created_by) + VALUES ?`; + + const values = balances.map(b => [ + b.worker_id, + b.vacation_type_id, + b.year, + b.total_days || 0, + b.used_days || 0, + b.notes || null, + b.created_by + ]); + + const [rows] = await db.query(query, [values]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 근속년수 기반 연차 일수 계산 (한국 근로기준법) + * @param {Date} hireDate - 입사일 + * @param {number} targetYear - 대상 연도 + * @returns {number} - 부여받을 연차 일수 + */ + calculateAnnualLeaveDays(hireDate, targetYear) { + const hire = new Date(hireDate); + const targetDate = new Date(targetYear, 0, 1); + + // 근속 월수 계산 + const monthsDiff = (targetDate.getFullYear() - hire.getFullYear()) * 12 + + (targetDate.getMonth() - hire.getMonth()); + + // 1년 미만: 월 1일 + if (monthsDiff < 12) { + return Math.floor(monthsDiff); + } + + // 1년 이상: 15일 기본 + 2년마다 1일 추가 (최대 25일) + const yearsWorked = Math.floor(monthsDiff / 12); + const additionalDays = Math.floor((yearsWorked - 1) / 2); + + return Math.min(15 + additionalDays, 25); + }, + + /** + * 휴가 사용 시 우선순위에 따라 잔액에서 차감 (Promise 버전) + * - 일일 근태 기록 저장 시 호출 + * @param {number} workerId - 작업자 ID + * @param {number} year - 연도 + * @param {number} daysToDeduct - 차감할 일수 (1, 0.5, 0.25) + * @returns {Promise} - 차감 결과 + */ + async deductByPriority(workerId, year, daysToDeduct) { + const db = await getDb(); + + // 우선순위순으로 잔여 일수가 있는 잔액 조회 + const [balances] = await db.query(` + SELECT vbd.id, vbd.vacation_type_id, vbd.total_days, vbd.used_days, + (vbd.total_days - vbd.used_days) as remaining_days, + vt.type_code, vt.type_name, vt.priority + FROM vacation_balance_details vbd + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.worker_id = ? AND vbd.year = ? + AND (vbd.total_days - vbd.used_days) > 0 + ORDER BY vt.priority ASC + `, [workerId, year]); + + if (balances.length === 0) { + // 잔액이 없어도 일단 기록은 저장 (경고만) + console.warn(`[VacationBalance] 작업자 ${workerId}의 ${year}년 휴가 잔액이 없습니다`); + return { success: false, message: '휴가 잔액이 없습니다', deducted: 0 }; + } + + let remaining = daysToDeduct; + const deductions = []; + + for (const balance of balances) { + if (remaining <= 0) break; + + const available = parseFloat(balance.remaining_days); + const toDeduct = Math.min(remaining, available); + + if (toDeduct > 0) { + await db.query(` + UPDATE vacation_balance_details + SET used_days = used_days + ?, updated_at = NOW() + WHERE id = ? + `, [toDeduct, balance.id]); + + deductions.push({ + balance_id: balance.id, + type_code: balance.type_code, + type_name: balance.type_name, + deducted: toDeduct + }); + + remaining -= toDeduct; + } + } + + console.log(`[VacationBalance] 작업자 ${workerId}: ${daysToDeduct}일 차감 완료`, deductions); + return { success: true, deductions, totalDeducted: daysToDeduct - remaining }; + }, + + /** + * 휴가 취소 시 우선순위 역순으로 복구 (Promise 버전) + * @param {number} workerId - 작업자 ID + * @param {number} year - 연도 + * @param {number} daysToRestore - 복구할 일수 + * @returns {Promise} - 복구 결과 + */ + async restoreByPriority(workerId, year, daysToRestore) { + const db = await getDb(); + + // 우선순위 역순으로 사용 일수가 있는 잔액 조회 (나중에 차감된 것부터 복구) + const [balances] = await db.query(` + SELECT vbd.id, vbd.vacation_type_id, vbd.used_days, + vt.type_code, vt.type_name, vt.priority + FROM vacation_balance_details vbd + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.worker_id = ? AND vbd.year = ? + AND vbd.used_days > 0 + ORDER BY vt.priority DESC + `, [workerId, year]); + + let remaining = daysToRestore; + const restorations = []; + + for (const balance of balances) { + if (remaining <= 0) break; + + const usedDays = parseFloat(balance.used_days); + const toRestore = Math.min(remaining, usedDays); + + if (toRestore > 0) { + await db.query(` + UPDATE vacation_balance_details + SET used_days = used_days - ?, updated_at = NOW() + WHERE id = ? + `, [toRestore, balance.id]); + + restorations.push({ + balance_id: balance.id, + type_code: balance.type_code, + type_name: balance.type_name, + restored: toRestore + }); + + remaining -= toRestore; + } + } + + console.log(`[VacationBalance] 작업자 ${workerId}: ${daysToRestore}일 복구 완료`, restorations); + return { success: true, restorations, totalRestored: daysToRestore - remaining }; + }, + + /** + * 특정 ID로 휴가 잔액 조회 + */ + async getById(id, callback) { + try { + const db = await getDb(); + const query = ` + SELECT + vbd.*, + w.worker_name, + vt.type_name, + vt.type_code + FROM vacation_balance_details vbd + INNER JOIN workers w ON vbd.worker_id = w.worker_id + INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id + WHERE vbd.id = ? + `; + const [rows] = await db.query(query, [id]); + callback(null, rows); + } catch (error) { + callback(error); + } + } +}; + +module.exports = vacationBalanceModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/vacationRequestModel.js b/deploy/tkfb-package/api.hyungi.net/models/vacationRequestModel.js new file mode 100644 index 0000000..adee31c --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/vacationRequestModel.js @@ -0,0 +1,271 @@ +/** + * vacationRequestModel.js + * 휴가 신청 관련 데이터베이스 쿼리 모델 + */ + +const { getDb } = require('../dbPool'); + +const vacationRequestModel = { + /** + * 휴가 신청 생성 + */ + async create(requestData, callback) { + try { + const db = await getDb(); + const query = `INSERT INTO vacation_requests SET ?`; + const [result] = await db.query(query, requestData); + callback(null, result); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 신청 목록 조회 (필터링 지원) + */ + async getAll(filters = {}, callback) { + try { + const db = await getDb(); + + let query = ` + SELECT + vr.*, + w.worker_name, + vt.type_name as vacation_type_name, + vt.deduct_days as vacation_deduct_days, + requester.name as requester_name, + reviewer.name as reviewer_name + FROM vacation_requests vr + INNER JOIN workers w ON vr.worker_id = w.worker_id + INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id + LEFT JOIN users requester ON vr.requested_by = requester.user_id + LEFT JOIN users reviewer ON vr.reviewed_by = reviewer.user_id + WHERE 1=1 + `; + + const params = []; + + // 작업자 필터 + if (filters.worker_id) { + query += ` AND vr.worker_id = ?`; + params.push(filters.worker_id); + } + + // 상태 필터 + if (filters.status) { + query += ` AND vr.status = ?`; + params.push(filters.status); + } + + // 기간 필터 + if (filters.start_date) { + query += ` AND vr.start_date >= ?`; + params.push(filters.start_date); + } + + if (filters.end_date) { + query += ` AND vr.end_date <= ?`; + params.push(filters.end_date); + } + + // 휴가 유형 필터 + if (filters.vacation_type_id) { + query += ` AND vr.vacation_type_id = ?`; + params.push(filters.vacation_type_id); + } + + query += ` ORDER BY vr.created_at DESC`; + + const [rows] = await db.query(query, params); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 특정 휴가 신청 조회 + */ + async getById(requestId, callback) { + try { + const db = await getDb(); + const query = ` + SELECT + vr.*, + w.worker_name, + w.phone_number as worker_phone, + w.email as worker_email, + vt.type_name as vacation_type_name, + vt.type_code as vacation_type_code, + vt.deduct_days as vacation_deduct_days, + requester.name as requester_name, + requester.username as requester_username, + reviewer.name as reviewer_name, + reviewer.username as reviewer_username + FROM vacation_requests vr + INNER JOIN workers w ON vr.worker_id = w.worker_id + INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id + LEFT JOIN users requester ON vr.requested_by = requester.user_id + LEFT JOIN users reviewer ON vr.reviewed_by = reviewer.user_id + WHERE vr.request_id = ? + `; + const [rows] = await db.query(query, [requestId]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 신청 수정 + */ + async update(requestId, updateData, callback) { + try { + const db = await getDb(); + const query = `UPDATE vacation_requests SET ? WHERE request_id = ?`; + const [result] = await db.query(query, [updateData, requestId]); + callback(null, result); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 신청 삭제 + */ + async delete(requestId, callback) { + try { + const db = await getDb(); + const query = `DELETE FROM vacation_requests WHERE request_id = ?`; + const [result] = await db.query(query, [requestId]); + callback(null, result); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 신청 승인/거부 + */ + async updateStatus(requestId, statusData, callback) { + try { + const db = await getDb(); + const query = ` + UPDATE vacation_requests + SET + status = ?, + reviewed_by = ?, + reviewed_at = NOW(), + review_note = ? + WHERE request_id = ? + `; + const [result] = await db.query(query, [ + statusData.status, + statusData.reviewed_by, + statusData.review_note || null, + requestId + ]); + callback(null, result); + } catch (error) { + callback(error); + } + }, + + /** + * 특정 작업자의 대기 중인 휴가 신청 수 + */ + async getPendingCount(workerId, callback) { + try { + const db = await getDb(); + const query = ` + SELECT COUNT(*) as count + FROM vacation_requests + WHERE worker_id = ? AND status = 'pending' + `; + const [rows] = await db.query(query, [workerId]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 특정 작업자의 승인된 휴가 일수 합계 (특정 기간) + */ + async getApprovedDaysInPeriod(workerId, startDate, endDate, callback) { + try { + const db = await getDb(); + const query = ` + SELECT COALESCE(SUM(days_used), 0) as total_days + FROM vacation_requests + WHERE worker_id = ? + AND status = 'approved' + AND start_date >= ? + AND end_date <= ? + `; + const [rows] = await db.query(query, [workerId, startDate, endDate]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 기간 중복 체크 + */ + async checkOverlap(workerId, startDate, endDate, excludeRequestId = null, callback) { + try { + const db = await getDb(); + let query = ` + SELECT COUNT(*) as count + FROM vacation_requests + WHERE worker_id = ? + AND status IN ('pending', 'approved') + AND ( + (start_date <= ? AND end_date >= ?) OR + (start_date <= ? AND end_date >= ?) OR + (start_date >= ? AND end_date <= ?) + ) + `; + const params = [workerId, startDate, startDate, endDate, endDate, startDate, endDate]; + + if (excludeRequestId) { + query += ` AND request_id != ?`; + params.push(excludeRequestId); + } + + const [rows] = await db.query(query, params); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 모든 대기 중인 휴가 신청 (관리자용) + */ + async getAllPending(callback) { + try { + const db = await getDb(); + const query = ` + SELECT + vr.*, + w.worker_name, + vt.type_name as vacation_type_name, + requester.name as requester_name + FROM vacation_requests vr + INNER JOIN workers w ON vr.worker_id = w.worker_id + INNER JOIN vacation_types vt ON vr.vacation_type_id = vt.id + LEFT JOIN users requester ON vr.requested_by = requester.user_id + WHERE vr.status = 'pending' + ORDER BY vr.created_at ASC + `; + const [rows] = await db.query(query); + callback(null, rows); + } catch (error) { + callback(error); + } + } +}; + +module.exports = vacationRequestModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/vacationTypeModel.js b/deploy/tkfb-package/api.hyungi.net/models/vacationTypeModel.js new file mode 100644 index 0000000..9ecce63 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/vacationTypeModel.js @@ -0,0 +1,132 @@ +/** + * vacationTypeModel.js + * 휴가 유형 관련 데이터베이스 쿼리 모델 + */ + +const { getDb } = require('../dbPool'); + +const vacationTypeModel = { + /** + * 모든 활성 휴가 유형 조회 (우선순위 순서대로) + */ + async getAll(callback) { + try { + const db = await getDb(); + const query = ` + SELECT * + FROM vacation_types + WHERE is_active = 1 + ORDER BY priority ASC, id ASC + `; + const [rows] = await db.query(query); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 시스템 기본 휴가 유형만 조회 + */ + async getSystemTypes(callback) { + try { + const db = await getDb(); + const query = ` + SELECT * + FROM vacation_types + WHERE is_system = 1 AND is_active = 1 + ORDER BY priority ASC + `; + const [rows] = await db.query(query); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 특정 ID로 휴가 유형 조회 + */ + async getById(id, callback) { + try { + const db = await getDb(); + const query = `SELECT * FROM vacation_types WHERE id = ?`; + const [rows] = await db.query(query, [id]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 유형 코드로 조회 + */ + async getByCode(code, callback) { + try { + const db = await getDb(); + const query = `SELECT * FROM vacation_types WHERE type_code = ?`; + const [rows] = await db.query(query, [code]); + callback(null, rows); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 유형 생성 + */ + async create(typeData, callback) { + try { + const db = await getDb(); + const query = `INSERT INTO vacation_types SET ?`; + const [result] = await db.query(query, typeData); + callback(null, result); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 유형 수정 + */ + async update(id, updateData, callback) { + try { + const db = await getDb(); + const query = `UPDATE vacation_types SET ? WHERE id = ?`; + const [result] = await db.query(query, [updateData, id]); + callback(null, result); + } catch (error) { + callback(error); + } + }, + + /** + * 휴가 유형 삭제 (논리적 삭제 - is_active = 0) + */ + async delete(id, callback) { + try { + const db = await getDb(); + const query = `UPDATE vacation_types SET is_active = 0, updated_at = NOW() WHERE id = ?`; + const [result] = await db.query(query, [id]); + callback(null, result); + } catch (error) { + callback(error); + } + }, + + /** + * 우선순위 업데이트 + */ + async updatePriority(id, priority, callback) { + try { + const db = await getDb(); + const query = `UPDATE vacation_types SET priority = ?, updated_at = NOW() WHERE id = ?`; + const [result] = await db.query(query, [priority, id]); + callback(null, result); + } catch (error) { + callback(error); + } + } +}; + +module.exports = vacationTypeModel; diff --git a/deploy/tkfb-package/api.hyungi.net/models/visitRequestModel.js b/deploy/tkfb-package/api.hyungi.net/models/visitRequestModel.js new file mode 100644 index 0000000..87bb6c9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/visitRequestModel.js @@ -0,0 +1,505 @@ +const { getDb } = require('../dbPool'); + +// ==================== 출입 신청 관리 ==================== + +/** + * 출입 신청 생성 + */ +const createVisitRequest = async (requestData, callback) => { + try { + const db = await getDb(); + const { + requester_id, + visitor_company, + visitor_count = 1, + category_id, + workplace_id, + visit_date, + visit_time, + purpose_id, + notes = null + } = requestData; + + const [result] = await db.query( + `INSERT INTO workplace_visit_requests + (requester_id, visitor_company, visitor_count, category_id, workplace_id, + visit_date, visit_time, purpose_id, notes) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [requester_id, visitor_company, visitor_count, category_id, workplace_id, + visit_date, visit_time, purpose_id, notes] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 출입 신청 목록 조회 (필터 옵션 포함) + */ +const getAllVisitRequests = async (filters = {}, callback) => { + try { + const db = await getDb(); + let query = ` + SELECT + vr.request_id, vr.requester_id, vr.visitor_company, vr.visitor_count, + vr.category_id, vr.workplace_id, vr.visit_date, vr.visit_time, + vr.purpose_id, vr.notes, vr.status, + vr.approved_by, vr.approved_at, vr.rejection_reason, + vr.created_at, vr.updated_at, + u.username as requester_name, u.name as requester_full_name, + wc.category_name, w.workplace_name, + vpt.purpose_name, + approver.username as approver_name + FROM workplace_visit_requests vr + INNER JOIN users u ON vr.requester_id = u.user_id + INNER JOIN workplace_categories wc ON vr.category_id = wc.category_id + INNER JOIN workplaces w ON vr.workplace_id = w.workplace_id + INNER JOIN visit_purpose_types vpt ON vr.purpose_id = vpt.purpose_id + LEFT JOIN users approver ON vr.approved_by = approver.user_id + WHERE 1=1 + `; + + const params = []; + + // 필터 적용 + if (filters.status) { + query += ` AND vr.status = ?`; + params.push(filters.status); + } + + if (filters.visit_date) { + query += ` AND vr.visit_date = ?`; + params.push(filters.visit_date); + } + + if (filters.start_date && filters.end_date) { + query += ` AND vr.visit_date BETWEEN ? AND ?`; + params.push(filters.start_date, filters.end_date); + } + + if (filters.requester_id) { + query += ` AND vr.requester_id = ?`; + params.push(filters.requester_id); + } + + if (filters.category_id) { + query += ` AND vr.category_id = ?`; + params.push(filters.category_id); + } + + query += ` ORDER BY vr.visit_date DESC, vr.visit_time DESC, vr.created_at DESC`; + + const [rows] = await db.query(query, params); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 출입 신청 상세 조회 + */ +const getVisitRequestById = async (requestId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT + vr.request_id, vr.requester_id, vr.visitor_company, vr.visitor_count, + vr.category_id, vr.workplace_id, vr.visit_date, vr.visit_time, + vr.purpose_id, vr.notes, vr.status, + vr.approved_by, vr.approved_at, vr.rejection_reason, + vr.created_at, vr.updated_at, + u.username as requester_name, u.name as requester_full_name, + wc.category_name, w.workplace_name, + vpt.purpose_name, + approver.username as approver_name + FROM workplace_visit_requests vr + INNER JOIN users u ON vr.requester_id = u.user_id + INNER JOIN workplace_categories wc ON vr.category_id = wc.category_id + INNER JOIN workplaces w ON vr.workplace_id = w.workplace_id + INNER JOIN visit_purpose_types vpt ON vr.purpose_id = vpt.purpose_id + LEFT JOIN users approver ON vr.approved_by = approver.user_id + WHERE vr.request_id = ?`, + [requestId] + ); + + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 출입 신청 수정 + */ +const updateVisitRequest = async (requestId, requestData, callback) => { + try { + const db = await getDb(); + const { + visitor_company, + visitor_count, + category_id, + workplace_id, + visit_date, + visit_time, + purpose_id, + notes + } = requestData; + + const [result] = await db.query( + `UPDATE workplace_visit_requests + SET visitor_company = ?, visitor_count = ?, category_id = ?, workplace_id = ?, + visit_date = ?, visit_time = ?, purpose_id = ?, notes = ?, updated_at = NOW() + WHERE request_id = ?`, + [visitor_company, visitor_count, category_id, workplace_id, + visit_date, visit_time, purpose_id, notes, requestId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 출입 신청 삭제 + */ +const deleteVisitRequest = async (requestId, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM workplace_visit_requests WHERE request_id = ?`, + [requestId] + ); + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 출입 신청 승인 + */ +const approveVisitRequest = async (requestId, approvedBy, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `UPDATE workplace_visit_requests + SET status = 'approved', approved_by = ?, approved_at = NOW(), updated_at = NOW() + WHERE request_id = ?`, + [approvedBy, requestId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 출입 신청 반려 + */ +const rejectVisitRequest = async (requestId, rejectionData, callback) => { + try { + const db = await getDb(); + const { approved_by, rejection_reason } = rejectionData; + + const [result] = await db.query( + `UPDATE workplace_visit_requests + SET status = 'rejected', approved_by = ?, approved_at = NOW(), + rejection_reason = ?, updated_at = NOW() + WHERE request_id = ?`, + [approved_by, rejection_reason, requestId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 출입 신청 상태 변경 + */ +const updateVisitRequestStatus = async (requestId, status, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `UPDATE workplace_visit_requests + SET status = ?, updated_at = NOW() + WHERE request_id = ?`, + [status, requestId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +// ==================== 방문 목적 관리 ==================== + +/** + * 모든 방문 목적 조회 + */ +const getAllVisitPurposes = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT purpose_id, purpose_name, display_order, is_active, created_at + FROM visit_purpose_types + ORDER BY display_order ASC, purpose_id ASC` + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 활성 방문 목적만 조회 + */ +const getActiveVisitPurposes = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT purpose_id, purpose_name, display_order, is_active, created_at + FROM visit_purpose_types + WHERE is_active = TRUE + ORDER BY display_order ASC, purpose_id ASC` + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 방문 목적 추가 + */ +const createVisitPurpose = async (purposeData, callback) => { + try { + const db = await getDb(); + const { purpose_name, display_order = 0, is_active = true } = purposeData; + + const [result] = await db.query( + `INSERT INTO visit_purpose_types (purpose_name, display_order, is_active) + VALUES (?, ?, ?)`, + [purpose_name, display_order, is_active] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 방문 목적 수정 + */ +const updateVisitPurpose = async (purposeId, purposeData, callback) => { + try { + const db = await getDb(); + const { purpose_name, display_order, is_active } = purposeData; + + const [result] = await db.query( + `UPDATE visit_purpose_types + SET purpose_name = ?, display_order = ?, is_active = ? + WHERE purpose_id = ?`, + [purpose_name, display_order, is_active, purposeId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 방문 목적 삭제 + */ +const deleteVisitPurpose = async (purposeId, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM visit_purpose_types WHERE purpose_id = ?`, + [purposeId] + ); + callback(null, result); + } catch (err) { + callback(err); + } +}; + +// ==================== 안전교육 기록 관리 ==================== + +/** + * 안전교육 기록 생성 + */ +const createTrainingRecord = async (trainingData, callback) => { + try { + const db = await getDb(); + const { + request_id, + trainer_id, + training_date, + training_start_time, + training_end_time = null, + training_topics = null + } = trainingData; + + const [result] = await db.query( + `INSERT INTO safety_training_records + (request_id, trainer_id, training_date, training_start_time, training_end_time, training_topics) + VALUES (?, ?, ?, ?, ?, ?)`, + [request_id, trainer_id, training_date, training_start_time, training_end_time, training_topics] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 특정 출입 신청의 안전교육 기록 조회 + */ +const getTrainingRecordByRequestId = async (requestId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT + str.training_id, str.request_id, str.trainer_id, str.training_date, + str.training_start_time, str.training_end_time, str.training_topics, + str.signature_data, str.completed_at, str.created_at, str.updated_at, + u.username as trainer_name, u.name as trainer_full_name + FROM safety_training_records str + INNER JOIN users u ON str.trainer_id = u.user_id + WHERE str.request_id = ?`, + [requestId] + ); + + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 안전교육 기록 수정 + */ +const updateTrainingRecord = async (trainingId, trainingData, callback) => { + try { + const db = await getDb(); + const { + training_date, + training_start_time, + training_end_time, + training_topics + } = trainingData; + + const [result] = await db.query( + `UPDATE safety_training_records + SET training_date = ?, training_start_time = ?, training_end_time = ?, + training_topics = ?, updated_at = NOW() + WHERE training_id = ?`, + [training_date, training_start_time, training_end_time, training_topics, trainingId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 안전교육 완료 (서명 포함) + */ +const completeTraining = async (trainingId, signatureData, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `UPDATE safety_training_records + SET signature_data = ?, completed_at = NOW(), updated_at = NOW() + WHERE training_id = ?`, + [signatureData, trainingId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 안전교육 목록 조회 (날짜별 필터) + */ +const getTrainingRecords = async (filters = {}, callback) => { + try { + const db = await getDb(); + let query = ` + SELECT + str.training_id, str.request_id, str.trainer_id, str.training_date, + str.training_start_time, str.training_end_time, str.training_topics, + str.completed_at, str.created_at, str.updated_at, + u.username as trainer_name, u.name as trainer_full_name, + vr.visitor_company, vr.visitor_count, vr.visit_date + FROM safety_training_records str + INNER JOIN users u ON str.trainer_id = u.user_id + INNER JOIN workplace_visit_requests vr ON str.request_id = vr.request_id + WHERE 1=1 + `; + + const params = []; + + if (filters.training_date) { + query += ` AND str.training_date = ?`; + params.push(filters.training_date); + } + + if (filters.start_date && filters.end_date) { + query += ` AND str.training_date BETWEEN ? AND ?`; + params.push(filters.start_date, filters.end_date); + } + + if (filters.trainer_id) { + query += ` AND str.trainer_id = ?`; + params.push(filters.trainer_id); + } + + query += ` ORDER BY str.training_date DESC, str.training_start_time DESC`; + + const [rows] = await db.query(query, params); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +module.exports = { + // 출입 신청 + createVisitRequest, + getAllVisitRequests, + getVisitRequestById, + updateVisitRequest, + deleteVisitRequest, + approveVisitRequest, + rejectVisitRequest, + updateVisitRequestStatus, + + // 방문 목적 + getAllVisitPurposes, + getActiveVisitPurposes, + createVisitPurpose, + updateVisitPurpose, + deleteVisitPurpose, + + // 안전교육 + createTrainingRecord, + getTrainingRecordByRequestId, + updateTrainingRecord, + completeTraining, + getTrainingRecords +}; diff --git a/deploy/tkfb-package/api.hyungi.net/models/workIssueModel.js b/deploy/tkfb-package/api.hyungi.net/models/workIssueModel.js new file mode 100644 index 0000000..34ec5ef --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/workIssueModel.js @@ -0,0 +1,887 @@ +/** + * 작업 중 문제 신고 모델 + * 부적합/안전 신고 관련 DB 쿼리 + */ + +const { getDb } = require('../dbPool'); + +// ==================== 신고 카테고리 관리 ==================== + +/** + * 모든 신고 카테고리 조회 + */ +const getAllCategories = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT category_id, category_type, category_name, description, display_order, is_active, created_at + FROM issue_report_categories + ORDER BY category_type, display_order, category_id` + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 타입별 활성 카테고리 조회 (nonconformity/safety) + */ +const getCategoriesByType = async (categoryType, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT category_id, category_type, category_name, description, display_order + FROM issue_report_categories + WHERE category_type = ? AND is_active = TRUE + ORDER BY display_order, category_id`, + [categoryType] + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 카테고리 생성 + */ +const createCategory = async (categoryData, callback) => { + try { + const db = await getDb(); + const { category_type, category_name, description = null, display_order = 0 } = categoryData; + + const [result] = await db.query( + `INSERT INTO issue_report_categories (category_type, category_name, description, display_order) + VALUES (?, ?, ?, ?)`, + [category_type, category_name, description, display_order] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 카테고리 수정 + */ +const updateCategory = async (categoryId, categoryData, callback) => { + try { + const db = await getDb(); + const { category_name, description, display_order, is_active } = categoryData; + + const [result] = await db.query( + `UPDATE issue_report_categories + SET category_name = ?, description = ?, display_order = ?, is_active = ? + WHERE category_id = ?`, + [category_name, description, display_order, is_active, categoryId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 카테고리 삭제 + */ +const deleteCategory = async (categoryId, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM issue_report_categories WHERE category_id = ?`, + [categoryId] + ); + callback(null, result); + } catch (err) { + callback(err); + } +}; + +// ==================== 사전 정의 신고 항목 관리 ==================== + +/** + * 카테고리별 활성 항목 조회 + */ +const getItemsByCategory = async (categoryId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT item_id, category_id, item_name, description, severity, display_order + FROM issue_report_items + WHERE category_id = ? AND is_active = TRUE + ORDER BY display_order, item_id`, + [categoryId] + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 모든 항목 조회 (관리용) + */ +const getAllItems = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT iri.item_id, iri.category_id, iri.item_name, iri.description, + iri.severity, iri.display_order, iri.is_active, iri.created_at, + irc.category_name, irc.category_type + FROM issue_report_items iri + INNER JOIN issue_report_categories irc ON iri.category_id = irc.category_id + ORDER BY irc.category_type, irc.display_order, iri.display_order, iri.item_id` + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 항목 생성 + */ +const createItem = async (itemData, callback) => { + try { + const db = await getDb(); + const { category_id, item_name, description = null, severity = 'medium', display_order = 0 } = itemData; + + const [result] = await db.query( + `INSERT INTO issue_report_items (category_id, item_name, description, severity, display_order) + VALUES (?, ?, ?, ?, ?)`, + [category_id, item_name, description, severity, display_order] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 항목 수정 + */ +const updateItem = async (itemId, itemData, callback) => { + try { + const db = await getDb(); + const { item_name, description, severity, display_order, is_active } = itemData; + + const [result] = await db.query( + `UPDATE issue_report_items + SET item_name = ?, description = ?, severity = ?, display_order = ?, is_active = ? + WHERE item_id = ?`, + [item_name, description, severity, display_order, is_active, itemId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 항목 삭제 + */ +const deleteItem = async (itemId, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM issue_report_items WHERE item_id = ?`, + [itemId] + ); + callback(null, result); + } catch (err) { + callback(err); + } +}; + +// ==================== 문제 신고 관리 ==================== + +// 한국 시간 유틸리티 import +const { getKoreaDatetime } = require('../utils/dateUtils'); + +/** + * 신고 생성 + */ +const createReport = async (reportData, callback) => { + try { + const db = await getDb(); + const { + reporter_id, + factory_category_id = null, + workplace_id = null, + custom_location = null, + tbm_session_id = null, + visit_request_id = null, + issue_category_id, + issue_item_id = null, + additional_description = null, + photo_path1 = null, + photo_path2 = null, + photo_path3 = null, + photo_path4 = null, + photo_path5 = null + } = reportData; + + // 한국 시간 기준으로 신고 일시 설정 + const reportDate = getKoreaDatetime(); + + const [result] = await db.query( + `INSERT INTO work_issue_reports + (reporter_id, report_date, factory_category_id, workplace_id, custom_location, + tbm_session_id, visit_request_id, issue_category_id, issue_item_id, + additional_description, photo_path1, photo_path2, photo_path3, photo_path4, photo_path5) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, + [reporter_id, reportDate, factory_category_id, workplace_id, custom_location, + tbm_session_id, visit_request_id, issue_category_id, issue_item_id, + additional_description, photo_path1, photo_path2, photo_path3, photo_path4, photo_path5] + ); + + // 상태 변경 로그 기록 + await db.query( + `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by) + VALUES (?, NULL, 'reported', ?)`, + [result.insertId, reporter_id] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 신고 목록 조회 (필터 옵션 포함) + */ +const getAllReports = async (filters = {}, callback) => { + try { + const db = await getDb(); + let query = ` + SELECT + wir.report_id, wir.reporter_id, wir.report_date, + wir.factory_category_id, wir.workplace_id, wir.custom_location, + wir.tbm_session_id, wir.visit_request_id, + wir.issue_category_id, wir.issue_item_id, wir.additional_description, + wir.photo_path1, wir.photo_path2, wir.photo_path3, wir.photo_path4, wir.photo_path5, + wir.status, wir.assigned_department, wir.assigned_user_id, wir.assigned_at, + wir.resolution_notes, wir.resolved_at, + wir.created_at, wir.updated_at, + u.username as reporter_name, u.name as reporter_full_name, + wc.category_name as factory_name, + w.workplace_name, + irc.category_type, irc.category_name as issue_category_name, + iri.item_name as issue_item_name, iri.severity, + assignee.username as assigned_user_name, assignee.name as assigned_full_name + FROM work_issue_reports wir + INNER JOIN users u ON wir.reporter_id = u.user_id + LEFT JOIN workplace_categories wc ON wir.factory_category_id = wc.category_id + LEFT JOIN workplaces w ON wir.workplace_id = w.workplace_id + INNER JOIN issue_report_categories irc ON wir.issue_category_id = irc.category_id + LEFT JOIN issue_report_items iri ON wir.issue_item_id = iri.item_id + LEFT JOIN users assignee ON wir.assigned_user_id = assignee.user_id + WHERE 1=1 + `; + + const params = []; + + // 필터 적용 + if (filters.status) { + query += ` AND wir.status = ?`; + params.push(filters.status); + } + + if (filters.category_type) { + query += ` AND irc.category_type = ?`; + params.push(filters.category_type); + } + + if (filters.issue_category_id) { + query += ` AND wir.issue_category_id = ?`; + params.push(filters.issue_category_id); + } + + if (filters.factory_category_id) { + query += ` AND wir.factory_category_id = ?`; + params.push(filters.factory_category_id); + } + + if (filters.workplace_id) { + query += ` AND wir.workplace_id = ?`; + params.push(filters.workplace_id); + } + + if (filters.reporter_id) { + query += ` AND wir.reporter_id = ?`; + params.push(filters.reporter_id); + } + + if (filters.assigned_user_id) { + query += ` AND wir.assigned_user_id = ?`; + params.push(filters.assigned_user_id); + } + + if (filters.start_date && filters.end_date) { + query += ` AND DATE(wir.report_date) BETWEEN ? AND ?`; + params.push(filters.start_date, filters.end_date); + } + + if (filters.search) { + query += ` AND (wir.additional_description LIKE ? OR iri.item_name LIKE ? OR wir.custom_location LIKE ?)`; + const searchTerm = `%${filters.search}%`; + params.push(searchTerm, searchTerm, searchTerm); + } + + query += ` ORDER BY wir.report_date DESC, wir.report_id DESC`; + + // 페이지네이션 + if (filters.limit) { + query += ` LIMIT ?`; + params.push(parseInt(filters.limit)); + + if (filters.offset) { + query += ` OFFSET ?`; + params.push(parseInt(filters.offset)); + } + } + + const [rows] = await db.query(query, params); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 신고 상세 조회 + */ +const getReportById = async (reportId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT + wir.report_id, wir.reporter_id, wir.report_date, + wir.factory_category_id, wir.workplace_id, wir.custom_location, + wir.tbm_session_id, wir.visit_request_id, + wir.issue_category_id, wir.issue_item_id, wir.additional_description, + wir.photo_path1, wir.photo_path2, wir.photo_path3, wir.photo_path4, wir.photo_path5, + wir.status, wir.assigned_department, wir.assigned_user_id, wir.assigned_at, wir.assigned_by, + wir.resolution_notes, wir.resolution_photo_path1, wir.resolution_photo_path2, + wir.resolved_at, wir.resolved_by, + wir.modification_history, + wir.created_at, wir.updated_at, + u.username as reporter_name, u.name as reporter_full_name, + wc.category_name as factory_name, + w.workplace_name, + irc.category_type, irc.category_name as issue_category_name, + iri.item_name as issue_item_name, iri.severity, + assignee.username as assigned_user_name, assignee.name as assigned_full_name, + assigner.username as assigned_by_name, + resolver.username as resolved_by_name + FROM work_issue_reports wir + INNER JOIN users u ON wir.reporter_id = u.user_id + LEFT JOIN workplace_categories wc ON wir.factory_category_id = wc.category_id + LEFT JOIN workplaces w ON wir.workplace_id = w.workplace_id + INNER JOIN issue_report_categories irc ON wir.issue_category_id = irc.category_id + LEFT JOIN issue_report_items iri ON wir.issue_item_id = iri.item_id + LEFT JOIN users assignee ON wir.assigned_user_id = assignee.user_id + LEFT JOIN users assigner ON wir.assigned_by = assigner.user_id + LEFT JOIN users resolver ON wir.resolved_by = resolver.user_id + WHERE wir.report_id = ?`, + [reportId] + ); + + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 신고 수정 + */ +const updateReport = async (reportId, reportData, userId, callback) => { + try { + const db = await getDb(); + + // 기존 데이터 조회 + const [existing] = await db.query( + `SELECT * FROM work_issue_reports WHERE report_id = ?`, + [reportId] + ); + + if (existing.length === 0) { + return callback(new Error('신고를 찾을 수 없습니다.')); + } + + const current = existing[0]; + + // 수정 이력 생성 + const modifications = []; + const now = new Date().toISOString(); + + for (const key of Object.keys(reportData)) { + if (current[key] !== reportData[key] && reportData[key] !== undefined) { + modifications.push({ + field: key, + old_value: current[key], + new_value: reportData[key], + modified_at: now, + modified_by: userId + }); + } + } + + // 기존 이력과 병합 + const existingHistory = current.modification_history ? JSON.parse(current.modification_history) : []; + const newHistory = [...existingHistory, ...modifications]; + + const { + factory_category_id, + workplace_id, + custom_location, + issue_category_id, + issue_item_id, + additional_description, + photo_path1, + photo_path2, + photo_path3, + photo_path4, + photo_path5 + } = reportData; + + const [result] = await db.query( + `UPDATE work_issue_reports + SET factory_category_id = COALESCE(?, factory_category_id), + workplace_id = COALESCE(?, workplace_id), + custom_location = COALESCE(?, custom_location), + issue_category_id = COALESCE(?, issue_category_id), + issue_item_id = COALESCE(?, issue_item_id), + additional_description = COALESCE(?, additional_description), + photo_path1 = COALESCE(?, photo_path1), + photo_path2 = COALESCE(?, photo_path2), + photo_path3 = COALESCE(?, photo_path3), + photo_path4 = COALESCE(?, photo_path4), + photo_path5 = COALESCE(?, photo_path5), + modification_history = ?, + updated_at = NOW() + WHERE report_id = ?`, + [factory_category_id, workplace_id, custom_location, + issue_category_id, issue_item_id, additional_description, + photo_path1, photo_path2, photo_path3, photo_path4, photo_path5, + JSON.stringify(newHistory), reportId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 신고 삭제 + */ +const deleteReport = async (reportId, callback) => { + try { + const db = await getDb(); + + // 먼저 사진 경로 조회 (삭제용) + const [photos] = await db.query( + `SELECT photo_path1, photo_path2, photo_path3, photo_path4, photo_path5, + resolution_photo_path1, resolution_photo_path2 + FROM work_issue_reports WHERE report_id = ?`, + [reportId] + ); + + const [result] = await db.query( + `DELETE FROM work_issue_reports WHERE report_id = ?`, + [reportId] + ); + + // 삭제할 사진 경로 반환 + callback(null, { result, photos: photos[0] }); + } catch (err) { + callback(err); + } +}; + +// ==================== 상태 관리 ==================== + +/** + * 신고 접수 (reported → received) + */ +const receiveReport = async (reportId, userId, callback) => { + try { + const db = await getDb(); + + // 현재 상태 확인 + const [current] = await db.query( + `SELECT status FROM work_issue_reports WHERE report_id = ?`, + [reportId] + ); + + if (current.length === 0) { + return callback(new Error('신고를 찾을 수 없습니다.')); + } + + if (current[0].status !== 'reported') { + return callback(new Error('접수 대기 상태가 아닙니다.')); + } + + const [result] = await db.query( + `UPDATE work_issue_reports + SET status = 'received', updated_at = NOW() + WHERE report_id = ?`, + [reportId] + ); + + // 상태 변경 로그 + await db.query( + `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by) + VALUES (?, 'reported', 'received', ?)`, + [reportId, userId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 담당자 배정 + */ +const assignReport = async (reportId, assignData, callback) => { + try { + const db = await getDb(); + const { assigned_department, assigned_user_id, assigned_by } = assignData; + + // 현재 상태 확인 + const [current] = await db.query( + `SELECT status FROM work_issue_reports WHERE report_id = ?`, + [reportId] + ); + + if (current.length === 0) { + return callback(new Error('신고를 찾을 수 없습니다.')); + } + + // 접수 상태 이상이어야 배정 가능 + const validStatuses = ['received', 'in_progress']; + if (!validStatuses.includes(current[0].status)) { + return callback(new Error('접수된 상태에서만 담당자 배정이 가능합니다.')); + } + + const [result] = await db.query( + `UPDATE work_issue_reports + SET assigned_department = ?, assigned_user_id = ?, + assigned_at = NOW(), assigned_by = ?, updated_at = NOW() + WHERE report_id = ?`, + [assigned_department, assigned_user_id, assigned_by, reportId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 처리 시작 (received → in_progress) + */ +const startProcessing = async (reportId, userId, callback) => { + try { + const db = await getDb(); + + // 현재 상태 확인 + const [current] = await db.query( + `SELECT status FROM work_issue_reports WHERE report_id = ?`, + [reportId] + ); + + if (current.length === 0) { + return callback(new Error('신고를 찾을 수 없습니다.')); + } + + if (current[0].status !== 'received') { + return callback(new Error('접수된 상태에서만 처리를 시작할 수 있습니다.')); + } + + const [result] = await db.query( + `UPDATE work_issue_reports + SET status = 'in_progress', updated_at = NOW() + WHERE report_id = ?`, + [reportId] + ); + + // 상태 변경 로그 + await db.query( + `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by) + VALUES (?, 'received', 'in_progress', ?)`, + [reportId, userId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 처리 완료 (in_progress → completed) + */ +const completeReport = async (reportId, completionData, callback) => { + try { + const db = await getDb(); + const { resolution_notes, resolution_photo_path1, resolution_photo_path2, resolved_by } = completionData; + + // 현재 상태 확인 + const [current] = await db.query( + `SELECT status FROM work_issue_reports WHERE report_id = ?`, + [reportId] + ); + + if (current.length === 0) { + return callback(new Error('신고를 찾을 수 없습니다.')); + } + + if (current[0].status !== 'in_progress') { + return callback(new Error('처리 중 상태에서만 완료할 수 있습니다.')); + } + + const [result] = await db.query( + `UPDATE work_issue_reports + SET status = 'completed', resolution_notes = ?, + resolution_photo_path1 = ?, resolution_photo_path2 = ?, + resolved_at = NOW(), resolved_by = ?, updated_at = NOW() + WHERE report_id = ?`, + [resolution_notes, resolution_photo_path1, resolution_photo_path2, resolved_by, reportId] + ); + + // 상태 변경 로그 + await db.query( + `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by, change_reason) + VALUES (?, 'in_progress', 'completed', ?, ?)`, + [reportId, resolved_by, resolution_notes] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 신고 종료 (completed → closed) + */ +const closeReport = async (reportId, userId, callback) => { + try { + const db = await getDb(); + + // 현재 상태 확인 + const [current] = await db.query( + `SELECT status FROM work_issue_reports WHERE report_id = ?`, + [reportId] + ); + + if (current.length === 0) { + return callback(new Error('신고를 찾을 수 없습니다.')); + } + + if (current[0].status !== 'completed') { + return callback(new Error('완료된 상태에서만 종료할 수 있습니다.')); + } + + const [result] = await db.query( + `UPDATE work_issue_reports + SET status = 'closed', updated_at = NOW() + WHERE report_id = ?`, + [reportId] + ); + + // 상태 변경 로그 + await db.query( + `INSERT INTO work_issue_status_logs (report_id, previous_status, new_status, changed_by) + VALUES (?, 'completed', 'closed', ?)`, + [reportId, userId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 상태 변경 이력 조회 + */ +const getStatusLogs = async (reportId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT wisl.log_id, wisl.report_id, wisl.previous_status, wisl.new_status, + wisl.changed_by, wisl.change_reason, wisl.changed_at, + u.username as changed_by_name, u.name as changed_by_full_name + FROM work_issue_status_logs wisl + INNER JOIN users u ON wisl.changed_by = u.user_id + WHERE wisl.report_id = ? + ORDER BY wisl.changed_at ASC`, + [reportId] + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +// ==================== 통계 ==================== + +/** + * 신고 통계 요약 + */ +const getStatsSummary = async (filters = {}, callback) => { + try { + const db = await getDb(); + + let whereClause = '1=1'; + const params = []; + + if (filters.start_date && filters.end_date) { + whereClause += ` AND DATE(report_date) BETWEEN ? AND ?`; + params.push(filters.start_date, filters.end_date); + } + + if (filters.factory_category_id) { + whereClause += ` AND factory_category_id = ?`; + params.push(filters.factory_category_id); + } + + const [rows] = await db.query( + `SELECT + COUNT(*) as total, + SUM(CASE WHEN status = 'reported' THEN 1 ELSE 0 END) as reported, + SUM(CASE WHEN status = 'received' THEN 1 ELSE 0 END) as received, + SUM(CASE WHEN status = 'in_progress' THEN 1 ELSE 0 END) as in_progress, + SUM(CASE WHEN status = 'completed' THEN 1 ELSE 0 END) as completed, + SUM(CASE WHEN status = 'closed' THEN 1 ELSE 0 END) as closed + FROM work_issue_reports + WHERE ${whereClause}`, + params + ); + + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 카테고리별 통계 + */ +const getStatsByCategory = async (filters = {}, callback) => { + try { + const db = await getDb(); + + let whereClause = '1=1'; + const params = []; + + if (filters.start_date && filters.end_date) { + whereClause += ` AND DATE(wir.report_date) BETWEEN ? AND ?`; + params.push(filters.start_date, filters.end_date); + } + + const [rows] = await db.query( + `SELECT + irc.category_type, irc.category_name, + COUNT(*) as count + FROM work_issue_reports wir + INNER JOIN issue_report_categories irc ON wir.issue_category_id = irc.category_id + WHERE ${whereClause} + GROUP BY irc.category_id + ORDER BY irc.category_type, count DESC`, + params + ); + + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 작업장별 통계 + */ +const getStatsByWorkplace = async (filters = {}, callback) => { + try { + const db = await getDb(); + + let whereClause = 'wir.workplace_id IS NOT NULL'; + const params = []; + + if (filters.start_date && filters.end_date) { + whereClause += ` AND DATE(wir.report_date) BETWEEN ? AND ?`; + params.push(filters.start_date, filters.end_date); + } + + if (filters.factory_category_id) { + whereClause += ` AND wir.factory_category_id = ?`; + params.push(filters.factory_category_id); + } + + const [rows] = await db.query( + `SELECT + wir.factory_category_id, wc.category_name as factory_name, + wir.workplace_id, w.workplace_name, + COUNT(*) as count + FROM work_issue_reports wir + INNER JOIN workplace_categories wc ON wir.factory_category_id = wc.category_id + INNER JOIN workplaces w ON wir.workplace_id = w.workplace_id + WHERE ${whereClause} + GROUP BY wir.factory_category_id, wir.workplace_id + ORDER BY count DESC`, + params + ); + + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +module.exports = { + // 카테고리 + getAllCategories, + getCategoriesByType, + createCategory, + updateCategory, + deleteCategory, + + // 항목 + getItemsByCategory, + getAllItems, + createItem, + updateItem, + deleteItem, + + // 신고 + createReport, + getAllReports, + getReportById, + updateReport, + deleteReport, + + // 상태 관리 + receiveReport, + assignReport, + startProcessing, + completeReport, + closeReport, + getStatusLogs, + + // 통계 + getStatsSummary, + getStatsByCategory, + getStatsByWorkplace +}; diff --git a/deploy/tkfb-package/api.hyungi.net/models/workReportModel.js b/deploy/tkfb-package/api.hyungi.net/models/workReportModel.js new file mode 100644 index 0000000..db0cf48 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/workReportModel.js @@ -0,0 +1,223 @@ +const { getDb } = require('../dbPool'); + +/** + * 1. 여러 건 등록 (트랜잭션 사용) + */ +const createBatch = async (reports, callback) => { + const db = await getDb(); + const conn = await db.getConnection(); + + try { + await conn.beginTransaction(); + + const sql = ` + INSERT INTO WorkReports + (\`date\`, worker_id, project_id, task_id, overtime_hours, work_details, memo) + VALUES (?, ?, ?, ?, ?, ?, ?) + `; + + for (const rpt of reports) { + const params = [ + rpt.date, + rpt.worker_id, + rpt.project_id, + rpt.task_id || null, + rpt.overtime_hours || null, + rpt.work_details || null, + rpt.memo || null + ]; + await conn.query(sql, params); + } + + await conn.commit(); + callback(null); + } catch (err) { + await conn.rollback(); + callback(err); + } finally { + conn.release(); + } +}; + +/** + * 2. 단일 등록 + */ +const create = async (report, callback) => { + try { + const db = await getDb(); + const { + date, worker_id, project_id, + task_id, overtime_hours, + work_details, memo + } = report; + + const [result] = await db.query( + `INSERT INTO WorkReports + (\`date\`, worker_id, project_id, task_id, overtime_hours, work_details, memo) + VALUES (?, ?, ?, ?, ?, ?, ?)`, + [ + date, + worker_id, + project_id, + task_id || null, + overtime_hours || null, + work_details || null, + memo || null + ] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + + /** + * 3. 날짜별 조회 + */ + const getAllByDate = async (date, callback) => { + try { + const db = await getDb(); + const sql = ` + SELECT + wr.worker_id, -- 이 줄을 추가했습니다 + wr.id, + wr.\`date\`, + w.worker_name, + p.project_name, + CONCAT(t.category, ':', t.subcategory) AS task_name, + wr.overtime_hours, + wr.work_details, + wr.memo + FROM WorkReports wr + LEFT JOIN workers w ON wr.worker_id = w.worker_id + LEFT JOIN projects p ON wr.project_id = p.project_id + LEFT JOIN Tasks t ON wr.task_id = t.task_id + WHERE wr.\`date\` = ? + ORDER BY w.worker_name ASC + `; + const [rows] = await db.query(sql, [date]); + callback(null, rows); + } catch (err) { + callback(err); + } + }; + +/** + * 4. 기간 조회 + */ +const getByRange = async (start, end, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT id, \`date\`, worker_id, project_id, morning_task_id, afternoon_task_id, overtime_hours, overtime_task_id, work_details, note, memo, created_at, updated_at, morning_project_id, afternoon_project_id, overtime_project_id, task_id FROM WorkReports + WHERE \`date\` BETWEEN ? AND ? + ORDER BY \`date\` ASC`, + [start, end] + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 5. ID로 조회 + */ +const getById = async (id, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT id, \`date\`, worker_id, project_id, morning_task_id, afternoon_task_id, overtime_hours, overtime_task_id, work_details, note, memo, created_at, updated_at, morning_project_id, afternoon_project_id, overtime_project_id, task_id FROM WorkReports WHERE id = ?`, + [id] + ); + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 6. 수정 + */ +const update = async (id, report, callback) => { + try { + const db = await getDb(); + const { + date, worker_id, project_id, + task_id, overtime_hours, + work_details, memo + } = report; + + const [result] = await db.query( + `UPDATE WorkReports + SET \`date\` = ?, + worker_id = ?, + project_id = ?, + task_id = ?, + overtime_hours = ?, + work_details = ?, + memo = ?, + updated_at = CURRENT_TIMESTAMP + WHERE id = ?`, + [ + date, + worker_id, + project_id, + task_id || null, + overtime_hours || null, + work_details || null, + memo || null, + id + ] + ); + + callback(null, result.affectedRows); + } catch (err) { + callback(err); + } +}; + +/** + * 7. 삭제 + */ +const remove = async (id, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM WorkReports WHERE id = ?`, + [id] + ); + callback(null, result.affectedRows); + } catch (err) { + callback(new Error(err.message || String(err))); + } +}; + +/** + * 8. 중복 확인 + */ +const existsByDateAndWorker = async (date, worker_id, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT 1 FROM WorkReports WHERE \`date\` = ? AND worker_id = ? LIMIT 1`, + [date, worker_id] + ); + callback(null, rows.length > 0); + } catch (err) { + callback(err); + } +}; + +// ✅ 내보내기 +module.exports = { + create, + createBatch, + getAllByDate, + getByRange, + getById, + update, + remove, + existsByDateAndWorker +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/models/workerModel.js b/deploy/tkfb-package/api.hyungi.net/models/workerModel.js new file mode 100644 index 0000000..b549750 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/workerModel.js @@ -0,0 +1,197 @@ +const { getDb } = require('../dbPool'); + +// 날짜 형식 변환 헬퍼 함수 (ISO 8601 -> MySQL DATE) +const formatDate = (dateStr) => { + if (!dateStr) return null; + if (typeof dateStr === 'string' && dateStr.includes('T')) { + return dateStr.split('T')[0]; // ISO 8601 -> YYYY-MM-DD + } + return dateStr; +}; + +// 1. 작업자 생성 +const create = async (worker) => { + const db = await getDb(); + const { + worker_name, + job_type = null, + join_date = null, + salary = null, + annual_leave = null, + status = 'active', + employment_status = 'employed', + department_id = null + } = worker; + + const [result] = await db.query( + `INSERT INTO workers + (worker_name, job_type, join_date, salary, annual_leave, status, employment_status, department_id) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + [worker_name, job_type, formatDate(join_date), salary, annual_leave, status, employment_status, department_id] + ); + + return result.insertId; +}; + +// 2. 전체 조회 +const getAll = async () => { + const db = await getDb(); + const [rows] = await db.query(` + SELECT + w.*, + CASE WHEN w.status = 'active' THEN 1 ELSE 0 END AS is_active, + u.user_id, + d.department_name + FROM workers w + LEFT JOIN users u ON w.worker_id = u.worker_id + LEFT JOIN departments d ON w.department_id = d.department_id + ORDER BY w.worker_id DESC + `); + return rows; +}; + +// 3. 단일 조회 +const getById = async (worker_id) => { + const db = await getDb(); + const [rows] = await db.query(` + SELECT + w.*, + CASE WHEN w.status = 'active' THEN 1 ELSE 0 END AS is_active, + u.user_id, + d.department_name + FROM workers w + LEFT JOIN users u ON w.worker_id = u.worker_id + LEFT JOIN departments d ON w.department_id = d.department_id + WHERE w.worker_id = ? + `, [worker_id]); + return rows[0]; +}; + +// 4. 작업자 수정 +const update = async (worker) => { + const db = await getDb(); + const { + worker_id, + worker_name, + job_type, + status, + join_date, + salary, + annual_leave, + employment_status, + department_id + } = worker; + + // 업데이트할 필드만 동적으로 구성 + const updates = []; + const values = []; + + if (worker_name !== undefined) { + updates.push('worker_name = ?'); + values.push(worker_name); + } + if (job_type !== undefined) { + updates.push('job_type = ?'); + values.push(job_type); + } + if (status !== undefined) { + updates.push('status = ?'); + values.push(status); + } + if (join_date !== undefined) { + updates.push('join_date = ?'); + values.push(formatDate(join_date)); + } + if (salary !== undefined) { + updates.push('salary = ?'); + values.push(salary); + } + if (annual_leave !== undefined) { + updates.push('annual_leave = ?'); + values.push(annual_leave); + } + if (employment_status !== undefined) { + updates.push('employment_status = ?'); + values.push(employment_status); + } + if (department_id !== undefined) { + updates.push('department_id = ?'); + values.push(department_id); + } + + if (updates.length === 0) { + throw new Error('업데이트할 필드가 없습니다'); + } + + values.push(worker_id); // WHERE 조건용 + + const query = `UPDATE workers SET ${updates.join(', ')} WHERE worker_id = ?`; + + console.log('🔍 실행할 SQL:', query); + console.log('🔍 SQL 파라미터:', values); + + const [result] = await db.query(query, values); + + return result.affectedRows; +}; + +// 5. 삭제 (외래키 제약조건 처리) +const remove = async (worker_id) => { + const db = await getDb(); + const conn = await db.getConnection(); + + try { + await conn.beginTransaction(); + + console.log(`🗑️ 작업자 삭제 시작: worker_id=${worker_id}`); + + // 안전한 삭제: 각 테이블을 개별적으로 처리하고 오류가 발생해도 계속 진행 + const tables = [ + { name: 'users', query: 'UPDATE users SET worker_id = NULL WHERE worker_id = ?', action: '업데이트' }, + { name: 'Users', query: 'UPDATE Users SET worker_id = NULL WHERE worker_id = ?', action: '업데이트' }, + { name: 'daily_issue_reports', query: 'DELETE FROM daily_issue_reports WHERE worker_id = ?', action: '삭제' }, + { name: 'DailyIssueReports', query: 'DELETE FROM DailyIssueReports WHERE worker_id = ?', action: '삭제' }, + { name: 'work_reports', query: 'DELETE FROM work_reports WHERE worker_id = ?', action: '삭제' }, + { name: 'WorkReports', query: 'DELETE FROM WorkReports WHERE worker_id = ?', action: '삭제' }, + { name: 'daily_work_reports', query: 'DELETE FROM daily_work_reports WHERE worker_id = ?', action: '삭제' }, + { name: 'monthly_worker_status', query: 'DELETE FROM monthly_worker_status WHERE worker_id = ?', action: '삭제' }, + { name: 'worker_groups', query: 'DELETE FROM worker_groups WHERE worker_id = ?', action: '삭제' } + ]; + + for (const table of tables) { + try { + const [result] = await conn.query(table.query, [worker_id]); + if (result.affectedRows > 0) { + console.log(`✅ ${table.name} 테이블 ${table.action}: ${result.affectedRows}건`); + } + } catch (tableError) { + console.log(`⚠️ ${table.name} 테이블 ${table.action} 실패 (무시): ${tableError.message}`); + } + } + + // 마지막으로 작업자 삭제 + const [result] = await conn.query( + `DELETE FROM workers WHERE worker_id = ?`, + [worker_id] + ); + console.log(`✅ 작업자 삭제 완료: ${result.affectedRows}건`); + + await conn.commit(); + return result.affectedRows; + + } catch (err) { + await conn.rollback(); + console.error(`❌ 작업자 삭제 오류 (worker_id: ${worker_id}):`, err); + throw new Error(`작업자 삭제 중 오류가 발생했습니다: ${err.message}`); + } finally { + conn.release(); + } +}; + +module.exports = { + create, + getAll, + getById, + update, + remove +}; diff --git a/deploy/tkfb-package/api.hyungi.net/models/workplaceModel.js b/deploy/tkfb-package/api.hyungi.net/models/workplaceModel.js new file mode 100644 index 0000000..4a7e754 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/models/workplaceModel.js @@ -0,0 +1,440 @@ +const { getDb } = require('../dbPool'); + +// ==================== 카테고리(공장) 관련 ==================== + +/** + * 카테고리 생성 + */ +const createCategory = async (category, callback) => { + try { + const db = await getDb(); + const { + category_name, + description = null, + display_order = 0, + is_active = true + } = category; + + const [result] = await db.query( + `INSERT INTO workplace_categories + (category_name, description, display_order, is_active) + VALUES (?, ?, ?, ?)`, + [category_name, description, display_order, is_active] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 모든 카테고리 조회 + */ +const getAllCategories = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT category_id, category_name, description, display_order, is_active, layout_image, created_at, updated_at + FROM workplace_categories + ORDER BY display_order ASC, category_id ASC` + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 활성 카테고리만 조회 + */ +const getActiveCategories = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT category_id, category_name, description, display_order, is_active, layout_image, created_at, updated_at + FROM workplace_categories + WHERE is_active = TRUE + ORDER BY display_order ASC, category_id ASC` + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * ID로 카테고리 조회 + */ +const getCategoryById = async (categoryId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT category_id, category_name, description, display_order, is_active, layout_image, created_at, updated_at + FROM workplace_categories + WHERE category_id = ?`, + [categoryId] + ); + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 카테고리 수정 + */ +const updateCategory = async (categoryId, category, callback) => { + try { + const db = await getDb(); + const { + category_name, + description, + display_order, + is_active, + layout_image + } = category; + + const [result] = await db.query( + `UPDATE workplace_categories + SET category_name = ?, description = ?, display_order = ?, is_active = ?, layout_image = ?, updated_at = NOW() + WHERE category_id = ?`, + [category_name, description, display_order, is_active, layout_image, categoryId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 카테고리 삭제 + */ +const deleteCategory = async (categoryId, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM workplace_categories WHERE category_id = ?`, + [categoryId] + ); + callback(null, result); + } catch (err) { + callback(err); + } +}; + +// ==================== 작업장 관련 ==================== + +/** + * 작업장 생성 + */ +const createWorkplace = async (workplace, callback) => { + try { + const db = await getDb(); + const { + category_id = null, + workplace_name, + description = null, + is_active = true, + workplace_purpose = null, + display_priority = 0 + } = workplace; + + const [result] = await db.query( + `INSERT INTO workplaces + (category_id, workplace_name, description, is_active, workplace_purpose, display_priority) + VALUES (?, ?, ?, ?, ?, ?)`, + [category_id, workplace_name, description, is_active, workplace_purpose, display_priority] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 모든 작업장 조회 (카테고리 정보 포함) + */ +const getAllWorkplaces = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT w.workplace_id, w.category_id, w.workplace_name, w.description, w.is_active, w.workplace_purpose, w.display_priority, + w.layout_image, w.created_at, w.updated_at, + wc.category_name + FROM workplaces w + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + ORDER BY wc.display_order ASC, w.display_priority ASC, w.workplace_id DESC` + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 활성 작업장만 조회 + */ +const getActiveWorkplaces = async (callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT w.workplace_id, w.category_id, w.workplace_name, w.description, w.is_active, w.workplace_purpose, w.display_priority, + w.layout_image, w.created_at, w.updated_at, + wc.category_name + FROM workplaces w + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + WHERE w.is_active = TRUE + ORDER BY wc.display_order ASC, w.workplace_id DESC` + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 카테고리별 작업장 조회 + */ +const getWorkplacesByCategory = async (categoryId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT w.workplace_id, w.category_id, w.workplace_name, w.description, w.is_active, w.workplace_purpose, w.display_priority, + w.layout_image, w.created_at, w.updated_at, + wc.category_name + FROM workplaces w + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + WHERE w.category_id = ? + ORDER BY w.workplace_id DESC`, + [categoryId] + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * ID로 작업장 조회 + */ +const getWorkplaceById = async (workplaceId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT w.workplace_id, w.category_id, w.workplace_name, w.description, w.is_active, w.workplace_purpose, w.display_priority, + w.layout_image, w.created_at, w.updated_at, + wc.category_name + FROM workplaces w + LEFT JOIN workplace_categories wc ON w.category_id = wc.category_id + WHERE w.workplace_id = ?`, + [workplaceId] + ); + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 작업장 수정 + */ +const updateWorkplace = async (workplaceId, workplace, callback) => { + try { + const db = await getDb(); + const { + category_id, + workplace_name, + description, + is_active, + workplace_purpose, + display_priority, + layout_image + } = workplace; + + const [result] = await db.query( + `UPDATE workplaces + SET category_id = ?, workplace_name = ?, description = ?, is_active = ?, + workplace_purpose = ?, display_priority = ?, layout_image = ?, updated_at = NOW() + WHERE workplace_id = ?`, + [category_id, workplace_name, description, is_active, workplace_purpose, display_priority, layout_image, workplaceId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 작업장 삭제 + */ +const deleteWorkplace = async (workplaceId, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM workplaces WHERE workplace_id = ?`, + [workplaceId] + ); + callback(null, result); + } catch (err) { + callback(err); + } +}; + +// ==================== 작업장 지도 영역 관련 ==================== + +/** + * 작업장 지도 영역 생성 + */ +const createMapRegion = async (region, callback) => { + try { + const db = await getDb(); + const { + workplace_id, + category_id, + x_start, + y_start, + x_end, + y_end, + shape = 'rect', + polygon_points = null + } = region; + + const [result] = await db.query( + `INSERT INTO workplace_map_regions + (workplace_id, category_id, x_start, y_start, x_end, y_end, shape, polygon_points) + VALUES (?, ?, ?, ?, ?, ?, ?, ?)`, + [workplace_id, category_id, x_start, y_start, x_end, y_end, shape, polygon_points] + ); + + callback(null, result.insertId); + } catch (err) { + callback(err); + } +}; + +/** + * 카테고리(공장)별 지도 영역 조회 + */ +const getMapRegionsByCategory = async (categoryId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT mr.*, w.workplace_name, w.description + FROM workplace_map_regions mr + INNER JOIN workplaces w ON mr.workplace_id = w.workplace_id + WHERE mr.category_id = ? AND w.is_active = TRUE + ORDER BY mr.region_id ASC`, + [categoryId] + ); + callback(null, rows); + } catch (err) { + callback(err); + } +}; + +/** + * 작업장별 지도 영역 조회 + */ +const getMapRegionByWorkplace = async (workplaceId, callback) => { + try { + const db = await getDb(); + const [rows] = await db.query( + `SELECT * FROM workplace_map_regions WHERE workplace_id = ?`, + [workplaceId] + ); + callback(null, rows[0]); + } catch (err) { + callback(err); + } +}; + +/** + * 지도 영역 수정 + */ +const updateMapRegion = async (regionId, region, callback) => { + try { + const db = await getDb(); + const { + x_start, + y_start, + x_end, + y_end, + shape, + polygon_points + } = region; + + const [result] = await db.query( + `UPDATE workplace_map_regions + SET x_start = ?, y_start = ?, x_end = ?, y_end = ?, shape = ?, polygon_points = ?, updated_at = NOW() + WHERE region_id = ?`, + [x_start, y_start, x_end, y_end, shape, polygon_points, regionId] + ); + + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 지도 영역 삭제 + */ +const deleteMapRegion = async (regionId, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM workplace_map_regions WHERE region_id = ?`, + [regionId] + ); + callback(null, result); + } catch (err) { + callback(err); + } +}; + +/** + * 작업장 영역 일괄 삭제 (카테고리별) + */ +const deleteMapRegionsByCategory = async (categoryId, callback) => { + try { + const db = await getDb(); + const [result] = await db.query( + `DELETE FROM workplace_map_regions WHERE category_id = ?`, + [categoryId] + ); + callback(null, result); + } catch (err) { + callback(err); + } +}; + +module.exports = { + // 카테고리 + createCategory, + getAllCategories, + getActiveCategories, + getCategoryById, + updateCategory, + deleteCategory, + + // 작업장 + createWorkplace, + getAllWorkplaces, + getActiveWorkplaces, + getWorkplacesByCategory, + getWorkplaceById, + updateWorkplace, + deleteWorkplace, + + // 지도 영역 + createMapRegion, + getMapRegionsByCategory, + getMapRegionByWorkplace, + updateMapRegion, + deleteMapRegion, + deleteMapRegionsByCategory +}; diff --git a/deploy/tkfb-package/api.hyungi.net/package-lock.json b/deploy/tkfb-package/api.hyungi.net/package-lock.json new file mode 100644 index 0000000..40600a7 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/package-lock.json @@ -0,0 +1,8605 @@ +{ + "name": "hyungi-api", + "version": "2.2.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hyungi-api", + "version": "2.2.0", + "dependencies": { + "@simplewebauthn/server": "^13.1.1", + "async-retry": "^1.3.3", + "axios": "^1.6.7", + "bcrypt": "^6.0.0", + "bcryptjs": "^2.4.3", + "compression": "^1.8.1", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.18.2", + "express-rate-limit": "^7.5.1", + "express-validator": "^7.2.1", + "helmet": "^7.2.0", + "jsonwebtoken": "^9.0.0", + "knex": "^3.1.0", + "multer": "^1.4.5-lts.1", + "mysql2": "^3.14.1", + "node-cache": "^5.1.2", + "pm2": "^5.3.0", + "qrcode": "^1.5.4", + "redis": "^5.9.0", + "sqlite3": "^5.1.6", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.1" + }, + "devDependencies": { + "@types/jest": "^29.5.12", + "jest": "^29.7.0", + "supertest": "^7.0.0" + } + }, + "node_modules/@apidevtools/json-schema-ref-parser": { + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.1.2.tgz", + "integrity": "sha512-r1w81DpR+KyRWd3f+rk6TNqMgedmAxZP5v5KWlXQWlgMUUtyEJch0DKEci1SorPMiSeM8XPl7MZ3miJ60JIpQg==", + "license": "MIT", + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.6", + "call-me-maybe": "^1.0.1", + "js-yaml": "^4.1.0" + } + }, + "node_modules/@apidevtools/openapi-schemas": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz", + "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@apidevtools/swagger-methods": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz", + "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==", + "license": "MIT" + }, + "node_modules/@apidevtools/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-sNiLY51vZOmSPFZA5TF35KZ2HbgYklQnTSDnkghamzLb3EkNtcQnrBQEj5AOCxHpTtXpqMCRM1CrmV2rG6nw4g==", + "license": "MIT", + "dependencies": { + "@apidevtools/json-schema-ref-parser": "^9.0.6", + "@apidevtools/openapi-schemas": "^2.0.4", + "@apidevtools/swagger-methods": "^3.0.2", + "@jsdevtools/ono": "^7.1.3", + "call-me-maybe": "^1.0.1", + "z-schema": "^5.0.1" + }, + "peerDependencies": { + "openapi-types": ">=7" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", + "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helpers": "^7.28.4", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", + "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.2", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", + "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", + "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1", + "@babel/traverse": "^7.28.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", + "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", + "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.5" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", + "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", + "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.27.1.tgz", + "integrity": "sha512-y8YTNIeKoyhGd9O0Jiyzyyqk8gdjnumGTQPsz0xOZOQ2RmkVJeZ1vmmfIvFEKqucBG6axJGBZDE/7iI5suUI/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", + "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", + "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", + "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", + "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.27.1.tgz", + "integrity": "sha512-xfYCBMxveHrRMnAWl1ZlPXOZjzkN82THFvLhQhFXFt81Z5HnN+EtUkZhv/zcKpmT3fzmWZB0ywiBrbC3vogbwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", + "license": "MIT", + "optional": true + }, + "node_modules/@hexagon/base64": { + "version": "1.1.28", + "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz", + "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==" + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", + "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", + "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/console/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/core/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "license": "MIT" + }, + "node_modules/@levischuck/tiny-cbor": { + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@levischuck/tiny-cbor/-/tiny-cbor-0.2.11.tgz", + "integrity": "sha512-llBRm4dT4Z89aRsm6u2oEZ8tfwL/2l6BwpZ7JcyieouniDECM5AqNgr/y08zalEIvW3RSK4upYyybDcmjXqAow==" + }, + "node_modules/@noble/hashes": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", + "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.21.3 || >=16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@npmcli/move-file/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@paralleldrive/cuid2": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.3.1.tgz", + "integrity": "sha512-XO7cAxhnTZl0Yggq6jOgjiOHhbgcO4NqFqwSmQpjK3b6TEE6Uj/jfSk6wzYyemh3+I0sHirKSetjQwn5cZktFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@noble/hashes": "^1.1.5" + } + }, + "node_modules/@peculiar/asn1-android": { + "version": "2.3.16", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-android/-/asn1-android-2.3.16.tgz", + "integrity": "sha512-a1viIv3bIahXNssrOIkXZIlI2ePpZaNmR30d4aBL99mu2rO+mT9D6zBsp7H6eROWGtmwv0Ionp5olJurIo09dw==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.15", + "asn1js": "^3.0.5", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-android/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/@peculiar/asn1-ecc": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.3.15.tgz", + "integrity": "sha512-/HtR91dvgog7z/WhCVdxZJ/jitJuIu8iTqiyWVgRE9Ac5imt2sT/E4obqIVGKQw7PIy+X6i8lVBoT6wC73XUgA==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.15", + "@peculiar/asn1-x509": "^2.3.15", + "asn1js": "^3.0.5", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-ecc/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/@peculiar/asn1-rsa": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.3.15.tgz", + "integrity": "sha512-p6hsanvPhexRtYSOHihLvUUgrJ8y0FtOM97N5UEpC+VifFYyZa0iZ5cXjTkZoDwxJ/TTJ1IJo3HVTB2JJTpXvg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.15", + "@peculiar/asn1-x509": "^2.3.15", + "asn1js": "^3.0.5", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-rsa/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.15.tgz", + "integrity": "sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w==", + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-schema/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/@peculiar/asn1-x509": { + "version": "2.3.15", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.3.15.tgz", + "integrity": "sha512-0dK5xqTqSLaxv1FHXIcd4Q/BZNuopg+u1l23hT9rOmQ1g4dNtw0g/RnEi+TboB0gOwGtrWn269v27cMgchFIIg==", + "dependencies": { + "@peculiar/asn1-schema": "^2.3.15", + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.6", + "tslib": "^2.8.1" + } + }, + "node_modules/@peculiar/asn1-x509/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/@pm2/agent": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@pm2/agent/-/agent-2.0.4.tgz", + "integrity": "sha512-n7WYvvTJhHLS2oBb1PjOtgLpMhgImOq8sXkPBw6smeg9LJBWZjiEgPKOpR8mn9UJZsB5P3W4V/MyvNnp31LKeA==", + "dependencies": { + "async": "~3.2.0", + "chalk": "~3.0.0", + "dayjs": "~1.8.24", + "debug": "~4.3.1", + "eventemitter2": "~5.0.1", + "fast-json-patch": "^3.0.0-1", + "fclone": "~1.0.11", + "nssocket": "0.6.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.0", + "proxy-agent": "~6.3.0", + "semver": "~7.5.0", + "ws": "~7.5.10" + } + }, + "node_modules/@pm2/agent/node_modules/dayjs": { + "version": "1.8.36", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.8.36.tgz", + "integrity": "sha512-3VmRXEtw7RZKAf+4Tv1Ym9AGeo8r8+CjDi26x+7SYQil1UqtqdaokhzoEJohqlzt0m5kacJSDhJQkG/LWhpRBw==" + }, + "node_modules/@pm2/agent/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@pm2/agent/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/@pm2/agent/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pm2/io": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@pm2/io/-/io-6.0.1.tgz", + "integrity": "sha512-KiA+shC6sULQAr9mGZ1pg+6KVW9MF8NpG99x26Lf/082/Qy8qsTCtnJy+HQReW1A9Rdf0C/404cz0RZGZro+IA==", + "dependencies": { + "async": "~2.6.1", + "debug": "~4.3.1", + "eventemitter2": "^6.3.1", + "require-in-the-middle": "^5.0.0", + "semver": "~7.5.4", + "shimmer": "^1.2.0", + "signal-exit": "^3.0.3", + "tslib": "1.9.3" + }, + "engines": { + "node": ">=6.0" + } + }, + "node_modules/@pm2/io/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/@pm2/io/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@pm2/io/node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + }, + "node_modules/@pm2/io/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/@pm2/io/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@pm2/js-api": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@pm2/js-api/-/js-api-0.8.0.tgz", + "integrity": "sha512-nmWzrA/BQZik3VBz+npRcNIu01kdBhWL0mxKmP1ciF/gTcujPTQqt027N9fc1pK9ERM8RipFhymw7RcmCyOEYA==", + "dependencies": { + "async": "^2.6.3", + "debug": "~4.3.1", + "eventemitter2": "^6.3.1", + "extrareqp2": "^1.0.0", + "ws": "^7.0.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/@pm2/js-api/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/@pm2/js-api/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@pm2/js-api/node_modules/eventemitter2": { + "version": "6.4.9", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.9.tgz", + "integrity": "sha512-JEPTiaOt9f04oa6NOkc4aH+nVp5I3wEjpHbIPqfgCdD5v5bUzy7xQqwcVO2aDQgOWhI28da57HksMrzK9HlRxg==" + }, + "node_modules/@pm2/js-api/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/@pm2/pm2-version-check": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@pm2/pm2-version-check/-/pm2-version-check-1.0.4.tgz", + "integrity": "sha512-SXsM27SGH3yTWKc2fKR4SYNxsmnvuBQ9dd6QHtEWmiZ/VqaOYPAIlS8+vMcn27YLtAEBGvNRSh3TPNvtjZgfqA==", + "dependencies": { + "debug": "^4.3.1" + } + }, + "node_modules/@redis/bloom": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-5.9.0.tgz", + "integrity": "sha512-W9D8yfKTWl4tP8lkC3MRYkMz4OfbuzE/W8iObe0jFgoRmgMfkBV+Vj38gvIqZPImtY0WB34YZkX3amYuQebvRQ==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@redis/client": "^5.9.0" + } + }, + "node_modules/@redis/client": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-5.9.0.tgz", + "integrity": "sha512-EI0Ti5pojD2p7TmcS7RRa+AJVahdQvP/urpcSbK/K9Rlk6+dwMJTQ354pCNGCwfke8x4yKr5+iH85wcERSkwLQ==", + "license": "MIT", + "dependencies": { + "cluster-key-slot": "1.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/@redis/json": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-5.9.0.tgz", + "integrity": "sha512-Bm2jjLYaXdUWPb9RaEywxnjmzw7dWKDZI4MS79mTWPV16R982jVWBj6lY2ZGelJbwxHtEVg4/FSVgYDkuO/MxA==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@redis/client": "^5.9.0" + } + }, + "node_modules/@redis/search": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-5.9.0.tgz", + "integrity": "sha512-jdk2csmJ29DlpvCIb2ySjix2co14/0iwIT3C0I+7ZaToXgPbgBMB+zfEilSuncI2F9JcVxHki0YtLA0xX3VdpA==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@redis/client": "^5.9.0" + } + }, + "node_modules/@redis/time-series": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-5.9.0.tgz", + "integrity": "sha512-W6ILxcyOqhnI7ELKjJXOktIg3w4+aBHugDbVpgVLPZ+YDjObis1M0v7ZzwlpXhlpwsfePfipeSK+KWNuymk52w==", + "license": "MIT", + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "@redis/client": "^5.9.0" + } + }, + "node_modules/@scarf/scarf": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@scarf/scarf/-/scarf-1.4.0.tgz", + "integrity": "sha512-xxeapPiUXdZAE3che6f3xogoJPeZgig6omHEy1rIY5WVsB3H2BHNnZH+gHG6x91SCWyQCzWGsuL2Hh3ClO5/qQ==", + "hasInstallScript": true, + "license": "Apache-2.0" + }, + "node_modules/@simplewebauthn/server": { + "version": "13.1.1", + "resolved": "https://registry.npmjs.org/@simplewebauthn/server/-/server-13.1.1.tgz", + "integrity": "sha512-1hsLpRHfSuMB9ee2aAdh0Htza/X3f4djhYISrggqGe3xopNjOcePiSDkDDoPzDYaaMCrbqGP1H2TYU7bgL9PmA==", + "dependencies": { + "@hexagon/base64": "^1.1.27", + "@levischuck/tiny-cbor": "^0.2.2", + "@peculiar/asn1-android": "^2.3.10", + "@peculiar/asn1-ecc": "^2.3.8", + "@peculiar/asn1-rsa": "^2.3.8", + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/asn1-x509": "^2.3.8" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", + "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "node_modules/@tootallnate/once": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", + "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/@tootallnate/quickjs-emscripten": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz", + "integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==" + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", + "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", + "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", + "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/jest": { + "version": "29.5.14", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz", + "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "25.0.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.0.0.tgz", + "integrity": "sha512-rl78HwuZlaDIUSeUKkmogkhebA+8K1Hy7tddZuJ3D0xV8pZSfsYGTsliGUol1JPzu9EKnTxPC4L1fiWouStRew==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.16.0" + } + }, + "node_modules/@types/stack-utils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", + "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "license": "ISC", + "optional": true + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agentkeepalive": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz", + "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "humanize-ms": "^1.2.1" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", + "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/amp": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/amp/-/amp-0.3.1.tgz", + "integrity": "sha512-OwIuC4yZaRogHKiuU5WlMR5Xk/jAcpPtawWL05Gj8Lvm2F6mwoJt4O/bHI+DHwG79vWd+8OFYM4/BzYqyRd3qw==" + }, + "node_modules/amp-message": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/amp-message/-/amp-message-0.1.2.tgz", + "integrity": "sha512-JqutcFwoU1+jhv7ArgW38bqrE+LQdcRv4NxNw0mp0JHQyB6tXesWRjtYKlDgHRY2o3JE5UTaBGUK8kSWUdxWUg==", + "dependencies": { + "amp": "0.3.1" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==", + "license": "MIT" + }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", + "license": "ISC", + "optional": true + }, + "node_modules/are-we-there-yet": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", + "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "optional": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" + }, + "node_modules/asap": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", + "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", + "dev": true, + "license": "MIT" + }, + "node_modules/asn1js": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.6.tgz", + "integrity": "sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA==", + "dependencies": { + "pvtsutils": "^1.3.6", + "pvutils": "^1.1.3", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/asn1js/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/ast-types": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.13.4.tgz", + "integrity": "sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/ast-types/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==" + }, + "node_modules/async-retry": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", + "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "dependencies": { + "retry": "0.13.1" + } + }, + "node_modules/async-retry/node_modules/retry": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", + "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "engines": { + "node": ">= 4" + } + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/axios": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.4.tgz", + "integrity": "sha512-1wVkUaAO6WyaYtCkcYCOx12ZgpGf9Zif+qXa4n+oYzK558YryKqiL6UWwd5DqiH3VRW0GYhTZQ/vlgJrCoNQlg==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.4", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz", + "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz", + "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-istanbul/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.2.0.tgz", + "integrity": "sha512-E/VlAEzRrsLEb2+dv8yp3bo4scof3l9nR4lrld+Iy5NyVqgVYUJnDAmunkhPMisRI32Qc4iRiz425d8vM++2fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.6", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.6.tgz", + "integrity": "sha512-v9BVVpOTLB59C9E7aSnmIF8h7qRsFpx+A2nugVMTszEOMcfjlZMsXRm4LF23I3Z9AJxc8ANpIvzbzONoX9VJlg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/basic-ftp": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/basic-ftp/-/basic-ftp-5.0.5.tgz", + "integrity": "sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/bcrypt": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz", + "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "node-addon-api": "^8.3.0", + "node-gyp-build": "^4.8.4" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/bcrypt/node_modules/node-addon-api": { + "version": "8.5.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz", + "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==", + "license": "MIT", + "engines": { + "node": "^18 || ^20 || >= 21" + } + }, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", + "license": "MIT" + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bindings": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", + "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", + "license": "MIT", + "dependencies": { + "file-uri-to-path": "1.0.0" + } + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/blessed": { + "version": "0.1.81", + "resolved": "https://registry.npmjs.org/blessed/-/blessed-0.1.81.tgz", + "integrity": "sha512-LoF5gae+hlmfORcG1M5+5XZi4LBmvlXTzwJWzUlPryN/SJdSflZvROM2TwkT0GMpq7oqT48NRd4GS7BiVBc5OQ==", + "bin": { + "blessed": "bin/tput.js" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/bodec": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/bodec/-/bodec-0.1.0.tgz", + "integrity": "sha512-Ylo+MAo5BDUq1KA3f3R/MFhh+g8cnHmo8bz3YPGhI1znrMaf77ol1sfvYJzsw3nTE+Y2GryfDxBaR+AqpAkEHQ==" + }, + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/body-parser/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", + "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cacache/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "optional": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-me-maybe": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz", + "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==", + "license": "MIT" + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001760", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", + "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/charm": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/charm/-/charm-0.1.2.tgz", + "integrity": "sha512-syedaZ9cPe7r3hoQA9twWYKu5AIyCswN5+szkmPBe9ccdLrj4bYaCnLVPTLd2kgVRc7+zoX4tyPgRnFKCj5YjQ==" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/cli-tableau": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cli-tableau/-/cli-tableau-2.0.1.tgz", + "integrity": "sha512-he+WTicka9cl0Fg/y+YyxcN6/bfQ/1O3QmgxRXDhABKqLzvoOSM4fMzp39uMyLBulAFuywD2N7UaoQE7WaADxQ==", + "dependencies": { + "chalk": "3.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/clone": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", + "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/cluster-key-slot": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz", + "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.3.tgz", + "integrity": "sha512-1L5aqIkwPfiodaMgQunkF1zRhNqifHBmtbbbxcr6yVxxBnliw4TDOW6NxpO8DJLgJ16OT+Y4ztZqP6p/FtXnAw==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "license": "ISC", + "optional": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.15.1.tgz", + "integrity": "sha512-VlfT9F3V0v+jr4yxPc5gg9s62/fIVWsd2Bk2iD435um1NlGMYdVCq+MjcXnhYq2icNOizHr1kK+5TI6H0Hy0ag==" + }, + "node_modules/component-emitter": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.1.tgz", + "integrity": "sha512-T0+barUSQRTUQASh8bx02dl+DhF54GtIDY13Y3m9oWTklKbb3Wv974meRpeZ3lp1JpLVECWWNHC4vaG2XHXouQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "license": "ISC", + "optional": true + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" + }, + "node_modules/cookiejar": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/cookiejar/-/cookiejar-2.1.4.tgz", + "integrity": "sha512-LDx6oHrK+PhzLKJU9j5S7/Y3jM/mUHvD/DeI1WQmJn652iPC5Y4TBzC9l+5OMOXlyTTA+SmVUPm0HQUwpD5Jqw==", + "dev": true, + "license": "MIT" + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/croner": { + "version": "4.1.97", + "resolved": "https://registry.npmjs.org/croner/-/croner-4.1.97.tgz", + "integrity": "sha512-/f6gpQuxDaqXu+1kwQYSckUglPaOrHdbIlBAu0YuW8/Cdb45XwXYNUBXg3r/9Mo6n540Kn/smKcZWko5x99KrQ==" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/culvert": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/culvert/-/culvert-0.1.2.tgz", + "integrity": "sha512-yi1x3EAWKjQTreYWeSd98431AV+IEE0qoDyOoaHJ7KJ21gv6HtBXHVLX74opVSGqcR8/AbjJBHAHpcOy2bj5Gg==" + }, + "node_modules/data-uri-to-buffer": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-6.0.2.tgz", + "integrity": "sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==" + }, + "node_modules/debug": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", + "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/debug/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dedent": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz", + "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/degenerator": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/degenerator/-/degenerator-5.0.1.tgz", + "integrity": "sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==", + "dependencies": { + "ast-types": "^0.13.4", + "escodegen": "^2.1.0", + "esprima": "^4.0.1" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT", + "optional": true + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/dezalgo": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz", + "integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==", + "dev": true, + "license": "ISC", + "dependencies": { + "asap": "^2.0.0", + "wrappy": "1" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==" + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dotenv": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.5.0.tgz", + "integrity": "sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", + "dev": true, + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, + "dependencies": { + "iconv-lite": "^0.6.2" + } + }, + "node_modules/encoding/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "optional": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/enquirer": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.3.6.tgz", + "integrity": "sha512-yjNnPr315/FjS4zIsUxYguYUPP2e1NK4d7E7ZOLiyYCcbFBiTMyID+2wvm2w6+pZ/odMA7cRkjhsPbltwBOrLg==", + "dependencies": { + "ansi-colors": "^4.1.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/escodegen": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", + "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", + "dependencies": { + "esprima": "^4.0.1", + "estraverse": "^5.2.0", + "esutils": "^2.0.2" + }, + "bin": { + "escodegen": "bin/escodegen.js", + "esgenerate": "bin/esgenerate.js" + }, + "engines": { + "node": ">=6.0" + }, + "optionalDependencies": { + "source-map": "~0.6.1" + } + }, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter2": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-5.0.1.tgz", + "integrity": "sha512-5EM1GHXycJBS6mauYAbVKT1cVs7POKWb2NXD4Vyt8dDqeZa7LaDK1/sjtL+Zb0lzTpSNil4596Dyu97hz37QLg==" + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expand-template": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz", + "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==", + "license": "(MIT OR WTFPL)", + "engines": { + "node": ">=6" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/express": { + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.12", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/express-rate-limit": { + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.5.1.tgz", + "integrity": "sha512-7iN8iPMDzOMHPUYllBEsQdWVB6fPDMPqwjBaFrgr4Jgr/+okjvzAy+UHlYYL/Vs0OsOrMkwS6PJDkFlJwoxUnw==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/express-rate-limit" + }, + "peerDependencies": { + "express": ">= 4.11" + } + }, + "node_modules/express-validator": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/express-validator/-/express-validator-7.2.1.tgz", + "integrity": "sha512-CjNE6aakfpuwGaHQZ3m8ltCG2Qvivd7RHtVMS/6nVxOM7xVGqr4bhflsm4+N5FP5zI7Zxp+Hae+9RE+o8e3ZOQ==", + "dependencies": { + "lodash": "^4.17.21", + "validator": "~13.12.0" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/extrareqp2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/extrareqp2/-/extrareqp2-1.0.0.tgz", + "integrity": "sha512-Gum0g1QYb6wpPJCVypWP3bbIuaibcFiJcpuPM10YSXp/tzqi84x9PJageob+eN4xVRIOto4wjSGNLyMD54D2xA==", + "dependencies": { + "follow-redirects": "^1.14.0" + } + }, + "node_modules/fast-json-patch": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/fast-json-patch/-/fast-json-patch-3.1.1.tgz", + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/fb-watchman": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", + "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/fclone": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/fclone/-/fclone-1.0.11.tgz", + "integrity": "sha512-GDqVQezKzRABdeqflsgMr7ktzgF9CyS+p2oe0jJqUY6izSSbhPIQJDpoU4PtGcD7VPM9xh/dVrTu6z1nwgmEGw==" + }, + "node_modules/file-uri-to-path": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", + "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", + "license": "MIT" + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz", + "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.2", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/formidable": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-3.5.4.tgz", + "integrity": "sha512-YikH+7CUTOtP44ZTnUhR7Ic2UASBPOqmaRkRKxRbywPTe5VxF7RRCck4af9wutiZ/QKM5nME9Bie2fFaPz5Gug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@paralleldrive/cuid2": "^2.2.2", + "dezalgo": "^1.0.4", + "once": "^1.4.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "funding": { + "url": "https://ko-fi.com/tunnckoCore/commissions" + } + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "license": "MIT" + }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "license": "ISC", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gauge": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", + "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.3", + "console-control-strings": "^1.1.0", + "has-unicode": "^2.0.1", + "signal-exit": "^3.0.7", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "license": "MIT", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-uri": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/get-uri/-/get-uri-6.0.4.tgz", + "integrity": "sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==", + "dependencies": { + "basic-ftp": "^5.0.2", + "data-uri-to-buffer": "^6.0.2", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==", + "license": "MIT" + }, + "node_modules/git-node-fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/git-node-fs/-/git-node-fs-1.0.0.tgz", + "integrity": "sha512-bLQypt14llVXBg0S0u8q8HmU7g9p3ysH+NvVlae5vILuUvs759665HvmR5+wb04KjHyjFcDRxdYb4kyNnluMUQ==" + }, + "node_modules/git-sha1": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/git-sha1/-/git-sha1-0.1.2.tgz", + "integrity": "sha512-2e/nZezdVlyCopOCYHeW0onkbZg7xP1Ad6pndPy1rCygeRykefUS6r7oA5cJRGEFvseiaz5a/qUHFVX1dd6Isg==" + }, + "node_modules/github-from-package": { + "version": "0.0.0", + "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz", + "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==", + "license": "MIT" + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "devOptional": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", + "license": "ISC", + "optional": true + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/helmet": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-7.2.0.tgz", + "integrity": "sha512-ZRiwvN089JfMXokizgqEPXsl2Guk094yExfoDXR0cBYWxtBbaSww/w+vT4WEJsBW2iTUi1GgZ6swmoug3Oy4Xw==", + "license": "MIT", + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause", + "optional": true + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-proxy-agent": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", + "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", + "license": "MIT", + "optional": true, + "dependencies": { + "@tootallnate/once": "1", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "ms": "^2.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "license": "ISC" + }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "license": "MIT", + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==", + "license": "MIT" + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", + "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-reports": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.2.0.tgz", + "integrity": "sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-changed-files/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-circus/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-cli/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/jest-cli/node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-cli/node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-cli/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-config/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-config/node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-diff/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-runner/node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-runner/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-util/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jest-validate/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/js-git": { + "version": "0.7.8", + "resolved": "https://registry.npmjs.org/js-git/-/js-git-0.7.8.tgz", + "integrity": "sha512-+E5ZH/HeRnoc/LW0AmAyhU+mNcWBzAKE+30+IDMLSLbbK+Tdt02AdkOKq9u15rlJsDEGFqtgckc8ZM59LhhiUA==", + "dependencies": { + "bodec": "^0.1.0", + "culvert": "^0.1.2", + "git-sha1": "^0.1.2", + "pako": "^0.2.5" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "license": "MIT" + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "optional": true + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", + "dependencies": { + "jws": "^3.2.2", + "lodash.includes": "^4.3.0", + "lodash.isboolean": "^3.0.3", + "lodash.isinteger": "^4.0.4", + "lodash.isnumber": "^3.0.3", + "lodash.isplainobject": "^4.0.6", + "lodash.isstring": "^4.0.1", + "lodash.once": "^4.0.0", + "ms": "^2.1.1", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/jwa": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.2.tgz", + "integrity": "sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==", + "dependencies": { + "buffer-equal-constant-time": "^1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/knex": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz", + "integrity": "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==", + "license": "MIT", + "dependencies": { + "colorette": "2.0.19", + "commander": "^10.0.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.6.2", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" + }, + "engines": { + "node": ">=16" + }, + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/knex/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/knex/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" + }, + "node_modules/lazy": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/lazy/-/lazy-1.0.11.tgz", + "integrity": "sha512-Y+CjUfLmIpoUCCRl0ub4smrYtGGr5AOa2AKOaWelGHOGz33X/Y/KizefGqbkwfz44+cnq/+9habclf8vOmu2LA==", + "engines": { + "node": ">=0.2.0" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", + "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", + "license": "MIT" + }, + "node_modules/lodash.includes": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", + "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" + }, + "node_modules/lodash.isboolean": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", + "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.isinteger": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", + "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" + }, + "node_modules/lodash.isnumber": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", + "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + }, + "node_modules/lodash.isstring": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "license": "MIT" + }, + "node_modules/lodash.once": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", + "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" + }, + "node_modules/long": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz", + "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==", + "license": "Apache-2.0" + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru.min": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.2.tgz", + "integrity": "sha512-Nv9KddBcQSlQopmBHXSsZVY5xsdlZkdH/Iey0BlcBYggMd4two7cZnKOK9vmy3nY0O5RGH99z1PCeTpPqszUYg==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-fetch-happen": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", + "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==", + "license": "ISC", + "optional": true, + "dependencies": { + "agentkeepalive": "^4.1.3", + "cacache": "^15.2.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^4.0.1", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^6.0.0", + "minipass": "^3.1.3", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^1.3.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.2", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^6.0.0", + "ssri": "^8.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz", + "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/merge-descriptors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", + "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-collect": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", + "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-fetch": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz", + "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==", + "license": "MIT", + "optional": true, + "dependencies": { + "minipass": "^3.1.0", + "minipass-sized": "^1.0.3", + "minizlib": "^2.0.0" + }, + "engines": { + "node": ">=8" + }, + "optionalDependencies": { + "encoding": "^0.1.12" + } + }, + "node_modules/minipass-flush": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", + "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minipass-pipeline": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", + "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minipass-sized": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz", + "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mkdirp-classic": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", + "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==", + "license": "MIT" + }, + "node_modules/module-details-from-path": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/module-details-from-path/-/module-details-from-path-1.0.4.tgz", + "integrity": "sha512-EGWKgxALGMgzvxYF1UyGTy0HXX/2vHLkw6+NvDKW2jypWbHpjQuj4UMcqQWXHERJhVGKikolT06G3bcKe4fi7w==" + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multer": { + "version": "1.4.5-lts.2", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.2.tgz", + "integrity": "sha512-VzGiVigcG9zUAoCNU+xShztrlr1auZOlurXynNvO9GiWD1/mTBbUljOKY+qMeazBqXgRnjzeEgJI/wyjJUHg9A==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==" + }, + "node_modules/mysql2": { + "version": "3.14.1", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.14.1.tgz", + "integrity": "sha512-7ytuPQJjQB8TNAYX/H2yhL+iQOnIBjAMam361R7UAL0lOVXWjtdrmoL9HYKqKoLp/8UUTRcvo1QPvK9KL7wA8w==", + "license": "MIT", + "dependencies": { + "aws-ssl-profiles": "^1.1.1", + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru.min": "^1.0.0", + "named-placeholders": "^1.1.3", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "license": "MIT", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/napi-build-utils": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz", + "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==", + "license": "MIT" + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/needle": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.4.0.tgz", + "integrity": "sha512-4Hnwzr3mi5L97hMYeNl8wRW/Onhy4nUKR/lVemJ8gJedxxUyBLm9kkrDColJvoSfwi0jCNhD+xCdOtiGDQiRZg==", + "dependencies": { + "debug": "^3.2.6", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "bin": { + "needle": "bin/needle" + }, + "engines": { + "node": ">= 4.4.x" + } + }, + "node_modules/needle/node_modules/debug": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", + "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "dependencies": { + "ms": "^2.1.1" + } + }, + "node_modules/needle/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/netmask": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/netmask/-/netmask-2.0.2.tgz", + "integrity": "sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/node-abi": { + "version": "3.74.0", + "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.74.0.tgz", + "integrity": "sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==", + "license": "MIT", + "dependencies": { + "semver": "^7.3.5" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/node-cache": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz", + "integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==", + "license": "MIT", + "dependencies": { + "clone": "2.x" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/node-gyp": { + "version": "8.4.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz", + "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==", + "license": "MIT", + "optional": true, + "dependencies": { + "env-paths": "^2.2.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.6", + "make-fetch-happen": "^9.1.0", + "nopt": "^5.0.0", + "npmlog": "^6.0.0", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.2", + "which": "^2.0.2" + }, + "bin": { + "node-gyp": "bin/node-gyp.js" + }, + "engines": { + "node": ">= 10.12.0" + } + }, + "node_modules/node-gyp-build": { + "version": "4.8.4", + "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz", + "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==", + "license": "MIT", + "bin": { + "node-gyp-build": "bin.js", + "node-gyp-build-optional": "optional.js", + "node-gyp-build-test": "build-test.js" + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", + "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/npmlog": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", + "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "optional": true, + "dependencies": { + "are-we-there-yet": "^3.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^4.0.3", + "set-blocking": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/nssocket": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/nssocket/-/nssocket-0.6.0.tgz", + "integrity": "sha512-a9GSOIql5IqgWJR3F/JXG4KpJTA3Z53Cj0MeMvGpglytB1nxE4PdFNC0jINe27CS7cGivoynwc054EzCcT3M3w==", + "dependencies": { + "eventemitter2": "~0.4.14", + "lazy": "~1.0.11" + }, + "engines": { + "node": ">= 0.10.x" + } + }, + "node_modules/nssocket/node_modules/eventemitter2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", + "integrity": "sha512-K7J4xq5xAD5jHsGM5ReWXRTFa3JRGofHiMcVgQ8PRwgWxzjHpMWCIzsmyf60+mh8KLsqYPcjUMa0AC4hd6lPyQ==" + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/openapi-types": { + "version": "12.1.3", + "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz", + "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==", + "license": "MIT", + "peer": true + }, + "node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/pac-proxy-agent": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/pac-proxy-agent/-/pac-proxy-agent-7.2.0.tgz", + "integrity": "sha512-TEB8ESquiLMc0lV8vcd5Ql/JAKAoyzHFXaStwjkzpOpC5Yv+pIzLfHvjTSdf3vpa2bMiUQrg9i6276yn8666aA==", + "dependencies": { + "@tootallnate/quickjs-emscripten": "^0.23.0", + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "get-uri": "^6.0.1", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.6", + "pac-resolver": "^7.0.1", + "socks-proxy-agent": "^8.0.5" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-proxy-agent/node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pac-resolver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/pac-resolver/-/pac-resolver-7.0.1.tgz", + "integrity": "sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==", + "dependencies": { + "degenerator": "^5.0.0", + "netmask": "^2.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/pako": { + "version": "0.2.9", + "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", + "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==" + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", + "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "license": "MIT" + }, + "node_modules/pg-connection-string": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidusage": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-3.0.2.tgz", + "integrity": "sha512-g0VU+y08pKw5M8EZ2rIGiEBaB8wrQMjYGFfW2QVIfyT8V+fq8YFLkvlz4bz5ljvFDJYNFCWT3PWqcRr2FKO81w==", + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pm2": { + "version": "5.4.3", + "resolved": "https://registry.npmjs.org/pm2/-/pm2-5.4.3.tgz", + "integrity": "sha512-4/I1htIHzZk1Y67UgOCo4F1cJtas1kSds31N8zN0PybO230id1nigyjGuGFzUnGmUFPmrJ0On22fO1ChFlp7VQ==", + "dependencies": { + "@pm2/agent": "~2.0.0", + "@pm2/io": "~6.0.1", + "@pm2/js-api": "~0.8.0", + "@pm2/pm2-version-check": "latest", + "async": "~3.2.0", + "blessed": "0.1.81", + "chalk": "3.0.0", + "chokidar": "^3.5.3", + "cli-tableau": "^2.0.0", + "commander": "2.15.1", + "croner": "~4.1.92", + "dayjs": "~1.11.5", + "debug": "^4.3.1", + "enquirer": "2.3.6", + "eventemitter2": "5.0.1", + "fclone": "1.0.11", + "js-yaml": "~4.1.0", + "mkdirp": "1.0.4", + "needle": "2.4.0", + "pidusage": "~3.0", + "pm2-axon": "~4.0.1", + "pm2-axon-rpc": "~0.7.1", + "pm2-deploy": "~1.0.2", + "pm2-multimeter": "^0.1.2", + "promptly": "^2", + "semver": "^7.2", + "source-map-support": "0.5.21", + "sprintf-js": "1.1.2", + "vizion": "~2.2.1" + }, + "bin": { + "pm2": "bin/pm2", + "pm2-dev": "bin/pm2-dev", + "pm2-docker": "bin/pm2-docker", + "pm2-runtime": "bin/pm2-runtime" + }, + "engines": { + "node": ">=12.0.0" + }, + "optionalDependencies": { + "pm2-sysmonit": "^1.2.8" + } + }, + "node_modules/pm2-axon": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pm2-axon/-/pm2-axon-4.0.1.tgz", + "integrity": "sha512-kES/PeSLS8orT8dR5jMlNl+Yu4Ty3nbvZRmaAtROuVm9nYYGiaoXqqKQqQYzWQzMYWUKHMQTvBlirjE5GIIxqg==", + "dependencies": { + "amp": "~0.3.1", + "amp-message": "~0.1.1", + "debug": "^4.3.1", + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/pm2-axon-rpc": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/pm2-axon-rpc/-/pm2-axon-rpc-0.7.1.tgz", + "integrity": "sha512-FbLvW60w+vEyvMjP/xom2UPhUN/2bVpdtLfKJeYM3gwzYhoTEEChCOICfFzxkxuoEleOlnpjie+n1nue91bDQw==", + "dependencies": { + "debug": "^4.3.1" + }, + "engines": { + "node": ">=5" + } + }, + "node_modules/pm2-deploy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pm2-deploy/-/pm2-deploy-1.0.2.tgz", + "integrity": "sha512-YJx6RXKrVrWaphEYf++EdOOx9EH18vM8RSZN/P1Y+NokTKqYAca/ejXwVLyiEpNju4HPZEk3Y2uZouwMqUlcgg==", + "dependencies": { + "run-series": "^1.1.8", + "tv4": "^1.3.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/pm2-multimeter": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/pm2-multimeter/-/pm2-multimeter-0.1.2.tgz", + "integrity": "sha512-S+wT6XfyKfd7SJIBqRgOctGxaBzUOmVQzTAS+cg04TsEUObJVreha7lvCfX8zzGVr871XwCSnHUU7DQQ5xEsfA==", + "dependencies": { + "charm": "~0.1.1" + } + }, + "node_modules/pm2-sysmonit": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/pm2-sysmonit/-/pm2-sysmonit-1.2.8.tgz", + "integrity": "sha512-ACOhlONEXdCTVwKieBIQLSi2tQZ8eKinhcr9JpZSUAL8Qy0ajIgRtsLxG/lwPOW3JEKqPyw/UaHmTWhUzpP4kA==", + "optional": true, + "dependencies": { + "async": "^3.2.0", + "debug": "^4.3.1", + "pidusage": "^2.0.21", + "systeminformation": "^5.7", + "tx2": "~1.0.4" + } + }, + "node_modules/pm2-sysmonit/node_modules/pidusage": { + "version": "2.0.21", + "resolved": "https://registry.npmjs.org/pidusage/-/pidusage-2.0.21.tgz", + "integrity": "sha512-cv3xAQos+pugVX+BfXpHsbyz/dLzX+lr44zNMsYiGxUw+kV5sgQCIcLd1z+0vq+KyC7dJ+/ts2PsfgWfSC3WXA==", + "optional": true, + "dependencies": { + "safe-buffer": "^5.2.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pm2/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pm2/node_modules/sprintf-js": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.2.tgz", + "integrity": "sha512-VE0SOVEHCk7Qc8ulkWw3ntAzXuqf7S2lvwQaDLRnUeIEaKNQJzV6BwmLKhOqT61aGhfUMrXeaBk+oDGCzvhcug==" + }, + "node_modules/pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/prebuild-install": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz", + "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==", + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.0", + "expand-template": "^2.0.3", + "github-from-package": "0.0.0", + "minimist": "^1.2.3", + "mkdirp-classic": "^0.5.3", + "napi-build-utils": "^2.0.0", + "node-abi": "^3.3.0", + "pump": "^3.0.0", + "rc": "^1.2.7", + "simple-get": "^4.0.0", + "tar-fs": "^2.0.0", + "tunnel-agent": "^0.6.0" + }, + "bin": { + "prebuild-install": "bin.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "license": "MIT" + }, + "node_modules/promise-inflight": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", + "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", + "license": "ISC", + "optional": true + }, + "node_modules/promise-retry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz", + "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==", + "license": "MIT", + "optional": true, + "dependencies": { + "err-code": "^2.0.2", + "retry": "^0.12.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/promptly": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/promptly/-/promptly-2.2.0.tgz", + "integrity": "sha512-aC9j+BZsRSSzEsXBNBwDnAxujdx19HycZoKgRgzWnS8eOHg1asuf9heuLprfbe739zY3IdUQx+Egv6Jn135WHA==", + "dependencies": { + "read": "^1.0.4" + } + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/proxy-addr": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", + "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/proxy-agent": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/proxy-agent/-/proxy-agent-6.3.1.tgz", + "integrity": "sha512-Rb5RVBy1iyqOtNl15Cw/llpeLH8bsb37gM1FUfKQ+Wck6xHlbAhWGUFiTRHtkjqGTA5pSHz6+0hrPW/oECihPQ==", + "dependencies": { + "agent-base": "^7.0.2", + "debug": "^4.3.4", + "http-proxy-agent": "^7.0.0", + "https-proxy-agent": "^7.0.2", + "lru-cache": "^7.14.1", + "pac-proxy-agent": "^7.0.1", + "proxy-from-env": "^1.1.0", + "socks-proxy-agent": "^8.0.2" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/agent-base": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", + "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/http-proxy-agent": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", + "dependencies": { + "agent-base": "^7.1.0", + "debug": "^4.3.4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/https-proxy-agent": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", + "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "4" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-agent/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/proxy-agent/node_modules/socks-proxy-agent": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-8.0.5.tgz", + "integrity": "sha512-HehCEsotFqbPW9sJ8WVYB6UbmIMv7kUUORIF2Nncq4VQvBfNBLibW9YZR5dlYCSUhwcD628pRllm7n+E+YTzJw==", + "dependencies": { + "agent-base": "^7.1.2", + "debug": "^4.3.4", + "socks": "^2.8.3" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pump": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", + "integrity": "sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/pvtsutils": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz", + "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==", + "dependencies": { + "tslib": "^2.8.1" + } + }, + "node_modules/pvtsutils/node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/qrcode": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/qrcode/-/qrcode-1.5.4.tgz", + "integrity": "sha512-1ca71Zgiu6ORjHqFBDpnSMTR2ReToX4l1Au1VFLyVeBTFavzQnv5JxMFr3ukHVKpSrSA2MCk0lNJSykjUfz7Zg==", + "dependencies": { + "dijkstrajs": "^1.0.1", + "pngjs": "^5.0.0", + "yargs": "^15.3.1" + }, + "bin": { + "qrcode": "bin/qrcode" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", + "dependencies": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "bin": { + "rc": "cli.js" + } + }, + "node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "dev": true, + "license": "MIT" + }, + "node_modules/read": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/read/-/read-1.0.7.tgz", + "integrity": "sha512-rSOKNYUmaxy0om1BNjMN4ezNT6VKK+2xF4GBhc81mkH7L60i6dp8qPYrkndNLT3QPphoII3maL9PVC9XmhHwVQ==", + "dependencies": { + "mute-stream": "~0.0.4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/rechoir": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz", + "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==", + "license": "MIT", + "dependencies": { + "resolve": "^1.20.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/redis": { + "version": "5.9.0", + "resolved": "https://registry.npmjs.org/redis/-/redis-5.9.0.tgz", + "integrity": "sha512-E8dQVLSyH6UE/C9darFuwq4usOPrqfZ1864kI4RFbr5Oj9ioB9qPF0oJMwX7s8mf6sPYrz84x/Dx1PGF3/0EaQ==", + "license": "MIT", + "dependencies": { + "@redis/bloom": "5.9.0", + "@redis/client": "5.9.0", + "@redis/json": "5.9.0", + "@redis/search": "5.9.0", + "@redis/time-series": "5.9.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-in-the-middle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/require-in-the-middle/-/require-in-the-middle-5.2.0.tgz", + "integrity": "sha512-efCx3b+0Z69/LGJmm9Yvi4cqEdxnoGnxYxGxBghkkTTFeXRtTCmmhO0AnAfHz59k957uTSuy8WaHqOs8wbYUWg==", + "dependencies": { + "debug": "^4.1.1", + "module-details-from-path": "^1.0.3", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==" + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", + "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 4" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-series": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/run-series/-/run-series-1.1.9.tgz", + "integrity": "sha512-Arc4hUN896vjkqCYrUXquBFtRZdv1PfLbTYP71efP6butxyQ0kWpiNJyAgsxscmQg1cqvHY32/UCBzXedTpU2g==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" + }, + "node_modules/sax": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + }, + "node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/send/node_modules/debug/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/send/node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shimmer": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.1.tgz", + "integrity": "sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw==" + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "license": "ISC" + }, + "node_modules/simple-concat": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz", + "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/simple-get": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz", + "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "decompress-response": "^6.0.0", + "once": "^1.3.1", + "simple-concat": "^1.0.0" + } + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "license": "MIT", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.8.4", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.4.tgz", + "integrity": "sha512-D3YaD0aRxR3mEcqnidIs7ReYJFVzWdd6fXJYUM8ixcQcJRGTka/b3saV0KflYhyVJXKhb947GndU35SxYNResQ==", + "license": "MIT", + "dependencies": { + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks-proxy-agent": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz", + "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause" + }, + "node_modules/sqlite3": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz", + "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "dependencies": { + "bindings": "^1.5.0", + "node-addon-api": "^7.0.0", + "prebuild-install": "^7.1.1", + "tar": "^6.1.11" + }, + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } + } + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/ssri": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", + "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", + "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", + "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "license": "MIT" + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/superagent": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/superagent/-/superagent-10.2.3.tgz", + "integrity": "sha512-y/hkYGeXAj7wUMjxRbB21g/l6aAEituGXM9Rwl4o20+SX3e8YOSV6BxFXl+dL3Uk0mjSL3kCbNkwURm8/gEDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "component-emitter": "^1.3.1", + "cookiejar": "^2.1.4", + "debug": "^4.3.7", + "fast-safe-stringify": "^2.1.1", + "form-data": "^4.0.4", + "formidable": "^3.5.4", + "methods": "^1.1.2", + "mime": "2.6.0", + "qs": "^6.11.2" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/superagent/node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/supertest": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/supertest/-/supertest-7.1.4.tgz", + "integrity": "sha512-tjLPs7dVyqgItVFirHYqe2T+MfWc2VOBQ8QFKKbWTA3PU7liZR8zoSpAi/C1k1ilm9RsXIKYf197oap9wXGVYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "methods": "^1.1.2", + "superagent": "^10.2.3" + }, + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/swagger-jsdoc": { + "version": "6.2.8", + "resolved": "https://registry.npmjs.org/swagger-jsdoc/-/swagger-jsdoc-6.2.8.tgz", + "integrity": "sha512-VPvil1+JRpmJ55CgAtn8DIcpBs0bL5L3q5bVQvF4tAW/k/9JYSj7dCpaYCAv5rufe0vcCbBRQXGvzpkWjvLklQ==", + "license": "MIT", + "dependencies": { + "commander": "6.2.0", + "doctrine": "3.0.0", + "glob": "7.1.6", + "lodash.mergewith": "^4.6.2", + "swagger-parser": "^10.0.3", + "yaml": "2.0.0-1" + }, + "bin": { + "swagger-jsdoc": "bin/swagger-jsdoc.js" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/swagger-jsdoc/node_modules/commander": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.0.tgz", + "integrity": "sha512-zP4jEKbe8SHzKJYQmq8Y9gYjtO/POJLgIdKgV7B9qNmABVFVc+ctqSX6iXh4mCpJfRBOabiZ2YKPg8ciDw6C+Q==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/swagger-jsdoc/node_modules/glob": { + "version": "7.1.6", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", + "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/swagger-parser": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/swagger-parser/-/swagger-parser-10.0.3.tgz", + "integrity": "sha512-nF7oMeL4KypldrQhac8RyHerJeGPD1p2xDh900GPvc+Nk7nWP6jX2FcC7WmkinMoAmoO774+AFXcWsW8gMWEIg==", + "license": "MIT", + "dependencies": { + "@apidevtools/swagger-parser": "10.0.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.30.1", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.30.1.tgz", + "integrity": "sha512-4mNAUM31sr52K3JcK9qiGbfsFKNh/dm3PkEe+F9FAM31YY/NoRYUgsR/L6d7LLFn6PgZXtBG2ygp8+7UnpUIPg==", + "license": "Apache-2.0", + "dependencies": { + "@scarf/scarf": "=1.4.0" + } + }, + "node_modules/swagger-ui-express": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.1.tgz", + "integrity": "sha512-SrNU3RiBGTLLmFU8GIJdOdanJTl4TOmT27tt3bWWHppqYmAZ6IDuEuBvMU6nZq0zLEe6b/1rACXCgLZqO6ZfrA==", + "license": "MIT", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, + "node_modules/systeminformation": { + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.27.1.tgz", + "integrity": "sha512-FgkVpT6GgATtNvADgtEzDxI/SVaBisfnQ4fmgQZhCJ4335noTgt9q6O81ioHwzs9HgnJaaFSdHSEMIkneZ55iA==", + "optional": true, + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tar-fs": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz", + "integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==", + "license": "MIT", + "dependencies": { + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.1.4" + } + }, + "node_modules/tar-fs/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tar-stream/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tar/node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/tar/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/tarn": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", + "integrity": "sha512-51LAVKUSZSVfI05vjPESNc5vwqqZpbXCsU+/+wxlOrUjk2SnFTt97v9ZgQrD4YmxYW1Px6w2KjaDitCfkvgxMQ==", + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", + "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tildify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", + "integrity": "sha512-Cc+OraorugtXNfs50hU9KS369rFXCfgGLpfCfvlc+Ud5u6VWmUQsOAa9HbTvheQdYnrdJqqv1e5oIqXppMYnSw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", + "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==" + }, + "node_modules/tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + }, + "engines": { + "node": "*" + } + }, + "node_modules/tv4": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tv4/-/tv4-1.3.0.tgz", + "integrity": "sha512-afizzfpJgvPr+eDkREK4MxJ/+r8nEEHcmitwgnPUqpaP+FpwQyadnxNoSACbgc/b1LsZYtODGoPiFxQrgJgjvw==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/tx2": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/tx2/-/tx2-1.0.5.tgz", + "integrity": "sha512-sJ24w0y03Md/bxzK4FU8J8JveYYUbSs2FViLJ2D/8bytSiyPRbuE3DyL/9UKYXTZlV3yXq0L8GLlhobTnekCVg==", + "optional": true, + "dependencies": { + "json-stringify-safe": "^5.0.1" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", + "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "7.16.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", + "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", + "dev": true, + "license": "MIT" + }, + "node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "optional": true, + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "optional": true, + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", + "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/validator": { + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vizion": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/vizion/-/vizion-2.2.1.tgz", + "integrity": "sha512-sfAcO2yeSU0CSPFI/DmZp3FsFE9T+8913nv1xWBOyzODv13fwkn6Vl7HqxGpkr9F608M+8SuFId3s+BlZqfXww==", + "dependencies": { + "async": "^2.6.3", + "git-node-fs": "^1.0.0", + "ini": "^1.3.5", + "js-git": "^0.7.8" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/vizion/node_modules/async": { + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz", + "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==", + "dependencies": { + "lodash": "^4.17.14" + } + }, + "node_modules/walker": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", + "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "devOptional": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==" + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "license": "ISC", + "optional": true, + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.0.0-1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.0.0-1.tgz", + "integrity": "sha512-W7h5dEhywMKenDJh2iX/LABkbFnBxasD27oyXWDS/feDsxiw0dD5ncXdYXgkvAsXIY2MpW/ZKkr9IU30DBdMNQ==", + "license": "ISC", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/z-schema": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/z-schema/-/z-schema-5.0.5.tgz", + "integrity": "sha512-D7eujBWkLa3p2sIpJA0d1pr7es+a7m0vFAnZLlCEKq/Ij2k0MLi9Br2UPxoxdYystm5K1yeBGzub0FlYUEWj2Q==", + "license": "MIT", + "dependencies": { + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "validator": "^13.7.0" + }, + "bin": { + "z-schema": "bin/z-schema" + }, + "engines": { + "node": ">=8.0.0" + }, + "optionalDependencies": { + "commander": "^9.4.1" + } + }, + "node_modules/z-schema/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "optional": true, + "engines": { + "node": "^12.20.0 || >=14" + } + } + } +} diff --git a/deploy/tkfb-package/api.hyungi.net/package.json b/deploy/tkfb-package/api.hyungi.net/package.json new file mode 100644 index 0000000..ff0bf1d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/package.json @@ -0,0 +1,51 @@ +{ + "name": "hyungi-api", + "version": "2.2.0", + "main": "index.js", + "scripts": { + "start": "pm2-runtime start ecosystem.config.js --env production", + "dev": "pm2-runtime start ecosystem.config.js --env development", + "test": "jest", + "test:watch": "jest --watch", + "test:coverage": "jest --coverage", + "test:unit": "jest tests/unit", + "test:integration": "jest tests/integration", + "test:verbose": "jest --verbose", + "setup": "node ../setup.js", + "db:migrate": "knex migrate:latest --knexfile knexfile.js", + "db:migrate:make": "knex migrate:make --knexfile knexfile.js", + "db:rollback": "knex migrate:rollback --knexfile knexfile.js", + "db:seed": "knex seed:run --knexfile knexfile.js", + "db:seed:make": "knex seed:make --knexfile knexfile.js" + }, + "dependencies": { + "@simplewebauthn/server": "^13.1.1", + "async-retry": "^1.3.3", + "axios": "^1.6.7", + "bcrypt": "^6.0.0", + "bcryptjs": "^2.4.3", + "compression": "^1.8.1", + "cors": "^2.8.5", + "dotenv": "^16.4.5", + "express": "^4.18.2", + "express-rate-limit": "^7.5.1", + "express-validator": "^7.2.1", + "helmet": "^7.2.0", + "jsonwebtoken": "^9.0.0", + "knex": "^3.1.0", + "multer": "^1.4.5-lts.1", + "mysql2": "^3.14.1", + "node-cache": "^5.1.2", + "pm2": "^5.3.0", + "qrcode": "^1.5.4", + "redis": "^5.9.0", + "sqlite3": "^5.1.6", + "swagger-jsdoc": "^6.2.8", + "swagger-ui-express": "^5.0.1" + }, + "devDependencies": { + "@types/jest": "^29.5.12", + "jest": "^29.7.0", + "supertest": "^7.0.0" + } +} diff --git a/deploy/tkfb-package/api.hyungi.net/public/img/login-bg.jpeg b/deploy/tkfb-package/api.hyungi.net/public/img/login-bg.jpeg new file mode 100644 index 0000000..1681fd4 Binary files /dev/null and b/deploy/tkfb-package/api.hyungi.net/public/img/login-bg.jpeg differ diff --git a/deploy/tkfb-package/api.hyungi.net/public/pages/hello.txt b/deploy/tkfb-package/api.hyungi.net/public/pages/hello.txt new file mode 100644 index 0000000..7d5e07e --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/public/pages/hello.txt @@ -0,0 +1 @@ +Hello Test diff --git a/deploy/tkfb-package/api.hyungi.net/public/pages/work_analysis_dashboard.html b/deploy/tkfb-package/api.hyungi.net/public/pages/work_analysis_dashboard.html new file mode 100644 index 0000000..6aa8cd3 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/public/pages/work_analysis_dashboard.html @@ -0,0 +1,689 @@ + + + + + + 작업 분석 대시보드 + + + + +
+
+

📊 작업 분석 대시보드

+

실시간 작업 현황 및 통계 분석

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+
+

총 작업시간

+
-
+
시간
+
+ +
+

총 보고서

+
-
+
+
+ +
+

활성 프로젝트

+
-
+
+
+ +
+

에러율

+
-
+
%
+
+
+ +
+
+

📈 일별 작업시간 추이

+
+ +
+
+ +
+

👥 작업자별 통계

+
+ +
+
+ +
+

📋 프로젝트별 통계

+
+ +
+
+ +
+

🔧 작업유형별 통계

+
+ +
+
+
+ +
+

🕐 최근 작업 현황

+
+
데이터를 불러오는 중...
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/analysisRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/analysisRoutes.js new file mode 100644 index 0000000..e0d9c92 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/analysisRoutes.js @@ -0,0 +1,10 @@ +// /routes/analysisRoutes.js +const express = require('express'); +const router = express.Router(); +const { getAnalysisData } = require('../controllers/analysisController'); +const { verifyToken } = require('../middlewares/authMiddleware'); // 인증 미들웨어 추가 + +// GET /api/analysis?startDate=...&endDate=... +router.get('/', verifyToken, getAnalysisData); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/attendanceRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/attendanceRoutes.js new file mode 100644 index 0000000..b93a7e4 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/attendanceRoutes.js @@ -0,0 +1,46 @@ +const express = require('express'); +const router = express.Router(); +const AttendanceController = require('../controllers/attendanceController'); +const { verifyToken } = require('../middlewares/authMiddleware'); + +// 모든 라우트에 인증 미들웨어 적용 +router.use(verifyToken); + +// 일일 근태 현황 조회 (대시보드용) +router.get('/daily-status', AttendanceController.getDailyAttendanceStatus); + +// 일일 근태 기록 조회 +router.get('/daily-records', AttendanceController.getDailyAttendanceRecords); + +// 기간별 근태 기록 조회 (월별 조회용) +router.get('/records', AttendanceController.getAttendanceRecordsByRange); + +// 근태 기록 생성/업데이트 +router.post('/records', AttendanceController.upsertAttendanceRecord); +router.put('/records', AttendanceController.upsertAttendanceRecord); + +// 휴가 처리 +router.post('/vacation', AttendanceController.processVacation); + +// 초과근무 승인 +router.post('/overtime/approve', AttendanceController.approveOvertime); + +// 근로 유형 목록 조회 +router.get('/attendance-types', AttendanceController.getAttendanceTypes); + +// 휴가 유형 목록 조회 +router.get('/vacation-types', AttendanceController.getVacationTypes); + +// 작업자 휴가 잔여 조회 +router.get('/vacation-balance/:worker_id', AttendanceController.getWorkerVacationBalance); + +// 월별 근태 통계 +router.get('/monthly-stats', AttendanceController.getMonthlyAttendanceStats); + +// 출근 체크 목록 조회 (아침용, 휴가 정보 포함) +router.get('/checkin-list', AttendanceController.getCheckinList); + +// 출근 체크 일괄 저장 +router.post('/checkins', AttendanceController.saveCheckins); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/auth.js b/deploy/tkfb-package/api.hyungi.net/routes/auth.js new file mode 100644 index 0000000..ee49f4f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/auth.js @@ -0,0 +1,215 @@ +// routes/auth.js +const express = require('express'); +const bcrypt = require('bcrypt'); +const jwt = require('jsonwebtoken'); +const { requireAuth, requireRole } = require('../middlewares/auth'); +const router = express.Router(); + +// 임시 사용자 데이터 (실제 운영 시 DB 사용 필수) +// 비밀번호 해시는 bcrypt.hash('password', 10)으로 생성됨 +let users = [ + { + user_id: 1, + username: 'admin', + password: '$2b$10$N9qo8uLOickgx2ZMRZoMyeIjZRGdjGj/n3.w7VtL.r8yR.nTfC7Hy', // 'password' 해시 + name: '관리자', + access_level: 'admin', + worker_id: null, + created_at: new Date() + }, + { + user_id: 2, + username: 'group_leader1', + password: '$2b$10$N9qo8uLOickgx2ZMRZoMyeIjZRGdjGj/n3.w7VtL.r8yR.nTfC7Hy', // 'password' 해시 + name: '김그룹장', + access_level: 'group_leader', + worker_id: 1, + created_at: new Date() + } +]; + +// 보안 경고: 운영 환경에서는 반드시 .env의 JWT_SECRET을 설정해야 합니다 +if (!process.env.JWT_SECRET) { + console.warn('⚠️ WARNING: JWT_SECRET이 설정되지 않았습니다. 운영 환경에서는 반드시 설정하세요!'); +} + +/** + * 로그인 + */ +router.post('/login', async (req, res) => { + try { + const { username, password } = req.body; + + if (!username || !password) { + return res.status(400).json({ error: '사용자명과 비밀번호를 입력해주세요.' }); + } + + const user = users.find(u => u.username === username); + if (!user) { + return res.status(401).json({ error: '사용자를 찾을 수 없습니다.' }); + } + + // 비밀번호 확인 (bcrypt.compare 사용) + const isValid = await bcrypt.compare(password, user.password); + if (!isValid) { + return res.status(401).json({ error: '비밀번호가 올바르지 않습니다.' }); + } + + // JWT 토큰 생성 + const token = jwt.sign( + { + user_id: user.user_id, + username: user.username, + access_level: user.access_level, + worker_id: user.worker_id + }, + process.env.JWT_SECRET, + { expiresIn: '24h' } + ); + + res.json({ + success: true, + token, + user: { + user_id: user.user_id, + username: user.username, + name: user.name, + access_level: user.access_level, + worker_id: user.worker_id + } + }); + + } catch (error) { + console.error('Login error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } +}); + +/** + * 현재 사용자 정보 조회 + */ +router.get('/me', requireAuth, (req, res) => { + try { + const userId = req.user.user_id; + const user = users.find(u => u.user_id === userId); + + if (!user) { + return res.status(404).json({ error: '사용자를 찾을 수 없습니다.' }); + } + + res.json({ + user_id: user.user_id, + username: user.username, + name: user.name, + access_level: user.access_level, + worker_id: user.worker_id + }); + + } catch (error) { + console.error('Get current user error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } +}); + +/** + * 사용자 등록 (관리자만) + */ +router.post('/register', requireAuth, requireRole('admin', 'system'), async (req, res) => { + try { + const { username, password, name, access_level, worker_id } = req.body; + + if (!username || !password || !name || !access_level) { + return res.status(400).json({ error: '필수 항목을 모두 입력해주세요.' }); + } + + // 사용자명 중복 체크 + const existingUser = users.find(u => u.username === username); + if (existingUser) { + return res.status(409).json({ error: '이미 존재하는 사용자명입니다.' }); + } + + // 비밀번호 해시 + const hashedPassword = await bcrypt.hash(password, 10); + + const newUser = { + user_id: users.length + 1, + username, + password: hashedPassword, + name, + access_level, + worker_id: worker_id || null, + created_at: new Date() + }; + + users.push(newUser); + + res.json({ + success: true, + message: '사용자가 성공적으로 등록되었습니다.', + user: { + user_id: newUser.user_id, + username: newUser.username, + name: newUser.name, + access_level: newUser.access_level, + worker_id: newUser.worker_id + } + }); + + } catch (error) { + console.error('Register error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } +}); + +/** + * 사용자 목록 조회 (관리자만) + */ +router.get('/users', requireAuth, requireRole('admin', 'system'), (req, res) => { + try { + const userList = users.map(user => ({ + user_id: user.user_id, + username: user.username, + name: user.name, + access_level: user.access_level, + worker_id: user.worker_id, + created_at: user.created_at + })); + + res.json(userList); + } catch (error) { + console.error('Get users error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } +}); + +/** + * 사용자 삭제 (관리자만) + */ +router.delete('/users/:id', requireAuth, requireRole('admin', 'system'), (req, res) => { + try { + const userId = parseInt(req.params.id); + + // 자기 자신 삭제 방지 + if (userId === req.user.user_id) { + return res.status(400).json({ error: '자기 자신은 삭제할 수 없습니다.' }); + } + + const userIndex = users.findIndex(u => u.user_id === userId); + if (userIndex === -1) { + return res.status(404).json({ error: '사용자를 찾을 수 없습니다.' }); + } + + users.splice(userIndex, 1); + + res.json({ + success: true, + message: '사용자가 성공적으로 삭제되었습니다.' + }); + + } catch (error) { + console.error('Delete user error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/authRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/authRoutes.js new file mode 100644 index 0000000..5b7c563 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/authRoutes.js @@ -0,0 +1,978 @@ +/** + * @swagger + * tags: + * name: Authentication + * description: 사용자 인증 및 권한 관리 API + */ + +// routes/authRoutes.js - 비밀번호 변경 및 보안 기능 포함 완전판 +const express = require('express'); +const bcrypt = require('bcryptjs'); +const jwt = require('jsonwebtoken'); +const mysql = require('mysql2/promise'); +const { verifyToken } = require('../middlewares/authMiddleware'); +const { validatePassword, getPasswordError } = require('../utils/passwordValidator'); +const router = express.Router(); +const authController = require('../controllers/authController'); + +// DB 연결 설정 +const dbConfig = { + host: process.env.DB_HOST || 'db_hyungi_net', + user: process.env.DB_USER || 'hyungi', + password: process.env.DB_PASSWORD, + database: process.env.DB_NAME || 'hyungi' +}; + +// 로그인 시도 추적 (메모리 기반 - 실제로는 Redis 권장) +const loginAttempts = new Map(); + +// 로그인 시도 체크 미들웨어 +const checkLoginAttempts = (req, res, next) => { + const { username } = req.body; + const key = `login_${username}`; + const attempts = loginAttempts.get(key) || { count: 0, blockedUntil: null }; + + // 차단 확인 + if (attempts.blockedUntil && attempts.blockedUntil > Date.now()) { + const remainingTime = Math.ceil((attempts.blockedUntil - Date.now()) / 1000 / 60); + return res.status(429).json({ + error: `너무 많은 로그인 시도입니다. ${remainingTime}분 후에 다시 시도하세요.` + }); + } + + req.loginAttempts = attempts; + next(); +}; + +// 로그인 시도 기록 +const recordLoginAttempt = (username, success = false) => { + const key = `login_${username}`; + const attempts = loginAttempts.get(key) || { count: 0, blockedUntil: null }; + + if (success) { + loginAttempts.delete(key); + } else { + attempts.count += 1; + + // 5회 실패 시 15분 차단 + if (attempts.count >= 5) { + attempts.blockedUntil = Date.now() + (15 * 60 * 1000); + console.log(`[로그인 차단] 사용자: ${username} - 15분간 차단`); + } + + loginAttempts.set(key, attempts); + } +}; + +// 로그인 이력 기록 +const recordLoginHistory = async (connection, userId, success, ipAddress, userAgent, failureReason = null) => { + try { + await connection.execute( + `INSERT INTO login_logs (user_id, login_time, ip_address, user_agent, login_status, failure_reason) + VALUES (?, NOW(), ?, ?, ?, ?)`, + [userId, ipAddress || 'unknown', userAgent || 'unknown', success ? 'success' : 'failed', failureReason] + ); + } catch (error) { + console.error('로그인 이력 기록 실패:', error); + // 로그 테이블이 없어도 계속 진행 + } +}; + +/** + * @swagger + * /api/auth/login: + * post: + * tags: [Authentication] + * summary: 사용자 로그인 + * description: 사용자명과 비밀번호로 로그인하여 JWT 토큰을 발급받습니다. + * requestBody: + * required: true + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/LoginRequest' + * responses: + * 200: + * description: 로그인 성공 + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/LoginResponse' + * 400: + * description: 잘못된 요청 (사용자명 또는 비밀번호 누락) + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + * 401: + * description: 인증 실패 (잘못된 사용자명 또는 비밀번호) + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + * 429: + * description: 너무 많은 로그인 시도 + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + * 500: + * description: 서버 내부 오류 + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/ErrorResponse' + */ +router.post('/login', authController.login); + +/** + * 토큰 갱신 + */ +router.post('/refresh-token', async (req, res) => { + try { + const { refreshToken } = req.body; + + if (!refreshToken) { + return res.status(401).json({ error: '리프레시 토큰이 필요합니다.' }); + } + + // 리프레시 토큰 검증 + const decoded = jwt.verify(refreshToken, process.env.JWT_REFRESH_SECRET || process.env.JWT_SECRET); + + if (decoded.type !== 'refresh') { + return res.status(401).json({ error: '유효하지 않은 토큰입니다.' }); + } + + const connection = await mysql.createConnection(dbConfig); + + // 사용자 정보 조회 + const [users] = await connection.execute( + 'SELECT * FROM Users WHERE user_id = ? AND is_active = TRUE', + [decoded.user_id] + ); + + await connection.end(); + + if (users.length === 0) { + return res.status(404).json({ error: '사용자를 찾을 수 없습니다.' }); + } + + const user = users[0]; + + // 새 토큰 발급 + const newToken = jwt.sign( + { + user_id: user.user_id, + username: user.username, + access_level: user.access_level, + worker_id: user.worker_id, + name: user.name || user.username + }, + process.env.JWT_SECRET || 'your-secret-key', + { expiresIn: process.env.JWT_EXPIRES_IN || '24h' } + ); + + const newRefreshToken = jwt.sign( + { + user_id: user.user_id, + type: 'refresh' + }, + process.env.JWT_REFRESH_SECRET || process.env.JWT_SECRET, + { expiresIn: process.env.JWT_REFRESH_EXPIRES_IN || '7d' } + ); + + res.json({ + success: true, + token: newToken, + refreshToken: newRefreshToken + }); + + } catch (error) { + if (error.name === 'TokenExpiredError') { + return res.status(401).json({ error: '리프레시 토큰이 만료되었습니다.' }); + } + console.error('Token refresh error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } +}); + +/** + * 본인 비밀번호 변경 + */ +router.post('/change-password', verifyToken, async (req, res) => { + let connection; + + try { + const { currentPassword, newPassword } = req.body; + const userId = req.user.user_id; + + // 입력값 검증 + if (!currentPassword || !newPassword) { + return res.status(400).json({ + success: false, + error: '현재 비밀번호와 새 비밀번호를 입력해주세요.' + }); + } + + // 비밀번호 강도 검증 (12자 이상, 대/소문자, 숫자, 특수문자 필수) + const passwordValidation = validatePassword(newPassword); + if (!passwordValidation.valid) { + return res.status(400).json({ + success: false, + error: '비밀번호가 보안 요구사항을 충족하지 않습니다.', + details: passwordValidation.errors, + code: 'WEAK_PASSWORD' + }); + } + + connection = await mysql.createConnection(dbConfig); + + // 현재 사용자의 비밀번호 조회 + const [users] = await connection.execute( + 'SELECT password FROM Users WHERE user_id = ?', + [userId] + ); + + if (users.length === 0) { + return res.status(404).json({ + success: false, + error: '사용자를 찾을 수 없습니다.' + }); + } + + // 현재 비밀번호 확인 + const isValidPassword = await bcrypt.compare(currentPassword, users[0].password); + if (!isValidPassword) { + console.log(`[비밀번호 변경 실패] 현재 비밀번호 불일치 - 사용자: ${req.user.username}`); + return res.status(401).json({ + success: false, + error: '현재 비밀번호가 올바르지 않습니다.' + }); + } + + // 새 비밀번호와 현재 비밀번호 동일 여부 확인 + const isSamePassword = await bcrypt.compare(newPassword, users[0].password); + if (isSamePassword) { + return res.status(400).json({ + success: false, + error: '새 비밀번호는 현재 비밀번호와 달라야 합니다.' + }); + } + + // 새 비밀번호 해시화 + const hashedPassword = await bcrypt.hash(newPassword, 10); + + // 비밀번호 업데이트 + await connection.execute( + 'UPDATE Users SET password = ?, password_changed_at = NOW(), updated_at = NOW() WHERE user_id = ?', + [hashedPassword, userId] + ); + + // 비밀번호 변경 로그 기록 + try { + await connection.execute( + 'INSERT INTO password_change_logs (user_id, changed_by_user_id, changed_at, change_type) VALUES (?, ?, NOW(), ?)', + [userId, userId, 'self'] + ); + } catch (logError) { + console.log('비밀번호 변경 로그 기록 실패 (테이블 없음)'); + } + + console.log(`[비밀번호 변경 성공] 사용자: ${req.user.username}`); + + res.json({ + success: true, + message: '비밀번호가 성공적으로 변경되었습니다.' + }); + + } catch (error) { + console.error('Change password error:', error); + res.status(500).json({ + success: false, + error: '서버 오류가 발생했습니다.' + }); + } finally { + if (connection) { + await connection.end(); + } + } +}); + +/** + * 시스템 관리자의 타인 비밀번호 변경 + */ +router.post('/admin/change-password', verifyToken, async (req, res) => { + let connection; + + try { + const { userId, newPassword } = req.body; + const adminId = req.user.user_id; + + // 권한 확인 (system 레벨만 허용) + if (req.user.access_level !== 'system') { + return res.status(403).json({ + success: false, + error: '시스템 관리자만 사용할 수 있는 기능입니다.' + }); + } + + // 입력값 검증 + if (!userId || !newPassword) { + return res.status(400).json({ + success: false, + error: '사용자 ID와 새 비밀번호를 입력해주세요.' + }); + } + + // 비밀번호 강도 검증 (12자 이상, 대/소문자, 숫자, 특수문자 필수) + const passwordValidation = validatePassword(newPassword); + if (!passwordValidation.valid) { + return res.status(400).json({ + success: false, + error: '비밀번호가 보안 요구사항을 충족하지 않습니다.', + details: passwordValidation.errors, + code: 'WEAK_PASSWORD' + }); + } + + connection = await mysql.createConnection(dbConfig); + + // 대상 사용자 확인 + const [users] = await connection.execute( + 'SELECT username, name FROM Users WHERE user_id = ?', + [userId] + ); + + if (users.length === 0) { + return res.status(404).json({ + success: false, + error: '대상 사용자를 찾을 수 없습니다.' + }); + } + + const targetUser = users[0]; + + // 자기 자신의 비밀번호는 이 API로 변경 불가 + if (parseInt(userId) === adminId) { + return res.status(400).json({ + success: false, + error: '본인의 비밀번호는 일반 비밀번호 변경 기능을 사용하세요.' + }); + } + + // 새 비밀번호 해시화 + const hashedPassword = await bcrypt.hash(newPassword, 10); + + // 비밀번호 업데이트 + await connection.execute( + 'UPDATE Users SET password = ?, password_changed_at = NOW(), updated_at = NOW(), failed_login_attempts = 0, locked_until = NULL WHERE user_id = ?', + [hashedPassword, userId] + ); + + // 비밀번호 변경 로그 기록 + try { + await connection.execute( + 'INSERT INTO password_change_logs (user_id, changed_by_user_id, changed_at, change_type) VALUES (?, ?, NOW(), ?)', + [userId, adminId, 'admin'] + ); + } catch (logError) { + console.log('비밀번호 변경 로그 기록 실패 (테이블 없음)'); + } + + console.log(`[관리자 비밀번호 변경] 대상: ${targetUser.username} - 관리자: ${req.user.username}`); + + res.json({ + success: true, + message: `${targetUser.name}(${targetUser.username})님의 비밀번호가 변경되었습니다.` + }); + + } catch (error) { + console.error('Admin change password error:', error); + res.status(500).json({ + success: false, + error: '서버 오류가 발생했습니다.' + }); + } finally { + if (connection) { + await connection.end(); + } + } +}); + +/** + * 비밀번호 강도 체크 + */ +router.post('/check-password-strength', (req, res) => { + const { password } = req.body; + + if (!password) { + return res.json({ strength: 0, message: '비밀번호를 입력하세요.' }); + } + + let strength = 0; + const feedback = []; + + // 길이 체크 + if (password.length >= 8) strength += 1; + if (password.length >= 12) strength += 1; + else feedback.push('12자 이상 사용을 권장합니다.'); + + // 대문자 포함 + if (/[A-Z]/.test(password)) strength += 1; + else feedback.push('대문자를 포함하세요.'); + + // 소문자 포함 + if (/[a-z]/.test(password)) strength += 1; + else feedback.push('소문자를 포함하세요.'); + + // 숫자 포함 + if (/\d/.test(password)) strength += 1; + else feedback.push('숫자를 포함하세요.'); + + // 특수문자 포함 + if (/[!@#$%^&*(),.?":{}|<>]/.test(password)) strength += 1; + else feedback.push('특수문자를 포함하세요.'); + + const strengthLevels = ['매우 약함', '약함', '보통', '강함', '매우 강함']; + const level = Math.min(Math.floor((strength / 6) * 5), 4); + + res.json({ + strength: level, + strengthText: strengthLevels[level], + score: strength, + maxScore: 6, + feedback: feedback + }); +}); + +/** + * 현재 사용자 정보 조회 + */ +router.get('/me', verifyToken, async (req, res) => { + let connection; + + try { + const userId = req.user.user_id; + + connection = await mysql.createConnection(dbConfig); + const [rows] = await connection.execute( + 'SELECT user_id, username, name, email, access_level, worker_id, last_login_at, created_at FROM Users WHERE user_id = ?', + [userId] + ); + + if (rows.length === 0) { + return res.status(404).json({ error: '사용자를 찾을 수 없습니다.' }); + } + + const user = rows[0]; + res.json({ + user_id: user.user_id, + username: user.username, + name: user.name || user.username, + email: user.email, + access_level: user.access_level, + worker_id: user.worker_id, + last_login_at: user.last_login_at, + created_at: user.created_at + }); + + } catch (error) { + console.error('Get current user error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } finally { + if (connection) { + await connection.end(); + } + } +}); + +/** + * 사용자 등록 + */ +router.post('/register', verifyToken, async (req, res) => { + let connection; + + try { + const { username, password, name, email, access_level, worker_id } = req.body; + + // 권한 확인 (admin 이상만 사용자 등록 가능) + if (!['admin', 'system'].includes(req.user.access_level)) { + return res.status(403).json({ + success: false, + error: '사용자 등록 권한이 없습니다.' + }); + } + + if (!username || !password || !name || !access_level) { + return res.status(400).json({ + success: false, + error: '필수 항목을 모두 입력해주세요.' + }); + } + + // 비밀번호 강도 검증 + if (password.length < 6) { + return res.status(400).json({ + success: false, + error: '비밀번호는 최소 6자 이상이어야 합니다.' + }); + } + + connection = await mysql.createConnection(dbConfig); + + // 사용자명 중복 체크 + const [existing] = await connection.execute( + 'SELECT user_id FROM Users WHERE username = ?', + [username] + ); + + if (existing.length > 0) { + return res.status(409).json({ + success: false, + error: '이미 존재하는 사용자명입니다.' + }); + } + + // 이메일 중복 체크 (이메일이 제공된 경우) + if (email) { + const [existingEmail] = await connection.execute( + 'SELECT user_id FROM Users WHERE email = ?', + [email] + ); + + if (existingEmail.length > 0) { + return res.status(409).json({ + success: false, + error: '이미 사용 중인 이메일입니다.' + }); + } + } + + // 비밀번호 해시 + const hashedPassword = await bcrypt.hash(password, 10); + + // 사용자 추가 + const [result] = await connection.execute( + `INSERT INTO Users (username, password, name, email, access_level, worker_id, is_active, created_at, password_changed_at) + VALUES (?, ?, ?, ?, ?, ?, TRUE, NOW(), NOW())`, + [username, hashedPassword, name, email || null, access_level, worker_id || null] + ); + + // 비밀번호 변경 로그 기록 (초기 설정) + try { + await connection.execute( + 'INSERT INTO password_change_logs (user_id, changed_by_user_id, changed_at, change_type) VALUES (?, ?, NOW(), ?)', + [result.insertId, req.user.user_id, 'initial'] + ); + } catch (logError) { + console.log('비밀번호 변경 로그 기록 실패 (테이블 없음)'); + } + + console.log(`[사용자 등록] 새 사용자: ${username} (${access_level}) - 등록자: ${req.user.username}`); + + res.json({ + success: true, + message: '사용자가 성공적으로 등록되었습니다.', + user: { + user_id: result.insertId, + username, + name, + email: email || null, + access_level, + worker_id: worker_id || null + } + }); + + } catch (error) { + console.error('Register error:', error); + res.status(500).json({ + success: false, + error: '서버 오류가 발생했습니다.' + }); + } finally { + if (connection) { + await connection.end(); + } + } +}); + +/** + * 사용자 목록 조회 + */ +router.get('/users', verifyToken, async (req, res) => { + let connection; + + try { + connection = await mysql.createConnection(dbConfig); + + // 기본 쿼리 (role 테이블과 JOIN) + let query = ` + SELECT + u.user_id, + u.username, + u.name, + u.email, + u.role_id, + r.name as role_name, + u._access_level_old as access_level, + u.worker_id, + u.is_active, + u.last_login_at, + u.created_at + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + WHERE 1=1 + `; + + const params = []; + + // 필터링 옵션 + if (req.query.active !== undefined) { + query += ' AND u.is_active = ?'; + params.push(req.query.active === 'true'); + } + + // role_name으로 필터링 (access_level 대신) + if (req.query.access_level) { + query += ' AND (u._access_level_old = ? OR r.name = ?)'; + params.push(req.query.access_level, req.query.access_level); + } + + query += ' ORDER BY u.created_at DESC'; + + const [rows] = await connection.execute(query, params); + + const userList = rows.map(user => ({ + user_id: user.user_id, + username: user.username, + name: user.name || user.username, + email: user.email, + role_id: user.role_id, + role_name: user.role_name, + access_level: user.access_level || user.role_name?.toLowerCase(), // 하위 호환성 + worker_id: user.worker_id, + is_active: user.is_active, + last_login_at: user.last_login_at, + created_at: user.created_at + })); + + res.json(userList); + + } catch (error) { + console.error('Get users error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } finally { + if (connection) { + await connection.end(); + } + } +}); + +/** + * 사용자 정보 수정 + */ +router.put('/users/:id', verifyToken, async (req, res) => { + let connection; + + try { + const userId = parseInt(req.params.id); + const { name, email, access_level, worker_id, password, is_active } = req.body; + + // 권한 확인 + if (!['admin', 'system'].includes(req.user.access_level)) { + // 일반 사용자는 자신의 정보만 수정 가능 (이름, 이메일만) + if (userId !== req.user.user_id) { + return res.status(403).json({ + success: false, + error: '다른 사용자의 정보를 수정할 권한이 없습니다.' + }); + } + + if (access_level || worker_id || is_active !== undefined) { + return res.status(403).json({ + success: false, + error: '권한, 작업자 ID, 활성화 상태는 관리자만 수정할 수 있습니다.' + }); + } + } + + connection = await mysql.createConnection(dbConfig); + + // 사용자 존재 확인 + const [existing] = await connection.execute( + 'SELECT user_id, username FROM Users WHERE user_id = ?', + [userId] + ); + + if (existing.length === 0) { + return res.status(404).json({ + success: false, + error: '사용자를 찾을 수 없습니다.' + }); + } + + // 업데이트할 필드들 준비 + let updateFields = []; + let updateValues = []; + + if (name !== undefined) { + updateFields.push('name = ?'); + updateValues.push(name); + } + + if (email !== undefined) { + // 이메일 중복 체크 + if (email) { + const [emailCheck] = await connection.execute( + 'SELECT user_id FROM Users WHERE email = ? AND user_id != ?', + [email, userId] + ); + + if (emailCheck.length > 0) { + return res.status(409).json({ + success: false, + error: '이미 사용 중인 이메일입니다.' + }); + } + } + updateFields.push('email = ?'); + updateValues.push(email || null); + } + + if (access_level !== undefined && ['admin', 'system'].includes(req.user.access_level)) { + updateFields.push('access_level = ?'); + updateValues.push(access_level); + } + + if (worker_id !== undefined && ['admin', 'system'].includes(req.user.access_level)) { + updateFields.push('worker_id = ?'); + updateValues.push(worker_id || null); + } + + if (is_active !== undefined && ['admin', 'system'].includes(req.user.access_level)) { + updateFields.push('is_active = ?'); + updateValues.push(is_active); + } + + if (password) { + if (password.length < 6) { + return res.status(400).json({ + success: false, + error: '비밀번호는 최소 6자 이상이어야 합니다.' + }); + } + updateFields.push('password = ?'); + updateValues.push(await bcrypt.hash(password, 10)); + updateFields.push('password_changed_at = NOW()'); + + // 비밀번호 변경 로그 + try { + await connection.execute( + 'INSERT INTO password_change_logs (user_id, changed_by_user_id, changed_at, change_type) VALUES (?, ?, NOW(), ?)', + [userId, req.user.user_id, userId === req.user.user_id ? 'self' : 'admin'] + ); + } catch (logError) { + console.log('비밀번호 변경 로그 기록 실패'); + } + } + + if (updateFields.length === 0) { + return res.status(400).json({ + success: false, + error: '수정할 내용이 없습니다.' + }); + } + + updateFields.push('updated_at = NOW()'); + updateValues.push(userId); + + // 업데이트 실행 + await connection.execute( + `UPDATE Users SET ${updateFields.join(', ')} WHERE user_id = ?`, + updateValues + ); + + // 업데이트된 사용자 정보 조회 + const [updated] = await connection.execute( + 'SELECT user_id, username, name, email, access_level, worker_id, is_active FROM Users WHERE user_id = ?', + [userId] + ); + + console.log(`[사용자 수정] 대상: ${existing[0].username} - 수정자: ${req.user.username}`); + + res.json({ + success: true, + message: '사용자 정보가 성공적으로 수정되었습니다.', + user: updated[0] + }); + + } catch (error) { + console.error('Update user error:', error); + res.status(500).json({ + success: false, + error: '서버 오류가 발생했습니다.' + }); + } finally { + if (connection) { + await connection.end(); + } + } +}); + +/** + * 사용자 삭제 + */ +router.delete('/users/:id', verifyToken, async (req, res) => { + let connection; + + try { + const userId = parseInt(req.params.id); + + // 권한 확인 (system만 삭제 가능) + if (req.user.access_level !== 'system') { + return res.status(403).json({ + success: false, + error: '사용자 삭제 권한이 없습니다.' + }); + } + + // 자기 자신 삭제 방지 + if (userId === req.user.user_id) { + return res.status(400).json({ + success: false, + error: '자기 자신은 삭제할 수 없습니다.' + }); + } + + connection = await mysql.createConnection(dbConfig); + + // 사용자 존재 확인 + const [existing] = await connection.execute( + 'SELECT username FROM users WHERE user_id = ?', + [userId] + ); + + if (existing.length === 0) { + return res.status(404).json({ + success: false, + error: '사용자를 찾을 수 없습니다.' + }); + } + + // 소프트 삭제 (실제로는 비활성화) + await connection.execute( + 'UPDATE users SET is_active = FALSE, updated_at = NOW() WHERE user_id = ?', + [userId] + ); + + // 또는 하드 삭제 (실제로 삭제) + // await connection.execute('DELETE FROM users WHERE user_id = ?', [userId]); + + console.log(`[사용자 삭제] 대상: ${existing[0].username} - 삭제자: ${req.user.username}`); + + res.json({ + success: true, + message: '사용자가 성공적으로 삭제되었습니다.' + }); + + } catch (error) { + console.error('Delete user error:', error); + res.status(500).json({ + success: false, + error: '서버 오류가 발생했습니다.' + }); + } finally { + if (connection) { + await connection.end(); + } + } +}); + +/** + * 로그아웃 + */ +router.post('/logout', verifyToken, async (req, res) => { + console.log(`[로그아웃] 사용자: ${req.user.username}`); + + // 로그아웃 시간 기록 (선택사항) + let connection; + try { + connection = await mysql.createConnection(dbConfig); + await connection.execute( + 'UPDATE login_logs SET logout_time = NOW() WHERE user_id = ? AND logout_time IS NULL ORDER BY login_time DESC LIMIT 1', + [req.user.user_id] + ); + } catch (error) { + console.error('로그아웃 기록 실패:', error); + } finally { + if (connection) { + await connection.end(); + } + } + + res.json({ + success: true, + message: '성공적으로 로그아웃되었습니다.' + }); +}); + +/** + * 로그인 이력 조회 + */ +router.get('/login-history', verifyToken, async (req, res) => { + let connection; + + try { + const { limit = 50, offset = 0 } = req.query; + const userId = req.user.user_id; + + connection = await mysql.createConnection(dbConfig); + + // 본인의 로그인 이력만 조회 (관리자는 전체 조회 가능) + let query = ` + SELECT + log_id, + user_id, + login_time, + logout_time, + ip_address, + user_agent, + login_status + FROM login_logs + `; + + const params = []; + + if (!['admin', 'system'].includes(req.user.access_level)) { + query += ' WHERE user_id = ?'; + params.push(userId); + } else if (req.query.user_id) { + query += ' WHERE user_id = ?'; + params.push(req.query.user_id); + } + + query += ' ORDER BY login_time DESC LIMIT ? OFFSET ?'; + params.push(parseInt(limit), parseInt(offset)); + + const [rows] = await connection.execute(query, params); + + res.json({ + success: true, + data: rows, + pagination: { + limit: parseInt(limit), + offset: parseInt(offset) + } + }); + + } catch (error) { + console.error('Get login history error:', error); + res.status(500).json({ error: '서버 오류가 발생했습니다.' }); + } finally { + if (connection) { + await connection.end(); + } + } +}); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/dailyIssueReportRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/dailyIssueReportRoutes.js new file mode 100644 index 0000000..5ff1ec6 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/dailyIssueReportRoutes.js @@ -0,0 +1,20 @@ +// routes/dailyIssueReportRoutes.js +const express = require('express'); +const router = express.Router(); + +const { + createDailyIssueReport, + getDailyIssuesByDate, + removeDailyIssue +} = require('../controllers/dailyIssueReportController'); + +// 1. 등록 (단일 또는 다중) +router.post('/', createDailyIssueReport); + +// 2. 날짜별 조회 (?date=YYYY-MM-DD 형식) +router.get('/', getDailyIssuesByDate); + +// 3. 삭제 +router.delete('/:id', removeDailyIssue); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/dailyWorkReportRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/dailyWorkReportRoutes.js new file mode 100644 index 0000000..f805c57 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/dailyWorkReportRoutes.js @@ -0,0 +1,97 @@ +// routes/dailyWorkReportRoutes.js - 누적입력 방식 + 모든 기존 기능 포함 +const express = require('express'); +const router = express.Router(); +const dailyWorkReportController = require('../controllers/dailyWorkReportController'); +const workReportController = require('../controllers/workReportController'); + +// 📋 마스터 데이터 조회 라우트들 (모든 인증된 사용자) +router.get('/work-types', dailyWorkReportController.getWorkTypes); +router.get('/work-status-types', dailyWorkReportController.getWorkStatusTypes); +router.get('/error-types', dailyWorkReportController.getErrorTypes); + +// 📝 마스터 데이터 CRUD 라우트들 (관리자만) +// 작업 유형 CRUD +router.post('/work-types', dailyWorkReportController.createWorkType); +router.put('/work-types/:id', dailyWorkReportController.updateWorkType); +router.delete('/work-types/:id', dailyWorkReportController.deleteWorkType); + +// 작업 상태 CRUD +router.post('/work-status-types', dailyWorkReportController.createWorkStatus); +router.put('/work-status-types/:id', dailyWorkReportController.updateWorkStatus); +router.delete('/work-status-types/:id', dailyWorkReportController.deleteWorkStatus); + +// 오류 유형 CRUD +router.post('/error-types', dailyWorkReportController.createErrorType); +router.put('/error-types/:id', dailyWorkReportController.updateErrorType); +router.delete('/error-types/:id', dailyWorkReportController.deleteErrorType); + +// 🔄 누적 관련 새로운 라우트들 (누적입력 시스템 전용) +router.get('/accumulated', dailyWorkReportController.getAccumulatedReports); // ?date=2024-06-16&worker_id=1 +router.get('/contributors', dailyWorkReportController.getContributorsSummary); // ?date=2024-06-16&worker_id=1 +router.get('/my-data', dailyWorkReportController.getMyAccumulatedData); // ?date=2024-06-16&worker_id=1 + +// ✅ check-overwrite 엔드포인트 추가 (누락된 엔드포인트) +router.get('/check-overwrite', (req, res) => { + const { date, worker_id } = req.query; + + if (!date || !worker_id) { + return res.status(400).json({ + error: 'date와 worker_id가 필요합니다.', + example: 'date=2025-06-16&worker_id=1' + }); + } + + console.log(`🔍 덮어쓰기 권한 확인: 날짜=${date}, 작업자=${worker_id} (누적입력모드)`); + + // 누적입력 시스템에서는 항상 덮어쓰기 가능 (실제로는 누적만 함) + res.json({ + canOverwrite: true, + reason: 'accumulate_mode', + message: '누적입력 모드에서는 항상 추가 가능합니다.', + date, + worker_id, + timestamp: new Date().toISOString() + }); +}); + +router.delete('/my-entry/:id', dailyWorkReportController.removeMyEntry); // 개별 항목 삭제 (본인 것만) + +// 📅 월간 요약 (반드시 다른 라우트보다 먼저 정의) +router.get('/summary/monthly', dailyWorkReportController.getMonthlySummary); + +// 📊 일일 근무 요약 조회 +router.get('/summary', dailyWorkReportController.getDailySummary); + +// 🔍 검색 (페이지네이션 포함) +router.get('/search', dailyWorkReportController.searchWorkReports); + +// 📈 통계 +router.get('/stats', dailyWorkReportController.getWorkReportStats); + +// 📝 일일 작업보고서 생성 (누적 방식 - 덮어쓰기 없음!) +router.post('/', dailyWorkReportController.createDailyWorkReport); + +// 📝 TBM 기반 작업보고서 생성 +router.post('/from-tbm', dailyWorkReportController.createFromTbm); + +// 📊 일일 작업보고서 조회 (날짜별 - 경로 파라미터) +router.get('/date/:date', dailyWorkReportController.getDailyWorkReportsByDate); + +// 📊 일일 작업보고서 조회 (쿼리 파라미터 기반 - 작성자별 필터링) +router.get('/', dailyWorkReportController.getDailyWorkReports); + +// ✏️ 작업보고서 수정 +router.put('/:id', dailyWorkReportController.updateWorkReport); + +// 🗑️ 작업자의 특정 날짜 전체 삭제 +router.delete('/date/:date/worker/:worker_id', dailyWorkReportController.removeDailyWorkReportByDateAndWorker); + +// 🗑️ 특정 작업보고서 삭제 (항상 가장 마지막에 정의) +router.delete('/:id', dailyWorkReportController.removeDailyWorkReport); + +// 📋 부적합 관리 (workReportController 사용) +router.get('/:reportId/defects', workReportController.getReportDefects); +router.put('/:reportId/defects', workReportController.saveReportDefects); +router.post('/:reportId/defects', workReportController.addReportDefect); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/departmentRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/departmentRoutes.js new file mode 100644 index 0000000..fa4fd43 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/departmentRoutes.js @@ -0,0 +1,31 @@ +// routes/departmentRoutes.js +const express = require('express'); +const router = express.Router(); +const departmentController = require('../controllers/departmentController'); +const { requireAuth, requireRole } = require('../middlewares/authMiddleware'); + +// 부서 목록 조회 (인증 필요) +router.get('/', requireAuth, departmentController.getAll); + +// 부서 상세 조회 +router.get('/:id', requireAuth, departmentController.getById); + +// 부서별 작업자 조회 +router.get('/:id/workers', requireAuth, departmentController.getWorkers); + +// 부서 생성 (관리자만) +router.post('/', requireAuth, requireRole(['Admin', 'System Admin']), departmentController.create); + +// 부서 수정 (관리자만) +router.put('/:id', requireAuth, requireRole(['Admin', 'System Admin']), departmentController.update); + +// 부서 삭제 (관리자만) +router.delete('/:id', requireAuth, requireRole(['Admin', 'System Admin']), departmentController.delete); + +// 작업자 부서 이동 (관리자만) +router.post('/move-worker', requireAuth, requireRole(['Admin', 'System Admin']), departmentController.moveWorker); + +// 여러 작업자 부서 일괄 이동 (관리자만) +router.post('/move-workers', requireAuth, requireRole(['Admin', 'System Admin']), departmentController.moveWorkers); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/equipmentRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/equipmentRoutes.js new file mode 100644 index 0000000..53f16b9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/equipmentRoutes.js @@ -0,0 +1,103 @@ +// routes/equipmentRoutes.js +const express = require('express'); +const router = express.Router(); +const equipmentController = require('../controllers/equipmentController'); + +// ==================== 설비 관리 ==================== + +// CREATE 설비 +router.post('/', equipmentController.createEquipment); + +// READ ALL 설비 (쿼리 파라미터로 필터링 가능) +// ?workplace_id=1&equipment_type=CNC&status=active&search=설비명 +router.get('/', equipmentController.getAllEquipments); + +// READ ACTIVE 설비 +router.get('/active/list', equipmentController.getActiveEquipments); + +// READ 설비 유형 목록 +router.get('/types', equipmentController.getEquipmentTypes); + +// GET NEXT EQUIPMENT CODE - 다음 관리번호 자동 생성 +// ?prefix=TKP (기본값: TKP) +router.get('/next-code', equipmentController.getNextEquipmentCode); + +// READ 작업장별 설비 +router.get('/workplace/:workplaceId', equipmentController.getEquipmentsByWorkplace); + +// ==================== 임시 이동 (목록) ==================== + +// 임시 이동된 설비 목록 +router.get('/moved/list', equipmentController.getTemporarilyMoved); + +// ==================== 외부 반출 (목록) ==================== + +// 현재 외부 반출 중인 설비 목록 +router.get('/exported/list', equipmentController.getExportedEquipments); + +// 반출 로그 반입 처리 +router.post('/external-logs/:logId/return', equipmentController.returnEquipment); + +// ==================== 수리 ==================== + +// 수리 항목 목록 조회 +router.get('/repair-categories', equipmentController.getRepairCategories); + +// 새 수리 항목 추가 +router.post('/repair-categories', equipmentController.addRepairCategory); + +// ==================== 사진 관리 ==================== + +// 사진 삭제 (설비 ID 없이 photo_id만으로) +router.delete('/photos/:photoId', equipmentController.deletePhoto); + +// ==================== 개별 설비 ==================== + +// READ ONE 설비 +router.get('/:id', equipmentController.getEquipmentById); + +// UPDATE 설비 +router.put('/:id', equipmentController.updateEquipment); + +// UPDATE 설비 지도 위치 +router.patch('/:id/map-position', equipmentController.updateMapPosition); + +// DELETE 설비 +router.delete('/:id', equipmentController.deleteEquipment); + +// ==================== 설비 사진 ==================== + +// 설비 사진 추가 +router.post('/:id/photos', equipmentController.addPhoto); + +// 설비 사진 목록 +router.get('/:id/photos', equipmentController.getPhotos); + +// ==================== 설비 임시 이동 ==================== + +// 설비 임시 이동 +router.post('/:id/move', equipmentController.moveTemporarily); + +// 설비 원위치 복귀 +router.post('/:id/return', equipmentController.returnToOriginal); + +// 설비 이동 이력 +router.get('/:id/move-logs', equipmentController.getMoveLogs); + +// ==================== 설비 외부 반출 ==================== + +// 설비 외부 반출 +router.post('/:id/export', equipmentController.exportEquipment); + +// 설비 외부 반출 이력 +router.get('/:id/external-logs', equipmentController.getExternalLogs); + +// ==================== 설비 수리 ==================== + +// 수리 신청 +router.post('/:id/repair-request', equipmentController.createRepairRequest); + +// 수리 이력 조회 +router.get('/:id/repair-history', equipmentController.getRepairHistory); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/healthRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/healthRoutes.js new file mode 100644 index 0000000..25f74b2 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/healthRoutes.js @@ -0,0 +1,123 @@ +// routes/healthRoutes.js +const express = require('express'); +const router = express.Router(); + +// 헬스체크 엔드포인트 +router.get('/', (req, res) => { + res.json({ + status: 'healthy', + service: 'Technical Korea API', + timestamp: new Date().toISOString(), + uptime: process.uptime() + }); +}); + +// 상세 헬스체크 (옵션) +router.get('/detail', (req, res) => { + res.json({ + status: 'healthy', + service: 'Technical Korea API', + version: '2.1.0', + timestamp: new Date().toISOString(), + uptime: process.uptime(), + memory: process.memoryUsage(), + environment: process.env.NODE_ENV || 'development' + }); +}); + +// 임시 마이그레이션 엔드포인트 - TBM work_type_id 수정 +// 실행 후 이 코드를 삭제하세요! +router.post('/migrate-work-type-id', async (req, res) => { + try { + const { getDb } = require('../dbPool'); + const db = await getDb(); + + console.log('🔄 TBM 기반 작업보고서 work_type_id 수정 시작...'); + + // 1. 수정 대상 확인 + const [checkResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id as current_work_type_id, + ta.task_id as correct_task_id, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + INNER JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + ORDER BY dwr.report_date DESC + `); + + console.log(`📊 수정 대상: ${checkResult.length}개 레코드`); + + if (checkResult.length === 0) { + return res.json({ + success: true, + message: '수정할 데이터가 없습니다.', + data: { affected_rows: 0 } + }); + } + + // 수정 전 샘플 로깅 + console.log('수정 전 샘플:', checkResult.slice(0, 5)); + + // 2. 업데이트 실행 + const [updateResult] = await db.query(` + UPDATE daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + SET dwr.work_type_id = ta.task_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + `); + + console.log(`✅ 업데이트 완료: ${updateResult.affectedRows}개 레코드 수정됨`); + + // 3. 수정 후 확인 + const [samples] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id, + t.task_name, + wt.name as work_type_name, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + ORDER BY dwr.report_date DESC + LIMIT 10 + `); + + res.json({ + success: true, + message: `${updateResult.affectedRows}개 레코드가 수정되었습니다.`, + data: { + affected_rows: updateResult.affectedRows, + before_count: checkResult.length, + samples: samples.map(s => ({ + id: s.id, + worker: s.worker_name, + date: s.report_date, + task: s.task_name, + work_type: s.work_type_name + })) + } + }); + + } catch (error) { + console.error('마이그레이션 실패:', error); + res.status(500).json({ + success: false, + error: '마이그레이션 실패: ' + error.message + }); + } +}); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/issueTypeRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/issueTypeRoutes.js new file mode 100644 index 0000000..2fd5228 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/issueTypeRoutes.js @@ -0,0 +1,10 @@ +const express = require('express'); +const router = express.Router(); +const issueTypeController = require('../controllers/issueTypeController'); + +router.post('/', issueTypeController.createIssueType); +router.get('/', issueTypeController.getAllIssueTypes); +router.put('/:id', issueTypeController.updateIssueType); +router.delete('/:id', issueTypeController.removeIssueType); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/monthlyStatusRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/monthlyStatusRoutes.js new file mode 100644 index 0000000..56af931 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/monthlyStatusRoutes.js @@ -0,0 +1,24 @@ +// routes/monthlyStatusRoutes.js +// 월별 작업자 상태 집계 라우트 + +const express = require('express'); +const router = express.Router(); +const MonthlyStatusController = require('../controllers/monthlyStatusController'); +const { verifyToken } = require('../middlewares/authMiddleware'); + +// 모든 라우트에 인증 미들웨어 적용 (임시로 주석 처리 - 테스트용) +// router.use(verifyToken); + +// 월별 캘린더 데이터 조회 (캘린더 페이지용) +router.get('/calendar', MonthlyStatusController.getMonthlyCalendarData); + +// 특정 날짜의 작업자별 상세 상태 조회 (모달용) +router.get('/daily-details', MonthlyStatusController.getDailyWorkerDetails); + +// 월별 집계 재계산 (관리자용) +router.post('/recalculate', MonthlyStatusController.recalculateMonth); + +// 집계 테이블 상태 확인 (관리자용) +router.get('/status', MonthlyStatusController.getStatusInfo); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/notificationRecipientRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/notificationRecipientRoutes.js new file mode 100644 index 0000000..ded32a5 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/notificationRecipientRoutes.js @@ -0,0 +1,28 @@ +// routes/notificationRecipientRoutes.js +const express = require('express'); +const router = express.Router(); +const notificationRecipientController = require('../controllers/notificationRecipientController'); +const { verifyToken, requireMinLevel } = require('../middlewares/authMiddleware'); + +// 모든 라우트에 인증 필요 +router.use(verifyToken); + +// 알림 유형 목록 +router.get('/types', notificationRecipientController.getTypes); + +// 전체 수신자 목록 (유형별 그룹화) +router.get('/', notificationRecipientController.getAll); + +// 유형별 수신자 조회 +router.get('/:type', notificationRecipientController.getByType); + +// 수신자 추가 (관리자만) +router.post('/', requireMinLevel('admin'), notificationRecipientController.add); + +// 유형별 수신자 일괄 설정 (관리자만) +router.put('/:type', requireMinLevel('admin'), notificationRecipientController.setRecipients); + +// 수신자 제거 (관리자만) +router.delete('/:type/:userId', requireMinLevel('admin'), notificationRecipientController.remove); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/notificationRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/notificationRoutes.js new file mode 100644 index 0000000..fbd5fa4 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/notificationRoutes.js @@ -0,0 +1,31 @@ +// routes/notificationRoutes.js +const express = require('express'); +const router = express.Router(); +const notificationController = require('../controllers/notificationController'); +const { requireAuth, requireMinLevel } = require('../middlewares/auth'); + +// 모든 알림 라우트는 인증 필요 +router.use(requireAuth); + +// 읽지 않은 알림 조회 (본인 알림만) +router.get('/unread', notificationController.getUnread); + +// 읽지 않은 알림 개수 +router.get('/unread/count', notificationController.getUnreadCount); + +// 전체 알림 조회 (페이징) +router.get('/', notificationController.getAll); + +// 알림 생성 (시스템/관리자용) +router.post('/', requireMinLevel('support_team'), notificationController.create); + +// 모든 알림 읽음 처리 (본인 알림만) +router.post('/read-all', notificationController.markAllAsRead); + +// 특정 알림 읽음 처리 (본인 알림만) +router.post('/:id/read', notificationController.markAsRead); + +// 알림 삭제 (본인 알림만) +router.delete('/:id', notificationController.delete); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/pageAccessRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/pageAccessRoutes.js new file mode 100644 index 0000000..9c46223 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/pageAccessRoutes.js @@ -0,0 +1,237 @@ +const express = require('express'); +const router = express.Router(); +const { getDb } = require('../dbPool'); +const { requireAuth, requireAdmin } = require('../middlewares/auth'); + +/** + * 모든 페이지 목록 조회 + * GET /api/pages + */ +router.get('/pages', requireAuth, async (req, res) => { + try { + const db = await getDb(); + const [pages] = await db.query(` + SELECT id, page_key, page_name, page_path, category, description, is_admin_only, display_order + FROM pages + ORDER BY display_order, page_name + `); + + res.json({ success: true, data: pages }); + } catch (error) { + console.error('페이지 목록 조회 오류:', error); + res.status(500).json({ success: false, error: '페이지 목록을 불러오는데 실패했습니다.' }); + } +}); + +/** + * 특정 사용자의 페이지 접근 권한 조회 + * GET /api/users/:userId/page-access + */ +router.get('/users/:userId/page-access', requireAuth, async (req, res) => { + try { + const { userId } = req.params; + const db = await getDb(); + + // 사용자의 역할 확인 + const [userRows] = await db.query(` + SELECT u.user_id, u.username, u.role_id, r.name as role_name + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + WHERE u.user_id = ? + `, [userId]); + + if (userRows.length === 0) { + return res.status(404).json({ success: false, error: '사용자를 찾을 수 없습니다.' }); + } + + const user = userRows[0]; + + // Admin/System Admin인 경우 모든 페이지 접근 가능 + if (user.role_name === 'Admin' || user.role_name === 'System Admin') { + const [allPages] = await db.query(` + SELECT id, page_key, page_name, page_path, category, is_admin_only + FROM pages + ORDER BY display_order, page_name + `); + + const pageAccess = allPages.map(page => ({ + page_id: page.id, + page_key: page.page_key, + page_name: page.page_name, + page_path: page.page_path, + category: page.category, + is_admin_only: page.is_admin_only, + can_access: true, + is_default: true // Admin은 기본적으로 모든 권한 보유 + })); + + return res.json({ success: true, data: { user, pageAccess } }); + } + + // 일반 사용자의 페이지 접근 권한 조회 + const [pageAccess] = await db.query(` + SELECT + p.id as page_id, + p.page_key, + p.page_name, + p.page_path, + p.category, + p.is_admin_only, + COALESCE(upa.can_access, 0) as can_access, + upa.granted_at, + u2.username as granted_by_username + FROM pages p + LEFT JOIN user_page_access upa ON p.id = upa.page_id AND upa.user_id = ? + LEFT JOIN users u2 ON upa.granted_by = u2.user_id + WHERE p.is_admin_only = 0 + ORDER BY p.display_order, p.page_name + `, [userId]); + + res.json({ success: true, data: { user, pageAccess } }); + } catch (error) { + console.error('페이지 접근 권한 조회 오류:', error); + res.status(500).json({ success: false, error: '페이지 접근 권한을 불러오는데 실패했습니다.' }); + } +}); + +/** + * 사용자에게 페이지 접근 권한 부여/회수 + * POST /api/users/:userId/page-access + * Body: { pageIds: [1, 2, 3], canAccess: true } + */ +router.post('/users/:userId/page-access', requireAuth, async (req, res) => { + try { + const { userId } = req.params; + const { pageIds, canAccess } = req.body; + const adminUserId = req.user.user_id; // 권한을 부여하는 Admin의 user_id + + // Admin 권한 확인 + const db = await getDb(); + const [adminRows] = await db.query(` + SELECT u.role_id, r.name as role_name + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + WHERE u.user_id = ? + `, [adminUserId]); + + if (adminRows.length === 0 || (adminRows[0].role_name !== 'Admin' && adminRows[0].role_name !== 'System Admin')) { + return res.status(403).json({ success: false, error: '권한이 없습니다. Admin 계정만 사용자 권한을 관리할 수 있습니다.' }); + } + + // 사용자 존재 확인 + const [userRows] = await db.query('SELECT user_id FROM users WHERE user_id = ?', [userId]); + if (userRows.length === 0) { + return res.status(404).json({ success: false, error: '사용자를 찾을 수 없습니다.' }); + } + + // 페이지 접근 권한 업데이트 + for (const pageId of pageIds) { + // 기존 권한 확인 + const [existing] = await db.query( + 'SELECT * FROM user_page_access WHERE user_id = ? AND page_id = ?', + [userId, pageId] + ); + + if (existing.length > 0) { + // 업데이트 + await db.query( + 'UPDATE user_page_access SET can_access = ?, granted_at = NOW(), granted_by = ? WHERE user_id = ? AND page_id = ?', + [canAccess ? 1 : 0, adminUserId, userId, pageId] + ); + } else { + // 삽입 + await db.query( + 'INSERT INTO user_page_access (user_id, page_id, can_access, granted_by) VALUES (?, ?, ?, ?)', + [userId, pageId, canAccess ? 1 : 0, adminUserId] + ); + } + } + + res.json({ success: true, message: '페이지 접근 권한이 업데이트되었습니다.' }); + } catch (error) { + console.error('페이지 접근 권한 부여 오류:', error); + res.status(500).json({ success: false, error: '페이지 접근 권한을 업데이트하는데 실패했습니다.' }); + } +}); + +/** + * 특정 페이지의 접근 권한 회수 + * DELETE /api/users/:userId/page-access/:pageId + */ +router.delete('/users/:userId/page-access/:pageId', requireAuth, async (req, res) => { + try { + const { userId, pageId } = req.params; + const adminUserId = req.user.user_id; + + // Admin 권한 확인 + const db = await getDb(); + const [adminRows] = await db.query(` + SELECT u.role_id, r.name as role_name + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + WHERE u.user_id = ? + `, [adminUserId]); + + if (adminRows.length === 0 || (adminRows[0].role_name !== 'Admin' && adminRows[0].role_name !== 'System Admin')) { + return res.status(403).json({ success: false, error: '권한이 없습니다.' }); + } + + // 접근 권한 삭제 + await db.query( + 'DELETE FROM user_page_access WHERE user_id = ? AND page_id = ?', + [userId, pageId] + ); + + res.json({ success: true, message: '페이지 접근 권한이 회수되었습니다.' }); + } catch (error) { + console.error('페이지 접근 권한 회수 오류:', error); + res.status(500).json({ success: false, error: '페이지 접근 권한을 회수하는데 실패했습니다.' }); + } +}); + +/** + * 모든 사용자의 페이지 접근 권한 요약 조회 (Admin용) + * GET /api/page-access/summary + */ +router.get('/page-access/summary', requireAuth, async (req, res) => { + try { + const adminUserId = req.user.user_id; + + // Admin 권한 확인 + const db = await getDb(); + const [adminRows] = await db.query(` + SELECT u.role_id, r.name as role_name + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + WHERE u.user_id = ? + `, [adminUserId]); + + if (adminRows.length === 0 || (adminRows[0].role_name !== 'Admin' && adminRows[0].role_name !== 'System Admin')) { + return res.status(403).json({ success: false, error: '권한이 없습니다.' }); + } + + // 모든 사용자와 페이지 권한 조회 + const [summary] = await db.query(` + SELECT + u.user_id, + u.username, + u.name, + r.name as role_name, + COUNT(DISTINCT upa.page_id) as accessible_pages_count, + (SELECT COUNT(*) FROM pages WHERE is_admin_only = 0) as total_pages_count + FROM users u + LEFT JOIN roles r ON u.role_id = r.id + LEFT JOIN user_page_access upa ON u.user_id = upa.user_id AND upa.can_access = 1 + WHERE r.name NOT IN ('Admin', 'System Admin') + GROUP BY u.user_id, u.username, u.name, r.name + ORDER BY u.username + `); + + res.json({ success: true, data: summary }); + } catch (error) { + console.error('페이지 접근 권한 요약 조회 오류:', error); + res.status(500).json({ success: false, error: '페이지 접근 권한 요약을 불러오는데 실패했습니다.' }); + } +}); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/patrolRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/patrolRoutes.js new file mode 100644 index 0000000..4368f44 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/patrolRoutes.js @@ -0,0 +1,126 @@ +// patrolRoutes.js +// 일일순회점검 시스템 라우트 + +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const path = require('path'); +const patrolController = require('../controllers/patrolController'); + +// Multer 설정 - 구역 현황 사진 업로드 +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, path.join(__dirname, '../uploads')); + }, + filename: (req, file, cb) => { + const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9); + const ext = path.extname(file.originalname).toLowerCase(); + cb(null, `zone-item-${uniqueSuffix}${ext}`); + } +}); + +const upload = multer({ + storage, + limits: { fileSize: 10 * 1024 * 1024 }, // 10MB + fileFilter: (req, file, cb) => { + const allowedTypes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp']; + if (allowedTypes.includes(file.mimetype)) { + cb(null, true); + } else { + cb(new Error('이미지 파일만 업로드 가능합니다.'), false); + } + } +}); + +// ==================== 순회점검 세션 ==================== + +// 세션 목록 조회 +// GET /patrol/sessions?patrol_date=2026-02-04&patrol_time=morning&category_id=1 +router.get('/sessions', patrolController.getSessions); + +// 세션 시작/조회 (POST로 생성하거나 기존 세션 반환) +// POST /patrol/sessions { patrol_date, patrol_time, category_id } +router.post('/sessions', patrolController.getOrCreateSession); + +// 세션 상세 조회 +router.get('/sessions/:sessionId', patrolController.getSession); + +// 세션 완료 +router.patch('/sessions/:sessionId/complete', patrolController.completeSession); + +// 세션 메모 업데이트 +router.patch('/sessions/:sessionId/notes', patrolController.updateSessionNotes); + +// 세션별 작업장 점검 현황 +router.get('/sessions/:sessionId/workplace-status', patrolController.getWorkplaceCheckStatus); + +// ==================== 체크리스트 항목 ==================== + +// 체크리스트 항목 조회 (필터링 가능) +// GET /patrol/checklist?category_id=1&workplace_id=2 +router.get('/checklist', patrolController.getChecklistItems); + +// 체크리스트 항목 CRUD +router.post('/checklist', patrolController.createChecklistItem); +router.put('/checklist/:itemId', patrolController.updateChecklistItem); +router.delete('/checklist/:itemId', patrolController.deleteChecklistItem); + +// ==================== 체크 기록 ==================== + +// 세션별 체크 기록 조회 +// GET /patrol/sessions/:sessionId/records?workplace_id=1 +router.get('/sessions/:sessionId/records', patrolController.getCheckRecords); + +// 체크 기록 저장 (단건) +router.post('/sessions/:sessionId/records', patrolController.saveCheckRecord); + +// 체크 기록 일괄 저장 +router.post('/sessions/:sessionId/records/batch', patrolController.saveCheckRecords); + +// ==================== 작업장 물품 현황 ==================== + +// 작업장별 물품 조회 +router.get('/workplaces/:workplaceId/items', patrolController.getWorkplaceItems); + +// 물품 CRUD +router.post('/workplaces/:workplaceId/items', patrolController.createWorkplaceItem); +router.put('/items/:itemId', patrolController.updateWorkplaceItem); +router.delete('/items/:itemId', patrolController.deleteWorkplaceItem); + +// ==================== 물품 유형 ==================== + +// 물품 유형 목록 +router.get('/item-types', patrolController.getItemTypes); + +// ==================== 대시보드/통계 ==================== + +// 오늘 순회점검 현황 +router.get('/today-status', patrolController.getTodayStatus); + +// ==================== 작업장 상세 정보 ==================== + +// 작업장 상세 정보 조회 (시설물, 안전신고, 부적합, 출입, TBM 통합) +// GET /patrol/workplaces/:workplaceId/detail?date=2026-02-05 +router.get('/workplaces/:workplaceId/detail', patrolController.getWorkplaceDetail); + +// ==================== 구역 내 등록 물품/시설물 ==================== + +// 구역 내 등록된 물품/시설물 목록 조회 +router.get('/workplaces/:workplaceId/zone-items', patrolController.getZoneItems); + +// 구역 내 물품/시설물 등록 +router.post('/workplaces/:workplaceId/zone-items', patrolController.createZoneItem); + +// 구역 내 물품/시설물 수정 +router.put('/zone-items/:itemId', patrolController.updateZoneItem); + +// 구역 내 물품/시설물 삭제 +router.delete('/zone-items/:itemId', patrolController.deleteZoneItem); + +// 구역 현황 사진 업로드 +router.post('/zone-items/photos', upload.single('photo'), patrolController.uploadZoneItemPhoto); + +// 구역 현황 이력 조회 +router.get('/zone-items/:itemId/history', patrolController.getZoneItemHistory); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/performanceRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/performanceRoutes.js new file mode 100644 index 0000000..2e919fd --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/performanceRoutes.js @@ -0,0 +1,388 @@ +/** + * @swagger + * tags: + * name: Performance + * description: 성능 모니터링 및 최적화 API + */ + +const express = require('express'); +const router = express.Router(); +const { asyncHandler } = require('../utils/errorHandler'); +const cache = require('../utils/cache'); +const { getPerformanceStats, suggestIndexes, analyzeQuery } = require('../utils/queryOptimizer'); + +/** + * @swagger + * /api/performance/cache/stats: + * get: + * tags: [Performance] + * summary: 캐시 통계 조회 + * description: 현재 캐시 시스템의 상태와 통계를 조회합니다. + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 캐시 통계 조회 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "캐시 통계 조회 성공" + * data: + * type: object + * properties: + * type: + * type: string + * example: "memory" + * connected: + * type: boolean + * example: true + * keys: + * type: integer + * example: 42 + * hits: + * type: integer + * example: 150 + * misses: + * type: integer + * example: 25 + * hitRate: + * type: number + * example: 0.857 + * 401: + * description: 인증 필요 + * 500: + * description: 서버 오류 + */ +router.get('/cache/stats', asyncHandler(async (req, res) => { + const stats = cache.getStats(); + res.success(stats, '캐시 통계 조회 성공'); +})); + +/** + * @swagger + * /api/performance/cache/flush: + * post: + * tags: [Performance] + * summary: 캐시 초기화 + * description: 모든 캐시 데이터를 삭제합니다. (관리자 전용) + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 캐시 초기화 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "캐시가 성공적으로 초기화되었습니다." + * 401: + * description: 인증 필요 + * 403: + * description: 권한 부족 + * 500: + * description: 서버 오류 + */ +router.post('/cache/flush', asyncHandler(async (req, res) => { + // 관리자 권한 확인 + if (req.user?.access_level !== 'admin' && req.user?.access_level !== 'system') { + return res.status(403).json({ + success: false, + error: '캐시 초기화 권한이 없습니다.' + }); + } + + await cache.flush(); + res.success(null, '캐시가 성공적으로 초기화되었습니다.'); +})); + +/** + * @swagger + * /api/performance/database/stats: + * get: + * tags: [Performance] + * summary: 데이터베이스 성능 통계 + * description: 데이터베이스 연결 상태와 성능 지표를 조회합니다. + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: DB 성능 통계 조회 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "DB 성능 통계 조회 성공" + * data: + * type: object + * properties: + * connections: + * type: object + * properties: + * current: + * type: integer + * example: 5 + * max: + * type: integer + * example: 151 + * slowQueries: + * type: integer + * example: 0 + * timestamp: + * type: string + * format: date-time + * 401: + * description: 인증 필요 + * 500: + * description: 서버 오류 + */ +router.get('/database/stats', asyncHandler(async (req, res) => { + const stats = await getPerformanceStats(); + res.success(stats, 'DB 성능 통계 조회 성공'); +})); + +/** + * @swagger + * /api/performance/database/indexes/{tableName}: + * get: + * tags: [Performance] + * summary: 인덱스 최적화 제안 + * description: 특정 테이블의 인덱스 상태를 분석하고 최적화 제안을 제공합니다. + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: tableName + * required: true + * schema: + * type: string + * description: 분석할 테이블명 + * example: "workers" + * responses: + * 200: + * description: 인덱스 분석 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "인덱스 분석 완료" + * data: + * type: object + * properties: + * tableName: + * type: string + * example: "workers" + * currentIndexes: + * type: array + * items: + * type: object + * properties: + * name: + * type: string + * column: + * type: string + * unique: + * type: boolean + * suggestions: + * type: array + * items: + * type: object + * properties: + * type: + * type: string + * column: + * type: string + * reason: + * type: string + * sql: + * type: string + * 401: + * description: 인증 필요 + * 500: + * description: 서버 오류 + */ +router.get('/database/indexes/:tableName', asyncHandler(async (req, res) => { + const { tableName } = req.params; + const analysis = await suggestIndexes(tableName); + res.success(analysis, '인덱스 분석 완료'); +})); + +/** + * @swagger + * /api/performance/query/analyze: + * post: + * tags: [Performance] + * summary: 쿼리 성능 분석 + * description: SQL 쿼리의 실행 계획과 성능을 분석합니다. (관리자 전용) + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - query + * properties: + * query: + * type: string + * example: "SELECT * FROM workers WHERE department = ?" + * params: + * type: array + * items: + * type: string + * example: ["생산부"] + * responses: + * 200: + * description: 쿼리 분석 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "쿼리 분석 완료" + * data: + * type: object + * properties: + * executionTime: + * type: integer + * example: 15 + * explainResult: + * type: array + * items: + * type: object + * recommendations: + * type: array + * items: + * type: object + * properties: + * type: + * type: string + * message: + * type: string + * suggestion: + * type: string + * 401: + * description: 인증 필요 + * 403: + * description: 권한 부족 + * 500: + * description: 서버 오류 + */ +router.post('/query/analyze', asyncHandler(async (req, res) => { + // 관리자 권한 확인 + if (req.user?.access_level !== 'admin' && req.user?.access_level !== 'system') { + return res.status(403).json({ + success: false, + error: '쿼리 분석 권한이 없습니다.' + }); + } + + const { query, params = [] } = req.body; + + if (!query) { + return res.status(400).json({ + success: false, + error: '분석할 쿼리가 필요합니다.' + }); + } + + const analysis = await analyzeQuery(query, params); + res.success(analysis, '쿼리 분석 완료'); +})); + +/** + * @swagger + * /api/performance/system/info: + * get: + * tags: [Performance] + * summary: 시스템 정보 조회 + * description: 서버의 메모리, CPU, 업타임 등 시스템 정보를 조회합니다. + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 시스템 정보 조회 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "시스템 정보 조회 성공" + * data: + * type: object + * properties: + * uptime: + * type: number + * example: 3600.5 + * memory: + * type: object + * properties: + * rss: + * type: integer + * heapTotal: + * type: integer + * heapUsed: + * type: integer + * external: + * type: integer + * nodeVersion: + * type: string + * example: "v18.17.0" + * platform: + * type: string + * example: "linux" + * 401: + * description: 인증 필요 + * 500: + * description: 서버 오류 + */ +router.get('/system/info', asyncHandler(async (req, res) => { + const systemInfo = { + uptime: process.uptime(), + memory: process.memoryUsage(), + nodeVersion: process.version, + platform: process.platform, + cpuUsage: process.cpuUsage(), + timestamp: new Date().toISOString() + }; + + res.success(systemInfo, '시스템 정보 조회 성공'); +})); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/projectRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/projectRoutes.js new file mode 100644 index 0000000..4fddf5d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/projectRoutes.js @@ -0,0 +1,19 @@ +// routes/projectRoutes.js +const express = require('express'); +const router = express.Router(); +const projectController = require('../controllers/projectController'); +const { requireAuth, requireMinLevel } = require('../middlewares/auth'); + +// READ - 인증된 사용자 +router.get('/', requireAuth, projectController.getAllProjects); +router.get('/active/list', requireAuth, projectController.getActiveProjects); +router.get('/:project_id', requireAuth, projectController.getProjectById); + +// CREATE/UPDATE - support_team 이상 권한 필요 +router.post('/', requireAuth, requireMinLevel('support_team'), projectController.createProject); +router.put('/:project_id', requireAuth, requireMinLevel('support_team'), projectController.updateProject); + +// DELETE - admin 이상 권한 필요 +router.delete('/:project_id', requireAuth, requireMinLevel('admin'), projectController.removeProject); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/setupRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/setupRoutes.js new file mode 100644 index 0000000..b93200f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/setupRoutes.js @@ -0,0 +1,717 @@ +const express = require('express'); +const router = express.Router(); +const { getDb } = require('../dbPool'); + +// DB 설정 엔드포인트 (개발용 - 인증 없이 접근 가능) +// 월별 집계 테이블 설정 +router.post('/setup-monthly-status', async (req, res) => { + try { + const db = await getDb(); + + console.log('📊 월별 집계 테이블 생성 중...'); + + // 1. 월별 작업자 상태 집계 테이블 + await db.execute(` + CREATE TABLE IF NOT EXISTS monthly_worker_status ( + id INT PRIMARY KEY AUTO_INCREMENT, + year INT NOT NULL COMMENT '연도', + month INT NOT NULL COMMENT '월 (1-12)', + worker_id INT NOT NULL COMMENT '작업자 ID', + date DATE NOT NULL COMMENT '날짜', + + total_work_hours DECIMAL(5,2) DEFAULT 0.00 COMMENT '총 작업시간', + actual_work_hours DECIMAL(5,2) DEFAULT 0.00 COMMENT '실제 작업시간 (휴가 제외)', + vacation_hours DECIMAL(5,2) DEFAULT 0.00 COMMENT '휴가 시간', + + total_work_count INT DEFAULT 0 COMMENT '총 작업 건수', + regular_work_count INT DEFAULT 0 COMMENT '정규 작업 건수', + error_work_count INT DEFAULT 0 COMMENT '오류 작업 건수', + + work_status ENUM( + 'incomplete', 'partial', 'complete', 'overtime', + 'vacation-full', 'vacation-half', 'vacation-quarter', 'vacation-half-half', + 'error', 'overtime-warning' + ) NOT NULL DEFAULT 'incomplete' COMMENT '작업 상태', + + has_vacation BOOLEAN DEFAULT FALSE COMMENT '휴가 여부', + has_error BOOLEAN DEFAULT FALSE COMMENT '오류 여부', + has_issues BOOLEAN DEFAULT FALSE COMMENT '문제 여부 (미입력/부분입력)', + + last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + + UNIQUE KEY unique_worker_date (worker_id, date), + KEY idx_year_month (year, month), + KEY idx_worker_year_month (worker_id, year, month), + KEY idx_status (work_status), + KEY idx_has_issues (has_issues), + KEY idx_has_error (has_error), + + FOREIGN KEY (worker_id) REFERENCES workers(worker_id) ON DELETE CASCADE + ) COMMENT='월별 작업자 상태 집계 테이블' + `); + + // 2. 월별 집계 요약 테이블 + await db.execute(` + CREATE TABLE IF NOT EXISTS monthly_summary ( + id INT PRIMARY KEY AUTO_INCREMENT, + year INT NOT NULL COMMENT '연도', + month INT NOT NULL COMMENT '월 (1-12)', + date DATE NOT NULL COMMENT '날짜', + + total_workers INT DEFAULT 0 COMMENT '총 작업자 수', + working_workers INT DEFAULT 0 COMMENT '작업한 작업자 수', + + incomplete_workers INT DEFAULT 0 COMMENT '미입력 작업자 수', + partial_workers INT DEFAULT 0 COMMENT '부분입력 작업자 수', + complete_workers INT DEFAULT 0 COMMENT '완료 작업자 수', + overtime_workers INT DEFAULT 0 COMMENT '연장근로 작업자 수', + vacation_workers INT DEFAULT 0 COMMENT '휴가 작업자 수', + error_workers INT DEFAULT 0 COMMENT '오류 작업자 수', + + total_work_hours DECIMAL(8,2) DEFAULT 0.00 COMMENT '총 작업시간', + total_work_count INT DEFAULT 0 COMMENT '총 작업 건수', + total_error_count INT DEFAULT 0 COMMENT '총 오류 건수', + + has_issues BOOLEAN DEFAULT FALSE COMMENT '문제 있음 (미입력/부분입력)', + has_errors BOOLEAN DEFAULT FALSE COMMENT '오류 있음', + + last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + + UNIQUE KEY unique_date (date), + KEY idx_year_month (year, month), + KEY idx_has_issues (has_issues), + KEY idx_has_errors (has_errors) + ) COMMENT='월별 일자별 요약 테이블 (캘린더 최적화용)' + `); + + console.log('📊 집계 프로시저 생성 중...'); + + // 3. 집계 업데이트 프로시저 + await db.execute(`DROP PROCEDURE IF EXISTS UpdateMonthlyWorkerStatus`); + await db.execute(` + CREATE PROCEDURE UpdateMonthlyWorkerStatus( + IN p_date DATE, + IN p_worker_id INT + ) + BEGIN + DECLARE v_year INT; + DECLARE v_month INT; + DECLARE v_total_hours DECIMAL(5,2); + DECLARE v_actual_hours DECIMAL(5,2); + DECLARE v_vacation_hours DECIMAL(5,2); + DECLARE v_total_count INT; + DECLARE v_regular_count INT; + DECLARE v_error_count INT; + DECLARE v_has_vacation BOOLEAN; + DECLARE v_has_error BOOLEAN; + DECLARE v_has_issues BOOLEAN; + DECLARE v_status VARCHAR(20); + + SET v_year = YEAR(p_date); + SET v_month = MONTH(p_date); + + SELECT + COALESCE(SUM(work_hours), 0), + COALESCE(SUM(CASE WHEN project_id != 13 THEN work_hours ELSE 0 END), 0), + COALESCE(SUM(CASE WHEN project_id = 13 THEN work_hours ELSE 0 END), 0), + COUNT(*), + COUNT(CASE WHEN project_id != 13 AND work_status_id != 2 THEN 1 END), + COUNT(CASE WHEN work_status_id = 2 THEN 1 END), + MAX(CASE WHEN project_id = 13 THEN 1 ELSE 0 END), + MAX(CASE WHEN work_status_id = 2 THEN 1 ELSE 0 END) + INTO + v_total_hours, v_actual_hours, v_vacation_hours, + v_total_count, v_regular_count, v_error_count, + v_has_vacation, v_has_error + FROM daily_work_reports + WHERE report_date = p_date AND worker_id = p_worker_id; + + IF v_has_error THEN + SET v_status = 'error'; + SET v_has_issues = FALSE; + ELSEIF v_total_hours > 12 THEN + SET v_status = 'overtime-warning'; + SET v_has_issues = TRUE; + ELSEIF v_has_vacation AND v_vacation_hours > 0 THEN + CASE v_vacation_hours + WHEN 8 THEN SET v_status = 'vacation-full'; + WHEN 6 THEN SET v_status = 'vacation-half-half'; + WHEN 4 THEN SET v_status = 'vacation-half'; + WHEN 2 THEN SET v_status = 'vacation-quarter'; + ELSE SET v_status = 'vacation-full'; + END CASE; + SET v_has_issues = FALSE; + ELSEIF v_total_hours > 8 THEN + SET v_status = 'overtime'; + SET v_has_issues = FALSE; + ELSEIF v_total_hours = 8 THEN + SET v_status = 'complete'; + SET v_has_issues = FALSE; + ELSEIF v_total_hours > 0 THEN + SET v_status = 'partial'; + SET v_has_issues = TRUE; + ELSE + SET v_status = 'incomplete'; + SET v_has_issues = TRUE; + END IF; + + INSERT INTO monthly_worker_status ( + year, month, worker_id, date, + total_work_hours, actual_work_hours, vacation_hours, + total_work_count, regular_work_count, error_work_count, + work_status, has_vacation, has_error, has_issues + ) VALUES ( + v_year, v_month, p_worker_id, p_date, + v_total_hours, v_actual_hours, v_vacation_hours, + v_total_count, v_regular_count, v_error_count, + v_status, v_has_vacation, v_has_error, v_has_issues + ) ON DUPLICATE KEY UPDATE + total_work_hours = v_total_hours, + actual_work_hours = v_actual_hours, + vacation_hours = v_vacation_hours, + total_work_count = v_total_count, + regular_work_count = v_regular_count, + error_work_count = v_error_count, + work_status = v_status, + has_vacation = v_has_vacation, + has_error = v_has_error, + has_issues = v_has_issues, + last_updated = CURRENT_TIMESTAMP; + + CALL UpdateDailySummary(p_date); + END + `); + + await db.execute(`DROP PROCEDURE IF EXISTS UpdateDailySummary`); + await db.execute(` + CREATE PROCEDURE UpdateDailySummary( + IN p_date DATE + ) + BEGIN + DECLARE v_year INT; + DECLARE v_month INT; + + SET v_year = YEAR(p_date); + SET v_month = MONTH(p_date); + + INSERT INTO monthly_summary ( + year, month, date, + total_workers, working_workers, + incomplete_workers, partial_workers, complete_workers, + overtime_workers, vacation_workers, error_workers, + total_work_hours, total_work_count, total_error_count, + has_issues, has_errors + ) + SELECT + v_year, v_month, p_date, + COUNT(*) as total_workers, + COUNT(CASE WHEN work_status != 'incomplete' THEN 1 END) as working_workers, + COUNT(CASE WHEN work_status = 'incomplete' THEN 1 END) as incomplete_workers, + COUNT(CASE WHEN work_status = 'partial' THEN 1 END) as partial_workers, + COUNT(CASE WHEN work_status IN ('complete') THEN 1 END) as complete_workers, + COUNT(CASE WHEN work_status = 'overtime' THEN 1 END) as overtime_workers, + COUNT(CASE WHEN work_status LIKE 'vacation%' THEN 1 END) as vacation_workers, + COUNT(CASE WHEN work_status = 'error' THEN 1 END) as error_workers, + SUM(total_work_hours) as total_work_hours, + SUM(total_work_count) as total_work_count, + SUM(error_work_count) as total_error_count, + MAX(has_issues) as has_issues, + MAX(has_error) as has_errors + FROM monthly_worker_status + WHERE date = p_date + ON DUPLICATE KEY UPDATE + total_workers = VALUES(total_workers), + working_workers = VALUES(working_workers), + incomplete_workers = VALUES(incomplete_workers), + partial_workers = VALUES(partial_workers), + complete_workers = VALUES(complete_workers), + overtime_workers = VALUES(overtime_workers), + vacation_workers = VALUES(vacation_workers), + error_workers = VALUES(error_workers), + total_work_hours = VALUES(total_work_hours), + total_work_count = VALUES(total_work_count), + total_error_count = VALUES(total_error_count), + has_issues = VALUES(has_issues), + has_errors = VALUES(has_errors), + last_updated = CURRENT_TIMESTAMP; + END + `); + + console.log('📊 트리거 생성 중...'); + + // 4. 트리거 생성 + await db.execute(`DROP TRIGGER IF EXISTS tr_daily_work_reports_insert`); + await db.execute(` + CREATE TRIGGER tr_daily_work_reports_insert + AFTER INSERT ON daily_work_reports + FOR EACH ROW + BEGIN + CALL UpdateMonthlyWorkerStatus(NEW.report_date, NEW.worker_id); + END + `); + + await db.execute(`DROP TRIGGER IF EXISTS tr_daily_work_reports_update`); + await db.execute(` + CREATE TRIGGER tr_daily_work_reports_update + AFTER UPDATE ON daily_work_reports + FOR EACH ROW + BEGIN + CALL UpdateMonthlyWorkerStatus(OLD.report_date, OLD.worker_id); + + IF OLD.report_date != NEW.report_date OR OLD.worker_id != NEW.worker_id THEN + CALL UpdateMonthlyWorkerStatus(NEW.report_date, NEW.worker_id); + END IF; + END + `); + + await db.execute(`DROP TRIGGER IF EXISTS tr_daily_work_reports_delete`); + await db.execute(` + CREATE TRIGGER tr_daily_work_reports_delete + AFTER DELETE ON daily_work_reports + FOR EACH ROW + BEGIN + CALL UpdateMonthlyWorkerStatus(OLD.report_date, OLD.worker_id); + END + `); + + console.log('📊 기존 데이터로 집계 테이블 초기화 중...'); + + // 5. 기존 작업 데이터로 집계 테이블 초기화 + const [existingDates] = await db.execute(` + SELECT DISTINCT report_date, worker_id + FROM daily_work_reports + WHERE report_date >= '2025-01-01' + ORDER BY report_date DESC, worker_id ASC + `); + + let processedCount = 0; + const batchSize = 50; + + for (let i = 0; i < existingDates.length; i += batchSize) { + const batch = existingDates.slice(i, i + batchSize); + + for (const { report_date, worker_id } of batch) { + try { + await db.execute('CALL UpdateMonthlyWorkerStatus(?, ?)', [report_date, worker_id]); + processedCount++; + } catch (error) { + console.warn(`집계 처리 실패: ${report_date}, worker ${worker_id}:`, error.message); + } + } + + if (i % 100 === 0) { + console.log(`📊 집계 초기화 진행률: ${processedCount}/${existingDates.length}`); + } + } + + res.json({ + success: true, + message: '월별 집계 시스템이 성공적으로 설정되었습니다.', + data: { + tables_created: [ + 'monthly_worker_status', + 'monthly_summary' + ], + procedures_created: [ + 'UpdateMonthlyWorkerStatus', + 'UpdateDailySummary' + ], + triggers_created: [ + 'tr_daily_work_reports_insert', + 'tr_daily_work_reports_update', + 'tr_daily_work_reports_delete' + ], + initialized_records: processedCount, + total_dates: existingDates.length + } + }); + + } catch (error) { + console.error('❌ 월별 집계 시스템 설정 오류:', error); + res.status(500).json({ + success: false, + message: '월별 집계 시스템 설정 중 오류가 발생했습니다.', + error: error.message + }); + } +}); + +router.post('/setup-attendance-db', async (req, res) => { + try { + console.log('🚀 근태 관리 DB 설정 API 호출됨'); + + const db = await getDb(); + + // 1. 근로 유형 테이블 생성 + console.log('📋 근로 유형 테이블 생성 중...'); + await db.execute(` + CREATE TABLE IF NOT EXISTS work_attendance_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + type_code VARCHAR(20) NOT NULL UNIQUE COMMENT '근로 유형 코드', + type_name VARCHAR(50) NOT NULL COMMENT '근로 유형명', + description TEXT COMMENT '설명', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) COMMENT='근로 유형 관리 테이블' + `); + + // 2. 휴가 유형 테이블 생성 + console.log('🏖️ 휴가 유형 테이블 생성 중...'); + await db.execute(` + CREATE TABLE IF NOT EXISTS vacation_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + type_code VARCHAR(20) NOT NULL UNIQUE COMMENT '휴가 유형 코드', + type_name VARCHAR(50) NOT NULL COMMENT '휴가 유형명', + hours_deduction DECIMAL(4,2) NOT NULL COMMENT '차감 시간', + description TEXT COMMENT '설명', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) COMMENT='휴가 유형 관리 테이블' + `); + + // 3. 일일 근태 기록 테이블 생성 + console.log('📊 일일 근태 기록 테이블 생성 중...'); + await db.execute(` + CREATE TABLE IF NOT EXISTS daily_attendance_records ( + id INT PRIMARY KEY AUTO_INCREMENT, + record_date DATE NOT NULL COMMENT '기록 날짜', + worker_id INT NOT NULL COMMENT '작업자 ID', + work_attendance_type_id INT COMMENT '근로 유형 ID (정시, 연장, 부분, 휴가)', + total_work_hours DECIMAL(4,2) DEFAULT 0.00 COMMENT '총 작업 시간', + vacation_type_id INT COMMENT '휴가 유형 ID (연차, 반차 등)', + is_overtime_approved BOOLEAN DEFAULT FALSE COMMENT '연장근로 승인 여부', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + UNIQUE KEY unique_worker_date (worker_id, record_date), + FOREIGN KEY (worker_id) REFERENCES workers(worker_id) ON DELETE CASCADE, + FOREIGN KEY (work_attendance_type_id) REFERENCES work_attendance_types(id) ON DELETE SET NULL, + FOREIGN KEY (vacation_type_id) REFERENCES vacation_types(id) ON DELETE SET NULL + ) COMMENT='일일 근태 기록 테이블' + `); + + // 4. 작업자별 휴가 잔여 관리 테이블 생성 + console.log('👥 작업자별 휴가 잔여 관리 테이블 생성 중...'); + await db.execute(` + CREATE TABLE IF NOT EXISTS worker_vacation_balance ( + id INT PRIMARY KEY AUTO_INCREMENT, + worker_id INT NOT NULL UNIQUE COMMENT '작업자 ID', + annual_leave_total DECIMAL(5,2) DEFAULT 15.00 COMMENT '총 연차 일수', + annual_leave_used DECIMAL(5,2) DEFAULT 0.00 COMMENT '사용 연차 일수', + sick_leave_total DECIMAL(5,2) DEFAULT 10.00 COMMENT '총 병가 일수', + sick_leave_used DECIMAL(5,2) DEFAULT 0.00 COMMENT '사용 병가 일수', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + FOREIGN KEY (worker_id) REFERENCES workers(worker_id) ON DELETE CASCADE + ) COMMENT='작업자별 휴가 잔여 관리 테이블' + `); + + // 5. 기본 데이터 삽입 + console.log('📝 기본 데이터 삽입 중...'); + + // 근로 유형 기본 데이터 + await db.execute(` + INSERT IGNORE INTO work_attendance_types (type_code, type_name, description) VALUES + ('REGULAR', '정시근로', '8시간 정규 근무'), + ('OVERTIME', '연장근로', '8시간 초과 근무'), + ('PARTIAL', '부분근로', '8시간 미만 근무'), + ('VACATION', '휴가근로', '휴가와 함께하는 부분 근무') + `); + + // 휴가 유형 기본 데이터 + await db.execute(` + INSERT IGNORE INTO vacation_types (type_code, type_name, hours_deduction, description) VALUES + ('ANNUAL_FULL', '연차', 8.0, '하루 전체 연차'), + ('ANNUAL_HALF', '반차', 4.0, '반일 연차'), + ('ANNUAL_QUARTER', '반반차', 2.0, '1/4일 연차'), + ('SICK_FULL', '병가', 8.0, '하루 전체 병가'), + ('SICK_HALF', '반일병가', 4.0, '반일 병가') + `); + + res.json({ + success: true, + message: '근태 관리 DB 설정이 완료되었습니다.', + data: { + tables_created: [ + 'work_attendance_types', + 'vacation_types', + 'daily_attendance_records', + 'worker_vacation_balance' + ], + basic_data_inserted: true + } + }); + + } catch (error) { + console.error('❌ DB 설정 API 오류:', error); + res.status(500).json({ + success: false, + message: 'DB 설정 중 오류가 발생했습니다.', + error: error.message + }); + } +}); + +// 12시간 초과 상태 컬럼 추가 +router.post('/add-overtime-warning', async (req, res) => { + try { + const db = await getDb(); + + console.log('⚠️ 12시간 초과 상태 컬럼 추가 중...'); + + // 1. monthly_summary 테이블에 컬럼 추가 + try { + await db.execute(` + ALTER TABLE monthly_summary + ADD COLUMN overtime_warning_workers INT DEFAULT 0 COMMENT '확인필요(12시간초과) 작업자 수' AFTER error_workers + `); + console.log('✅ overtime_warning_workers 컬럼 추가 완료'); + } catch (error) { + if (error.code === 'ER_DUP_FIELDNAME') { + console.log('ℹ️ overtime_warning_workers 컬럼이 이미 존재합니다.'); + } else { + throw error; + } + } + + try { + await db.execute(` + ALTER TABLE monthly_summary + ADD COLUMN has_overtime_warning BOOLEAN DEFAULT FALSE COMMENT '확인필요 상태 있음' AFTER has_errors + `); + console.log('✅ has_overtime_warning 컬럼 추가 완료'); + } catch (error) { + if (error.code === 'ER_DUP_FIELDNAME') { + console.log('ℹ️ has_overtime_warning 컬럼이 이미 존재합니다.'); + } else { + throw error; + } + } + + // 2. UpdateDailySummary 프로시저 업데이트 + await db.execute(`DROP PROCEDURE IF EXISTS UpdateDailySummary`); + + await db.execute(` + CREATE PROCEDURE UpdateDailySummary( + IN p_date DATE + ) + BEGIN + DECLARE v_year INT; + DECLARE v_month INT; + + SET v_year = YEAR(p_date); + SET v_month = MONTH(p_date); + + INSERT INTO monthly_summary ( + year, month, date, + total_workers, working_workers, + incomplete_workers, partial_workers, complete_workers, + overtime_workers, vacation_workers, error_workers, overtime_warning_workers, + total_work_hours, total_work_count, total_error_count, + has_issues, has_errors, has_overtime_warning + ) + SELECT + v_year, v_month, p_date, + COUNT(*) as total_workers, + COUNT(CASE WHEN work_status != 'incomplete' THEN 1 END) as working_workers, + COUNT(CASE WHEN work_status = 'incomplete' THEN 1 END) as incomplete_workers, + COUNT(CASE WHEN work_status = 'partial' THEN 1 END) as partial_workers, + COUNT(CASE WHEN work_status IN ('complete', 'overtime', 'vacation-full', 'vacation-half', 'vacation-quarter', 'vacation-half-half') THEN 1 END) as complete_workers, + COUNT(CASE WHEN work_status = 'overtime' THEN 1 END) as overtime_workers, + COUNT(CASE WHEN work_status LIKE 'vacation%' THEN 1 END) as vacation_workers, + COUNT(CASE WHEN work_status = 'error' THEN 1 END) as error_workers, + COUNT(CASE WHEN work_status = 'overtime-warning' THEN 1 END) as overtime_warning_workers, + SUM(total_work_hours) as total_work_hours, + SUM(total_work_count) as total_work_count, + SUM(error_work_count) as total_error_count, + MAX(has_issues) as has_issues, + MAX(has_error) as has_errors, + MAX(CASE WHEN work_status = 'overtime-warning' THEN 1 ELSE 0 END) as has_overtime_warning + FROM monthly_worker_status + WHERE date = p_date + ON DUPLICATE KEY UPDATE + total_workers = VALUES(total_workers), + working_workers = VALUES(working_workers), + incomplete_workers = VALUES(incomplete_workers), + partial_workers = VALUES(partial_workers), + complete_workers = VALUES(complete_workers), + overtime_workers = VALUES(overtime_workers), + vacation_workers = VALUES(vacation_workers), + error_workers = VALUES(error_workers), + overtime_warning_workers = VALUES(overtime_warning_workers), + total_work_hours = VALUES(total_work_hours), + total_work_count = VALUES(total_work_count), + total_error_count = VALUES(total_error_count), + has_issues = VALUES(has_issues), + has_errors = VALUES(has_errors), + has_overtime_warning = VALUES(has_overtime_warning), + last_updated = CURRENT_TIMESTAMP; + END + `); + console.log('✅ UpdateDailySummary 프로시저 업데이트 완료'); + + res.json({ + success: true, + message: '12시간 초과 상태 컬럼 추가 완료', + columns_added: ['overtime_warning_workers', 'has_overtime_warning'], + procedure_updated: 'UpdateDailySummary' + }); + + } catch (error) { + console.error('❌ 12시간 초과 상태 설정 오류:', error); + res.status(500).json({ + success: false, + message: '12시간 초과 상태 설정 실패', + error: error.message + }); + } +}); + +// 기존 데이터를 월별 집계 테이블로 마이그레이션 +router.post('/migrate-existing-data', async (req, res) => { + try { + const db = await getDb(); + + console.log('🔄 기존 데이터 마이그레이션 시작...'); + + // 1. 기존 데이터 범위 확인 + const [dateRange] = await db.execute(` + SELECT + MIN(report_date) as min_date, + MAX(report_date) as max_date, + COUNT(*) as total_reports + FROM daily_work_reports + `); + + if (dateRange.length === 0 || !dateRange[0].min_date) { + return res.json({ + success: true, + message: '마이그레이션할 데이터가 없습니다.', + migrated_count: 0 + }); + } + + const { min_date, max_date, total_reports } = dateRange[0]; + console.log(`📊 데이터 범위: ${min_date} ~ ${max_date} (총 ${total_reports}건)`); + + // 2. 기존 monthly_worker_status, monthly_summary 데이터 삭제 + await db.execute('DELETE FROM monthly_summary'); + await db.execute('DELETE FROM monthly_worker_status'); + console.log('🗑️ 기존 집계 데이터 삭제 완료'); + + // 3. 날짜별로 작업자별 상태 재계산 + const [allDates] = await db.execute(` + SELECT DISTINCT report_date, worker_id + FROM daily_work_reports + WHERE report_date BETWEEN ? AND ? + ORDER BY report_date, worker_id + `, [min_date, max_date]); + + console.log(`🔄 ${allDates.length}개 날짜-작업자 조합 처리 중...`); + + let processedCount = 0; + for (const { report_date, worker_id } of allDates) { + try { + // UpdateMonthlyWorkerStatus 프로시저 호출 + await db.execute('CALL UpdateMonthlyWorkerStatus(?, ?)', [report_date, worker_id]); + processedCount++; + + if (processedCount % 50 === 0) { + console.log(`📈 진행률: ${processedCount}/${allDates.length} (${Math.round(processedCount/allDates.length*100)}%)`); + } + } catch (error) { + console.error(`❌ ${report_date} ${worker_id} 처리 오류:`, error.message); + } + } + + // 4. 결과 확인 + const [workerStatusCount] = await db.execute('SELECT COUNT(*) as count FROM monthly_worker_status'); + const [summaryCount] = await db.execute('SELECT COUNT(*) as count FROM monthly_summary'); + + console.log(`✅ 마이그레이션 완료:`); + console.log(` - monthly_worker_status: ${workerStatusCount[0].count}건`); + console.log(` - monthly_summary: ${summaryCount[0].count}건`); + + res.json({ + success: true, + message: '기존 데이터 마이그레이션 완료', + original_reports: total_reports, + processed_combinations: processedCount, + worker_status_records: workerStatusCount[0].count, + summary_records: summaryCount[0].count, + date_range: { + from: min_date, + to: max_date + } + }); + + } catch (error) { + console.error('❌ 데이터 마이그레이션 오류:', error); + res.status(500).json({ + success: false, + message: '데이터 마이그레이션 실패', + error: error.message + }); + } +}); + +// DB 상태 확인 +router.get('/check-data-status', async (req, res) => { + try { + const db = await getDb(); + + const [dailyReports] = await db.execute('SELECT COUNT(*) as count FROM daily_work_reports'); + const [workerStatus] = await db.execute('SELECT COUNT(*) as count FROM monthly_worker_status'); + const [monthlySummary] = await db.execute('SELECT COUNT(*) as count FROM monthly_summary'); + + // 최근 데이터 확인 + const [recentData] = await db.execute(` + SELECT + DATE(report_date) as date, + COUNT(*) as reports + FROM daily_work_reports + WHERE report_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) + GROUP BY DATE(report_date) + ORDER BY report_date DESC + LIMIT 5 + `); + + const [recentSummary] = await db.execute(` + SELECT + date, + total_workers, + has_issues, + has_errors, + has_overtime_warning + FROM monthly_summary + WHERE date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) + ORDER BY date DESC + LIMIT 5 + `); + + res.json({ + success: true, + data: { + daily_work_reports: dailyReports[0].count, + monthly_worker_status: workerStatus[0].count, + monthly_summary: monthlySummary[0].count, + recent_daily_reports: recentData, + recent_summary: recentSummary, + migration_needed: workerStatus[0].count === 0 && dailyReports[0].count > 0 + } + }); + + } catch (error) { + console.error('❌ DB 상태 확인 오류:', error); + res.status(500).json({ + success: false, + message: 'DB 상태 확인 실패', + error: error.message + }); + } +}); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/systemRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/systemRoutes.js new file mode 100644 index 0000000..ff5cd22 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/systemRoutes.js @@ -0,0 +1,378 @@ +// 시스템 관리 라우트 +const express = require('express'); +const router = express.Router(); +const systemController = require('../controllers/systemController'); +const { requireAuth, requireRole } = require('../middlewares/auth'); + +// 모든 라우트에 인증 및 시스템 권한 확인 적용 +router.use(requireAuth); +router.use(requireRole('system')); + +// ===== 시스템 상태 관련 ===== + +/** + * GET /api/system/status + * 시스템 전체 상태 확인 + */ +router.get('/status', systemController.getSystemStatus); + +/** + * GET /api/system/db-status + * 데이터베이스 상태 확인 + */ +router.get('/db-status', systemController.getDatabaseStatus); + +/** + * GET /api/system/alerts + * 시스템 알림 조회 + */ +router.get('/alerts', systemController.getSystemAlerts); + +/** + * GET /api/system/recent-activities + * 최근 시스템 활동 조회 + */ +router.get('/recent-activities', systemController.getRecentActivities); + +// ===== 사용자 관리 관련 ===== + +/** + * GET /api/system/users/stats + * 사용자 통계 조회 + */ +router.get('/users/stats', systemController.getUserStats); + +/** + * GET /api/system/users + * 모든 사용자 목록 조회 + */ +router.get('/users', systemController.getAllUsers); + +/** + * POST /api/system/users + * 새 사용자 생성 + */ +router.post('/users', systemController.createUser); + +/** + * PUT /api/system/users/:id + * 사용자 정보 수정 + */ +router.put('/users/:id', systemController.updateUser); + +/** + * DELETE /api/system/users/:id + * 사용자 삭제 + */ +router.delete('/users/:id', systemController.deleteUser); + +/** + * POST /api/system/users/:id/reset-password + * 사용자 비밀번호 재설정 + */ +router.post('/users/:id/reset-password', systemController.resetUserPassword); + +// ===== 시스템 로그 관련 ===== + +/** + * GET /api/system/logs/login + * 로그인 로그 조회 + */ +router.get('/logs/login', async (req, res) => { + try { + const { getDb } = require('../dbPool'); + const db = await getDb(); + + const { page = 1, limit = 50, status, user_id, start_date, end_date } = req.query; + const offset = (page - 1) * limit; + + let whereClause = '1=1'; + const params = []; + + if (status) { + whereClause += ' AND ll.login_status = ?'; + params.push(status); + } + + if (user_id) { + whereClause += ' AND ll.user_id = ?'; + params.push(user_id); + } + + if (start_date) { + whereClause += ' AND ll.login_time >= ?'; + params.push(start_date); + } + + if (end_date) { + whereClause += ' AND ll.login_time <= ?'; + params.push(end_date); + } + + const [logs] = await db.query(` + SELECT + ll.log_id, + ll.user_id, + u.username, + u.name, + ll.login_time, + ll.ip_address, + ll.user_agent, + ll.login_status, + ll.failure_reason + FROM login_logs ll + LEFT JOIN Users u ON ll.user_id = u.user_id + WHERE ${whereClause} + ORDER BY ll.login_time DESC + LIMIT ? OFFSET ? + `, [...params, parseInt(limit), parseInt(offset)]); + + const [totalCount] = await db.query(` + SELECT COUNT(*) as count + FROM login_logs ll + WHERE ${whereClause} + `, params); + + res.json({ + success: true, + data: { + logs, + pagination: { + page: parseInt(page), + limit: parseInt(limit), + total: totalCount[0].count, + pages: Math.ceil(totalCount[0].count / limit) + } + } + }); + + } catch (error) { + console.error('로그인 로그 조회 오류:', error); + res.status(500).json({ + success: false, + error: '로그인 로그를 조회할 수 없습니다.' + }); + } +}); + +/** + * GET /api/system/logs/password-changes + * 비밀번호 변경 로그 조회 + */ +router.get('/logs/password-changes', async (req, res) => { + try { + const { getDb } = require('../dbPool'); + const db = await getDb(); + + const { page = 1, limit = 50 } = req.query; + const offset = (page - 1) * limit; + + const [logs] = await db.query(` + SELECT + pcl.log_id, + pcl.user_id, + u.username, + u.name, + pcl.changed_by_user_id, + admin.username as changed_by_username, + admin.name as changed_by_name, + pcl.changed_at, + pcl.change_type, + pcl.ip_address + FROM password_change_logs pcl + LEFT JOIN Users u ON pcl.user_id = u.user_id + LEFT JOIN Users admin ON pcl.changed_by_user_id = admin.user_id + ORDER BY pcl.changed_at DESC + LIMIT ? OFFSET ? + `, [parseInt(limit), parseInt(offset)]); + + const [totalCount] = await db.query('SELECT COUNT(*) as count FROM password_change_logs'); + + res.json({ + success: true, + data: { + logs, + pagination: { + page: parseInt(page), + limit: parseInt(limit), + total: totalCount[0].count, + pages: Math.ceil(totalCount[0].count / limit) + } + } + }); + + } catch (error) { + console.error('비밀번호 변경 로그 조회 오류:', error); + res.status(500).json({ + success: false, + error: '비밀번호 변경 로그를 조회할 수 없습니다.' + }); + } +}); + +/** + * POST /api/system/migrations/fix-work-type-id + * TBM 기반 작업보고서의 work_type_id를 task_id로 수정 + */ +router.post('/migrations/fix-work-type-id', async (req, res) => { + try { + const { getDb } = require('../dbPool'); + const db = await getDb(); + + console.log('🔄 TBM 기반 작업보고서 work_type_id 수정 시작...'); + + // 1. 수정 대상 확인 + const [checkResult] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id as current_work_type_id, + ta.task_id as correct_task_id, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + INNER JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + ORDER BY dwr.report_date DESC + `); + + if (checkResult.length === 0) { + return res.json({ + success: true, + message: '수정할 데이터가 없습니다.', + data: { affected_rows: 0, samples: [] } + }); + } + + // 2. 업데이트 실행 + const [updateResult] = await db.query(` + UPDATE daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + SET dwr.work_type_id = ta.task_id + WHERE dwr.tbm_assignment_id IS NOT NULL + AND ta.task_id IS NOT NULL + AND dwr.work_type_id != ta.task_id + `); + + console.log(`✅ 업데이트 완료: ${updateResult.affectedRows}개 레코드 수정됨`); + + // 3. 수정된 샘플 조회 + const [samples] = await db.query(` + SELECT + dwr.id, + dwr.work_type_id, + t.task_name, + wt.name as work_type_name, + w.worker_name, + dwr.report_date + FROM daily_work_reports dwr + INNER JOIN tbm_team_assignments ta ON dwr.tbm_assignment_id = ta.assignment_id + LEFT JOIN tasks t ON dwr.work_type_id = t.task_id + LEFT JOIN work_types wt ON t.work_type_id = wt.id + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + WHERE dwr.tbm_assignment_id IS NOT NULL + ORDER BY dwr.report_date DESC + LIMIT 10 + `); + + res.json({ + success: true, + message: `${updateResult.affectedRows}개 레코드가 수정되었습니다.`, + data: { + affected_rows: updateResult.affectedRows, + before_count: checkResult.length, + samples: samples.map(s => ({ + id: s.id, + worker: s.worker_name, + date: s.report_date, + task: s.task_name, + work_type: s.work_type_name + })) + } + }); + + } catch (error) { + console.error('마이그레이션 실패:', error); + res.status(500).json({ + success: false, + error: '마이그레이션 실패: ' + error.message + }); + } +}); + +/** + * GET /api/system/logs/activity + * 활동 로그 조회 (activity_logs 테이블이 있는 경우) + */ +router.get('/logs/activity', async (req, res) => { + try { + const { getDb } = require('../dbPool'); + const db = await getDb(); + + const { page = 1, limit = 50, activity_type, user_id } = req.query; + const offset = (page - 1) * limit; + + let whereClause = '1=1'; + const params = []; + + if (activity_type) { + whereClause += ' AND al.activity_type = ?'; + params.push(activity_type); + } + + if (user_id) { + whereClause += ' AND al.user_id = ?'; + params.push(user_id); + } + + const [logs] = await db.query(` + SELECT + al.log_id, + al.user_id, + u.username, + u.name, + al.activity_type, + al.table_name, + al.record_id, + al.action, + al.ip_address, + al.user_agent, + al.created_at + FROM activity_logs al + LEFT JOIN Users u ON al.user_id = u.user_id + WHERE ${whereClause} + ORDER BY al.created_at DESC + LIMIT ? OFFSET ? + `, [...params, parseInt(limit), parseInt(offset)]); + + const [totalCount] = await db.query(` + SELECT COUNT(*) as count + FROM activity_logs al + WHERE ${whereClause} + `, params); + + res.json({ + success: true, + data: { + logs, + pagination: { + page: parseInt(page), + limit: parseInt(limit), + total: totalCount[0].count, + pages: Math.ceil(totalCount[0].count / limit) + } + } + }); + + } catch (error) { + console.error('활동 로그 조회 오류:', error); + res.status(500).json({ + success: false, + error: '활동 로그를 조회할 수 없습니다.' + }); + } +}); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/taskRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/taskRoutes.js new file mode 100644 index 0000000..ba1d242 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/taskRoutes.js @@ -0,0 +1,27 @@ +// routes/taskRoutes.js +const express = require('express'); +const router = express.Router(); +const taskController = require('../controllers/taskController'); + +// CREATE 작업 +router.post('/', taskController.createTask); + +// READ ALL 작업 +router.get('/', taskController.getAllTasks); + +// READ ACTIVE 작업 +router.get('/active/list', taskController.getActiveTasks); + +// READ BY WORK TYPE (공정별) +router.get('/by-work-type/:work_type_id', taskController.getTasksByWorkType); + +// READ ONE 작업 +router.get('/:id', taskController.getTaskById); + +// UPDATE 작업 +router.put('/:id', taskController.updateTask); + +// DELETE 작업 +router.delete('/:id', taskController.deleteTask); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/tbmRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/tbmRoutes.js new file mode 100644 index 0000000..5e22a7a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/tbmRoutes.js @@ -0,0 +1,103 @@ +// routes/tbmRoutes.js - TBM 시스템 라우트 +const express = require('express'); +const router = express.Router(); +const TbmController = require('../controllers/tbmController'); +const { requireAuth } = require('../middlewares/auth'); + +// ==================== TBM 세션 관련 ==================== + +// TBM 세션 생성 +router.post('/sessions', requireAuth, TbmController.createSession); + +// 작업보고서가 작성되지 않은 TBM 팀 배정 조회 (구체적인 경로이므로 먼저 정의) +router.get('/sessions/incomplete-reports', requireAuth, TbmController.getIncompleteWorkReports); + +// 특정 날짜의 TBM 세션 목록 조회 +router.get('/sessions/date/:date', requireAuth, TbmController.getSessionsByDate); + +// TBM 세션 상세 조회 +router.get('/sessions/:sessionId', requireAuth, TbmController.getSessionById); + +// TBM 세션 수정 +router.put('/sessions/:sessionId', requireAuth, TbmController.updateSession); + +// TBM 세션 완료 처리 +router.post('/sessions/:sessionId/complete', requireAuth, TbmController.completeSession); + +// ==================== 팀 구성 관련 ==================== + +// 팀원 추가 (단일) +router.post('/sessions/:sessionId/team', requireAuth, TbmController.addTeamMember); + +// 팀 구성 일괄 추가 +router.post('/sessions/:sessionId/team/batch', requireAuth, TbmController.addTeamMembers); + +// TBM 세션의 팀 구성 조회 +router.get('/sessions/:sessionId/team', requireAuth, TbmController.getTeamMembers); + +// 팀원 전체 삭제 (수정 시 사용) - 더 구체적인 경로이므로 먼저 정의 +router.delete('/sessions/:sessionId/team/clear', requireAuth, TbmController.clearAllTeamMembers); + +// 팀원 제거 +router.delete('/sessions/:sessionId/team/:workerId', requireAuth, TbmController.removeTeamMember); + +// ==================== 안전 체크리스트 관련 ==================== + +// 모든 안전 체크 항목 조회 +router.get('/safety-checks', requireAuth, TbmController.getAllSafetyChecks); + +// 안전 체크 항목 생성 (관리자용) +router.post('/safety-checks', requireAuth, TbmController.createSafetyCheck); + +// 안전 체크 항목 수정 (관리자용) +router.put('/safety-checks/:checkId', requireAuth, TbmController.updateSafetyCheck); + +// 안전 체크 항목 삭제 (관리자용) +router.delete('/safety-checks/:checkId', requireAuth, TbmController.deleteSafetyCheck); + +// TBM 세션의 안전 체크 기록 조회 +router.get('/sessions/:sessionId/safety', requireAuth, TbmController.getSafetyRecords); + +// 안전 체크 일괄 저장 +router.post('/sessions/:sessionId/safety', requireAuth, TbmController.saveSafetyRecords); + +// 필터링된 안전 체크리스트 조회 (기본 + 날씨 + 작업별) +router.get('/sessions/:sessionId/safety-checks/filtered', requireAuth, TbmController.getFilteredSafetyChecks); + +// ==================== 날씨 관련 ==================== + +// 현재 날씨 조회 +router.get('/weather/current', requireAuth, TbmController.getCurrentWeather); + +// 날씨 조건 목록 조회 +router.get('/weather/conditions', requireAuth, TbmController.getWeatherConditions); + +// 세션 날씨 정보 조회 +router.get('/sessions/:sessionId/weather', requireAuth, TbmController.getSessionWeather); + +// 세션 날씨 정보 저장 +router.post('/sessions/:sessionId/weather', requireAuth, TbmController.saveSessionWeather); + +// ==================== 작업 인계 관련 ==================== + +// 작업 인계 생성 +router.post('/handovers', requireAuth, TbmController.createHandover); + +// 작업 인계 확인 +router.post('/handovers/:handoverId/confirm', requireAuth, TbmController.confirmHandover); + +// 특정 날짜의 작업 인계 목록 조회 +router.get('/handovers/date/:date', requireAuth, TbmController.getHandoversByDate); + +// 나에게 온 미확인 인계 건 조회 +router.get('/handovers/pending', requireAuth, TbmController.getMyPendingHandovers); + +// ==================== 통계 및 리포트 ==================== + +// TBM 통계 조회 +router.get('/statistics/tbm', requireAuth, TbmController.getTbmStatistics); + +// 리더별 TBM 진행 현황 조회 +router.get('/statistics/leaders', requireAuth, TbmController.getLeaderStatistics); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/toolsRoute.js b/deploy/tkfb-package/api.hyungi.net/routes/toolsRoute.js new file mode 100644 index 0000000..c1bdcd5 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/toolsRoute.js @@ -0,0 +1,16 @@ +// routes/toolsRoute.js +const express = require('express'); +const router = express.Router(); +const controller = require('../controllers/toolsController'); +const { requireAuth, requireMinLevel } = require('../middlewares/auth'); + +// 읽기 작업: 인증된 사용자 +router.get('/', requireAuth, controller.getAll); +router.get('/:id', requireAuth, controller.getById); + +// 쓰기 작업: group_leader 이상 권한 필요 +router.post('/', requireAuth, requireMinLevel('group_leader'), controller.create); +router.put('/:id', requireAuth, requireMinLevel('group_leader'), controller.update); +router.delete('/:id', requireAuth, requireMinLevel('admin'), controller.delete); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/uploadBgRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/uploadBgRoutes.js new file mode 100644 index 0000000..dd807a9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/uploadBgRoutes.js @@ -0,0 +1,52 @@ +// ✅ routes/uploadBgRoutes.js (배경 이미지 전용 업로드 라우터 - 보안 강화) +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const path = require('path'); +const { requireAuth, requireMinLevel } = require('../middlewares/auth'); +const { createFileFilter, validateUploadedFile } = require('../utils/fileUploadSecurity'); + +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, path.join(__dirname, '../public/img')); + }, + filename: (req, file, cb) => { + cb(null, 'login-bg.jpeg'); // 고정된 파일명으로 덮어쓰기 + } +}); + +// 보안 강화된 파일 필터 (이미지만 허용) +const imageFileFilter = createFileFilter({ + allowedExtensions: ['.jpg', '.jpeg', '.png', '.gif', '.webp'], + allowedMimes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'] +}); + +const upload = multer({ + storage, + fileFilter: imageFileFilter, + limits: { + fileSize: 10 * 1024 * 1024, // 10MB 제한 (배경 이미지는 크기가 클 수 있음) + files: 1 + } +}); + +// 관리자 권한 필요 +router.post('/upload-bg', requireAuth, requireMinLevel('admin'), upload.single('image'), async (req, res) => { + if (!req.file) { + return res.status(400).json({ success: false, message: '파일이 없습니다.' }); + } + + // 업로드된 파일의 실제 내용 검증 (Magic number) + const validation = await validateUploadedFile(req.file.path, req.file.mimetype); + if (!validation.valid) { + return res.status(400).json({ + success: false, + message: validation.message, + code: 'INVALID_FILE_TYPE' + }); + } + + res.json({ success: true, path: '/img/login-bg.jpeg' }); +}); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/uploadRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/uploadRoutes.js new file mode 100644 index 0000000..5166ca5 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/uploadRoutes.js @@ -0,0 +1,10 @@ +// ✅ routes/uploadRoutes.js (기존 업로드 라우터) +const express = require('express'); +const router = express.Router(); +const uploadController = require('../controllers/uploadController'); + +// 기존 업로드 등록/조회 +router.post('/', uploadController.createUpload); +router.get('/', uploadController.getUploads); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/userRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/userRoutes.js new file mode 100644 index 0000000..9de69f9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/userRoutes.js @@ -0,0 +1,167 @@ +/** + * 사용자 관리 라우터 + * + * 사용자 CRUD 및 상태 관리를 위한 API 라우트 정의 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const express = require('express'); +const router = express.Router(); +const userController = require('../controllers/userController'); +const { verifyToken } = require('../middlewares/authMiddleware'); +const logger = require('../utils/logger'); + +/** + * 모든 라우트에 인증 미들웨어 적용 + */ +router.use(verifyToken); + +/** + * 관리자 권한 확인 미들웨어 + * role 또는 access_level로 관리자 확인 + */ +const adminOnly = (req, res, next) => { + const userRole = req.user?.role?.toLowerCase(); + const accessLevel = req.user?.access_level?.toLowerCase(); + + // role 기반 확인 + const isAdminByRole = userRole === 'admin' || userRole === 'system' || userRole === 'system admin'; + // access_level 기반 확인 (role이 없는 경우 대비) + const isAdminByAccessLevel = accessLevel === 'admin' || accessLevel === 'system'; + + if (req.user && (isAdminByRole || isAdminByAccessLevel)) { + next(); + } else { + logger.warn('관리자 권한 없는 접근 시도', { + userId: req.user?.user_id, + username: req.user?.username, + role: req.user?.role, + accessLevel: req.user?.access_level, + url: req.originalUrl + }); + return res.status(403).json({ + success: false, + message: '관리자 권한이 필요합니다' + }); + } +}; + +// ========== 개인 정보 조회 API (관리자 권한 불필요) ========== +// 내 정보 조회 +router.get('/me', userController.getMyInfo || ((req, res) => res.json({ success: true, data: req.user }))); + +// 내 출근 기록 조회 +router.get('/me/attendance-records', async (req, res) => { + try { + const { year, month } = req.query; + const AttendanceModel = require('../models/attendanceModel'); + const startDate = `${year}-${String(month).padStart(2, '0')}-01`; + const endDate = `${year}-${String(month).padStart(2, '0')}-31`; + const records = await AttendanceModel.getDailyRecords(startDate, endDate, req.user.worker_id); + res.json({ success: true, data: records }); + } catch (error) { + res.status(500).json({ success: false, error: error.message }); + } +}); + +// 내 연차 잔액 조회 +router.get('/me/vacation-balance', async (req, res) => { + try { + const AttendanceModel = require('../models/attendanceModel'); + const year = req.query.year || new Date().getFullYear(); + const balance = await AttendanceModel.getWorkerVacationBalance(req.user.worker_id, year); + res.json({ success: true, data: balance }); + } catch (error) { + res.status(500).json({ success: false, error: error.message }); + } +}); + +// 내 작업 보고서 조회 +router.get('/me/work-reports', async (req, res) => { + try { + const { startDate, endDate } = req.query; + const db = require('../config/database'); + const reports = await db.query( + 'SELECT * FROM daily_work_reports WHERE worker_id = ? AND report_date BETWEEN ? AND ? ORDER BY report_date DESC', + [req.user.worker_id, startDate, endDate] + ); + res.json({ success: true, data: reports }); + } catch (error) { + res.status(500).json({ success: false, error: error.message }); + } +}); + +// 내 월별 통계 +router.get('/me/monthly-stats', async (req, res) => { + try { + const { year, month } = req.query; + const { getDb } = require('../dbPool'); + const db = await getDb(); + const [stats] = await db.execute( + `SELECT + SUM(total_work_hours) as month_hours, + COUNT(DISTINCT record_date) as work_days + FROM daily_attendance_records + WHERE worker_id = ? AND YEAR(record_date) = ? AND MONTH(record_date) = ?`, + [req.user.worker_id, year, month] + ); + res.json({ success: true, data: stats[0] || { month_hours: 0, work_days: 0 } }); + } catch (error) { + res.status(500).json({ success: false, error: error.message }); + } +}); + +// ========== 자신의 페이지 권한 조회 (Admin 불필요) ========== +// 📄 사용자 페이지 접근 권한 조회 (자신 또는 Admin) +router.get('/:id/page-access', (req, res, next) => { + const requestedId = parseInt(req.params.id); + const currentUserId = req.user?.user_id; + const userRole = req.user?.role?.toLowerCase(); + + // 자신의 권한 조회이거나 Admin인 경우 허용 + if (requestedId === currentUserId || userRole === 'admin' || userRole === 'system admin') { + return userController.getUserPageAccess(req, res, next); + } + + return res.status(403).json({ + success: false, + message: '자신의 페이지 권한만 조회할 수 있습니다' + }); +}); + +// ========== 관리자 전용 API ========== +/** + * 모든 라우트에 관리자 권한 적용 + */ +router.use(adminOnly); + +// 📋 사용자 목록 조회 +router.get('/', userController.getAllUsers); + +// 👤 특정 사용자 조회 +router.get('/:id', userController.getUserById); + +// ➕ 새 사용자 생성 +router.post('/', userController.createUser); + +// ✏️ 사용자 정보 수정 +router.put('/:id', userController.updateUser); + +// 🔄 사용자 상태 변경 +router.put('/:id/status', userController.updateUserStatus); + +// 🔑 사용자 비밀번호 초기화 (000000) +router.post('/:id/reset-password', userController.resetUserPassword); + +// 🗑️ 사용자 비활성화 (Soft Delete) +router.delete('/:id', userController.deleteUser); + +// 💀 사용자 영구 삭제 (Hard Delete) +router.delete('/:id/permanent', userController.permanentDeleteUser); + +// 🔐 사용자 페이지 접근 권한 업데이트 (Admin만) +router.put('/:id/page-access', userController.updateUserPageAccess); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/vacationBalanceRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/vacationBalanceRoutes.js new file mode 100644 index 0000000..e44872f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/vacationBalanceRoutes.js @@ -0,0 +1,34 @@ +/** + * vacationBalanceRoutes.js + * 휴가 잔액 관련 라우트 + */ + +const express = require('express'); +const router = express.Router(); +const vacationBalanceController = require('../controllers/vacationBalanceController'); + +// 모든 작업자의 휴가 잔액 조회 (특정 연도) +router.get('/year/:year', vacationBalanceController.getAllByYear); + +// 특정 작업자의 휴가 잔액 조회 (특정 연도) +router.get('/worker/:workerId/year/:year', vacationBalanceController.getByWorkerAndYear); + +// 작업자의 사용 가능한 휴가 일수 조회 +router.get('/worker/:workerId/year/:year/available', vacationBalanceController.getAvailableDays); + +// 근속년수 기반 연차 자동 계산 및 생성 (관리자만) +router.post('/auto-calculate', vacationBalanceController.autoCalculateAndCreate); + +// 휴가 잔액 생성 (관리자만) +router.post('/', vacationBalanceController.createBalance); + +// 휴가 잔액 일괄 저장 (upsert) +router.post('/bulk-upsert', vacationBalanceController.bulkUpsert); + +// 휴가 잔액 수정 (관리자만) +router.put('/:id', vacationBalanceController.updateBalance); + +// 휴가 잔액 삭제 (관리자만) +router.delete('/:id', vacationBalanceController.deleteBalance); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/vacationRequestRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/vacationRequestRoutes.js new file mode 100644 index 0000000..7ca3212 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/vacationRequestRoutes.js @@ -0,0 +1,34 @@ +/** + * vacationRequestRoutes.js + * 휴가 신청 관련 라우트 + */ + +const express = require('express'); +const router = express.Router(); +const vacationRequestController = require('../controllers/vacationRequestController'); + +// 휴가 신청 생성 +router.post('/', vacationRequestController.createRequest); + +// 휴가 신청 목록 조회 +router.get('/', vacationRequestController.getAllRequests); + +// 대기 중인 휴가 신청 목록 (관리자용) +router.get('/pending', vacationRequestController.getPendingRequests); + +// 특정 휴가 신청 조회 +router.get('/:id', vacationRequestController.getRequestById); + +// 휴가 신청 수정 +router.put('/:id', vacationRequestController.updateRequest); + +// 휴가 신청 삭제 +router.delete('/:id', vacationRequestController.deleteRequest); + +// 휴가 신청 승인 +router.patch('/:id/approve', vacationRequestController.approveRequest); + +// 휴가 신청 거부 +router.patch('/:id/reject', vacationRequestController.rejectRequest); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/vacationTypeRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/vacationTypeRoutes.js new file mode 100644 index 0000000..b39673a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/vacationTypeRoutes.js @@ -0,0 +1,31 @@ +/** + * vacationTypeRoutes.js + * 휴가 유형 관련 라우트 + */ + +const express = require('express'); +const router = express.Router(); +const vacationTypeController = require('../controllers/vacationTypeController'); + +// 모든 활성 휴가 유형 조회 +router.get('/', vacationTypeController.getAllTypes); + +// 시스템 기본 휴가 유형 조회 +router.get('/system', vacationTypeController.getSystemTypes); + +// 특별 휴가 유형 조회 +router.get('/special', vacationTypeController.getSpecialTypes); + +// 휴가 유형 우선순위 일괄 업데이트 (관리자만) +router.put('/priorities', vacationTypeController.updatePriorities); + +// 특별 휴가 유형 생성 (관리자만) +router.post('/', vacationTypeController.createType); + +// 휴가 유형 수정 (관리자만) +router.put('/:id', vacationTypeController.updateType); + +// 특별 휴가 유형 삭제 (관리자만, 시스템 기본 휴가는 삭제 불가) +router.delete('/:id', vacationTypeController.deleteType); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/visitRequestRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/visitRequestRoutes.js new file mode 100644 index 0000000..5d48d80 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/visitRequestRoutes.js @@ -0,0 +1,66 @@ +const express = require('express'); +const router = express.Router(); +const visitRequestController = require('../controllers/visitRequestController'); +const { verifyToken } = require('../middlewares/authMiddleware'); + +// 모든 라우트에 인증 미들웨어 적용 +router.use(verifyToken); + +// ==================== 출입 신청 관리 ==================== + +// 출입 신청 생성 +router.post('/requests', visitRequestController.createVisitRequest); + +// 출입 신청 목록 조회 (필터: status, visit_date, start_date, end_date, requester_id, category_id) +router.get('/requests', visitRequestController.getAllVisitRequests); + +// 출입 신청 상세 조회 +router.get('/requests/:id', visitRequestController.getVisitRequestById); + +// 출입 신청 수정 +router.put('/requests/:id', visitRequestController.updateVisitRequest); + +// 출입 신청 삭제 +router.delete('/requests/:id', visitRequestController.deleteVisitRequest); + +// 출입 신청 승인 +router.put('/requests/:id/approve', visitRequestController.approveVisitRequest); + +// 출입 신청 반려 +router.put('/requests/:id/reject', visitRequestController.rejectVisitRequest); + +// ==================== 방문 목적 관리 ==================== + +// 모든 방문 목적 조회 +router.get('/purposes', visitRequestController.getAllVisitPurposes); + +// 활성 방문 목적만 조회 +router.get('/purposes/active', visitRequestController.getActiveVisitPurposes); + +// 방문 목적 추가 +router.post('/purposes', visitRequestController.createVisitPurpose); + +// 방문 목적 수정 +router.put('/purposes/:id', visitRequestController.updateVisitPurpose); + +// 방문 목적 삭제 +router.delete('/purposes/:id', visitRequestController.deleteVisitPurpose); + +// ==================== 안전교육 기록 관리 ==================== + +// 안전교육 기록 생성 +router.post('/training', visitRequestController.createTrainingRecord); + +// 안전교육 기록 목록 조회 (필터: training_date, start_date, end_date, trainer_id) +router.get('/training', visitRequestController.getTrainingRecords); + +// 특정 출입 신청의 안전교육 기록 조회 +router.get('/training/request/:requestId', visitRequestController.getTrainingRecordByRequestId); + +// 안전교육 기록 수정 +router.put('/training/:id', visitRequestController.updateTrainingRecord); + +// 안전교육 완료 (서명 포함) +router.post('/training/:id/complete', visitRequestController.completeTraining); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/workAnalysis.js b/deploy/tkfb-package/api.hyungi.net/routes/workAnalysis.js new file mode 100644 index 0000000..3d6c901 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/workAnalysis.js @@ -0,0 +1,74 @@ +// routes/workAnalysis.js + +const express = require('express'); +const router = express.Router(); +const workAnalysisController = require('../controllers/workAnalysisController'); + +// 🔒 분석 기능은 admin 또는 system 권한만 접근 가능 +const requireAnalysisAccess = (req, res, next) => { + if (!req.user) { + return res.status(401).json({ error: '인증이 필요합니다.' }); + } + + const allowedLevels = ['admin', 'system']; + if (!allowedLevels.includes(req.user.access_level)) { + return res.status(403).json({ + error: '분석 기능 접근 권한이 없습니다. 관리자 권한이 필요합니다.', + required: 'admin 또는 system', + current: req.user.access_level + }); + } + + console.log(`🔓 분석 기능 접근 허용: ${req.user.username} (${req.user.access_level})`); + next(); +}; + +// 임시로 권한 체크 건너뛰기 (테스트용) +const skipAuth = (req, res, next) => { + console.log('⚠️ 임시로 권한 체크 건너뛰기'); + next(); +}; + +// 기본 통계 조회 - 임시로 권한 체크 비활성화 +router.get('/stats', skipAuth, workAnalysisController.getStats); + +// 일별 작업시간 추이 - 임시로 권한 체크 비활성화 +router.get('/daily-trend', skipAuth, workAnalysisController.getDailyTrend); + +// 작업자별 통계 - 임시로 권한 체크 비활성화 +router.get('/worker-stats', skipAuth, workAnalysisController.getWorkerStats); + +// 프로젝트별 통계 - 임시로 권한 체크 비활성화 +router.get('/project-stats', skipAuth, workAnalysisController.getProjectStats); + +// 작업유형별 통계 - 임시로 권한 체크 비활성화 +router.get('/worktype-stats', skipAuth, workAnalysisController.getWorkTypeStats); + +// 최근 작업 현황 - 임시로 권한 체크 비활성화 +router.get('/recent-work', skipAuth, workAnalysisController.getRecentWork); + +// 요일별 패턴 분석 +router.get('/weekday-pattern', requireAnalysisAccess, workAnalysisController.getWeekdayPattern); + +// 에러 분석 +router.get('/error-analysis', requireAnalysisAccess, workAnalysisController.getErrorAnalysis); + +// 월별 비교 분석 +router.get('/monthly-comparison', requireAnalysisAccess, workAnalysisController.getMonthlyComparison); + +// 작업자별 전문분야 분석 +router.get('/worker-specialization', requireAnalysisAccess, workAnalysisController.getWorkerSpecialization); + +// 대시보드용 종합 데이터 (한 번에 여러 데이터 조회) +router.get('/dashboard', requireAnalysisAccess, workAnalysisController.getDashboardData); + +// 헬스체크 - 인증 없이 접근 가능 +router.get('/health', (req, res) => { + res.status(200).json({ + success: true, + message: 'Work Analysis API is running', + timestamp: new Date().toISOString() + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/workAnalysisRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/workAnalysisRoutes.js new file mode 100644 index 0000000..bd3e8ed --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/workAnalysisRoutes.js @@ -0,0 +1,65 @@ +// routes/workAnalysisRoutes.js +const express = require('express'); +const router = express.Router(); +const workAnalysisController = require('../controllers/workAnalysisController'); + +// 🏠 대시보드용 종합 데이터 (가장 많이 사용될 것 같아서 맨 위에) +router.get('/dashboard', workAnalysisController.getDashboardData); + +// 📊 기본 통계 +router.get('/stats', workAnalysisController.getStats); + +// 📈 일별 작업시간 추이 +router.get('/daily-trend', workAnalysisController.getDailyTrend); + +// 👥 작업자별 통계 +router.get('/worker-stats', workAnalysisController.getWorkerStats); + +// 📋 프로젝트별 통계 +router.get('/project-stats', workAnalysisController.getProjectStats); + +// 🔧 작업유형별 통계 +router.get('/work-type-stats', workAnalysisController.getWorkTypeStats); + +// 🕐 최근 작업 현황 +router.get('/recent-work', workAnalysisController.getRecentWork); + +// 📅 요일별 패턴 분석 +router.get('/weekday-pattern', workAnalysisController.getWeekdayPattern); + +// ❌ 에러 분석 +router.get('/error-analysis', workAnalysisController.getErrorAnalysis); + +// 📊 월별 비교 분석 +router.get('/monthly-comparison', workAnalysisController.getMonthlyComparison); + +// 🎯 작업자별 전문분야 분석 +router.get('/worker-specialization', workAnalysisController.getWorkerSpecialization); + +// 🏗️ 프로젝트별-작업별 시간 분석 (총시간, 정규시간, 에러시간) +router.get('/project-worktype-analysis', workAnalysisController.getProjectWorkTypeAnalysis); + +// 📋 헬스체크 및 API 정보 +router.get('/health', (req, res) => { + res.json({ + success: true, + message: '작업 분석 API가 정상 작동 중입니다.', + endpoints: [ + 'GET /work-analysis/dashboard - 대시보드 종합 데이터', + 'GET /work-analysis/stats - 기본 통계', + 'GET /work-analysis/daily-trend - 일별 추이', + 'GET /work-analysis/worker-stats - 작업자별 통계', + 'GET /work-analysis/project-stats - 프로젝트별 통계', + 'GET /work-analysis/work-type-stats - 작업유형별 통계', + 'GET /work-analysis/recent-work - 최근 작업 현황', + 'GET /work-analysis/weekday-pattern - 요일별 패턴', + 'GET /work-analysis/error-analysis - 에러 분석', + 'GET /work-analysis/monthly-comparison - 월별 비교', + 'GET /work-analysis/worker-specialization - 작업자 전문분야', + 'GET /work-analysis/project-worktype-analysis - 프로젝트별-작업별 시간 분석' + ], + timestamp: new Date().toISOString() + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/workIssueRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/workIssueRoutes.js new file mode 100644 index 0000000..31f5fda --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/workIssueRoutes.js @@ -0,0 +1,92 @@ +/** + * 작업 중 문제 신고 라우터 + */ + +const express = require('express'); +const router = express.Router(); +const workIssueController = require('../controllers/workIssueController'); +const { requireMinLevel } = require('../middlewares/auth'); + +// ==================== 카테고리 관리 ==================== + +// 모든 카테고리 조회 +router.get('/categories', workIssueController.getAllCategories); + +// 타입별 카테고리 조회 (nonconformity/safety) +router.get('/categories/type/:type', workIssueController.getCategoriesByType); + +// 카테고리 생성 (admin 이상) +router.post('/categories', requireMinLevel('admin'), workIssueController.createCategory); + +// 카테고리 수정 (admin 이상) +router.put('/categories/:id', requireMinLevel('admin'), workIssueController.updateCategory); + +// 카테고리 삭제 (admin 이상) +router.delete('/categories/:id', requireMinLevel('admin'), workIssueController.deleteCategory); + +// ==================== 사전 정의 항목 관리 ==================== + +// 모든 항목 조회 +router.get('/items', workIssueController.getAllItems); + +// 카테고리별 항목 조회 +router.get('/items/category/:categoryId', workIssueController.getItemsByCategory); + +// 항목 생성 (admin 이상) +router.post('/items', requireMinLevel('admin'), workIssueController.createItem); + +// 항목 수정 (admin 이상) +router.put('/items/:id', requireMinLevel('admin'), workIssueController.updateItem); + +// 항목 삭제 (admin 이상) +router.delete('/items/:id', requireMinLevel('admin'), workIssueController.deleteItem); + +// ==================== 통계 ==================== + +// 통계 요약 (support_team 이상) +router.get('/stats/summary', requireMinLevel('support_team'), workIssueController.getStatsSummary); + +// 카테고리별 통계 (support_team 이상) +router.get('/stats/by-category', requireMinLevel('support_team'), workIssueController.getStatsByCategory); + +// 작업장별 통계 (support_team 이상) +router.get('/stats/by-workplace', requireMinLevel('support_team'), workIssueController.getStatsByWorkplace); + +// ==================== 문제 신고 관리 ==================== + +// 신고 목록 조회 +router.get('/', workIssueController.getAllReports); + +// 신고 생성 +router.post('/', workIssueController.createReport); + +// 신고 상세 조회 +router.get('/:id', workIssueController.getReportById); + +// 신고 수정 +router.put('/:id', workIssueController.updateReport); + +// 신고 삭제 +router.delete('/:id', workIssueController.deleteReport); + +// ==================== 상태 관리 ==================== + +// 신고 접수 (support_team 이상) +router.put('/:id/receive', requireMinLevel('support_team'), workIssueController.receiveReport); + +// 담당자 배정 (support_team 이상) +router.put('/:id/assign', requireMinLevel('support_team'), workIssueController.assignReport); + +// 처리 시작 +router.put('/:id/start', workIssueController.startProcessing); + +// 처리 완료 +router.put('/:id/complete', workIssueController.completeReport); + +// 신고 종료 (admin 이상) +router.put('/:id/close', requireMinLevel('admin'), workIssueController.closeReport); + +// 상태 변경 이력 조회 +router.get('/:id/logs', workIssueController.getStatusLogs); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/workReportAnalysisRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/workReportAnalysisRoutes.js new file mode 100644 index 0000000..6e53a64 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/workReportAnalysisRoutes.js @@ -0,0 +1,23 @@ +// routes/workReportAnalysisRoutes.js - 데일리 워크 레포트 분석 라우트 +const express = require('express'); +const router = express.Router(); +const workReportAnalysisController = require('../controllers/workReportAnalysisController'); +const { requireAuth, requireRole } = require('../middlewares/auth'); + +// 🔒 모든 분석 라우트에 인증 + Admin 권한 필요 +router.use(requireAuth); +router.use(requireRole('admin', 'system')); + +// 📋 분석용 필터 데이터 조회 (프로젝트, 작업자, 작업유형 목록) +router.get('/filters', workReportAnalysisController.getAnalysisFilters); + +// 📊 기간별 종합 분석 +router.get('/period', workReportAnalysisController.getAnalyticsByPeriod); + +// 📈 프로젝트별 상세 분석 +router.get('/project', workReportAnalysisController.getProjectAnalysis); + +// 👤 작업자별 상세 분석 +router.get('/worker', workReportAnalysisController.getWorkerAnalysis); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/routes/workReportRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/workReportRoutes.js new file mode 100644 index 0000000..a320ae9 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/workReportRoutes.js @@ -0,0 +1,39 @@ +const express = require('express'); +const router = express.Router(); +const workReportController = require('../controllers/workReportController'); + +// CREATE +router.post('/', workReportController.createWorkReport); + +// READ BY DATE +router.get('/date/:date', workReportController.getWorkReportsByDate); + +// ✅ summary 라우트는 반드시 아래보다 위에 둬야 작동합니다 +router.get('/summary', workReportController.getSummary); + +// READ IN RANGE +router.get('/', workReportController.getWorkReportsInRange); + +// READ ONE (항상 가장 마지막) +router.get('/:id', workReportController.getWorkReportById); + +// UPDATE +router.put('/:id', workReportController.updateWorkReport); + +// DELETE +router.delete('/:id', workReportController.removeWorkReport); + +// ========== 부적합 원인 관리 ========== +// 작업 보고서의 부적합 원인 목록 조회 +router.get('/:reportId/defects', workReportController.getReportDefects); + +// 부적합 원인 저장 (전체 교체) +router.put('/:reportId/defects', workReportController.saveReportDefects); + +// 부적합 원인 추가 (단일) +router.post('/:reportId/defects', workReportController.addReportDefect); + +// 부적합 원인 삭제 +router.delete('/defects/:defectId', workReportController.removeReportDefect); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/workerRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/workerRoutes.js new file mode 100644 index 0000000..15d5f0e --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/workerRoutes.js @@ -0,0 +1,228 @@ +/** + * @swagger + * tags: + * name: Workers + * description: 작업자 관리 API + */ + +const express = require('express'); +const router = express.Router(); +const workerController = require('../controllers/workerController'); + +/** + * @swagger + * /api/workers: + * post: + * tags: [Workers] + * summary: 작업자 생성 + * description: 새로운 작업자를 생성합니다. + * security: + * - bearerAuth: [] + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * required: + * - worker_name + * properties: + * worker_name: + * type: string + * example: "김철수" + * position: + * type: string + * example: "용접공" + * department: + * type: string + * example: "생산부" + * phone: + * type: string + * example: "010-1234-5678" + * email: + * type: string + * format: email + * example: "worker@technicalkorea.com" + * responses: + * 201: + * description: 작업자 생성 성공 + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/SuccessResponse' + * 400: + * description: 잘못된 요청 + * 401: + * description: 인증 필요 + * 500: + * description: 서버 오류 + * get: + * tags: [Workers] + * summary: 전체 작업자 조회 + * description: 모든 작업자 목록을 조회합니다. + * security: + * - bearerAuth: [] + * responses: + * 200: + * description: 작업자 목록 조회 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "작업자 목록 조회 성공" + * data: + * type: array + * items: + * $ref: '#/components/schemas/Worker' + * meta: + * type: object + * properties: + * count: + * type: integer + * example: 10 + * 401: + * description: 인증 필요 + * 500: + * description: 서버 오류 + */ +router.post('/', workerController.createWorker); +router.get('/', workerController.getAllWorkers); + +/** + * @swagger + * /api/workers/{worker_id}: + * get: + * tags: [Workers] + * summary: 특정 작업자 조회 + * description: ID로 특정 작업자 정보를 조회합니다. + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: worker_id + * required: true + * schema: + * type: integer + * description: 작업자 ID + * responses: + * 200: + * description: 작업자 조회 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "작업자 조회 성공" + * data: + * $ref: '#/components/schemas/Worker' + * 400: + * description: 잘못된 작업자 ID + * 401: + * description: 인증 필요 + * 404: + * description: 작업자를 찾을 수 없음 + * 500: + * description: 서버 오류 + * put: + * tags: [Workers] + * summary: 작업자 정보 수정 + * description: 작업자 정보를 수정합니다. + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: worker_id + * required: true + * schema: + * type: integer + * description: 작업자 ID + * requestBody: + * required: true + * content: + * application/json: + * schema: + * type: object + * properties: + * worker_name: + * type: string + * example: "김철수" + * position: + * type: string + * example: "용접공" + * department: + * type: string + * example: "생산부" + * phone: + * type: string + * example: "010-1234-5678" + * email: + * type: string + * format: email + * example: "worker@technicalkorea.com" + * responses: + * 200: + * description: 작업자 수정 성공 + * content: + * application/json: + * schema: + * $ref: '#/components/schemas/SuccessResponse' + * 400: + * description: 잘못된 요청 + * 401: + * description: 인증 필요 + * 404: + * description: 작업자를 찾을 수 없음 + * 500: + * description: 서버 오류 + * delete: + * tags: [Workers] + * summary: 작업자 삭제 + * description: 작업자를 삭제합니다. + * security: + * - bearerAuth: [] + * parameters: + * - in: path + * name: worker_id + * required: true + * schema: + * type: integer + * description: 작업자 ID + * responses: + * 200: + * description: 작업자 삭제 성공 + * content: + * application/json: + * schema: + * type: object + * properties: + * success: + * type: boolean + * example: true + * message: + * type: string + * example: "작업자가 성공적으로 삭제되었습니다." + * 400: + * description: 잘못된 작업자 ID + * 401: + * description: 인증 필요 + * 404: + * description: 작업자를 찾을 수 없음 + * 500: + * description: 서버 오류 + */ +router.get('/:worker_id', workerController.getWorkerById); +router.put('/:worker_id', workerController.updateWorker); +router.delete('/:worker_id', workerController.removeWorker); + +module.exports = router; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/routes/workplaceRoutes.js b/deploy/tkfb-package/api.hyungi.net/routes/workplaceRoutes.js new file mode 100644 index 0000000..b5cca31 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/routes/workplaceRoutes.js @@ -0,0 +1,103 @@ +// routes/workplaceRoutes.js +const express = require('express'); +const router = express.Router(); +const multer = require('multer'); +const path = require('path'); +const workplaceController = require('../controllers/workplaceController'); +const { + generateSafeFilename, + createFileFilter, + ALLOWED_IMAGE_EXTENSIONS +} = require('../utils/fileUploadSecurity'); + +// Multer 설정 - 작업장 레이아웃 이미지 업로드 (보안 강화) +const storage = multer.diskStorage({ + destination: (req, file, cb) => { + cb(null, path.join(__dirname, '../uploads')); + }, + filename: (req, file, cb) => { + // 안전한 랜덤 파일명 생성 (원본 파일명 노출 방지) + const safeName = generateSafeFilename(file.originalname); + cb(null, `workplace-layout-${safeName}`); + } +}); + +// 보안 강화된 파일 필터 +const imageFileFilter = createFileFilter({ + allowedExtensions: ALLOWED_IMAGE_EXTENSIONS, + allowedMimes: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'] +}); + +const upload = multer({ + storage, + fileFilter: imageFileFilter, + limits: { + fileSize: 5 * 1024 * 1024, // 5MB 제한 + files: 1 // 단일 파일만 허용 + } +}); + +// ==================== 카테고리(공장) 관리 ==================== + +// CREATE 카테고리 +router.post('/categories', workplaceController.createCategory); + +// READ ALL 카테고리 +router.get('/categories', workplaceController.getAllCategories); + +// READ ACTIVE 카테고리 +router.get('/categories/active/list', workplaceController.getActiveCategories); + +// READ ONE 카테고리 +router.get('/categories/:id', workplaceController.getCategoryById); + +// UPDATE 카테고리 +router.put('/categories/:id', workplaceController.updateCategory); + +// DELETE 카테고리 +router.delete('/categories/:id', workplaceController.deleteCategory); + +// ==================== 작업장 관리 ==================== + +// CREATE 작업장 +router.post('/', workplaceController.createWorkplace); + +// READ ALL 작업장 (쿼리 파라미터로 카테고리 필터링 가능: ?category_id=1) +router.get('/', workplaceController.getAllWorkplaces); + +// READ ACTIVE 작업장 +router.get('/active/list', workplaceController.getActiveWorkplaces); + +// READ ONE 작업장 +router.get('/:id', workplaceController.getWorkplaceById); + +// UPDATE 작업장 +router.put('/:id', workplaceController.updateWorkplace); + +// DELETE 작업장 +router.delete('/:id', workplaceController.deleteWorkplace); + +// ==================== 작업장 지도 영역 관리 ==================== + +// 카테고리 레이아웃 이미지 업로드 +router.post('/categories/:id/layout-image', upload.single('image'), workplaceController.uploadCategoryLayoutImage); + +// 작업장 레이아웃 이미지 업로드 +router.post('/:id/layout-image', upload.single('image'), workplaceController.uploadWorkplaceLayoutImage); + +// CREATE 지도 영역 +router.post('/map-regions', workplaceController.createMapRegion); + +// READ 카테고리별 지도 영역 +router.get('/categories/:categoryId/map-regions', workplaceController.getMapRegionsByCategory); + +// READ 작업장별 지도 영역 +router.get('/map-regions/workplace/:workplaceId', workplaceController.getMapRegionByWorkplace); + +// UPDATE 지도 영역 +router.put('/map-regions/:id', workplaceController.updateMapRegion); + +// DELETE 지도 영역 +router.delete('/map-regions/:id', workplaceController.deleteMapRegion); + +module.exports = router; diff --git a/deploy/tkfb-package/api.hyungi.net/services/analysisService.js b/deploy/tkfb-package/api.hyungi.net/services/analysisService.js new file mode 100644 index 0000000..bc67473 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/analysisService.js @@ -0,0 +1,81 @@ +/** + * 프로젝트 분석 서비스 + * + * 기간별 프로젝트, 작업자, 작업 유형 분석 데이터 처리 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const analysisModel = require('../models/analysisModel'); +const { ValidationError, DatabaseError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 기간별 프로젝트 분석 데이터 조회 + * + * @param {string} startDate - 시작일 (YYYY-MM-DD) + * @param {string} endDate - 종료일 (YYYY-MM-DD) + * @returns {Promise} 가공된 분석 데이터 + */ +const getAnalysisService = async (startDate, endDate) => { + // 필수 필드 검증 + if (!startDate || !endDate) { + throw new ValidationError('시작일과 종료일이 필요합니다', { + required: ['startDate', 'endDate'], + received: { startDate, endDate } + }); + } + + logger.info('분석 데이터 조회 요청', { startDate, endDate }); + + try { + const analysisData = await analysisModel.getAnalysis(startDate, endDate); + + const { summary, byProject, byWorker, byTask, details } = analysisData; + const totalHours = summary.totalHours || 0; + + // 비율(percentage) 계산 헬퍼 함수 + const addPercentage = (item) => ({ + ...item, + hours: parseFloat(item.hours.toFixed(1)), + percentage: totalHours > 0 ? parseFloat((item.hours / totalHours * 100).toFixed(1)) : 0 + }); + + const result = { + summary: { + ...summary, + totalHours: parseFloat(totalHours.toFixed(1)) + }, + byProject: byProject.map(addPercentage), + byWorker: byWorker.map(addPercentage), + byTask: byTask.map(addPercentage), + details: details.map(d => ({ + ...d, + work_hours: parseFloat(d.work_hours.toFixed(1)) + })) + }; + + logger.info('분석 데이터 조회 성공', { + startDate, + endDate, + totalHours: result.summary.totalHours, + projectCount: result.byProject.length, + workerCount: result.byWorker.length, + detailCount: result.details.length + }); + + return result; + } catch (error) { + logger.error('분석 데이터 조회 실패', { + startDate, + endDate, + error: error.message + }); + throw new DatabaseError('분석 데이터 조회 중 오류가 발생했습니다'); + } +}; + +module.exports = { + getAnalysisService +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/attendanceService.js b/deploy/tkfb-package/api.hyungi.net/services/attendanceService.js new file mode 100644 index 0000000..6d6a182 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/attendanceService.js @@ -0,0 +1,394 @@ +/** + * 근태 관리 서비스 + * + * 근태 기록 관련 비즈니스 로직 처리 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const AttendanceModel = require('../models/attendanceModel'); +const vacationBalanceModel = require('../models/vacationBalanceModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 휴가 사용 유형 ID를 차감 일수로 변환 + * vacation_type_id: 1=연차(1일), 2=반차(0.5일), 3=반반차(0.25일) + */ +const getVacationDays = (vacationTypeId) => { + const daysMap = { 1: 1, 2: 0.5, 3: 0.25 }; + return daysMap[vacationTypeId] || 0; +}; + +/** + * 일일 근태 현황 조회 + */ +const getDailyAttendanceStatusService = async (date) => { + if (!date) { + throw new ValidationError('날짜가 필요합니다', { + required: ['date'], + received: { date } + }); + } + + logger.info('일일 근태 현황 조회 요청', { date }); + + try { + // 조회 전 초기화 수행 (Lazy Initialization) + // 생성자는 시스템(1) 또는 요청자가 될 수 있으나, 여기서는 안전하게 1(System/Admin) 사용 + // 혹은 req.user가 없으므로 서비스 레벨에서는 1로 가정하거나 파라미터로 받아야 함. + // 서비스 인터페이스 변경 최소화를 위해 하드코딩 또는 안전장치. + await AttendanceModel.initializeDailyRecords(date, 1); + + const attendanceStatus = await AttendanceModel.getWorkerAttendanceStatus(date); + logger.info('일일 근태 현황 조회 성공', { date, count: attendanceStatus.length }); + return attendanceStatus; + } catch (error) { + logger.error('일일 근태 현황 조회 실패', { date, error: error.message }); + throw new DatabaseError('근태 현황 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 일일 근태 기록 조회 + */ +const getDailyAttendanceRecordsService = async (date, workerId = null) => { + if (!date) { + throw new ValidationError('날짜가 필요합니다', { + required: ['date'], + received: { date } + }); + } + + logger.info('일일 근태 기록 조회 요청', { date, workerId }); + + try { + const records = await AttendanceModel.getDailyAttendanceRecords(date, workerId); + logger.info('일일 근태 기록 조회 성공', { date, count: records.length }); + return records; + } catch (error) { + logger.error('일일 근태 기록 조회 실패', { date, error: error.message }); + throw new DatabaseError('근태 기록 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 기간별 근태 기록 조회 (월별 조회용) + */ +const getAttendanceRecordsByRangeService = async (startDate, endDate, workerId = null) => { + if (!startDate || !endDate) { + throw new ValidationError('시작 날짜와 종료 날짜가 필요합니다', { + required: ['start_date', 'end_date'], + received: { startDate, endDate } + }); + } + + logger.info('기간별 근태 기록 조회 요청', { startDate, endDate, workerId }); + + try { + const records = await AttendanceModel.getDailyRecords(startDate, endDate, workerId); + logger.info('기간별 근태 기록 조회 성공', { startDate, endDate, count: records.length }); + return records; + } catch (error) { + logger.error('기간별 근태 기록 조회 실패', { startDate, endDate, error: error.message }); + throw new DatabaseError('근태 기록 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 근태 기록 생성/업데이트 + * - 휴가 기록 시 vacation_balance_details의 used_days 자동 연동 + */ +const upsertAttendanceRecordService = async (recordData) => { + const { + record_date, + worker_id, + total_work_hours, + attendance_type_id, + vacation_type_id, + is_vacation_processed, + overtime_approved, + status, + notes, + created_by + } = recordData; + + // 필수 필드 검증 + if (!record_date || !worker_id) { + throw new ValidationError('필수 필드가 누락되었습니다', { + required: ['record_date', 'worker_id'], + received: { record_date, worker_id } + }); + } + + logger.info('근태 기록 저장 요청', { record_date, worker_id, vacation_type_id }); + + try { + // 1. 기존 기록 조회 (휴가 연동을 위해) + const existingRecords = await AttendanceModel.getDailyAttendanceRecords(record_date, worker_id); + const existingRecord = existingRecords.find(r => r.worker_id === worker_id); + const previousVacationTypeId = existingRecord?.vacation_type_id || null; + + // 2. 근태 기록 저장 + const result = await AttendanceModel.upsertAttendanceRecord({ + record_date, + worker_id, + total_work_hours, + work_attendance_type_id: attendance_type_id, + vacation_type_id, + is_overtime_approved: overtime_approved, + created_by + }); + + // 3. 휴가 잔액 연동 (vacation_balance_details.used_days 업데이트) + const year = new Date(record_date).getFullYear(); + const previousDays = getVacationDays(previousVacationTypeId); + const newDays = getVacationDays(vacation_type_id); + + // 이전 휴가가 있었고 변경된 경우 → 복구 후 차감 + if (previousDays !== newDays) { + // 이전 휴가 복구 + if (previousDays > 0) { + await vacationBalanceModel.restoreByPriority(worker_id, year, previousDays); + logger.info('휴가 잔액 복구', { worker_id, year, restored: previousDays }); + } + + // 새 휴가 차감 + if (newDays > 0) { + await vacationBalanceModel.deductByPriority(worker_id, year, newDays); + logger.info('휴가 잔액 차감', { worker_id, year, deducted: newDays }); + } + } + + logger.info('근태 기록 저장 성공', { record_date, worker_id }); + return result; + } catch (error) { + logger.error('근태 기록 저장 실패', { record_date, worker_id, error: error.message }); + throw new DatabaseError('근태 기록 저장 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 휴가 처리 + */ +const processVacationService = async (vacationData) => { + const { record_date, worker_id, vacation_type_id } = vacationData; + + if (!record_date || !worker_id || !vacation_type_id) { + throw new ValidationError('필수 필드가 누락되었습니다', { + required: ['record_date', 'worker_id', 'vacation_type_id'], + received: { record_date, worker_id, vacation_type_id } + }); + } + + logger.info('휴가 처리 요청', { record_date, worker_id, vacation_type_id }); + + try { + const result = await AttendanceModel.processVacation({ + record_date, + worker_id, + vacation_type_id + }); + + logger.info('휴가 처리 성공', { record_date, worker_id }); + return result; + } catch (error) { + logger.error('휴가 처리 실패', { record_date, worker_id, error: error.message }); + throw new DatabaseError('휴가 처리 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 초과 근무 승인 + */ +const approveOvertimeService = async (overtimeData) => { + const { record_date, worker_id, overtime_approved } = overtimeData; + + if (!record_date || !worker_id || overtime_approved === undefined) { + throw new ValidationError('필수 필드가 누락되었습니다', { + required: ['record_date', 'worker_id', 'overtime_approved'], + received: { record_date, worker_id, overtime_approved } + }); + } + + logger.info('초과 근무 승인 요청', { record_date, worker_id, overtime_approved }); + + try { + const result = await AttendanceModel.approveOvertime({ + record_date, + worker_id, + overtime_approved + }); + + logger.info('초과 근무 승인 처리 성공', { record_date, worker_id }); + return result; + } catch (error) { + logger.error('초과 근무 승인 실패', { record_date, worker_id, error: error.message }); + throw new DatabaseError('초과 근무 승인 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 근태 유형 목록 조회 + */ +const getAttendanceTypesService = async () => { + logger.info('근태 유형 목록 조회 요청'); + + try { + const types = await AttendanceModel.getAttendanceTypes(); + logger.info('근태 유형 목록 조회 성공', { count: types.length }); + return types; + } catch (error) { + logger.error('근태 유형 목록 조회 실패', { error: error.message }); + throw new DatabaseError('근태 유형 목록 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 휴가 유형 목록 조회 + */ +const getVacationTypesService = async () => { + logger.info('휴가 유형 목록 조회 요청'); + + try { + const types = await AttendanceModel.getVacationTypes(); + logger.info('휴가 유형 목록 조회 성공', { count: types.length }); + return types; + } catch (error) { + logger.error('휴가 유형 목록 조회 실패', { error: error.message }); + throw new DatabaseError('휴가 유형 목록 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 작업자 휴가 잔여 일수 조회 + */ +const getWorkerVacationBalanceService = async (workerId) => { + if (!workerId) { + throw new ValidationError('작업자 ID가 필요합니다', { + required: ['worker_id'], + received: { workerId } + }); + } + + logger.info('휴가 잔여 일수 조회 요청', { workerId }); + + try { + const balance = await AttendanceModel.getWorkerVacationBalance(workerId); + logger.info('휴가 잔여 일수 조회 성공', { workerId }); + return balance; + } catch (error) { + logger.error('휴가 잔여 일수 조회 실패', { workerId, error: error.message }); + throw new DatabaseError('휴가 잔여 일수 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 월별 근태 통계 조회 + */ +const getMonthlyAttendanceStatsService = async (year, month, workerId = null) => { + if (!year || !month) { + throw new ValidationError('연도와 월이 필요합니다', { + required: ['year', 'month'], + received: { year, month } + }); + } + + logger.info('월별 근태 통계 조회 요청', { year, month, workerId }); + + try { + const stats = await AttendanceModel.getMonthlyAttendanceStats(year, month, workerId); + logger.info('월별 근태 통계 조회 성공', { year, month }); + return stats; + } catch (error) { + logger.error('월별 근태 통계 조회 실패', { year, month, error: error.message }); + throw new DatabaseError('월별 근태 통계 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 출근 체크 목록 조회 (휴가 정보 포함) + */ +const getCheckinListService = async (date) => { + if (!date) { + throw new ValidationError('날짜가 필요합니다', { + required: ['date'], + received: { date } + }); + } + + logger.info('출근 체크 목록 조회 요청', { date }); + + try { + const checkinList = await AttendanceModel.getCheckinList(date); + logger.info('출근 체크 목록 조회 성공', { date, count: checkinList.length }); + return checkinList; + } catch (error) { + logger.error('출근 체크 목록 조회 실패', { date, error: error.message }); + throw new DatabaseError('출근 체크 목록 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 출근 체크 일괄 저장 + */ +const saveCheckinsService = async (date, checkins) => { + if (!date || !checkins || !Array.isArray(checkins)) { + throw new ValidationError('날짜와 출근 체크 목록이 필요합니다', { + required: ['date', 'checkins'], + received: { date, checkins: checkins ? `Array[${checkins.length}]` : null } + }); + } + + logger.info('출근 체크 일괄 저장 요청', { date, count: checkins.length }); + + try { + const results = []; + + for (const checkin of checkins) { + const { worker_id, is_present } = checkin; + + if (!worker_id || is_present === undefined) { + logger.warn('출근 체크 데이터 누락', { checkin }); + continue; + } + + const result = await AttendanceModel.upsertCheckin({ + worker_id, + record_date: date, + is_present + }); + + results.push({ + worker_id, + record_id: result, + is_present + }); + } + + logger.info('출근 체크 일괄 저장 성공', { date, saved: results.length }); + return { + saved_count: results.length, + results + }; + } catch (error) { + logger.error('출근 체크 일괄 저장 실패', { date, error: error.message }); + throw new DatabaseError('출근 체크 저장 중 데이터베이스 오류가 발생했습니다'); + } +}; + +module.exports = { + getDailyAttendanceStatusService, + getDailyAttendanceRecordsService, + getAttendanceRecordsByRangeService, + upsertAttendanceRecordService, + processVacationService, + approveOvertimeService, + getAttendanceTypesService, + getVacationTypesService, + getWorkerVacationBalanceService, + getMonthlyAttendanceStatsService, + getCheckinListService, + saveCheckinsService +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/auth.service.js b/deploy/tkfb-package/api.hyungi.net/services/auth.service.js new file mode 100644 index 0000000..a7481b4 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/auth.service.js @@ -0,0 +1,98 @@ +const bcrypt = require('bcryptjs'); +const jwt = require('jsonwebtoken'); +const userModel = require('../models/userModel'); +const { getDb } = require('../dbPool'); + +// 로그인 이력 기록 (서비스 내부 헬퍼 함수) +const recordLoginHistory = async (userId, success, ipAddress, userAgent, failureReason = null) => { + try { + const db = await getDb(); + await db.query( + `INSERT INTO login_logs (user_id, login_time, ip_address, user_agent, login_status, failure_reason) + VALUES (?, NOW(), ?, ?, ?, ?)`, + [userId, ipAddress || 'unknown', userAgent || 'unknown', success ? 'success' : 'failed', failureReason] + ); + } catch (error) { + console.error('로그인 이력 기록 실패:', error); + } +}; + +const loginService = async (username, password, ipAddress, userAgent) => { + // 서비스 레이어에서는 더 이상 DB 커넥션을 직접 다루지 않음 + try { + const user = await userModel.findByUsername(username); + + if (!user) { + console.log(`[로그인 실패] 사용자를 찾을 수 없음: ${username}`); + return { success: false, status: 401, error: '아이디 또는 비밀번호가 올바르지 않습니다.' }; + } + + if (user.is_active === false) { + await recordLoginHistory(user.user_id, false, ipAddress, userAgent, 'account_disabled'); + return { success: false, status: 403, error: '비활성화된 계정입니다. 관리자에게 문의하세요.' }; + } + + if (user.locked_until && new Date(user.locked_until) > new Date()) { + const remainingTime = Math.ceil((new Date(user.locked_until) - new Date()) / 1000 / 60); + return { success: false, status: 429, error: `계정이 잠겨있습니다. ${remainingTime}분 후에 다시 시도하세요.` }; + } + + const isValid = await bcrypt.compare(password, user.password); + if (!isValid) { + console.log(`[로그인 실패] 비밀번호 불일치: ${username}`); + + // 모델 함수를 사용하여 로그인 실패 처리 + await userModel.incrementFailedLoginAttempts(user.user_id); + + if (user.failed_login_attempts >= 4) { + await userModel.lockUserAccount(user.user_id); + } + + await recordLoginHistory(user.user_id, false, ipAddress, userAgent, 'invalid_password'); + return { success: false, status: 401, error: '아이디 또는 비밀번호가 올바르지 않습니다.' }; + } + + // 성공 시 모델 함수를 사용하여 상태 초기화 + await userModel.resetLoginAttempts(user.user_id); + + + const token = jwt.sign( + { user_id: user.user_id, username: user.username, role: user.role_name, role_id: user.role_id, access_level: user.access_level, worker_id: user.worker_id, name: user.name || user.username }, + process.env.JWT_SECRET || 'your-secret-key', + { expiresIn: process.env.JWT_EXPIRES_IN || '24h' } + ); + + const refreshToken = jwt.sign( + { user_id: user.user_id, type: 'refresh' }, + process.env.JWT_REFRESH_SECRET || process.env.JWT_SECRET || 'your-refresh-secret', + { expiresIn: process.env.JWT_REFRESH_EXPIRES_IN || '7d' } + ); + + await recordLoginHistory(user.user_id, true, ipAddress, userAgent); + console.log(`[로그인 성공] 사용자: ${user.username} (${user.access_level})`); + + return { + success: true, + data: { + token, + refreshToken, + user: { + user_id: user.user_id, + username: user.username, + name: user.name || user.username, + role: user.role_name, + access_level: user.access_level, + worker_id: user.worker_id + } + } + }; + } catch (error) { + console.error('Login service error:', error); + throw new Error('서버 오류가 발생했습니다.'); + } + // 서비스 레이어에서는 더 이상 DB 커넥션을 직접 다루지 않음 +}; + +module.exports = { + loginService, +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/services/dailyIssueReportService.js b/deploy/tkfb-package/api.hyungi.net/services/dailyIssueReportService.js new file mode 100644 index 0000000..f8e8f92 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/dailyIssueReportService.js @@ -0,0 +1,170 @@ +/** + * 일일 이슈 보고서 관리 서비스 + * + * 일일 이슈 보고서 생성, 조회, 삭제 관련 비즈니스 로직 처리 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const dailyIssueReportModel = require('../models/dailyIssueReportModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 일일 이슈 보고서 생성 + * + * 한 번에 여러 작업자에 대해 동일한 이슈를 등록할 수 있습니다. + * + * @param {object} issueData - 컨트롤러에서 전달된 이슈 데이터 + * @param {string} issueData.date - 이슈 발생 날짜 (YYYY-MM-DD) + * @param {number} issueData.project_id - 프로젝트 ID + * @param {string} issueData.start_time - 이슈 시작 시간 + * @param {string} issueData.end_time - 이슈 종료 시간 + * @param {number} issueData.issue_type_id - 이슈 유형 ID + * @param {number[]} issueData.worker_ids - 작업자 ID 배열 + * @returns {Promise} 생성 결과 + */ +const createDailyIssueReportService = async (issueData) => { + const { date, project_id, start_time, end_time, issue_type_id, worker_ids } = issueData; + + // 필수 필드 검증 + if (!date || !project_id || !start_time || !end_time || !issue_type_id || !worker_ids) { + throw new ValidationError('필수 필드가 누락되었습니다', { + required: ['date', 'project_id', 'start_time', 'end_time', 'issue_type_id', 'worker_ids'], + received: { date, project_id, start_time, end_time, issue_type_id, worker_ids: !!worker_ids } + }); + } + + if (!Array.isArray(worker_ids) || worker_ids.length === 0) { + throw new ValidationError('worker_ids는 최소 한 명 이상의 작업자를 포함하는 배열이어야 합니다', { + received: { worker_ids, isArray: Array.isArray(worker_ids), length: worker_ids?.length } + }); + } + + logger.info('이슈 보고서 생성 요청', { + date, + project_id, + issue_type_id, + worker_count: worker_ids.length + }); + + // 모델에 전달할 데이터 준비 + const reportsToCreate = worker_ids.map(worker_id => ({ + date, + project_id, + start_time, + end_time, + issue_type_id, + worker_id + })); + + try { + const insertedIds = await dailyIssueReportModel.createMany(reportsToCreate); + + logger.info('이슈 보고서 생성 성공', { + count: insertedIds.length, + issue_report_ids: insertedIds + }); + + return { + message: `${insertedIds.length}개의 이슈 보고서가 성공적으로 생성되었습니다`, + issue_report_ids: insertedIds + }; + } catch (error) { + logger.error('이슈 보고서 생성 실패', { + date, + project_id, + worker_ids, + error: error.message + }); + throw new DatabaseError('이슈 보고서 생성 중 오류가 발생했습니다'); + } +}; + +/** + * 특정 날짜의 모든 이슈 보고서 조회 + * + * @param {string} date - 조회할 날짜 (YYYY-MM-DD) + * @returns {Promise} 조회된 이슈 보고서 배열 + */ +const getDailyIssuesByDateService = async (date) => { + if (!date) { + throw new ValidationError('날짜가 필요합니다', { + required: ['date'], + received: { date } + }); + } + + logger.info('이슈 보고서 날짜별 조회 요청', { date }); + + try { + const issues = await dailyIssueReportModel.getAllByDate(date); + + logger.info('이슈 보고서 조회 성공', { + date, + count: issues.length + }); + + return issues; + } catch (error) { + logger.error('이슈 보고서 조회 실패', { + date, + error: error.message + }); + throw new DatabaseError('이슈 보고서 조회 중 오류가 발생했습니다'); + } +}; + +/** + * 특정 ID의 이슈 보고서 삭제 + * + * @param {string|number} issueId - 삭제할 이슈 보고서의 ID + * @returns {Promise} 삭제 결과 + */ +const removeDailyIssueService = async (issueId) => { + if (!issueId) { + throw new ValidationError('이슈 보고서 ID가 필요합니다', { + required: ['issue_id'], + received: { issueId } + }); + } + + logger.info('이슈 보고서 삭제 요청', { issue_id: issueId }); + + try { + const affectedRows = await dailyIssueReportModel.remove(issueId); + + if (affectedRows === 0) { + logger.warn('삭제할 이슈 보고서를 찾을 수 없음', { issue_id: issueId }); + throw new NotFoundError('삭제할 이슈 보고서를 찾을 수 없습니다'); + } + + logger.info('이슈 보고서 삭제 성공', { + issue_id: issueId, + affected_rows: affectedRows + }); + + return { + message: '이슈 보고서가 성공적으로 삭제되었습니다', + deleted_id: issueId, + affected_rows: affectedRows + }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('이슈 보고서 삭제 실패', { + issue_id: issueId, + error: error.message + }); + throw new DatabaseError('이슈 보고서 삭제 중 오류가 발생했습니다'); + } +}; + +module.exports = { + createDailyIssueReportService, + getDailyIssuesByDateService, + removeDailyIssueService +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/dailyWorkReportService.js b/deploy/tkfb-package/api.hyungi.net/services/dailyWorkReportService.js new file mode 100644 index 0000000..5b058a3 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/dailyWorkReportService.js @@ -0,0 +1,326 @@ +/** + * 일일 작업 보고서 서비스 + * + * 작업 보고서 관련 비즈니스 로직 처리 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const dailyWorkReportModel = require('../models/dailyWorkReportModel'); +const { ValidationError, NotFoundError, ForbiddenError, DatabaseError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 일일 작업 보고서를 생성하는 비즈니스 로직을 처리합니다. + * @param {object} reportData - 컨트롤러에서 전달된 보고서 데이터 + * @returns {Promise} 생성 결과 또는 에러 + */ +const createDailyWorkReportService = async (reportData) => { + const { report_date, worker_id, work_entries, created_by, created_by_name } = reportData; + + // 1. 기본 유효성 검사 + if (!report_date || !worker_id || !work_entries) { + throw new ValidationError('필수 필드가 누락되었습니다', { + required: ['report_date', 'worker_id', 'work_entries'], + received: { report_date, worker_id, work_entries: !!work_entries } + }); + } + + if (!Array.isArray(work_entries) || work_entries.length === 0) { + throw new ValidationError('최소 하나의 작업 항목이 필요합니다'); + } + + if (!created_by) { + throw new ValidationError('사용자 인증 정보가 없습니다'); + } + + // 2. 작업 항목 유효성 검사 + for (let i = 0; i < work_entries.length; i++) { + const entry = work_entries[i]; + const requiredFields = ['project_id', 'task_id', 'work_hours']; + + for (const field of requiredFields) { + if (entry[field] === undefined || entry[field] === null || entry[field] === '') { + throw new ValidationError(`작업 항목 ${i + 1}의 필수 필드가 누락되었습니다`, { + entry: i + 1, + missingField: field + }); + } + } + + // is_error가 true일 때 error_type_code_id 필수 검사 + if (entry.is_error === true && !entry.error_type_code_id) { + throw new ValidationError(`에러 상태인 경우 에러 타입이 필요합니다`, { + entry: i + 1, + is_error: true + }); + } + + const hours = parseFloat(entry.work_hours); + if (isNaN(hours) || hours <= 0 || hours > 24) { + throw new ValidationError(`작업 시간이 유효하지 않습니다 (0 초과 24 이하)`, { + entry: i + 1, + work_hours: entry.work_hours, + valid_range: '0 < hours <= 24' + }); + } + } + + // 3. 모델에 전달할 데이터 준비 + const modelData = { + report_date, + worker_id: parseInt(worker_id), + entries: work_entries.map(entry => ({ + project_id: entry.project_id, + work_type_id: entry.task_id, // task_id를 work_type_id로 매핑 + work_hours: parseFloat(entry.work_hours), + work_status_id: entry.work_status_id, + error_type_id: entry.error_type_id, + created_by: created_by + })) + }; + + logger.info('작업보고서 생성 요청', { + date: report_date, + worker: worker_id, + creator: created_by_name, + entries_count: modelData.entries.length + }); + + // 4. 모델 함수 호출 + try { + const result = await dailyWorkReportModel.createReportEntries(modelData); + + logger.info('작업보고서 생성 성공', { + report_id: result.report_id, + entries_count: modelData.entries.length + }); + + return { + message: '작업보고서가 성공적으로 생성되었습니다.', + ...result + }; + } catch (error) { + logger.error('작업보고서 생성 실패', { + error: error.message, + stack: error.stack + }); + throw new DatabaseError('작업보고서 생성 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 사용자 권한과 요청 파라미터에 따라 일일 작업 보고서를 조회하는 비즈니스 로직을 처리합니다. + * @param {object} queryParams - 컨트롤러에서 전달된 쿼리 파라미터 + * @param {object} userInfo - 요청을 보낸 사용자의 정보 (id, role 등) + * @returns {Promise} 조회된 작업 보고서 배열 + */ +const getDailyWorkReportsService = async (queryParams, userInfo) => { + const { date, start_date, end_date, worker_id, created_by: requested_created_by, view_all } = queryParams; + const { user_id: current_user_id, role } = userInfo; + + // 날짜 또는 날짜 범위 중 하나는 필수 + if (!date && (!start_date || !end_date)) { + throw new ValidationError('날짜 또는 날짜 범위가 필요합니다', { + required: 'date OR (start_date AND end_date)', + received: { date, start_date, end_date } + }); + } + + // 관리자 여부 확인 + const isAdmin = role === 'system' || role === 'admin'; + const canViewAll = isAdmin || view_all === 'true'; + + // 모델에 전달할 조회 옵션 객체 생성 + const options = {}; + + if (date) { + options.date = date; + } else { + options.start_date = start_date; + options.end_date = end_date; + } + + if (worker_id) { + options.worker_id = parseInt(worker_id); + } + + // 최종적으로 필터링할 작성자 ID 결정 + if (!canViewAll) { + // 관리자가 아니면 자신의 데이터만 보거나, 명시적으로 요청된 자신의 ID만 허용 + options.created_by_user_id = requested_created_by ? Math.min(requested_created_by, current_user_id) : current_user_id; + } else if (requested_created_by) { + // 관리자는 다른 사람의 데이터도 조회 가능 + options.created_by_user_id = parseInt(requested_created_by); + } + // created_by_user_id가 명시되지 않으면 모든 작성자의 데이터를 조회 + + logger.info('작업보고서 조회 요청', { ...options, requester: current_user_id, isAdmin }); + + try { + const reports = await dailyWorkReportModel.getReportsWithOptions(options); + logger.info('작업보고서 조회 성공', { count: reports.length }); + return reports; + } catch (error) { + logger.error('작업보고서 조회 실패', { error: error.message }); + throw new DatabaseError('작업보고서 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 특정 작업 보고서 항목을 수정하는 비즈니스 로직을 처리합니다. + * @param {string} reportId - 수정할 보고서의 ID + * @param {object} updateData - 수정할 데이터 + * @param {object} userInfo - 요청을 보낸 사용자의 정보 + * @returns {Promise} 수정 결과 + */ +const updateWorkReportService = async (reportId, updateData, userInfo) => { + const { user_id: updated_by } = userInfo; + + if (!reportId || !updateData || Object.keys(updateData).length === 0) { + throw new ValidationError('보고서 ID와 수정할 데이터가 필요합니다', { + reportId, + hasUpdateData: !!updateData, + updateFieldsCount: updateData ? Object.keys(updateData).length : 0 + }); + } + + const modelUpdateData = { ...updateData, updated_by_user_id: updated_by }; + + logger.info('작업보고서 수정 요청', { reportId, updatedBy: updated_by }); + + try { + const affectedRows = await dailyWorkReportModel.updateReportById(reportId, modelUpdateData); + + if (affectedRows === 0) { + throw new NotFoundError('수정할 작업보고서를 찾을 수 없습니다'); + } + + logger.info('작업보고서 수정 성공', { reportId }); + return { + message: '작업보고서가 성공적으로 수정되었습니다.', + report_id: reportId, + affected_rows: affectedRows + }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + logger.error('작업보고서 수정 실패', { reportId, error: error.message }); + throw new DatabaseError('작업보고서 수정 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 특정 작업 보고서 항목을 삭제하는 비즈니스 로직을 처리합니다. + * @param {string} reportId - 삭제할 보고서의 ID + * @param {object} userInfo - 요청을 보낸 사용자의 정보 + * @returns {Promise} 삭제 결과 + */ +const removeDailyWorkReportService = async (reportId, userInfo) => { + const { user_id: deleted_by } = userInfo; + + if (!reportId) { + throw new ValidationError('삭제할 보고서 ID가 필요합니다'); + } + + logger.info('작업보고서 삭제 요청', { reportId, deletedBy: deleted_by }); + + try { + const affectedRows = await dailyWorkReportModel.removeReportById(reportId, deleted_by); + + if (affectedRows === 0) { + throw new NotFoundError('삭제할 작업보고서를 찾을 수 없습니다'); + } + + logger.info('작업보고서 삭제 성공', { reportId }); + return { + message: '작업보고서가 성공적으로 삭제되었습니다.', + report_id: reportId, + affected_rows: affectedRows + }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + logger.error('작업보고서 삭제 실패', { reportId, error: error.message }); + throw new DatabaseError('작업보고서 삭제 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 기간별 작업 보고서 통계를 조회하는 비즈니스 로직을 처리합니다. + * @param {object} queryParams - 컨트롤러에서 전달된 쿼리 파라미터 (start_date, end_date) + * @returns {Promise} 통계 데이터 + */ +const getStatisticsService = async (queryParams) => { + const { start_date, end_date } = queryParams; + + if (!start_date || !end_date) { + throw new ValidationError('시작일과 종료일이 모두 필요합니다', { + required: ['start_date', 'end_date'], + received: { start_date, end_date } + }); + } + + logger.info('작업보고서 통계 조회 요청', { start_date, end_date }); + + try { + const statsData = await dailyWorkReportModel.getStatistics(start_date, end_date); + + logger.info('작업보고서 통계 조회 성공', { period: `${start_date} ~ ${end_date}` }); + return { + ...statsData, + metadata: { + period: `${start_date} ~ ${end_date}`, + timestamp: new Date().toISOString() + } + }; + } catch (error) { + logger.error('통계 조회 실패', { error: error.message }); + throw new DatabaseError('통계 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +/** + * 일일 또는 작업자별 작업 요약 정보를 조회하는 비즈니스 로직을 처리합니다. + * @param {object} queryParams - 컨트롤러에서 전달된 쿼리 파라미터 (date 또는 worker_id) + * @returns {Promise} 요약 데이터 + */ +const getSummaryService = async (queryParams) => { + const { date, worker_id } = queryParams; + + if (!date && !worker_id) { + throw new ValidationError('날짜 또는 작업자 ID가 필요합니다', { + required: 'date OR worker_id', + received: { date, worker_id } + }); + } + + try { + if (date) { + logger.info('일일 요약 조회 요청', { date }); + const result = await dailyWorkReportModel.getSummaryByDate(date); + logger.info('일일 요약 조회 성공', { date }); + return result; + } else { // worker_id + logger.info('작업자별 요약 조회 요청', { worker_id }); + const result = await dailyWorkReportModel.getSummaryByWorker(worker_id); + logger.info('작업자별 요약 조회 성공', { worker_id }); + return result; + } + } catch (error) { + logger.error('요약 정보 조회 실패', { error: error.message }); + throw new DatabaseError('요약 정보 조회 중 데이터베이스 오류가 발생했습니다'); + } +}; + +module.exports = { + createDailyWorkReportService, + getDailyWorkReportsService, + updateWorkReportService, + removeDailyWorkReportService, + getStatisticsService, + getSummaryService, +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/services/imageUploadService.js b/deploy/tkfb-package/api.hyungi.net/services/imageUploadService.js new file mode 100644 index 0000000..7870130 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/imageUploadService.js @@ -0,0 +1,217 @@ +/** + * 이미지 업로드 서비스 + * Base64 인코딩된 이미지를 파일로 저장 + * + * 사용 전 sharp 패키지 설치 필요: + * npm install sharp + */ + +const path = require('path'); +const fs = require('fs').promises; +const crypto = require('crypto'); + +// sharp는 선택적으로 사용 (설치되어 있지 않으면 리사이징 없이 저장) +let sharp; +try { + sharp = require('sharp'); +} catch (e) { + console.warn('sharp 패키지가 설치되어 있지 않습니다. 이미지 리사이징이 비활성화됩니다.'); + console.warn('이미지 최적화를 위해 npm install sharp 를 실행하세요.'); +} + +// 업로드 디렉토리 설정 +const UPLOAD_DIRS = { + issues: path.join(__dirname, '../public/uploads/issues'), + equipments: path.join(__dirname, '../public/uploads/equipments') +}; +const UPLOAD_DIR = UPLOAD_DIRS.issues; // 기존 호환성 유지 +const MAX_SIZE = { width: 1920, height: 1920 }; +const QUALITY = 85; + +/** + * 업로드 디렉토리 확인 및 생성 + * @param {string} category - 카테고리 ('issues' 또는 'equipments') + */ +async function ensureUploadDir(category = 'issues') { + const uploadDir = UPLOAD_DIRS[category] || UPLOAD_DIRS.issues; + try { + await fs.access(uploadDir); + } catch { + await fs.mkdir(uploadDir, { recursive: true }); + } + return uploadDir; +} + +/** + * UUID 생성 (간단한 버전) + */ +function generateId() { + return crypto.randomBytes(4).toString('hex'); +} + +/** + * 타임스탬프 문자열 생성 + */ +function getTimestamp() { + const now = new Date(); + return now.toISOString().replace(/[-:T]/g, '').slice(0, 14); +} + +/** + * Base64 문자열에서 이미지 형식 추출 + * @param {string} base64String - Base64 인코딩된 이미지 + * @returns {string} 이미지 확장자 (jpg, png, etc) + */ +function getImageExtension(base64String) { + const match = base64String.match(/^data:image\/(\w+);base64,/); + if (match) { + const format = match[1].toLowerCase(); + // jpeg를 jpg로 변환 + return format === 'jpeg' ? 'jpg' : format; + } + return 'jpg'; // 기본값 +} + +/** + * Base64 이미지를 파일로 저장 + * @param {string} base64String - Base64 인코딩된 이미지 (data:image/...;base64,... 형식) + * @param {string} prefix - 파일명 접두사 (예: 'issue', 'resolution', 'equipment') + * @param {string} category - 저장 카테고리 ('issues' 또는 'equipments') + * @returns {Promise} 저장된 파일의 웹 경로 또는 null + */ +async function saveBase64Image(base64String, prefix = 'issue', category = 'issues') { + try { + if (!base64String || typeof base64String !== 'string') { + return null; + } + + // Base64 헤더가 없는 경우 처리 + let base64Data = base64String; + if (base64String.includes('base64,')) { + base64Data = base64String.split('base64,')[1]; + } + + // Base64 디코딩 + const buffer = Buffer.from(base64Data, 'base64'); + + if (buffer.length === 0) { + console.error('이미지 데이터가 비어있습니다.'); + return null; + } + + // 디렉토리 확인 + const uploadDir = await ensureUploadDir(category); + + // 파일명 생성 + const timestamp = getTimestamp(); + const uniqueId = generateId(); + const extension = 'jpg'; // 모든 이미지를 JPEG로 저장 + const filename = `${prefix}_${timestamp}_${uniqueId}.${extension}`; + const filepath = path.join(uploadDir, filename); + + // sharp가 설치되어 있으면 리사이징 및 최적화 + if (sharp) { + try { + await sharp(buffer) + .resize(MAX_SIZE.width, MAX_SIZE.height, { + fit: 'inside', + withoutEnlargement: true + }) + .jpeg({ quality: QUALITY }) + .toFile(filepath); + } catch (sharpError) { + console.error('sharp 처리 실패, 원본 저장:', sharpError.message); + // sharp 실패 시 원본 저장 + await fs.writeFile(filepath, buffer); + } + } else { + // sharp가 없으면 원본 그대로 저장 + await fs.writeFile(filepath, buffer); + } + + // 웹 접근 경로 반환 + return `/uploads/${category}/${filename}`; + } catch (error) { + console.error('이미지 저장 실패:', error); + return null; + } +} + +/** + * 여러 Base64 이미지를 한번에 저장 + * @param {string[]} base64Images - Base64 이미지 배열 + * @param {string} prefix - 파일명 접두사 + * @returns {Promise} 저장된 파일 경로 배열 + */ +async function saveMultipleImages(base64Images, prefix = 'issue') { + const paths = []; + + for (const base64 of base64Images) { + if (base64) { + const savedPath = await saveBase64Image(base64, prefix); + if (savedPath) { + paths.push(savedPath); + } + } + } + + return paths; +} + +/** + * 파일 삭제 + * @param {string} webPath - 웹 경로 (예: /uploads/issues/filename.jpg) + * @returns {Promise} 삭제 성공 여부 + */ +async function deleteFile(webPath) { + try { + if (!webPath || typeof webPath !== 'string') { + return false; + } + + // 보안: uploads 경로만 삭제 허용 + if (!webPath.startsWith('/uploads/')) { + console.error('삭제 불가: uploads 외부 경로', webPath); + return false; + } + + const filename = path.basename(webPath); + const fullPath = path.join(UPLOAD_DIR, filename); + + try { + await fs.access(fullPath); + await fs.unlink(fullPath); + return true; + } catch (accessError) { + // 파일이 없으면 성공으로 처리 + if (accessError.code === 'ENOENT') { + return true; + } + throw accessError; + } + } catch (error) { + console.error('파일 삭제 실패:', error); + return false; + } +} + +/** + * 여러 파일 삭제 + * @param {string[]} webPaths - 웹 경로 배열 + * @returns {Promise} + */ +async function deleteMultipleFiles(webPaths) { + for (const webPath of webPaths) { + if (webPath) { + await deleteFile(webPath); + } + } +} + +module.exports = { + saveBase64Image, + saveMultipleImages, + deleteFile, + deleteMultipleFiles, + UPLOAD_DIR +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/issueTypeService.js b/deploy/tkfb-package/api.hyungi.net/services/issueTypeService.js new file mode 100644 index 0000000..25aa048 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/issueTypeService.js @@ -0,0 +1,169 @@ +/** + * 이슈 유형 관리 서비스 + * + * 이슈 유형(카테고리/서브카테고리) 관련 비즈니스 로직 처리 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const issueTypeModel = require('../models/issueTypeModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 이슈 유형 생성 + */ +const createIssueTypeService = async (issueTypeData) => { + const { category, subcategory } = issueTypeData; + + // 필수 필드 검증 + if (!category || !subcategory) { + throw new ValidationError('카테고리와 서브카테고리가 필요합니다', { + required: ['category', 'subcategory'], + received: { category, subcategory } + }); + } + + logger.info('이슈 유형 생성 요청', { category, subcategory }); + + try { + const insertId = await new Promise((resolve, reject) => { + issueTypeModel.create({ category, subcategory }, (err, id) => { + if (err) reject(err); + else resolve(id); + }); + }); + + logger.info('이슈 유형 생성 성공', { issue_type_id: insertId }); + + return { issue_type_id: insertId }; + } catch (error) { + logger.error('이슈 유형 생성 실패', { + category, + subcategory, + error: error.message + }); + throw new DatabaseError('이슈 유형 생성 중 오류가 발생했습니다'); + } +}; + +/** + * 전체 이슈 유형 조회 + */ +const getAllIssueTypesService = async () => { + logger.info('이슈 유형 목록 조회 요청'); + + try { + const rows = await new Promise((resolve, reject) => { + issueTypeModel.getAll((err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + logger.info('이슈 유형 목록 조회 성공', { count: rows.length }); + + return rows; + } catch (error) { + logger.error('이슈 유형 목록 조회 실패', { error: error.message }); + throw new DatabaseError('이슈 유형 목록 조회 중 오류가 발생했습니다'); + } +}; + +/** + * 이슈 유형 수정 + */ +const updateIssueTypeService = async (id, issueTypeData) => { + const { category, subcategory } = issueTypeData; + + // ID 검증 + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 이슈 유형 ID입니다'); + } + + // 필수 필드 검증 + if (!category || !subcategory) { + throw new ValidationError('카테고리와 서브카테고리가 필요합니다', { + required: ['category', 'subcategory'], + received: { category, subcategory } + }); + } + + logger.info('이슈 유형 수정 요청', { issue_type_id: id, category, subcategory }); + + try { + const affectedRows = await new Promise((resolve, reject) => { + issueTypeModel.update(id, { category, subcategory }, (err, rows) => { + if (err) reject(err); + else resolve(rows); + }); + }); + + if (affectedRows === 0) { + logger.warn('이슈 유형을 찾을 수 없음', { issue_type_id: id }); + throw new NotFoundError('이슈 유형을 찾을 수 없습니다'); + } + + logger.info('이슈 유형 수정 성공', { issue_type_id: id, affectedRows }); + + return { changes: affectedRows }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('이슈 유형 수정 실패', { + issue_type_id: id, + error: error.message + }); + throw new DatabaseError('이슈 유형 수정 중 오류가 발생했습니다'); + } +}; + +/** + * 이슈 유형 삭제 + */ +const removeIssueTypeService = async (id) => { + // ID 검증 + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 이슈 유형 ID입니다'); + } + + logger.info('이슈 유형 삭제 요청', { issue_type_id: id }); + + try { + const affectedRows = await new Promise((resolve, reject) => { + issueTypeModel.remove(id, (err, rows) => { + if (err) reject(err); + else resolve(rows); + }); + }); + + if (affectedRows === 0) { + logger.warn('이슈 유형을 찾을 수 없음', { issue_type_id: id }); + throw new NotFoundError('이슈 유형을 찾을 수 없습니다'); + } + + logger.info('이슈 유형 삭제 성공', { issue_type_id: id, affectedRows }); + + return { changes: affectedRows }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('이슈 유형 삭제 실패', { + issue_type_id: id, + error: error.message + }); + throw new DatabaseError('이슈 유형 삭제 중 오류가 발생했습니다'); + } +}; + +module.exports = { + createIssueTypeService, + getAllIssueTypesService, + updateIssueTypeService, + removeIssueTypeService +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/mProjectService.js b/deploy/tkfb-package/api.hyungi.net/services/mProjectService.js new file mode 100644 index 0000000..6336621 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/mProjectService.js @@ -0,0 +1,383 @@ +/** + * M-Project API 연동 서비스 + * + * TK-FB-Project의 부적합 신고를 M-Project로 전송하는 서비스 + * + * @author TK-FB-Project + * @since 2026-02-03 + */ + +const logger = require('../utils/logger'); + +// M-Project API 설정 +const M_PROJECT_CONFIG = { + baseUrl: process.env.M_PROJECT_API_URL || 'http://localhost:16080', + username: process.env.M_PROJECT_USERNAME || 'api_service', + password: process.env.M_PROJECT_PASSWORD || '', + defaultProjectId: parseInt(process.env.M_PROJECT_DEFAULT_PROJECT_ID) || 1, +}; + +// 캐시된 인증 토큰 +let cachedToken = null; +let tokenExpiry = null; + +/** + * TK-FB 카테고리를 M-Project 카테고리로 매핑 + * @param {string} tkCategory - TK-FB-Project 카테고리 + * @returns {string} M-Project 카테고리 + */ +function mapCategoryToMProject(tkCategory) { + const categoryMap = { + // TK-FB 카테고리 → M-Project 카테고리 + '자재 누락': 'material_missing', + '자재누락': 'material_missing', + '자재 관련': 'material_missing', + '설계 오류': 'design_error', + '설계미스': 'design_error', + '설계 관련': 'design_error', + '입고 불량': 'incoming_defect', + '입고자재 불량': 'incoming_defect', + '입고 관련': 'incoming_defect', + '검사 미스': 'inspection_miss', + '검사미스': 'inspection_miss', + '검사 관련': 'inspection_miss', + '기타': 'etc', + }; + + // 정확히 매칭되는 경우 + if (categoryMap[tkCategory]) { + return categoryMap[tkCategory]; + } + + // 부분 매칭 시도 + const lowerCategory = tkCategory?.toLowerCase() || ''; + if (lowerCategory.includes('자재') || lowerCategory.includes('material')) { + return 'material_missing'; + } + if (lowerCategory.includes('설계') || lowerCategory.includes('design')) { + return 'design_error'; + } + if (lowerCategory.includes('입고') || lowerCategory.includes('incoming')) { + return 'incoming_defect'; + } + if (lowerCategory.includes('검사') || lowerCategory.includes('inspection')) { + return 'inspection_miss'; + } + + // 기본값 + return 'etc'; +} + +/** + * M-Project API 인증 토큰 획득 + * @returns {Promise} JWT 토큰 + */ +async function getAuthToken() { + // 캐시된 토큰이 유효하면 재사용 + if (cachedToken && tokenExpiry && new Date() < tokenExpiry) { + return cachedToken; + } + + try { + const formData = new URLSearchParams(); + formData.append('username', M_PROJECT_CONFIG.username); + formData.append('password', M_PROJECT_CONFIG.password); + + const response = await fetch(`${M_PROJECT_CONFIG.baseUrl}/api/auth/login`, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: formData.toString(), + }); + + if (!response.ok) { + const errorText = await response.text(); + logger.error('M-Project 인증 실패', { + status: response.status, + error: errorText + }); + return null; + } + + const data = await response.json(); + cachedToken = data.access_token; + + // 토큰 만료 시간 설정 (기본 6일, M-Project는 7일 유효) + tokenExpiry = new Date(Date.now() + 6 * 24 * 60 * 60 * 1000); + + logger.info('M-Project 인증 성공'); + return cachedToken; + } catch (error) { + logger.error('M-Project 인증 요청 오류', { error: error.message }); + return null; + } +} + +/** + * 이미지 URL을 Base64로 변환 + * @param {string} imageUrl - 이미지 URL 또는 경로 + * @returns {Promise} Base64 인코딩된 이미지 + */ +async function convertImageToBase64(imageUrl) { + if (!imageUrl) return null; + + try { + // 이미 Base64인 경우 그대로 반환 + if (imageUrl.startsWith('data:image')) { + return imageUrl; + } + + // URL인 경우 fetch + if (imageUrl.startsWith('http://') || imageUrl.startsWith('https://')) { + const response = await fetch(imageUrl); + if (!response.ok) return null; + + const buffer = await response.arrayBuffer(); + const base64 = Buffer.from(buffer).toString('base64'); + const contentType = response.headers.get('content-type') || 'image/jpeg'; + return `data:${contentType};base64,${base64}`; + } + + // 로컬 파일 경로인 경우 + const fs = require('fs').promises; + const path = require('path'); + const filePath = path.join(process.cwd(), 'uploads', imageUrl); + + try { + const fileBuffer = await fs.readFile(filePath); + const base64 = fileBuffer.toString('base64'); + const ext = path.extname(imageUrl).toLowerCase(); + const mimeTypes = { + '.jpg': 'image/jpeg', + '.jpeg': 'image/jpeg', + '.png': 'image/png', + '.gif': 'image/gif', + '.webp': 'image/webp', + }; + const contentType = mimeTypes[ext] || 'image/jpeg'; + return `data:${contentType};base64,${base64}`; + } catch { + return null; + } + } catch (error) { + logger.warn('이미지 Base64 변환 실패', { imageUrl, error: error.message }); + return null; + } +} + +/** + * TK-FB-Project 부적합 신고를 M-Project로 전송 + * + * @param {Object} issueData - 부적합 신고 데이터 + * @param {string} issueData.category - 카테고리 이름 + * @param {string} issueData.description - 신고 내용 + * @param {string} issueData.reporter_name - 신고자 이름 + * @param {string} issueData.project_name - 프로젝트 이름 (옵션) + * @param {number} issueData.tk_issue_id - TK-FB-Project 이슈 ID + * @param {string[]} issueData.photos - 사진 URL 배열 (최대 5개) + * @returns {Promise<{success: boolean, mProjectId?: number, error?: string}>} + */ +async function sendToMProject(issueData) { + const { + category, + description, + reporter_name, + project_name, + tk_issue_id, + photos = [], + } = issueData; + + logger.info('M-Project 연동 시작', { tk_issue_id, category }); + + // 인증 토큰 획득 + const token = await getAuthToken(); + if (!token) { + return { success: false, error: 'M-Project 인증 실패' }; + } + + try { + // 카테고리 매핑 + const mProjectCategory = mapCategoryToMProject(category); + + // 설명에 TK-FB 정보 추가 + const enhancedDescription = [ + description, + '', + '---', + `[TK-FB-Project 연동]`, + `- 원본 이슈 ID: ${tk_issue_id}`, + `- 신고자: ${reporter_name || '미상'}`, + project_name ? `- 프로젝트: ${project_name}` : null, + ].filter(Boolean).join('\n'); + + // 사진 변환 (최대 5개) + const photoPromises = photos.slice(0, 5).map(convertImageToBase64); + const base64Photos = await Promise.all(photoPromises); + + // 요청 본문 구성 + const requestBody = { + category: mProjectCategory, + description: enhancedDescription, + project_id: M_PROJECT_CONFIG.defaultProjectId, + }; + + // 사진 추가 + base64Photos.forEach((photo, index) => { + if (photo) { + const fieldName = index === 0 ? 'photo' : `photo${index + 1}`; + requestBody[fieldName] = photo; + } + }); + + // M-Project API 호출 + const response = await fetch(`${M_PROJECT_CONFIG.baseUrl}/api/issues`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}`, + }, + body: JSON.stringify(requestBody), + }); + + if (!response.ok) { + const errorText = await response.text(); + logger.error('M-Project 이슈 생성 실패', { + status: response.status, + error: errorText, + tk_issue_id + }); + return { + success: false, + error: `M-Project API 오류: ${response.status}` + }; + } + + const createdIssue = await response.json(); + + logger.info('M-Project 이슈 생성 성공', { + tk_issue_id, + m_project_id: createdIssue.id + }); + + return { + success: true, + mProjectId: createdIssue.id + }; + } catch (error) { + logger.error('M-Project 연동 오류', { + tk_issue_id, + error: error.message + }); + return { + success: false, + error: error.message + }; + } +} + +/** + * M-Project에서 이슈 상태 조회 + * + * @param {number} mProjectId - M-Project 이슈 ID + * @returns {Promise<{success: boolean, status?: string, data?: Object, error?: string}>} + */ +async function getIssueStatus(mProjectId) { + const token = await getAuthToken(); + if (!token) { + return { success: false, error: 'M-Project 인증 실패' }; + } + + try { + const response = await fetch( + `${M_PROJECT_CONFIG.baseUrl}/api/issues/${mProjectId}`, + { + method: 'GET', + headers: { + 'Authorization': `Bearer ${token}`, + }, + } + ); + + if (!response.ok) { + return { + success: false, + error: `M-Project API 오류: ${response.status}` + }; + } + + const data = await response.json(); + + return { + success: true, + status: data.review_status || data.status, + data + }; + } catch (error) { + return { + success: false, + error: error.message + }; + } +} + +/** + * M-Project 상태를 TK-FB 상태로 매핑 + * @param {string} mProjectStatus - M-Project 상태 + * @returns {string} TK-FB-Project 상태 + */ +function mapStatusFromMProject(mProjectStatus) { + const statusMap = { + 'pending_review': 'received', + 'in_progress': 'in_progress', + 'completed': 'completed', + 'disposed': 'closed', + }; + return statusMap[mProjectStatus] || 'received'; +} + +/** + * M-Project 연결 테스트 + * @returns {Promise<{success: boolean, message: string}>} + */ +async function testConnection() { + try { + const token = await getAuthToken(); + if (!token) { + return { success: false, message: 'M-Project 인증 실패' }; + } + + // /api/auth/me로 연결 테스트 + const response = await fetch(`${M_PROJECT_CONFIG.baseUrl}/api/auth/me`, { + headers: { + 'Authorization': `Bearer ${token}`, + }, + }); + + if (response.ok) { + const user = await response.json(); + return { + success: true, + message: `M-Project 연결 성공 (사용자: ${user.username})` + }; + } else { + return { + success: false, + message: `M-Project 연결 실패: ${response.status}` + }; + } + } catch (error) { + return { + success: false, + message: `M-Project 연결 오류: ${error.message}` + }; + } +} + +module.exports = { + sendToMProject, + getIssueStatus, + mapStatusFromMProject, + testConnection, + mapCategoryToMProject, +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/toolsService.js b/deploy/tkfb-package/api.hyungi.net/services/toolsService.js new file mode 100644 index 0000000..bd3718a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/toolsService.js @@ -0,0 +1,171 @@ +/** + * 도구 관리 서비스 + * + * 도구(공구) 재고 및 위치 관리 관련 비즈니스 로직 처리 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const toolsModel = require('../models/toolsModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 전체 도구 조회 + */ +const getAllToolsService = async () => { + logger.info('도구 목록 조회 요청'); + + try { + const rows = await toolsModel.getAll(); + + logger.info('도구 목록 조회 성공', { count: rows.length }); + + return rows; + } catch (error) { + logger.error('도구 목록 조회 실패', { error: error.message }); + throw new DatabaseError('도구 목록 조회 중 오류가 발생했습니다'); + } +}; + +/** + * 단일 도구 조회 + */ +const getToolByIdService = async (id) => { + // ID 검증 + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 도구 ID입니다'); + } + + logger.info('도구 조회 요청', { tool_id: id }); + + try { + const row = await toolsModel.getById(id); + + if (!row) { + logger.warn('도구를 찾을 수 없음', { tool_id: id }); + throw new NotFoundError('도구를 찾을 수 없습니다'); + } + + logger.info('도구 조회 성공', { tool_id: id }); + + return row; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('도구 조회 실패', { tool_id: id, error: error.message }); + throw new DatabaseError('도구 조회 중 오류가 발생했습니다'); + } +}; + +/** + * 도구 생성 + */ +const createToolService = async (toolData) => { + const { name, location, stock, status, factory_id } = toolData; + + // 필수 필드 검증 + if (!name) { + throw new ValidationError('도구 이름이 필요합니다', { + required: ['name'], + received: { name } + }); + } + + logger.info('도구 생성 요청', { name, location, stock, status }); + + try { + const insertId = await toolsModel.create(toolData); + + logger.info('도구 생성 성공', { tool_id: insertId, name }); + + return { tool_id: insertId }; + } catch (error) { + logger.error('도구 생성 실패', { + name, + error: error.message + }); + throw new DatabaseError('도구 생성 중 오류가 발생했습니다'); + } +}; + +/** + * 도구 수정 + */ +const updateToolService = async (id, toolData) => { + // ID 검증 + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 도구 ID입니다'); + } + + logger.info('도구 수정 요청', { tool_id: id, updates: toolData }); + + try { + const affectedRows = await toolsModel.update(id, toolData); + + if (affectedRows === 0) { + logger.warn('도구를 찾을 수 없거나 변경사항 없음', { tool_id: id }); + throw new NotFoundError('도구를 찾을 수 없습니다'); + } + + logger.info('도구 수정 성공', { tool_id: id, affectedRows }); + + return { changes: affectedRows }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('도구 수정 실패', { + tool_id: id, + error: error.message + }); + throw new DatabaseError('도구 수정 중 오류가 발생했습니다'); + } +}; + +/** + * 도구 삭제 + */ +const deleteToolService = async (id) => { + // ID 검증 + if (!id || isNaN(id)) { + throw new ValidationError('유효하지 않은 도구 ID입니다'); + } + + logger.info('도구 삭제 요청', { tool_id: id }); + + try { + const affectedRows = await toolsModel.remove(id); + + if (affectedRows === 0) { + logger.warn('도구를 찾을 수 없음', { tool_id: id }); + throw new NotFoundError('도구를 찾을 수 없습니다'); + } + + logger.info('도구 삭제 성공', { tool_id: id, affectedRows }); + + return { changes: affectedRows }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('도구 삭제 실패', { + tool_id: id, + error: error.message + }); + throw new DatabaseError('도구 삭제 중 오류가 발생했습니다'); + } +}; + +module.exports = { + getAllToolsService, + getToolByIdService, + createToolService, + updateToolService, + deleteToolService +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/uploadService.js b/deploy/tkfb-package/api.hyungi.net/services/uploadService.js new file mode 100644 index 0000000..89951cc --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/uploadService.js @@ -0,0 +1,96 @@ +/** + * 문서 업로드 관리 서비스 + * + * 파일 업로드 및 문서 메타데이터 관리 관련 비즈니스 로직 처리 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const uploadModel = require('../models/uploadModel'); +const { ValidationError, DatabaseError } = require('../utils/errors'); +const logger = require('../utils/logger'); + +/** + * 문서 업로드 생성 + */ +const createUploadService = async (uploadData) => { + const { + title, + tags, + description, + original_name, + stored_name, + file_path, + file_type, + file_size, + submitted_by + } = uploadData; + + // 필수 필드 검증 + if (!original_name || !stored_name || !file_path) { + throw new ValidationError('필수 필드가 누락되었습니다', { + required: ['original_name', 'stored_name', 'file_path'], + received: { original_name, stored_name, file_path } + }); + } + + logger.info('문서 업로드 생성 요청', { + title, + original_name, + file_type, + file_size, + submitted_by + }); + + try { + const insertId = await new Promise((resolve, reject) => { + uploadModel.create(uploadData, (err, id) => { + if (err) reject(err); + else resolve(id); + }); + }); + + logger.info('문서 업로드 생성 성공', { + upload_id: insertId, + original_name, + file_size + }); + + return { upload_id: insertId }; + } catch (error) { + logger.error('문서 업로드 생성 실패', { + original_name, + error: error.message + }); + throw new DatabaseError('문서 업로드 생성 중 오류가 발생했습니다'); + } +}; + +/** + * 전체 업로드 문서 조회 + */ +const getAllUploadsService = async () => { + logger.info('업로드 문서 목록 조회 요청'); + + try { + const rows = await new Promise((resolve, reject) => { + uploadModel.getAll((err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + logger.info('업로드 문서 목록 조회 성공', { count: rows.length }); + + return rows; + } catch (error) { + logger.error('업로드 문서 목록 조회 실패', { error: error.message }); + throw new DatabaseError('업로드 문서 목록 조회 중 오류가 발생했습니다'); + } +}; + +module.exports = { + createUploadService, + getAllUploadsService +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/weatherService.js b/deploy/tkfb-package/api.hyungi.net/services/weatherService.js new file mode 100644 index 0000000..7b7d2a7 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/weatherService.js @@ -0,0 +1,435 @@ +/** + * 날씨 API 서비스 + * + * 기상청 단기예보 API를 사용하여 현재 날씨 정보를 조회 + * 날씨 조건에 따른 안전 체크리스트 필터링 지원 + * + * @since 2026-02-02 + */ + +const axios = require('axios'); +const logger = require('../utils/logger'); +const { getDb } = require('../dbPool'); + +// 기상청 API 설정 +const WEATHER_BASE_URL = process.env.WEATHER_API_URL || 'https://apis.data.go.kr/1360000/VilageFcstInfoService_2.0'; +const WEATHER_API = { + baseUrl: WEATHER_BASE_URL, + ultraShortUrl: `${WEATHER_BASE_URL}/getUltraSrtNcst`, + shortForecastUrl: `${WEATHER_BASE_URL}/getVilageFcst`, + apiKey: process.env.WEATHER_API_KEY || '', + // 화성시 남양읍 좌표 (격자 좌표) + // 위도: 37.2072, 경도: 126.8232 + defaultLocation: { + nx: 57, // 화성시 남양읍 X 좌표 + ny: 119 // 화성시 남양읍 Y 좌표 + } +}; + +// PTY (강수형태) 코드 +const PTY_CODES = { + 0: 'none', // 없음 + 1: 'rain', // 비 + 2: 'rain', // 비/눈 (혼합) + 3: 'snow', // 눈 + 4: 'rain', // 소나기 + 5: 'rain', // 빗방울 + 6: 'rain', // 빗방울/눈날림 + 7: 'snow' // 눈날림 +}; + +// SKY (하늘상태) 코드 +const SKY_CODES = { + 1: 'clear', // 맑음 + 3: 'cloudy', // 구름많음 + 4: 'overcast' // 흐림 +}; + +/** + * 현재 날씨 정보 조회 (초단기실황) + * @param {number} nx - 격자 X 좌표 (optional) + * @param {number} ny - 격자 Y 좌표 (optional) + * @returns {Promise} 날씨 데이터 + */ +async function getCurrentWeather(nx = WEATHER_API.defaultLocation.nx, ny = WEATHER_API.defaultLocation.ny) { + if (!WEATHER_API.apiKey) { + logger.warn('날씨 API 키가 설정되지 않음. 기본값 반환'); + return getDefaultWeatherData(); + } + + try { + // 한국 시간 기준으로 base_date, base_time 계산 + const { baseDate, baseTime } = getBaseDateTime(); + + logger.info('날씨 API 호출', { baseDate, baseTime, nx, ny }); + + // Encoding 키는 이미 URL 인코딩되어 있으므로 직접 URL에 추가 (이중 인코딩 방지) + const url = `${WEATHER_API.ultraShortUrl}?serviceKey=${WEATHER_API.apiKey}` + + `&pageNo=1&numOfRows=10&dataType=JSON` + + `&base_date=${baseDate}&base_time=${baseTime}` + + `&nx=${nx}&ny=${ny}`; + + const response = await axios.get(url, { timeout: 5000 }); + + if (response.data?.response?.header?.resultCode !== '00') { + throw new Error(`API 오류: ${response.data?.response?.header?.resultMsg}`); + } + + const items = response.data.response.body.items.item; + const weatherData = parseWeatherItems(items); + + logger.info('날씨 데이터 파싱 완료', weatherData); + + return weatherData; + } catch (error) { + logger.error('날씨 API 호출 실패', { error: error.message }); + return getDefaultWeatherData(); + } +} + +/** + * 날씨 API 응답 파싱 + */ +function parseWeatherItems(items) { + const data = { + temperature: null, + humidity: null, + windSpeed: null, + precipitation: null, + precipitationType: null, + skyCondition: null + }; + + if (!items || !Array.isArray(items)) { + return data; + } + + items.forEach(item => { + switch (item.category) { + case 'T1H': // 기온 + data.temperature = parseFloat(item.obsrValue); + break; + case 'REH': // 습도 + data.humidity = parseInt(item.obsrValue); + break; + case 'WSD': // 풍속 + data.windSpeed = parseFloat(item.obsrValue); + break; + case 'RN1': // 1시간 강수량 + data.precipitation = parseFloat(item.obsrValue) || 0; + break; + case 'PTY': // 강수형태 + data.precipitationType = parseInt(item.obsrValue); + break; + } + }); + + return data; +} + +/** + * 날씨 데이터를 기반으로 조건 판단 + * @param {Object} weatherData - 날씨 데이터 + * @returns {Promise} 해당하는 날씨 조건 코드 배열 + */ +async function determineWeatherConditions(weatherData) { + const conditions = []; + + // DB에서 날씨 조건 기준 조회 + const db = await getDb(); + const [thresholds] = await db.execute(` + SELECT condition_code, temp_threshold_min, temp_threshold_max, + wind_threshold, precip_threshold + FROM weather_conditions + WHERE is_active = TRUE + `); + + // 조건 판단 + thresholds.forEach(threshold => { + let matches = false; + + switch (threshold.condition_code) { + case 'rain': + // 강수형태가 비(1,2,4,5,6) 또는 강수량 > 0 + if (weatherData.precipitationType && PTY_CODES[weatherData.precipitationType] === 'rain') { + matches = true; + } else if (weatherData.precipitation > 0 && threshold.precip_threshold !== null) { + matches = weatherData.precipitation >= threshold.precip_threshold; + } + break; + + case 'snow': + // 강수형태가 눈(3,7) + if (weatherData.precipitationType && PTY_CODES[weatherData.precipitationType] === 'snow') { + matches = true; + } + break; + + case 'heat': + // 기온이 폭염 기준 이상 + if (weatherData.temperature !== null && threshold.temp_threshold_min !== null) { + matches = weatherData.temperature >= threshold.temp_threshold_min; + } + break; + + case 'cold': + // 기온이 한파 기준 이하 + if (weatherData.temperature !== null && threshold.temp_threshold_max !== null) { + matches = weatherData.temperature <= threshold.temp_threshold_max; + } + break; + + case 'wind': + // 풍속이 강풍 기준 이상 + if (weatherData.windSpeed !== null && threshold.wind_threshold !== null) { + matches = weatherData.windSpeed >= threshold.wind_threshold; + } + break; + + case 'clear': + // 강수 없고 기온이 정상 범위 + if (!weatherData.precipitationType || weatherData.precipitationType === 0) { + if (weatherData.temperature !== null && + weatherData.temperature > -10 && weatherData.temperature < 35) { + matches = true; + } + } + break; + } + + if (matches) { + conditions.push(threshold.condition_code); + } + }); + + // 조건이 없으면 기본으로 'clear' 추가 + if (conditions.length === 0) { + conditions.push('clear'); + } + + logger.info('날씨 조건 판단 완료', { weatherData, conditions }); + + return conditions; +} + +/** + * TBM 세션에 날씨 정보 저장 + * @param {number} sessionId - TBM 세션 ID + * @param {Object} weatherData - 날씨 데이터 + * @param {string[]} conditions - 날씨 조건 배열 + */ +async function saveWeatherRecord(sessionId, weatherData, conditions) { + const db = await getDb(); + + try { + const weatherDate = new Date().toISOString().split('T')[0]; + + await db.execute(` + INSERT INTO tbm_weather_records + (session_id, weather_date, temperature, humidity, wind_speed, precipitation, + weather_condition, weather_conditions, data_source, fetched_at) + VALUES (?, ?, ?, ?, ?, ?, ?, ?, 'api', NOW()) + ON DUPLICATE KEY UPDATE + temperature = VALUES(temperature), + humidity = VALUES(humidity), + wind_speed = VALUES(wind_speed), + precipitation = VALUES(precipitation), + weather_condition = VALUES(weather_condition), + weather_conditions = VALUES(weather_conditions), + fetched_at = NOW() + `, [ + sessionId, + weatherDate, + weatherData.temperature, + weatherData.humidity, + weatherData.windSpeed, + weatherData.precipitation, + conditions[0] || 'clear', // 주요 조건 + JSON.stringify(conditions) // 모든 조건 + ]); + + logger.info('날씨 기록 저장 완료', { sessionId, conditions }); + return { success: true }; + } catch (error) { + logger.error('날씨 기록 저장 실패', { sessionId, error: error.message }); + throw error; + } +} + +/** + * TBM 세션의 날씨 기록 조회 + * @param {number} sessionId - TBM 세션 ID + */ +async function getWeatherRecord(sessionId) { + const db = await getDb(); + + const [rows] = await db.execute(` + SELECT wr.*, wc.condition_name, wc.icon + FROM tbm_weather_records wr + LEFT JOIN weather_conditions wc ON wr.weather_condition = wc.condition_code + WHERE wr.session_id = ? + `, [sessionId]); + + if (rows.length === 0) { + return null; + } + + const record = rows[0]; + // JSON 문자열 파싱 + if (record.weather_conditions && typeof record.weather_conditions === 'string') { + try { + record.weather_conditions = JSON.parse(record.weather_conditions); + } catch (e) { + record.weather_conditions = []; + } + } + + return record; +} + +/** + * 날씨 조건 코드 목록 조회 + */ +async function getWeatherConditionList() { + const db = await getDb(); + + const [rows] = await db.execute(` + SELECT condition_code, condition_name, description, icon, + temp_threshold_min, temp_threshold_max, wind_threshold, precip_threshold + FROM weather_conditions + WHERE is_active = TRUE + ORDER BY display_order + `); + + return rows; +} + +/** + * 기본 날씨 데이터 반환 (API 실패 시) + */ +function getDefaultWeatherData() { + return { + temperature: 20, + humidity: 50, + windSpeed: 2, + precipitation: 0, + precipitationType: 0, + skyCondition: 'clear', + isDefault: true + }; +} + +/** + * 기상청 API용 기준 날짜/시간 계산 + * 한국 시간(KST, UTC+9) 기준으로 계산 + * 매시간 정각에 생성되고 10분 후에 제공됨 + * @returns {{ baseDate: string, baseTime: string }} + */ +function getBaseDateTime() { + // 한국 시간으로 변환 (UTC + 9시간) + const now = new Date(); + const kstOffset = 9 * 60 * 60 * 1000; // 9시간을 밀리초로 + const kstDate = new Date(now.getTime() + kstOffset); + + let year = kstDate.getUTCFullYear(); + let month = kstDate.getUTCMonth() + 1; + let day = kstDate.getUTCDate(); + let hours = kstDate.getUTCHours(); + let minutes = kstDate.getUTCMinutes(); + + // 10분 이전이면 이전 시간 데이터 사용 + if (minutes < 10) { + hours = hours - 1; + if (hours < 0) { + hours = 23; + // 전날로 변경 + const prevDay = new Date(kstDate.getTime() - 24 * 60 * 60 * 1000); + year = prevDay.getUTCFullYear(); + month = prevDay.getUTCMonth() + 1; + day = prevDay.getUTCDate(); + } + } + + const baseDate = `${year}${String(month).padStart(2, '0')}${String(day).padStart(2, '0')}`; + const baseTime = String(hours).padStart(2, '0') + '00'; + + return { baseDate, baseTime }; +} + +/** + * 날짜 포맷 (YYYYMMDD) - 호환성 유지용 + * @deprecated getBaseDateTime() 사용 권장 + */ +function formatDate(date) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}${month}${day}`; +} + +/** + * @deprecated getBaseDateTime() 사용 권장 + */ +function getBaseTime(date) { + let hours = date.getHours(); + let minutes = date.getMinutes(); + + if (minutes < 10) { + hours = hours - 1; + if (hours < 0) hours = 23; + } + + return String(hours).padStart(2, '0') + '00'; +} + +/** + * 위경도를 기상청 격자 좌표로 변환 + * LCC (Lambert Conformal Conic) 투영법 사용 + */ +function convertToGrid(lat, lon) { + const RE = 6371.00877; // 지구 반경(km) + const GRID = 5.0; // 격자 간격(km) + const SLAT1 = 30.0; // 투영 위도1(degree) + const SLAT2 = 60.0; // 투영 위도2(degree) + const OLON = 126.0; // 기준점 경도(degree) + const OLAT = 38.0; // 기준점 위도(degree) + const XO = 43; // 기준점 X좌표(GRID) + const YO = 136; // 기준점 Y좌표(GRID) + + const DEGRAD = Math.PI / 180.0; + + const re = RE / GRID; + const slat1 = SLAT1 * DEGRAD; + const slat2 = SLAT2 * DEGRAD; + const olon = OLON * DEGRAD; + const olat = OLAT * DEGRAD; + + let sn = Math.tan(Math.PI * 0.25 + slat2 * 0.5) / Math.tan(Math.PI * 0.25 + slat1 * 0.5); + sn = Math.log(Math.cos(slat1) / Math.cos(slat2)) / Math.log(sn); + let sf = Math.tan(Math.PI * 0.25 + slat1 * 0.5); + sf = Math.pow(sf, sn) * Math.cos(slat1) / sn; + let ro = Math.tan(Math.PI * 0.25 + olat * 0.5); + ro = re * sf / Math.pow(ro, sn); + + let ra = Math.tan(Math.PI * 0.25 + lat * DEGRAD * 0.5); + ra = re * sf / Math.pow(ra, sn); + let theta = lon * DEGRAD - olon; + if (theta > Math.PI) theta -= 2.0 * Math.PI; + if (theta < -Math.PI) theta += 2.0 * Math.PI; + theta *= sn; + + const x = Math.floor(ra * Math.sin(theta) + XO + 0.5); + const y = Math.floor(ro - ra * Math.cos(theta) + YO + 0.5); + + return { nx: x, ny: y }; +} + +module.exports = { + getCurrentWeather, + determineWeatherConditions, + saveWeatherRecord, + getWeatherRecord, + getWeatherConditionList, + convertToGrid, + getDefaultWeatherData +}; diff --git a/deploy/tkfb-package/api.hyungi.net/services/workAnalysisService.js b/deploy/tkfb-package/api.hyungi.net/services/workAnalysisService.js new file mode 100644 index 0000000..c080719 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/workAnalysisService.js @@ -0,0 +1,109 @@ +/** + * Work Analysis Service + * + * Handles complex business logic and data aggregation for detailed work analysis reports + * + * @author TK-FB-Project + * @since 2025-12-19 + */ + +const { getDb } = require('../dbPool'); +const WorkAnalysis = require('../models/WorkAnalysis'); +const logger = require('../utils/logger'); +const { DatabaseError } = require('../utils/errors'); + +class WorkAnalysisService { + constructor() { + this.db = null; + this.model = null; + } + + async init() { + if (!this.db) { + this.db = await getDb(); + this.model = new WorkAnalysis(this.db); + } + } + + /** + * 프로젝트별-작업별 시간 분석 및 집계 (Service Layer logic) + */ + async getProjectWorkTypeAnalysis(startDate, endDate) { + await this.init(); + + try { + // 1. Get Raw Data from Model + const rawData = await this.model.getProjectWorkTypeRawData(startDate, endDate); + + // 2. Process and Group Data + const groupedData = {}; + + rawData.forEach(row => { + const projectKey = `${row.project_id}_${row.project_name}`; + + if (!groupedData[projectKey]) { + groupedData[projectKey] = { + project_id: row.project_id, + project_name: row.project_name, + job_no: row.job_no, + total_project_hours: 0, + total_regular_hours: 0, + total_error_hours: 0, + work_types: [] + }; + } + + // Project Totals Accumulation + groupedData[projectKey].total_project_hours += parseFloat(row.total_hours); + groupedData[projectKey].total_regular_hours += parseFloat(row.regular_hours); + groupedData[projectKey].total_error_hours += parseFloat(row.error_hours); + + // Add WorkType Entry + groupedData[projectKey].work_types.push({ + work_type_id: row.work_type_id, + work_type_name: row.work_type_name, + total_hours: parseFloat(row.total_hours), + regular_hours: parseFloat(row.regular_hours), + error_hours: parseFloat(row.error_hours), + total_reports: row.total_reports, + regular_reports: row.regular_reports, + error_reports: row.error_reports, + error_rate_percent: parseFloat(row.error_rate_percent) || 0 + }); + }); + + // 3. Calculate Project Error Rates + Object.values(groupedData).forEach(project => { + project.project_error_rate = project.total_project_hours > 0 + ? Math.round((project.total_error_hours / project.total_project_hours) * 100 * 100) / 100 + : 0; + }); + + // 4. Calculate Grand Totals + const totalStats = { + total_projects: Object.keys(groupedData).length, + total_work_types: new Set(rawData.map(r => r.work_type_id)).size, + grand_total_hours: Object.values(groupedData).reduce((sum, p) => sum + p.total_project_hours, 0), + grand_regular_hours: Object.values(groupedData).reduce((sum, p) => sum + p.total_regular_hours, 0), + grand_error_hours: Object.values(groupedData).reduce((sum, p) => sum + p.total_error_hours, 0) + }; + + totalStats.grand_error_rate = totalStats.grand_total_hours > 0 + ? Math.round((totalStats.grand_error_hours / totalStats.grand_total_hours) * 100 * 100) / 100 + : 0; + + return { + summary: totalStats, + projects: Object.values(groupedData), + period: { start: startDate, end: endDate } + }; + + } catch (error) { + logger.error('Service: 프로젝트별-작업별 시간 분석 처리 실패', { error: error.message }); + // Re-throw as DatabaseError to maintain consistency with controller expectation, or custom ServiceError + throw new DatabaseError(`분석 데이터 처리 중 오류 발생: ${error.message}`); + } + } +} + +module.exports = new WorkAnalysisService(); diff --git a/deploy/tkfb-package/api.hyungi.net/services/workReportService.js b/deploy/tkfb-package/api.hyungi.net/services/workReportService.js new file mode 100644 index 0000000..f1b0daf --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/services/workReportService.js @@ -0,0 +1,488 @@ +/** + * 작업 보고서 관리 서비스 + * + * 작업 보고서 CRUD 및 조회 관련 비즈니스 로직 처리 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const workReportModel = require('../models/workReportModel'); +const { ValidationError, NotFoundError, DatabaseError } = require('../utils/errors'); +const logger = require('../utils/logger'); +const { getDb } = require('../dbPool'); + +/** + * 작업 보고서 생성 (단일 또는 다중) + */ +const createWorkReportService = async (reportData) => { + const reports = Array.isArray(reportData) ? reportData : [reportData]; + + if (reports.length === 0) { + throw new ValidationError('보고서 데이터가 필요합니다'); + } + + logger.info('작업 보고서 생성 요청', { count: reports.length }); + + const workReport_ids = []; + + try { + for (const report of reports) { + const id = await new Promise((resolve, reject) => { + workReportModel.create(report, (err, insertId) => { + if (err) reject(err); + else resolve(insertId); + }); + }); + workReport_ids.push(id); + } + + logger.info('작업 보고서 생성 성공', { + count: workReport_ids.length, + ids: workReport_ids + }); + + return { workReport_ids }; + } catch (error) { + logger.error('작업 보고서 생성 실패', { + count: reports.length, + error: error.message + }); + throw new DatabaseError('작업 보고서 생성 중 오류가 발생했습니다'); + } +}; + +/** + * 날짜별 작업 보고서 조회 + */ +const getWorkReportsByDateService = async (date) => { + if (!date) { + throw new ValidationError('날짜가 필요합니다', { + required: ['date'], + received: { date } + }); + } + + logger.info('작업 보고서 날짜별 조회 요청', { date }); + + try { + const rows = await new Promise((resolve, reject) => { + workReportModel.getAllByDate(date, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + logger.info('작업 보고서 조회 성공', { date, count: rows.length }); + + return rows; + } catch (error) { + logger.error('작업 보고서 조회 실패', { date, error: error.message }); + throw new DatabaseError('작업 보고서 조회 중 오류가 발생했습니다'); + } +}; + +/** + * 기간별 작업 보고서 조회 + */ +const getWorkReportsInRangeService = async (start, end) => { + if (!start || !end) { + throw new ValidationError('시작일과 종료일이 필요합니다', { + required: ['start', 'end'], + received: { start, end } + }); + } + + logger.info('작업 보고서 기간별 조회 요청', { start, end }); + + try { + const rows = await new Promise((resolve, reject) => { + workReportModel.getByRange(start, end, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + logger.info('작업 보고서 조회 성공', { start, end, count: rows.length }); + + return rows; + } catch (error) { + logger.error('작업 보고서 조회 실패', { start, end, error: error.message }); + throw new DatabaseError('작업 보고서 조회 중 오류가 발생했습니다'); + } +}; + +/** + * 단일 작업 보고서 조회 + */ +const getWorkReportByIdService = async (id) => { + if (!id) { + throw new ValidationError('보고서 ID가 필요합니다'); + } + + logger.info('작업 보고서 조회 요청', { report_id: id }); + + try { + const row = await new Promise((resolve, reject) => { + workReportModel.getById(id, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + if (!row) { + logger.warn('작업 보고서를 찾을 수 없음', { report_id: id }); + throw new NotFoundError('작업 보고서를 찾을 수 없습니다'); + } + + logger.info('작업 보고서 조회 성공', { report_id: id }); + + return row; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('작업 보고서 조회 실패', { report_id: id, error: error.message }); + throw new DatabaseError('작업 보고서 조회 중 오류가 발생했습니다'); + } +}; + +/** + * 작업 보고서 수정 + */ +const updateWorkReportService = async (id, updateData) => { + if (!id) { + throw new ValidationError('보고서 ID가 필요합니다'); + } + + logger.info('작업 보고서 수정 요청', { report_id: id }); + + try { + const changes = await new Promise((resolve, reject) => { + workReportModel.update(id, updateData, (err, affectedRows) => { + if (err) reject(err); + else resolve(affectedRows); + }); + }); + + if (changes === 0) { + logger.warn('작업 보고서를 찾을 수 없거나 변경사항 없음', { report_id: id }); + throw new NotFoundError('작업 보고서를 찾을 수 없습니다'); + } + + logger.info('작업 보고서 수정 성공', { report_id: id, changes }); + + return { changes }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('작업 보고서 수정 실패', { report_id: id, error: error.message }); + throw new DatabaseError('작업 보고서 수정 중 오류가 발생했습니다'); + } +}; + +/** + * 작업 보고서 삭제 + */ +const removeWorkReportService = async (id) => { + if (!id) { + throw new ValidationError('보고서 ID가 필요합니다'); + } + + logger.info('작업 보고서 삭제 요청', { report_id: id }); + + try { + const changes = await new Promise((resolve, reject) => { + workReportModel.remove(id, (err, affectedRows) => { + if (err) reject(err); + else resolve(affectedRows); + }); + }); + + if (changes === 0) { + logger.warn('작업 보고서를 찾을 수 없음', { report_id: id }); + throw new NotFoundError('작업 보고서를 찾을 수 없습니다'); + } + + logger.info('작업 보고서 삭제 성공', { report_id: id, changes }); + + return { changes }; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('작업 보고서 삭제 실패', { report_id: id, error: error.message }); + throw new DatabaseError('작업 보고서 삭제 중 오류가 발생했습니다'); + } +}; + +/** + * 월간 요약 조회 + */ +const getSummaryService = async (year, month) => { + if (!year || !month) { + throw new ValidationError('연도와 월이 필요합니다', { + required: ['year', 'month'], + received: { year, month } + }); + } + + const start = `${year.padStart(4, '0')}-${month.padStart(2, '0')}-01`; + const end = `${year.padStart(4, '0')}-${month.padStart(2, '0')}-31`; + + logger.info('작업 보고서 월간 요약 조회 요청', { year, month, start, end }); + + try { + const rows = await new Promise((resolve, reject) => { + workReportModel.getByRange(start, end, (err, data) => { + if (err) reject(err); + else resolve(data); + }); + }); + + if (!rows || rows.length === 0) { + logger.warn('월간 요약 데이터 없음', { year, month }); + throw new NotFoundError('해당 기간의 작업 보고서가 없습니다'); + } + + logger.info('작업 보고서 월간 요약 조회 성공', { + year, + month, + count: rows.length + }); + + return rows; + } catch (error) { + if (error instanceof NotFoundError) { + throw error; + } + + logger.error('작업 보고서 월간 요약 조회 실패', { + year, + month, + error: error.message + }); + throw new DatabaseError('월간 요약 조회 중 오류가 발생했습니다'); + } +}; + +// ========== 부적합 원인 관리 서비스 ========== + +/** + * 작업 보고서의 부적합 원인 목록 조회 + * - error_type_id 또는 issue_report_id 중 하나로 연결 + */ +const getReportDefectsService = async (reportId) => { + const db = await getDb(); + try { + const [rows] = await db.execute(` + SELECT + d.defect_id, + d.report_id, + d.error_type_id, + d.issue_report_id, + d.defect_hours, + d.note, + d.created_at, + et.name as error_type_name, + et.severity as error_severity, + ir.content as issue_content, + ir.status as issue_status, + irc.category_name as issue_category_name, + irc.severity as issue_severity, + iri.item_name as issue_item_name + FROM work_report_defects d + LEFT JOIN error_types et ON d.error_type_id = et.id + LEFT JOIN work_issue_reports ir ON d.issue_report_id = ir.report_id + LEFT JOIN issue_report_categories irc ON ir.category_id = irc.category_id + LEFT JOIN issue_report_items iri ON ir.item_id = iri.item_id + WHERE d.report_id = ? + ORDER BY d.created_at + `, [reportId]); + + return rows; + } catch (error) { + logger.error('부적합 원인 조회 실패', { reportId, error: error.message }); + throw new DatabaseError('부적합 원인 조회 중 오류가 발생했습니다'); + } +}; + +/** + * 부적합 원인 저장 (전체 교체) + * - error_type_id 또는 issue_report_id 중 하나 사용 가능 + * - issue_report_id: 신고된 이슈와 연결 + * - error_type_id: 기존 오류 유형 (레거시) + */ +const saveReportDefectsService = async (reportId, defects) => { + const db = await getDb(); + try { + await db.query('START TRANSACTION'); + + // 기존 부적합 원인 삭제 + await db.execute('DELETE FROM work_report_defects WHERE report_id = ?', [reportId]); + + // 새 부적합 원인 추가 + if (defects && defects.length > 0) { + for (const defect of defects) { + // issue_report_id > category_id/item_id > error_type_id 순으로 우선 + await db.execute(` + INSERT INTO work_report_defects (report_id, error_type_id, issue_report_id, category_id, item_id, defect_hours, note) + VALUES (?, ?, ?, ?, ?, ?, ?) + `, [ + reportId, + (defect.issue_report_id || defect.category_id) ? null : (defect.error_type_id || null), + defect.issue_report_id || null, + defect.category_id || null, + defect.item_id || null, + defect.defect_hours || 0, + defect.note || null + ]); + } + } + + // 총 부적합 시간 계산 및 daily_work_reports 업데이트 + const totalErrorHours = defects + ? defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0) + : 0; + + // 첫 번째 defect의 error_type_id를 대표값으로 (레거시 호환) + const firstErrorTypeId = defects && defects.length > 0 + ? (defects.find(d => d.error_type_id)?.error_type_id || null) + : null; + + await db.execute(` + UPDATE daily_work_reports + SET error_hours = ?, + error_type_id = ?, + work_status_id = ? + WHERE id = ? + `, [ + totalErrorHours, + firstErrorTypeId, + totalErrorHours > 0 ? 2 : 1, + reportId + ]); + + await db.query('COMMIT'); + + logger.info('부적합 원인 저장 성공', { reportId, count: defects?.length || 0 }); + return { success: true, count: defects?.length || 0, totalErrorHours }; + } catch (error) { + await db.query('ROLLBACK'); + logger.error('부적합 원인 저장 실패', { reportId, error: error.message }); + throw new DatabaseError('부적합 원인 저장 중 오류가 발생했습니다'); + } +}; + +/** + * 부적합 원인 추가 (단일) + * - issue_report_id 또는 error_type_id 중 하나 사용 + */ +const addReportDefectService = async (reportId, defectData) => { + const db = await getDb(); + try { + const [result] = await db.execute(` + INSERT INTO work_report_defects (report_id, error_type_id, issue_report_id, defect_hours, note) + VALUES (?, ?, ?, ?, ?) + `, [ + reportId, + defectData.issue_report_id ? null : (defectData.error_type_id || null), + defectData.issue_report_id || null, + defectData.defect_hours || 0, + defectData.note || null + ]); + + // 총 부적합 시간 업데이트 + await updateTotalErrorHours(reportId); + + logger.info('부적합 원인 추가 성공', { reportId, defectId: result.insertId }); + return { success: true, defect_id: result.insertId }; + } catch (error) { + logger.error('부적합 원인 추가 실패', { reportId, error: error.message }); + throw new DatabaseError('부적합 원인 추가 중 오류가 발생했습니다'); + } +}; + +/** + * 부적합 원인 삭제 + */ +const removeReportDefectService = async (defectId) => { + const db = await getDb(); + try { + // report_id 먼저 조회 + const [defect] = await db.execute('SELECT report_id FROM work_report_defects WHERE defect_id = ?', [defectId]); + if (defect.length === 0) { + throw new NotFoundError('부적합 원인을 찾을 수 없습니다'); + } + + const reportId = defect[0].report_id; + + // 삭제 + await db.execute('DELETE FROM work_report_defects WHERE defect_id = ?', [defectId]); + + // 총 부적합 시간 업데이트 + await updateTotalErrorHours(reportId); + + logger.info('부적합 원인 삭제 성공', { defectId, reportId }); + return { success: true }; + } catch (error) { + if (error instanceof NotFoundError) throw error; + logger.error('부적합 원인 삭제 실패', { defectId, error: error.message }); + throw new DatabaseError('부적합 원인 삭제 중 오류가 발생했습니다'); + } +}; + +/** + * 총 부적합 시간 업데이트 헬퍼 + * - issue_report_id가 있는 경우도 고려 + */ +const updateTotalErrorHours = async (reportId) => { + const db = await getDb(); + const [result] = await db.execute(` + SELECT COALESCE(SUM(defect_hours), 0) as total + FROM work_report_defects + WHERE report_id = ? + `, [reportId]); + + const totalErrorHours = result[0].total || 0; + + // 첫 번째 부적합 원인의 error_type_id를 대표값으로 사용 (레거시 호환) + // issue_report_id만 있는 경우 error_type_id는 null + const [firstDefect] = await db.execute(` + SELECT error_type_id FROM work_report_defects + WHERE report_id = ? AND error_type_id IS NOT NULL + ORDER BY created_at LIMIT 1 + `, [reportId]); + + await db.execute(` + UPDATE daily_work_reports + SET error_hours = ?, + error_type_id = ?, + work_status_id = ? + WHERE id = ? + `, [ + totalErrorHours, + firstDefect.length > 0 ? firstDefect[0].error_type_id : null, + totalErrorHours > 0 ? 2 : 1, + reportId + ]); +}; + +module.exports = { + createWorkReportService, + getWorkReportsByDateService, + getWorkReportsInRangeService, + getWorkReportByIdService, + updateWorkReportService, + removeWorkReportService, + getSummaryService, + // 부적합 원인 관리 + getReportDefectsService, + saveReportDefectsService, + addReportDefectService, + removeReportDefectService +}; diff --git a/deploy/tkfb-package/api.hyungi.net/setup-attendance-db.js b/deploy/tkfb-package/api.hyungi.net/setup-attendance-db.js new file mode 100644 index 0000000..284124a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/setup-attendance-db.js @@ -0,0 +1,177 @@ +const { getDb } = require('./dbPool'); +const fs = require('fs'); +const path = require('path'); + +async function setupAttendanceDB() { + try { + console.log('🚀 근태 관리 DB 설정 시작...'); + + const db = await getDb(); + + // 1. 근로 유형 테이블 생성 + console.log('📋 근로 유형 테이블 생성 중...'); + await db.execute(` + CREATE TABLE IF NOT EXISTS work_attendance_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + type_code VARCHAR(20) NOT NULL UNIQUE COMMENT '근로 유형 코드', + type_name VARCHAR(50) NOT NULL COMMENT '근로 유형명', + description TEXT COMMENT '설명', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) COMMENT='근로 유형 관리 테이블' + `); + + // 2. 휴가 유형 테이블 생성 + console.log('🏖️ 휴가 유형 테이블 생성 중...'); + await db.execute(` + CREATE TABLE IF NOT EXISTS vacation_types ( + id INT PRIMARY KEY AUTO_INCREMENT, + type_code VARCHAR(20) NOT NULL UNIQUE COMMENT '휴가 유형 코드', + type_name VARCHAR(50) NOT NULL COMMENT '휴가 유형명', + hours_deduction DECIMAL(4,2) NOT NULL COMMENT '차감 시간', + description TEXT COMMENT '설명', + is_active BOOLEAN DEFAULT TRUE COMMENT '활성 상태', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP + ) COMMENT='휴가 유형 관리 테이블' + `); + + // 3. 일일 근태 기록 테이블 생성 + console.log('📊 일일 근태 기록 테이블 생성 중...'); + await db.execute(` + CREATE TABLE IF NOT EXISTS daily_attendance_records ( + id INT PRIMARY KEY AUTO_INCREMENT, + record_date DATE NOT NULL COMMENT '기록 날짜', + worker_id INT NOT NULL COMMENT '작업자 ID', + total_work_hours DECIMAL(4,2) DEFAULT 0 COMMENT '총 작업 시간', + attendance_type_id INT COMMENT '근로 유형 ID', + vacation_type_id INT NULL COMMENT '휴가 유형 ID', + is_vacation_processed BOOLEAN DEFAULT FALSE COMMENT '휴가 처리 여부', + overtime_approved BOOLEAN DEFAULT FALSE COMMENT '초과근무 승인 여부', + overtime_approved_by INT NULL COMMENT '초과근무 승인자 ID', + overtime_approved_at TIMESTAMP NULL COMMENT '초과근무 승인 시간', + status ENUM('incomplete', 'partial', 'complete', 'overtime', 'vacation', 'error') DEFAULT 'incomplete' COMMENT '상태', + notes TEXT COMMENT '비고', + created_by INT NOT NULL COMMENT '생성자 ID', + updated_by INT NULL COMMENT '수정자 ID', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE KEY unique_worker_date (worker_id, record_date), + INDEX idx_record_date (record_date), + INDEX idx_worker_date (worker_id, record_date), + INDEX idx_status (status) + ) COMMENT='일일 근태 기록 테이블' + `); + + // 4. 작업자 휴가 잔여 관리 테이블 생성 + console.log('📅 휴가 잔여 관리 테이블 생성 중...'); + await db.execute(` + CREATE TABLE IF NOT EXISTS worker_vacation_balance ( + id INT PRIMARY KEY AUTO_INCREMENT, + worker_id INT NOT NULL COMMENT '작업자 ID', + year YEAR NOT NULL COMMENT '연도', + total_annual_leave DECIMAL(4,2) DEFAULT 15.0 COMMENT '연간 총 연차 (일)', + used_annual_leave DECIMAL(4,2) DEFAULT 0 COMMENT '사용한 연차 (일)', + remaining_annual_leave DECIMAL(4,2) GENERATED ALWAYS AS (total_annual_leave - used_annual_leave) STORED COMMENT '잔여 연차 (일)', + notes TEXT COMMENT '비고', + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + + UNIQUE KEY unique_worker_year (worker_id, year), + INDEX idx_worker_year (worker_id, year) + ) COMMENT='작업자별 휴가 잔여 관리 테이블' + `); + + // 5. 기본 데이터 삽입 + console.log('📝 기본 데이터 삽입 중...'); + + // 근로 유형 기본 데이터 + await db.execute(` + INSERT IGNORE INTO work_attendance_types (type_code, type_name, description) VALUES + ('REGULAR', '정시근로', '8시간 정규 근무'), + ('OVERTIME', '연장근로', '8시간 초과 근무'), + ('PARTIAL', '부분근로', '8시간 미만 근무'), + ('VACATION', '휴가근로', '휴가와 함께하는 부분 근무') + `); + + // 휴가 유형 기본 데이터 + await db.execute(` + INSERT IGNORE INTO vacation_types (type_code, type_name, hours_deduction, description) VALUES + ('ANNUAL_FULL', '연차', 8.0, '하루 전체 연차'), + ('ANNUAL_HALF', '반차', 4.0, '반일 연차'), + ('ANNUAL_QUARTER', '반반차', 2.0, '1/4일 연차'), + ('SICK_FULL', '병가', 8.0, '하루 전체 병가'), + ('SICK_HALF', '반일병가', 4.0, '반일 병가'), + ('PERSONAL_FULL', '개인사유', 8.0, '개인사유로 인한 휴가'), + ('PERSONAL_HALF', '반일개인사유', 4.0, '반일 개인사유 휴가') + `); + + // 6. 휴가 전용 작업 유형 추가 + console.log('🏖️ 휴가 전용 작업 유형 추가 중...'); + await db.execute(` + INSERT IGNORE INTO work_types (name, description, is_active) VALUES + ('휴가', '연차, 반차, 병가 등 휴가 처리용', TRUE) + `); + + // 7. daily_work_reports 테이블에 근태 기록 연결 컬럼 추가 (이미 있으면 무시) + try { + await db.execute(` + ALTER TABLE daily_work_reports + ADD COLUMN attendance_record_id INT NULL COMMENT '근태 기록 ID' AFTER updated_by + `); + console.log('✅ daily_work_reports 테이블에 attendance_record_id 컬럼 추가됨'); + } catch (error) { + if (error.code !== 'ER_DUP_FIELDNAME') { + console.log('⚠️ attendance_record_id 컬럼 추가 실패 (이미 존재할 수 있음):', error.message); + } else { + console.log('✅ attendance_record_id 컬럼이 이미 존재함'); + } + } + + // 8. 인덱스 추가 + try { + await db.execute(`CREATE INDEX idx_attendance_record ON daily_work_reports(attendance_record_id)`); + console.log('✅ attendance_record_id 인덱스 추가됨'); + } catch (error) { + console.log('⚠️ 인덱스 추가 실패 (이미 존재할 수 있음):', error.message); + } + + try { + await db.execute(`CREATE INDEX idx_daily_work_reports_worker_date ON daily_work_reports(worker_id, report_date)`); + console.log('✅ worker_date 인덱스 추가됨'); + } catch (error) { + console.log('⚠️ 인덱스 추가 실패 (이미 존재할 수 있음):', error.message); + } + + console.log('🎉 근태 관리 DB 설정 완료!'); + console.log(''); + console.log('📋 생성된 테이블:'); + console.log(' - work_attendance_types (근로 유형)'); + console.log(' - vacation_types (휴가 유형)'); + console.log(' - daily_attendance_records (일일 근태 기록)'); + console.log(' - worker_vacation_balance (휴가 잔여 관리)'); + console.log(''); + console.log('✅ 기본 데이터도 모두 삽입되었습니다.'); + + } catch (error) { + console.error('❌ DB 설정 중 오류 발생:', error); + throw error; + } +} + +// 직접 실행 +if (require.main === module) { + setupAttendanceDB() + .then(() => { + console.log('✅ 설정 완료'); + process.exit(0); + }) + .catch((error) => { + console.error('❌ 설정 실패:', error); + process.exit(1); + }); +} + +module.exports = { setupAttendanceDB }; diff --git a/deploy/tkfb-package/api.hyungi.net/tests/README.md b/deploy/tkfb-package/api.hyungi.net/tests/README.md new file mode 100644 index 0000000..fd0a004 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/tests/README.md @@ -0,0 +1,170 @@ +# 테스트 시작하기 + +## 빠른 시작 + +### 1단계: 테스트 패키지 설치 + +```bash +cd /Users/hyungiahn/Documents/code/TK-FB-Project/api.hyungi.net +npm install +``` + +### 2단계: 첫 번째 테스트 실행 + +```bash +# 모든 테스트 실행 +npm test + +# 특정 파일만 테스트 +npm test -- tests/unit/services/workReportService.test.js + +# Watch 모드 (파일 변경 시 자동 재실행) +npm run test:watch +``` + +### 3단계: 커버리지 확인 + +```bash +# 커버리지와 함께 테스트 실행 +npm run test:coverage + +# 커버리지 리포트 HTML 보기 +open coverage/lcov-report/index.html +``` + +--- + +## 디렉토리 구조 + +``` +tests/ +├── README.md # 이 파일 +├── setup.js # Jest 전역 설정 +├── helpers/ +│ └── mockData.js # 테스트용 더미 데이터 +├── unit/ +│ ├── services/ # 서비스 레이어 테스트 +│ │ └── workReportService.test.js # ✅ 작성 완료 (예제) +│ ├── controllers/ # 컨트롤러 테스트 (미작성) +│ └── models/ # 모델 테스트 (미작성) +└── integration/ # 통합 테스트 (미작성) +``` + +--- + +## 다음 단계: 테스트 파일 작성 + +### 우선순위 1: 서비스 레이어 테스트 작성 + +다음 서비스들에 대한 테스트 파일을 작성하세요: + +```bash +tests/unit/services/ +├── workReportService.test.js # ✅ 완료 +├── attendanceService.test.js # ⬜ TODO +├── dailyWorkReportService.test.js # ⬜ TODO +├── workerService.test.js # ⬜ TODO (간단) +├── projectService.test.js # ⬜ TODO (간단) +├── issueTypeService.test.js # ⬜ TODO (간단) +├── toolsService.test.js # ⬜ TODO +├── dailyIssueReportService.test.js # ⬜ TODO +├── uploadService.test.js # ⬜ TODO (간단) +└── analysisService.test.js # ⬜ TODO +``` + +**추천 작성 순서:** +1. **workReportService.test.js** ✅ (이미 완료 - 참고용) +2. **workerService.test.js** (간단한 CRUD, 시작하기 좋음) +3. **projectService.test.js** (간단한 CRUD) +4. **attendanceService.test.js** (복잡도 중간) +5. **나머지 서비스들...** + +### 우선순위 2: 컨트롤러 테스트 + +서비스 레이어 테스트가 어느정도 완료되면 컨트롤러 테스트를 시작하세요. + +### 우선순위 3: 통합 테스트 + +마지막으로 실제 HTTP 요청을 테스트하는 통합 테스트를 작성하세요. + +--- + +## 예제 테스트 작성 방법 + +### 서비스 레이어 테스트 템플릿 + +```javascript +const serviceName = require('../../../services/serviceName'); +const { ValidationError, NotFoundError, DatabaseError } = require('../../../utils/errors'); + +// 모델 모킹 +jest.mock('../../../models/modelName'); +const modelName = require('../../../models/modelName'); + +describe('ServiceName', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('methodName', () => { + it('should succeed when valid data provided', async () => { + // Arrange + const mockData = { /* ... */ }; + modelName.method.mockResolvedValue(mockData); + + // Act + const result = await serviceName.methodName(params); + + // Assert + expect(result).toEqual(expectedResult); + expect(modelName.method).toHaveBeenCalledWith(expectedParams); + }); + + it('should throw ValidationError when invalid data', async () => { + // Act & Assert + await expect(serviceName.methodName(invalidParams)) + .rejects.toThrow(ValidationError); + }); + }); +}); +``` + +--- + +## 유용한 명령어 + +```bash +# 특정 describe 블록만 테스트 +npm test -- --testNamePattern="createWorkReportService" + +# 실패한 테스트만 재실행 +npm test -- --onlyFailures + +# 병렬 실행 비활성화 (디버깅 시) +npm test -- --runInBand + +# 상세 출력 +npm run test:verbose +``` + +--- + +## 목표 커버리지 + +- **서비스 레이어**: 80% 이상 +- **컨트롤러**: 70% 이상 +- **전체**: 75% 이상 + +--- + +## 도움말 + +전체 가이드는 프로젝트 루트의 `TESTING_GUIDE.md`를 참고하세요: + +```bash +cat /Users/hyungiahn/Documents/code/TK-FB-Project/TESTING_GUIDE.md +``` + +--- + +**Happy Testing! 🧪** diff --git a/deploy/tkfb-package/api.hyungi.net/tests/helpers/mockData.js b/deploy/tkfb-package/api.hyungi.net/tests/helpers/mockData.js new file mode 100644 index 0000000..165969c --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/tests/helpers/mockData.js @@ -0,0 +1,225 @@ +/** + * 테스트용 더미 데이터 + * + * 테스트에서 재사용 가능한 모킹 데이터 + */ + +// 사용자 더미 데이터 +const mockUsers = { + admin: { + id: 1, + username: 'admin', + role: 'admin', + access_level: 5 + }, + groupLeader: { + id: 2, + username: 'group_leader', + role: 'group_leader', + access_level: 3 + }, + worker: { + id: 3, + username: 'worker', + role: 'worker', + access_level: 1 + } +}; + +// 작업자 더미 데이터 +const mockWorkers = [ + { + worker_id: 1, + worker_name: '김철수', + job_type: 'developer', + is_active: 1, + created_at: '2025-01-01 00:00:00' + }, + { + worker_id: 2, + worker_name: '이영희', + job_type: 'designer', + is_active: 1, + created_at: '2025-01-01 00:00:00' + }, + { + worker_id: 3, + worker_name: '박민수', + job_type: 'developer', + is_active: 0, + created_at: '2025-01-01 00:00:00' + } +]; + +// 프로젝트 더미 데이터 +const mockProjects = [ + { + project_id: 1, + project_name: '프로젝트 A', + job_no: 'PRJ-001', + created_at: '2025-01-01 00:00:00' + }, + { + project_id: 2, + project_name: '프로젝트 B', + job_no: 'PRJ-002', + created_at: '2025-01-15 00:00:00' + } +]; + +// 작업 유형 더미 데이터 +const mockWorkTypes = [ + { id: 1, name: '개발' }, + { id: 2, name: '디자인' }, + { id: 3, name: '테스트' }, + { id: 4, name: '회의' } +]; + +// 에러 유형 더미 데이터 +const mockErrorTypes = [ + { id: 1, name: '버그 수정' }, + { id: 2, name: '재작업' }, + { id: 3, name: '긴급 수정' } +]; + +// 작업 보고서 더미 데이터 +const mockWorkReports = [ + { + id: 1, + report_date: '2025-12-11', + worker_id: 1, + project_id: 1, + work_type_id: 1, + work_hours: 8.0, + work_content: '기능 개발', + error_type_id: null, + work_status_id: 1, + created_by: 1, + created_at: '2025-12-11 09:00:00', + updated_at: '2025-12-11 09:00:00' + }, + { + id: 2, + report_date: '2025-12-11', + worker_id: 2, + project_id: 1, + work_type_id: 2, + work_hours: 7.5, + work_content: 'UI 디자인', + error_type_id: null, + work_status_id: 1, + created_by: 2, + created_at: '2025-12-11 09:00:00', + updated_at: '2025-12-11 09:00:00' + }, + { + id: 3, + report_date: '2025-12-11', + worker_id: 1, + project_id: 2, + work_type_id: 1, + work_hours: 2.0, + work_content: '버그 수정', + error_type_id: 1, + work_status_id: 2, + created_by: 1, + created_at: '2025-12-11 14:00:00', + updated_at: '2025-12-11 14:00:00' + } +]; + +// 출석 더미 데이터 +const mockAttendance = [ + { + id: 1, + worker_id: 1, + attendance_date: '2025-12-11', + status: 'work', + regular_hours: 8.0, + overtime_hours: 0.0, + created_by: 1, + created_at: '2025-12-11 09:00:00' + }, + { + id: 2, + worker_id: 2, + attendance_date: '2025-12-11', + status: 'vacation', + regular_hours: 0.0, + overtime_hours: 0.0, + created_by: 2, + created_at: '2025-12-11 09:00:00' + } +]; + +// 분석 데이터 더미 +const mockAnalysisData = { + summary: { + total_entries: 100, + total_hours: 800.0, + unique_workers: 10, + unique_projects: 5, + working_days: 20, + avg_hours_per_entry: 8.0, + contributors: 3, + error_entries: 5, + error_rate: 5.0 + }, + dailyStats: [ + { report_date: '2025-12-01', daily_hours: 40.0, daily_entries: 5, daily_workers: 5 }, + { report_date: '2025-12-02', daily_hours: 35.0, daily_entries: 5, daily_workers: 4 } + ] +}; + +// API 응답 형식 +const createSuccessResponse = (data, message = '성공') => ({ + success: true, + data, + message +}); + +const createErrorResponse = (error, message = '오류 발생') => ({ + success: false, + error, + message +}); + +// 날짜 헬퍼 +const createDateString = (daysFromToday = 0) => { + const date = new Date(); + date.setDate(date.getDate() + daysFromToday); + return date.toISOString().split('T')[0]; +}; + +// DB 쿼리 결과 모킹 헬퍼 +const createDbResult = (data, affectedRows = 1, insertId = 1) => { + if (Array.isArray(data)) { + return [data, []]; // [rows, fields] + } + return [ + { + affectedRows, + insertId, + changedRows: affectedRows + }, + [] + ]; +}; + +module.exports = { + // 더미 데이터 + mockUsers, + mockWorkers, + mockProjects, + mockWorkTypes, + mockErrorTypes, + mockWorkReports, + mockAttendance, + mockAnalysisData, + + // 헬퍼 함수 + createSuccessResponse, + createErrorResponse, + createDateString, + createDbResult +}; diff --git a/deploy/tkfb-package/api.hyungi.net/tests/setup.js b/deploy/tkfb-package/api.hyungi.net/tests/setup.js new file mode 100644 index 0000000..d31ce4c --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/tests/setup.js @@ -0,0 +1,67 @@ +/** + * Jest 전역 테스트 설정 + * + * 모든 테스트 실행 전 자동으로 로드됩니다 + */ + +// 환경 변수 설정 (테스트 환경) +process.env.NODE_ENV = 'test'; +process.env.LOG_LEVEL = 'error'; // 테스트 시 로그 최소화 + +// 타임존 설정 +process.env.TZ = 'Asia/Seoul'; + +// 전역 타임아웃 확장 (필요 시) +jest.setTimeout(10000); + +// 콘솔 출력 모킹 (선택사항 - 테스트 출력을 깔끔하게) +// global.console = { +// ...console, +// log: jest.fn(), +// debug: jest.fn(), +// info: jest.fn(), +// warn: jest.fn(), +// error: jest.fn(), +// }; + +// 모든 테스트 실행 전 +beforeAll(() => { + // 전역 설정 +}); + +// 각 테스트 파일 실행 전 +beforeEach(() => { + // 각 테스트 전 초기화 +}); + +// 각 테스트 파일 실행 후 +afterEach(() => { + // 모킹 정리 + jest.clearAllMocks(); +}); + +// 모든 테스트 실행 후 +afterAll(() => { + // 정리 작업 +}); + +// 커스텀 매처 (선택사항) +expect.extend({ + // 날짜 문자열 검증 + toBeValidDate(received) { + const isValid = !isNaN(Date.parse(received)); + return { + message: () => `expected ${received} to be a valid date string`, + pass: isValid + }; + }, + + // ID 검증 + toBeValidId(received) { + const isValid = Number.isInteger(received) && received > 0; + return { + message: () => `expected ${received} to be a valid ID (positive integer)`, + pass: isValid + }; + } +}); diff --git a/deploy/tkfb-package/api.hyungi.net/tests/unit/services/workReportService.test.js b/deploy/tkfb-package/api.hyungi.net/tests/unit/services/workReportService.test.js new file mode 100644 index 0000000..7567d31 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/tests/unit/services/workReportService.test.js @@ -0,0 +1,321 @@ +/** + * WorkReportService 테스트 + * + * 작업 보고서 서비스 레이어 단위 테스트 + */ + +const workReportService = require('../../../services/workReportService'); +const { ValidationError, NotFoundError, DatabaseError } = require('../../../utils/errors'); +const { mockWorkReports } = require('../../helpers/mockData'); + +// 모델 모킹 +jest.mock('../../../models/workReportModel'); +const workReportModel = require('../../../models/workReportModel'); + +describe('WorkReportService', () => { + beforeEach(() => { + jest.clearAllMocks(); + }); + + describe('createWorkReportService', () => { + it('단일 보고서를 성공적으로 생성해야 함', async () => { + // Arrange + const reportData = { + report_date: '2025-12-11', + worker_id: 1, + project_id: 1, + work_type_id: 1, + work_hours: 8.0, + work_content: '기능 개발' + }; + + // workReportModel.create가 콜백 형태이므로 모킹 설정 + workReportModel.create = jest.fn((data, callback) => { + callback(null, 123); // insertId = 123 + }); + + // Act + const result = await workReportService.createWorkReportService(reportData); + + // Assert + expect(result).toEqual({ workReport_ids: [123] }); + expect(workReportModel.create).toHaveBeenCalledTimes(1); + expect(workReportModel.create).toHaveBeenCalledWith( + reportData, + expect.any(Function) + ); + }); + + it('다중 보고서를 성공적으로 생성해야 함', async () => { + // Arrange + const reportsData = [ + { report_date: '2025-12-11', worker_id: 1, work_hours: 8 }, + { report_date: '2025-12-11', worker_id: 2, work_hours: 7 } + ]; + + let callCount = 0; + workReportModel.create = jest.fn((data, callback) => { + callCount++; + callback(null, 100 + callCount); + }); + + // Act + const result = await workReportService.createWorkReportService(reportsData); + + // Assert + expect(result).toEqual({ workReport_ids: [101, 102] }); + expect(workReportModel.create).toHaveBeenCalledTimes(2); + }); + + it('빈 배열이면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.createWorkReportService([])) + .rejects.toThrow(ValidationError); + + await expect(workReportService.createWorkReportService([])) + .rejects.toThrow('보고서 데이터가 필요합니다'); + }); + + it('DB 오류 시 DatabaseError를 던져야 함', async () => { + // Arrange + const reportData = { report_date: '2025-12-11', worker_id: 1 }; + + workReportModel.create = jest.fn((data, callback) => { + callback(new Error('DB connection failed'), null); + }); + + // Act & Assert + await expect(workReportService.createWorkReportService(reportData)) + .rejects.toThrow(DatabaseError); + }); + }); + + describe('getWorkReportsByDateService', () => { + it('날짜로 보고서를 조회해야 함', async () => { + // Arrange + const date = '2025-12-11'; + const mockReports = mockWorkReports.filter(r => r.report_date === date); + + workReportModel.getAllByDate = jest.fn((date, callback) => { + callback(null, mockReports); + }); + + // Act + const result = await workReportService.getWorkReportsByDateService(date); + + // Assert + expect(result).toEqual(mockReports); + expect(workReportModel.getAllByDate).toHaveBeenCalledWith(date, expect.any(Function)); + }); + + it('날짜가 없으면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.getWorkReportsByDateService(null)) + .rejects.toThrow(ValidationError); + + await expect(workReportService.getWorkReportsByDateService(null)) + .rejects.toThrow('날짜가 필요합니다'); + }); + + it('DB 오류 시 DatabaseError를 던져야 함', async () => { + // Arrange + workReportModel.getAllByDate = jest.fn((date, callback) => { + callback(new Error('DB error'), null); + }); + + // Act & Assert + await expect(workReportService.getWorkReportsByDateService('2025-12-11')) + .rejects.toThrow(DatabaseError); + }); + }); + + describe('getWorkReportByIdService', () => { + it('ID로 보고서를 조회해야 함', async () => { + // Arrange + const mockReport = mockWorkReports[0]; + + workReportModel.getById = jest.fn((id, callback) => { + callback(null, mockReport); + }); + + // Act + const result = await workReportService.getWorkReportByIdService(1); + + // Assert + expect(result).toEqual(mockReport); + expect(workReportModel.getById).toHaveBeenCalledWith(1, expect.any(Function)); + }); + + it('보고서가 없으면 NotFoundError를 던져야 함', async () => { + // Arrange + workReportModel.getById = jest.fn((id, callback) => { + callback(null, null); + }); + + // Act & Assert + await expect(workReportService.getWorkReportByIdService(999)) + .rejects.toThrow(NotFoundError); + + await expect(workReportService.getWorkReportByIdService(999)) + .rejects.toThrow('작업 보고서를 찾을 수 없습니다'); + }); + + it('ID가 없으면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.getWorkReportByIdService(null)) + .rejects.toThrow(ValidationError); + }); + }); + + describe('updateWorkReportService', () => { + it('보고서를 성공적으로 수정해야 함', async () => { + // Arrange + const updateData = { work_hours: 9 }; + + workReportModel.update = jest.fn((id, data, callback) => { + callback(null, 1); // affectedRows = 1 + }); + + // Act + const result = await workReportService.updateWorkReportService(123, updateData); + + // Assert + expect(result).toEqual({ changes: 1 }); + expect(workReportModel.update).toHaveBeenCalledWith( + 123, + updateData, + expect.any(Function) + ); + }); + + it('수정할 보고서가 없으면 NotFoundError를 던져야 함', async () => { + // Arrange + workReportModel.update = jest.fn((id, data, callback) => { + callback(null, 0); // affectedRows = 0 + }); + + // Act & Assert + await expect(workReportService.updateWorkReportService(999, {})) + .rejects.toThrow(NotFoundError); + }); + + it('ID가 없으면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.updateWorkReportService(null, {})) + .rejects.toThrow(ValidationError); + }); + }); + + describe('removeWorkReportService', () => { + it('보고서를 성공적으로 삭제해야 함', async () => { + // Arrange + workReportModel.remove = jest.fn((id, callback) => { + callback(null, 1); + }); + + // Act + const result = await workReportService.removeWorkReportService(123); + + // Assert + expect(result).toEqual({ changes: 1 }); + expect(workReportModel.remove).toHaveBeenCalledWith(123, expect.any(Function)); + }); + + it('삭제할 보고서가 없으면 NotFoundError를 던져야 함', async () => { + // Arrange + workReportModel.remove = jest.fn((id, callback) => { + callback(null, 0); + }); + + // Act & Assert + await expect(workReportService.removeWorkReportService(999)) + .rejects.toThrow(NotFoundError); + }); + + it('ID가 없으면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.removeWorkReportService(null)) + .rejects.toThrow(ValidationError); + }); + }); + + describe('getWorkReportsInRangeService', () => { + it('기간으로 보고서를 조회해야 함', async () => { + // Arrange + const start = '2025-12-01'; + const end = '2025-12-31'; + + workReportModel.getByRange = jest.fn((start, end, callback) => { + callback(null, mockWorkReports); + }); + + // Act + const result = await workReportService.getWorkReportsInRangeService(start, end); + + // Assert + expect(result).toEqual(mockWorkReports); + expect(workReportModel.getByRange).toHaveBeenCalledWith( + start, + end, + expect.any(Function) + ); + }); + + it('시작일이 없으면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.getWorkReportsInRangeService(null, '2025-12-31')) + .rejects.toThrow(ValidationError); + }); + + it('종료일이 없으면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.getWorkReportsInRangeService('2025-12-01', null)) + .rejects.toThrow(ValidationError); + }); + }); + + describe('getSummaryService', () => { + it('월간 요약을 조회해야 함', async () => { + // Arrange + const year = '2025'; + const month = '12'; + + workReportModel.getByRange = jest.fn((start, end, callback) => { + callback(null, mockWorkReports); + }); + + // Act + const result = await workReportService.getSummaryService(year, month); + + // Assert + expect(result).toEqual(mockWorkReports); + expect(workReportModel.getByRange).toHaveBeenCalled(); + }); + + it('연도가 없으면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.getSummaryService(null, '12')) + .rejects.toThrow(ValidationError); + }); + + it('월이 없으면 ValidationError를 던져야 함', async () => { + // Act & Assert + await expect(workReportService.getSummaryService('2025', null)) + .rejects.toThrow(ValidationError); + }); + + it('데이터가 없으면 NotFoundError를 던져야 함', async () => { + // Arrange + workReportModel.getByRange = jest.fn((start, end, callback) => { + callback(null, []); + }); + + // Act & Assert + await expect(workReportService.getSummaryService('2025', '12')) + .rejects.toThrow(NotFoundError); + + await expect(workReportService.getSummaryService('2025', '12')) + .rejects.toThrow('해당 기간의 작업 보고서가 없습니다'); + }); + }); +}); diff --git a/deploy/tkfb-package/api.hyungi.net/utils/access.js b/deploy/tkfb-package/api.hyungi.net/utils/access.js new file mode 100644 index 0000000..8c6fe5f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/access.js @@ -0,0 +1,178 @@ +/** + * @deprecated 이 파일의 미들웨어 함수들은 하위 호환성을 위해 유지됩니다. + * 새로운 코드에서는 '../middlewares/auth'를 사용하세요. + */ + +// utils/access.js - 유틸리티 함수와 레거시 호환성 +const ACCESS_LEVELS = { + worker: 1, + group_leader: 2, + support_team: 3, + admin: 4, + system: 5 +}; + +const ACCESS_LEVEL_NAMES = { + worker: '작업자', + group_leader: '그룹장', + support_team: '지원팀', + admin: '관리자', + system: '시스템' +}; + +/** + * 권한 레벨 비교 (유틸리티 함수) + * @param {string} userLevel - 사용자의 권한 레벨 + * @param {string} requiredLevel - 필요한 권한 레벨 + * @returns {boolean} - 권한 여부 + */ +const hasPermission = (userLevel, requiredLevel) => { + const userOrder = ACCESS_LEVELS[userLevel] || 0; + const requiredOrder = ACCESS_LEVELS[requiredLevel] || 999; + return userOrder >= requiredOrder; +}; + +/** + * 권한 레벨을 숫자로 변환 + * @param {string} level - 권한 레벨 문자열 + * @returns {number} - 권한 레벨 숫자 + */ +const getLevelNumber = (level) => { + return ACCESS_LEVELS[level] || 0; +}; + +/** + * 권한 레벨을 한글명으로 변환 + * @param {string} level - 권한 레벨 문자열 + * @returns {string} - 한글 권한명 + */ +const getLevelName = (level) => { + return ACCESS_LEVEL_NAMES[level] || '알 수 없음'; +}; + +/** + * 사용자가 특정 권한들 중 하나라도 가지고 있는지 확인 + * @param {string} userLevel - 사용자의 권한 레벨 + * @param {string[]} allowedLevels - 허용된 권한 레벨들 + * @returns {boolean} - 권한 여부 + */ +const hasAnyPermission = (userLevel, allowedLevels) => { + return allowedLevels.some(level => hasPermission(userLevel, level)); +}; + +/** + * 모든 권한 레벨 목록 반환 + * @returns {string[]} - 권한 레벨 배열 + */ +const getAllLevels = () => { + return Object.keys(ACCESS_LEVELS); +}; + +/** + * 특정 권한 레벨 이상의 모든 권한 반환 + * @param {string} minLevel - 최소 권한 레벨 + * @returns {string[]} - 해당 레벨 이상의 권한들 + */ +const getLevelsAbove = (minLevel) => { + const minOrder = ACCESS_LEVELS[minLevel] || 0; + return Object.keys(ACCESS_LEVELS).filter(level => ACCESS_LEVELS[level] >= minOrder); +}; + +// ===== 프론트엔드용 권한 체크 함수들 ===== + +/** + * 페이지 접근 권한 체크 (프론트엔드에서 사용) + * @param {string} userLevel - 사용자 권한 + * @param {object} pageConfig - 페이지 설정 {minLevel?, allowedRoles?, deniedRoles?} + * @returns {boolean} - 접근 가능 여부 + */ +const canAccessPage = (userLevel, pageConfig) => { + const { minLevel, allowedRoles, deniedRoles = [] } = pageConfig; + + // 거부 목록 체크 + if (deniedRoles.includes(userLevel)) { + return false; + } + + // 허용 목록 체크 + if (allowedRoles && allowedRoles.length > 0) { + return allowedRoles.includes(userLevel); + } + + // 최소 레벨 체크 + if (minLevel) { + return hasPermission(userLevel, minLevel); + } + + return true; +}; + +/** + * CRUD 권한 체크 (프론트엔드에서 사용) + * @param {string} userLevel - 사용자 권한 + * @param {string} table - 테이블명 + * @param {string} action - 액션 (CREATE, READ, UPDATE, DELETE) + * @returns {boolean} - 권한 여부 + */ +const canPerformAction = (userLevel, table, action) => { + // 기본적으로 모든 인증된 사용자에게 권한 부여 + // 특별한 제한이 필요한 경우에만 여기서 체크 + + // 예시: 사용자 관리는 admin 이상만 + if (table === 'Users' && ['CREATE', 'UPDATE', 'DELETE'].includes(action)) { + return hasPermission(userLevel, 'admin'); + } + + // 예시: 시스템 테이블은 system만 + if (table === 'SystemConfig') { + return hasPermission(userLevel, 'system'); + } + + // 나머지는 모든 인증된 사용자에게 허용 + return userLevel && userLevel !== 'anonymous'; +}; + +// ===== 레거시 호환성: 미들웨어 함수 ===== + +/** + * @deprecated 이 미들웨어는 하위 호환성을 위해 유지됩니다. + * 새로운 코드에서는 '../middlewares/auth'의 requireRole을 사용하세요. + * + * @example + * // 이전 방식 (deprecated) + * const { requireAccess } = require('../utils/access'); + * router.get('/admin', requireAccess('admin'), handler); + * + * // 새로운 방식 (권장) + * const { requireAuth, requireRole } = require('../middlewares/auth'); + * router.get('/admin', requireAuth, requireRole('admin'), handler); + */ +const requireAccess = (...allowed) => { + return (req, res, next) => { + if (!req.user || !allowed.includes(req.user.access_level)) { + return res.status(403).json({ error: '접근 권한이 없습니다' }); + } + next(); + }; +}; + +module.exports = { + // 기본 유틸리티 함수들 + hasPermission, + getLevelNumber, + getLevelName, + hasAnyPermission, + getAllLevels, + getLevelsAbove, + + // 프론트엔드용 함수들 + canAccessPage, + canPerformAction, + + // 레거시 호환성 (deprecated) + requireAccess, + + // 상수들 + ACCESS_LEVELS, + ACCESS_LEVEL_NAMES +}; \ No newline at end of file diff --git a/deploy/tkfb-package/api.hyungi.net/utils/cache.js b/deploy/tkfb-package/api.hyungi.net/utils/cache.js new file mode 100644 index 0000000..de2002f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/cache.js @@ -0,0 +1,284 @@ +// utils/cache.js - 통합 캐싱 시스템 + +const NodeCache = require('node-cache'); + +// 메모리 캐시 (Redis가 없을 때 fallback) +const memoryCache = new NodeCache({ + stdTTL: 600, // 기본 10분 + checkperiod: 120, // 2분마다 만료된 키 정리 + useClones: false // 성능 향상을 위해 복사본 생성 안함 +}); + +// Redis 클라이언트 (선택적) +let redisClient = null; + +/** + * Redis 연결 초기화 (선택적) + */ +const initRedis = async () => { + try { + const redis = require('redis'); + + redisClient = redis.createClient({ + socket: { + host: process.env.REDIS_HOST || 'localhost', + port: process.env.REDIS_PORT || 6379, + reconnectStrategy: (retries) => { + if (retries > 10) { + console.warn('Redis 재시도 횟수 초과. 메모리 캐시를 사용합니다.'); + return false; // Redis 연결 포기 + } + return Math.min(retries * 100, 3000); + } + }, + password: process.env.REDIS_PASSWORD || undefined, + database: process.env.REDIS_DB || 0 + }); + + redisClient.on('error', (err) => { + console.warn('Redis 오류:', err.message); + redisClient = null; // Redis 사용 중단, 메모리 캐시로 fallback + }); + + redisClient.on('connect', () => { + console.log('✅ Redis 캐시 연결 성공'); + }); + + await redisClient.connect(); + + } catch (error) { + console.warn('Redis 초기화 실패, 메모리 캐시 사용:', error.message); + redisClient = null; + } +}; + +/** + * 캐시에서 값 조회 + */ +const get = async (key) => { + try { + if (redisClient && redisClient.isOpen) { + const value = await redisClient.get(key); + return value ? JSON.parse(value) : null; + } else { + return memoryCache.get(key) || null; + } + } catch (error) { + console.warn(`캐시 조회 오류 (${key}):`, error.message); + return null; + } +}; + +/** + * 캐시에 값 저장 + */ +const set = async (key, value, ttl = 600) => { + try { + if (redisClient && redisClient.isOpen) { + await redisClient.setEx(key, ttl, JSON.stringify(value)); + } else { + memoryCache.set(key, value, ttl); + } + return true; + } catch (error) { + console.warn(`캐시 저장 오류 (${key}):`, error.message); + return false; + } +}; + +/** + * 캐시에서 값 삭제 + */ +const del = async (key) => { + try { + if (redisClient && redisClient.isOpen) { + await redisClient.del(key); + } else { + memoryCache.del(key); + } + return true; + } catch (error) { + console.warn(`캐시 삭제 오류 (${key}):`, error.message); + return false; + } +}; + +/** + * 패턴으로 캐시 키 삭제 + */ +const delPattern = async (pattern) => { + try { + if (redisClient && redisClient.isOpen) { + const keys = await redisClient.keys(pattern); + if (keys.length > 0) { + await redisClient.del(keys); + } + } else { + const keys = memoryCache.keys(); + const matchingKeys = keys.filter(key => { + const regex = new RegExp(pattern.replace('*', '.*')); + return regex.test(key); + }); + memoryCache.del(matchingKeys); + } + return true; + } catch (error) { + console.warn(`패턴 캐시 삭제 오류 (${pattern}):`, error.message); + return false; + } +}; + +/** + * 전체 캐시 초기화 + */ +const flush = async () => { + try { + if (redisClient && redisClient.isOpen) { + await redisClient.flushDb(); + } else { + memoryCache.flushAll(); + } + return true; + } catch (error) { + console.warn('캐시 초기화 오류:', error.message); + return false; + } +}; + +/** + * 캐시 통계 조회 + */ +const getStats = () => { + if (redisClient && redisClient.isOpen) { + return { + type: 'redis', + connected: true, + host: process.env.REDIS_HOST || 'localhost', + port: process.env.REDIS_PORT || 6379 + }; + } else { + const stats = memoryCache.getStats(); + return { + type: 'memory', + connected: true, + keys: stats.keys, + hits: stats.hits, + misses: stats.misses, + hitRate: stats.hits / (stats.hits + stats.misses) || 0 + }; + } +}; + +/** + * 캐시 키 생성 헬퍼 + */ +const createKey = (prefix, ...parts) => { + return `${prefix}:${parts.join(':')}`; +}; + +/** + * TTL 상수 정의 + */ +const TTL = { + SHORT: 60, // 1분 + MEDIUM: 300, // 5분 + LONG: 600, // 10분 + HOUR: 3600, // 1시간 + DAY: 86400 // 24시간 +}; + +/** + * 캐시 미들웨어 생성기 + */ +const createCacheMiddleware = (keyGenerator, ttl = TTL.MEDIUM) => { + return async (req, res, next) => { + try { + const cacheKey = typeof keyGenerator === 'function' + ? keyGenerator(req) + : keyGenerator; + + const cachedData = await get(cacheKey); + + if (cachedData) { + console.log(`🎯 캐시 히트: ${cacheKey}`); + return res.json(cachedData); + } + + // 원본 res.json을 저장 + const originalJson = res.json; + + // res.json을 오버라이드하여 응답을 캐시에 저장 + res.json = function(data) { + // 성공 응답만 캐시 + if (res.statusCode >= 200 && res.statusCode < 300) { + set(cacheKey, data, ttl).then(() => { + console.log(`💾 캐시 저장: ${cacheKey}`); + }); + } + + // 원본 응답 실행 + return originalJson.call(this, data); + }; + + next(); + + } catch (error) { + console.warn('캐시 미들웨어 오류:', error.message); + next(); + } + }; +}; + +/** + * 캐시 무효화 헬퍼 + */ +const invalidateCache = { + // 사용자 관련 캐시 무효화 + user: async (userId) => { + await delPattern(`user:${userId}:*`); + await delPattern('users:*'); + }, + + // 작업자 관련 캐시 무효화 + worker: async (workerId) => { + await delPattern(`worker:${workerId}:*`); + await delPattern('workers:*'); + }, + + // 프로젝트 관련 캐시 무효화 + project: async (projectId) => { + await delPattern(`project:${projectId}:*`); + await delPattern('projects:*'); + }, + + // 작업 관련 캐시 무효화 + task: async (taskId) => { + await delPattern(`task:${taskId}:*`); + await delPattern('tasks:*'); + }, + + // 일일 작업 보고서 관련 캐시 무효화 + dailyWorkReport: async (date) => { + await delPattern(`daily-work-report:${date}:*`); + await delPattern('daily-work-reports:*'); + }, + + // 전체 캐시 무효화 + all: async () => { + await flush(); + } +}; + +module.exports = { + initRedis, + get, + set, + del, + delPattern, + flush, + getStats, + createKey, + TTL, + createCacheMiddleware, + invalidateCache +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/dateUtils.js b/deploy/tkfb-package/api.hyungi.net/utils/dateUtils.js new file mode 100644 index 0000000..322462a --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/dateUtils.js @@ -0,0 +1,131 @@ +/** + * 날짜/시간 유틸리티 함수 + * + * 중요: 이 프로젝트는 한국(Asia/Seoul, UTC+9) 시간대 기준으로 운영됩니다. + * DB에 저장되는 비즈니스 날짜(report_date, session_date 등)는 반드시 한국 시간 기준이어야 합니다. + * + * @author TK-FB-Project + * @since 2026-02-03 + */ + +const KOREA_TIMEZONE_OFFSET = 9; // UTC+9 + +/** + * 한국 시간(KST) 기준 현재 Date 객체 반환 + * @returns {Date} 한국 시간 기준 Date 객체 + */ +function getKoreaDate() { + const now = new Date(); + return new Date(now.getTime() + (KOREA_TIMEZONE_OFFSET * 60 * 60 * 1000)); +} + +/** + * 한국 시간(KST) 기준 현재 날짜 문자열 반환 + * @returns {string} 'YYYY-MM-DD' 형식 + */ +function getKoreaDateString() { + const koreaDate = getKoreaDate(); + const year = koreaDate.getUTCFullYear(); + const month = String(koreaDate.getUTCMonth() + 1).padStart(2, '0'); + const day = String(koreaDate.getUTCDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +/** + * 한국 시간(KST) 기준 현재 datetime 문자열 반환 + * @returns {string} 'YYYY-MM-DD HH:mm:ss' 형식 (MySQL DATETIME 호환) + */ +function getKoreaDatetime() { + const koreaDate = getKoreaDate(); + const year = koreaDate.getUTCFullYear(); + const month = String(koreaDate.getUTCMonth() + 1).padStart(2, '0'); + const day = String(koreaDate.getUTCDate()).padStart(2, '0'); + const hours = String(koreaDate.getUTCHours()).padStart(2, '0'); + const minutes = String(koreaDate.getUTCMinutes()).padStart(2, '0'); + const seconds = String(koreaDate.getUTCSeconds()).padStart(2, '0'); + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; +} + +/** + * 한국 시간(KST) 기준 현재 시간 문자열 반환 + * @returns {string} 'HH:mm:ss' 형식 + */ +function getKoreaTimeString() { + const koreaDate = getKoreaDate(); + const hours = String(koreaDate.getUTCHours()).padStart(2, '0'); + const minutes = String(koreaDate.getUTCMinutes()).padStart(2, '0'); + const seconds = String(koreaDate.getUTCSeconds()).padStart(2, '0'); + return `${hours}:${minutes}:${seconds}`; +} + +/** + * UTC Date를 한국 시간 datetime 문자열로 변환 + * @param {Date} date - UTC 기준 Date 객체 + * @returns {string} 'YYYY-MM-DD HH:mm:ss' 형식 + */ +function toKoreaDatetime(date) { + if (!date) return null; + const koreaDate = new Date(date.getTime() + (KOREA_TIMEZONE_OFFSET * 60 * 60 * 1000)); + const year = koreaDate.getUTCFullYear(); + const month = String(koreaDate.getUTCMonth() + 1).padStart(2, '0'); + const day = String(koreaDate.getUTCDate()).padStart(2, '0'); + const hours = String(koreaDate.getUTCHours()).padStart(2, '0'); + const minutes = String(koreaDate.getUTCMinutes()).padStart(2, '0'); + const seconds = String(koreaDate.getUTCSeconds()).padStart(2, '0'); + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`; +} + +/** + * UTC Date를 한국 날짜 문자열로 변환 + * @param {Date} date - UTC 기준 Date 객체 + * @returns {string} 'YYYY-MM-DD' 형식 + */ +function toKoreaDateString(date) { + if (!date) return null; + const koreaDate = new Date(date.getTime() + (KOREA_TIMEZONE_OFFSET * 60 * 60 * 1000)); + const year = koreaDate.getUTCFullYear(); + const month = String(koreaDate.getUTCMonth() + 1).padStart(2, '0'); + const day = String(koreaDate.getUTCDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +/** + * 한국 시간 datetime 문자열을 Date 객체로 변환 + * @param {string} koreaDatetimeStr - 'YYYY-MM-DD HH:mm:ss' 형식 + * @returns {Date} UTC 기준 Date 객체 + */ +function fromKoreaDatetime(koreaDatetimeStr) { + if (!koreaDatetimeStr) return null; + // 한국 시간 문자열을 UTC로 변환 + const date = new Date(koreaDatetimeStr + '+09:00'); + return date; +} + +/** + * 연도 반환 (한국 시간 기준) + * @returns {number} 현재 연도 + */ +function getKoreaYear() { + return getKoreaDate().getUTCFullYear(); +} + +/** + * 월 반환 (한국 시간 기준, 1-12) + * @returns {number} 현재 월 (1-12) + */ +function getKoreaMonth() { + return getKoreaDate().getUTCMonth() + 1; +} + +module.exports = { + KOREA_TIMEZONE_OFFSET, + getKoreaDate, + getKoreaDateString, + getKoreaDatetime, + getKoreaTimeString, + toKoreaDatetime, + toKoreaDateString, + fromKoreaDatetime, + getKoreaYear, + getKoreaMonth, +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/errorHandler.js b/deploy/tkfb-package/api.hyungi.net/utils/errorHandler.js new file mode 100644 index 0000000..4cd1a47 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/errorHandler.js @@ -0,0 +1,143 @@ +// utils/errorHandler.js - 통합 에러 처리 유틸리티 + +/** + * 표준화된 에러 응답 생성 + */ +class ApiError extends Error { + constructor(message, statusCode = 500, errorCode = null) { + super(message); + this.statusCode = statusCode; + this.errorCode = errorCode; + this.timestamp = new Date().toISOString(); + } +} + +/** + * 에러 응답 포맷터 + */ +const formatErrorResponse = (error, req = null) => { + const response = { + success: false, + error: error.message || '알 수 없는 오류가 발생했습니다.', + timestamp: error.timestamp || new Date().toISOString() + }; + + // 개발 환경에서만 상세 정보 포함 + if (process.env.NODE_ENV === 'development') { + response.stack = error.stack; + response.errorCode = error.errorCode; + if (req) { + response.requestInfo = { + method: req.method, + url: req.originalUrl, + userAgent: req.get('User-Agent'), + ip: req.ip + }; + } + } + + return response; +}; + +/** + * 데이터베이스 에러 처리 + */ +const handleDatabaseError = (error, operation = 'database operation') => { + console.error(`[DB Error] ${operation}:`, error); + + // 일반적인 DB 에러 코드 매핑 + const errorMappings = { + 'ER_DUP_ENTRY': { message: '중복된 데이터입니다.', statusCode: 409 }, + 'ER_NO_REFERENCED_ROW_2': { message: '참조된 데이터가 존재하지 않습니다.', statusCode: 400 }, + 'ER_ROW_IS_REFERENCED_2': { message: '다른 데이터에서 참조되고 있어 삭제할 수 없습니다.', statusCode: 409 }, + 'ER_BAD_FIELD_ERROR': { message: '잘못된 필드명입니다.', statusCode: 400 }, + 'ER_NO_SUCH_TABLE': { message: '테이블이 존재하지 않습니다.', statusCode: 500 }, + 'ECONNREFUSED': { message: '데이터베이스 연결에 실패했습니다.', statusCode: 503 } + }; + + const mapping = errorMappings[error.code] || errorMappings[error.errno]; + if (mapping) { + throw new ApiError(mapping.message, mapping.statusCode, error.code); + } + + // 기본 에러 + throw new ApiError(`${operation} 중 오류가 발생했습니다.`, 500, error.code); +}; + +/** + * 유효성 검사 에러 처리 + */ +const handleValidationError = (field, value, rule) => { + const message = `${field} 필드가 유효하지 않습니다. (값: ${value}, 규칙: ${rule})`; + throw new ApiError(message, 400, 'VALIDATION_ERROR'); +}; + +/** + * 권한 에러 처리 + */ +const handleAuthorizationError = (requiredLevel, userLevel) => { + const message = `접근 권한이 부족합니다. (필요: ${requiredLevel}, 현재: ${userLevel})`; + throw new ApiError(message, 403, 'AUTHORIZATION_ERROR'); +}; + +/** + * 리소스 없음 에러 처리 + */ +const handleNotFoundError = (resource, identifier = null) => { + const message = identifier + ? `${resource}(${identifier})을(를) 찾을 수 없습니다.` + : `${resource}을(를) 찾을 수 없습니다.`; + throw new ApiError(message, 404, 'NOT_FOUND'); +}; + +/** + * Express 에러 핸들러 미들웨어 + */ +const errorMiddleware = (error, req, res, next) => { + // ApiError가 아닌 경우 변환 + if (!(error instanceof ApiError)) { + error = new ApiError(error.message || '서버 내부 오류', 500); + } + + const response = formatErrorResponse(error, req); + + // 로깅 + if (error.statusCode >= 500) { + console.error('[Server Error]', { + message: error.message, + stack: error.stack, + url: req.originalUrl, + method: req.method, + user: req.user?.username || 'anonymous' + }); + } else { + console.warn('[Client Error]', { + message: error.message, + url: req.originalUrl, + method: req.method, + user: req.user?.username || 'anonymous' + }); + } + + res.status(error.statusCode).json(response); +}; + +/** + * 비동기 함수 래퍼 (에러 자동 처리) + */ +const asyncHandler = (fn) => { + return (req, res, next) => { + Promise.resolve(fn(req, res, next)).catch(next); + }; +}; + +module.exports = { + ApiError, + formatErrorResponse, + handleDatabaseError, + handleValidationError, + handleAuthorizationError, + handleNotFoundError, + errorMiddleware, + asyncHandler +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/errors.js b/deploy/tkfb-package/api.hyungi.net/utils/errors.js new file mode 100644 index 0000000..490908d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/errors.js @@ -0,0 +1,186 @@ +/** + * 커스텀 에러 클래스 + * + * 애플리케이션 전체에서 사용하는 표준화된 에러 클래스들 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +/** + * 기본 애플리케이션 에러 클래스 + * 모든 커스텀 에러의 부모 클래스 + */ +class AppError extends Error { + /** + * @param {string} message - 에러 메시지 + * @param {number} statusCode - HTTP 상태 코드 + * @param {string} code - 에러 코드 (예: 'VALIDATION_ERROR') + * @param {object} details - 추가 세부 정보 + */ + constructor(message, statusCode = 500, code = 'INTERNAL_ERROR', details = null) { + super(message); + this.name = this.constructor.name; + this.statusCode = statusCode; + this.code = code; + this.details = details; + this.isOperational = true; // 운영 에러 (예상된 에러) + + Error.captureStackTrace(this, this.constructor); + } + + /** + * JSON 형태로 에러 정보 반환 + */ + toJSON() { + return { + name: this.name, + message: this.message, + statusCode: this.statusCode, + code: this.code, + details: this.details + }; + } +} + +/** + * 검증 에러 (400 Bad Request) + * 입력값 검증 실패 시 사용 + */ +class ValidationError extends AppError { + /** + * @param {string} message - 에러 메시지 + * @param {object} details - 검증 실패 세부 정보 + */ + constructor(message = '입력값이 올바르지 않습니다', details = null) { + super(message, 400, 'VALIDATION_ERROR', details); + } +} + +/** + * 인증 에러 (401 Unauthorized) + * 인증이 필요하거나 인증 실패 시 사용 + */ +class AuthenticationError extends AppError { + /** + * @param {string} message - 에러 메시지 + */ + constructor(message = '인증이 필요합니다') { + super(message, 401, 'AUTHENTICATION_ERROR'); + } +} + +/** + * 권한 에러 (403 Forbidden) + * 권한이 부족할 때 사용 + */ +class ForbiddenError extends AppError { + /** + * @param {string} message - 에러 메시지 + */ + constructor(message = '권한이 없습니다') { + super(message, 403, 'FORBIDDEN'); + } +} + +/** + * 리소스 없음 에러 (404 Not Found) + * 요청한 리소스를 찾을 수 없을 때 사용 + */ +class NotFoundError extends AppError { + /** + * @param {string} message - 에러 메시지 + * @param {string} resource - 찾을 수 없는 리소스명 + */ + constructor(message = '리소스를 찾을 수 없습니다', resource = null) { + super(message, 404, 'NOT_FOUND', resource ? { resource } : null); + } +} + +/** + * 충돌 에러 (409 Conflict) + * 중복된 리소스 등 충돌 발생 시 사용 + */ +class ConflictError extends AppError { + /** + * @param {string} message - 에러 메시지 + * @param {object} details - 충돌 세부 정보 + */ + constructor(message = '이미 존재하는 데이터입니다', details = null) { + super(message, 409, 'CONFLICT', details); + } +} + +/** + * 서버 에러 (500 Internal Server Error) + * 예상하지 못한 서버 오류 시 사용 + */ +class InternalServerError extends AppError { + /** + * @param {string} message - 에러 메시지 + */ + constructor(message = '서버 오류가 발생했습니다') { + super(message, 500, 'INTERNAL_SERVER_ERROR'); + } +} + +/** + * 데이터베이스 에러 (500 Internal Server Error) + * DB 관련 오류 시 사용 + */ +class DatabaseError extends AppError { + /** + * @param {string} message - 에러 메시지 + * @param {Error} originalError - 원본 DB 에러 + */ + constructor(message = '데이터베이스 오류가 발생했습니다', originalError = null) { + super( + message, + 500, + 'DATABASE_ERROR', + originalError ? { originalMessage: originalError.message } : null + ); + this.originalError = originalError; + } +} + +/** + * 외부 API 에러 (502 Bad Gateway) + * 외부 서비스 호출 실패 시 사용 + */ +class ExternalApiError extends AppError { + /** + * @param {string} message - 에러 메시지 + * @param {string} service - 외부 서비스명 + */ + constructor(message = '외부 서비스 호출에 실패했습니다', service = null) { + super(message, 502, 'EXTERNAL_API_ERROR', service ? { service } : null); + } +} + +/** + * 타임아웃 에러 (504 Gateway Timeout) + * 요청 처리 시간 초과 시 사용 + */ +class TimeoutError extends AppError { + /** + * @param {string} message - 에러 메시지 + * @param {number} timeout - 타임아웃 시간 (ms) + */ + constructor(message = '요청 처리 시간이 초과되었습니다', timeout = null) { + super(message, 504, 'TIMEOUT_ERROR', timeout ? { timeout } : null); + } +} + +module.exports = { + AppError, + ValidationError, + AuthenticationError, + ForbiddenError, + NotFoundError, + ConflictError, + InternalServerError, + DatabaseError, + ExternalApiError, + TimeoutError +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/fileUploadSecurity.js b/deploy/tkfb-package/api.hyungi.net/utils/fileUploadSecurity.js new file mode 100644 index 0000000..cb87406 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/fileUploadSecurity.js @@ -0,0 +1,315 @@ +/** + * File Upload Security - 파일 업로드 보안 유틸리티 + * + * - Magic number (파일 시그니처) 검증 + * - 파일명 sanitize + * - 확장자 화이트리스트 검증 + * - 파일 크기 제한 + * + * @author TK-FB-Project + * @since 2026-02-04 + */ + +const path = require('path'); +const crypto = require('crypto'); +const fs = require('fs').promises; + +/** + * 파일 시그니처 (Magic Numbers) + * 파일의 실제 타입을 확인하기 위한 바이너리 시그니처 + */ +const FILE_SIGNATURES = { + // 이미지 + 'ffd8ff': { mime: 'image/jpeg', ext: ['.jpg', '.jpeg'] }, + '89504e47': { mime: 'image/png', ext: ['.png'] }, + '47494638': { mime: 'image/gif', ext: ['.gif'] }, + '52494646': { mime: 'image/webp', ext: ['.webp'] }, // RIFF (WebP 시작) + + // 문서 + '25504446': { mime: 'application/pdf', ext: ['.pdf'] }, + '504b0304': { mime: 'application/zip', ext: ['.zip', '.xlsx', '.docx', '.pptx'] }, + + // 주의: BMP, TIFF 등 추가 가능 +}; + +/** + * 허용된 이미지 확장자 + */ +const ALLOWED_IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.webp']; + +/** + * 허용된 문서 확장자 + */ +const ALLOWED_DOCUMENT_EXTENSIONS = ['.pdf', '.xlsx', '.docx', '.pptx', '.zip']; + +/** + * 위험한 확장자 (절대 허용 안 함) + */ +const DANGEROUS_EXTENSIONS = [ + '.exe', '.bat', '.cmd', '.sh', '.ps1', '.vbs', '.js', '.jar', + '.php', '.asp', '.aspx', '.jsp', '.cgi', '.pl', '.py', '.rb', + '.htaccess', '.htpasswd', '.ini', '.config', '.env' +]; + +/** + * 파일 시그니처(Magic Number) 검증 + * + * @param {Buffer} buffer - 파일 버퍼 (최소 8바이트) + * @returns {Object|null} 매칭된 파일 정보 또는 null + */ +const checkMagicNumber = (buffer) => { + if (!buffer || buffer.length < 4) { + return null; + } + + // 처음 8바이트를 hex로 변환 + const hex = buffer.slice(0, 8).toString('hex').toLowerCase(); + + // 시그니처 매칭 + for (const [signature, info] of Object.entries(FILE_SIGNATURES)) { + if (hex.startsWith(signature)) { + return info; + } + } + + return null; +}; + +/** + * 파일 버퍼에서 실제 MIME 타입 검증 + * + * @param {Buffer} buffer - 파일 버퍼 + * @param {string} declaredMime - 선언된 MIME 타입 + * @returns {Object} { valid: boolean, actualType: string|null, message: string } + */ +const validateFileType = (buffer, declaredMime) => { + const detected = checkMagicNumber(buffer); + + if (!detected) { + return { + valid: false, + actualType: null, + message: '알 수 없는 파일 형식입니다.' + }; + } + + // MIME 타입이 일치하는지 확인 + if (detected.mime !== declaredMime) { + return { + valid: false, + actualType: detected.mime, + message: `파일 형식이 일치하지 않습니다. (선언: ${declaredMime}, 실제: ${detected.mime})` + }; + } + + return { + valid: true, + actualType: detected.mime, + message: 'OK' + }; +}; + +/** + * 파일명 sanitize + * 경로 조작 및 특수문자 제거 + * + * @param {string} filename - 원본 파일명 + * @returns {string} 안전한 파일명 + */ +const sanitizeFilename = (filename) => { + if (!filename || typeof filename !== 'string') { + return 'unnamed'; + } + + // 경로 구분자 제거 (path traversal 방지) + let safe = path.basename(filename); + + // 특수문자 제거 (영문, 숫자, -, _, . 만 허용) + safe = safe.replace(/[^a-zA-Z0-9가-힣._-]/g, '_'); + + // 연속된 점 제거 (이중 확장자 방지) + safe = safe.replace(/\.{2,}/g, '.'); + + // 앞뒤 점/공백 제거 + safe = safe.replace(/^[\s.]+|[\s.]+$/g, ''); + + // 빈 파일명 처리 + if (!safe || safe === '') { + safe = 'unnamed'; + } + + // 최대 길이 제한 (255자) + if (safe.length > 255) { + const ext = path.extname(safe); + const name = path.basename(safe, ext); + safe = name.slice(0, 255 - ext.length) + ext; + } + + return safe; +}; + +/** + * 확장자 검증 + * + * @param {string} filename - 파일명 + * @param {string[]} allowedExtensions - 허용된 확장자 배열 + * @returns {Object} { valid: boolean, extension: string, message: string } + */ +const validateExtension = (filename, allowedExtensions = ALLOWED_IMAGE_EXTENSIONS) => { + const ext = path.extname(filename).toLowerCase(); + + // 위험한 확장자 체크 + if (DANGEROUS_EXTENSIONS.includes(ext)) { + return { + valid: false, + extension: ext, + message: `보안상 허용되지 않는 파일 형식입니다: ${ext}` + }; + } + + // 허용된 확장자 체크 + if (!allowedExtensions.includes(ext)) { + return { + valid: false, + extension: ext, + message: `허용된 파일 형식: ${allowedExtensions.join(', ')}` + }; + } + + return { + valid: true, + extension: ext, + message: 'OK' + }; +}; + +/** + * 안전한 랜덤 파일명 생성 + * + * @param {string} originalFilename - 원본 파일명 (확장자 추출용) + * @returns {string} 랜덤 파일명 + */ +const generateSafeFilename = (originalFilename) => { + const ext = path.extname(originalFilename).toLowerCase(); + const randomName = crypto.randomBytes(16).toString('hex'); + const timestamp = Date.now(); + + return `${timestamp}_${randomName}${ext}`; +}; + +/** + * 안전한 업로드 경로 생성 + * 경로 조작(path traversal) 방지 + * + * @param {string} baseDir - 기본 업로드 디렉토리 + * @param {string} filename - 파일명 + * @returns {string} 안전한 전체 경로 + */ +const getSafeUploadPath = (baseDir, filename) => { + const safeName = sanitizeFilename(filename); + const fullPath = path.join(baseDir, safeName); + + // 결과 경로가 baseDir 안에 있는지 확인 + const resolvedBase = path.resolve(baseDir); + const resolvedFull = path.resolve(fullPath); + + if (!resolvedFull.startsWith(resolvedBase)) { + throw new Error('경로 조작이 감지되었습니다.'); + } + + return resolvedFull; +}; + +/** + * Multer 파일 필터 생성 + * + * @param {Object} options - 옵션 + * @param {string[]} options.allowedExtensions - 허용된 확장자 + * @param {string[]} options.allowedMimes - 허용된 MIME 타입 + * @param {boolean} options.checkMagicNumber - Magic number 검증 여부 + * @returns {Function} Multer fileFilter 함수 + */ +const createFileFilter = (options = {}) => { + const { + allowedExtensions = ALLOWED_IMAGE_EXTENSIONS, + allowedMimes = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], + checkMagicNumber = false // Multer에서는 버퍼 접근이 제한적이므로 기본 false + } = options; + + return (req, file, cb) => { + // 확장자 검증 + const extResult = validateExtension(file.originalname, allowedExtensions); + if (!extResult.valid) { + return cb(new Error(extResult.message), false); + } + + // MIME 타입 검증 + if (!allowedMimes.includes(file.mimetype)) { + return cb(new Error(`허용된 MIME 타입: ${allowedMimes.join(', ')}`), false); + } + + cb(null, true); + }; +}; + +/** + * 업로드된 파일 검증 (후처리용) + * Multer 업로드 후 파일 내용을 검증 + * + * @param {string} filePath - 업로드된 파일 경로 + * @param {string} declaredMime - 선언된 MIME 타입 + * @returns {Promise} 검증 결과 + */ +const validateUploadedFile = async (filePath, declaredMime) => { + try { + // 파일 시작 부분 읽기 + const fd = await fs.open(filePath, 'r'); + const buffer = Buffer.alloc(8); + await fd.read(buffer, 0, 8, 0); + await fd.close(); + + // Magic number 검증 + const typeResult = validateFileType(buffer, declaredMime); + + if (!typeResult.valid) { + // 위험한 파일이면 삭제 + await fs.unlink(filePath); + return { + valid: false, + deleted: true, + message: typeResult.message + }; + } + + return { + valid: true, + deleted: false, + message: 'OK', + actualType: typeResult.actualType + }; + } catch (error) { + return { + valid: false, + deleted: false, + message: `파일 검증 중 오류: ${error.message}` + }; + } +}; + +module.exports = { + // 상수 + ALLOWED_IMAGE_EXTENSIONS, + ALLOWED_DOCUMENT_EXTENSIONS, + DANGEROUS_EXTENSIONS, + FILE_SIGNATURES, + + // 함수 + checkMagicNumber, + validateFileType, + sanitizeFilename, + validateExtension, + generateSafeFilename, + getSafeUploadPath, + createFileFilter, + validateUploadedFile +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/hangulToRoman.js b/deploy/tkfb-package/api.hyungi.net/utils/hangulToRoman.js new file mode 100644 index 0000000..fcc5ae0 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/hangulToRoman.js @@ -0,0 +1,166 @@ +/** + * 한글 이름을 영문(로마자)으로 변환하는 유틸리티 + * + * 사용 예시: + * hangulToRoman('홍길동') => 'hong.gildong' + * hangulToRoman('김철수') => 'kim.cheolsu' + */ + +// 한글 로마자 변환 매핑 (국립국어원 표기법 기준) +const CHOSUNG_MAP = { + 'ㄱ': 'g', 'ㄲ': 'kk', 'ㄴ': 'n', 'ㄷ': 'd', 'ㄸ': 'tt', + 'ㄹ': 'r', 'ㅁ': 'm', 'ㅂ': 'b', 'ㅃ': 'pp', 'ㅅ': 's', + 'ㅆ': 'ss', 'ㅇ': '', 'ㅈ': 'j', 'ㅉ': 'jj', 'ㅊ': 'ch', + 'ㅋ': 'k', 'ㅌ': 't', 'ㅍ': 'p', 'ㅎ': 'h' +}; + +const JUNGSUNG_MAP = { + 'ㅏ': 'a', 'ㅐ': 'ae', 'ㅑ': 'ya', 'ㅒ': 'yae', 'ㅓ': 'eo', + 'ㅔ': 'e', 'ㅕ': 'yeo', 'ㅖ': 'ye', 'ㅗ': 'o', 'ㅘ': 'wa', + 'ㅙ': 'wae', 'ㅚ': 'oe', 'ㅛ': 'yo', 'ㅜ': 'u', 'ㅝ': 'wo', + 'ㅞ': 'we', 'ㅟ': 'wi', 'ㅠ': 'yu', 'ㅡ': 'eu', 'ㅢ': 'ui', + 'ㅣ': 'i' +}; + +const JONGSUNG_MAP = { + '': '', 'ㄱ': 'k', 'ㄲ': 'k', 'ㄳ': 'k', 'ㄴ': 'n', 'ㄵ': 'n', + 'ㄶ': 'n', 'ㄷ': 't', 'ㄹ': 'l', 'ㄺ': 'k', 'ㄻ': 'm', 'ㄼ': 'p', + 'ㄽ': 'l', 'ㄾ': 'l', 'ㄿ': 'p', 'ㅀ': 'l', 'ㅁ': 'm', 'ㅂ': 'p', + 'ㅄ': 'p', 'ㅅ': 't', 'ㅆ': 't', 'ㅇ': 'ng', 'ㅈ': 't', 'ㅊ': 't', + 'ㅋ': 'k', 'ㅌ': 't', 'ㅍ': 'p', 'ㅎ': 't' +}; + +const CHOSUNG = [ + 'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', + 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ' +]; + +const JUNGSUNG = [ + 'ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ', 'ㅔ', 'ㅕ', 'ㅖ', 'ㅗ', 'ㅘ', + 'ㅙ', 'ㅚ', 'ㅛ', 'ㅜ', 'ㅝ', 'ㅞ', 'ㅟ', 'ㅠ', 'ㅡ', 'ㅢ', 'ㅣ' +]; + +const JONGSUNG = [ + '', 'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄹ', 'ㄺ', + 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅁ', 'ㅂ', 'ㅄ', 'ㅅ', + 'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ' +]; + +/** + * 한글 한 글자를 초성, 중성, 종성으로 분리 + * @param {string} char - 한글 한 글자 + * @returns {object} { cho, jung, jong } + */ +function decomposeHangul(char) { + const code = char.charCodeAt(0) - 0xAC00; + + if (code < 0 || code > 11171) { + return null; // 한글이 아님 + } + + const choIndex = Math.floor(code / 588); + const jungIndex = Math.floor((code % 588) / 28); + const jongIndex = code % 28; + + return { + cho: CHOSUNG[choIndex], + jung: JUNGSUNG[jungIndex], + jong: JONGSUNG[jongIndex] + }; +} + +/** + * 한글 이름을 로마자로 변환 + * @param {string} koreanName - 한글 이름 + * @returns {string} 로마자 이름 (예: 'hong.gildong') + */ +function hangulToRoman(koreanName) { + if (!koreanName || typeof koreanName !== 'string') { + return ''; + } + + // 공백 제거 + const trimmed = koreanName.trim(); + + // 성과 이름 분리 (첫 글자를 성으로 간주) + const surname = trimmed[0]; + const givenName = trimmed.substring(1); + + // 각 부분을 로마자로 변환 + const romanSurname = convertToRoman(surname); + const romanGivenName = convertToRoman(givenName); + + // 점(.)으로 연결 + return `${romanSurname}.${romanGivenName}`.toLowerCase(); +} + +/** + * 한글 문자열을 로마자로 변환 + * @param {string} text - 한글 문자열 + * @returns {string} 로마자 문자열 + */ +function convertToRoman(text) { + let result = ''; + + for (let i = 0; i < text.length; i++) { + const char = text[i]; + const decomposed = decomposeHangul(char); + + if (decomposed) { + result += CHOSUNG_MAP[decomposed.cho] || ''; + result += JUNGSUNG_MAP[decomposed.jung] || ''; + result += JONGSUNG_MAP[decomposed.jong] || ''; + } else { + // 한글이 아닌 경우 그대로 추가 + result += char; + } + } + + return result; +} + +/** + * 사용자명 생성 (중복 확인 및 처리) + * @param {string} koreanName - 한글 이름 + * @param {object} db - Database connection (mysql2 pool or knex) + * @returns {Promise} 고유한 username + */ +async function generateUniqueUsername(koreanName, db) { + const baseUsername = hangulToRoman(koreanName); + let username = baseUsername; + let counter = 1; + + // 중복 확인 + while (true) { + let existing; + + // mysql2 pool 또는 knex 모두 지원 + if (typeof db === 'function') { + // Knex + existing = await db('users') + .where('username', username) + .first(); + } else { + // mysql2 pool + const [rows] = await db.query('SELECT username FROM users WHERE username = ?', [username]); + existing = rows[0]; + } + + if (!existing) { + break; // 중복 없음 + } + + // 중복 시 숫자 추가 + username = `${baseUsername}${counter}`; + counter++; + } + + return username; +} + +module.exports = { + hangulToRoman, + convertToRoman, + generateUniqueUsername, + decomposeHangul +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/logger.js b/deploy/tkfb-package/api.hyungi.net/utils/logger.js new file mode 100644 index 0000000..4109a96 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/logger.js @@ -0,0 +1,197 @@ +/** + * 로깅 유틸리티 + * + * 애플리케이션 전체에서 사용하는 통합 로거 + * + * @author TK-FB-Project + * @since 2025-12-11 + */ + +const fs = require('fs'); +const path = require('path'); + +/** + * 로그 레벨 정의 + */ +const LogLevel = { + ERROR: 'ERROR', + WARN: 'WARN', + INFO: 'INFO', + DEBUG: 'DEBUG' +}; + +/** + * 로그 레벨별 이모지 + */ +const LogEmoji = { + ERROR: '❌', + WARN: '⚠️', + INFO: 'ℹ️', + DEBUG: '🔍' +}; + +/** + * 로그 레벨별 색상 (콘솔) + */ +const LogColor = { + ERROR: '\x1b[31m', // Red + WARN: '\x1b[33m', // Yellow + INFO: '\x1b[36m', // Cyan + DEBUG: '\x1b[90m', // Gray + RESET: '\x1b[0m' +}; + +class Logger { + constructor() { + this.logDir = path.join(__dirname, '../logs'); + this.logFile = path.join(this.logDir, 'app.log'); + this.errorFile = path.join(this.logDir, 'error.log'); + this.ensureLogDirectory(); + } + + /** + * 로그 디렉토리 생성 + */ + ensureLogDirectory() { + if (!fs.existsSync(this.logDir)) { + fs.mkdirSync(this.logDir, { recursive: true }); + } + } + + /** + * 타임스탬프 생성 + */ + getTimestamp() { + return new Date().toISOString(); + } + + /** + * 로그 포맷팅 + */ + formatLog(level, message, context = {}) { + const timestamp = this.getTimestamp(); + const emoji = LogEmoji[level] || ''; + const contextStr = Object.keys(context).length > 0 + ? `\n Context: ${JSON.stringify(context, null, 2)}` + : ''; + + return `[${timestamp}] [${level}] ${emoji} ${message}${contextStr}`; + } + + /** + * 콘솔에 컬러 로그 출력 + */ + logToConsole(level, message, context = {}) { + const color = LogColor[level] || LogColor.RESET; + const formattedLog = this.formatLog(level, message, context); + + if (level === LogLevel.ERROR) { + console.error(`${color}${formattedLog}${LogColor.RESET}`); + } else if (level === LogLevel.WARN) { + console.warn(`${color}${formattedLog}${LogColor.RESET}`); + } else { + console.log(`${color}${formattedLog}${LogColor.RESET}`); + } + } + + /** + * 파일에 로그 기록 + */ + logToFile(level, message, context = {}) { + const formattedLog = this.formatLog(level, message, context); + const logEntry = `${formattedLog}\n`; + + try { + // 모든 로그를 app.log에 기록 + fs.appendFileSync(this.logFile, logEntry, 'utf8'); + + // 에러는 error.log에도 기록 + if (level === LogLevel.ERROR) { + fs.appendFileSync(this.errorFile, logEntry, 'utf8'); + } + } catch (err) { + console.error('로그 파일 기록 실패:', err); + } + } + + /** + * 로그 기록 메인 함수 + */ + log(level, message, context = {}) { + // 개발 환경에서는 콘솔에 출력 + if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV !== 'production') { + this.logToConsole(level, message, context); + } + + // 프로덕션에서는 파일에만 기록 + if (process.env.NODE_ENV === 'production') { + this.logToFile(level, message, context); + } + } + + /** + * 에러 로그 + */ + error(message, context = {}) { + this.log(LogLevel.ERROR, message, context); + } + + /** + * 경고 로그 + */ + warn(message, context = {}) { + this.log(LogLevel.WARN, message, context); + } + + /** + * 정보 로그 + */ + info(message, context = {}) { + this.log(LogLevel.INFO, message, context); + } + + /** + * 디버그 로그 + */ + debug(message, context = {}) { + // DEBUG 로그는 개발 환경에서만 출력 + if (process.env.NODE_ENV === 'development') { + this.log(LogLevel.DEBUG, message, context); + } + } + + /** + * HTTP 요청 로그 + */ + http(method, url, statusCode, duration, user = 'anonymous') { + const level = statusCode >= 400 ? LogLevel.ERROR : LogLevel.INFO; + const message = `${method} ${url} - ${statusCode} (${duration}ms)`; + const context = { + method, + url, + statusCode, + duration, + user + }; + + this.log(level, message, context); + } + + /** + * 데이터베이스 쿼리 로그 + */ + query(sql, params = [], duration = 0) { + if (process.env.NODE_ENV === 'development') { + this.debug('DB Query', { + sql, + params, + duration: `${duration}ms` + }); + } + } +} + +// 싱글톤 인스턴스 생성 및 내보내기 +const logger = new Logger(); + +module.exports = logger; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/passwordValidator.js b/deploy/tkfb-package/api.hyungi.net/utils/passwordValidator.js new file mode 100644 index 0000000..dcfe583 --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/passwordValidator.js @@ -0,0 +1,173 @@ +/** + * Password Validator - 비밀번호 정책 검증 + * + * 강력한 비밀번호 정책: + * - 최소 12자 이상 + * - 대문자 포함 + * - 소문자 포함 + * - 숫자 포함 + * - 특수문자 포함 + * + * @author TK-FB-Project + * @since 2026-02-04 + */ + +/** + * 비밀번호 강도 검증 + * + * @param {string} password - 검증할 비밀번호 + * @param {Object} options - 옵션 (기본값 사용 권장) + * @returns {Object} { valid: boolean, errors: string[], strength: string } + */ +const validatePassword = (password, options = {}) => { + const config = { + minLength: options.minLength || 12, + requireUppercase: options.requireUppercase !== false, + requireLowercase: options.requireLowercase !== false, + requireNumbers: options.requireNumbers !== false, + requireSpecialChars: options.requireSpecialChars !== false, + maxLength: options.maxLength || 128 + }; + + const errors = []; + let strength = 0; + + // 필수 검증 + if (!password || typeof password !== 'string') { + return { + valid: false, + errors: ['비밀번호를 입력해주세요.'], + strength: 'invalid' + }; + } + + // 길이 검증 + if (password.length < config.minLength) { + errors.push(`비밀번호는 최소 ${config.minLength}자 이상이어야 합니다.`); + } else { + strength += 1; + } + + if (password.length > config.maxLength) { + errors.push(`비밀번호는 ${config.maxLength}자를 초과할 수 없습니다.`); + } + + // 대문자 검증 + if (config.requireUppercase && !/[A-Z]/.test(password)) { + errors.push('대문자를 1개 이상 포함해야 합니다.'); + } else if (/[A-Z]/.test(password)) { + strength += 1; + } + + // 소문자 검증 + if (config.requireLowercase && !/[a-z]/.test(password)) { + errors.push('소문자를 1개 이상 포함해야 합니다.'); + } else if (/[a-z]/.test(password)) { + strength += 1; + } + + // 숫자 검증 + if (config.requireNumbers && !/\d/.test(password)) { + errors.push('숫자를 1개 이상 포함해야 합니다.'); + } else if (/\d/.test(password)) { + strength += 1; + } + + // 특수문자 검증 + const specialChars = /[!@#$%^&*()_+\-=\[\]{};':"\\|,.<>\/?]/; + if (config.requireSpecialChars && !specialChars.test(password)) { + errors.push('특수문자를 1개 이상 포함해야 합니다. (!@#$%^&*()_+-=[]{};\':"|,.<>/?)'); + } else if (specialChars.test(password)) { + strength += 1; + } + + // 공백 검증 + if (/\s/.test(password)) { + errors.push('비밀번호에 공백을 포함할 수 없습니다.'); + } + + // 연속된 문자 검증 (선택적) + if (/(.)\1{2,}/.test(password)) { + errors.push('동일한 문자를 3회 이상 연속 사용할 수 없습니다.'); + } + + // 강도 계산 + let strengthLabel; + if (strength <= 2) { + strengthLabel = 'weak'; + } else if (strength <= 3) { + strengthLabel = 'medium'; + } else if (strength <= 4) { + strengthLabel = 'strong'; + } else { + strengthLabel = 'very_strong'; + } + + return { + valid: errors.length === 0, + errors, + strength: strengthLabel, + score: strength + }; +}; + +/** + * 간단한 비밀번호 검증 (기존 호환용) + * 모든 조건을 만족하면 true, 아니면 false + * + * @param {string} password - 검증할 비밀번호 + * @returns {boolean} 유효 여부 + */ +const isValidPassword = (password) => { + return validatePassword(password).valid; +}; + +/** + * 비밀번호 검증 결과를 한국어 메시지로 반환 + * + * @param {string} password - 검증할 비밀번호 + * @returns {string|null} 오류 메시지 (유효하면 null) + */ +const getPasswordError = (password) => { + const result = validatePassword(password); + if (result.valid) { + return null; + } + return result.errors.join(' '); +}; + +/** + * Express 미들웨어: 요청 body의 password 또는 newPassword 필드 검증 + * + * @param {string} fieldName - 검증할 필드명 (기본: 'password') + * @returns {Function} Express 미들웨어 + */ +const validatePasswordMiddleware = (fieldName = 'password') => { + return (req, res, next) => { + const password = req.body[fieldName] || req.body.newPassword; + + if (!password) { + return next(); // 비밀번호 필드가 없으면 다음 미들웨어로 + } + + const result = validatePassword(password); + + if (!result.valid) { + return res.status(400).json({ + success: false, + error: '비밀번호가 보안 요구사항을 충족하지 않습니다.', + details: result.errors, + code: 'WEAK_PASSWORD' + }); + } + + next(); + }; +}; + +module.exports = { + validatePassword, + isValidPassword, + getPasswordError, + validatePasswordMiddleware +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/queryOptimizer.js b/deploy/tkfb-package/api.hyungi.net/utils/queryOptimizer.js new file mode 100644 index 0000000..e716d0f --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/queryOptimizer.js @@ -0,0 +1,433 @@ +// utils/queryOptimizer.js - 데이터베이스 쿼리 최적화 유틸리티 + +const { getDb } = require('../dbPool'); + +/** + * SQL Injection 방지를 위한 화이트리스트 검증 + */ +const ALLOWED_ORDER_DIRECTIONS = ['ASC', 'DESC']; +const ALLOWED_TABLE_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/; +const ALLOWED_COLUMN_NAME_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_.]*$/; + +const validateOrderDirection = (direction) => { + const normalized = (direction || 'DESC').toUpperCase(); + if (!ALLOWED_ORDER_DIRECTIONS.includes(normalized)) { + throw new Error(`Invalid order direction: ${direction}`); + } + return normalized; +}; + +const validateIdentifier = (identifier, type = 'column') => { + if (!identifier || typeof identifier !== 'string') { + throw new Error(`Invalid ${type} name`); + } + if (!ALLOWED_COLUMN_NAME_PATTERN.test(identifier)) { + throw new Error(`Invalid ${type} name: ${identifier}`); + } + return identifier; +}; + +const validateTableName = (tableName) => { + if (!tableName || typeof tableName !== 'string') { + throw new Error('Invalid table name'); + } + if (!ALLOWED_TABLE_NAME_PATTERN.test(tableName)) { + throw new Error(`Invalid table name: ${tableName}`); + } + return tableName; +}; + +/** + * 페이지네이션 헬퍼 + */ +const paginate = (page = 1, limit = 10) => { + const pageNum = Math.max(1, parseInt(page)); + const limitNum = Math.min(100, Math.max(1, parseInt(limit))); // 최대 100개 제한 + const offset = (pageNum - 1) * limitNum; + + return { + limit: limitNum, + offset, + page: pageNum + }; +}; + +/** + * 페이지네이션된 쿼리 실행 + */ +const executePagedQuery = async (baseQuery, countQuery, params = [], options = {}) => { + const { page = 1, limit = 10, orderBy = 'id', orderDirection = 'DESC' } = options; + const { limit: limitNum, offset, page: pageNum } = paginate(page, limit); + + // SQL Injection 방지: 컬럼명과 정렬방향 검증 + const safeOrderBy = validateIdentifier(orderBy, 'column'); + const safeOrderDirection = validateOrderDirection(orderDirection); + + try { + const db = await getDb(); + + // 전체 개수 조회 + const [countResult] = await db.execute(countQuery, params); + const totalCount = countResult[0]?.total || 0; + + // 데이터 조회 (ORDER BY와 LIMIT 추가) - 검증된 값만 사용 + const pagedQuery = `${baseQuery} ORDER BY ${safeOrderBy} ${safeOrderDirection} LIMIT ${limitNum} OFFSET ${offset}`; + const [rows] = await db.execute(pagedQuery, params); + + // 페이지네이션 메타데이터 계산 + const totalPages = Math.ceil(totalCount / limitNum); + + return { + data: rows, + pagination: { + currentPage: pageNum, + totalPages, + totalCount, + limit: limitNum, + hasNextPage: pageNum < totalPages, + hasPrevPage: pageNum > 1 + } + }; + + } catch (error) { + throw new Error(`페이지네이션 쿼리 실행 오류: ${error.message}`); + } +}; + +/** + * 인덱스 최적화 제안 + */ +const suggestIndexes = async (tableName) => { + // SQL Injection 방지: 테이블명 검증 + const safeTableName = validateTableName(tableName); + + try { + const db = await getDb(); + + // 현재 인덱스 조회 - 검증된 테이블명 사용 + const [indexes] = await db.execute(`SHOW INDEX FROM \`${safeTableName}\``); + + // 테이블 구조 조회 - 검증된 테이블명 사용 + const [columns] = await db.execute(`DESCRIBE \`${safeTableName}\``); + + const suggestions = []; + + // 외래키 컬럼에 인덱스 제안 + const foreignKeyColumns = columns.filter(col => + col.Field.endsWith('_id') && !indexes.some(idx => idx.Column_name === col.Field) + ); + + foreignKeyColumns.forEach(col => { + suggestions.push({ + type: 'INDEX', + column: col.Field, + reason: '외래키 컬럼에 인덱스 추가로 JOIN 성능 향상', + sql: `CREATE INDEX idx_${safeTableName}_${col.Field} ON \`${safeTableName}\`(\`${col.Field}\`);` + }); + }); + + // 날짜 컬럼에 인덱스 제안 + const dateColumns = columns.filter(col => + (col.Type.includes('date') || col.Type.includes('timestamp')) && + !indexes.some(idx => idx.Column_name === col.Field) + ); + + dateColumns.forEach(col => { + suggestions.push({ + type: 'INDEX', + column: col.Field, + reason: '날짜 범위 검색 성능 향상', + sql: `CREATE INDEX idx_${safeTableName}_${col.Field} ON \`${safeTableName}\`(\`${col.Field}\`);` + }); + }); + + return { + tableName: safeTableName, + currentIndexes: indexes.map(idx => ({ + name: idx.Key_name, + column: idx.Column_name, + unique: idx.Non_unique === 0 + })), + suggestions + }; + + } catch (error) { + throw new Error(`인덱스 분석 오류: ${error.message}`); + } +}; + +/** + * 쿼리 성능 분석 + */ +const analyzeQuery = async (query, params = []) => { + try { + const db = await getDb(); + + // EXPLAIN 실행 + const explainQuery = `EXPLAIN ${query}`; + const [explainResult] = await db.execute(explainQuery, params); + + // 쿼리 실행 시간 측정 + const startTime = Date.now(); + await db.execute(query, params); + const executionTime = Date.now() - startTime; + + // 성능 분석 + const analysis = { + executionTime, + explainResult, + recommendations: [] + }; + + // 성능 권장사항 생성 + explainResult.forEach(row => { + if (row.type === 'ALL') { + analysis.recommendations.push({ + type: 'WARNING', + message: `테이블 전체 스캔 발생: ${row.table}`, + suggestion: '적절한 인덱스 추가 권장' + }); + } + + if (row.rows > 1000) { + analysis.recommendations.push({ + type: 'WARNING', + message: `많은 행 검사: ${row.rows}행`, + suggestion: 'WHERE 조건 최적화 또는 인덱스 추가 권장' + }); + } + + if (row.Extra && row.Extra.includes('Using filesort')) { + analysis.recommendations.push({ + type: 'INFO', + message: '파일 정렬 사용 중', + suggestion: 'ORDER BY 컬럼에 인덱스 추가 고려' + }); + } + }); + + return analysis; + + } catch (error) { + throw new Error(`쿼리 분석 오류: ${error.message}`); + } +}; + +/** + * 배치 삽입 최적화 + */ +const batchInsert = async (tableName, data, batchSize = 100) => { + if (!Array.isArray(data) || data.length === 0) { + throw new Error('삽입할 데이터가 없습니다.'); + } + + // SQL Injection 방지: 테이블명 검증 + const safeTableName = validateTableName(tableName); + + try { + const db = await getDb(); + const connection = await db.getConnection(); + + await connection.beginTransaction(); + + const columns = Object.keys(data[0]); + // 컬럼명도 검증 + const safeColumns = columns.map(col => validateIdentifier(col, 'column')); + const placeholders = safeColumns.map(() => '?').join(', '); + const columnList = safeColumns.map(col => `\`${col}\``).join(', '); + const insertQuery = `INSERT INTO \`${safeTableName}\` (${columnList}) VALUES (${placeholders})`; + + let insertedCount = 0; + + // 배치 단위로 처리 + for (let i = 0; i < data.length; i += batchSize) { + const batch = data.slice(i, i + batchSize); + + for (const row of batch) { + const values = columns.map(col => row[col]); + await connection.execute(insertQuery, values); + insertedCount++; + } + } + + await connection.commit(); + connection.release(); + + return { + insertedCount, + batchSize, + totalBatches: Math.ceil(data.length / batchSize) + }; + + } catch (error) { + throw new Error(`배치 삽입 오류: ${error.message}`); + } +}; + +/** + * 쿼리 캐시 키 생성 + */ +const generateCacheKey = (query, params = [], prefix = 'query') => { + const paramString = params.length > 0 ? JSON.stringify(params) : ''; + const queryHash = require('crypto') + .createHash('md5') + .update(query + paramString) + .digest('hex'); + + return `${prefix}:${queryHash}`; +}; + +/** + * 자주 사용되는 최적화된 쿼리들 + */ +const optimizedQueries = { + // 작업자 목록 (페이지네이션) + getWorkersPaged: async (page = 1, limit = 10, search = '', status = '', departmentId = null) => { + let baseQuery = ` + SELECT w.*, d.department_name, COUNT(dwr.id) as report_count + FROM workers w + LEFT JOIN daily_work_reports dwr ON w.worker_id = dwr.worker_id + LEFT JOIN departments d ON w.department_id = d.department_id + `; + + let countQuery = ` + SELECT COUNT(*) as total FROM workers w + LEFT JOIN departments d ON w.department_id = d.department_id + `; + let params = []; + let conditions = []; + + // 검색 조건 + if (search) { + conditions.push('(w.worker_name LIKE ? OR w.position LIKE ?)'); + params.push(`%${search}%`, `%${search}%`); + } + + // 상태 조건 + if (status) { + conditions.push('w.status = ?'); + params.push(status); + } + + // 부서 조건 + if (departmentId) { + conditions.push('w.department_id = ?'); + params.push(departmentId); + } + + // 조건 조합 + if (conditions.length > 0) { + const whereClause = ' WHERE ' + conditions.join(' AND '); + baseQuery += whereClause; + countQuery += whereClause; + } + + baseQuery += ' GROUP BY w.worker_id'; + + return executePagedQuery(baseQuery, countQuery, params, { + page, limit, orderBy: 'w.worker_id', orderDirection: 'DESC' + }); + }, + + // 프로젝트 목록 (페이지네이션) + getProjectsPaged: async (page = 1, limit = 10, status = '') => { + let baseQuery = ` + SELECT p.*, COUNT(dwr.id) as report_count, + SUM(dwr.work_hours) as total_hours + FROM projects p + LEFT JOIN daily_work_reports dwr ON p.project_id = dwr.project_id + `; + + let countQuery = 'SELECT COUNT(*) as total FROM projects p'; + let params = []; + + if (status) { + const statusCondition = ' WHERE p.status = ?'; + baseQuery += statusCondition + ' GROUP BY p.project_id'; + countQuery += statusCondition; + params = [status]; + } else { + baseQuery += ' GROUP BY p.project_id'; + } + + return executePagedQuery(baseQuery, countQuery, params, { + page, limit, orderBy: 'p.project_id', orderDirection: 'DESC' + }); + }, + + // 일일 작업 보고서 (날짜 범위, 페이지네이션) + getDailyWorkReportsPaged: async (startDate, endDate, page = 1, limit = 10) => { + const baseQuery = ` + SELECT dwr.*, w.worker_name, p.project_name, + wt.name as work_type_name, wst.name as work_status_name, + et.name as error_type_name, u.name as created_by_name + FROM daily_work_reports dwr + LEFT JOIN workers w ON dwr.worker_id = w.worker_id + LEFT JOIN projects p ON dwr.project_id = p.project_id + LEFT JOIN work_types wt ON dwr.work_type_id = wt.id + LEFT JOIN work_status_types wst ON dwr.work_status_id = wst.id + LEFT JOIN error_types et ON dwr.error_type_id = et.id + LEFT JOIN users u ON dwr.created_by = u.user_id + WHERE dwr.report_date BETWEEN ? AND ? + `; + + const countQuery = ` + SELECT COUNT(*) as total + FROM daily_work_reports dwr + WHERE dwr.report_date BETWEEN ? AND ? + `; + + return executePagedQuery(baseQuery, countQuery, [startDate, endDate], { + page, limit, orderBy: 'dwr.report_date', orderDirection: 'DESC' + }); + } +}; + +/** + * 데이터베이스 성능 모니터링 + */ +const getPerformanceStats = async () => { + try { + const db = await getDb(); + + // 연결 상태 조회 + const [connections] = await db.execute('SHOW STATUS LIKE "Threads_connected"'); + const [maxConnections] = await db.execute('SHOW VARIABLES LIKE "max_connections"'); + + // 쿼리 캐시 상태 (MySQL 8.0 이전 버전) + let queryCacheStats = null; + try { + const [qcStats] = await db.execute('SHOW STATUS LIKE "Qcache%"'); + queryCacheStats = qcStats; + } catch (error) { + // MySQL 8.0+에서는 쿼리 캐시가 제거됨 + } + + // 슬로우 쿼리 로그 상태 + const [slowQueries] = await db.execute('SHOW STATUS LIKE "Slow_queries"'); + + return { + connections: { + current: parseInt(connections[0]?.Value || 0), + max: parseInt(maxConnections[0]?.Value || 0) + }, + queryCacheStats, + slowQueries: parseInt(slowQueries[0]?.Value || 0), + timestamp: new Date().toISOString() + }; + + } catch (error) { + throw new Error(`성능 통계 조회 오류: ${error.message}`); + } +}; + +module.exports = { + paginate, + executePagedQuery, + suggestIndexes, + analyzeQuery, + batchInsert, + generateCacheKey, + optimizedQueries, + getPerformanceStats +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/responseFormatter.js b/deploy/tkfb-package/api.hyungi.net/utils/responseFormatter.js new file mode 100644 index 0000000..46365bc --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/responseFormatter.js @@ -0,0 +1,188 @@ +// utils/responseFormatter.js - 통합 응답 포맷터 + +/** + * 성공 응답 포맷터 + */ +const successResponse = (data = null, message = '요청이 성공적으로 처리되었습니다.', meta = null) => { + const response = { + success: true, + message, + timestamp: new Date().toISOString() + }; + + if (data !== null) { + response.data = data; + } + + if (meta) { + response.meta = meta; + } + + return response; +}; + +/** + * 페이지네이션 응답 포맷터 + */ +const paginatedResponse = (data, totalCount, page = 1, limit = 10, message = '데이터 조회 성공') => { + const totalPages = Math.ceil(totalCount / limit); + + return successResponse(data, message, { + pagination: { + currentPage: parseInt(page), + totalPages, + totalCount: parseInt(totalCount), + limit: parseInt(limit), + hasNextPage: page < totalPages, + hasPrevPage: page > 1 + } + }); +}; + +/** + * 리스트 응답 포맷터 + */ +const listResponse = (items, message = '목록 조회 성공') => { + return successResponse(items, message, { + count: items.length + }); +}; + +/** + * 생성 응답 포맷터 + */ +const createdResponse = (data, message = '데이터가 성공적으로 생성되었습니다.') => { + return successResponse(data, message); +}; + +/** + * 업데이트 응답 포맷터 + */ +const updatedResponse = (data = null, message = '데이터가 성공적으로 업데이트되었습니다.') => { + return successResponse(data, message); +}; + +/** + * 삭제 응답 포맷터 + */ +const deletedResponse = (message = '데이터가 성공적으로 삭제되었습니다.') => { + return successResponse(null, message); +}; + +/** + * 통계 응답 포맷터 + */ +const statsResponse = (stats, period = null, message = '통계 조회 성공') => { + const meta = {}; + if (period) { + meta.period = period; + } + meta.generatedAt = new Date().toISOString(); + + return successResponse(stats, message, meta); +}; + +/** + * 인증 응답 포맷터 + */ +const authResponse = (user, token, redirectUrl = null, message = '로그인 성공') => { + const data = { + user, + token + }; + + if (redirectUrl) { + data.redirectUrl = redirectUrl; + } + + return successResponse(data, message); +}; + +/** + * 파일 업로드 응답 포맷터 + */ +const uploadResponse = (fileInfo, message = '파일 업로드 성공') => { + return successResponse({ + filename: fileInfo.filename, + originalName: fileInfo.originalname, + size: fileInfo.size, + mimetype: fileInfo.mimetype, + path: fileInfo.path, + uploadedAt: new Date().toISOString() + }, message); +}; + +/** + * 헬스체크 응답 포맷터 + */ +const healthResponse = (status = 'healthy', services = {}) => { + return successResponse({ + status, + services, + uptime: process.uptime(), + memory: process.memoryUsage(), + version: process.version + }, `서버 상태: ${status}`); +}; + +/** + * Express 응답 확장 미들웨어 + */ +const responseMiddleware = (req, res, next) => { + // 성공 응답 헬퍼들을 res 객체에 추가 + res.success = (data, message, meta) => { + return res.json(successResponse(data, message, meta)); + }; + + res.paginated = (data, totalCount, page, limit, message) => { + return res.json(paginatedResponse(data, totalCount, page, limit, message)); + }; + + res.list = (items, message) => { + return res.json(listResponse(items, message)); + }; + + res.created = (data, message) => { + return res.status(201).json(createdResponse(data, message)); + }; + + res.updated = (data, message) => { + return res.json(updatedResponse(data, message)); + }; + + res.deleted = (message) => { + return res.json(deletedResponse(message)); + }; + + res.stats = (stats, period, message) => { + return res.json(statsResponse(stats, period, message)); + }; + + res.auth = (user, token, redirectUrl, message) => { + return res.json(authResponse(user, token, redirectUrl, message)); + }; + + res.upload = (fileInfo, message) => { + return res.json(uploadResponse(fileInfo, message)); + }; + + res.health = (status, services) => { + return res.json(healthResponse(status, services)); + }; + + next(); +}; + +module.exports = { + successResponse, + paginatedResponse, + listResponse, + createdResponse, + updatedResponse, + deletedResponse, + statsResponse, + authResponse, + uploadResponse, + healthResponse, + responseMiddleware +}; diff --git a/deploy/tkfb-package/api.hyungi.net/utils/validator.js b/deploy/tkfb-package/api.hyungi.net/utils/validator.js new file mode 100644 index 0000000..66d4f3d --- /dev/null +++ b/deploy/tkfb-package/api.hyungi.net/utils/validator.js @@ -0,0 +1,304 @@ +// utils/validator.js - 유효성 검사 유틸리티 + +const { handleValidationError } = require('./errorHandler'); + +/** + * 필수 필드 검사 + */ +const required = (value, fieldName) => { + if (value === undefined || value === null || value === '') { + handleValidationError(fieldName, value, 'required'); + } + return true; +}; + +/** + * 문자열 길이 검사 + */ +const stringLength = (value, fieldName, min = 0, max = Infinity) => { + if (typeof value !== 'string') { + handleValidationError(fieldName, value, 'string type'); + } + if (value.length < min || value.length > max) { + handleValidationError(fieldName, value, `length between ${min} and ${max}`); + } + return true; +}; + +/** + * 숫자 범위 검사 + */ +const numberRange = (value, fieldName, min = -Infinity, max = Infinity) => { + const num = parseFloat(value); + if (isNaN(num)) { + handleValidationError(fieldName, value, 'number type'); + } + if (num < min || num > max) { + handleValidationError(fieldName, value, `number between ${min} and ${max}`); + } + return true; +}; + +/** + * 정수 검사 + */ +const integer = (value, fieldName) => { + const num = parseInt(value); + if (isNaN(num) || num.toString() !== value.toString()) { + handleValidationError(fieldName, value, 'integer'); + } + return true; +}; + +/** + * 이메일 형식 검사 + */ +const email = (value, fieldName) => { + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + if (!emailRegex.test(value)) { + handleValidationError(fieldName, value, 'valid email format'); + } + return true; +}; + +/** + * 날짜 형식 검사 (YYYY-MM-DD) + */ +const dateFormat = (value, fieldName) => { + const dateRegex = /^\d{4}-\d{2}-\d{2}$/; + if (!dateRegex.test(value)) { + handleValidationError(fieldName, value, 'YYYY-MM-DD format'); + } + + const date = new Date(value); + if (isNaN(date.getTime())) { + handleValidationError(fieldName, value, 'valid date'); + } + return true; +}; + +/** + * 시간 형식 검사 (HH:MM) + */ +const timeFormat = (value, fieldName) => { + const timeRegex = /^([0-1]?[0-9]|2[0-3]):[0-5][0-9]$/; + if (!timeRegex.test(value)) { + handleValidationError(fieldName, value, 'HH:MM format'); + } + return true; +}; + +/** + * 열거형 값 검사 + */ +const enumValue = (value, fieldName, allowedValues) => { + if (!allowedValues.includes(value)) { + handleValidationError(fieldName, value, `one of: ${allowedValues.join(', ')}`); + } + return true; +}; + +/** + * 배열 검사 + */ +const arrayType = (value, fieldName, minLength = 0, maxLength = Infinity) => { + if (!Array.isArray(value)) { + handleValidationError(fieldName, value, 'array type'); + } + if (value.length < minLength || value.length > maxLength) { + handleValidationError(fieldName, value, `array length between ${minLength} and ${maxLength}`); + } + return true; +}; + +/** + * 객체 검사 + */ +const objectType = (value, fieldName) => { + if (typeof value !== 'object' || value === null || Array.isArray(value)) { + handleValidationError(fieldName, value, 'object type'); + } + return true; +}; + +/** + * 비밀번호 강도 검사 + */ +const passwordStrength = (value, fieldName) => { + if (typeof value !== 'string') { + handleValidationError(fieldName, value, 'string type'); + } + + const minLength = 8; + const hasUpperCase = /[A-Z]/.test(value); + const hasLowerCase = /[a-z]/.test(value); + const hasNumbers = /\d/.test(value); + const hasSpecialChar = /[!@#$%^&*(),.?":{}|<>]/.test(value); + + if (value.length < minLength) { + handleValidationError(fieldName, value, `minimum ${minLength} characters`); + } + + const strengthChecks = [hasUpperCase, hasLowerCase, hasNumbers, hasSpecialChar]; + const passedChecks = strengthChecks.filter(Boolean).length; + + if (passedChecks < 3) { + handleValidationError(fieldName, value, 'at least 3 of: uppercase, lowercase, numbers, special characters'); + } + + return true; +}; + +/** + * 스키마 기반 유효성 검사 + */ +const validateSchema = (data, schema) => { + const errors = []; + + for (const [field, rules] of Object.entries(schema)) { + const value = data[field]; + + try { + // 필수 필드 검사 + if (rules.required) { + required(value, field); + } + + // 값이 없고 필수가 아니면 다른 검사 스킵 + if ((value === undefined || value === null || value === '') && !rules.required) { + continue; + } + + // 타입별 검사 + if (rules.type === 'string' && rules.minLength !== undefined && rules.maxLength !== undefined) { + stringLength(value, field, rules.minLength, rules.maxLength); + } + + if (rules.type === 'number' && rules.min !== undefined && rules.max !== undefined) { + numberRange(value, field, rules.min, rules.max); + } + + if (rules.type === 'integer') { + integer(value, field); + } + + if (rules.type === 'email') { + email(value, field); + } + + if (rules.type === 'date') { + dateFormat(value, field); + } + + if (rules.type === 'time') { + timeFormat(value, field); + } + + if (rules.type === 'array') { + arrayType(value, field, rules.minLength, rules.maxLength); + } + + if (rules.type === 'object') { + objectType(value, field); + } + + if (rules.enum) { + enumValue(value, field, rules.enum); + } + + if (rules.password) { + passwordStrength(value, field); + } + + // 커스텀 검증 함수 + if (rules.custom && typeof rules.custom === 'function') { + rules.custom(value, field); + } + + } catch (error) { + errors.push({ + field, + value, + message: error.message + }); + } + } + + if (errors.length > 0) { + const errorMessage = errors.map(e => `${e.field}: ${e.message}`).join(', '); + handleValidationError('validation', 'multiple fields', errorMessage); + } + + return true; +}; + +/** + * 일반적인 스키마 정의들 + */ +const schemas = { + // 사용자 생성 + createUser: { + username: { required: true, type: 'string', minLength: 3, maxLength: 50 }, + password: { required: true, password: true }, + name: { required: true, type: 'string', minLength: 2, maxLength: 100 }, + access_level: { required: true, enum: ['user', 'admin', 'system'] }, + worker_id: { type: 'integer' } + }, + + // 사용자 업데이트 + updateUser: { + name: { type: 'string', minLength: 2, maxLength: 100 }, + access_level: { enum: ['user', 'admin', 'system'] }, + worker_id: { type: 'integer' } + }, + + // 비밀번호 변경 + changePassword: { + currentPassword: { required: true, type: 'string' }, + newPassword: { required: true, password: true } + }, + + // 일일 작업 보고서 생성 (배열 형태) + createDailyWorkReport: { + report_date: { required: true, type: 'date' }, + worker_id: { required: true, type: 'integer' }, + work_entries: { required: true, type: 'array' }, + created_by: { type: 'integer' } + }, + + // 프로젝트 생성 + createProject: { + project_name: { required: true, type: 'string', minLength: 2, maxLength: 200 }, + description: { type: 'string', maxLength: 1000 }, + start_date: { type: 'date' }, + end_date: { type: 'date' } + }, + + // 작업자 생성 + createWorker: { + worker_name: { required: true, type: 'string', minLength: 2, maxLength: 100 }, + position: { type: 'string', maxLength: 100 }, + department: { type: 'string', maxLength: 100 }, + phone: { type: 'string', maxLength: 20 }, + email: { type: 'email' } + } +}; + +module.exports = { + // 개별 검증 함수들 + required, + stringLength, + numberRange, + integer, + email, + dateFormat, + timeFormat, + enumValue, + arrayType, + objectType, + passwordStrength, + + // 스키마 검증 + validateSchema, + schemas +}; diff --git a/deploy/tkfb-package/backup_20260206_085303.sql b/deploy/tkfb-package/backup_20260206_085303.sql new file mode 100644 index 0000000..9e7094d --- /dev/null +++ b/deploy/tkfb-package/backup_20260206_085303.sql @@ -0,0 +1,7407 @@ +-- MariaDB dump 10.19 Distrib 10.9.8-MariaDB, for debian-linux-gnu (aarch64) +-- +-- Host: localhost Database: hyungi +-- ------------------------------------------------------ +-- Server version 10.9.8-MariaDB-1:10.9.8+maria~ubu2204 + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8mb4 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; + +-- +-- Current Database: `hyungi` +-- + +CREATE DATABASE /*!32312 IF NOT EXISTS*/ `hyungi` /*!40100 DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci */; + +USE `hyungi`; + +-- +-- Table structure for table `CuttingPlan` +-- + +DROP TABLE IF EXISTS `CuttingPlan`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `CuttingPlan` ( + `cutting_plan_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int(11) NOT NULL, + `drawing_name` varchar(255) NOT NULL, + `area_number` varchar(100) DEFAULT NULL, + `spool_number` varchar(255) DEFAULT NULL, + `length` decimal(10,2) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `spec_id` int(11) NOT NULL, + PRIMARY KEY (`cutting_plan_id`), + KEY `project_id` (`project_id`), + KEY `fk_cuttingplan_spec` (`spec_id`), + CONSTRAINT `CuttingPlan_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`), + CONSTRAINT `fk_cuttingplan_spec` FOREIGN KEY (`spec_id`) REFERENCES `PipeSpecs` (`spec_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `CuttingPlan` +-- + +LOCK TABLES `CuttingPlan` WRITE; +/*!40000 ALTER TABLE `CuttingPlan` DISABLE KEYS */; +/*!40000 ALTER TABLE `CuttingPlan` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `DailyIssueReports` +-- + +DROP TABLE IF EXISTS `DailyIssueReports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `DailyIssueReports` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `issue_type_id` int(11) DEFAULT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `start_time` time NOT NULL, + `end_time` time NOT NULL, + PRIMARY KEY (`id`), + KEY `worker_id` (`worker_id`), + KEY `fk_dird_project` (`project_id`), + KEY `fk_dird_issuetype` (`issue_type_id`), + CONSTRAINT `dailyissuereports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `fk_dird_issuetype` FOREIGN KEY (`issue_type_id`) REFERENCES `IssueTypes` (`issue_type_id`), + CONSTRAINT `fk_dird_project` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `DailyIssueReports` +-- + +LOCK TABLES `DailyIssueReports` WRITE; +/*!40000 ALTER TABLE `DailyIssueReports` DISABLE KEYS */; +INSERT INTO `DailyIssueReports` VALUES +(1,'2025-06-02',1,7,5,NULL,'2025-06-02 05:54:35','10:00:00','11:30:00'), +(2,'2025-06-02',9,7,5,NULL,'2025-06-02 05:54:35','10:00:00','11:30:00'), +(3,'2025-06-02',7,7,5,NULL,'2025-06-02 05:54:35','10:00:00','11:30:00'), +(4,'2025-06-04',10,7,3,NULL,'2025-06-04 01:54:03','10:00:00','11:30:00'), +(5,'2025-06-04',6,7,3,NULL,'2025-06-04 01:54:03','10:00:00','11:30:00'), +(6,'2025-06-04',3,7,3,NULL,'2025-06-04 01:54:03','10:00:00','11:30:00'), +(7,'2025-06-11',10,7,6,NULL,'2025-06-10 08:56:09','07:30:00','08:00:00'), +(8,'2025-06-11',6,7,6,NULL,'2025-06-10 08:56:09','07:30:00','08:00:00'), +(9,'2025-06-11',3,7,6,NULL,'2025-06-10 08:56:09','07:30:00','08:00:00'); +/*!40000 ALTER TABLE `DailyIssueReports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `FactoryInfo` +-- + +DROP TABLE IF EXISTS `FactoryInfo`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `FactoryInfo` ( + `factory_id` int(11) NOT NULL AUTO_INCREMENT, + `factory_name` varchar(255) NOT NULL, + `address` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `map_image_url` varchar(255) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`factory_id`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `FactoryInfo` +-- + +LOCK TABLES `FactoryInfo` WRITE; +/*!40000 ALTER TABLE `FactoryInfo` DISABLE KEYS */; +INSERT INTO `FactoryInfo` VALUES +(3,'제1공장 휴게공간 및 작업자 사물함','현대기아로 771-9','개인 보관함, 컨테이너(휴게공간), 화장실, 흡연장','/uploads/map_image-1746593523450.png','2025-05-07 04:52:03','2025-05-07 04:52:03'), +(4,'제 1공장 공구 및 용접봉 보관 구역','현대기아로 771-9','소모품, 공구류, 용접봉 보관 구역','/uploads/map_image-1746593674259.png','2025-05-07 04:53:59','2025-05-07 04:53:59'), +(5,'ee','ee','ee',NULL,'2025-06-03 22:13:23','2025-06-03 22:13:23'); +/*!40000 ALTER TABLE `FactoryInfo` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `IssueTypes` +-- + +DROP TABLE IF EXISTS `IssueTypes`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `IssueTypes` ( + `issue_type_id` int(11) NOT NULL AUTO_INCREMENT, + `category` varchar(100) NOT NULL, + `subcategory` varchar(100) NOT NULL, + PRIMARY KEY (`issue_type_id`) +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `IssueTypes` +-- + +LOCK TABLES `IssueTypes` WRITE; +/*!40000 ALTER TABLE `IssueTypes` DISABLE KEYS */; +INSERT INTO `IssueTypes` VALUES +(1,'구매팀','자재입고지연'), +(2,'구매팀','자재전달 미흡'), +(3,'품질','검사 내용 전달 미흡'), +(4,'품질','검사오류'), +(5,'설계','설계미스(치수)'), +(6,'설계','설계미스(작업불가)'); +/*!40000 ALTER TABLE `IssueTypes` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `PipeSpecs` +-- + +DROP TABLE IF EXISTS `PipeSpecs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `PipeSpecs` ( + `spec_id` int(11) NOT NULL AUTO_INCREMENT, + `material` varchar(50) NOT NULL COMMENT '재질 (예: SS400, STS304)', + `diameter_in` varchar(10) NOT NULL COMMENT '직경 (inch, 예: 2")', + `schedule` varchar(50) NOT NULL COMMENT '스케줄 (예: STD, SCH10, SCH40)', + PRIMARY KEY (`spec_id`), + UNIQUE KEY `unique_spec` (`material`,`diameter_in`,`schedule`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `PipeSpecs` +-- + +LOCK TABLES `PipeSpecs` WRITE; +/*!40000 ALTER TABLE `PipeSpecs` DISABLE KEYS */; +INSERT INTO `PipeSpecs` VALUES +(2,'516-70N','1','SCH80'), +(1,'A106','3/4','SCH80'); +/*!40000 ALTER TABLE `PipeSpecs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `Processes` +-- + +DROP TABLE IF EXISTS `Processes`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `Processes` ( + `process_id` int(11) NOT NULL AUTO_INCREMENT, + `project_id` int(11) NOT NULL, + `process_name` varchar(255) NOT NULL, + `process_start` date NOT NULL, + `process_end` date DEFAULT NULL, + `planned_worker_count` int(11) NOT NULL, + `process_description` text DEFAULT NULL, + `note` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`process_id`), + KEY `project_id` (`project_id`), + CONSTRAINT `Processes_ibfk_1` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `Processes` +-- + +LOCK TABLES `Processes` WRITE; +/*!40000 ALTER TABLE `Processes` DISABLE KEYS */; +/*!40000 ALTER TABLE `Processes` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `WorkReports` +-- + +DROP TABLE IF EXISTS `WorkReports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `WorkReports` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `project_id` int(11) NOT NULL, + `morning_task_id` int(11) DEFAULT NULL, + `afternoon_task_id` int(11) DEFAULT NULL, + `overtime_hours` decimal(4,1) DEFAULT 0.0, + `overtime_task_id` int(11) DEFAULT NULL, + `work_details` text DEFAULT NULL, + `note` text DEFAULT NULL, + `memo` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `morning_project_id` int(11) DEFAULT NULL, + `afternoon_project_id` int(11) DEFAULT NULL, + `overtime_project_id` int(11) DEFAULT NULL, + `task_id` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `worker_id` (`worker_id`), + KEY `project_id` (`project_id`), + KEY `morning_task_id` (`morning_task_id`), + KEY `afternoon_task_id` (`afternoon_task_id`), + KEY `overtime_task_id` (`overtime_task_id`), + CONSTRAINT `WorkReports_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `WorkReports_ibfk_2` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`), + CONSTRAINT `WorkReports_ibfk_3` FOREIGN KEY (`morning_task_id`) REFERENCES `tasks_old_backup` (`task_id`), + CONSTRAINT `WorkReports_ibfk_4` FOREIGN KEY (`afternoon_task_id`) REFERENCES `tasks_old_backup` (`task_id`), + CONSTRAINT `WorkReports_ibfk_5` FOREIGN KEY (`overtime_task_id`) REFERENCES `tasks_old_backup` (`task_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1766 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `WorkReports` +-- + +LOCK TABLES `WorkReports` WRITE; +/*!40000 ALTER TABLE `WorkReports` DISABLE KEYS */; +INSERT INTO `WorkReports` VALUES +(176,'2025-01-02',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(177,'2025-01-02',2,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(178,'2025-01-02',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(179,'2025-01-02',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(180,'2025-01-02',8,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(181,'2025-01-02',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(182,'2025-01-02',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,9), +(183,'2025-01-02',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:40:56','2025-04-16 05:40:56',NULL,NULL,NULL,15), +(194,'2025-01-03',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(195,'2025-01-03',2,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(196,'2025-01-03',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,15), +(197,'2025-01-03',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(198,'2025-01-03',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,15), +(199,'2025-01-03',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(200,'2025-01-03',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(201,'2025-01-03',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(202,'2025-01-03',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:42:07','2025-04-16 05:42:07',NULL,NULL,NULL,9), +(203,'2025-01-04',7,12,NULL,NULL,NULL,NULL,'휴일근무',NULL,NULL,'2025-04-16 05:43:25','2025-04-16 05:43:25',NULL,NULL,NULL,12), +(204,'2025-01-06',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:03','2025-04-16 05:44:03',NULL,NULL,NULL,12), +(205,'2025-01-06',3,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:03','2025-04-16 05:44:03',NULL,NULL,NULL,12), +(206,'2025-01-06',2,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(207,'2025-01-06',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(208,'2025-01-06',8,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(209,'2025-01-06',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(210,'2025-01-06',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(211,'2025-01-06',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(212,'2025-01-06',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:44:04','2025-04-16 05:44:04',NULL,NULL,NULL,12), +(213,'2025-01-07',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(214,'2025-01-07',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,1), +(215,'2025-01-07',3,12,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(216,'2025-01-07',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(217,'2025-01-07',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,1), +(218,'2025-01-07',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(219,'2025-01-07',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:24','2025-04-16 05:45:24',NULL,NULL,NULL,12), +(220,'2025-01-07',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:25','2025-04-16 05:45:25',NULL,NULL,NULL,12), +(221,'2025-01-07',5,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:45:25','2025-04-16 05:45:25',NULL,NULL,NULL,1), +(222,'2025-01-08',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(223,'2025-01-08',2,2,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,1), +(224,'2025-01-08',3,12,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(225,'2025-01-08',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(226,'2025-01-08',8,2,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,1), +(227,'2025-01-08',9,12,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(228,'2025-01-08',6,12,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(229,'2025-01-08',4,2,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,1), +(230,'2025-01-08',5,12,NULL,NULL,1.0,NULL,'근무',NULL,NULL,'2025-04-16 05:46:50','2025-04-16 05:46:50',NULL,NULL,NULL,13), +(231,'2025-01-09',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(232,'2025-01-09',2,2,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,1), +(233,'2025-01-09',3,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(234,'2025-01-09',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(235,'2025-01-09',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,1), +(236,'2025-01-09',6,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(237,'2025-01-09',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,1), +(238,'2025-01-09',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(239,'2025-01-09',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:48:02','2025-04-16 05:48:02',NULL,NULL,NULL,13), +(240,'2025-01-10',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:16','2025-04-16 05:49:16',NULL,NULL,NULL,13), +(241,'2025-01-10',2,2,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,1), +(242,'2025-01-10',3,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,13), +(243,'2025-01-10',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,13), +(244,'2025-01-10',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,1), +(245,'2025-01-10',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,13), +(246,'2025-01-10',6,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,15), +(247,'2025-01-10',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,1), +(248,'2025-01-10',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:49:17','2025-04-16 05:49:17',NULL,NULL,NULL,13), +(249,'2025-01-13',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,13), +(250,'2025-01-13',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,1), +(251,'2025-01-13',3,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,1), +(252,'2025-01-13',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,13), +(253,'2025-01-13',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,1), +(254,'2025-01-13',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,13), +(255,'2025-01-13',6,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,1), +(256,'2025-01-13',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,15), +(257,'2025-01-13',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:50:22','2025-04-16 05:50:22',NULL,NULL,NULL,13), +(258,'2025-01-14',1,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(259,'2025-01-14',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,1), +(260,'2025-01-14',3,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,1), +(261,'2025-01-14',7,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(262,'2025-01-14',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,1), +(263,'2025-01-14',9,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(265,'2025-01-14',4,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(266,'2025-01-14',5,12,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,13), +(267,'2025-01-14',6,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:51:24','2025-04-16 05:51:24',NULL,NULL,NULL,1), +(268,'2025-01-15',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,1), +(269,'2025-01-15',2,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,14), +(270,'2025-01-15',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,1), +(271,'2025-01-15',7,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,13), +(272,'2025-01-15',8,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,14), +(273,'2025-01-15',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,1), +(275,'2025-01-15',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:37','2025-04-16 05:52:37',NULL,NULL,NULL,1), +(276,'2025-01-15',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:38','2025-04-16 05:52:38',NULL,NULL,NULL,1), +(277,'2025-01-15',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:52:38','2025-04-16 05:52:38',NULL,NULL,NULL,1), +(278,'2025-01-16',1,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,1), +(279,'2025-01-16',2,7,NULL,NULL,NULL,NULL,'근무',NULL,'볼트 보관함 제작','2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,14), +(280,'2025-01-16',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,1), +(281,'2025-01-16',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,1), +(282,'2025-01-16',8,7,NULL,NULL,NULL,NULL,'근무',NULL,'볼트 보관함 제작','2025-04-16 05:54:11','2025-04-16 05:54:11',NULL,NULL,NULL,14), +(283,'2025-01-16',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:12','2025-04-16 05:54:12',NULL,NULL,NULL,1), +(285,'2025-01-16',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:12','2025-04-16 05:54:12',NULL,NULL,NULL,1), +(286,'2025-01-16',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:12','2025-04-16 05:54:12',NULL,NULL,NULL,1), +(287,'2025-01-16',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:54:12','2025-04-16 05:54:12',NULL,NULL,NULL,1), +(288,'2025-01-17',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(289,'2025-01-17',2,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(290,'2025-01-17',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(291,'2025-01-17',7,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(292,'2025-01-17',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(293,'2025-01-17',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(295,'2025-01-17',4,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(296,'2025-01-17',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(297,'2025-01-17',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:55:22','2025-04-16 05:55:22',NULL,NULL,NULL,1), +(298,'2025-01-20',1,7,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,14), +(299,'2025-01-20',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,8), +(300,'2025-01-20',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,1), +(301,'2025-01-20',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,1), +(302,'2025-01-20',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,1), +(303,'2025-01-20',9,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,14), +(304,'2025-01-20',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,1), +(305,'2025-01-20',7,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,14), +(306,'2025-01-20',5,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:58:05','2025-04-16 05:58:05',NULL,NULL,NULL,14), +(307,'2025-01-21',1,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,15), +(308,'2025-01-21',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,8), +(309,'2025-01-21',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,1), +(310,'2025-01-21',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,1), +(311,'2025-01-21',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,8), +(312,'2025-01-21',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,15), +(313,'2025-01-21',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,1), +(314,'2025-01-21',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:06','2025-04-16 05:59:06',NULL,NULL,NULL,1), +(315,'2025-01-21',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 05:59:07','2025-04-16 05:59:07',NULL,NULL,NULL,1), +(316,'2025-01-22',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(317,'2025-01-22',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,8), +(318,'2025-01-22',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(319,'2025-01-22',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(320,'2025-01-22',8,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,8), +(321,'2025-01-22',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(322,'2025-01-22',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(323,'2025-01-22',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,1), +(324,'2025-01-22',5,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:00:28','2025-04-16 06:00:28',NULL,NULL,NULL,8), +(325,'2025-01-23',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(326,'2025-01-23',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,8), +(327,'2025-01-23',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(328,'2025-01-23',7,1,NULL,NULL,NULL,NULL,'조퇴',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(329,'2025-01-23',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(330,'2025-01-23',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(331,'2025-01-23',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(332,'2025-01-23',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,1), +(333,'2025-01-23',5,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:01:57','2025-04-16 06:01:57',NULL,NULL,NULL,8), +(334,'2025-01-24',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(335,'2025-01-24',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,8), +(336,'2025-01-24',3,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(337,'2025-01-24',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(338,'2025-01-24',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(339,'2025-01-24',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(340,'2025-01-24',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(341,'2025-01-24',5,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,8), +(342,'2025-01-24',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:03:43','2025-04-16 06:03:43',NULL,NULL,NULL,1), +(343,'2025-02-03',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(344,'2025-02-03',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,8), +(345,'2025-02-03',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(346,'2025-02-03',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(347,'2025-02-03',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(348,'2025-02-03',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(349,'2025-02-03',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(350,'2025-02-03',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,8), +(351,'2025-02-03',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:07:37','2025-04-16 06:07:37',NULL,NULL,NULL,1), +(352,'2025-02-04',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(353,'2025-02-04',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(354,'2025-02-04',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,8), +(355,'2025-02-04',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(356,'2025-02-04',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(357,'2025-02-04',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(358,'2025-02-04',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(359,'2025-02-04',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,8), +(360,'2025-02-04',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:08:43','2025-04-16 06:08:43',NULL,NULL,NULL,1), +(361,'2025-02-05',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,8), +(362,'2025-02-05',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(363,'2025-02-05',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(364,'2025-02-05',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(365,'2025-02-05',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(366,'2025-02-05',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:02','2025-04-16 06:10:02',NULL,NULL,NULL,1), +(367,'2025-02-05',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:03','2025-04-16 06:10:03',NULL,NULL,NULL,1), +(368,'2025-02-05',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:03','2025-04-16 06:10:03',NULL,NULL,NULL,8), +(369,'2025-02-05',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:03','2025-04-16 06:10:03',NULL,NULL,NULL,1), +(370,'2025-02-06',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(371,'2025-02-06',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,15), +(372,'2025-02-06',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(373,'2025-02-06',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(374,'2025-02-06',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(375,'2025-02-06',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(376,'2025-02-06',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(377,'2025-02-06',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(378,'2025-02-06',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:10:55','2025-04-16 06:10:55',NULL,NULL,NULL,1), +(379,'2025-02-07',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(380,'2025-02-07',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,8), +(381,'2025-02-07',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(382,'2025-02-07',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,15), +(383,'2025-02-07',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(384,'2025-02-07',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(385,'2025-02-07',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(386,'2025-02-07',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,8), +(387,'2025-02-07',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:11:54','2025-04-16 06:11:54',NULL,NULL,NULL,1), +(388,'2025-02-10',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(389,'2025-02-10',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,8), +(390,'2025-02-10',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(391,'2025-02-10',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(392,'2025-02-10',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(393,'2025-02-10',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(394,'2025-02-10',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(395,'2025-02-10',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,8), +(396,'2025-02-10',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:12:54','2025-04-16 06:12:54',NULL,NULL,NULL,1), +(397,'2025-02-11',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(398,'2025-02-11',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,8), +(399,'2025-02-11',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(400,'2025-02-11',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(401,'2025-02-11',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(402,'2025-02-11',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(403,'2025-02-11',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(404,'2025-02-11',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,8), +(405,'2025-02-11',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:13:53','2025-04-16 06:13:53',NULL,NULL,NULL,1), +(406,'2025-02-12',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(407,'2025-02-12',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,8), +(408,'2025-02-12',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(409,'2025-02-12',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(410,'2025-02-12',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(411,'2025-02-12',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(412,'2025-02-12',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,15), +(413,'2025-02-12',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(414,'2025-02-12',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:14:52','2025-04-16 06:14:52',NULL,NULL,NULL,1), +(415,'2025-02-13',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(416,'2025-02-13',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,7), +(417,'2025-02-13',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(418,'2025-02-13',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(419,'2025-02-13',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(420,'2025-02-13',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(421,'2025-02-13',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(422,'2025-02-13',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,7), +(423,'2025-02-13',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:16:00','2025-04-16 06:16:00',NULL,NULL,NULL,1), +(424,'2025-02-14',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(425,'2025-02-14',2,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,7), +(426,'2025-02-14',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(427,'2025-02-14',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(428,'2025-02-14',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(429,'2025-02-14',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(430,'2025-02-14',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(431,'2025-02-14',4,2,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,7), +(432,'2025-02-14',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:17:21','2025-04-16 06:17:21',NULL,NULL,NULL,1), +(433,'2025-02-17',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:39','2025-04-16 06:18:39',NULL,NULL,NULL,1), +(434,'2025-02-17',2,2,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,8), +(435,'2025-02-17',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(436,'2025-02-17',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(437,'2025-02-17',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,15), +(438,'2025-02-17',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(439,'2025-02-17',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(440,'2025-02-17',4,2,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,8), +(441,'2025-02-17',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:18:40','2025-04-16 06:18:40',NULL,NULL,NULL,1), +(442,'2025-02-18',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(443,'2025-02-18',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,15), +(444,'2025-02-18',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(445,'2025-02-18',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(446,'2025-02-18',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(447,'2025-02-18',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(448,'2025-02-18',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,7), +(449,'2025-02-18',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(450,'2025-02-18',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:19:57','2025-04-16 06:19:57',NULL,NULL,NULL,1), +(451,'2025-02-19',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(452,'2025-02-19',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(453,'2025-02-19',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(454,'2025-02-19',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(455,'2025-02-19',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(456,'2025-02-19',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(457,'2025-02-19',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(458,'2025-02-19',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(459,'2025-02-19',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:21:01','2025-04-16 06:21:01',NULL,NULL,NULL,7), +(460,'2025-02-20',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(461,'2025-02-20',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(462,'2025-02-20',3,1,NULL,NULL,NULL,NULL,'조퇴',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(463,'2025-02-20',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(464,'2025-02-20',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(465,'2025-02-20',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(466,'2025-02-20',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(467,'2025-02-20',7,1,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(468,'2025-02-20',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:22:23','2025-04-16 06:22:23',NULL,NULL,NULL,7), +(469,'2025-02-21',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(470,'2025-02-21',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(471,'2025-02-21',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(472,'2025-02-21',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(473,'2025-02-21',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(474,'2025-02-21',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(475,'2025-02-21',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(476,'2025-02-21',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(477,'2025-02-21',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:23:40','2025-04-16 06:23:40',NULL,NULL,NULL,7), +(478,'2025-02-24',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(479,'2025-02-24',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(480,'2025-02-24',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(481,'2025-02-24',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(482,'2025-02-24',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(483,'2025-02-24',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(484,'2025-02-24',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(485,'2025-02-24',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:32','2025-04-16 06:24:32',NULL,NULL,NULL,7), +(486,'2025-02-24',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:24:33','2025-04-16 06:24:33',NULL,NULL,NULL,7), +(487,'2025-02-24',10,1,NULL,NULL,NULL,NULL,'근무',NULL,'근무시작','2025-04-16 06:25:07','2025-04-16 06:25:07',NULL,NULL,NULL,7), +(488,'2025-02-25',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(489,'2025-02-25',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(490,'2025-02-25',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(491,'2025-02-25',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(492,'2025-02-25',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(493,'2025-02-25',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(494,'2025-02-25',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(495,'2025-02-25',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(496,'2025-02-25',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(497,'2025-02-25',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:26:02','2025-04-16 06:26:02',NULL,NULL,NULL,7), +(498,'2025-02-26',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'당진출장 건','2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,14), +(499,'2025-02-26',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(500,'2025-02-26',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(501,'2025-02-26',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'당진출장 건','2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,14), +(502,'2025-02-26',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(503,'2025-02-26',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(504,'2025-02-26',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(505,'2025-02-26',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,15), +(506,'2025-02-26',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(507,'2025-02-26',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:27:50','2025-04-16 06:27:50',NULL,NULL,NULL,7), +(508,'2025-02-27',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(509,'2025-02-27',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(510,'2025-02-27',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(511,'2025-02-27',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(512,'2025-02-27',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(513,'2025-02-27',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(514,'2025-02-27',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(515,'2025-02-27',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(516,'2025-02-27',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(517,'2025-02-27',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:28:41','2025-04-16 06:28:41',NULL,NULL,NULL,7), +(518,'2025-02-28',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,13), +(519,'2025-02-28',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(520,'2025-02-28',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(521,'2025-02-28',7,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,13), +(522,'2025-02-28',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(523,'2025-02-28',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(524,'2025-02-28',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(525,'2025-02-28',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(526,'2025-02-28',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,15), +(527,'2025-02-28',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:29:53','2025-04-16 06:29:53',NULL,NULL,NULL,7), +(528,'2025-03-04',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(529,'2025-03-04',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(530,'2025-03-04',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,8), +(531,'2025-03-04',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,15), +(532,'2025-03-04',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(533,'2025-03-04',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(534,'2025-03-04',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(535,'2025-03-04',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(536,'2025-03-04',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,7), +(537,'2025-03-04',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:32:11','2025-04-16 06:32:11',NULL,NULL,NULL,8), +(538,'2025-03-05',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(539,'2025-03-05',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(540,'2025-03-05',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,8), +(541,'2025-03-05',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(542,'2025-03-05',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(543,'2025-03-05',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(544,'2025-03-05',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(545,'2025-03-05',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,15), +(546,'2025-03-05',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,7), +(547,'2025-03-05',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:33:15','2025-04-16 06:33:15',NULL,NULL,NULL,8), +(548,'2025-03-06',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(549,'2025-03-06',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(550,'2025-03-06',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,8), +(551,'2025-03-06',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,15), +(552,'2025-03-06',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(553,'2025-03-06',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(554,'2025-03-06',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(555,'2025-03-06',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(556,'2025-03-06',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,7), +(557,'2025-03-06',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:34:18','2025-04-16 06:34:18',NULL,NULL,NULL,8), +(558,'2025-03-07',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(559,'2025-03-07',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,13), +(560,'2025-03-07',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,8), +(561,'2025-03-07',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,15), +(562,'2025-03-07',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(563,'2025-03-07',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(564,'2025-03-07',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(565,'2025-03-07',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,13), +(566,'2025-03-07',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,7), +(567,'2025-03-07',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:35:36','2025-04-16 06:35:36',NULL,NULL,NULL,8), +(568,'2025-03-10',1,1,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,8), +(569,'2025-03-10',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,3), +(570,'2025-03-10',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,8), +(571,'2025-03-10',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,15), +(572,'2025-03-10',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,7), +(573,'2025-03-10',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,15), +(574,'2025-03-10',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,7), +(575,'2025-03-10',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,3), +(576,'2025-03-10',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,8), +(577,'2025-03-10',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:37:11','2025-04-16 06:37:11',NULL,NULL,NULL,8), +(578,'2025-03-11',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:06','2025-04-16 06:39:06',NULL,NULL,NULL,8), +(579,'2025-03-11',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(580,'2025-03-11',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(581,'2025-03-11',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,7), +(582,'2025-03-11',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,7), +(583,'2025-03-11',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,15), +(584,'2025-03-11',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,7), +(585,'2025-03-11',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(586,'2025-03-11',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(587,'2025-03-11',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:39:07','2025-04-16 06:39:07',NULL,NULL,NULL,8), +(588,'2025-03-12',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(589,'2025-03-12',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(590,'2025-03-12',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(591,'2025-03-12',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(592,'2025-03-12',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,7), +(593,'2025-03-12',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,15), +(594,'2025-03-12',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,7), +(595,'2025-03-12',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,7), +(596,'2025-03-12',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(597,'2025-03-12',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:40:08','2025-04-16 06:40:08',NULL,NULL,NULL,8), +(598,'2025-03-13',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,8), +(599,'2025-03-13',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,8), +(600,'2025-03-13',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,8), +(601,'2025-03-13',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,7), +(602,'2025-03-13',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,7), +(603,'2025-03-13',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,15), +(604,'2025-03-13',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:07','2025-04-16 06:41:07',NULL,NULL,NULL,7), +(605,'2025-03-13',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:08','2025-04-16 06:41:08',NULL,NULL,NULL,8), +(606,'2025-03-13',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:08','2025-04-16 06:41:08',NULL,NULL,NULL,8), +(607,'2025-03-13',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:41:08','2025-04-16 06:41:08',NULL,NULL,NULL,8), +(608,'2025-03-14',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,8), +(609,'2025-03-14',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,4), +(610,'2025-03-14',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,8), +(612,'2025-03-14',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,7), +(613,'2025-03-14',9,13,NULL,NULL,NULL,NULL,'유급',NULL,'결혼(5일)','2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,15), +(614,'2025-03-14',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,7), +(615,'2025-03-14',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,8), +(616,'2025-03-14',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,8), +(617,'2025-03-14',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:42:24','2025-04-16 06:42:24',NULL,NULL,NULL,7), +(628,'2025-03-18',1,1,NULL,NULL,NULL,NULL,'조퇴',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(629,'2025-03-18',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,4), +(630,'2025-03-18',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(631,'2025-03-18',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,4), +(632,'2025-03-18',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(633,'2025-03-18',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,15), +(634,'2025-03-18',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(635,'2025-03-18',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,4), +(636,'2025-03-18',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(637,'2025-03-18',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:46:29','2025-04-16 06:46:29',NULL,NULL,NULL,8), +(648,'2025-03-17',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,8), +(649,'2025-03-17',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,4), +(650,'2025-03-17',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,8), +(651,'2025-03-17',7,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,4), +(652,'2025-03-17',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,7), +(653,'2025-03-17',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,15), +(654,'2025-03-17',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,7), +(655,'2025-03-17',4,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,8), +(656,'2025-03-17',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,8), +(657,'2025-03-17',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:50:50','2025-04-16 06:50:50',NULL,NULL,NULL,7), +(658,'2025-03-19',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,4), +(659,'2025-03-19',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,8), +(660,'2025-03-19',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,8), +(661,'2025-03-19',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,4), +(662,'2025-03-19',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:33','2025-04-16 06:52:33',NULL,NULL,NULL,8), +(663,'2025-03-19',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,8), +(664,'2025-03-19',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,8), +(665,'2025-03-19',4,7,NULL,NULL,NULL,NULL,'근무',NULL,'용접기 보관함 제작','2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,14), +(666,'2025-03-19',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,4), +(667,'2025-03-19',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:52:34','2025-04-16 06:52:34',NULL,NULL,NULL,8), +(668,'2025-03-20',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(669,'2025-03-20',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,4), +(670,'2025-03-20',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(671,'2025-03-20',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,4), +(672,'2025-03-20',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,4), +(673,'2025-03-20',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(674,'2025-03-20',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(675,'2025-03-20',4,7,NULL,NULL,2.0,NULL,'근무',NULL,'용접기 보관함 제작','2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,14), +(676,'2025-03-20',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,4), +(677,'2025-03-20',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 06:54:20','2025-04-16 06:54:20',NULL,NULL,NULL,8), +(678,'2025-03-21',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:27','2025-04-16 21:34:27',NULL,NULL,NULL,8), +(679,'2025-03-21',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,4), +(680,'2025-03-21',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(681,'2025-03-21',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(682,'2025-03-21',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,4), +(683,'2025-03-21',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(684,'2025-03-21',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(685,'2025-03-21',4,7,NULL,NULL,NULL,NULL,'근무',NULL,'용기 보관함 제작','2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,14), +(686,'2025-03-21',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,4), +(687,'2025-03-21',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:34:28','2025-04-16 21:34:28',NULL,NULL,NULL,8), +(688,'2025-03-24',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,8), +(689,'2025-03-24',2,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,5), +(690,'2025-03-24',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,8), +(691,'2025-03-24',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,5), +(692,'2025-03-24',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,5), +(693,'2025-03-24',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:47','2025-04-16 21:39:47',NULL,NULL,NULL,8), +(694,'2025-03-24',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:48','2025-04-16 21:39:48',NULL,NULL,NULL,8), +(695,'2025-03-24',4,7,NULL,NULL,2.0,NULL,'근무',NULL,'용기 보관함 제작','2025-04-16 21:39:48','2025-04-16 21:39:48',NULL,NULL,NULL,14), +(696,'2025-03-24',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:48','2025-04-16 21:39:48',NULL,NULL,NULL,8), +(697,'2025-03-24',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:39:48','2025-04-16 21:39:48',NULL,NULL,NULL,8), +(698,'2025-03-25',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(699,'2025-03-25',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,5), +(700,'2025-03-25',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(701,'2025-03-25',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,5), +(702,'2025-03-25',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(703,'2025-03-25',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(704,'2025-03-25',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(705,'2025-03-25',4,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,14), +(706,'2025-03-25',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,5), +(707,'2025-03-25',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:42:13','2025-04-16 21:42:13',NULL,NULL,NULL,13), +(708,'2025-03-26',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,13), +(709,'2025-03-26',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,15), +(710,'2025-03-26',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,5), +(711,'2025-03-26',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,5), +(712,'2025-03-26',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,8), +(713,'2025-03-26',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,8), +(714,'2025-03-26',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,8), +(715,'2025-03-26',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,13), +(716,'2025-03-26',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,5), +(717,'2025-03-26',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:43:37','2025-04-16 21:43:37',NULL,NULL,NULL,8), +(718,'2025-03-27',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(719,'2025-03-27',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,5), +(720,'2025-03-27',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(721,'2025-03-27',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,5), +(722,'2025-03-27',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,5), +(723,'2025-03-27',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(724,'2025-03-27',10,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,15), +(725,'2025-03-27',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,5), +(726,'2025-03-27',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(727,'2025-03-27',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-16 21:45:14','2025-04-16 21:45:14',NULL,NULL,NULL,8), +(728,'2025-03-28',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(729,'2025-03-28',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,5), +(730,'2025-03-28',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,15), +(731,'2025-03-28',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,15), +(732,'2025-03-28',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(733,'2025-03-28',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(734,'2025-03-28',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(735,'2025-03-28',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,5), +(736,'2025-03-28',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,5), +(737,'2025-03-28',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:46:31','2025-04-16 21:46:31',NULL,NULL,NULL,8), +(738,'2025-03-31',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(739,'2025-03-31',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,5), +(740,'2025-03-31',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(741,'2025-03-31',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(742,'2025-03-31',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(743,'2025-03-31',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(744,'2025-03-31',10,13,NULL,NULL,NULL,NULL,'유급',NULL,'외조모상(2일)','2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,15), +(745,'2025-03-31',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,5), +(746,'2025-03-31',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(747,'2025-03-31',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-16 21:47:37','2025-04-16 21:47:37',NULL,NULL,NULL,8), +(748,'2025-03-14',7,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-17 01:53:24','2025-04-17 01:53:24',NULL,NULL,NULL,4), +(749,'2025-04-01',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(750,'2025-04-01',2,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,5), +(751,'2025-04-01',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(752,'2025-04-01',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,5), +(753,'2025-04-01',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(754,'2025-04-01',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(755,'2025-04-01',10,13,NULL,NULL,NULL,NULL,'유급',NULL,'외조모상','2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,15), +(756,'2025-04-01',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,5), +(757,'2025-04-01',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:42','2025-04-17 04:22:42',NULL,NULL,NULL,9), +(758,'2025-04-01',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:22:43','2025-04-17 04:22:43',NULL,NULL,NULL,9), +(769,'2025-04-02',1,1,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-17 04:25:55','2025-04-17 04:25:55',NULL,NULL,NULL,9), +(770,'2025-04-02',2,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(771,'2025-04-02',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(773,'2025-04-02',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(774,'2025-04-02',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(775,'2025-04-02',10,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,15), +(776,'2025-04-02',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,15), +(777,'2025-04-02',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(778,'2025-04-02',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:25:56','2025-04-17 04:25:56',NULL,NULL,NULL,9), +(779,'2025-04-03',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(780,'2025-04-03',2,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(781,'2025-04-03',3,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(783,'2025-04-03',8,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(784,'2025-04-03',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(785,'2025-04-03',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(786,'2025-04-03',4,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(787,'2025-04-03',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(788,'2025-04-03',6,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:27:12','2025-04-17 04:27:12',NULL,NULL,NULL,9), +(789,'2025-04-04',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(790,'2025-04-04',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(791,'2025-04-04',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,5), +(792,'2025-04-04',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(793,'2025-04-04',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,5), +(794,'2025-04-04',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(795,'2025-04-04',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(796,'2025-04-04',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(797,'2025-04-04',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,9), +(798,'2025-04-04',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:30:07','2025-04-17 04:30:07',NULL,NULL,NULL,5), +(799,'2025-04-07',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(800,'2025-04-07',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(801,'2025-04-07',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,5), +(802,'2025-04-07',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(803,'2025-04-07',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,5), +(804,'2025-04-07',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(805,'2025-04-07',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(806,'2025-04-07',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(807,'2025-04-07',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,9), +(808,'2025-04-07',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:39:43','2025-04-17 04:39:43',NULL,NULL,NULL,5), +(809,'2025-04-08',1,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(811,'2025-04-08',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,5), +(812,'2025-04-08',7,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(813,'2025-04-08',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,5), +(814,'2025-04-08',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(815,'2025-04-08',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(816,'2025-04-08',4,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(817,'2025-04-08',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,9), +(818,'2025-04-08',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:41:16','2025-04-17 04:41:16',NULL,NULL,NULL,5), +(819,'2025-04-09',1,1,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-17 04:43:02','2025-04-17 04:43:02',NULL,NULL,NULL,9), +(820,'2025-04-09',2,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:02','2025-04-17 04:43:02',NULL,NULL,NULL,9), +(821,'2025-04-09',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,5), +(822,'2025-04-09',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(823,'2025-04-09',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,5), +(824,'2025-04-09',9,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(825,'2025-04-09',10,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(826,'2025-04-09',4,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(827,'2025-04-09',5,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,9), +(828,'2025-04-09',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-04-17 04:43:03','2025-04-17 04:43:03',NULL,NULL,NULL,5), +(829,'2025-04-10',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(830,'2025-04-10',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(831,'2025-04-10',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,5), +(832,'2025-04-10',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(833,'2025-04-10',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,5), +(834,'2025-04-10',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(835,'2025-04-10',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(836,'2025-04-10',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(837,'2025-04-10',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,9), +(838,'2025-04-10',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:44:30','2025-04-17 04:44:30',NULL,NULL,NULL,5), +(839,'2025-04-11',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:24','2025-04-17 04:46:24',NULL,NULL,NULL,9), +(840,'2025-04-11',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:24','2025-04-17 04:46:24',NULL,NULL,NULL,9), +(841,'2025-04-11',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:24','2025-04-17 04:46:24',NULL,NULL,NULL,5), +(842,'2025-04-11',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,9), +(843,'2025-04-11',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,5), +(844,'2025-04-11',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,15), +(845,'2025-04-11',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,5), +(846,'2025-04-11',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,9), +(847,'2025-04-11',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,15), +(848,'2025-04-11',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:46:25','2025-04-17 04:46:25',NULL,NULL,NULL,9), +(849,'2025-04-14',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:37','2025-04-17 04:47:37',NULL,NULL,NULL,9), +(850,'2025-04-14',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:37','2025-04-17 04:47:37',NULL,NULL,NULL,9), +(851,'2025-04-14',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:37','2025-04-17 04:47:37',NULL,NULL,NULL,5), +(852,'2025-04-14',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:37','2025-04-17 04:47:37',NULL,NULL,NULL,9), +(853,'2025-04-14',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,5), +(854,'2025-04-14',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(855,'2025-04-14',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(856,'2025-04-14',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(857,'2025-04-14',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(858,'2025-04-14',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:47:38','2025-04-17 04:47:38',NULL,NULL,NULL,9), +(859,'2025-04-17',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(860,'2025-04-17',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,5), +(861,'2025-04-17',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,5), +(862,'2025-04-17',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(863,'2025-04-17',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,5), +(864,'2025-04-17',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(865,'2025-04-17',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(866,'2025-04-17',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(867,'2025-04-17',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,9), +(868,'2025-04-17',6,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-04-17 04:48:39','2025-04-17 04:48:39',NULL,NULL,NULL,5), +(879,'2025-04-21',1,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,14), +(880,'2025-04-21',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(881,'2025-04-21',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(882,'2025-04-21',7,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,14), +(883,'2025-04-21',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(884,'2025-04-21',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(885,'2025-04-21',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(886,'2025-04-21',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(887,'2025-04-21',5,7,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,14), +(888,'2025-04-21',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-21 06:22:20','2025-04-21 06:22:20',NULL,NULL,NULL,5), +(889,'2025-04-22',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'ICK 크레인 공사','2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,14), +(890,'2025-04-22',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(891,'2025-04-22',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(892,'2025-04-22',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'ICK 크레인 공사','2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,14), +(893,'2025-04-22',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(894,'2025-04-22',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(895,'2025-04-22',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(896,'2025-04-22',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(897,'2025-04-22',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'ICK 크레인 공사','2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,14), +(898,'2025-04-22',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-22 01:49:11','2025-04-22 01:49:11',NULL,NULL,NULL,5), +(899,'2025-04-23',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,14), +(900,'2025-04-23',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(901,'2025-04-23',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(902,'2025-04-23',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,14), +(903,'2025-04-23',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(904,'2025-04-23',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(905,'2025-04-23',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(906,'2025-04-23',4,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(907,'2025-04-23',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,14), +(908,'2025-04-23',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-23 06:57:29','2025-04-23 06:57:29',NULL,NULL,NULL,5), +(909,'2025-04-24',1,1,NULL,NULL,NULL,NULL,'근무',NULL,'벨브 부적합 관련 작업 추가','2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(910,'2025-04-24',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(911,'2025-04-24',3,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(912,'2025-04-24',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(913,'2025-04-24',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(914,'2025-04-24',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(915,'2025-04-24',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(916,'2025-04-24',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(917,'2025-04-24',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(918,'2025-04-24',6,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-24 05:42:30','2025-04-24 05:42:30',NULL,NULL,NULL,9), +(919,'2025-04-25',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(920,'2025-04-25',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(921,'2025-04-25',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,5), +(922,'2025-04-25',7,1,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(923,'2025-04-25',8,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(924,'2025-04-25',9,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(925,'2025-04-25',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(926,'2025-04-25',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'확관 작업','2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,5), +(927,'2025-04-25',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:38','2025-04-25 04:23:38',NULL,NULL,NULL,9), +(928,'2025-04-25',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-25 04:23:39','2025-04-25 04:23:39',NULL,NULL,NULL,5), +(929,'2025-04-28',1,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:22','2025-04-28 23:20:22',NULL,NULL,NULL,9), +(930,'2025-04-28',2,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(931,'2025-04-28',3,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(932,'2025-04-28',7,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(934,'2025-04-28',9,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(935,'2025-04-28',10,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(936,'2025-04-28',4,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(937,'2025-04-28',5,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(938,'2025-04-28',6,1,NULL,NULL,NULL,NULL,'근무',NULL,'NCR 벨브 라인 설치','2025-04-28 23:20:23','2025-04-28 23:20:23',NULL,NULL,NULL,9), +(939,'2025-04-29',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,9), +(940,'2025-04-29',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(941,'2025-04-29',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(942,'2025-04-29',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,9), +(943,'2025-04-29',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(944,'2025-04-29',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(945,'2025-04-29',10,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,14), +(946,'2025-04-29',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(947,'2025-04-29',8,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(948,'2025-04-29',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-29 04:41:11','2025-04-29 04:41:11',NULL,NULL,NULL,16), +(949,'2025-04-30',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,14), +(950,'2025-04-30',2,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,16), +(951,'2025-04-30',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,16), +(953,'2025-04-30',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,15), +(954,'2025-04-30',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,16), +(955,'2025-04-30',10,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,14), +(956,'2025-04-30',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,14), +(957,'2025-04-30',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,15), +(958,'2025-04-30',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-04-30 03:43:51','2025-04-30 03:43:51',NULL,NULL,NULL,16), +(959,'2025-04-30',4,7,NULL,NULL,NULL,NULL,'반반차',NULL,'제2공장 공사','2025-04-30 04:22:04','2025-04-30 04:22:04',NULL,NULL,NULL,14), +(1023,'2025-04-15',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1024,'2025-04-15',2,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1025,'2025-04-15',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1026,'2025-04-15',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1027,'2025-04-15',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1028,'2025-04-15',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1029,'2025-04-15',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1030,'2025-04-15',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1031,'2025-04-15',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,5), +(1032,'2025-04-15',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:01:35','2025-05-07 01:01:35',NULL,NULL,NULL,9), +(1033,'2025-04-16',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1034,'2025-04-16',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,5), +(1035,'2025-04-16',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,5), +(1036,'2025-04-16',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1037,'2025-04-16',5,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1038,'2025-04-16',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,5), +(1039,'2025-04-16',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1040,'2025-04-16',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,15), +(1041,'2025-04-16',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,5), +(1042,'2025-04-16',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:03:57','2025-05-07 01:03:57',NULL,NULL,NULL,9), +(1043,'2025-04-18',1,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,9), +(1044,'2025-04-18',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1045,'2025-04-18',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1046,'2025-04-18',4,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,9), +(1047,'2025-04-18',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,15), +(1048,'2025-04-18',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1049,'2025-04-18',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,9), +(1050,'2025-04-18',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1051,'2025-04-18',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,5), +(1052,'2025-04-18',10,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 01:05:17','2025-05-07 01:05:17',NULL,NULL,NULL,9), +(1053,'2025-04-02',7,1,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-07 02:19:00','2025-05-07 02:19:00',NULL,NULL,NULL,9), +(1054,'2025-04-03',7,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 02:19:45','2025-05-07 02:19:45',NULL,NULL,NULL,9), +(1055,'2025-04-08',2,1,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 02:20:22','2025-05-07 02:20:22',NULL,NULL,NULL,9), +(1056,'2025-04-28',8,1,NULL,NULL,NULL,NULL,'반반차',NULL,'NCR 벨브라인 설치','2025-05-07 02:21:44','2025-05-07 02:21:44',NULL,NULL,NULL,9), +(1057,'2025-05-02',1,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1058,'2025-05-02',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1059,'2025-05-02',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1060,'2025-05-02',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1061,'2025-05-02',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1062,'2025-05-02',6,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1063,'2025-05-02',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1064,'2025-05-02',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1065,'2025-05-02',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1066,'2025-05-02',10,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-07 03:13:26','2025-05-07 03:13:26',NULL,NULL,NULL,15), +(1067,'2025-05-07',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,14), +(1068,'2025-05-07',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1069,'2025-05-07',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1070,'2025-05-07',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1071,'2025-05-07',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,14), +(1072,'2025-05-07',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1073,'2025-05-07',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,14), +(1074,'2025-05-07',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1075,'2025-05-07',9,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,14), +(1076,'2025-05-07',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 03:19:18','2025-05-07 03:19:18',NULL,NULL,NULL,16), +(1078,'2025-05-08',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1079,'2025-05-08',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1080,'2025-05-08',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1081,'2025-05-08',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,14), +(1082,'2025-05-08',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1083,'2025-05-08',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,14), +(1084,'2025-05-08',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1085,'2025-05-08',9,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,14), +(1086,'2025-05-08',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-07 23:06:52','2025-05-07 23:06:52',NULL,NULL,NULL,16), +(1087,'2025-05-08',1,7,NULL,NULL,NULL,NULL,'반반차',NULL,'작업장 구역 설치','2025-05-08 06:57:51','2025-05-08 06:57:51',NULL,NULL,NULL,14), +(1088,'2025-05-09',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,14), +(1089,'2025-05-09',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1090,'2025-05-09',3,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1091,'2025-05-09',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1092,'2025-05-09',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,14), +(1093,'2025-05-09',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1094,'2025-05-09',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,14), +(1095,'2025-05-09',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1096,'2025-05-09',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,16), +(1097,'2025-05-09',10,7,NULL,NULL,NULL,NULL,'근무',NULL,'작업장 구역 정리','2025-05-09 06:12:16','2025-05-09 06:12:16',NULL,NULL,NULL,14), +(1100,'2025-05-12',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-11 21:52:46','2025-05-11 21:52:46',NULL,NULL,NULL,15), +(1108,'2025-05-12',1,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1111,'2025-05-12',5,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1113,'2025-05-12',7,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1115,'2025-05-12',9,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1116,'2025-05-12',10,1,NULL,NULL,NULL,NULL,'근무',NULL,'포장','2025-05-12 23:55:17','2025-05-12 23:55:17',NULL,NULL,NULL,13), +(1117,'2025-05-13',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,14), +(1118,'2025-05-13',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,3), +(1119,'2025-05-13',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,7), +(1120,'2025-05-13',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,3), +(1121,'2025-05-13',5,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,14), +(1122,'2025-05-13',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,7), +(1123,'2025-05-13',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,14), +(1124,'2025-05-13',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,7), +(1125,'2025-05-13',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,3), +(1126,'2025-05-13',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:00:41','2025-05-13 00:00:41',NULL,NULL,NULL,7), +(1127,'2025-05-12',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:01:44','2025-05-13 00:01:44',NULL,NULL,NULL,3), +(1128,'2025-05-12',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:01:44','2025-05-13 00:01:44',NULL,NULL,NULL,3), +(1129,'2025-05-12',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:01:44','2025-05-13 00:01:44',NULL,NULL,NULL,3), +(1130,'2025-05-12',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-13 00:01:44','2025-05-13 00:01:44',NULL,NULL,NULL,3), +(1131,'2025-05-14',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,3), +(1132,'2025-05-14',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,3), +(1133,'2025-05-14',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1134,'2025-05-14',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1135,'2025-05-14',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1136,'2025-05-14',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,3), +(1137,'2025-05-14',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,3), +(1138,'2025-05-14',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1139,'2025-05-14',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1140,'2025-05-14',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-14 22:42:17','2025-05-14 22:42:17',NULL,NULL,NULL,7), +(1141,'2025-05-15',1,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,14), +(1142,'2025-05-15',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,3), +(1143,'2025-05-15',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1144,'2025-05-15',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1145,'2025-05-15',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1146,'2025-05-15',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1147,'2025-05-15',7,7,NULL,NULL,NULL,NULL,'근무',NULL,'제2공장 공사','2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,14), +(1148,'2025-05-15',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,3), +(1149,'2025-05-15',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,3), +(1150,'2025-05-15',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:53:53','2025-05-16 02:53:53',NULL,NULL,NULL,7), +(1151,'2025-05-16',1,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1152,'2025-05-16',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,3), +(1153,'2025-05-16',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1154,'2025-05-16',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1155,'2025-05-16',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1156,'2025-05-16',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1157,'2025-05-16',7,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1158,'2025-05-16',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,3), +(1159,'2025-05-16',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,3), +(1160,'2025-05-16',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-16 02:55:12','2025-05-16 02:55:12',NULL,NULL,NULL,7), +(1171,'2025-05-19',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1172,'2025-05-19',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,4), +(1173,'2025-05-19',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1174,'2025-05-19',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1175,'2025-05-19',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1176,'2025-05-19',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1177,'2025-05-19',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1179,'2025-05-19',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1180,'2025-05-19',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:47:56','2025-05-22 04:47:56',NULL,NULL,NULL,7), +(1181,'2025-05-21',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1183,'2025-05-21',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1184,'2025-05-21',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1185,'2025-05-21',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1186,'2025-05-21',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1187,'2025-05-21',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1188,'2025-05-21',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1189,'2025-05-21',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1190,'2025-05-21',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:49:38','2025-05-22 04:49:38',NULL,NULL,NULL,7), +(1191,'2025-05-20',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1192,'2025-05-20',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,3), +(1193,'2025-05-20',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1194,'2025-05-20',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1195,'2025-05-20',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1196,'2025-05-20',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1197,'2025-05-20',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1198,'2025-05-20',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1199,'2025-05-20',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1200,'2025-05-20',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-05-22 04:51:34','2025-05-22 04:51:34',NULL,NULL,NULL,7), +(1201,'2025-05-22',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1202,'2025-05-22',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,3), +(1203,'2025-05-22',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1204,'2025-05-22',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1205,'2025-05-22',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1206,'2025-05-22',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1207,'2025-05-22',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1208,'2025-05-22',8,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1209,'2025-05-22',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1210,'2025-05-22',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-05-22 04:53:17','2025-05-22 04:53:17',NULL,NULL,NULL,7), +(1211,'2025-05-21',2,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-22 04:54:12','2025-05-22 04:54:12',NULL,NULL,NULL,15), +(1215,'2025-05-26',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-05-26 06:58:00','2025-05-26 06:58:00',NULL,NULL,NULL,15), +(1222,'2025-05-19',8,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-01 22:34:36','2025-06-01 22:34:36',NULL,NULL,NULL,3), +(1223,'2025-05-26',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1224,'2025-05-26',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,5), +(1225,'2025-05-26',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1226,'2025-05-26',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,5), +(1227,'2025-05-26',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1228,'2025-05-26',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1229,'2025-05-26',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,5), +(1230,'2025-05-26',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1231,'2025-05-26',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:37:29','2025-06-01 22:37:29',NULL,NULL,NULL,8), +(1232,'2025-05-23',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1233,'2025-05-23',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,3), +(1234,'2025-05-23',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1235,'2025-05-23',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1236,'2025-05-23',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1237,'2025-05-23',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1238,'2025-05-23',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1239,'2025-05-23',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1240,'2025-05-23',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1241,'2025-05-23',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:41:30','2025-06-01 22:41:30',NULL,NULL,NULL,8), +(1242,'2025-05-27',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1243,'2025-05-27',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,5), +(1244,'2025-05-27',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1245,'2025-05-27',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1246,'2025-05-27',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,5), +(1247,'2025-05-27',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1248,'2025-05-27',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1249,'2025-05-27',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,5), +(1250,'2025-05-27',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1251,'2025-05-27',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:45:06','2025-06-01 22:45:06',NULL,NULL,NULL,8), +(1252,'2025-05-28',1,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-06-01 22:46:40','2025-06-01 22:46:40',NULL,NULL,NULL,8), +(1258,'2025-05-28',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:46:40','2025-06-01 22:46:40',NULL,NULL,NULL,8), +(1262,'2025-05-28',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,5), +(1263,'2025-05-28',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1264,'2025-05-28',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1265,'2025-05-28',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,5), +(1266,'2025-05-28',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1267,'2025-05-28',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,5), +(1268,'2025-05-28',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1269,'2025-05-28',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:48:21','2025-06-01 22:48:21',NULL,NULL,NULL,8), +(1270,'2025-05-29',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1271,'2025-05-29',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,5), +(1272,'2025-05-29',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1273,'2025-05-29',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1274,'2025-05-29',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,5), +(1275,'2025-05-29',6,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1276,'2025-05-29',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1277,'2025-05-29',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,5), +(1278,'2025-05-29',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1279,'2025-05-29',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-01 22:49:55','2025-06-01 22:49:55',NULL,NULL,NULL,8), +(1281,'2025-05-30',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,5), +(1282,'2025-05-30',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1283,'2025-05-30',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1284,'2025-05-30',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,5), +(1285,'2025-05-30',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1286,'2025-05-30',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1287,'2025-05-30',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,5), +(1288,'2025-05-30',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1289,'2025-05-30',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:50:53','2025-06-01 22:50:53',NULL,NULL,NULL,8), +(1290,'2025-06-02',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:18','2025-06-01 22:52:18',NULL,NULL,NULL,8), +(1291,'2025-06-02',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,5), +(1292,'2025-06-02',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1293,'2025-06-02',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1294,'2025-06-02',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,15), +(1295,'2025-06-02',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1296,'2025-06-02',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1297,'2025-06-02',8,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,15), +(1298,'2025-06-02',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,8), +(1299,'2025-06-02',10,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-01 22:52:19','2025-06-01 22:52:19',NULL,NULL,NULL,15), +(1300,'2025-05-30',1,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-01 23:17:51','2025-06-01 23:17:51',NULL,NULL,NULL,8), +(1301,'2025-01-02',5,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-01 23:31:26','2025-06-01 23:31:26',NULL,NULL,NULL,15), +(1302,'2025-06-04',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1303,'2025-06-04',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,5), +(1304,'2025-06-04',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1305,'2025-06-04',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,15), +(1306,'2025-06-04',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1307,'2025-06-04',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,5), +(1308,'2025-06-04',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1309,'2025-06-04',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,5), +(1310,'2025-06-04',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1311,'2025-06-04',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-04 22:13:30','2025-06-04 22:13:30',NULL,NULL,NULL,8), +(1312,'2025-06-09',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:28',NULL,NULL,NULL,8), +(1313,'2025-06-09',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,5), +(1314,'2025-06-09',3,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:30',NULL,NULL,NULL,8), +(1315,'2025-06-09',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,5), +(1316,'2025-06-09',5,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:31',NULL,NULL,NULL,8), +(1317,'2025-06-09',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,5), +(1318,'2025-06-09',7,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:32',NULL,NULL,NULL,8), +(1319,'2025-06-09',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,5), +(1320,'2025-06-09',9,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-09 06:47:48','2025-06-09 06:47:48',NULL,NULL,NULL,15), +(1321,'2025-06-09',10,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-09 06:47:48','2025-06-13 03:43:34',NULL,NULL,NULL,8), +(1322,'2025-06-10',1,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:03','2025-06-13 03:43:51',NULL,NULL,NULL,8), +(1323,'2025-06-10',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-10 08:47:03','2025-06-10 08:47:03',NULL,NULL,NULL,5), +(1324,'2025-06-10',3,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:03','2025-06-13 03:43:53',NULL,NULL,NULL,8), +(1325,'2025-06-10',4,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:04','2025-06-13 03:43:54',NULL,NULL,NULL,8), +(1326,'2025-06-10',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-10 08:47:04','2025-06-10 08:47:04',NULL,NULL,NULL,5), +(1327,'2025-06-10',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-10 08:47:04','2025-06-10 08:47:04',NULL,NULL,NULL,5), +(1328,'2025-06-10',7,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:04','2025-06-13 03:43:55',NULL,NULL,NULL,8), +(1329,'2025-06-10',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-10 08:47:04','2025-06-10 08:47:04',NULL,NULL,NULL,5), +(1330,'2025-06-10',9,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:04','2025-06-13 03:43:56',NULL,NULL,NULL,8), +(1331,'2025-06-10',10,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-10 08:47:04','2025-06-13 03:43:56',NULL,NULL,NULL,8), +(1332,'2025-06-11',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:18',NULL,NULL,NULL,8), +(1333,'2025-06-11',2,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-11 07:59:16','2025-06-11 07:59:16',NULL,NULL,NULL,5), +(1334,'2025-06-11',3,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:19',NULL,NULL,NULL,8), +(1335,'2025-06-11',4,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:20',NULL,NULL,NULL,8), +(1336,'2025-06-11',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-11 07:59:16','2025-06-11 07:59:16',NULL,NULL,NULL,5), +(1337,'2025-06-11',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-11 07:59:16','2025-06-11 07:59:16',NULL,NULL,NULL,5), +(1338,'2025-06-11',7,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:22',NULL,NULL,NULL,8), +(1339,'2025-06-11',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-11 07:59:16','2025-06-11 07:59:16',NULL,NULL,NULL,5), +(1340,'2025-06-11',9,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:23',NULL,NULL,NULL,8), +(1341,'2025-06-11',10,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-11 07:59:16','2025-06-13 03:44:23',NULL,NULL,NULL,8), +(1342,'2025-06-13',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1343,'2025-06-13',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,5), +(1344,'2025-06-13',3,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1345,'2025-06-13',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1346,'2025-06-13',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,5), +(1347,'2025-06-13',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,5), +(1348,'2025-06-13',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,15), +(1349,'2025-06-13',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,5), +(1350,'2025-06-13',9,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1351,'2025-06-13',10,4,NULL,NULL,NULL,NULL,'반차',NULL,'라인수정','2025-06-13 03:25:23','2025-06-13 03:25:23',NULL,NULL,NULL,8), +(1352,'2025-06-05',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1353,'2025-06-05',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,5), +(1354,'2025-06-05',3,4,NULL,NULL,NULL,NULL,'반차',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1355,'2025-06-05',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1356,'2025-06-05',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,5), +(1357,'2025-06-05',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,5), +(1358,'2025-06-05',7,4,NULL,NULL,NULL,NULL,'반반차',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1359,'2025-06-05',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,5), +(1360,'2025-06-05',9,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1361,'2025-06-05',10,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:34:20','2025-06-13 03:34:20',NULL,NULL,NULL,8), +(1362,'2025-06-12',1,4,NULL,NULL,NULL,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1363,'2025-06-12',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,5), +(1364,'2025-06-12',3,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1365,'2025-06-12',4,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1366,'2025-06-12',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,5), +(1367,'2025-06-12',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,5), +(1368,'2025-06-12',7,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1369,'2025-06-12',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,5), +(1370,'2025-06-12',9,4,NULL,NULL,NULL,NULL,'반차',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1371,'2025-06-12',10,4,NULL,NULL,2.0,NULL,'근무',NULL,'라인수정','2025-06-13 03:36:11','2025-06-13 03:36:11',NULL,NULL,NULL,8), +(1372,'2025-06-16',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:26','2025-06-16 04:26:26',NULL,NULL,NULL,8), +(1373,'2025-06-16',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,5), +(1374,'2025-06-16',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,8), +(1375,'2025-06-16',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,8), +(1376,'2025-06-16',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,5), +(1377,'2025-06-16',6,3,NULL,NULL,NULL,NULL,'근무',NULL,'Vessel NDE 불량 수리','2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,5), +(1378,'2025-06-16',7,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,15), +(1379,'2025-06-16',8,3,NULL,NULL,NULL,NULL,'근무',NULL,'Vessel NDE 불량 수리','2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,5), +(1380,'2025-06-16',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,8), +(1381,'2025-06-16',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-16 04:26:27','2025-06-16 04:26:27',NULL,NULL,NULL,8), +(1382,'2025-06-17',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1383,'2025-06-17',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,5), +(1384,'2025-06-17',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1385,'2025-06-17',4,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:36:28',NULL,NULL,NULL,5), +(1386,'2025-06-17',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,5), +(1387,'2025-06-17',6,3,NULL,NULL,2.0,NULL,'근무',NULL,'용기 비파괴 불량','2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,5), +(1388,'2025-06-17',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1389,'2025-06-17',8,3,NULL,NULL,2.0,NULL,'근무',NULL,'용기 비파괴 불량','2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,5), +(1390,'2025-06-17',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1391,'2025-06-17',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-17 08:17:30','2025-06-17 08:17:30',NULL,NULL,NULL,8), +(1392,'2025-06-18',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1393,'2025-06-18',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,5), +(1394,'2025-06-18',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1395,'2025-06-18',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1396,'2025-06-18',5,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,5), +(1397,'2025-06-18',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,5), +(1398,'2025-06-18',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1399,'2025-06-18',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,5), +(1400,'2025-06-18',9,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1401,'2025-06-18',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-06-18 08:16:50','2025-06-18 08:16:50',NULL,NULL,NULL,8), +(1402,'2025-06-24',1,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1403,'2025-06-24',2,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,5), +(1404,'2025-06-24',3,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1405,'2025-06-24',4,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1406,'2025-06-24',5,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1407,'2025-06-24',6,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1408,'2025-06-24',7,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1409,'2025-06-24',8,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,5), +(1410,'2025-06-24',9,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1411,'2025-06-24',10,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-24 09:25:01','2025-06-24 09:25:01',NULL,NULL,NULL,8), +(1412,'2025-06-25',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1413,'2025-06-25',2,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,5), +(1414,'2025-06-25',3,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1415,'2025-06-25',4,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1416,'2025-06-25',5,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1417,'2025-06-25',6,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1418,'2025-06-25',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1419,'2025-06-25',8,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,5), +(1420,'2025-06-25',9,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1421,'2025-06-25',10,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-25 07:08:25','2025-06-25 07:08:25',NULL,NULL,NULL,18), +(1422,'2025-06-26',1,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1423,'2025-06-26',2,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,5), +(1424,'2025-06-26',3,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,5), +(1425,'2025-06-26',4,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1426,'2025-06-26',5,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1427,'2025-06-26',6,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,5), +(1428,'2025-06-26',7,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1429,'2025-06-26',8,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,5), +(1430,'2025-06-26',9,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1431,'2025-06-26',10,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-06-26 22:45:15','2025-06-26 22:45:15',NULL,NULL,NULL,18), +(1432,'2025-06-27',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1433,'2025-06-27',2,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1434,'2025-06-27',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1435,'2025-06-27',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1436,'2025-06-27',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1437,'2025-06-27',6,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1438,'2025-06-27',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1439,'2025-06-27',8,3,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,5), +(1440,'2025-06-27',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1441,'2025-06-27',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-06-26 22:48:37','2025-06-26 22:48:37',NULL,NULL,NULL,18), +(1442,'2025-06-19',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1443,'2025-06-19',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,5), +(1444,'2025-06-19',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1445,'2025-06-19',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1446,'2025-06-19',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,5), +(1447,'2025-06-19',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1448,'2025-06-19',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1449,'2025-06-19',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,5), +(1450,'2025-06-19',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1451,'2025-06-19',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:53:46','2025-07-07 03:53:46',NULL,NULL,NULL,8), +(1452,'2025-06-20',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1453,'2025-06-20',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,5), +(1454,'2025-06-20',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1455,'2025-06-20',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1456,'2025-06-20',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,5), +(1457,'2025-06-20',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1458,'2025-06-20',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1459,'2025-06-20',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,5), +(1460,'2025-06-20',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1461,'2025-06-20',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:54:44','2025-07-07 03:54:44',NULL,NULL,NULL,8), +(1462,'2025-06-23',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1463,'2025-06-23',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,5), +(1464,'2025-06-23',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1465,'2025-06-23',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1466,'2025-06-23',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,5), +(1467,'2025-06-23',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1468,'2025-06-23',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1469,'2025-06-23',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,5), +(1470,'2025-06-23',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1471,'2025-06-23',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 03:55:50','2025-07-07 03:55:50',NULL,NULL,NULL,8), +(1472,'2025-06-30',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1473,'2025-06-30',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,5), +(1474,'2025-06-30',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1475,'2025-06-30',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1476,'2025-06-30',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,5), +(1477,'2025-06-30',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,5), +(1478,'2025-06-30',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1479,'2025-06-30',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,5), +(1480,'2025-06-30',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1481,'2025-06-30',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:24:36','2025-07-07 04:24:36',NULL,NULL,NULL,8), +(1482,'2025-07-01',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,8), +(1483,'2025-07-01',2,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1484,'2025-07-01',3,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1485,'2025-07-01',4,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,8), +(1486,'2025-07-01',5,4,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,8), +(1487,'2025-07-01',6,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1488,'2025-07-01',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,8), +(1489,'2025-07-01',8,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1490,'2025-07-01',9,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1491,'2025-07-01',10,3,NULL,NULL,4.0,NULL,'근무',NULL,NULL,'2025-07-07 04:26:44','2025-07-07 04:26:44',NULL,NULL,NULL,5), +(1492,'2025-07-02',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,9), +(1493,'2025-07-02',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1494,'2025-07-02',3,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1495,'2025-07-02',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,9), +(1496,'2025-07-02',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,9), +(1497,'2025-07-02',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1498,'2025-07-02',7,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1499,'2025-07-02',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1500,'2025-07-02',9,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1501,'2025-07-02',10,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:28:16','2025-07-07 04:28:16',NULL,NULL,NULL,5), +(1502,'2025-07-03',1,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1503,'2025-07-03',2,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,5), +(1504,'2025-07-03',3,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1505,'2025-07-03',4,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1506,'2025-07-03',5,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1507,'2025-07-03',6,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,5), +(1508,'2025-07-03',7,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1509,'2025-07-03',8,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,5), +(1510,'2025-07-03',9,3,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,5), +(1511,'2025-07-03',10,4,NULL,NULL,2.0,NULL,'근무',NULL,NULL,'2025-07-07 04:30:04','2025-07-07 04:30:04',NULL,NULL,NULL,9), +(1512,'2025-07-04',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1513,'2025-07-04',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1514,'2025-07-04',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1515,'2025-07-04',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1516,'2025-07-04',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1517,'2025-07-04',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1518,'2025-07-04',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1519,'2025-07-04',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1520,'2025-07-04',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1521,'2025-07-04',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:09','2025-07-07 04:31:09',NULL,NULL,NULL,9), +(1522,'2025-07-05',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1523,'2025-07-05',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1524,'2025-07-05',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1525,'2025-07-05',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1526,'2025-07-05',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1527,'2025-07-05',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:31:53','2025-07-07 04:31:53',NULL,NULL,NULL,9), +(1528,'2025-07-06',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1529,'2025-07-06',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1530,'2025-07-06',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1531,'2025-07-06',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1532,'2025-07-06',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1533,'2025-07-06',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1534,'2025-07-06',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1535,'2025-07-06',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 04:32:52','2025-07-07 04:32:52',NULL,NULL,NULL,9), +(1536,'2025-07-07',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1537,'2025-07-07',2,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1538,'2025-07-07',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1539,'2025-07-07',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1540,'2025-07-07',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:13','2025-07-07 23:35:13',NULL,NULL,NULL,9), +(1541,'2025-07-07',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1542,'2025-07-07',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1543,'2025-07-07',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1544,'2025-07-07',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1545,'2025-07-07',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-07 23:35:14','2025-07-07 23:35:14',NULL,NULL,NULL,9), +(1546,'2025-07-08',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1547,'2025-07-08',2,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1548,'2025-07-08',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1549,'2025-07-08',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1550,'2025-07-08',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1551,'2025-07-08',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1552,'2025-07-08',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1553,'2025-07-08',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1554,'2025-07-08',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1555,'2025-07-08',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:12:44','2025-07-10 02:12:44',NULL,NULL,NULL,9), +(1556,'2025-07-09',1,4,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1557,'2025-07-09',2,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1558,'2025-07-09',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1559,'2025-07-09',4,4,NULL,NULL,NULL,NULL,'근무',NULL,'tubing','2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1560,'2025-07-09',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1561,'2025-07-09',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1562,'2025-07-09',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1563,'2025-07-09',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1564,'2025-07-09',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1565,'2025-07-09',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-10 02:13:45','2025-07-10 02:13:45',NULL,NULL,NULL,9), +(1566,'2025-07-10',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1567,'2025-07-10',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1568,'2025-07-10',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1569,'2025-07-10',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1570,'2025-07-10',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1571,'2025-07-10',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1572,'2025-07-10',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1573,'2025-07-10',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1574,'2025-07-10',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1575,'2025-07-10',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:06:02','2025-07-30 02:06:02',NULL,NULL,NULL,8), +(1576,'2025-07-14',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1577,'2025-07-14',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1578,'2025-07-14',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1579,'2025-07-14',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1580,'2025-07-14',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1581,'2025-07-14',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1582,'2025-07-14',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1583,'2025-07-14',8,4,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1584,'2025-07-14',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1585,'2025-07-14',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:07:29','2025-07-30 02:07:29',NULL,NULL,NULL,8), +(1586,'2025-07-15',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:41','2025-07-30 02:23:58',NULL,NULL,NULL,8), +(1587,'2025-07-15',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:41','2025-07-30 02:23:58',NULL,NULL,NULL,8), +(1588,'2025-07-15',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:41','2025-07-30 02:24:00',NULL,NULL,NULL,8), +(1589,'2025-07-15',4,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-07-30 02:08:41','2025-07-30 02:24:00',NULL,NULL,NULL,15), +(1590,'2025-07-15',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:01',NULL,NULL,NULL,5), +(1591,'2025-07-15',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:02',NULL,NULL,NULL,8), +(1592,'2025-07-15',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:02',NULL,NULL,NULL,8), +(1593,'2025-07-15',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:03',NULL,NULL,NULL,8), +(1594,'2025-07-15',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:03',NULL,NULL,NULL,5), +(1595,'2025-07-15',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:08:42','2025-07-30 02:24:04',NULL,NULL,NULL,8), +(1596,'2025-07-16',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:17','2025-07-30 02:10:17',NULL,NULL,NULL,8), +(1597,'2025-07-16',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1598,'2025-07-16',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1599,'2025-07-16',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,8), +(1600,'2025-07-16',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1601,'2025-07-16',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1602,'2025-07-16',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,8), +(1603,'2025-07-16',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1604,'2025-07-16',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1605,'2025-07-16',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:10:18','2025-07-30 02:10:18',NULL,NULL,NULL,5), +(1606,'2025-07-17',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:24:31',NULL,NULL,NULL,7), +(1607,'2025-07-17',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1608,'2025-07-17',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1609,'2025-07-17',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1610,'2025-07-17',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1611,'2025-07-17',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1612,'2025-07-17',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1613,'2025-07-17',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1614,'2025-07-17',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1615,'2025-07-17',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:11:12','2025-07-30 02:11:12',NULL,NULL,NULL,18), +(1616,'2025-07-18',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,9), +(1617,'2025-07-18',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1618,'2025-07-18',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1619,'2025-07-18',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1620,'2025-07-18',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,9), +(1621,'2025-07-18',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1622,'2025-07-18',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,9), +(1623,'2025-07-18',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1624,'2025-07-18',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1625,'2025-07-18',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:13:22','2025-07-30 02:13:22',NULL,NULL,NULL,5), +(1626,'2025-07-21',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,7), +(1627,'2025-07-21',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1628,'2025-07-21',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1629,'2025-07-21',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,9), +(1630,'2025-07-21',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,9), +(1631,'2025-07-21',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1632,'2025-07-21',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1633,'2025-07-21',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1634,'2025-07-21',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1635,'2025-07-21',10,3,NULL,NULL,NULL,NULL,'반반차',NULL,NULL,'2025-07-30 02:14:45','2025-07-30 02:14:45',NULL,NULL,NULL,5), +(1636,'2025-07-22',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,5), +(1637,'2025-07-22',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1638,'2025-07-22',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1639,'2025-07-22',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,7), +(1640,'2025-07-22',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,7), +(1641,'2025-07-22',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1642,'2025-07-22',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1643,'2025-07-22',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1644,'2025-07-22',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1645,'2025-07-22',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:16:04','2025-07-30 02:16:04',NULL,NULL,NULL,9), +(1646,'2025-07-23',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,7), +(1647,'2025-07-23',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1648,'2025-07-23',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1649,'2025-07-23',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,7), +(1650,'2025-07-23',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,7), +(1651,'2025-07-23',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1652,'2025-07-23',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1653,'2025-07-23',8,13,NULL,NULL,NULL,NULL,'유급',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 22:39:10',NULL,NULL,NULL,15), +(1654,'2025-07-23',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1655,'2025-07-23',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:17:15','2025-07-30 02:17:15',NULL,NULL,NULL,5), +(1656,'2025-07-24',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,7), +(1657,'2025-07-24',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1658,'2025-07-24',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1659,'2025-07-24',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,7), +(1660,'2025-07-24',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,7), +(1661,'2025-07-24',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1662,'2025-07-24',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1663,'2025-07-24',8,13,NULL,NULL,NULL,NULL,'유급',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,15), +(1664,'2025-07-24',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1665,'2025-07-24',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:18:29','2025-07-30 02:18:29',NULL,NULL,NULL,5), +(1666,'2025-07-25',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,13), +(1667,'2025-07-25',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1668,'2025-07-25',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1669,'2025-07-25',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1670,'2025-07-25',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,13), +(1671,'2025-07-25',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,13), +(1672,'2025-07-25',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,18), +(1673,'2025-07-25',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1674,'2025-07-25',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1675,'2025-07-25',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:21:24','2025-07-30 02:21:24',NULL,NULL,NULL,5), +(1676,'2025-07-28',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,7), +(1677,'2025-07-28',2,5,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,13), +(1678,'2025-07-28',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1679,'2025-07-28',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,7), +(1680,'2025-07-28',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,7), +(1681,'2025-07-28',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1682,'2025-07-28',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1683,'2025-07-28',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1684,'2025-07-28',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1685,'2025-07-28',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 02:22:32','2025-07-30 02:22:32',NULL,NULL,NULL,5), +(1686,'2025-07-11',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1687,'2025-07-11',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1688,'2025-07-11',3,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1689,'2025-07-11',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1690,'2025-07-11',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1691,'2025-07-11',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1692,'2025-07-11',7,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1693,'2025-07-11',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1694,'2025-07-11',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:30','2025-07-30 22:48:30',NULL,NULL,NULL,9), +(1695,'2025-07-11',10,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:48:31','2025-07-30 22:48:31',NULL,NULL,NULL,9), +(1696,'2025-07-12',1,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1697,'2025-07-12',2,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1698,'2025-07-12',3,13,NULL,NULL,NULL,NULL,'휴무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,15), +(1699,'2025-07-12',4,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1700,'2025-07-12',5,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1701,'2025-07-12',6,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1702,'2025-07-12',7,13,NULL,NULL,NULL,NULL,'휴무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,15), +(1703,'2025-07-12',8,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1704,'2025-07-12',9,4,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,9), +(1705,'2025-07-12',10,13,NULL,NULL,NULL,NULL,'휴무',NULL,NULL,'2025-07-30 22:49:19','2025-07-30 22:49:19',NULL,NULL,NULL,15), +(1706,'2025-07-29',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,7), +(1707,'2025-07-29',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1708,'2025-07-29',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1709,'2025-07-29',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,7), +(1710,'2025-07-29',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,7), +(1711,'2025-07-29',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1712,'2025-07-29',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1713,'2025-07-29',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1714,'2025-07-29',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1715,'2025-07-29',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:50:13','2025-07-30 22:50:13',NULL,NULL,NULL,5), +(1716,'2025-07-30',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,7), +(1717,'2025-07-30',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1718,'2025-07-30',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1719,'2025-07-30',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,7), +(1720,'2025-07-30',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,7), +(1721,'2025-07-30',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1722,'2025-07-30',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1723,'2025-07-30',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1724,'2025-07-30',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1725,'2025-07-30',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:05','2025-07-30 22:51:05',NULL,NULL,NULL,5), +(1726,'2025-07-31',1,3,NULL,NULL,NULL,NULL,'반차',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,7), +(1727,'2025-07-31',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1728,'2025-07-31',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1729,'2025-07-31',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,7), +(1730,'2025-07-31',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,7), +(1731,'2025-07-31',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1732,'2025-07-31',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1733,'2025-07-31',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1734,'2025-07-31',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1735,'2025-07-31',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-07-30 22:51:54','2025-07-30 22:51:54',NULL,NULL,NULL,5), +(1736,'2025-09-18',1,3,NULL,NULL,NULL,NULL,'근무',NULL,'냉동기','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,18), +(1737,'2025-09-18',2,8,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,8), +(1738,'2025-09-18',3,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1739,'2025-09-18',4,8,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,8), +(1740,'2025-09-18',5,3,NULL,NULL,NULL,NULL,'근무',NULL,'냉동기','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,9), +(1741,'2025-09-18',6,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1742,'2025-09-18',7,3,NULL,NULL,NULL,NULL,'근무',NULL,'냉동기','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,18), +(1743,'2025-09-18',8,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1744,'2025-09-18',9,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1745,'2025-09-18',10,3,NULL,NULL,NULL,NULL,'근무',NULL,'BOG','2025-09-17 23:53:35','2025-09-17 23:53:35',NULL,NULL,NULL,5), +(1746,'2025-10-01',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,16), +(1747,'2025-10-01',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,16), +(1748,'2025-10-01',3,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1749,'2025-10-01',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,5), +(1750,'2025-10-01',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,16), +(1751,'2025-10-01',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1752,'2025-10-01',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1753,'2025-10-01',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1754,'2025-10-01',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1755,'2025-10-01',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:49:56','2025-10-01 23:49:56',NULL,NULL,NULL,7), +(1756,'2025-10-02',1,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1757,'2025-10-02',2,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1758,'2025-10-02',3,13,NULL,NULL,NULL,NULL,'연차',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,15), +(1759,'2025-10-02',4,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1760,'2025-10-02',5,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1761,'2025-10-02',6,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1762,'2025-10-02',7,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1763,'2025-10-02',8,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1764,'2025-10-02',9,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7), +(1765,'2025-10-02',10,3,NULL,NULL,NULL,NULL,'근무',NULL,NULL,'2025-10-01 23:50:57','2025-10-01 23:50:57',NULL,NULL,NULL,7); +/*!40000 ALTER TABLE `WorkReports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `activity_logs` +-- + +DROP TABLE IF EXISTS `activity_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `activity_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL, + `activity_type` varchar(100) DEFAULT NULL, + `table_name` varchar(50) DEFAULT NULL, + `record_id` int(11) DEFAULT NULL, + `action` enum('create','read','update','delete') DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `created_at` datetime DEFAULT current_timestamp(), + PRIMARY KEY (`log_id`), + KEY `idx_user_activity` (`user_id`,`activity_type`,`created_at`), + KEY `idx_table_record` (`table_name`,`record_id`), + CONSTRAINT `activity_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `activity_logs` +-- + +LOCK TABLES `activity_logs` WRITE; +/*!40000 ALTER TABLE `activity_logs` DISABLE KEYS */; +/*!40000 ALTER TABLE `activity_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `daily_attendance_records` +-- + +DROP TABLE IF EXISTS `daily_attendance_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_attendance_records` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `worker_id` int(10) unsigned NOT NULL COMMENT '작업자 ID', + `record_date` date NOT NULL COMMENT '기록 날짜', + `attendance_type_id` int(10) unsigned NOT NULL COMMENT '출근 유형 ID', + `vacation_type_id` int(10) unsigned DEFAULT NULL COMMENT '휴가 유형 ID', + `check_in_time` time DEFAULT NULL COMMENT '출근 시간', + `check_out_time` time DEFAULT NULL COMMENT '퇴근 시간', + `total_work_hours` decimal(4,2) DEFAULT 0.00 COMMENT '총 근무 시간', + `is_overtime_approved` tinyint(1) DEFAULT 0 COMMENT '초과근무 승인 여부', + `notes` text DEFAULT NULL COMMENT '비고', + `created_by` int(10) unsigned NOT NULL COMMENT '등록자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `is_present` tinyint(1) DEFAULT 1 COMMENT '출근 여부', + PRIMARY KEY (`id`), + UNIQUE KEY `daily_attendance_records_worker_id_record_date_unique` (`worker_id`,`record_date`) +) ENGINE=InnoDB AUTO_INCREMENT=231 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_attendance_records` +-- + +LOCK TABLES `daily_attendance_records` WRITE; +/*!40000 ALTER TABLE `daily_attendance_records` DISABLE KEYS */; +INSERT INTO `daily_attendance_records` VALUES +(1,11,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(2,10,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(3,9,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(4,8,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(5,6,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(6,5,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(7,4,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(8,3,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(9,2,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(10,1,'2026-02-04',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 11:44:37','2026-02-04 11:55:01',1), +(11,11,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(12,10,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(13,9,'2026-01-05',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',0), +(14,8,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(15,6,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(16,5,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(17,4,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(18,3,'2026-01-05',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',0), +(19,2,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(20,1,'2026-01-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-04 22:38:37','2026-02-05 01:37:32',1), +(21,11,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(22,10,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(23,9,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(24,8,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(25,6,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(26,5,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(27,4,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(28,3,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(29,2,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(30,1,'2026-02-05',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:44','2026-02-05 05:04:34',1), +(31,11,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(32,10,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(33,9,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(34,8,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(35,6,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(36,5,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(37,4,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(38,3,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(39,2,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(40,1,'2026-01-02',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:33:51','2026-02-05 01:37:06',0), +(41,11,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(42,10,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(43,9,'2026-01-06',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',0), +(44,8,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(45,6,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(46,5,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(47,4,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(48,3,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(49,2,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(50,1,'2026-01-06',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:12','2026-02-05 05:22:37',1), +(51,11,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(52,10,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(53,9,'2026-01-07',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(54,8,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(55,6,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:57',1), +(56,5,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(57,4,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(58,3,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(59,2,'2026-01-07',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(60,1,'2026-01-07',4,3,NULL,NULL,6.00,0,NULL,1,'2026-02-05 01:34:23','2026-02-05 01:37:58',1), +(61,11,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(62,10,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(63,9,'2026-01-08',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(64,8,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(65,6,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(66,5,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(67,4,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(68,3,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(69,2,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(70,1,'2026-01-08',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:27','2026-02-05 01:38:17',1), +(71,11,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(72,10,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(73,9,'2026-01-09',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(74,8,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(75,6,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(76,5,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(77,4,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(78,3,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(79,2,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(80,1,'2026-01-09',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:31','2026-02-05 01:38:27',1), +(81,11,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:37',1), +(82,10,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:37',1), +(83,9,'2026-01-12',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:37',1), +(84,8,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:37',1), +(85,6,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(86,5,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(87,4,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(88,3,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(89,2,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(90,1,'2026-01-12',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:39','2026-02-05 01:38:38',1), +(91,11,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(92,10,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(93,9,'2026-01-13',4,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(94,8,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(95,6,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(96,5,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(97,4,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(98,3,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(99,2,'2026-01-13',4,2,NULL,NULL,4.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(100,1,'2026-01-13',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:34:47','2026-02-05 01:38:52',1), +(101,11,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(102,10,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(103,9,'2026-01-14',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',0), +(104,8,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(105,6,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(106,5,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(107,4,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(108,3,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(109,2,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(110,1,'2026-01-14',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:06','2026-02-05 01:39:05',1), +(111,11,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(112,10,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(113,9,'2026-01-15',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',0), +(114,8,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(115,6,'2026-01-15',3,NULL,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(116,5,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(117,4,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(118,3,'2026-01-15',5,2,NULL,NULL,4.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(119,2,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(120,1,'2026-01-15',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:13','2026-02-05 05:25:16',1), +(121,11,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(122,10,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(123,9,'2026-01-16',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',0), +(124,8,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(125,6,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(126,5,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(127,4,'2026-01-16',4,1,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',0), +(128,3,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(129,2,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(130,1,'2026-01-16',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:26','2026-02-05 01:39:26',1), +(131,11,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(132,10,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(133,9,'2026-01-19',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',0), +(134,8,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(135,6,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(136,5,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(137,4,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(138,3,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(139,2,'2026-01-19',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',1), +(140,1,'2026-01-19',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:35:38','2026-02-05 05:25:51',0), +(141,11,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(142,10,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(143,9,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(144,8,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(145,6,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(146,5,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(147,4,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(148,3,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(149,2,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(150,1,'2026-01-20',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:35:58','2026-02-05 05:25:58',1), +(151,11,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(152,10,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(153,9,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(154,8,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(155,6,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(156,5,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(157,4,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(158,3,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(159,2,'2026-01-21',5,2,NULL,NULL,4.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(160,1,'2026-01-21',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:03','2026-02-05 05:26:06',1), +(161,11,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(162,10,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(163,9,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(164,8,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(165,6,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(166,5,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(167,4,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(168,3,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(169,2,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(170,1,'2026-01-22',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:06','2026-02-05 05:26:13',1), +(171,11,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(172,10,'2026-01-23',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',0), +(173,9,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(174,8,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(175,6,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(176,5,'2026-01-23',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',0), +(177,4,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(178,3,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(179,2,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(180,1,'2026-01-23',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:20','2026-02-05 05:26:21',1), +(181,11,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(182,10,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(183,9,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(184,8,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(185,6,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(186,5,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(187,4,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(188,3,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(189,2,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(190,1,'2026-01-26',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:31','2026-02-05 05:26:26',1), +(191,11,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(192,10,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(193,9,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(194,8,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(195,6,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(196,5,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(197,4,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(198,3,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(199,2,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(200,1,'2026-01-27',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:38','2026-02-05 05:26:32',1), +(201,11,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(202,10,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(203,9,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(204,8,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(205,6,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(206,5,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(207,4,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(208,3,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(209,2,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(210,1,'2026-01-28',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:42','2026-02-05 05:26:37',1), +(211,11,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(212,10,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(213,9,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(214,8,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(215,6,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(216,5,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(217,4,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(218,3,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(219,2,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(220,1,'2026-01-29',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:45','2026-02-05 05:26:42',1), +(221,11,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(222,10,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(223,9,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(224,8,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(225,6,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(226,5,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(227,4,'2026-01-30',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',0), +(228,3,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1), +(229,2,'2026-01-30',5,1,NULL,NULL,0.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',0), +(230,1,'2026-01-30',1,NULL,NULL,NULL,8.00,0,NULL,1,'2026-02-05 01:36:52','2026-02-05 05:26:54',1); +/*!40000 ALTER TABLE `daily_attendance_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `daily_patrol_sessions` +-- + +DROP TABLE IF EXISTS `daily_patrol_sessions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_patrol_sessions` ( + `session_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `patrol_date` date NOT NULL COMMENT '점검 날짜', + `patrol_time` enum('morning','afternoon') NOT NULL COMMENT '점검 시간대', + `inspector_id` int(11) NOT NULL COMMENT '순찰자 user_id', + `category_id` int(10) unsigned DEFAULT NULL COMMENT '공장 ID', + `status` enum('in_progress','completed') DEFAULT 'in_progress' COMMENT '상태', + `notes` text DEFAULT NULL COMMENT '특이사항', + `started_at` time DEFAULT NULL COMMENT '점검 시작 시간', + `completed_at` time DEFAULT NULL COMMENT '점검 완료 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`session_id`), + UNIQUE KEY `daily_patrol_sessions_patrol_date_patrol_time_category_id_unique` (`patrol_date`,`patrol_time`,`category_id`), + KEY `daily_patrol_sessions_patrol_date_patrol_time_index` (`patrol_date`,`patrol_time`), + KEY `daily_patrol_sessions_inspector_id_index` (`inspector_id`), + KEY `daily_patrol_sessions_category_id_foreign` (`category_id`), + CONSTRAINT `daily_patrol_sessions_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE SET NULL, + CONSTRAINT `daily_patrol_sessions_inspector_id_foreign` FOREIGN KEY (`inspector_id`) REFERENCES `users` (`user_id`) +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_patrol_sessions` +-- + +LOCK TABLES `daily_patrol_sessions` WRITE; +/*!40000 ALTER TABLE `daily_patrol_sessions` DISABLE KEYS */; +INSERT INTO `daily_patrol_sessions` VALUES +(1,'2026-02-04','morning',1,1,'in_progress',NULL,'02:20:32',NULL,'2026-02-04 02:20:32','2026-02-04 02:20:32'), +(2,'2026-02-04','afternoon',1,1,'in_progress',NULL,'07:36:23',NULL,'2026-02-04 07:36:23','2026-02-04 07:36:23'), +(3,'2026-02-05','afternoon',1,1,'in_progress',NULL,'04:30:44',NULL,'2026-02-05 04:30:44','2026-02-05 04:30:44'); +/*!40000 ALTER TABLE `daily_patrol_sessions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `daily_work_reports` +-- + +DROP TABLE IF EXISTS `daily_work_reports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_work_reports` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `report_date` date NOT NULL COMMENT '작업 날짜', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `project_id` int(11) NOT NULL COMMENT '프로젝트 ID', + `work_type_id` int(11) NOT NULL COMMENT '작업 유형 ID', + `work_status_id` int(11) DEFAULT 1 COMMENT '업무 상태 ID (1:정규, 2:에러)', + `error_type_id` int(11) DEFAULT NULL COMMENT '에러 유형 ID (에러일 때만)', + `work_hours` decimal(4,2) NOT NULL COMMENT '작업 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + `created_by` int(11) NOT NULL DEFAULT 1 COMMENT '작성자 user_id', + `updated_by` int(11) DEFAULT NULL COMMENT '수정자 user_id', + `tbm_session_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 TBM 세션 ID', + `tbm_assignment_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 TBM 팀 배정 ID', + `start_time` time DEFAULT NULL COMMENT '작업 시작 시간', + `end_time` time DEFAULT NULL COMMENT '작업 종료 시간', + `total_hours` decimal(5,2) DEFAULT NULL COMMENT '총 작업 시간', + `regular_hours` decimal(5,2) DEFAULT NULL COMMENT '정규 작업 시간 (총 시간 - 오류 시간)', + `error_hours` decimal(5,2) DEFAULT NULL COMMENT '부적합 사항 처리 시간', + PRIMARY KEY (`id`), + KEY `idx_report_date` (`report_date`), + KEY `idx_worker_date` (`worker_id`,`report_date`), + KEY `idx_project_date` (`project_id`,`report_date`), + KEY `idx_work_type` (`work_type_id`), + KEY `idx_work_status` (`work_status_id`), + KEY `idx_error_type` (`error_type_id`), + KEY `idx_created_by` (`created_by`), + KEY `idx_date_worker_creator` (`report_date`,`worker_id`,`created_by`), + KEY `daily_work_reports_tbm_session_id_foreign` (`tbm_session_id`), + KEY `daily_work_reports_tbm_assignment_id_foreign` (`tbm_assignment_id`), + CONSTRAINT `daily_work_reports_tbm_assignment_id_foreign` FOREIGN KEY (`tbm_assignment_id`) REFERENCES `tbm_team_assignments` (`assignment_id`) ON DELETE SET NULL, + CONSTRAINT `daily_work_reports_tbm_session_id_foreign` FOREIGN KEY (`tbm_session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=1858 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_work_reports` +-- + +LOCK TABLES `daily_work_reports` WRITE; +/*!40000 ALTER TABLE `daily_work_reports` DISABLE KEYS */; +INSERT INTO `daily_work_reports` VALUES +(14,'2025-06-02',1,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(15,'2025-06-02',3,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(16,'2025-06-02',4,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(17,'2025-06-02',6,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(18,'2025-06-02',7,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(19,'2025-06-02',9,4,3,1,NULL,8.00,'2025-06-16 05:10:23','2025-06-16 05:10:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(20,'2025-06-02',2,3,2,1,NULL,8.00,'2025-06-16 05:10:47','2025-06-16 05:10:47',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(21,'2025-06-04',1,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(22,'2025-06-04',3,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(23,'2025-06-04',5,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(24,'2025-06-04',7,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(25,'2025-06-04',9,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(26,'2025-06-04',10,4,3,1,NULL,8.00,'2025-06-16 05:11:37','2025-06-16 05:11:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(27,'2025-06-04',2,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(28,'2025-06-04',6,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(29,'2025-06-04',8,3,2,1,NULL,8.00,'2025-06-16 05:12:07','2025-06-16 05:12:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(30,'2025-06-05',1,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(31,'2025-06-05',3,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(32,'2025-06-05',4,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(33,'2025-06-05',7,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(34,'2025-06-05',10,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(35,'2025-06-05',9,4,3,2,6,8.00,'2025-06-16 05:12:57','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(36,'2025-06-05',2,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(37,'2025-06-05',5,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(38,'2025-06-05',6,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(39,'2025-06-05',8,3,2,1,NULL,8.00,'2025-06-16 05:13:56','2025-06-16 05:13:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(40,'2025-06-16',5,3,2,1,NULL,8.00,'2025-06-16 06:12:01','2025-06-16 06:12:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(43,'2025-06-16',2,3,2,1,NULL,8.00,'2025-06-16 06:12:01','2025-06-16 06:12:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(44,'2025-06-16',6,3,2,2,43,4.00,'2025-06-16 06:13:02','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(45,'2025-06-16',6,3,2,1,NULL,4.00,'2025-06-16 06:13:50','2025-06-16 06:13:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(46,'2025-06-16',8,3,2,2,43,4.00,'2025-06-16 06:15:22','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(47,'2025-06-16',8,3,2,1,NULL,4.00,'2025-06-16 06:15:22','2025-06-16 06:15:22',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(48,'2025-06-16',4,4,3,2,6,8.00,'2025-06-16 06:46:44','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(50,'2025-06-16',1,4,3,2,6,8.00,'2025-06-16 06:46:44','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(51,'2025-06-16',9,4,3,1,NULL,8.00,'2025-06-16 06:48:29','2025-06-16 06:48:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(52,'2025-06-16',10,4,3,1,NULL,6.00,'2025-06-16 06:50:09','2025-06-16 06:50:09',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(53,'2025-06-16',10,4,3,2,6,2.00,'2025-06-16 06:50:09','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(54,'2025-06-16',3,4,3,1,NULL,6.00,'2025-06-16 06:50:09','2025-06-16 06:50:09',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(55,'2025-06-16',3,4,3,2,6,2.00,'2025-06-16 06:50:09','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(56,'2025-06-17',2,3,2,1,NULL,8.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(57,'2025-06-17',2,3,2,1,NULL,2.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(58,'2025-06-17',5,3,2,1,NULL,8.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(59,'2025-06-17',5,3,2,1,NULL,2.00,'2025-06-17 08:23:41','2025-06-17 08:23:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(60,'2025-06-17',6,3,2,1,NULL,8.00,'2025-06-17 08:24:33','2025-06-17 08:24:33',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(61,'2025-06-17',6,3,2,2,43,2.00,'2025-06-17 08:24:33','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(62,'2025-06-17',8,3,2,1,NULL,8.00,'2025-06-17 08:24:33','2025-06-17 08:24:33',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(63,'2025-06-17',8,3,2,2,43,2.00,'2025-06-17 08:24:33','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(65,'2025-06-17',9,4,3,2,6,4.00,'2025-06-17 08:25:24','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(66,'2025-06-17',1,4,3,2,6,4.00,'2025-06-17 08:27:06','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(67,'2025-06-17',4,4,3,2,6,4.00,'2025-06-17 08:27:06','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(68,'2025-06-17',1,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(69,'2025-06-17',9,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(70,'2025-06-17',4,4,3,1,NULL,4.00,'2025-06-17 08:31:06','2025-06-17 08:31:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(71,'2025-06-17',9,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(72,'2025-06-17',4,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(73,'2025-06-17',1,4,3,1,NULL,2.00,'2025-06-17 08:33:06','2025-06-17 08:33:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(74,'2025-06-17',10,4,3,1,NULL,8.00,'2025-06-17 08:34:11','2025-06-17 08:34:11',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(75,'2025-06-17',10,4,3,2,6,2.00,'2025-06-17 08:34:11','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(76,'2025-06-17',3,4,3,1,NULL,8.00,'2025-06-17 08:34:11','2025-06-17 08:34:11',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(77,'2025-06-17',3,4,3,2,6,2.00,'2025-06-17 08:34:11','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(78,'2025-06-18',6,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(79,'2025-06-18',2,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(80,'2025-06-18',8,3,2,1,NULL,8.00,'2025-06-18 08:40:27','2025-06-18 08:40:27',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(81,'2025-06-18',2,3,2,1,NULL,2.00,'2025-06-18 08:41:02','2025-06-18 08:41:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(82,'2025-06-18',6,3,2,1,NULL,2.00,'2025-06-18 08:41:03','2025-06-18 08:41:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(83,'2025-06-18',8,3,2,1,NULL,2.00,'2025-06-18 08:41:03','2025-06-18 08:41:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(84,'2025-06-18',5,4,3,1,NULL,8.00,'2025-06-18 08:41:45','2025-06-18 08:41:45',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(85,'2025-06-18',5,4,3,1,NULL,2.00,'2025-06-18 08:41:45','2025-06-18 08:41:45',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(86,'2025-06-18',10,4,3,1,NULL,9.00,'2025-06-18 08:47:55','2025-06-18 08:47:55',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(87,'2025-06-18',10,4,3,2,6,1.00,'2025-06-18 08:47:55','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(88,'2025-06-18',3,4,3,1,NULL,9.00,'2025-06-18 08:47:55','2025-06-18 08:47:55',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(89,'2025-06-18',3,4,3,2,6,1.00,'2025-06-18 08:47:55','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(90,'2025-06-18',4,4,3,2,6,4.00,'2025-06-18 08:50:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(91,'2025-06-18',4,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(92,'2025-06-18',9,4,3,2,6,4.00,'2025-06-18 08:50:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(93,'2025-06-18',9,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(94,'2025-06-18',1,4,3,2,6,4.00,'2025-06-18 08:50:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(95,'2025-06-18',1,4,3,1,NULL,6.00,'2025-06-18 08:50:19','2025-06-18 08:50:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(96,'2025-06-18',7,4,3,2,6,4.00,'2025-06-18 09:00:17','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(97,'2025-06-18',7,4,3,1,NULL,6.00,'2025-06-18 09:00:17','2025-06-18 09:00:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(98,'2025-06-19',8,3,2,1,NULL,8.00,'2025-06-19 06:37:59','2025-06-19 06:37:59',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(99,'2025-06-19',2,3,2,1,NULL,8.00,'2025-06-19 06:37:59','2025-06-19 06:37:59',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(100,'2025-06-19',10,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(101,'2025-06-19',3,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(102,'2025-06-19',5,4,3,1,NULL,8.00,'2025-06-19 06:59:36','2025-06-19 06:59:36',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(103,'2025-06-19',9,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(104,'2025-06-19',9,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(105,'2025-06-19',4,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(106,'2025-06-19',4,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(107,'2025-06-19',1,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(108,'2025-06-19',1,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(109,'2025-06-19',7,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(110,'2025-06-19',7,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(111,'2025-06-19',6,4,3,1,NULL,6.00,'2025-06-19 07:01:02','2025-06-19 07:01:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(112,'2025-06-19',6,4,3,2,6,2.00,'2025-06-19 07:01:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(113,'2025-06-20',9,4,3,2,6,2.00,'2025-06-20 06:44:01','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(114,'2025-06-20',9,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(115,'2025-06-20',4,4,3,2,6,2.00,'2025-06-20 06:44:01','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(116,'2025-06-20',4,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(117,'2025-06-20',7,4,3,2,6,2.00,'2025-06-20 06:44:01','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(118,'2025-06-20',7,4,3,1,NULL,6.00,'2025-06-20 06:44:01','2025-06-20 06:44:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(119,'2025-06-20',6,4,3,2,6,2.00,'2025-06-20 06:44:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(120,'2025-06-20',6,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(121,'2025-06-20',1,4,3,2,6,2.00,'2025-06-20 06:44:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(122,'2025-06-20',1,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(123,'2025-06-20',5,4,3,2,6,2.00,'2025-06-20 06:44:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(124,'2025-06-20',5,4,3,1,NULL,6.00,'2025-06-20 06:44:02','2025-06-20 06:44:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(125,'2025-06-20',10,4,3,1,NULL,8.00,'2025-06-20 06:45:30','2025-06-20 06:45:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(126,'2025-06-20',3,4,3,1,NULL,8.00,'2025-06-20 06:45:31','2025-06-20 06:45:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(127,'2025-06-23',10,4,3,1,NULL,8.00,'2025-06-23 06:42:58','2025-06-23 06:42:58',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(128,'2025-06-23',3,4,3,1,NULL,8.00,'2025-06-23 06:42:58','2025-06-23 06:42:58',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(129,'2025-06-23',5,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(130,'2025-06-23',5,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(131,'2025-06-23',1,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(132,'2025-06-23',1,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(133,'2025-06-23',9,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(134,'2025-06-23',9,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(135,'2025-06-23',4,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(136,'2025-06-23',4,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(137,'2025-06-23',7,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(138,'2025-06-23',7,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(139,'2025-06-23',6,4,3,2,6,2.00,'2025-06-23 06:51:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(140,'2025-06-23',6,4,3,1,NULL,6.00,'2025-06-23 06:51:28','2025-06-23 06:51:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(141,'2025-06-24',10,4,3,1,NULL,12.00,'2025-06-24 11:10:32','2025-06-24 11:10:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(142,'2025-06-24',3,4,3,1,NULL,12.00,'2025-06-24 11:10:32','2025-06-24 11:10:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(143,'2025-06-24',9,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(144,'2025-06-24',9,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(145,'2025-06-24',5,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(146,'2025-06-24',5,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(147,'2025-06-24',4,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(148,'2025-06-24',4,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(149,'2025-06-24',7,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(150,'2025-06-24',7,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(151,'2025-06-24',6,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(152,'2025-06-24',6,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(153,'2025-06-24',1,4,3,2,6,2.00,'2025-06-24 11:11:00','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(154,'2025-06-24',1,4,3,1,NULL,10.00,'2025-06-24 11:11:00','2025-06-24 11:11:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(155,'2025-06-24',8,3,2,1,NULL,8.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(156,'2025-06-24',8,3,2,1,NULL,4.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(157,'2025-06-24',2,3,2,1,NULL,8.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(158,'2025-06-24',2,3,2,1,NULL,4.00,'2025-06-24 11:11:05','2025-06-24 11:11:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(159,'2025-06-25',2,3,2,1,NULL,8.00,'2025-06-25 11:08:04','2025-06-25 11:08:04',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(160,'2025-06-25',2,3,2,1,NULL,4.00,'2025-06-25 11:08:04','2025-06-25 11:08:04',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(161,'2025-06-25',8,3,2,1,NULL,8.00,'2025-06-25 11:08:05','2025-06-25 11:08:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(162,'2025-06-25',8,3,2,1,NULL,4.00,'2025-06-25 11:08:05','2025-06-25 11:08:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(163,'2025-06-25',10,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(164,'2025-06-25',9,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(165,'2025-06-25',3,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(166,'2025-06-25',6,4,3,1,NULL,12.00,'2025-06-25 11:11:30','2025-06-25 11:11:30',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(167,'2025-06-26',10,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(168,'2025-06-26',5,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(169,'2025-06-26',7,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(170,'2025-06-26',1,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(171,'2025-06-26',4,4,3,1,NULL,12.00,'2025-06-26 10:29:38','2025-06-26 10:29:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(172,'2025-06-26',8,3,2,1,NULL,8.00,'2025-06-26 11:11:31','2025-06-26 11:11:31',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(173,'2025-06-26',8,3,2,1,NULL,4.00,'2025-06-26 11:11:31','2025-06-26 11:11:31',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(174,'2025-06-26',2,3,2,1,NULL,8.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(175,'2025-06-26',2,3,2,1,NULL,4.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(176,'2025-06-26',9,3,2,1,NULL,8.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(177,'2025-06-26',9,3,2,1,NULL,4.00,'2025-06-26 11:11:32','2025-06-26 11:11:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(178,'2025-06-26',3,3,2,1,NULL,12.00,'2025-06-26 11:19:34','2025-06-26 11:19:34',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(179,'2025-06-26',6,3,2,1,NULL,12.00,'2025-06-26 11:19:34','2025-06-26 11:19:34',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(182,'2025-06-27',2,3,2,1,NULL,4.00,'2025-06-27 01:54:40','2025-06-27 01:54:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(183,'2025-06-27',9,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(184,'2025-06-27',10,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(185,'2025-06-27',7,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(186,'2025-06-27',5,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(187,'2025-06-27',4,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(188,'2025-06-27',1,4,3,1,NULL,8.00,'2025-06-27 06:47:43','2025-06-27 06:47:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(189,'2025-06-27',3,3,2,1,NULL,8.00,'2025-06-27 06:49:08','2025-06-27 06:49:08',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(191,'2025-06-27',6,3,2,1,NULL,4.00,'2025-06-27 06:58:46','2025-06-27 06:58:46',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(192,'2025-06-27',8,3,2,1,NULL,6.00,'2025-06-27 07:00:10','2025-06-27 07:00:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(193,'2025-06-30',6,3,2,2,43,2.00,'2025-07-05 01:37:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(194,'2025-06-30',6,3,2,1,NULL,2.00,'2025-07-05 01:37:29','2025-07-07 04:15:25',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(195,'2025-06-30',2,3,2,1,NULL,4.00,'2025-07-05 01:38:19','2025-07-07 04:15:40',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(196,'2025-06-30',3,3,2,1,NULL,8.00,'2025-07-05 01:38:19','2025-07-05 01:38:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(197,'2025-06-30',8,3,2,1,NULL,6.00,'2025-07-05 01:38:19','2025-07-07 04:15:02',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(198,'2025-07-01',3,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(199,'2025-07-01',2,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(200,'2025-07-01',6,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(201,'2025-07-01',8,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(202,'2025-07-01',10,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(203,'2025-07-01',9,3,2,1,NULL,10.00,'2025-07-05 01:39:21','2025-07-05 01:39:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(204,'2025-07-01',2,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:42:08',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(205,'2025-07-01',3,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:42:02',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(206,'2025-07-01',6,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:41:56',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(207,'2025-07-01',8,3,2,1,NULL,2.00,'2025-07-05 01:39:48','2025-07-05 01:41:48',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(208,'2025-07-01',9,3,2,2,43,2.00,'2025-07-05 01:40:10','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(209,'2025-07-01',10,3,2,2,43,2.00,'2025-07-05 01:40:10','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(210,'2025-07-01',7,4,3,1,NULL,5.00,'2025-07-05 01:42:57','2025-07-05 01:42:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(211,'2025-07-01',7,4,3,2,10,3.00,'2025-07-05 01:42:57','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(212,'2025-07-01',5,4,3,1,NULL,8.00,'2025-07-05 01:42:57','2025-07-07 04:21:24',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(213,'2025-07-01',5,4,3,2,10,4.00,'2025-07-05 01:42:57','2026-02-05 22:24:28',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(214,'2025-07-01',4,4,3,1,NULL,8.00,'2025-07-05 01:42:57','2025-07-07 04:21:41',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(215,'2025-07-01',4,4,3,2,10,4.00,'2025-07-05 01:42:57','2026-02-05 22:24:28',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(216,'2025-07-01',1,4,3,1,NULL,5.00,'2025-07-05 01:42:57','2025-07-05 01:42:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(217,'2025-07-01',1,4,3,2,10,3.00,'2025-07-05 01:42:57','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(218,'2025-07-02',2,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(219,'2025-07-02',3,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(220,'2025-07-02',10,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(221,'2025-07-02',9,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(222,'2025-07-02',8,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(223,'2025-07-02',6,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(224,'2025-07-02',7,3,2,1,NULL,10.00,'2025-07-05 01:43:36','2025-07-05 01:43:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(225,'2025-07-02',5,4,3,2,10,4.00,'2025-07-05 01:44:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(226,'2025-07-02',5,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:44:54',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(227,'2025-07-02',4,4,3,2,10,4.00,'2025-07-05 01:44:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(228,'2025-07-02',4,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:44:59',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(229,'2025-07-02',1,4,3,2,10,4.00,'2025-07-05 01:44:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(230,'2025-07-02',1,4,3,1,NULL,6.00,'2025-07-05 01:44:11','2025-07-05 01:45:05',3,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(231,'2025-07-03',2,3,2,1,NULL,10.00,'2025-07-05 01:45:44','2025-07-05 01:45:44',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(232,'2025-07-03',6,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(233,'2025-07-03',9,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(234,'2025-07-03',8,3,2,1,NULL,10.00,'2025-07-05 01:45:45','2025-07-05 01:45:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(235,'2025-07-03',7,4,3,1,NULL,10.00,'2025-07-05 01:46:07','2025-07-05 01:46:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(236,'2025-07-03',1,4,3,1,NULL,10.00,'2025-07-05 01:46:07','2025-07-05 01:46:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(237,'2025-07-03',3,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(238,'2025-07-03',4,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(239,'2025-07-03',5,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(240,'2025-07-03',10,4,3,1,NULL,10.00,'2025-07-05 01:46:08','2025-07-05 01:46:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(241,'2025-07-04',10,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(242,'2025-07-04',10,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(243,'2025-07-04',5,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(244,'2025-07-04',5,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(245,'2025-07-04',4,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(246,'2025-07-04',4,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(247,'2025-07-04',9,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(248,'2025-07-04',9,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(249,'2025-07-04',8,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(250,'2025-07-04',8,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(251,'2025-07-04',3,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(252,'2025-07-04',3,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(253,'2025-07-04',2,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(254,'2025-07-04',2,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(255,'2025-07-04',7,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(256,'2025-07-04',7,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(257,'2025-07-04',6,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(258,'2025-07-04',6,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(259,'2025-07-04',1,4,3,2,10,2.00,'2025-07-05 01:51:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(260,'2025-07-04',1,4,3,1,NULL,6.00,'2025-07-05 01:51:47','2025-07-05 01:51:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(261,'2025-07-05',8,4,2,1,NULL,8.00,'2025-07-05 05:36:38','2025-07-05 05:36:38',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(262,'2025-07-05',5,4,2,1,NULL,8.00,'2025-07-05 05:36:38','2025-07-05 05:36:38',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(263,'2025-07-05',4,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(264,'2025-07-05',3,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(265,'2025-07-05',2,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(266,'2025-07-05',1,4,2,1,NULL,8.00,'2025-07-05 05:36:39','2025-07-05 05:36:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(267,'2025-07-06',10,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:08',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(268,'2025-07-06',9,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:16',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(269,'2025-07-06',7,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:22',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(270,'2025-07-06',6,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:27',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(271,'2025-07-06',4,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:33',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(272,'2025-07-06',3,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:39',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(273,'2025-07-06',2,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:44',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(274,'2025-07-06',1,4,3,1,NULL,8.00,'2025-07-06 05:34:32','2025-07-06 05:46:49',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(275,'2025-07-07',10,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(276,'2025-07-07',9,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(277,'2025-07-07',8,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(278,'2025-07-07',7,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(279,'2025-07-07',3,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(280,'2025-07-07',4,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(281,'2025-07-07',5,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(282,'2025-07-07',6,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(283,'2025-07-07',2,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(284,'2025-07-07',1,4,3,1,NULL,8.00,'2025-07-07 06:49:31','2025-07-07 06:49:31',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(285,'2025-07-08',10,4,3,1,NULL,8.00,'2025-07-08 06:36:57','2025-07-08 06:36:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(286,'2025-07-08',9,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(287,'2025-07-08',8,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(288,'2025-07-08',7,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(289,'2025-07-08',6,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(290,'2025-07-08',1,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(291,'2025-07-08',2,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(292,'2025-07-08',3,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(293,'2025-07-08',5,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(294,'2025-07-08',4,4,3,1,NULL,8.00,'2025-07-08 06:36:58','2025-07-08 06:36:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(295,'2025-07-09',10,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(296,'2025-07-09',9,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(297,'2025-07-09',8,4,3,1,NULL,8.00,'2025-07-09 22:08:40','2025-07-09 22:08:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(298,'2025-07-09',7,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(299,'2025-07-09',6,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(300,'2025-07-09',2,4,3,1,NULL,8.00,'2025-07-09 22:08:41','2025-07-09 22:08:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(301,'2025-07-09',3,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(302,'2025-07-09',4,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(303,'2025-07-09',5,4,3,1,NULL,8.00,'2025-07-09 22:08:42','2025-07-09 22:08:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(304,'2025-07-09',1,4,3,1,NULL,4.00,'2025-07-09 22:09:10','2025-07-09 22:09:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(305,'2025-07-10',9,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(306,'2025-07-10',8,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(307,'2025-07-10',5,4,3,1,NULL,8.00,'2025-07-10 06:33:58','2025-07-10 06:33:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(308,'2025-07-10',6,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(309,'2025-07-10',2,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(310,'2025-07-10',3,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(311,'2025-07-10',4,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(312,'2025-07-10',1,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(313,'2025-07-10',7,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(314,'2025-07-10',10,4,3,1,NULL,8.00,'2025-07-10 06:33:59','2025-07-10 06:33:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(315,'2025-07-12',9,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(316,'2025-07-12',8,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(317,'2025-07-12',6,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(318,'2025-07-12',5,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(319,'2025-07-12',4,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(320,'2025-07-12',2,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(321,'2025-07-12',1,4,3,1,NULL,8.00,'2025-07-12 05:41:30','2025-07-12 05:41:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(322,'2025-07-14',8,4,3,1,NULL,6.00,'2025-07-14 06:46:30','2025-07-14 06:46:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(323,'2025-07-14',10,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(324,'2025-07-14',9,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(325,'2025-07-14',7,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(326,'2025-07-14',6,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(327,'2025-07-14',1,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(328,'2025-07-14',2,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(329,'2025-07-14',3,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(330,'2025-07-14',4,4,3,1,NULL,8.00,'2025-07-14 06:46:57','2025-07-14 06:46:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(331,'2025-07-15',3,3,2,1,NULL,8.00,'2025-07-15 05:57:06','2025-07-15 05:57:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(332,'2025-07-15',9,3,2,1,NULL,8.00,'2025-07-15 05:57:06','2025-07-15 05:57:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(333,'2025-07-15',5,3,2,2,43,4.00,'2025-07-15 05:57:47','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(334,'2025-07-15',5,4,3,1,NULL,4.00,'2025-07-15 05:57:47','2025-07-15 05:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(335,'2025-07-15',10,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(336,'2025-07-15',8,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(337,'2025-07-15',7,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(338,'2025-07-15',6,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(339,'2025-07-15',2,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(340,'2025-07-15',1,4,3,1,NULL,8.00,'2025-07-15 05:58:19','2025-07-15 05:58:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(341,'2025-07-14',5,4,3,1,NULL,8.00,'2025-07-15 06:57:26','2025-07-15 06:57:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(342,'2025-07-16',4,4,3,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(343,'2025-07-16',4,3,2,1,NULL,4.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(344,'2025-07-16',4,3,2,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(345,'2025-07-16',5,4,3,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(346,'2025-07-16',5,3,2,1,NULL,4.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(347,'2025-07-16',5,3,2,1,NULL,2.00,'2025-07-16 06:46:46','2025-07-16 06:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(348,'2025-07-16',10,4,3,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(349,'2025-07-16',10,3,2,1,NULL,4.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(350,'2025-07-16',10,3,2,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(351,'2025-07-16',6,4,3,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(352,'2025-07-16',6,3,2,1,NULL,4.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(353,'2025-07-16',6,3,2,1,NULL,2.00,'2025-07-16 06:47:53','2025-07-16 06:47:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(354,'2025-07-16',9,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(355,'2025-07-16',8,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(356,'2025-07-16',3,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(357,'2025-07-16',2,3,2,1,NULL,8.00,'2025-07-16 06:48:32','2025-07-16 06:48:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(358,'2025-07-16',1,4,3,1,NULL,8.00,'2025-07-16 06:51:31','2025-07-16 06:51:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(359,'2025-07-16',7,4,3,1,NULL,8.00,'2025-07-16 06:51:31','2025-07-16 06:51:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(360,'2025-07-17',1,3,3,1,NULL,8.00,'2025-07-17 06:45:22','2025-07-17 06:45:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(361,'2025-07-17',5,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(362,'2025-07-17',5,3,2,2,43,4.00,'2025-07-17 06:46:48','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(363,'2025-07-17',4,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(364,'2025-07-17',4,3,2,2,43,4.00,'2025-07-17 06:46:48','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(365,'2025-07-17',2,3,2,1,NULL,4.00,'2025-07-17 06:46:48','2025-07-17 06:46:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(366,'2025-07-17',2,3,2,2,43,4.00,'2025-07-17 06:46:48','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(367,'2025-07-17',10,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(368,'2025-07-17',9,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(369,'2025-07-17',8,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(370,'2025-07-17',7,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(371,'2025-07-17',6,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(372,'2025-07-17',3,3,2,1,NULL,8.00,'2025-07-17 06:47:19','2025-07-17 06:47:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(373,'2025-07-18',7,4,3,2,6,2.00,'2025-07-18 05:54:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(374,'2025-07-18',1,4,3,2,6,2.00,'2025-07-18 05:54:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(376,'2025-07-18',5,4,3,1,NULL,2.00,'2025-07-18 05:58:33','2025-07-18 05:58:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(377,'2025-07-18',5,3,2,1,NULL,6.00,'2025-07-18 05:58:33','2025-07-18 05:58:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(378,'2025-07-18',7,3,2,1,NULL,6.00,'2025-07-18 05:59:42','2025-07-18 05:59:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(379,'2025-07-18',1,3,3,1,NULL,6.00,'2025-07-18 06:00:15','2025-07-18 06:00:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(380,'2025-07-18',10,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(381,'2025-07-18',9,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(382,'2025-07-18',8,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(383,'2025-07-18',6,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(384,'2025-07-18',4,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(385,'2025-07-18',3,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(386,'2025-07-18',2,3,2,1,NULL,8.00,'2025-07-18 06:36:13','2025-07-18 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(387,'2025-07-21',5,4,3,2,6,4.00,'2025-07-21 06:40:08','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(388,'2025-07-21',5,3,2,1,NULL,4.00,'2025-07-21 06:40:08','2025-07-21 06:40:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(389,'2025-07-21',4,4,3,2,6,4.00,'2025-07-21 06:40:08','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(390,'2025-07-21',4,3,2,1,NULL,4.00,'2025-07-21 06:40:08','2025-07-21 06:40:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(391,'2025-07-21',10,3,2,1,NULL,6.00,'2025-07-21 06:40:32','2025-07-22 06:58:42',5,3,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(392,'2025-07-21',9,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(393,'2025-07-21',8,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(394,'2025-07-21',7,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(395,'2025-07-21',6,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(396,'2025-07-21',3,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(397,'2025-07-21',2,3,2,1,NULL,8.00,'2025-07-21 06:40:32','2025-07-21 06:40:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(398,'2025-07-21',1,3,3,1,NULL,8.00,'2025-07-21 06:53:37','2025-07-21 06:53:37',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(399,'2025-07-22',10,3,2,1,NULL,8.00,'2025-07-22 06:45:47','2025-07-22 06:45:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(400,'2025-07-22',9,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(401,'2025-07-22',8,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(402,'2025-07-22',7,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(403,'2025-07-22',6,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(404,'2025-07-22',4,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(405,'2025-07-22',3,3,2,1,NULL,8.00,'2025-07-22 06:45:48','2025-07-22 06:45:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(406,'2025-07-22',2,4,3,2,6,8.00,'2025-07-22 06:46:11','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(407,'2025-07-22',5,3,3,1,NULL,8.00,'2025-07-22 06:46:11','2025-07-22 06:46:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(408,'2025-07-22',1,3,3,1,NULL,8.00,'2025-07-22 06:46:11','2025-07-22 06:46:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(409,'2025-07-23',4,3,3,1,NULL,8.00,'2025-07-23 06:45:06','2025-07-23 06:45:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(410,'2025-07-23',5,3,3,1,NULL,8.00,'2025-07-23 06:45:28','2025-07-23 06:45:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(411,'2025-07-23',1,3,3,1,NULL,8.00,'2025-07-23 06:45:28','2025-07-23 06:45:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(412,'2025-07-23',10,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(413,'2025-07-23',9,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(414,'2025-07-23',7,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(415,'2025-07-23',6,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(416,'2025-07-23',3,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(417,'2025-07-23',2,3,2,1,NULL,8.00,'2025-07-23 06:45:30','2025-07-23 06:45:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(418,'2025-07-24',4,3,3,1,NULL,8.00,'2025-07-24 06:36:55','2025-07-24 06:36:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(419,'2025-07-24',10,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(420,'2025-07-24',9,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(421,'2025-07-24',7,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(422,'2025-07-24',6,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(423,'2025-07-24',3,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(424,'2025-07-24',2,3,2,1,NULL,8.00,'2025-07-24 06:37:18','2025-07-24 06:37:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(425,'2025-07-24',5,3,3,1,NULL,8.00,'2025-07-24 06:47:04','2025-07-24 06:47:04',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(426,'2025-07-24',1,3,3,1,NULL,8.00,'2025-07-24 06:47:04','2025-07-24 06:47:04',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(427,'2025-07-25',4,3,3,1,NULL,8.00,'2025-07-25 06:44:23','2025-07-25 06:44:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(428,'2025-07-25',10,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(429,'2025-07-25',9,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(430,'2025-07-25',8,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(431,'2025-07-25',6,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(432,'2025-07-25',3,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(433,'2025-07-25',2,3,2,1,NULL,8.00,'2025-07-25 06:45:15','2025-07-25 06:45:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(434,'2025-07-25',5,4,3,1,NULL,8.00,'2025-07-25 06:45:18','2025-07-25 06:45:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(435,'2025-07-25',7,4,3,1,NULL,8.00,'2025-07-25 06:45:19','2025-07-25 06:45:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(436,'2025-07-25',1,4,3,1,NULL,8.00,'2025-07-25 06:45:19','2025-07-25 06:45:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(437,'2025-07-28',5,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(438,'2025-07-28',4,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(439,'2025-07-28',1,3,3,1,NULL,8.00,'2025-07-28 06:30:39','2025-07-28 06:30:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(440,'2025-07-28',2,5,2,1,NULL,4.00,'2025-07-28 06:33:08','2025-07-28 06:33:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(441,'2025-07-28',2,3,2,1,NULL,4.00,'2025-07-28 06:33:08','2025-07-28 06:33:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(442,'2025-07-28',10,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(443,'2025-07-28',9,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(444,'2025-07-28',8,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(445,'2025-07-28',7,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(446,'2025-07-28',6,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(447,'2025-07-28',3,3,2,1,NULL,8.00,'2025-07-28 06:33:34','2025-07-28 06:33:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(448,'2025-07-29',5,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(449,'2025-07-29',4,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(450,'2025-07-29',1,3,3,1,NULL,8.00,'2025-07-29 06:39:13','2025-07-29 06:39:13',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(451,'2025-07-30',5,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(452,'2025-07-30',4,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(453,'2025-07-30',1,3,3,1,NULL,8.00,'2025-07-30 06:50:30','2025-07-30 06:50:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(454,'2025-07-30',10,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(455,'2025-07-30',9,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(456,'2025-07-30',8,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(457,'2025-07-30',7,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(458,'2025-07-30',6,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(459,'2025-07-30',3,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(460,'2025-07-30',2,3,2,1,NULL,8.00,'2025-07-30 06:52:16','2025-07-30 06:52:16',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(461,'2025-07-31',1,3,3,1,NULL,4.00,'2025-07-31 06:42:56','2025-07-31 06:42:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(462,'2025-07-31',4,3,3,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(463,'2025-07-31',4,3,2,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(464,'2025-07-31',5,3,3,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(465,'2025-07-31',5,3,2,1,NULL,4.00,'2025-07-31 06:43:32','2025-07-31 06:43:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(466,'2025-07-31',10,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(467,'2025-07-31',9,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(468,'2025-07-31',8,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(469,'2025-07-31',7,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(470,'2025-07-31',6,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(471,'2025-07-31',3,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(472,'2025-07-31',2,3,2,1,NULL,8.00,'2025-07-31 06:44:00','2025-07-31 06:44:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(473,'2025-07-11',10,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(474,'2025-07-11',5,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(475,'2025-07-11',4,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(476,'2025-07-11',9,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(477,'2025-07-11',8,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(478,'2025-07-11',3,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(479,'2025-07-11',2,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(480,'2025-07-11',7,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(481,'2025-07-11',6,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(482,'2025-07-11',1,3,2,1,NULL,8.00,'2025-07-31 22:24:47','2025-07-31 22:24:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(483,'2025-08-01',10,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(484,'2025-08-01',9,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(485,'2025-08-01',8,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(486,'2025-08-01',7,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(487,'2025-08-01',6,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(488,'2025-08-01',3,3,2,1,NULL,8.00,'2025-08-01 04:57:47','2025-08-01 04:57:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(489,'2025-08-01',2,3,2,1,NULL,8.00,'2025-08-01 04:57:48','2025-08-01 04:57:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(490,'2025-08-01',4,3,3,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(491,'2025-08-01',4,5,1,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(492,'2025-08-01',5,3,3,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(493,'2025-08-01',5,5,1,1,NULL,4.00,'2025-08-01 05:02:28','2025-08-01 05:02:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(494,'2025-08-07',9,3,2,2,43,4.00,'2025-08-07 06:42:39','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(495,'2025-08-07',9,3,2,1,NULL,4.00,'2025-08-07 06:42:39','2025-08-07 06:42:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(496,'2025-08-07',7,3,2,2,43,4.00,'2025-08-07 06:42:39','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(497,'2025-08-07',7,3,2,1,NULL,4.00,'2025-08-07 06:42:39','2025-08-07 06:42:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(498,'2025-08-07',10,5,2,1,NULL,8.00,'2025-08-07 06:43:14','2025-08-07 06:43:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(499,'2025-08-07',4,5,2,1,NULL,8.00,'2025-08-07 06:43:15','2025-08-07 06:43:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(500,'2025-08-07',2,5,2,1,NULL,8.00,'2025-08-07 06:43:15','2025-08-07 06:43:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(501,'2025-08-07',6,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(502,'2025-08-07',3,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(503,'2025-08-07',8,3,2,1,NULL,8.00,'2025-08-07 06:43:39','2025-08-07 06:43:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(504,'2025-08-07',1,3,3,1,NULL,8.00,'2025-08-07 06:43:52','2025-08-07 06:43:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(505,'2025-08-08',1,3,3,1,NULL,8.00,'2025-08-08 06:45:20','2025-08-08 06:45:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(506,'2025-08-08',10,5,2,1,NULL,8.00,'2025-08-08 06:58:42','2025-08-08 06:58:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(507,'2025-08-08',2,5,2,1,NULL,8.00,'2025-08-08 06:58:42','2025-08-08 06:58:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(508,'2025-08-08',9,3,2,1,NULL,8.00,'2025-08-08 06:59:18','2025-08-08 06:59:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(509,'2025-08-08',8,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(510,'2025-08-08',3,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(511,'2025-08-08',4,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(512,'2025-08-08',6,3,2,1,NULL,8.00,'2025-08-08 06:59:19','2025-08-08 06:59:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(513,'2025-08-11',1,3,3,1,NULL,8.00,'2025-08-11 06:27:37','2025-08-11 06:27:37',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(514,'2025-08-11',1,3,3,1,NULL,8.00,'2025-08-11 06:27:37','2025-08-11 06:27:37',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(515,'2025-08-11',10,5,2,1,NULL,8.00,'2025-08-11 06:46:23','2025-08-11 06:46:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(516,'2025-08-11',2,5,2,1,NULL,8.00,'2025-08-11 06:46:23','2025-08-11 06:46:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(517,'2025-08-11',8,3,2,1,NULL,8.00,'2025-08-11 06:46:49','2025-08-11 06:46:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(518,'2025-08-11',7,3,2,1,NULL,8.00,'2025-08-11 06:46:49','2025-08-11 06:46:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(519,'2025-08-11',6,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(520,'2025-08-11',5,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(521,'2025-08-11',4,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(522,'2025-08-11',3,3,2,1,NULL,8.00,'2025-08-11 06:46:50','2025-08-11 06:46:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(523,'2025-08-12',10,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(524,'2025-08-12',9,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(525,'2025-08-12',8,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(526,'2025-08-12',7,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(527,'2025-08-12',5,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(528,'2025-08-12',4,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(529,'2025-08-12',3,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(530,'2025-08-12',1,3,2,1,NULL,8.00,'2025-08-12 06:47:24','2025-08-12 06:47:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(531,'2025-08-13',1,3,3,1,NULL,8.00,'2025-08-13 06:31:32','2025-08-13 06:31:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(532,'2025-08-13',2,3,2,1,NULL,4.00,'2025-08-13 06:36:13','2025-08-13 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(533,'2025-08-13',2,5,2,1,NULL,4.00,'2025-08-13 06:36:13','2025-08-13 06:36:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(534,'2025-08-13',9,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(535,'2025-08-13',8,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(536,'2025-08-13',7,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(537,'2025-08-13',6,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(538,'2025-08-13',5,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(539,'2025-08-13',4,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(540,'2025-08-13',3,3,2,1,NULL,8.00,'2025-08-13 06:36:48','2025-08-13 06:36:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(541,'2025-08-13',10,5,2,1,NULL,8.00,'2025-08-13 06:37:19','2025-08-13 06:37:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(542,'2025-08-14',1,3,3,2,6,4.00,'2025-08-14 06:35:27','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(543,'2025-08-14',1,3,3,1,NULL,4.00,'2025-08-14 06:35:27','2025-08-14 06:35:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(544,'2025-08-14',10,5,2,1,NULL,4.00,'2025-08-14 06:39:03','2025-08-14 06:39:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(545,'2025-08-14',10,5,3,1,NULL,4.00,'2025-08-14 06:39:03','2025-08-14 06:39:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(546,'2025-08-14',2,5,2,1,NULL,2.00,'2025-08-14 06:39:44','2025-08-14 06:39:44',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(547,'2025-08-14',2,3,2,1,NULL,6.00,'2025-08-14 06:39:44','2025-08-14 06:39:44',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(548,'2025-08-14',9,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(549,'2025-08-14',8,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(550,'2025-08-14',7,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(551,'2025-08-14',6,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(552,'2025-08-14',5,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(553,'2025-08-14',4,3,2,1,NULL,8.00,'2025-08-14 06:40:10','2025-08-14 06:40:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(554,'2025-08-18',2,3,2,1,NULL,8.00,'2025-08-18 06:21:36','2025-08-18 06:21:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(555,'2025-08-18',8,3,2,1,NULL,8.00,'2025-08-18 06:21:36','2025-08-18 06:21:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(556,'2025-08-18',4,3,2,1,NULL,8.00,'2025-08-18 06:22:01','2025-08-18 06:22:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(557,'2025-08-18',10,5,3,1,NULL,6.00,'2025-08-18 06:22:53','2025-08-18 06:22:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(558,'2025-08-18',10,3,2,1,NULL,2.00,'2025-08-18 06:22:53','2025-08-18 06:22:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(559,'2025-08-18',9,3,2,1,NULL,4.00,'2025-08-18 06:23:34','2025-08-18 06:23:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(560,'2025-08-18',9,3,3,1,NULL,4.00,'2025-08-18 06:23:34','2025-08-18 06:23:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(561,'2025-08-18',5,3,3,2,6,4.00,'2025-08-18 06:41:24','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(562,'2025-08-18',1,3,3,2,6,4.00,'2025-08-18 06:41:24','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(563,'2025-08-18',7,3,3,2,6,4.00,'2025-08-18 06:41:24','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(564,'2025-08-18',7,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(565,'2025-08-18',5,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(566,'2025-08-18',1,3,3,1,NULL,4.00,'2025-08-18 06:43:10','2025-08-18 06:43:10',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(567,'2025-08-18',6,3,3,1,NULL,8.00,'2025-08-18 06:43:35','2025-08-18 06:43:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(568,'2025-08-18',3,3,3,1,NULL,8.00,'2025-08-18 06:43:35','2025-08-18 06:43:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(569,'2025-08-19',1,3,3,1,NULL,6.00,'2025-08-19 08:02:49','2025-08-19 08:02:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(573,'2025-08-19',9,3,3,1,NULL,10.00,'2025-08-19 08:03:30','2025-08-19 08:03:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(574,'2025-08-19',10,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(575,'2025-08-19',8,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(576,'2025-08-19',5,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(577,'2025-08-19',4,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(578,'2025-08-19',2,3,2,1,NULL,10.00,'2025-08-19 08:04:05','2025-08-19 08:04:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(579,'2025-08-19',3,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(580,'2025-08-19',7,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(581,'2025-08-19',6,3,3,1,NULL,10.00,'2025-08-19 08:36:51','2025-08-19 08:36:51',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(582,'2025-08-20',2,3,2,1,NULL,8.00,'2025-08-20 06:19:36','2025-08-20 06:19:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(583,'2025-08-20',5,3,1,1,NULL,2.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(584,'2025-08-20',5,3,2,1,NULL,6.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(585,'2025-08-20',4,3,1,1,NULL,2.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(586,'2025-08-20',4,3,2,1,NULL,6.00,'2025-08-20 06:21:28','2025-08-20 06:21:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(587,'2025-08-20',6,3,3,1,NULL,4.00,'2025-08-20 06:43:46','2025-08-20 06:43:46',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(589,'2025-08-20',9,3,3,1,NULL,8.00,'2025-08-20 06:44:23','2025-08-20 06:44:23',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(590,'2025-08-20',8,3,3,1,NULL,8.00,'2025-08-20 06:44:23','2025-08-20 06:44:23',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(591,'2025-08-20',7,3,3,1,NULL,8.00,'2025-08-20 06:44:24','2025-08-20 06:44:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(593,'2025-08-20',1,3,3,1,NULL,8.00,'2025-08-20 06:44:24','2025-08-20 06:44:24',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(594,'2025-08-20',10,3,3,1,NULL,8.00,'2025-08-20 06:44:26','2025-08-20 06:44:26',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(595,'2025-08-20',3,3,3,1,NULL,8.00,'2025-08-20 06:44:26','2025-08-20 06:44:26',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(596,'2025-08-21',7,3,3,1,NULL,8.00,'2025-08-21 06:30:36','2025-08-21 06:30:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(597,'2025-08-21',1,3,3,1,NULL,8.00,'2025-08-21 06:30:36','2025-08-21 06:30:36',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(600,'2025-08-21',10,3,3,1,NULL,8.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(601,'2025-08-21',10,3,3,1,NULL,2.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(602,'2025-08-21',9,3,3,1,NULL,8.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(603,'2025-08-21',9,3,3,1,NULL,2.00,'2025-08-21 07:51:23','2025-08-21 07:51:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(608,'2025-08-21',2,3,2,1,NULL,8.00,'2025-08-21 07:54:46','2025-08-21 07:54:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(609,'2025-08-21',2,5,2,1,NULL,2.00,'2025-08-21 07:54:46','2025-08-21 07:54:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(610,'2025-08-21',8,3,3,1,NULL,4.00,'2025-08-21 07:55:25','2025-08-21 07:55:25',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(611,'2025-08-21',8,3,2,1,NULL,6.00,'2025-08-21 07:55:25','2025-08-21 07:55:25',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(612,'2025-08-21',6,3,3,1,NULL,10.00,'2025-08-21 08:24:50','2025-08-21 08:24:50',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(613,'2025-08-21',3,3,3,1,NULL,10.00,'2025-08-21 08:24:50','2025-08-21 08:24:50',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(614,'2025-08-22',2,3,2,1,NULL,8.00,'2025-08-22 06:21:15','2025-08-22 06:21:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(615,'2025-08-22',8,3,2,1,NULL,4.00,'2025-08-22 06:23:12','2025-08-22 06:23:12',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(616,'2025-08-22',8,3,3,1,NULL,4.00,'2025-08-22 06:23:12','2025-08-22 06:23:12',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(617,'2025-08-22',5,3,3,1,NULL,8.00,'2025-08-22 06:23:55','2025-08-22 06:23:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(618,'2025-08-22',6,3,2,1,NULL,4.00,'2025-08-22 06:27:43','2025-08-22 06:27:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(619,'2025-08-22',10,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(620,'2025-08-22',9,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(621,'2025-08-22',7,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(622,'2025-08-22',4,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(623,'2025-08-22',3,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(624,'2025-08-22',1,3,3,1,NULL,8.00,'2025-08-22 06:28:15','2025-08-22 06:28:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(625,'2025-08-23',4,3,2,1,NULL,2.00,'2025-08-23 04:57:02','2025-08-23 04:57:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(626,'2025-08-23',4,3,3,1,NULL,6.00,'2025-08-23 04:57:02','2025-08-23 04:57:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(627,'2025-08-23',2,3,2,1,NULL,8.00,'2025-08-23 04:57:25','2025-08-23 04:57:25',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(628,'2025-08-23',10,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(629,'2025-08-23',9,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(630,'2025-08-23',8,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(631,'2025-08-23',6,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(632,'2025-08-23',5,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(633,'2025-08-23',3,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(634,'2025-08-23',1,3,3,1,NULL,8.00,'2025-08-23 04:57:54','2025-08-23 04:57:54',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(635,'2025-08-25',10,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(636,'2025-08-25',9,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(637,'2025-08-25',8,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(638,'2025-08-25',7,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(640,'2025-08-25',5,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(641,'2025-08-25',4,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(643,'2025-08-25',2,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(644,'2025-08-25',1,3,3,1,NULL,8.00,'2025-08-25 06:48:34','2025-08-25 06:48:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(645,'2025-08-25',6,3,3,1,NULL,8.00,'2025-08-25 06:49:16','2025-08-25 06:49:16',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(646,'2025-08-25',3,3,3,1,NULL,8.00,'2025-08-25 06:49:17','2025-08-25 06:49:17',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(647,'2025-08-26',4,8,3,1,NULL,8.00,'2025-08-26 07:28:03','2025-08-26 07:28:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(648,'2025-08-26',4,3,3,1,NULL,2.00,'2025-08-26 07:28:03','2025-08-26 07:28:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(649,'2025-08-26',2,8,3,1,NULL,10.00,'2025-08-26 07:28:35','2025-08-26 07:28:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(651,'2025-08-26',9,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(652,'2025-08-26',8,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(653,'2025-08-26',7,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(655,'2025-08-26',5,3,3,1,NULL,10.00,'2025-08-26 07:29:02','2025-08-26 07:29:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(657,'2025-08-26',1,3,3,1,NULL,10.00,'2025-08-26 07:29:03','2025-08-26 07:29:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(658,'2025-08-26',6,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(659,'2025-08-26',10,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(660,'2025-08-26',3,3,3,1,NULL,10.00,'2025-08-26 08:22:12','2025-08-26 08:22:12',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(661,'2025-08-27',10,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(662,'2025-08-27',9,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(663,'2025-08-27',7,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(664,'2025-08-27',6,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(665,'2025-08-27',5,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(666,'2025-08-27',4,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(667,'2025-08-27',3,3,3,2,38,8.00,'2025-08-27 06:44:47','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(668,'2025-08-27',1,3,3,2,38,8.00,'2025-08-27 06:44:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(669,'2025-08-27',2,3,3,2,6,2.00,'2025-08-27 06:45:32','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(670,'2025-08-27',2,8,2,1,NULL,6.00,'2025-08-27 06:45:32','2025-08-27 06:45:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(671,'2025-08-27',8,3,3,2,6,2.00,'2025-08-27 06:45:32','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(672,'2025-08-27',8,8,2,1,NULL,6.00,'2025-08-27 06:45:32','2025-08-27 06:45:32',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(673,'2025-08-28',10,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(674,'2025-08-28',10,3,3,2,6,4.00,'2025-08-28 08:31:42','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(675,'2025-08-28',5,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(676,'2025-08-28',5,3,3,2,6,4.00,'2025-08-28 08:31:42','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(677,'2025-08-28',6,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(678,'2025-08-28',6,3,3,2,6,4.00,'2025-08-28 08:31:42','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(679,'2025-08-28',3,3,3,1,NULL,6.00,'2025-08-28 08:31:42','2025-08-28 08:31:42',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(680,'2025-08-28',3,3,3,2,6,4.00,'2025-08-28 08:31:42','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(681,'2025-08-28',4,3,3,1,NULL,4.00,'2025-08-28 08:37:46','2025-08-28 08:37:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(682,'2025-08-28',4,5,3,1,NULL,4.00,'2025-08-28 08:37:46','2025-08-28 08:37:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(683,'2025-08-28',8,8,2,1,NULL,4.00,'2025-08-28 08:38:15','2025-08-28 08:38:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(684,'2025-08-28',8,5,3,1,NULL,4.00,'2025-08-28 08:38:15','2025-08-28 08:38:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(685,'2025-08-28',2,3,3,2,6,2.00,'2025-08-28 08:38:50','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(686,'2025-08-28',2,5,3,1,NULL,6.00,'2025-08-28 08:38:50','2025-08-28 08:38:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(687,'2025-08-28',1,3,3,2,6,8.00,'2025-08-28 08:39:24','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(689,'2025-08-28',9,3,3,2,43,8.00,'2025-08-28 08:40:00','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(690,'2025-08-28',7,3,3,2,43,8.00,'2025-08-28 08:40:00','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(694,'2025-08-28',4,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(695,'2025-08-28',8,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(696,'2025-08-28',2,5,3,1,NULL,2.00,'2025-08-28 08:44:56','2025-08-28 08:44:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(698,'2025-08-28',9,3,3,1,NULL,2.00,'2025-08-28 08:45:19','2025-08-28 08:45:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(699,'2025-08-28',7,3,3,1,NULL,2.00,'2025-08-28 08:45:19','2025-08-28 08:45:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(703,'2025-08-29',10,3,3,2,38,8.00,'2025-08-29 06:47:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(704,'2025-08-29',9,3,3,2,38,8.00,'2025-08-29 06:47:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(706,'2025-08-29',7,3,3,2,38,8.00,'2025-08-29 06:47:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(710,'2025-08-29',1,3,3,2,38,8.00,'2025-08-29 06:47:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(713,'2025-08-29',5,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(714,'2025-08-29',5,3,3,2,6,2.00,'2025-08-29 06:47:35','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(715,'2025-08-29',3,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(716,'2025-08-29',3,3,3,2,6,2.00,'2025-08-29 06:47:35','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(717,'2025-08-29',6,3,3,1,NULL,6.00,'2025-08-29 06:47:35','2025-08-29 06:47:35',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(718,'2025-08-29',6,3,3,2,6,2.00,'2025-08-29 06:47:35','2026-02-05 22:24:28',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(719,'2025-08-29',8,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(720,'2025-08-29',4,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(721,'2025-08-29',2,5,3,1,NULL,8.00,'2025-08-29 21:55:56','2025-08-29 21:55:56',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(722,'2025-08-30',2,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(723,'2025-08-30',8,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(724,'2025-08-30',4,5,3,1,NULL,8.00,'2025-08-30 05:12:03','2025-08-30 05:12:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(725,'2025-08-30',10,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(726,'2025-08-30',9,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(727,'2025-08-30',7,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(728,'2025-08-30',6,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(729,'2025-08-30',5,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(730,'2025-08-30',3,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(731,'2025-08-30',1,3,3,2,6,8.00,'2025-08-30 05:36:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(732,'2025-09-01',7,3,3,1,NULL,8.00,'2025-09-01 06:18:28','2025-09-01 06:18:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(733,'2025-09-01',9,3,3,1,NULL,8.00,'2025-09-01 06:18:28','2025-09-01 06:18:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(734,'2025-09-01',10,3,3,2,38,4.00,'2025-09-01 06:19:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(735,'2025-09-01',3,3,3,2,38,4.00,'2025-09-01 06:19:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(736,'2025-09-01',1,3,3,2,38,4.00,'2025-09-01 06:19:11','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(737,'2025-09-01',10,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(738,'2025-09-01',3,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(739,'2025-09-01',1,3,3,1,NULL,4.00,'2025-09-01 06:19:35','2025-09-01 06:19:35',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(740,'2025-09-01',5,3,3,2,6,8.00,'2025-09-01 06:20:03','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(741,'2025-08-21',4,3,3,1,NULL,10.00,'2025-09-01 23:18:03','2025-09-01 23:18:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(742,'2025-08-21',5,3,3,1,NULL,10.00,'2025-09-01 23:18:03','2025-09-01 23:18:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(745,'2025-09-02',10,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(746,'2025-09-02',9,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(747,'2025-09-02',6,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(748,'2025-09-02',5,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(749,'2025-09-02',3,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(750,'2025-09-02',1,3,3,2,6,6.00,'2025-09-02 07:36:04','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(751,'2025-09-02',10,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(752,'2025-09-02',9,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(753,'2025-09-02',6,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(754,'2025-09-02',5,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(755,'2025-09-02',3,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(756,'2025-09-02',1,3,3,1,NULL,4.00,'2025-09-02 07:36:31','2025-09-02 07:36:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(757,'2025-09-02',8,3,3,1,NULL,10.00,'2025-09-02 07:37:19','2025-09-02 07:37:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(758,'2025-09-02',7,3,3,1,NULL,10.00,'2025-09-02 07:37:19','2025-09-02 07:37:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(759,'2025-09-02',2,5,3,1,NULL,8.00,'2025-09-02 08:16:14','2025-09-02 08:16:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(760,'2025-09-02',2,5,3,1,NULL,2.00,'2025-09-02 08:16:14','2025-09-02 08:16:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(761,'2025-09-02',4,5,3,1,NULL,8.00,'2025-09-02 08:16:14','2025-09-02 08:16:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(762,'2025-09-02',4,5,3,1,NULL,2.00,'2025-09-02 08:16:14','2025-09-02 08:16:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(763,'2025-09-03',10,3,3,1,NULL,8.00,'2025-09-03 06:34:47','2025-09-03 06:34:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(764,'2025-09-03',9,3,3,1,NULL,8.00,'2025-09-03 06:34:47','2025-09-03 06:34:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(765,'2025-09-03',8,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(766,'2025-09-03',7,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(767,'2025-09-03',6,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(768,'2025-09-03',5,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(769,'2025-09-03',3,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(770,'2025-09-03',1,3,3,1,NULL,8.00,'2025-09-03 06:34:48','2025-09-03 06:34:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(771,'2025-09-03',2,5,3,1,NULL,8.00,'2025-09-03 06:44:18','2025-09-03 06:44:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(772,'2025-09-04',10,3,3,1,NULL,8.00,'2025-09-04 06:41:32','2025-09-04 06:41:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(773,'2025-09-04',5,3,3,1,NULL,8.00,'2025-09-04 06:41:32','2025-09-04 06:41:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(774,'2025-09-04',9,3,3,1,NULL,8.00,'2025-09-04 06:41:32','2025-09-04 06:41:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(775,'2025-09-04',8,3,3,1,NULL,8.00,'2025-09-04 06:41:32','2025-09-04 06:41:32',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(776,'2025-09-04',3,3,3,1,NULL,8.00,'2025-09-04 06:41:33','2025-09-04 06:41:33',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(777,'2025-09-04',7,3,3,1,NULL,8.00,'2025-09-04 06:41:33','2025-09-04 06:41:33',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(778,'2025-09-04',1,3,3,1,NULL,8.00,'2025-09-04 06:41:33','2025-09-04 06:41:33',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(779,'2025-09-04',6,3,3,1,NULL,8.00,'2025-09-04 06:41:33','2025-09-04 06:41:33',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(780,'2025-09-04',2,5,3,1,NULL,8.00,'2025-09-04 06:48:34','2025-09-04 06:48:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(781,'2025-09-04',4,5,3,1,NULL,8.00,'2025-09-04 06:48:34','2025-09-04 06:48:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(782,'2025-09-05',10,3,3,1,NULL,8.00,'2025-09-05 06:39:30','2025-09-05 06:39:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(783,'2025-09-05',9,3,3,1,NULL,8.00,'2025-09-05 06:39:30','2025-09-05 06:39:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(784,'2025-09-05',7,3,3,1,NULL,8.00,'2025-09-05 06:39:30','2025-09-05 06:39:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(785,'2025-09-05',6,3,3,1,NULL,8.00,'2025-09-05 06:39:31','2025-09-05 06:39:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(786,'2025-09-05',5,3,3,1,NULL,8.00,'2025-09-05 06:39:31','2025-09-05 06:39:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(787,'2025-09-05',3,3,3,1,NULL,8.00,'2025-09-05 06:39:31','2025-09-05 06:39:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(788,'2025-09-05',1,3,3,1,NULL,8.00,'2025-09-05 06:39:31','2025-09-05 06:39:31',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(789,'2025-09-05',2,5,3,1,NULL,8.00,'2025-09-05 22:09:55','2025-09-05 22:09:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(790,'2025-09-05',8,5,3,1,NULL,8.00,'2025-09-05 22:09:55','2025-09-05 22:09:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(791,'2025-09-05',4,5,3,1,NULL,8.00,'2025-09-05 22:09:55','2025-09-05 22:09:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(792,'2025-09-06',8,10,3,1,NULL,8.00,'2025-09-06 04:21:10','2025-09-06 04:21:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(793,'2025-09-06',4,10,3,1,NULL,8.00,'2025-09-06 04:21:10','2025-09-06 04:21:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(794,'2025-09-06',2,10,3,1,NULL,8.00,'2025-09-06 04:21:10','2025-09-06 04:21:10',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(795,'2025-09-06',10,3,3,1,NULL,8.00,'2025-09-06 05:28:18','2025-09-06 05:28:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(796,'2025-09-06',9,3,3,1,NULL,8.00,'2025-09-06 05:28:18','2025-09-06 05:28:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(797,'2025-09-06',7,3,3,1,NULL,8.00,'2025-09-06 05:28:18','2025-09-06 05:28:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(798,'2025-09-06',6,3,3,1,NULL,8.00,'2025-09-06 05:28:19','2025-09-06 05:28:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(799,'2025-09-06',5,3,3,1,NULL,8.00,'2025-09-06 05:28:19','2025-09-06 05:28:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(800,'2025-09-06',3,3,3,1,NULL,8.00,'2025-09-06 05:28:19','2025-09-06 05:28:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(801,'2025-09-06',1,3,3,1,NULL,8.00,'2025-09-06 05:28:19','2025-09-06 05:28:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(802,'2025-09-08',10,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(803,'2025-09-08',9,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(804,'2025-09-08',7,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(805,'2025-09-08',6,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(806,'2025-09-08',5,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(807,'2025-09-08',3,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(808,'2025-09-08',1,3,3,1,NULL,8.00,'2025-09-08 06:15:43','2025-09-08 06:15:43',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(809,'2025-09-08',8,5,3,1,NULL,8.00,'2025-09-08 06:47:37','2025-09-08 06:47:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(810,'2025-09-08',4,5,3,1,NULL,8.00,'2025-09-08 06:47:37','2025-09-08 06:47:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(811,'2025-09-08',2,5,3,1,NULL,8.00,'2025-09-08 06:47:37','2025-09-08 06:47:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(812,'2025-09-09',10,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(813,'2025-09-09',9,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(814,'2025-09-09',7,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(815,'2025-09-09',6,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(816,'2025-09-09',5,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(817,'2025-09-09',3,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(818,'2025-09-09',1,3,3,1,NULL,8.00,'2025-09-09 06:03:27','2025-09-09 06:03:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(819,'2025-09-09',8,5,3,1,NULL,8.00,'2025-09-09 06:44:29','2025-09-09 06:44:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(820,'2025-09-09',4,5,3,1,NULL,8.00,'2025-09-09 06:44:29','2025-09-09 06:44:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(821,'2025-09-09',2,5,3,1,NULL,8.00,'2025-09-09 06:44:29','2025-09-09 06:44:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(822,'2025-09-10',10,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(823,'2025-09-10',9,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(824,'2025-09-10',7,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(825,'2025-09-10',6,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(826,'2025-09-10',5,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(827,'2025-09-10',3,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(828,'2025-09-10',1,3,3,1,NULL,8.00,'2025-09-10 06:27:52','2025-09-10 06:27:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(829,'2025-09-10',8,5,3,1,NULL,8.00,'2025-09-10 06:48:43','2025-09-10 06:48:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(830,'2025-09-10',4,5,3,1,NULL,8.00,'2025-09-10 06:48:43','2025-09-10 06:48:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(831,'2025-09-10',2,5,3,1,NULL,8.00,'2025-09-10 06:48:43','2025-09-10 06:48:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(832,'2025-09-11',2,5,3,1,NULL,2.00,'2025-09-11 06:37:11','2025-09-11 06:37:11',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(833,'2025-09-11',2,8,3,1,NULL,6.00,'2025-09-11 06:37:11','2025-09-11 06:37:11',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(834,'2025-09-11',4,5,3,1,NULL,2.00,'2025-09-11 06:38:24','2025-09-11 06:38:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(835,'2025-09-11',4,8,3,1,NULL,2.00,'2025-09-11 06:38:24','2025-09-11 06:38:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(836,'2025-09-11',4,3,3,1,NULL,4.00,'2025-09-11 06:38:24','2025-09-11 06:38:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(838,'2025-09-11',1,3,1,1,NULL,4.00,'2025-09-11 06:40:48','2025-09-11 06:40:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(840,'2025-09-11',5,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(841,'2025-09-11',8,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(842,'2025-09-11',3,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(843,'2025-09-11',7,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(844,'2025-09-11',6,3,2,1,NULL,8.00,'2025-09-11 06:41:47','2025-09-11 06:41:47',6,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(845,'2025-09-11',10,3,2,1,NULL,4.00,'2025-09-11 06:41:51','2025-09-11 06:41:51',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(846,'2025-09-11',10,3,3,1,NULL,4.00,'2025-09-11 06:41:51','2025-09-11 06:41:51',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(847,'2025-09-11',9,3,2,1,NULL,4.00,'2025-09-11 06:41:51','2025-09-11 06:41:51',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(848,'2025-09-11',9,3,3,1,NULL,4.00,'2025-09-11 06:41:51','2025-09-11 06:41:51',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(851,'2025-09-12',10,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(852,'2025-09-12',9,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(853,'2025-09-12',8,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(854,'2025-09-12',6,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(855,'2025-09-12',5,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(856,'2025-09-12',4,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(857,'2025-09-12',3,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(858,'2025-09-12',2,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(859,'2025-09-12',1,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(860,'2025-09-12',7,3,3,1,NULL,8.00,'2025-09-12 06:45:29','2025-09-12 06:45:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(861,'2025-09-13',10,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(862,'2025-09-13',8,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(863,'2025-09-13',7,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(864,'2025-09-13',6,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(865,'2025-09-13',5,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(866,'2025-09-13',4,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(867,'2025-09-13',3,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(868,'2025-09-13',2,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(869,'2025-09-13',1,3,3,1,NULL,8.00,'2025-09-13 06:38:14','2025-09-13 06:38:14',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(870,'2025-09-14',9,3,3,1,NULL,8.00,'2025-09-14 04:47:40','2025-09-14 04:47:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(871,'2025-09-14',8,3,3,1,NULL,8.00,'2025-09-14 04:47:40','2025-09-14 04:47:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(872,'2025-09-14',7,3,3,1,NULL,8.00,'2025-09-14 04:47:40','2025-09-14 04:47:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(873,'2025-09-14',6,3,3,1,NULL,8.00,'2025-09-14 04:47:40','2025-09-14 04:47:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(874,'2025-09-14',5,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(875,'2025-09-14',4,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(876,'2025-09-14',3,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(877,'2025-09-14',2,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(878,'2025-09-14',1,3,3,1,NULL,8.00,'2025-09-14 04:47:41','2025-09-14 04:47:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(879,'2025-09-15',5,3,3,1,NULL,8.00,'2025-09-15 06:50:00','2025-09-15 06:50:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(880,'2025-09-15',10,3,3,1,NULL,8.00,'2025-09-15 06:50:00','2025-09-15 06:50:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(881,'2025-09-15',9,3,3,1,NULL,8.00,'2025-09-15 06:50:00','2025-09-15 06:50:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(882,'2025-09-15',8,3,3,1,NULL,8.00,'2025-09-15 06:50:00','2025-09-15 06:50:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(883,'2025-09-15',7,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(884,'2025-09-15',6,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(885,'2025-09-15',4,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(886,'2025-09-15',3,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(887,'2025-09-15',2,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(888,'2025-09-15',1,3,3,1,NULL,8.00,'2025-09-15 06:50:01','2025-09-15 06:50:01',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(889,'2025-09-16',2,8,3,1,NULL,8.00,'2025-09-16 06:51:19','2025-09-16 06:51:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(890,'2025-09-16',4,8,3,1,NULL,8.00,'2025-09-16 06:51:19','2025-09-16 06:51:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(891,'2025-09-16',8,8,2,1,NULL,2.00,'2025-09-16 06:52:12','2025-09-16 06:52:12',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(892,'2025-09-16',8,3,2,1,NULL,6.00,'2025-09-16 06:52:12','2025-09-16 06:52:12',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(893,'2025-09-17',4,8,3,1,NULL,8.00,'2025-09-17 06:43:08','2025-09-17 06:43:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(894,'2025-09-17',2,8,3,1,NULL,8.00,'2025-09-17 06:43:08','2025-09-17 06:43:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(895,'2025-09-17',10,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(896,'2025-09-17',9,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(897,'2025-09-17',8,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(898,'2025-09-17',7,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(899,'2025-09-17',6,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(900,'2025-09-17',5,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(901,'2025-09-17',3,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(902,'2025-09-17',1,3,3,1,NULL,8.00,'2025-09-17 06:45:06','2025-09-17 06:45:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(903,'2025-09-18',7,3,3,1,NULL,8.00,'2025-09-18 06:43:40','2025-09-18 06:43:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(904,'2025-09-18',1,3,3,1,NULL,8.00,'2025-09-18 06:43:40','2025-09-18 06:43:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(905,'2025-09-18',10,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(906,'2025-09-18',9,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(907,'2025-09-18',8,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(908,'2025-09-18',6,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(909,'2025-09-18',3,3,2,1,NULL,8.00,'2025-09-18 06:44:42','2025-09-18 06:44:42',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(910,'2025-09-18',5,3,2,1,NULL,6.00,'2025-09-18 06:46:39','2025-09-18 06:46:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(911,'2025-09-18',2,8,3,1,NULL,8.00,'2025-09-18 06:54:48','2025-09-18 06:54:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(912,'2025-09-18',4,8,3,1,NULL,8.00,'2025-09-18 06:54:48','2025-09-18 06:54:48',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(913,'2025-09-19',4,8,3,1,NULL,8.00,'2025-09-19 06:51:40','2025-09-19 06:51:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(914,'2025-09-19',2,8,3,1,NULL,8.00,'2025-09-19 06:51:40','2025-09-19 06:51:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(915,'2025-09-19',10,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(916,'2025-09-19',8,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(917,'2025-09-19',7,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(918,'2025-09-19',6,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(919,'2025-09-19',5,3,2,1,NULL,8.00,'2025-09-19 06:52:05','2025-09-19 06:52:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(920,'2025-09-19',3,3,2,1,NULL,4.00,'2025-09-19 06:52:23','2025-09-19 06:52:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(921,'2025-09-20',4,8,3,1,NULL,8.00,'2025-09-20 05:30:19','2025-09-20 05:30:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(922,'2025-09-20',2,8,3,1,NULL,8.00,'2025-09-20 05:30:19','2025-09-20 05:30:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(923,'2025-09-22',10,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(924,'2025-09-22',9,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(925,'2025-09-22',8,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(926,'2025-09-22',7,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(927,'2025-09-22',5,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(928,'2025-09-22',1,3,2,1,NULL,8.00,'2025-09-22 06:47:25','2025-09-22 06:47:25',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(929,'2025-09-22',4,8,3,1,NULL,8.00,'2025-09-22 06:50:29','2025-09-22 06:50:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(930,'2025-09-22',2,8,3,1,NULL,8.00,'2025-09-22 06:50:29','2025-09-22 06:50:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(931,'2025-09-23',4,8,3,1,NULL,8.00,'2025-09-23 05:46:40','2025-09-23 05:46:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(932,'2025-09-23',2,8,3,1,NULL,8.00,'2025-09-23 05:46:40','2025-09-23 05:46:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(933,'2025-09-24',4,8,3,1,NULL,8.00,'2025-09-25 01:14:58','2025-09-25 01:14:58',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(934,'2025-09-24',2,8,3,1,NULL,8.00,'2025-09-25 01:14:58','2025-09-25 01:14:58',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(935,'2025-09-29',7,14,1,1,NULL,8.00,'2025-09-29 06:36:07','2025-09-29 06:36:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(936,'2025-09-29',1,14,1,1,NULL,8.00,'2025-09-29 06:36:07','2025-09-29 06:36:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(937,'2025-09-29',10,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(938,'2025-09-29',8,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(939,'2025-09-29',6,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(940,'2025-09-29',9,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(941,'2025-09-29',5,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(942,'2025-09-29',4,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(943,'2025-09-29',3,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(944,'2025-09-29',2,3,2,1,NULL,8.00,'2025-09-29 06:36:47','2025-09-29 06:36:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(945,'2025-09-30',10,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(946,'2025-09-30',9,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(947,'2025-09-30',8,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(948,'2025-09-30',6,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(949,'2025-09-30',5,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(950,'2025-09-30',4,3,2,1,NULL,8.00,'2025-09-30 06:52:26','2025-09-30 06:52:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(951,'2025-09-30',3,3,2,1,NULL,8.00,'2025-09-30 06:52:27','2025-09-30 06:52:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(953,'2025-09-30',1,3,2,1,NULL,8.00,'2025-09-30 06:52:27','2025-09-30 06:52:27',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(954,'2025-09-30',2,8,3,1,NULL,8.00,'2025-09-30 06:56:55','2025-09-30 06:56:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(955,'2025-10-02',5,3,2,1,NULL,6.00,'2025-10-02 05:25:58','2025-10-02 05:25:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(956,'2025-10-02',8,3,2,1,NULL,6.00,'2025-10-02 05:25:59','2025-10-02 05:25:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(957,'2025-10-02',10,3,2,1,NULL,8.00,'2025-10-02 06:22:32','2025-10-02 06:22:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(958,'2025-10-02',9,3,2,1,NULL,8.00,'2025-10-02 06:22:32','2025-10-02 06:22:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(959,'2025-10-02',7,3,2,1,NULL,8.00,'2025-10-02 06:22:32','2025-10-02 06:22:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(960,'2025-10-02',6,3,2,1,NULL,8.00,'2025-10-02 06:22:32','2025-10-02 06:22:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(961,'2025-10-02',4,3,2,1,NULL,8.00,'2025-10-02 06:22:33','2025-10-02 06:22:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(962,'2025-10-02',2,3,2,1,NULL,8.00,'2025-10-02 06:22:33','2025-10-02 06:22:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(963,'2025-10-02',1,3,2,1,NULL,8.00,'2025-10-02 06:22:33','2025-10-02 06:22:33',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(964,'2025-09-01',8,5,3,1,NULL,8.00,'2025-10-10 23:35:07','2025-10-10 23:35:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(965,'2025-09-01',4,5,3,1,NULL,8.00,'2025-10-10 23:35:07','2025-10-10 23:35:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(966,'2025-09-01',2,5,3,1,NULL,8.00,'2025-10-10 23:35:07','2025-10-10 23:35:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(967,'2025-10-13',10,10,3,1,NULL,8.00,'2025-10-13 06:53:05','2025-10-13 06:53:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(968,'2025-10-13',7,10,3,1,NULL,8.00,'2025-10-13 06:53:05','2025-10-13 06:53:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(969,'2025-10-13',2,10,3,1,NULL,8.00,'2025-10-13 06:53:05','2025-10-13 06:53:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(970,'2025-10-13',8,3,2,1,NULL,8.00,'2025-10-13 06:53:30','2025-10-13 06:53:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(971,'2025-10-13',6,3,2,1,NULL,8.00,'2025-10-13 06:53:30','2025-10-13 06:53:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(972,'2025-10-13',3,3,2,1,NULL,8.00,'2025-10-13 06:53:30','2025-10-13 06:53:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(973,'2025-10-13',5,3,3,1,NULL,8.00,'2025-10-13 06:53:53','2025-10-13 06:53:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(974,'2025-10-13',4,3,3,1,NULL,8.00,'2025-10-13 06:53:53','2025-10-13 06:53:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(975,'2025-10-13',9,3,2,1,NULL,4.00,'2025-10-13 06:54:19','2025-10-13 06:54:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(976,'2025-10-13',9,10,3,1,NULL,4.00,'2025-10-13 06:54:19','2025-10-13 06:54:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(977,'2025-10-13',1,3,1,1,NULL,8.00,'2025-10-13 06:54:41','2025-10-13 06:54:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(978,'2025-10-14',10,10,3,1,NULL,8.00,'2025-10-14 06:55:49','2025-10-14 06:55:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(979,'2025-10-14',2,10,3,1,NULL,8.00,'2025-10-14 06:55:49','2025-10-14 06:55:49',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(980,'2025-10-14',9,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(981,'2025-10-14',8,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(982,'2025-10-14',7,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(983,'2025-10-14',6,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(984,'2025-10-14',5,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(985,'2025-10-14',4,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(986,'2025-10-14',3,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(987,'2025-10-14',1,3,2,1,NULL,8.00,'2025-10-14 06:56:57','2025-10-14 06:56:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(988,'2025-10-15',8,3,2,1,NULL,8.00,'2025-10-15 06:58:52','2025-10-15 06:58:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(989,'2025-10-15',7,3,2,1,NULL,8.00,'2025-10-15 06:58:52','2025-10-15 06:58:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(990,'2025-10-15',6,3,2,1,NULL,8.00,'2025-10-15 06:58:52','2025-10-15 06:58:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(991,'2025-10-15',5,3,2,1,NULL,8.00,'2025-10-15 06:58:52','2025-10-15 06:58:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(992,'2025-10-15',4,3,2,1,NULL,8.00,'2025-10-15 06:58:53','2025-10-15 06:58:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(993,'2025-10-15',3,3,2,1,NULL,8.00,'2025-10-15 06:58:53','2025-10-15 06:58:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(994,'2025-10-15',1,3,2,1,NULL,8.00,'2025-10-15 06:58:53','2025-10-15 06:58:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(995,'2025-10-15',10,10,3,1,6,8.00,'2025-10-15 06:59:41','2026-02-05 22:40:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(996,'2025-10-15',9,10,3,1,NULL,8.00,'2025-10-15 06:59:41','2025-10-15 06:59:41',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(997,'2025-10-15',2,10,3,1,NULL,4.00,'2025-10-15 07:00:06','2025-10-15 07:00:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(998,'2025-10-16',9,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(999,'2025-10-16',8,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1000,'2025-10-16',7,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1001,'2025-10-16',6,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1002,'2025-10-16',5,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1003,'2025-10-16',4,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1004,'2025-10-16',3,3,2,1,NULL,8.00,'2025-10-16 06:51:59','2025-10-16 06:51:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1005,'2025-10-16',1,3,2,1,NULL,8.00,'2025-10-16 06:52:00','2025-10-16 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1006,'2025-10-20',9,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1007,'2025-10-20',8,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1008,'2025-10-20',7,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1009,'2025-10-20',6,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1010,'2025-10-20',5,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1011,'2025-10-20',4,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1012,'2025-10-20',3,3,2,1,NULL,8.00,'2025-10-20 06:49:45','2025-10-20 06:49:45',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1013,'2025-10-20',1,3,2,1,NULL,8.00,'2025-10-20 06:49:46','2025-10-20 06:49:46',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1014,'2025-10-20',2,10,3,1,NULL,8.00,'2025-10-20 06:50:55','2025-10-20 06:50:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1015,'2025-10-20',10,10,3,1,NULL,8.00,'2025-10-20 06:50:55','2025-10-20 06:50:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1017,'2025-10-21',10,3,3,1,NULL,4.00,'2025-10-21 08:42:41','2025-10-21 08:42:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1019,'2025-10-21',2,3,3,1,NULL,4.00,'2025-10-21 08:42:41','2025-10-21 08:42:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1020,'2025-10-21',8,3,2,1,NULL,10.00,'2025-10-21 08:43:34','2025-10-21 08:43:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1021,'2025-10-21',6,3,2,1,NULL,10.00,'2025-10-21 08:43:34','2025-10-21 08:43:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1022,'2025-10-21',3,3,2,1,NULL,10.00,'2025-10-21 08:43:34','2025-10-21 08:43:34',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1023,'2025-10-21',10,10,3,1,NULL,6.00,'2025-10-21 08:44:26','2025-10-21 08:44:26',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1024,'2025-10-21',2,10,3,1,NULL,6.00,'2025-10-21 08:44:27','2025-10-21 08:44:27',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1025,'2025-10-21',5,3,3,1,NULL,10.00,'2025-10-21 08:45:01','2025-10-21 08:45:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1026,'2025-10-21',4,3,3,1,NULL,10.00,'2025-10-21 08:45:01','2025-10-21 08:45:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1027,'2025-10-21',9,3,3,1,NULL,10.00,'2025-10-21 08:45:28','2025-10-21 08:45:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1028,'2025-10-21',1,3,3,1,NULL,10.00,'2025-10-21 08:45:28','2025-10-21 08:45:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1029,'2025-10-21',7,3,3,1,NULL,10.00,'2025-10-21 08:45:28','2025-10-21 08:45:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1030,'2025-10-22',2,11,2,1,NULL,4.00,'2025-10-22 06:47:36','2025-10-22 06:47:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1031,'2025-10-22',2,10,1,1,NULL,4.00,'2025-10-22 06:47:36','2025-10-22 06:47:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1032,'2025-10-22',10,11,2,1,NULL,4.00,'2025-10-22 06:47:36','2025-10-22 06:47:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1033,'2025-10-22',10,10,1,1,NULL,4.00,'2025-10-22 06:47:36','2025-10-22 06:47:36',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1034,'2025-10-22',9,3,3,1,NULL,8.00,'2025-10-22 06:48:06','2025-10-22 06:48:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1035,'2025-10-22',8,3,3,1,NULL,8.00,'2025-10-22 06:48:06','2025-10-22 06:48:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1036,'2025-10-22',6,3,3,1,NULL,8.00,'2025-10-22 06:48:06','2025-10-22 06:48:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1039,'2025-10-22',7,3,3,1,NULL,8.00,'2025-10-22 06:48:11','2025-10-22 06:48:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1043,'2025-10-22',3,3,3,1,NULL,8.00,'2025-10-22 06:48:11','2025-10-22 06:48:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1044,'2025-10-22',1,3,3,1,NULL,8.00,'2025-10-22 06:48:11','2025-10-22 06:48:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1047,'2025-10-22',5,11,3,1,NULL,8.00,'2025-10-22 06:48:50','2025-10-22 06:48:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1048,'2025-10-22',4,11,3,1,NULL,8.00,'2025-10-22 06:48:50','2025-10-22 06:48:50',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1051,'2025-10-24',9,3,3,1,NULL,8.00,'2025-10-24 06:47:05','2025-10-24 06:47:05',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1052,'2025-10-24',8,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1053,'2025-10-24',7,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1054,'2025-10-24',6,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1055,'2025-10-24',5,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1056,'2025-10-24',3,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1057,'2025-10-24',1,3,3,1,NULL,8.00,'2025-10-24 06:47:06','2025-10-24 06:47:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1058,'2025-10-24',4,3,3,1,NULL,4.00,'2025-10-24 06:48:13','2025-10-24 06:48:13',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1059,'2025-10-25',10,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1060,'2025-10-25',8,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1061,'2025-10-25',6,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1062,'2025-10-25',5,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1063,'2025-10-25',4,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1064,'2025-10-25',3,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1065,'2025-10-25',1,3,3,1,NULL,8.00,'2025-10-25 05:32:47','2025-10-25 05:32:47',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1066,'2025-10-27',9,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1067,'2025-10-27',8,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1070,'2025-10-27',5,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1071,'2025-10-27',4,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1072,'2025-10-27',3,3,3,1,NULL,8.00,'2025-10-27 06:41:58','2025-10-27 06:41:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1074,'2025-10-27',6,3,3,1,NULL,4.00,'2025-10-27 06:43:11','2025-10-27 06:43:11',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1075,'2025-10-27',10,10,3,1,NULL,8.00,'2025-10-28 08:44:41','2025-10-28 08:44:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1076,'2025-10-27',2,10,3,1,NULL,8.00,'2025-10-28 08:44:41','2025-10-28 08:44:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1077,'2025-10-28',10,10,3,1,NULL,10.00,'2025-10-28 08:45:05','2025-10-28 08:45:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1078,'2025-10-28',2,10,3,1,NULL,10.00,'2025-10-28 08:45:05','2025-10-28 08:45:05',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1079,'2025-10-28',7,3,1,2,6,10.00,'2025-10-28 08:47:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1080,'2025-10-28',1,3,1,2,6,10.00,'2025-10-28 08:47:28','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1081,'2025-10-28',9,3,3,1,NULL,10.00,'2025-10-28 08:48:02','2025-10-28 08:48:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1082,'2025-10-28',8,3,3,1,NULL,10.00,'2025-10-28 08:48:02','2025-10-28 08:48:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1083,'2025-10-28',6,3,3,1,NULL,10.00,'2025-10-28 08:48:02','2025-10-28 08:48:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1084,'2025-10-28',5,3,3,1,NULL,10.00,'2025-10-28 08:48:02','2025-10-28 08:48:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1085,'2025-10-28',4,3,3,1,NULL,10.00,'2025-10-28 08:48:03','2025-10-28 08:48:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1086,'2025-10-28',3,3,3,1,NULL,10.00,'2025-10-28 08:48:03','2025-10-28 08:48:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1087,'2025-10-29',8,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1089,'2025-10-29',6,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1090,'2025-10-29',5,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1091,'2025-10-29',4,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1092,'2025-10-29',3,3,3,1,NULL,8.00,'2025-10-29 06:51:34','2025-10-29 06:51:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1094,'2025-10-29',10,10,3,1,NULL,8.00,'2025-10-29 06:51:44','2025-10-29 06:51:44',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1095,'2025-10-29',2,10,3,1,NULL,8.00,'2025-10-29 06:51:44','2025-10-29 06:51:44',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1097,'2025-10-30',8,3,3,1,NULL,8.00,'2025-10-30 08:49:06','2025-10-30 08:49:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1098,'2025-10-30',8,10,3,1,NULL,2.00,'2025-10-30 08:49:06','2025-10-30 08:49:06',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1099,'2025-10-30',9,13,4,1,NULL,0.00,'2025-10-30 08:49:47','2025-10-30 08:49:47',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1100,'2025-10-30',7,3,3,1,NULL,10.00,'2025-10-30 08:50:19','2025-10-30 08:50:19',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1101,'2025-10-30',5,11,3,1,NULL,10.00,'2025-10-30 08:50:43','2025-10-30 08:50:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1102,'2025-10-30',4,11,3,1,NULL,10.00,'2025-10-30 08:50:43','2025-10-30 08:50:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1104,'2025-10-30',2,10,3,1,NULL,10.00,'2025-10-30 08:51:30','2025-10-30 08:51:30',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1105,'2025-10-30',6,3,3,1,NULL,10.00,'2025-10-30 08:52:04','2025-10-30 08:52:04',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1106,'2025-10-30',3,3,3,1,NULL,10.00,'2025-10-30 08:52:04','2025-10-30 08:52:04',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1107,'2025-10-31',9,10,3,2,6,8.00,'2025-10-31 06:53:09','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1108,'2025-10-31',2,10,3,2,6,8.00,'2025-10-31 06:53:09','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1110,'2025-11-01',10,10,3,1,NULL,8.00,'2025-11-01 05:55:09','2025-11-01 05:55:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1111,'2025-11-01',9,10,3,1,NULL,8.00,'2025-11-01 05:55:09','2025-11-01 05:55:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1112,'2025-11-01',2,10,3,1,NULL,8.00,'2025-11-01 05:55:09','2025-11-01 05:55:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1113,'2025-10-30',1,13,1,1,NULL,2.00,'2025-11-03 21:48:30','2025-11-03 21:48:30',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1114,'2025-10-30',9,13,1,1,NULL,8.00,'2025-11-03 21:56:32','2025-11-03 21:56:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1115,'2025-10-01',10,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1116,'2025-10-01',4,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1117,'2025-10-01',3,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1118,'2025-10-01',9,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1119,'2025-10-01',8,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1120,'2025-10-01',2,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1121,'2025-10-01',1,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1122,'2025-10-01',7,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1123,'2025-10-01',6,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1124,'2025-10-01',5,3,2,1,NULL,8.00,'2025-11-04 05:29:09','2025-11-04 05:29:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1125,'2025-10-02',5,13,1,1,NULL,2.00,'2025-11-04 05:30:23','2025-11-04 05:30:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1126,'2025-10-02',8,13,1,1,NULL,2.00,'2025-11-04 05:31:11','2025-11-04 05:31:11',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1127,'2025-10-02',3,13,11,1,NULL,8.00,'2025-11-04 06:09:53','2025-11-04 06:09:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1128,'2025-10-15',2,13,11,1,NULL,4.00,'2025-11-04 06:10:29','2025-11-04 06:10:29',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1130,'2025-10-16',2,10,3,2,6,8.00,'2025-11-04 06:11:29','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1131,'2025-10-16',10,10,3,2,6,8.00,'2025-11-04 06:11:47','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1132,'2025-10-24',10,10,3,2,6,8.00,'2025-11-04 06:12:35','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1133,'2025-10-24',2,10,3,2,6,8.00,'2025-11-04 06:12:51','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1134,'2025-10-24',4,13,11,1,NULL,4.00,'2025-11-04 06:13:01','2025-11-04 06:13:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1135,'2025-10-27',6,13,11,1,NULL,4.00,'2025-11-04 06:13:24','2025-11-04 06:13:24',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1136,'2025-10-30',10,10,3,1,NULL,8.00,'2025-11-04 06:15:07','2025-11-04 06:15:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1137,'2025-10-29',9,3,3,1,NULL,8.00,'2025-11-04 06:15:43','2025-11-04 06:15:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1138,'2025-10-25',9,13,11,1,NULL,8.00,'2025-11-04 06:17:02','2025-11-04 06:17:02',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1139,'2025-10-25',7,13,11,1,NULL,8.00,'2025-11-04 06:17:15','2025-11-04 06:17:15',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1140,'2025-10-25',2,13,11,1,NULL,8.00,'2025-11-04 06:17:29','2025-11-04 06:17:29',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1141,'2025-10-17',10,10,3,2,6,8.00,'2025-11-04 06:31:47','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1142,'2025-10-17',2,10,3,2,6,8.00,'2025-11-04 06:31:47','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1143,'2025-10-17',9,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1144,'2025-10-17',8,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1145,'2025-10-17',7,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1146,'2025-10-17',6,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1147,'2025-10-17',5,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1148,'2025-10-17',4,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1149,'2025-10-17',3,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1150,'2025-10-17',1,3,3,2,6,8.00,'2025-11-04 06:36:54','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1151,'2025-10-23',2,10,3,2,6,10.00,'2025-11-04 06:37:19','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1152,'2025-10-23',10,10,3,2,6,10.00,'2025-11-04 06:37:19','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1153,'2025-10-23',9,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1154,'2025-10-23',8,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1155,'2025-10-23',7,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1156,'2025-10-23',6,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1157,'2025-10-23',5,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1159,'2025-10-23',3,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1160,'2025-10-23',4,3,3,2,6,10.00,'2025-11-04 06:37:41','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1161,'2025-10-31',10,10,3,2,6,8.00,'2025-11-04 06:38:35','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1164,'2025-10-31',3,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1165,'2025-10-31',4,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1166,'2025-10-31',1,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1167,'2025-10-31',7,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1168,'2025-10-31',5,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1169,'2025-10-31',8,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1170,'2025-10-31',6,3,3,2,6,8.00,'2025-11-04 06:39:13','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1171,'2025-10-23',1,3,3,2,6,8.00,'2025-11-04 06:43:18','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1172,'2025-10-30',1,3,3,1,NULL,5.00,'2025-11-04 22:27:07','2025-11-04 22:27:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1173,'2025-10-30',1,14,1,1,NULL,1.00,'2025-11-04 22:27:22','2025-11-04 22:27:22',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1174,'2025-10-29',1,3,3,1,NULL,7.00,'2025-11-04 22:27:49','2025-11-04 22:27:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1175,'2025-10-29',1,14,1,1,NULL,1.00,'2025-11-04 22:28:03','2025-11-04 22:28:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1176,'2025-10-29',7,14,1,1,NULL,1.00,'2025-11-04 22:28:22','2025-11-04 22:28:22',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1177,'2025-10-29',7,3,3,1,NULL,7.00,'2025-11-04 22:28:32','2025-11-04 22:28:32',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1178,'2025-10-27',1,3,3,1,NULL,6.00,'2025-11-04 22:29:03','2025-11-04 22:29:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1179,'2025-10-27',1,14,1,1,NULL,2.00,'2025-11-04 22:29:13','2025-11-04 22:29:13',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1180,'2025-10-27',7,14,1,1,NULL,2.00,'2025-11-04 22:29:34','2025-11-04 22:29:34',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1181,'2025-10-27',7,3,3,1,NULL,6.00,'2025-11-04 22:29:45','2025-11-04 22:29:45',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1192,'2025-11-03',2,10,3,2,6,8.00,'2025-11-05 02:54:31','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1193,'2025-11-03',10,10,3,2,6,8.00,'2025-11-05 02:54:31','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1194,'2025-11-03',9,10,3,2,6,6.00,'2025-11-05 02:55:16','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1195,'2025-11-03',9,3,3,1,NULL,2.00,'2025-11-05 02:55:16','2025-11-05 02:55:16',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1196,'2025-11-03',6,10,3,2,6,6.00,'2025-11-05 02:55:16','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1197,'2025-11-03',6,3,3,1,NULL,2.00,'2025-11-05 02:55:16','2025-11-05 02:55:16',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1199,'2025-11-05',10,10,3,1,NULL,8.00,'2025-11-05 06:54:26','2025-11-05 06:54:26',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1200,'2025-11-05',2,10,3,1,NULL,8.00,'2025-11-05 06:54:26','2025-11-05 06:54:26',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1201,'2025-11-05',9,10,3,1,NULL,4.00,'2025-11-05 06:54:40','2025-11-05 06:54:40',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1202,'2025-11-06',10,10,3,2,6,4.00,'2025-11-06 08:44:42','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1203,'2025-11-06',10,11,3,1,NULL,6.00,'2025-11-06 08:44:42','2025-11-06 08:44:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1204,'2025-11-06',4,11,1,1,NULL,10.00,'2025-11-06 08:45:59','2025-11-06 08:45:59',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1205,'2025-11-06',5,11,1,1,NULL,10.00,'2025-11-06 08:45:59','2025-11-06 08:45:59',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1206,'2025-11-06',2,10,3,2,6,1.00,'2025-11-06 08:46:46','2026-02-05 22:24:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1207,'2025-11-06',2,11,3,1,NULL,9.00,'2025-11-06 08:46:46','2025-11-06 08:46:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1208,'2025-11-06',9,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1209,'2025-11-06',8,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1210,'2025-11-06',7,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1211,'2025-11-06',6,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1212,'2025-11-06',3,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1213,'2025-11-06',1,3,3,1,NULL,10.00,'2025-11-06 08:48:17','2025-11-06 08:48:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1214,'2025-11-07',7,3,3,1,NULL,4.00,'2025-11-07 06:48:19','2025-11-07 06:48:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1217,'2025-11-07',9,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1218,'2025-11-07',8,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1219,'2025-11-07',6,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1222,'2025-11-07',3,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1223,'2025-11-07',1,3,3,1,NULL,8.00,'2025-11-07 06:48:57','2025-11-07 06:48:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1224,'2025-11-07',4,10,3,1,NULL,2.00,'2025-11-07 06:49:20','2025-11-07 06:49:20',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1225,'2025-11-07',4,3,3,1,NULL,6.00,'2025-11-07 06:49:20','2025-11-07 06:49:20',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1226,'2025-11-07',5,10,3,1,NULL,2.00,'2025-11-07 06:49:20','2025-11-07 06:49:20',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1227,'2025-11-07',5,3,3,1,NULL,6.00,'2025-11-07 06:49:20','2025-11-07 06:49:20',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1228,'2025-11-07',2,11,3,1,NULL,8.00,'2025-11-07 06:50:15','2025-11-07 06:50:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1229,'2025-11-07',10,11,3,1,NULL,8.00,'2025-11-07 06:50:55','2025-11-07 06:50:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1230,'2025-11-08',10,11,3,1,NULL,8.00,'2025-11-08 05:53:23','2025-11-08 05:53:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1231,'2025-11-08',2,11,3,1,NULL,8.00,'2025-11-08 05:53:24','2025-11-08 05:53:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1232,'2025-11-09',10,10,3,1,NULL,8.00,'2025-11-09 05:39:09','2025-11-09 05:39:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1233,'2025-11-09',2,10,3,1,NULL,8.00,'2025-11-09 05:39:09','2025-11-09 05:39:09',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1234,'2025-11-09',9,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1235,'2025-11-09',8,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1236,'2025-11-09',7,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1237,'2025-11-09',6,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1238,'2025-11-09',3,3,3,1,NULL,8.00,'2025-11-09 05:40:41','2025-11-09 05:40:41',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1239,'2025-11-10',10,10,3,1,NULL,8.00,'2025-11-11 08:28:29','2025-11-11 08:28:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1240,'2025-11-10',4,10,3,1,NULL,8.00,'2025-11-11 08:28:29','2025-11-11 08:28:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1241,'2025-11-10',2,10,3,1,NULL,8.00,'2025-11-11 08:28:29','2025-11-11 08:28:29',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1242,'2025-11-11',10,11,3,1,NULL,8.00,'2025-11-11 08:29:03','2025-11-11 08:29:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1243,'2025-11-11',9,11,3,1,NULL,8.00,'2025-11-11 08:29:03','2025-11-11 08:29:03',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1244,'2025-11-11',4,10,3,1,NULL,4.00,'2025-11-11 08:29:45','2025-11-11 08:29:45',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1245,'2025-11-11',4,11,3,1,NULL,6.00,'2025-11-11 08:29:45','2025-11-11 08:29:45',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1246,'2025-11-11',2,10,3,1,NULL,10.00,'2025-11-11 08:30:08','2025-11-11 08:30:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1247,'2025-11-11',10,11,3,1,NULL,2.00,'2025-11-11 08:30:35','2025-11-11 08:30:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1248,'2025-11-11',9,11,3,1,NULL,2.00,'2025-11-11 08:30:35','2025-11-11 08:30:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1249,'2025-11-11',7,3,3,1,NULL,8.00,'2025-11-11 08:45:23','2025-11-11 08:45:23',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1251,'2025-11-11',8,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1252,'2025-11-11',6,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1253,'2025-11-11',5,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1254,'2025-11-11',3,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1255,'2025-11-11',1,3,3,1,NULL,10.00,'2025-11-11 08:46:26','2025-11-11 08:46:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1256,'2025-11-12',10,11,3,1,NULL,8.00,'2025-11-12 06:47:21','2025-11-12 06:47:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1257,'2025-11-12',2,11,3,1,NULL,8.00,'2025-11-12 06:47:21','2025-11-12 06:47:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1258,'2025-11-12',9,11,3,1,NULL,8.00,'2025-11-12 06:47:21','2025-11-12 06:47:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1259,'2025-11-12',8,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1260,'2025-11-12',7,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1261,'2025-11-12',6,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1262,'2025-11-12',5,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1263,'2025-11-12',3,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1264,'2025-11-12',1,3,3,1,NULL,8.00,'2025-11-12 06:52:00','2025-11-12 06:52:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1265,'2025-11-13',10,11,3,1,NULL,10.00,'2025-11-13 08:46:09','2025-11-13 08:46:09',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1266,'2025-11-13',4,11,3,1,NULL,10.00,'2025-11-13 08:46:09','2025-11-13 08:46:09',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1267,'2025-11-13',2,11,3,1,NULL,4.00,'2025-11-13 08:46:32','2025-11-13 08:46:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1268,'2025-11-13',9,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1269,'2025-11-13',8,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1270,'2025-11-13',7,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1271,'2025-11-13',6,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1272,'2025-11-13',5,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1273,'2025-11-13',3,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1274,'2025-11-13',1,3,3,1,NULL,10.00,'2025-11-13 08:47:12','2025-11-13 08:47:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1275,'2025-11-14',10,11,3,1,NULL,6.00,'2025-11-14 07:00:16','2025-11-14 07:00:16',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1276,'2025-11-14',10,11,3,2,6,2.00,'2025-11-14 07:00:16','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1277,'2025-11-14',9,11,3,1,NULL,6.00,'2025-11-14 07:00:16','2025-11-14 07:00:16',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1278,'2025-11-14',9,11,3,2,6,2.00,'2025-11-14 07:00:16','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1279,'2025-11-14',2,11,3,1,NULL,6.00,'2025-11-14 07:00:17','2025-11-14 07:00:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1280,'2025-11-14',2,11,3,2,6,2.00,'2025-11-14 07:00:17','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1281,'2025-11-14',8,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1282,'2025-11-14',8,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1283,'2025-11-14',7,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1284,'2025-11-14',7,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1285,'2025-11-14',5,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1286,'2025-11-14',5,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1287,'2025-11-14',6,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1288,'2025-11-14',6,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1289,'2025-11-14',4,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1290,'2025-11-14',4,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1291,'2025-11-14',3,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1292,'2025-11-14',3,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1293,'2025-11-14',1,3,3,1,NULL,3.00,'2025-11-14 07:00:51','2025-11-14 07:00:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1294,'2025-11-14',1,3,3,2,6,5.00,'2025-11-14 07:00:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1295,'2025-11-15',10,11,3,1,NULL,8.00,'2025-11-15 05:46:53','2025-11-15 05:46:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1296,'2025-11-15',9,11,3,1,NULL,8.00,'2025-11-15 05:46:53','2025-11-15 05:46:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1297,'2025-11-15',2,11,3,1,NULL,8.00,'2025-11-15 05:46:53','2025-11-15 05:46:53',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1298,'2025-11-17',10,11,3,1,NULL,8.00,'2025-11-18 08:45:07','2025-11-18 08:45:07',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1300,'2025-11-17',2,11,3,1,NULL,8.00,'2025-11-18 08:45:08','2025-11-18 08:45:08',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1301,'2025-11-18',4,11,3,1,NULL,6.00,'2025-11-18 08:46:01','2025-11-18 08:46:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1302,'2025-11-18',4,10,3,1,NULL,4.00,'2025-11-18 08:46:01','2025-11-18 08:46:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1303,'2025-11-18',2,11,3,1,NULL,6.00,'2025-11-18 08:46:01','2025-11-18 08:46:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1304,'2025-11-18',2,10,3,1,NULL,4.00,'2025-11-18 08:46:01','2025-11-18 08:46:01',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1305,'2025-11-18',10,11,3,1,NULL,10.00,'2025-11-18 08:46:23','2025-11-18 08:46:23',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1306,'2025-11-24',2,11,3,1,NULL,8.00,'2025-11-25 08:47:55','2025-11-25 08:47:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1307,'2025-11-24',4,11,3,1,NULL,8.00,'2025-11-25 08:47:55','2025-11-25 08:47:55',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1308,'2025-11-22',4,11,3,1,NULL,8.00,'2025-11-25 08:48:18','2025-11-25 08:48:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1309,'2025-11-22',2,11,3,1,NULL,8.00,'2025-11-25 08:48:18','2025-11-25 08:48:18',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1310,'2025-11-21',4,11,3,1,NULL,8.00,'2025-11-25 08:48:39','2025-11-25 08:48:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1311,'2025-11-21',2,11,3,1,NULL,8.00,'2025-11-25 08:48:39','2025-11-25 08:48:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1312,'2025-11-25',4,11,3,1,NULL,10.00,'2025-11-25 08:49:02','2025-11-25 08:49:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1313,'2025-11-25',2,11,3,1,NULL,10.00,'2025-11-25 08:49:02','2025-11-25 08:49:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1314,'2025-11-26',10,11,3,1,NULL,8.00,'2025-11-26 06:51:13','2025-11-26 06:51:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1315,'2025-11-26',4,11,3,1,NULL,8.00,'2025-11-26 06:51:13','2025-11-26 06:51:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1316,'2025-11-26',2,11,3,1,NULL,8.00,'2025-11-26 06:51:13','2025-11-26 06:51:13',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1317,'2025-11-27',10,11,3,1,NULL,10.00,'2025-11-27 07:34:37','2025-11-27 07:34:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1318,'2025-11-27',4,11,3,1,NULL,10.00,'2025-11-27 07:34:37','2025-11-27 07:34:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1319,'2025-11-27',2,11,3,1,NULL,10.00,'2025-11-27 07:34:37','2025-11-27 07:34:37',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1320,'2025-11-27',9,11,3,1,NULL,6.00,'2025-11-27 07:35:24','2025-11-27 07:35:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1321,'2025-11-27',9,3,3,1,NULL,4.00,'2025-11-27 07:35:24','2025-11-27 07:35:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1322,'2025-11-28',10,11,3,1,NULL,8.00,'2025-11-28 06:47:35','2025-11-28 06:47:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1323,'2025-11-28',9,11,3,1,NULL,8.00,'2025-11-28 06:47:35','2025-11-28 06:47:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1324,'2025-11-28',2,11,3,1,NULL,8.00,'2025-11-28 06:47:35','2025-11-28 06:47:35',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1325,'2025-11-28',4,13,11,1,NULL,1.00,'2025-11-28 06:48:24','2025-11-28 06:48:24',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1326,'2025-11-29',10,11,3,1,NULL,8.00,'2025-11-29 05:12:39','2025-11-29 05:12:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1327,'2025-11-29',4,11,3,1,NULL,8.00,'2025-11-29 05:12:39','2025-11-29 05:12:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1328,'2025-11-29',2,11,3,1,NULL,8.00,'2025-11-29 05:12:39','2025-11-29 05:12:39',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1329,'2025-11-29',1,3,3,1,NULL,4.00,'2025-11-29 05:17:02','2025-11-29 05:17:02',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1331,'2025-11-29',8,3,3,1,NULL,8.00,'2025-11-29 05:17:46','2025-11-29 05:17:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1332,'2025-11-29',6,3,3,1,NULL,8.00,'2025-11-29 05:17:46','2025-11-29 05:17:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1333,'2025-11-29',5,3,3,1,NULL,8.00,'2025-11-29 05:17:46','2025-11-29 05:17:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1334,'2025-11-29',3,3,3,1,NULL,8.00,'2025-11-29 05:17:46','2025-11-29 05:17:46',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1335,'2025-12-01',10,11,3,1,NULL,8.00,'2025-12-01 06:55:15','2025-12-01 06:55:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1336,'2025-12-01',9,11,3,1,NULL,8.00,'2025-12-01 06:55:15','2025-12-01 06:55:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1337,'2025-12-01',4,11,3,1,NULL,8.00,'2025-12-01 06:55:15','2025-12-01 06:55:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1338,'2025-12-01',2,11,3,1,NULL,8.00,'2025-12-01 06:55:15','2025-12-01 06:55:15',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1339,'2025-11-01',8,3,3,1,NULL,4.00,'2025-12-02 02:07:51','2025-12-02 02:07:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1340,'2025-11-01',8,3,3,2,6,4.00,'2025-12-02 02:07:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1341,'2025-11-01',7,3,3,1,NULL,4.00,'2025-12-02 02:07:52','2025-12-02 02:07:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1342,'2025-11-01',7,3,3,2,6,4.00,'2025-12-02 02:07:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1345,'2025-11-01',5,3,3,1,NULL,4.00,'2025-12-02 02:07:52','2025-12-02 02:07:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1346,'2025-11-01',5,3,3,2,6,4.00,'2025-12-02 02:07:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1347,'2025-11-01',4,3,3,1,NULL,4.00,'2025-12-02 02:07:52','2025-12-02 02:07:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1348,'2025-11-01',4,3,3,2,6,4.00,'2025-12-02 02:07:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1349,'2025-11-01',3,3,3,1,NULL,4.00,'2025-12-02 02:07:52','2025-12-02 02:07:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1350,'2025-11-01',3,3,3,2,6,4.00,'2025-12-02 02:07:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1353,'2025-11-03',8,3,3,1,NULL,4.00,'2025-12-02 02:09:19','2025-12-02 02:09:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1354,'2025-11-03',8,3,3,2,6,4.00,'2025-12-02 02:09:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1356,'2025-11-03',5,3,3,1,NULL,4.00,'2025-12-02 02:09:19','2025-12-02 02:09:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1357,'2025-11-03',5,3,3,2,6,4.00,'2025-12-02 02:09:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1359,'2025-11-03',4,3,3,1,NULL,4.00,'2025-12-02 02:09:19','2025-12-02 02:09:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1360,'2025-11-03',4,3,3,2,6,4.00,'2025-12-02 02:09:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1362,'2025-11-03',3,3,3,1,NULL,4.00,'2025-12-02 02:09:19','2025-12-02 02:09:19',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1363,'2025-11-03',3,3,3,2,6,4.00,'2025-12-02 02:09:19','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1369,'2025-11-03',7,13,1,1,NULL,8.00,'2025-12-02 02:11:57','2025-12-02 02:11:57',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1370,'2025-11-04',10,10,3,1,NULL,6.00,'2025-12-02 02:17:03','2025-12-02 02:17:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1371,'2025-11-04',10,10,3,2,6,4.00,'2025-12-02 02:17:03','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1372,'2025-11-04',9,10,3,1,NULL,6.00,'2025-12-02 02:17:03','2025-12-02 02:17:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1373,'2025-11-04',9,10,3,2,6,4.00,'2025-12-02 02:17:03','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1374,'2025-11-04',2,10,3,1,NULL,6.00,'2025-12-02 02:17:03','2025-12-02 02:17:03',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1375,'2025-11-04',2,10,3,2,6,4.00,'2025-12-02 02:17:03','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1376,'2025-11-04',8,3,3,1,NULL,8.00,'2025-12-02 02:19:20','2025-12-02 02:19:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1377,'2025-11-04',6,3,3,2,6,4.00,'2025-12-02 02:19:51','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1378,'2025-11-04',6,3,3,1,NULL,4.00,'2025-12-02 02:19:51','2025-12-02 02:19:51',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1379,'2025-11-24',1,3,3,1,NULL,4.00,'2025-12-02 02:43:58','2025-12-02 02:43:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1380,'2025-11-24',1,3,3,2,6,4.00,'2025-12-02 02:43:58','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1381,'2025-11-24',7,3,3,1,NULL,4.00,'2025-12-02 02:43:58','2025-12-02 02:43:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1382,'2025-11-24',7,3,3,2,6,4.00,'2025-12-02 02:43:58','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1383,'2025-11-25',3,3,3,1,NULL,8.00,'2025-12-02 04:17:39','2025-12-02 04:17:39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1384,'2025-11-25',3,3,3,2,6,1.00,'2025-12-02 04:17:39','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1385,'2025-11-25',3,3,3,2,14,1.00,'2025-12-02 04:17:39','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1386,'2025-11-25',6,3,3,1,NULL,8.00,'2025-12-02 04:17:39','2025-12-02 04:17:39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1387,'2025-11-25',6,3,3,2,6,1.00,'2025-12-02 04:17:39','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1388,'2025-11-25',6,3,3,2,14,1.00,'2025-12-02 04:17:39','2026-02-05 22:24:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1389,'2025-12-03',10,11,3,1,NULL,8.00,'2025-12-03 06:52:28','2025-12-03 06:52:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1390,'2025-12-03',9,11,3,1,NULL,8.00,'2025-12-03 06:52:28','2025-12-03 06:52:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1391,'2025-12-03',4,11,3,1,NULL,8.00,'2025-12-03 06:52:28','2025-12-03 06:52:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1392,'2025-12-03',2,11,3,1,NULL,8.00,'2025-12-03 06:52:28','2025-12-03 06:52:28',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1393,'2025-12-04',10,11,3,1,NULL,8.00,'2025-12-04 06:45:00','2025-12-04 06:45:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1394,'2025-12-04',9,11,3,1,NULL,8.00,'2025-12-04 06:45:00','2025-12-04 06:45:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1395,'2025-12-04',4,11,3,1,NULL,8.00,'2025-12-04 06:45:00','2025-12-04 06:45:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1396,'2025-12-04',2,11,3,1,NULL,8.00,'2025-12-04 06:45:00','2025-12-04 06:45:00',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1397,'2025-11-01',6,3,3,1,NULL,4.00,'2025-12-05 00:34:20','2025-12-05 00:34:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1398,'2025-11-01',6,3,3,2,6,4.00,'2025-12-05 00:34:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1399,'2025-11-01',1,3,3,1,NULL,4.00,'2025-12-05 00:34:20','2025-12-05 00:34:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1400,'2025-11-01',1,3,3,2,6,4.00,'2025-12-05 00:34:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1401,'2025-11-03',1,3,3,1,NULL,8.00,'2025-12-05 00:35:16','2025-12-05 00:35:16',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1402,'2025-11-04',6,3,3,1,NULL,2.00,'2025-12-05 01:02:21','2025-12-05 01:02:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1403,'2025-11-04',8,3,3,1,NULL,2.00,'2025-12-05 01:02:21','2025-12-05 01:02:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1404,'2025-11-04',7,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1405,'2025-11-04',7,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1406,'2025-11-04',5,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1407,'2025-11-04',5,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1408,'2025-11-04',4,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1409,'2025-11-04',4,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1410,'2025-11-04',3,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1411,'2025-11-04',3,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1412,'2025-11-04',1,3,3,1,NULL,6.00,'2025-12-05 01:03:12','2025-12-05 01:03:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1413,'2025-11-04',1,3,3,2,6,4.00,'2025-12-05 01:03:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1414,'2025-11-05',8,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1415,'2025-11-05',8,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1416,'2025-11-05',8,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1417,'2025-11-05',7,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1418,'2025-11-05',7,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1419,'2025-11-05',7,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1420,'2025-11-05',6,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1421,'2025-11-05',6,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1422,'2025-11-05',6,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1423,'2025-11-05',4,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1424,'2025-11-05',4,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1425,'2025-11-05',4,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1426,'2025-11-05',3,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1427,'2025-11-05',3,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1428,'2025-11-05',3,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1429,'2025-11-05',1,3,3,1,NULL,5.00,'2025-12-05 01:04:39','2025-12-05 01:04:39',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1430,'2025-11-05',1,3,3,2,1,1.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1431,'2025-11-05',1,3,3,2,6,2.00,'2025-12-05 01:04:39','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1434,'2025-11-08',9,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1435,'2025-11-08',9,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1436,'2025-11-08',8,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1437,'2025-11-08',8,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1438,'2025-11-08',7,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1439,'2025-11-08',7,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1440,'2025-11-08',6,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1441,'2025-11-08',6,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1442,'2025-11-08',5,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1443,'2025-11-08',5,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1444,'2025-11-08',3,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1445,'2025-11-08',3,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1446,'2025-11-08',1,3,3,1,NULL,5.00,'2025-12-05 01:06:12','2025-12-05 01:06:12',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1447,'2025-11-08',1,3,3,2,6,3.00,'2025-12-05 01:06:12','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1448,'2025-11-10',8,3,3,1,NULL,4.00,'2025-12-05 01:06:58','2025-12-05 01:06:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1449,'2025-11-10',8,13,11,1,NULL,4.00,'2025-12-05 01:06:58','2025-12-05 01:06:58',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1450,'2025-11-10',9,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1451,'2025-11-10',9,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1452,'2025-11-10',7,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1453,'2025-11-10',7,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1454,'2025-11-10',6,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1455,'2025-11-10',6,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1456,'2025-11-10',5,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1457,'2025-11-10',5,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1458,'2025-11-10',3,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1459,'2025-11-10',3,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1460,'2025-11-10',1,3,3,1,NULL,4.00,'2025-12-05 01:07:29','2025-12-05 01:07:29',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1461,'2025-11-10',1,3,3,2,6,4.00,'2025-12-05 01:07:29','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1462,'2025-11-12',4,3,3,1,NULL,8.00,'2025-12-05 01:08:07','2025-12-05 01:08:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1463,'2025-11-15',8,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1464,'2025-11-15',8,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1465,'2025-11-15',7,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1466,'2025-11-15',7,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1467,'2025-11-15',6,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1468,'2025-11-15',6,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1469,'2025-11-15',5,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1470,'2025-11-15',5,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1471,'2025-11-15',4,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1472,'2025-11-15',4,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1473,'2025-11-15',3,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1474,'2025-11-15',3,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1475,'2025-11-15',1,3,3,1,NULL,4.00,'2025-12-05 01:08:52','2025-12-05 01:08:52',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1476,'2025-11-15',1,3,3,2,6,4.00,'2025-12-05 01:08:52','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1477,'2025-11-17',9,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1478,'2025-11-17',9,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1479,'2025-11-17',8,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1480,'2025-11-17',8,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1481,'2025-11-17',6,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1482,'2025-11-17',6,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1483,'2025-11-17',5,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1484,'2025-11-17',5,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1485,'2025-11-17',3,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1486,'2025-11-17',3,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1487,'2025-11-17',1,3,3,1,NULL,5.00,'2025-12-05 01:09:53','2025-12-05 01:09:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1488,'2025-11-17',1,3,3,2,6,3.00,'2025-12-05 01:09:53','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1489,'2025-11-18',8,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1490,'2025-11-18',8,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1491,'2025-11-18',9,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1492,'2025-11-18',9,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1493,'2025-11-18',7,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1494,'2025-11-18',7,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1495,'2025-11-18',6,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1496,'2025-11-18',6,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1497,'2025-11-18',5,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1498,'2025-11-18',5,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1499,'2025-11-18',3,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1500,'2025-11-18',3,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1501,'2025-11-18',1,3,3,1,NULL,6.00,'2025-12-05 01:11:02','2025-12-05 01:11:02',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1502,'2025-11-18',1,3,3,2,6,4.00,'2025-12-05 01:11:02','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1503,'2025-11-19',2,11,3,1,NULL,4.00,'2025-12-05 01:12:15','2025-12-05 01:12:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1504,'2025-11-19',2,11,3,2,6,4.00,'2025-12-05 01:12:15','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1505,'2025-11-19',10,11,3,1,NULL,4.00,'2025-12-05 01:12:15','2025-12-05 01:12:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1506,'2025-11-19',10,11,3,2,6,4.00,'2025-12-05 01:12:15','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1507,'2025-11-19',9,11,3,1,NULL,4.00,'2025-12-05 01:12:15','2025-12-05 01:12:15',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1508,'2025-11-19',9,11,3,2,6,4.00,'2025-12-05 01:12:15','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1509,'2025-11-19',8,3,3,1,NULL,5.00,'2025-12-05 01:12:48','2025-12-05 01:12:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1510,'2025-11-19',8,3,3,2,6,3.00,'2025-12-05 01:12:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1511,'2025-11-19',7,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1512,'2025-11-19',7,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1513,'2025-11-19',6,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1514,'2025-11-19',6,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1515,'2025-11-19',5,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1516,'2025-11-19',5,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1517,'2025-11-19',4,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1518,'2025-11-19',4,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1519,'2025-11-19',3,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1520,'2025-11-19',3,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1521,'2025-11-19',1,3,3,1,NULL,5.00,'2025-12-05 01:12:49','2025-12-05 01:12:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1522,'2025-11-19',1,3,3,2,6,3.00,'2025-12-05 01:12:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1523,'2025-11-20',10,11,3,1,NULL,5.00,'2025-12-05 01:13:18','2025-12-05 01:13:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1524,'2025-11-20',10,11,3,2,6,3.00,'2025-12-05 01:13:18','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1525,'2025-11-20',9,11,3,1,NULL,5.00,'2025-12-05 01:13:18','2025-12-05 01:13:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1526,'2025-11-20',9,11,3,2,6,3.00,'2025-12-05 01:13:18','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1527,'2025-11-20',2,11,3,1,NULL,5.00,'2025-12-05 01:13:18','2025-12-05 01:13:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1528,'2025-11-20',2,11,3,2,6,3.00,'2025-12-05 01:13:18','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1529,'2025-11-20',4,11,3,1,NULL,5.00,'2025-12-05 01:13:18','2025-12-05 01:13:18',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1530,'2025-11-20',4,11,3,2,6,3.00,'2025-12-05 01:13:18','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1531,'2025-11-20',8,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1532,'2025-11-20',8,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1533,'2025-11-20',7,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1534,'2025-11-20',7,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1535,'2025-11-20',6,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1536,'2025-11-20',6,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1537,'2025-11-20',5,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1538,'2025-11-20',5,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1539,'2025-11-20',3,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1540,'2025-11-20',3,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1541,'2025-11-20',1,3,3,1,NULL,5.00,'2025-12-05 01:13:48','2025-12-05 01:13:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1542,'2025-11-20',1,3,3,2,6,3.00,'2025-12-05 01:13:48','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1543,'2025-11-21',9,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1544,'2025-11-21',9,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1545,'2025-11-21',8,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1546,'2025-11-21',8,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1547,'2025-11-21',6,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1548,'2025-11-21',6,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1549,'2025-11-21',7,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1550,'2025-11-21',7,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1551,'2025-11-21',5,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1552,'2025-11-21',5,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1553,'2025-11-21',3,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1554,'2025-11-21',3,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1555,'2025-11-21',1,3,3,1,NULL,4.00,'2025-12-05 01:14:50','2025-12-05 01:14:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1556,'2025-11-21',1,3,3,2,14,4.00,'2025-12-05 01:14:50','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1557,'2025-11-22',9,3,3,1,NULL,8.00,'2025-12-05 01:15:21','2025-12-05 01:15:21',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1558,'2025-11-22',8,3,3,1,NULL,8.00,'2025-12-05 01:15:22','2025-12-05 01:15:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1559,'2025-11-22',6,3,3,1,NULL,8.00,'2025-12-05 01:15:22','2025-12-05 01:15:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1560,'2025-11-22',3,3,3,1,NULL,8.00,'2025-12-05 01:15:22','2025-12-05 01:15:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1561,'2025-11-22',1,3,3,1,NULL,8.00,'2025-12-05 01:15:22','2025-12-05 01:15:22',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1562,'2025-11-24',9,11,3,1,NULL,4.00,'2025-12-05 01:21:20','2025-12-05 01:21:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1563,'2025-11-24',9,11,3,2,6,4.00,'2025-12-05 01:21:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1564,'2025-11-24',8,11,3,1,NULL,4.00,'2025-12-05 01:21:20','2025-12-05 01:21:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1565,'2025-11-24',8,11,3,2,6,4.00,'2025-12-05 01:21:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1566,'2025-11-24',6,11,3,1,NULL,4.00,'2025-12-05 01:21:20','2025-12-05 01:21:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1567,'2025-11-24',6,11,3,2,6,4.00,'2025-12-05 01:21:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1568,'2025-11-24',5,11,3,1,NULL,4.00,'2025-12-05 01:21:20','2025-12-05 01:21:20',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1569,'2025-11-24',5,11,3,2,6,4.00,'2025-12-05 01:21:20','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1570,'2025-11-25',1,13,11,1,NULL,2.00,'2025-12-05 01:21:59','2025-12-05 01:21:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1571,'2025-11-25',1,3,3,1,NULL,6.00,'2025-12-05 01:21:59','2025-12-05 01:21:59',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1572,'2025-11-25',9,3,3,1,NULL,4.00,'2025-12-05 01:22:49','2025-12-05 01:22:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1573,'2025-11-25',9,3,3,2,14,2.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1574,'2025-11-25',9,3,3,2,6,4.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1575,'2025-11-25',8,3,3,1,NULL,4.00,'2025-12-05 01:22:49','2025-12-05 01:22:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1576,'2025-11-25',8,3,3,2,14,2.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1577,'2025-11-25',8,3,3,2,6,4.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1578,'2025-11-25',5,3,3,1,NULL,4.00,'2025-12-05 01:22:49','2025-12-05 01:22:49',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1579,'2025-11-25',5,3,3,2,14,2.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1580,'2025-11-25',5,3,3,2,6,4.00,'2025-12-05 01:22:49','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1581,'2025-11-26',9,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1582,'2025-11-26',9,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1583,'2025-11-26',8,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1584,'2025-11-26',8,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1585,'2025-11-26',6,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1586,'2025-11-26',6,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1587,'2025-11-26',5,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1588,'2025-11-26',5,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1589,'2025-11-26',3,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1590,'2025-11-26',3,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1591,'2025-11-26',1,3,3,1,NULL,4.00,'2025-12-05 01:23:32','2025-12-05 01:23:32',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1592,'2025-11-26',1,3,3,2,1,4.00,'2025-12-05 01:23:32','2026-02-05 22:24:28',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1593,'2025-11-27',1,3,3,1,NULL,8.00,'2025-12-05 01:24:00','2025-12-05 01:24:00',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1594,'2025-11-27',8,3,3,1,NULL,10.00,'2025-12-05 01:24:26','2025-12-05 01:24:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1595,'2025-11-27',6,3,3,1,NULL,10.00,'2025-12-05 01:24:26','2025-12-05 01:24:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1596,'2025-11-27',5,3,3,1,NULL,10.00,'2025-12-05 01:24:26','2025-12-05 01:24:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1597,'2025-11-27',3,3,3,1,NULL,10.00,'2025-12-05 01:24:26','2025-12-05 01:24:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1598,'2025-11-28',4,13,11,1,NULL,8.00,'2025-12-05 01:24:50','2025-12-05 01:24:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1599,'2025-11-28',6,13,11,1,NULL,8.00,'2025-12-05 01:24:50','2025-12-05 01:24:50',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1600,'2025-11-28',8,3,3,1,NULL,8.00,'2025-12-05 01:25:17','2025-12-05 01:25:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1601,'2025-11-28',5,3,3,1,NULL,8.00,'2025-12-05 01:25:17','2025-12-05 01:25:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1602,'2025-11-28',3,3,3,1,NULL,8.00,'2025-12-05 01:25:17','2025-12-05 01:25:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1603,'2025-11-28',1,3,3,1,NULL,8.00,'2025-12-05 01:25:17','2025-12-05 01:25:17',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1604,'2025-11-05',5,3,3,1,NULL,8.00,'2025-12-05 01:26:26','2025-12-05 01:26:26',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1605,'2025-11-13',2,13,1,1,NULL,4.00,'2025-12-05 01:28:08','2025-12-05 01:28:08',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1606,'2025-11-17',7,13,1,1,NULL,8.00,'2025-12-05 01:28:40','2025-12-05 01:28:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1607,'2025-11-17',4,11,3,1,NULL,6.00,'2025-12-05 01:30:38','2025-12-05 01:30:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1608,'2025-11-17',4,13,11,1,NULL,2.00,'2025-12-05 01:30:38','2025-12-05 01:30:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1609,'2025-11-21',10,13,1,1,NULL,8.00,'2025-12-05 01:31:07','2025-12-05 01:31:07',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1610,'2025-11-24',10,13,1,1,NULL,8.00,'2025-12-05 01:31:34','2025-12-05 01:31:34',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1611,'2025-11-24',3,13,1,1,NULL,8.00,'2025-12-05 01:31:40','2025-12-05 01:31:40',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1612,'2025-11-25',10,13,1,1,NULL,8.00,'2025-12-05 01:31:53','2025-12-05 01:31:53',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1613,'2025-12-05',10,11,3,1,NULL,8.00,'2025-12-05 06:53:42','2025-12-05 06:53:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1614,'2025-12-05',9,11,3,1,NULL,8.00,'2025-12-05 06:53:42','2025-12-05 06:53:42',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1615,'2025-12-05',4,11,3,1,NULL,8.00,'2025-12-05 06:53:43','2025-12-05 06:53:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1616,'2025-12-05',2,11,3,1,NULL,8.00,'2025-12-05 06:53:43','2025-12-05 06:53:43',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1617,'2025-12-06',10,11,3,1,NULL,8.00,'2025-12-06 05:46:14','2025-12-06 05:46:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1618,'2025-12-06',9,11,3,1,NULL,8.00,'2025-12-06 05:46:14','2025-12-06 05:46:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1619,'2025-12-06',4,11,3,1,NULL,8.00,'2025-12-06 05:46:14','2025-12-06 05:46:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1620,'2025-12-06',2,11,3,1,NULL,8.00,'2025-12-06 05:46:14','2025-12-06 05:46:14',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1621,'2025-12-08',1,11,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1622,'2025-12-08',1,3,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1623,'2025-12-08',5,11,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1624,'2025-12-08',5,3,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1625,'2025-12-08',3,11,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1626,'2025-12-08',3,3,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1627,'2025-12-08',10,11,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1628,'2025-12-08',10,3,3,1,NULL,4.00,'2025-12-09 07:33:48','2025-12-09 07:33:48',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1629,'2025-12-08',9,3,3,1,NULL,8.00,'2025-12-09 07:34:05','2025-12-09 07:34:05',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1630,'2025-12-08',8,3,3,1,NULL,8.00,'2025-12-09 07:34:05','2025-12-09 07:34:05',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1631,'2025-12-08',2,3,3,1,NULL,8.00,'2025-12-09 07:34:05','2025-12-09 07:34:05',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1632,'2025-12-08',4,3,3,1,NULL,8.00,'2025-12-09 07:34:06','2025-12-09 07:34:06',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1634,'2025-12-08',6,3,3,1,NULL,8.00,'2025-12-09 07:34:38','2025-12-09 07:34:38',3,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1635,'2025-12-10',4,3,3,1,NULL,8.00,'2025-12-10 06:56:21','2025-12-10 06:56:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1636,'2025-12-10',2,3,3,1,NULL,8.00,'2025-12-10 06:56:21','2025-12-10 06:56:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1637,'2025-12-10',8,3,3,1,NULL,8.00,'2025-12-10 06:56:21','2025-12-10 06:56:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1638,'2025-12-10',6,3,3,1,NULL,8.00,'2025-12-10 06:56:21','2025-12-10 06:56:21',5,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1642,'2026-01-02',10,13,21,1,NULL,8.00,'2026-02-04 22:47:59','2026-02-04 22:47:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1643,'2026-01-02',9,13,20,1,NULL,8.00,'2026-02-04 22:50:13','2026-02-04 22:50:13',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1644,'2026-01-05',11,15,3,1,42,8.00,'2026-02-04 22:52:41','2026-02-05 22:40:21',1,1,NULL,NULL,NULL,NULL,NULL,NULL,4.00), +(1645,'2026-01-06',11,15,3,1,NULL,8.00,'2026-02-04 22:53:13','2026-02-04 22:53:13',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1646,'2026-01-07',11,15,3,1,NULL,8.00,'2026-02-04 22:53:35','2026-02-04 22:53:35',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1647,'2026-01-08',11,15,3,1,NULL,8.00,'2026-02-04 22:54:03','2026-02-04 22:54:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1648,'2026-01-09',11,15,3,1,NULL,8.00,'2026-02-04 22:54:24','2026-02-04 22:54:24',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1649,'2026-01-12',11,15,3,1,NULL,8.00,'2026-02-04 22:55:52','2026-02-04 22:55:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1650,'2026-01-13',11,15,3,1,NULL,8.00,'2026-02-04 22:56:20','2026-02-04 22:56:20',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1651,'2026-01-14',11,15,3,1,NULL,8.00,'2026-02-04 22:56:50','2026-02-04 22:56:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1652,'2026-01-15',11,15,3,1,NULL,8.00,'2026-02-04 22:57:09','2026-02-04 22:57:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1653,'2026-01-16',11,15,3,1,NULL,8.00,'2026-02-04 22:57:29','2026-02-04 22:57:29',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1654,'2026-01-19',11,15,14,1,NULL,8.00,'2026-02-04 22:58:20','2026-02-04 22:58:20',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1655,'2026-01-20',11,15,14,1,NULL,8.00,'2026-02-04 22:58:49','2026-02-04 22:58:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1656,'2026-01-21',11,15,14,1,NULL,8.00,'2026-02-04 23:00:27','2026-02-04 23:00:27',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1657,'2026-01-22',11,15,3,1,NULL,8.00,'2026-02-04 23:00:50','2026-02-04 23:00:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1658,'2026-01-23',11,15,15,1,NULL,8.00,'2026-02-04 23:01:12','2026-02-04 23:01:12',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1659,'2026-01-26',11,15,15,1,NULL,8.00,'2026-02-04 23:01:35','2026-02-04 23:01:35',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1660,'2026-01-27',11,15,15,1,NULL,8.00,'2026-02-04 23:02:09','2026-02-04 23:02:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1661,'2026-01-29',11,15,15,1,NULL,8.00,'2026-02-04 23:02:29','2026-02-04 23:02:29',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1662,'2026-01-28',11,15,15,1,NULL,8.00,'2026-02-04 23:02:58','2026-02-04 23:02:58',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1663,'2026-01-30',11,15,15,1,NULL,8.00,'2026-02-04 23:03:16','2026-02-04 23:03:16',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1664,'2026-01-02',6,13,21,1,NULL,8.00,'2026-02-04 23:03:55','2026-02-04 23:03:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1665,'2026-01-05',6,15,16,1,NULL,8.00,'2026-02-04 23:04:43','2026-02-04 23:04:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1666,'2026-01-06',6,15,16,1,NULL,8.00,'2026-02-04 23:05:15','2026-02-04 23:05:15',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1667,'2026-01-07',6,15,16,1,NULL,8.00,'2026-02-04 23:05:59','2026-02-04 23:05:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1668,'2026-01-08',6,15,16,1,NULL,8.00,'2026-02-04 23:06:37','2026-02-04 23:06:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1669,'2026-01-09',6,15,16,1,NULL,8.00,'2026-02-04 23:06:56','2026-02-04 23:06:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1670,'2026-01-12',6,17,8,1,NULL,8.00,'2026-02-04 23:07:38','2026-02-04 23:07:38',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1671,'2026-01-13',6,17,8,1,NULL,8.00,'2026-02-04 23:08:01','2026-02-04 23:08:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1672,'2026-01-14',6,17,8,1,NULL,8.00,'2026-02-04 23:08:22','2026-02-04 23:08:22',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1673,'2026-01-15',6,17,8,1,NULL,8.00,'2026-02-04 23:08:56','2026-02-04 23:08:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1674,'2026-01-16',6,15,8,1,NULL,2.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1675,'2026-01-16',6,13,24,1,NULL,6.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1676,'2026-01-19',6,17,8,2,43,2.00,'2026-02-04 23:22:54','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,2.00), +(1677,'2026-01-19',6,17,10,1,NULL,6.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1678,'2026-01-20',6,17,10,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1679,'2026-01-21',6,17,8,2,44,8.00,'2026-02-04 23:22:54','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1680,'2026-01-22',6,17,10,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1681,'2026-01-23',6,17,10,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1682,'2026-01-26',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1683,'2026-01-27',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1684,'2026-01-28',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1685,'2026-01-29',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1686,'2026-01-30',6,15,15,1,NULL,8.00,'2026-02-04 23:22:54','2026-02-04 23:22:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1687,'2026-01-02',3,13,21,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1688,'2026-01-05',3,13,21,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1689,'2026-01-06',3,15,2,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1690,'2026-01-07',3,15,2,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1691,'2026-01-08',3,15,2,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1692,'2026-01-09',3,15,2,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1693,'2026-01-12',3,15,16,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1694,'2026-01-13',3,15,16,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1695,'2026-01-14',3,15,16,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1696,'2026-01-15',3,15,16,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1697,'2026-01-16',3,15,16,1,NULL,6.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1698,'2026-01-16',3,13,23,1,NULL,2.00,'2026-02-04 23:34:05','2026-02-05 02:05:51',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1699,'2026-01-19',3,17,10,1,NULL,8.00,'2026-02-04 23:34:05','2026-02-04 23:34:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1700,'2026-01-20',3,17,10,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1701,'2026-01-21',3,17,10,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1702,'2026-01-22',3,17,10,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1703,'2026-01-23',3,17,10,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1704,'2026-01-26',3,15,17,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1705,'2026-01-27',3,15,17,1,NULL,8.00,'2026-02-04 23:36:37','2026-02-04 23:36:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1706,'2026-01-28',3,15,17,2,15,8.00,'2026-02-04 23:36:37','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,4.00), +(1707,'2026-01-29',3,15,17,2,15,8.00,'2026-02-04 23:36:37','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1708,'2026-01-30',3,15,17,2,15,8.00,'2026-02-04 23:36:37','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1709,'2026-01-05',10,15,2,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1710,'2026-01-06',10,15,2,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1711,'2026-01-07',10,15,2,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1712,'2026-01-08',10,15,2,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1713,'2026-01-09',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1714,'2026-01-12',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1715,'2026-01-13',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1716,'2026-01-14',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1717,'2026-01-15',10,15,3,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1718,'2026-01-16',10,17,8,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1719,'2026-01-19',10,17,8,2,43,8.00,'2026-02-04 23:44:26','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1720,'2026-01-20',10,17,10,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1721,'2026-01-21',10,17,10,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1722,'2026-01-22',10,17,10,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1723,'2026-01-22',10,17,10,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1724,'2026-01-23',10,13,21,1,NULL,8.00,'2026-02-04 23:44:26','2026-02-04 23:44:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1725,'2026-01-26',10,16,25,1,NULL,8.00,'2026-02-04 23:47:27','2026-02-04 23:47:27',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1726,'2026-01-27',10,16,25,1,NULL,8.00,'2026-02-04 23:47:27','2026-02-04 23:47:27',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1727,'2026-01-28',10,16,25,1,NULL,8.00,'2026-02-04 23:50:51','2026-02-04 23:50:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1728,'2026-01-29',10,16,25,1,NULL,8.00,'2026-02-04 23:50:51','2026-02-04 23:50:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1729,'2026-01-30',10,16,25,1,NULL,8.00,'2026-02-04 23:50:51','2026-02-04 23:50:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1730,'2026-01-05',9,13,20,1,NULL,8.00,'2026-02-04 23:54:55','2026-02-04 23:54:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1731,'2026-01-06',9,13,20,1,NULL,8.00,'2026-02-04 23:54:56','2026-02-04 23:54:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1732,'2026-01-07',9,13,20,1,NULL,8.00,'2026-02-04 23:54:57','2026-02-04 23:54:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1733,'2026-01-08',9,13,20,1,NULL,8.00,'2026-02-04 23:54:58','2026-02-04 23:54:58',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1734,'2026-01-09',9,13,20,1,NULL,8.00,'2026-02-04 23:54:59','2026-02-04 23:54:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1735,'2026-01-12',9,13,20,1,NULL,8.00,'2026-02-04 23:55:00','2026-02-04 23:55:00',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1736,'2026-01-13',9,13,20,1,NULL,8.00,'2026-02-04 23:55:01','2026-02-04 23:55:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1737,'2026-01-14',9,13,20,1,NULL,8.00,'2026-02-04 23:55:02','2026-02-04 23:55:02',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1738,'2026-01-15',9,13,20,1,NULL,8.00,'2026-02-04 23:55:03','2026-02-04 23:55:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1739,'2026-01-16',9,13,20,1,NULL,8.00,'2026-02-04 23:55:04','2026-02-04 23:55:04',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1740,'2026-01-19',9,13,20,1,NULL,8.00,'2026-02-04 23:55:05','2026-02-04 23:55:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1741,'2026-01-20',9,15,15,1,NULL,8.00,'2026-02-04 23:56:33','2026-02-04 23:56:33',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1742,'2026-01-21',9,15,15,1,NULL,8.00,'2026-02-04 23:56:34','2026-02-04 23:56:34',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1743,'2026-01-22',9,15,15,1,NULL,8.00,'2026-02-04 23:56:35','2026-02-04 23:56:35',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1744,'2026-01-23',9,15,15,1,NULL,8.00,'2026-02-04 23:56:36','2026-02-04 23:56:36',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1745,'2026-01-26',9,16,25,1,NULL,8.00,'2026-02-04 23:59:49','2026-02-04 23:59:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1746,'2026-01-27',9,16,25,1,NULL,8.00,'2026-02-04 23:59:50','2026-02-04 23:59:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1747,'2026-01-28',9,16,25,1,NULL,8.00,'2026-02-04 23:59:51','2026-02-04 23:59:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1748,'2026-01-29',9,16,25,1,NULL,8.00,'2026-02-04 23:59:52','2026-02-04 23:59:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1749,'2026-01-30',9,16,25,1,NULL,8.00,'2026-02-04 23:59:53','2026-02-04 23:59:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1750,'2026-01-02',1,13,21,1,NULL,8.00,'2026-02-05 00:26:36','2026-02-05 00:26:36',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1751,'2026-01-05',1,15,2,1,NULL,8.00,'2026-02-05 00:26:37','2026-02-05 00:26:37',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1752,'2026-01-06',1,15,2,1,NULL,8.00,'2026-02-05 00:26:38','2026-02-05 00:26:38',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1753,'2026-01-07',1,15,2,1,NULL,6.00,'2026-02-05 00:26:39','2026-02-05 00:26:39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1754,'2026-01-07',1,13,23,1,NULL,2.00,'2026-02-05 00:26:40','2026-02-05 00:26:40',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1755,'2026-01-08',1,15,2,1,NULL,8.00,'2026-02-05 00:26:41','2026-02-05 00:26:41',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1756,'2026-01-09',1,15,2,1,NULL,8.00,'2026-02-05 00:26:42','2026-02-05 00:26:42',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1757,'2026-01-12',1,15,2,1,NULL,8.00,'2026-02-05 00:26:43','2026-02-05 00:26:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1758,'2026-01-13',1,15,2,1,NULL,8.00,'2026-02-05 00:26:44','2026-02-05 00:26:44',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1759,'2026-01-14',1,15,2,1,NULL,8.00,'2026-02-05 00:26:45','2026-02-05 00:26:45',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1760,'2026-01-15',1,16,25,1,NULL,8.00,'2026-02-05 00:26:46','2026-02-05 00:26:46',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1761,'2026-01-16',1,16,25,1,NULL,8.00,'2026-02-05 00:26:47','2026-02-05 00:26:47',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1762,'2026-01-19',1,13,21,1,NULL,8.00,'2026-02-05 00:26:48','2026-02-05 00:26:48',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1763,'2026-01-20',1,17,10,1,NULL,8.00,'2026-02-05 00:26:49','2026-02-05 00:26:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1764,'2026-01-21',1,17,10,1,NULL,8.00,'2026-02-05 00:26:50','2026-02-05 00:26:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1765,'2026-01-22',1,15,17,1,NULL,8.00,'2026-02-05 00:26:51','2026-02-05 00:26:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1766,'2026-01-23',1,15,17,1,NULL,8.00,'2026-02-05 00:26:52','2026-02-05 00:26:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1767,'2026-01-26',1,16,25,1,NULL,8.00,'2026-02-05 00:26:53','2026-02-05 00:26:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1768,'2026-01-27',1,16,25,1,NULL,8.00,'2026-02-05 00:26:54','2026-02-05 00:26:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1769,'2026-01-28',1,16,25,1,NULL,8.00,'2026-02-05 00:26:55','2026-02-05 00:26:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1770,'2026-01-29',1,16,25,1,NULL,8.00,'2026-02-05 00:26:56','2026-02-05 00:26:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1771,'2026-01-30',1,16,25,1,NULL,8.00,'2026-02-05 00:26:57','2026-02-05 00:26:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1772,'2026-01-02',2,13,21,1,NULL,8.00,'2026-02-05 00:36:41','2026-02-05 00:36:41',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1773,'2026-01-05',2,15,2,1,NULL,8.00,'2026-02-05 00:36:42','2026-02-05 00:36:42',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1774,'2026-01-06',2,15,2,1,NULL,8.00,'2026-02-05 00:36:43','2026-02-05 00:36:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1775,'2026-01-07',2,15,2,1,NULL,8.00,'2026-02-05 00:36:44','2026-02-05 00:36:44',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1776,'2026-01-08',2,14,19,1,NULL,8.00,'2026-02-05 00:36:45','2026-02-05 00:36:45',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1777,'2026-01-09',2,14,19,1,NULL,8.00,'2026-02-05 00:36:46','2026-02-05 00:36:46',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1778,'2026-01-12',2,14,19,1,NULL,8.00,'2026-02-05 00:36:47','2026-02-05 00:36:47',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1779,'2026-01-13',2,14,19,1,NULL,4.00,'2026-02-05 00:36:48','2026-02-05 00:36:48',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1780,'2026-01-13',2,13,22,1,NULL,4.00,'2026-02-05 00:36:49','2026-02-05 00:36:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1781,'2026-01-14',2,15,16,1,NULL,8.00,'2026-02-05 00:36:50','2026-02-05 00:36:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1782,'2026-01-15',2,15,16,1,NULL,8.00,'2026-02-05 00:36:51','2026-02-05 00:36:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1783,'2026-01-16',2,15,16,1,NULL,8.00,'2026-02-05 00:36:52','2026-02-05 00:36:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1784,'2026-01-19',2,15,16,1,NULL,8.00,'2026-02-05 00:36:53','2026-02-05 00:46:20',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1785,'2026-01-20',2,15,14,1,NULL,8.00,'2026-02-05 00:36:54','2026-02-05 00:36:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1786,'2026-01-21',2,15,14,1,NULL,4.00,'2026-02-05 00:36:55','2026-02-05 00:46:43',1,1,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1787,'2026-01-22',2,15,14,1,NULL,8.00,'2026-02-05 00:36:56','2026-02-05 00:36:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1788,'2026-01-23',2,15,14,1,NULL,8.00,'2026-02-05 00:36:57','2026-02-05 00:36:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1789,'2026-01-26',2,15,14,1,NULL,8.00,'2026-02-05 00:36:58','2026-02-05 00:36:58',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1790,'2026-01-27',2,15,17,1,NULL,8.00,'2026-02-05 00:36:59','2026-02-05 00:36:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1791,'2026-01-28',2,15,17,1,NULL,8.00,'2026-02-05 00:37:00','2026-02-05 00:37:00',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1792,'2026-01-29',2,15,17,2,15,8.00,'2026-02-05 00:37:01','2026-02-05 22:40:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1793,'2026-01-30',2,13,21,1,15,8.00,'2026-02-05 00:37:02','2026-02-05 22:40:21',1,1,NULL,NULL,NULL,NULL,NULL,NULL,8.00), +(1794,'2026-01-21',2,13,22,1,NULL,4.00,'2026-02-05 00:47:10','2026-02-05 00:47:10',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1795,'2026-01-02',4,13,21,1,NULL,8.00,'2026-02-05 00:53:38','2026-02-05 00:53:38',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1796,'2026-01-05',4,15,1,1,NULL,8.00,'2026-02-05 00:53:39','2026-02-05 00:53:39',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1797,'2026-01-06',4,15,1,1,NULL,8.00,'2026-02-05 00:53:40','2026-02-05 00:53:40',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1798,'2026-01-07',4,15,1,1,NULL,8.00,'2026-02-05 00:53:41','2026-02-05 00:53:41',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1799,'2026-01-08',4,15,1,1,NULL,8.00,'2026-02-05 00:53:42','2026-02-05 00:53:42',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1800,'2026-01-09',4,15,2,1,NULL,8.00,'2026-02-05 00:53:43','2026-02-05 00:53:43',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1801,'2026-01-12',4,15,13,1,NULL,8.00,'2026-02-05 00:53:44','2026-02-05 00:53:44',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1802,'2026-01-13',4,15,13,1,NULL,8.00,'2026-02-05 00:53:45','2026-02-05 00:53:45',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1803,'2026-01-14',4,15,13,1,NULL,8.00,'2026-02-05 00:53:46','2026-02-05 00:53:46',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1804,'2026-01-15',4,15,13,1,NULL,8.00,'2026-02-05 00:53:47','2026-02-05 00:53:47',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1805,'2026-01-16',4,13,21,1,NULL,8.00,'2026-02-05 00:53:48','2026-02-05 00:53:48',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1806,'2026-01-19',4,14,19,1,NULL,8.00,'2026-02-05 00:53:49','2026-02-05 00:53:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1807,'2026-01-20',4,14,19,1,NULL,8.00,'2026-02-05 00:53:50','2026-02-05 00:53:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1808,'2026-01-21',4,14,19,1,NULL,8.00,'2026-02-05 00:53:51','2026-02-05 00:53:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1809,'2026-01-22',4,15,16,1,NULL,8.00,'2026-02-05 00:53:52','2026-02-05 00:53:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1810,'2026-01-23',4,15,16,1,NULL,8.00,'2026-02-05 00:53:53','2026-02-05 00:53:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1811,'2026-01-26',4,14,10,1,NULL,8.00,'2026-02-05 00:56:53','2026-02-05 00:56:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1812,'2026-01-27',4,14,10,1,NULL,8.00,'2026-02-05 00:56:54','2026-02-05 00:56:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1813,'2026-01-28',4,14,10,1,NULL,8.00,'2026-02-05 00:56:55','2026-02-05 00:56:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1814,'2026-01-29',4,14,10,1,NULL,8.00,'2026-02-05 00:56:56','2026-02-05 00:56:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1815,'2026-01-30',4,13,21,1,NULL,8.00,'2026-02-05 00:56:57','2026-02-05 00:56:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1816,'2026-01-02',5,13,21,1,NULL,8.00,'2026-02-05 01:05:46','2026-02-05 01:05:46',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1817,'2026-01-23',5,13,21,1,NULL,8.00,'2026-02-05 01:06:01','2026-02-05 01:06:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1818,'2026-01-05',5,15,1,1,NULL,8.00,'2026-02-05 01:07:09','2026-02-05 01:07:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1819,'2026-01-06',5,15,1,1,NULL,8.00,'2026-02-05 01:07:11','2026-02-05 01:07:11',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1820,'2026-01-07',5,15,2,1,NULL,8.00,'2026-02-05 01:07:12','2026-02-05 01:07:12',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1821,'2026-01-08',5,15,2,1,NULL,8.00,'2026-02-05 01:07:13','2026-02-05 01:07:13',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1822,'2026-01-09',5,15,2,1,NULL,8.00,'2026-02-05 01:07:14','2026-02-05 01:07:14',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1823,'2026-01-12',5,17,26,1,NULL,8.00,'2026-02-05 01:07:15','2026-02-05 01:07:15',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1824,'2026-01-13',5,17,26,1,NULL,8.00,'2026-02-05 01:07:16','2026-02-05 01:07:16',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1825,'2026-01-14',5,17,26,1,NULL,8.00,'2026-02-05 01:07:17','2026-02-05 01:07:17',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1826,'2026-01-15',5,17,26,1,NULL,8.00,'2026-02-05 01:07:18','2026-02-05 01:07:18',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1827,'2026-01-16',5,17,26,1,NULL,8.00,'2026-02-05 01:07:19','2026-02-05 01:07:19',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1828,'2026-01-19',5,15,16,1,NULL,8.00,'2026-02-05 01:07:20','2026-02-05 01:07:20',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1829,'2026-01-20',5,15,16,1,NULL,8.00,'2026-02-05 01:07:21','2026-02-05 01:07:21',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1830,'2026-01-21',5,15,16,1,NULL,8.00,'2026-02-05 01:07:22','2026-02-05 01:07:22',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1831,'2026-01-22',5,15,16,1,NULL,8.00,'2026-02-05 01:07:23','2026-02-05 01:07:23',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1832,'2026-01-26',5,16,25,1,NULL,8.00,'2026-02-05 01:07:24','2026-02-05 01:07:24',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1833,'2026-01-27',5,16,25,1,NULL,8.00,'2026-02-05 01:07:25','2026-02-05 01:07:25',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1834,'2026-01-28',5,16,25,1,NULL,8.00,'2026-02-05 01:07:26','2026-02-05 01:07:26',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1835,'2026-01-29',5,16,25,1,NULL,8.00,'2026-02-05 01:07:27','2026-02-05 01:07:27',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1836,'2026-01-30',5,16,25,1,NULL,8.00,'2026-02-05 01:07:28','2026-02-05 01:07:28',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1837,'2026-01-02',8,13,21,1,NULL,8.00,'2026-02-05 01:14:48','2026-02-05 01:14:48',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1838,'2026-01-05',8,15,3,1,NULL,8.00,'2026-02-05 01:14:49','2026-02-05 01:14:49',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1839,'2026-01-06',8,15,3,1,NULL,8.00,'2026-02-05 01:14:50','2026-02-05 01:14:50',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1840,'2026-01-07',8,15,3,1,NULL,8.00,'2026-02-05 01:14:51','2026-02-05 01:14:51',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1841,'2026-01-08',8,15,3,1,NULL,8.00,'2026-02-05 01:14:52','2026-02-05 01:14:52',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1842,'2026-01-09',8,15,3,1,NULL,8.00,'2026-02-05 01:14:53','2026-02-05 01:14:53',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1843,'2026-01-12',8,15,4,1,NULL,8.00,'2026-02-05 01:14:54','2026-02-05 01:14:54',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1844,'2026-01-13',8,15,4,1,NULL,8.00,'2026-02-05 01:14:55','2026-02-05 01:14:55',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1845,'2026-01-14',8,15,4,1,NULL,8.00,'2026-02-05 01:14:56','2026-02-05 01:14:56',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1846,'2026-01-15',8,15,4,1,NULL,8.00,'2026-02-05 01:14:57','2026-02-05 01:14:57',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1847,'2026-01-16',8,15,4,1,NULL,8.00,'2026-02-05 01:14:58','2026-02-05 01:14:58',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1848,'2026-01-19',8,15,4,1,NULL,8.00,'2026-02-05 01:14:59','2026-02-05 01:14:59',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1849,'2026-01-20',8,15,4,1,NULL,8.00,'2026-02-05 01:15:00','2026-02-05 01:15:00',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1850,'2026-01-21',8,14,10,1,NULL,8.00,'2026-02-05 01:15:01','2026-02-05 01:15:01',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1851,'2026-01-22',8,14,10,1,NULL,8.00,'2026-02-05 01:15:02','2026-02-05 01:15:02',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1852,'2026-01-23',8,14,10,1,NULL,8.00,'2026-02-05 01:15:03','2026-02-05 01:15:03',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1853,'2026-01-26',8,15,14,1,NULL,8.00,'2026-02-05 01:15:04','2026-02-05 01:15:04',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1854,'2026-01-27',8,15,14,1,NULL,8.00,'2026-02-05 01:15:05','2026-02-05 01:15:05',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1855,'2026-01-28',8,15,14,1,NULL,8.00,'2026-02-05 01:15:06','2026-02-05 01:15:06',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1856,'2026-01-29',8,15,14,1,NULL,8.00,'2026-02-05 01:15:07','2026-02-05 01:15:07',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL), +(1857,'2026-01-30',8,15,14,1,NULL,8.00,'2026-02-05 01:15:09','2026-02-05 01:15:09',1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL); +/*!40000 ALTER TABLE `daily_work_reports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `daily_worker_summary` +-- + +DROP TABLE IF EXISTS `daily_worker_summary`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `daily_worker_summary` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `report_date` date NOT NULL, + `worker_id` int(11) NOT NULL, + `total_hours` decimal(4,2) NOT NULL DEFAULT 8.00 COMMENT '총 근무시간', + `work_status` enum('normal','annual_leave','half_leave','overtime') DEFAULT 'normal' COMMENT '근무 상태', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `unique_worker_date` (`worker_id`,`report_date`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `daily_worker_summary` +-- + +LOCK TABLES `daily_worker_summary` WRITE; +/*!40000 ALTER TABLE `daily_worker_summary` DISABLE KEYS */; +/*!40000 ALTER TABLE `daily_worker_summary` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `departments` +-- + +DROP TABLE IF EXISTS `departments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `departments` ( + `department_id` int(11) NOT NULL AUTO_INCREMENT, + `department_name` varchar(100) NOT NULL, + `parent_id` int(11) DEFAULT NULL, + `description` text DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `display_order` int(11) DEFAULT 0, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`department_id`), + KEY `parent_id` (`parent_id`), + CONSTRAINT `departments_ibfk_1` FOREIGN KEY (`parent_id`) REFERENCES `departments` (`department_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `departments` +-- + +LOCK TABLES `departments` WRITE; +/*!40000 ALTER TABLE `departments` DISABLE KEYS */; +INSERT INTO `departments` VALUES +(1,'생산팀',NULL,'현장 생산 작업 담당',1,1,'2026-02-03 05:03:37','2026-02-03 05:03:37'); +/*!40000 ALTER TABLE `departments` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `equipment_external_logs` +-- + +DROP TABLE IF EXISTS `equipment_external_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `equipment_external_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `equipment_id` int(10) unsigned NOT NULL COMMENT '설비 ID', + `log_type` enum('export','return') NOT NULL COMMENT '반출/반입', + `export_date` date DEFAULT NULL COMMENT '반출일', + `expected_return_date` date DEFAULT NULL COMMENT '반입 예정일', + `actual_return_date` date DEFAULT NULL COMMENT '실제 반입일', + `destination` varchar(200) DEFAULT NULL COMMENT '반출처 (수리업체명 등)', + `reason` text DEFAULT NULL COMMENT '반출 사유', + `notes` text DEFAULT NULL COMMENT '비고', + `exported_by` int(11) DEFAULT NULL COMMENT '반출 담당자', + `returned_by` int(11) DEFAULT NULL COMMENT '반입 담당자', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`log_id`), + KEY `fk_eel_exported_by` (`exported_by`), + KEY `fk_eel_returned_by` (`returned_by`), + KEY `idx_eel_equipment_id` (`equipment_id`), + KEY `idx_eel_log_type` (`log_type`), + KEY `idx_eel_export_date` (`export_date`), + CONSTRAINT `fk_eel_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipments` (`equipment_id`) ON DELETE CASCADE, + CONSTRAINT `fk_eel_exported_by` FOREIGN KEY (`exported_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, + CONSTRAINT `fk_eel_returned_by` FOREIGN KEY (`returned_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `equipment_external_logs` +-- + +LOCK TABLES `equipment_external_logs` WRITE; +/*!40000 ALTER TABLE `equipment_external_logs` DISABLE KEYS */; +/*!40000 ALTER TABLE `equipment_external_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `equipment_move_logs` +-- + +DROP TABLE IF EXISTS `equipment_move_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `equipment_move_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `equipment_id` int(10) unsigned NOT NULL COMMENT '설비 ID', + `move_type` enum('temporary','return') NOT NULL COMMENT '임시이동/복귀', + `from_workplace_id` int(10) unsigned DEFAULT NULL COMMENT '이전 작업장', + `to_workplace_id` int(10) unsigned DEFAULT NULL COMMENT '이동 작업장', + `from_x_percent` decimal(5,2) DEFAULT NULL COMMENT '이전 X좌표', + `from_y_percent` decimal(5,2) DEFAULT NULL COMMENT '이전 Y좌표', + `to_x_percent` decimal(5,2) DEFAULT NULL COMMENT '이동 X좌표', + `to_y_percent` decimal(5,2) DEFAULT NULL COMMENT '이동 Y좌표', + `reason` text DEFAULT NULL COMMENT '이동 사유', + `moved_by` int(11) DEFAULT NULL COMMENT '이동 처리자', + `moved_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`log_id`), + KEY `fk_eml_from_workplace` (`from_workplace_id`), + KEY `fk_eml_to_workplace` (`to_workplace_id`), + KEY `fk_eml_moved_by` (`moved_by`), + KEY `idx_eml_equipment_id` (`equipment_id`), + KEY `idx_eml_move_type` (`move_type`), + CONSTRAINT `fk_eml_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipments` (`equipment_id`) ON DELETE CASCADE, + CONSTRAINT `fk_eml_from_workplace` FOREIGN KEY (`from_workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL, + CONSTRAINT `fk_eml_moved_by` FOREIGN KEY (`moved_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, + CONSTRAINT `fk_eml_to_workplace` FOREIGN KEY (`to_workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `equipment_move_logs` +-- + +LOCK TABLES `equipment_move_logs` WRITE; +/*!40000 ALTER TABLE `equipment_move_logs` DISABLE KEYS */; +INSERT INTO `equipment_move_logs` VALUES +(1,68,'temporary',2,10,7.82,8.53,NULL,NULL,NULL,1,'2026-02-04 04:34:45'), +(2,68,'temporary',2,10,7.82,8.53,NULL,NULL,NULL,1,'2026-02-04 04:44:36'); +/*!40000 ALTER TABLE `equipment_move_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `equipment_photos` +-- + +DROP TABLE IF EXISTS `equipment_photos`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `equipment_photos` ( + `photo_id` int(11) NOT NULL AUTO_INCREMENT, + `equipment_id` int(10) unsigned NOT NULL, + `photo_path` varchar(255) NOT NULL COMMENT '이미지 경로', + `description` varchar(200) DEFAULT NULL COMMENT '사진 설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `uploaded_by` int(11) DEFAULT NULL COMMENT '업로드한 사용자 ID', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`photo_id`), + KEY `fk_eq_photos_user` (`uploaded_by`), + KEY `idx_eq_photos_equipment_id` (`equipment_id`), + CONSTRAINT `fk_eq_photos_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipments` (`equipment_id`) ON DELETE CASCADE, + CONSTRAINT `fk_eq_photos_user` FOREIGN KEY (`uploaded_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `equipment_photos` +-- + +LOCK TABLES `equipment_photos` WRITE; +/*!40000 ALTER TABLE `equipment_photos` DISABLE KEYS */; +/*!40000 ALTER TABLE `equipment_photos` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `equipments` +-- + +DROP TABLE IF EXISTS `equipments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `equipments` ( + `equipment_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '설비 ID', + `equipment_code` varchar(50) NOT NULL COMMENT '설비 코드 (예: CNC-01, LATHE-A)', + `equipment_name` varchar(100) NOT NULL COMMENT '설비명', + `equipment_type` varchar(50) DEFAULT NULL COMMENT '설비 유형 (예: CNC, 선반, 밀링 등)', + `model_name` varchar(100) DEFAULT NULL COMMENT '모델명', + `manufacturer` varchar(100) DEFAULT NULL COMMENT '제조사', + `supplier` varchar(100) DEFAULT NULL COMMENT '구입처', + `purchase_price` decimal(15,0) DEFAULT NULL COMMENT '구입가격', + `installation_date` date DEFAULT NULL COMMENT '설치일', + `serial_number` varchar(100) DEFAULT NULL COMMENT '시리얼 번호', + `specifications` text DEFAULT NULL COMMENT '사양 정보 (JSON 형태로 저장 가능)', + `status` enum('active','maintenance','repair_needed','inactive','external','repair_external') DEFAULT 'active' COMMENT '설비 상태', + `notes` text DEFAULT NULL COMMENT '비고', + `workplace_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 작업장 ID', + `map_x_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 X 위치 (%)', + `map_y_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 Y 위치 (%)', + `map_width_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 영역 너비 (%)', + `map_height_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 영역 높이 (%)', + `current_workplace_id` int(10) unsigned DEFAULT NULL COMMENT '현재 임시 위치 - 작업장 ID', + `current_map_x_percent` decimal(5,2) DEFAULT NULL COMMENT '현재 위치 X%', + `current_map_y_percent` decimal(5,2) DEFAULT NULL COMMENT '현재 위치 Y%', + `current_map_width_percent` decimal(5,2) DEFAULT NULL COMMENT '현재 위치 너비%', + `current_map_height_percent` decimal(5,2) DEFAULT NULL COMMENT '현재 위치 높이%', + `is_temporarily_moved` tinyint(1) DEFAULT 0 COMMENT '임시 이동 상태', + `moved_at` datetime DEFAULT NULL COMMENT '이동 일시', + `moved_by` int(11) DEFAULT NULL COMMENT '이동 처리자', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '생성일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정일시', + PRIMARY KEY (`equipment_id`), + UNIQUE KEY `equipments_equipment_code_unique` (`equipment_code`), + KEY `equipments_workplace_id_index` (`workplace_id`), + KEY `equipments_equipment_type_index` (`equipment_type`), + KEY `equipments_status_index` (`status`), + KEY `fk_eq_current_workplace` (`current_workplace_id`), + CONSTRAINT `equipments_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL, + CONSTRAINT `fk_eq_current_workplace` FOREIGN KEY (`current_workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=69 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `equipments` +-- + +LOCK TABLES `equipments` WRITE; +/*!40000 ALTER TABLE `equipments` DISABLE KEYS */; +INSERT INTO `equipments` VALUES +(1,'TKP-001','AIR COMPRESSOR',NULL,'AR10E','경원','지티씨',NULL,'2016-06-01','K603023Y','7.5KW(10HP)','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(2,'TKP-002','TURN TABLE',NULL,'YCT-200T','유체기계','형진종합공구',3600000,'2016-05-30',NULL,'220V','active',NULL,2,9.93,79.22,3.41,7.29,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:57:25'), +(3,'TKP-003','BAND SAW(中)',NULL,'CY300W','유림싸이겐','형진종합공구',4800000,'2016-05-30','20150943','1500W*380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(4,'TKP-004','BAND SAW(小)',NULL,'XB-180WA','렉스','형진종합공구',2700000,'2016-05-30',NULL,'180(VICE)','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(5,'TKP-005','BAND SAW(小)',NULL,'XB-180WA','렉스',NULL,NULL,'2019-05-30',NULL,'180(VICE)','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(6,'TKP-006','TIG용접기',NULL,'DAESUNG-500DT','대성용접기','형진종합공구',2200000,'2016-05-30','TEAG0168-001','500A','active',NULL,2,0.35,42.33,3.90,3.88,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-04 00:23:29'), +(7,'TKP-007','TIG용접기',NULL,'DAESUNG-500DT','대성용접기','형진종합공구',2200000,'2016-05-30','TEAG0168-002','500A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(8,'TKP-008','TIG용접기',NULL,'DAESUNG-500DT','대성용접기','형진종합공구',2200000,'2016-05-30','TEAG0168-003','500A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(9,'TKP-009','CO2용접기',NULL,'COD-500A','대성용접기','형진종합공구',2000000,'2016-05-30','10880','500A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(10,'TKP-010','O2용접기',NULL,'GSORK','재현오토닉스','형진종합공구',620000,'2016-05-30',NULL,'220V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(11,'TKP-011','PIPE BEVELLING MACHINE',NULL,'S-200LT_MT(테이블포함)','DCS ENG','DCS ENG',12000000,'2017-03-29','KR-17030007','2\" ~ 8\"','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(12,'TKP-012','CO2용접기',NULL,'500MX','현대용접기','현대용접기',1800000,'2017-08-02',NULL,'220/380V,500A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(13,'TKP-013','프라즈마',NULL,'Perfect-150AP','퍼펙트대대','현대용접기',1900000,'2017-08-02',NULL,'220/380/440V,140A','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(14,'TKP-014','터닝로라',NULL,'JK-5-TR','정일기공','정일기공',5700000,'2017-09-08',NULL,'5TON/380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(15,'TKP-015','터닝로라',NULL,'JK-5-TR','정일기공','정일기공',5700000,'2017-09-08',NULL,'5TON/380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(16,'TKP-016','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1600000,'2017-10-18','TJAD017B-005','500A/350A','active',NULL,2,0.02,46.36,4.87,4.34,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-04 00:22:53'), +(17,'TKP-017','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1600000,'2017-10-18','TJAD017B-006','500A/350A','active',NULL,2,0.35,20.93,4.06,4.03,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-04 00:23:46'), +(18,'TKP-018','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1600000,'2017-10-18','TJAD017B-007','500A/350A','repair_needed',NULL,2,0.35,17.05,4.06,3.57,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-04 05:35:54'), +(19,'TKP-019','전해연마기',NULL,'ONB-8000VP','메탈브라이트(오토기전)','오토기전',1450000,'2018-03-13','8022701','220V/MAX1200W','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(20,'TKP-020','지게차',NULL,'50DA-9F','현대지게차','현대지게차',45000000,'2018-05-10','HHKHFV36JJ0000061','5000KGS','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(21,'TKP-021','조방',NULL,NULL,'테크니컬코리아','천우기계공업/삼덕금속',14200000,'2018-05-11',NULL,'3658*12190','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(22,'TKP-022','BAND SAW(大)',NULL,'WBS-RC500AN','원공사','원공사',36000000,'2018-05-31','BC50A18-005F001','3,300kgs / 7.88kw','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(23,'TKP-023','AIR COMPRESSOR',NULL,'AR20E','경원기계','경원기계',NULL,'2018-06-05','AR020FE358','0.95Mpa','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(24,'TKP-024','TURN TABLE',NULL,'YCT-200TA','유체기계','청운종합공구',3245000,'2018-06-12',NULL,'220V','active',NULL,2,9.76,69.92,4.06,7.60,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:57:40'), +(25,'TKP-025','TIG용접기',NULL,'Perfect-500WT','퍼펙트대대','현대용접기',2400000,'2018-06-12','ADKAC017B-006','500A/AC DC','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(26,'TKP-026','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1900000,'2018-06-12','TAAI018B-002','500A/DC','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(27,'TKP-027','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1900000,'2018-06-12','TAAA018B-009','500A/DC','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(28,'TKP-028','TIG용접기',NULL,'Perfect-500PT','퍼펙트대대','현대용접기',1900000,'2018-06-12','TAAA018B-001','500A/DC','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(29,'TKP-029','ELECTRIC CHAIN HOIST',NULL,'DSM-2S','대산','청운종합공구',2300000,'2018-07-06','K1806077','3Ph-60Hz-380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(30,'TKP-030','ELECTRIC CHAIN HOIST',NULL,'DSM-2S','대산','청운종합공구',2300000,'2018-07-10','K1807028','3Ph-60Hz-380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(31,'TKP-031','ELECTRIC CHAIN HOIST',NULL,'DSM-2S','대산','청운종합공구',2300000,'2018-07-10','K1807029','3Ph-60Hz-380V','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(32,'TKP-032','만능탭 드릴링머신',NULL,'SF-TDM32','㈜애스앤에프','㈜애스앤애프',2927000,'2018-11-09',NULL,'1.5KW','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(33,'TKP-033','지게차',NULL,'30D-9B','현대지게차','현대지게차',29400000,'2019-03-06','HHKHHN51KK0000864','2850KGS','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(34,'TKP-034','갠츄리크레인',NULL,'CRANE - DHG','반도호이스트','유진산업기계',249000000,'2019-05-09',NULL,'50/10Ton x SP20M x T/L50M x H15M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(35,'TKP-035','OVER HEAD CRANE',NULL,'CRANE - DHO','반도호이스트','유진산업기계',58000000,'2019-05-09',NULL,'20Ton x SP24.0M x T/L67M x H11M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(36,'TKP-036','OVER HEAD CRANE',NULL,'CRANE - DHO','반도호이스트','유진산업기계',58000000,'2019-05-09',NULL,'20Ton x SP24.0M x T/L67M x H11M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(37,'TKP-037','OVER HEAD CRANE',NULL,'CRANE - DHO','반도호이스트','유진산업기계',29000000,'2019-05-09',NULL,'5Ton x SP24.0M x T/L67M x H11M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(38,'TKP-038','OVER HEAD CRANE',NULL,'CRANE - DHO','반도호이스트','유진산업기계',29000000,'2019-05-09',NULL,'5Ton x SP24.0M x T/L67M x H11M','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(39,'TKP-039','고소작업대',NULL,NULL,'㈜쓰리제이테크',NULL,NULL,'2019-01-01',NULL,'250 Kg','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(40,'TKP-040','고소작업대',NULL,NULL,'㈜쓰리제이테크',NULL,NULL,'2019-01-01',NULL,'250 Kg','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(41,'TKP-041','AIR CONDITIONER',NULL,'코끼리 냉장고','㈜에스엔에프',NULL,NULL,'2019-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(42,'TKP-042','AIR CONDITIONER',NULL,NULL,'㈜에스엔에프',NULL,NULL,'2019-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(43,'TKP-043','AIR CONDITIONER',NULL,NULL,'㈜에스엔에프',NULL,NULL,'2019-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(44,'TKP-044','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(45,'TKP-045','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(46,'TKP-046','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(47,'TKP-047','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(48,'TKP-048','용접흄집진기',NULL,NULL,NULL,NULL,NULL,'2019-01-01',NULL,'5 HP / 60 m3/Min','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(49,'TKP-049','자동용접기',NULL,NULL,'Swage-Lok','Swage-Lok',50000000,'2019-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(50,'TKP-050','Magnetic Drill',NULL,NULL,'NITTO','청운종합공구',NULL,'2020-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(51,'TKP-051','Magnetic Drill',NULL,NULL,'Key-Yang','청운종합공구',NULL,'2020-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(52,'TKP-052','Tube Bending M/C',NULL,NULL,'REMS',NULL,NULL,'2020-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(53,'TKP-053','Unit Test Panel',NULL,NULL,NULL,NULL,NULL,'2021-01-01',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(54,'TKP-054','고소작업대',NULL,NULL,'㈜쓰리제이테크',NULL,NULL,'2021-01-01',NULL,'500 Kg','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(55,'TKP-055','용접봉 건조기',NULL,'주문제작','진원하이텍','진원하이텍',2300000,'2022-05-04',NULL,'박스형','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(56,'TKP-056','C&T 가공기',NULL,'MS-CTK469','Swage-Lok','Swage-Lok',7347600,'2022-07-20',NULL,NULL,'active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(57,'TKP-057','테이블형 튜브 벤딩기',NULL,'MS-BTT-K','Swage-Lok','Swage-Lok',20000000,'2022-06-03',NULL,'1/2\", 1/4\"','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(58,'TKP-058','자동용접기 헤드',NULL,'SWS-10H-D-15','Swage-Lok','Swage-Lok',20000000,'2022-06-03',NULL,'1/2\"','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(59,'TKP-059','천장주행크레인',NULL,'HC-75D-13105','에이치앤씨','에이치앤씨',22800000,'2023-06-09',NULL,'7.5ton','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(60,'TKP-060','AED',NULL,'CU-SP1 Plus','제이메디','제이메디',1600000,'2023-11-09',NULL,'저출력심장충격기','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(61,'TKP-061','베벨머신',NULL,'S-150','DCSENG','DCSENG',16000000,'2023-12-12',NULL,'O.D 20mm ~ 170mm','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(62,'TKP-062','피막제거기',NULL,'CM4_OD_GC','DCSENG','DCSENG',2000000,'2023-12-12',NULL,'최대 폭 48mm, 최대 깊이 15mm, 6\"이상','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(63,'TKP-063','피막제거기',NULL,'S-CM4_OD','DCSENG','DCSENG',1200000,'2023-12-12',NULL,'최대 폭 48mm, 최대 깊이 15mm, 1\" 이상','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(64,'TKP-064','텅스텐 가공기',NULL,'S-TGR','DCSENG','DCSENG',800000,'2023-12-12',NULL,'0.89kg, 0.25~3.2','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(65,'TKP-065','전동대차',NULL,'LPM15','두산산업차량','두산산업차량',2800000,'2023-12-20',NULL,'2.0 ton','active',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-03 23:17:57','2026-02-03 23:17:57'), +(66,'TKP-066','TURN TABLE',NULL,'YCT-200T','유체기계','청운종합공구',3000000,NULL,NULL,'220V','active',NULL,2,9.76,60.78,6.17,3.10,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-04 00:17:49','2026-02-04 00:19:51'), +(67,'TKP-067','TURN TABLE',NULL,'YCT-200T','유체기계','청운종합공구',3000000,NULL,NULL,'220V','active',NULL,2,9.60,55.66,6.33,2.95,NULL,NULL,NULL,NULL,NULL,0,NULL,NULL,'2026-02-04 00:18:26','2026-02-04 00:19:57'), +(68,'TKP-068','TURN TABLE',NULL,'YCT-200TA','유체기계','청운종합공구',3000000,NULL,NULL,'220V','active',NULL,2,7.82,8.53,5.68,3.10,10,NULL,NULL,NULL,NULL,1,'2026-02-04 04:44:36',1,'2026-02-04 00:18:59','2026-02-04 04:44:36'); +/*!40000 ALTER TABLE `equipments` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `issue_report_categories` +-- + +DROP TABLE IF EXISTS `issue_report_categories`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `issue_report_categories` ( + `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '카테고리 ID', + `category_type` enum('nonconformity','safety') NOT NULL COMMENT '카테고리 유형 (부적합/안전)', + `category_name` varchar(100) NOT NULL COMMENT '카테고리명', + `description` text DEFAULT NULL COMMENT '카테고리 설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`category_id`), + KEY `idx_irc_category_type` (`category_type`), + KEY `idx_irc_is_active` (`is_active`) +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `issue_report_categories` +-- + +LOCK TABLES `issue_report_categories` WRITE; +/*!40000 ALTER TABLE `issue_report_categories` DISABLE KEYS */; +INSERT INTO `issue_report_categories` VALUES +(1,'nonconformity','자재누락',NULL,1,1,'2026-02-02 00:23:42'), +(2,'nonconformity','설계미스',NULL,2,1,'2026-02-02 00:23:42'), +(3,'nonconformity','입고불량',NULL,3,1,'2026-02-02 00:23:42'), +(4,'nonconformity','검사미스',NULL,4,1,'2026-02-02 00:23:42'), +(5,'nonconformity','기타 부적합',NULL,99,1,'2026-02-02 00:23:42'), +(6,'safety','보호구 미착용',NULL,1,1,'2026-02-02 00:23:42'), +(7,'safety','위험구역 출입',NULL,2,1,'2026-02-02 00:23:42'), +(8,'safety','안전시설 파손',NULL,3,1,'2026-02-02 00:23:42'), +(9,'safety','안전수칙 위반',NULL,4,1,'2026-02-02 00:23:42'), +(10,'safety','기타 안전',NULL,99,1,'2026-02-02 00:23:42'), +(11,'nonconformity','설비 수리','설비 고장 및 수리 요청',10,1,'2026-02-04 03:22:27'), +(12,'nonconformity','NDE 불합격',NULL,0,1,'2026-02-04 23:15:15'), +(13,'nonconformity','작업 부적합',NULL,0,1,'2026-02-04 23:15:37'); +/*!40000 ALTER TABLE `issue_report_categories` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `issue_report_items` +-- + +DROP TABLE IF EXISTS `issue_report_items`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `issue_report_items` ( + `item_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '항목 ID', + `category_id` int(10) unsigned NOT NULL COMMENT '소속 카테고리 ID', + `item_name` varchar(200) NOT NULL COMMENT '신고 항목명', + `description` text DEFAULT NULL COMMENT '항목 설명', + `severity` enum('low','medium','high','critical') DEFAULT 'medium' COMMENT '심각도', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`item_id`), + KEY `idx_iri_category_id` (`category_id`), + KEY `idx_iri_is_active` (`is_active`), + CONSTRAINT `issue_report_items_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `issue_report_categories` (`category_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=45 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `issue_report_items` +-- + +LOCK TABLES `issue_report_items` WRITE; +/*!40000 ALTER TABLE `issue_report_items` DISABLE KEYS */; +INSERT INTO `issue_report_items` VALUES +(1,1,'배관 자재 미입고',NULL,'high',1,1,'2026-02-02 00:23:42'), +(2,1,'피팅류 부족',NULL,'medium',2,1,'2026-02-02 00:23:42'), +(3,1,'밸브류 미입고',NULL,'high',3,1,'2026-02-02 00:23:42'), +(4,1,'가스켓/볼트류 부족',NULL,'low',4,1,'2026-02-02 00:23:42'), +(5,1,'서포트 자재 부족',NULL,'medium',5,1,'2026-02-02 00:23:42'), +(6,2,'도면 치수 오류',NULL,'high',1,1,'2026-02-02 00:23:42'), +(7,2,'스펙 불일치',NULL,'high',2,1,'2026-02-02 00:23:42'), +(8,2,'누락된 상세도',NULL,'medium',3,1,'2026-02-02 00:23:42'), +(9,2,'간섭 발생',NULL,'critical',4,1,'2026-02-02 00:23:42'), +(10,3,'외관 불량',NULL,'medium',1,1,'2026-02-02 00:23:42'), +(11,3,'치수 불량',NULL,'high',2,1,'2026-02-02 00:23:42'), +(12,3,'수량 부족',NULL,'medium',3,1,'2026-02-02 00:23:42'), +(13,3,'재질 불일치',NULL,'critical',4,1,'2026-02-02 00:23:42'), +(14,4,'치수 검사 누락',NULL,'high',1,1,'2026-02-02 00:23:42'), +(15,4,'외관 검사 누락',NULL,'medium',2,1,'2026-02-02 00:23:42'), +(16,4,'용접 검사 누락',NULL,'critical',3,1,'2026-02-02 00:23:42'), +(17,4,'도장 검사 누락',NULL,'medium',4,1,'2026-02-02 00:23:42'), +(18,6,'안전모 미착용',NULL,'high',1,1,'2026-02-02 00:23:42'), +(19,6,'안전화 미착용',NULL,'high',2,1,'2026-02-02 00:23:42'), +(20,6,'보안경 미착용',NULL,'medium',3,1,'2026-02-02 00:23:42'), +(21,6,'안전대 미착용',NULL,'critical',4,1,'2026-02-02 00:23:42'), +(22,6,'귀마개 미착용',NULL,'low',5,1,'2026-02-02 00:23:42'), +(23,6,'안전장갑 미착용',NULL,'medium',6,1,'2026-02-02 00:23:42'), +(24,7,'통제구역 무단 출입',NULL,'critical',1,1,'2026-02-02 00:23:42'), +(25,7,'고소 작업 구역 무단 출입',NULL,'critical',2,1,'2026-02-02 00:23:42'), +(26,7,'밀폐공간 무단 진입',NULL,'critical',3,1,'2026-02-02 00:23:42'), +(27,7,'장비 가동 구역 무단 접근',NULL,'high',4,1,'2026-02-02 00:23:42'), +(28,8,'안전난간 파손',NULL,'high',1,1,'2026-02-02 00:23:42'), +(29,8,'경고 표지판 훼손',NULL,'medium',2,1,'2026-02-02 00:23:42'), +(30,8,'안전망 파손',NULL,'high',3,1,'2026-02-02 00:23:42'), +(31,8,'비상조명 고장',NULL,'medium',4,1,'2026-02-02 00:23:42'), +(32,8,'소화설비 파손',NULL,'critical',5,1,'2026-02-02 00:23:42'), +(33,9,'지정 통로 미사용',NULL,'medium',1,1,'2026-02-02 00:23:42'), +(34,9,'고소 작업 안전 미준수',NULL,'critical',2,1,'2026-02-02 00:23:42'), +(35,9,'화기 작업 절차 미준수',NULL,'critical',3,1,'2026-02-02 00:23:42'), +(36,9,'정리정돈 미흡',NULL,'low',4,1,'2026-02-02 00:23:42'), +(37,9,'장비 조작 절차 미준수',NULL,'high',5,1,'2026-02-02 00:23:42'), +(38,11,'기계 고장','기계 작동 불가 또는 이상','high',1,1,'2026-02-04 03:22:27'), +(39,11,'부품 교체 필요','소모품 또는 부품 교체 필요','medium',2,1,'2026-02-04 03:22:27'), +(40,11,'정기 점검 필요','예방 정비 또는 정기 점검','low',3,1,'2026-02-04 03:22:27'), +(41,11,'외부 수리 필요','전문 업체 수리가 필요한 경우','high',4,1,'2026-02-04 03:22:27'), +(42,5,'작업대기',NULL,'medium',0,1,'2026-02-04 22:52:31'), +(43,13,'NDE 불합격',NULL,'medium',0,1,'2026-02-04 23:15:46'), +(44,4,'결과 전달 부적합',NULL,'medium',0,1,'2026-02-04 23:19:05'); +/*!40000 ALTER TABLE `issue_report_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `item_types` +-- + +DROP TABLE IF EXISTS `item_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `item_types` ( + `type_code` varchar(20) NOT NULL, + `type_name` varchar(50) NOT NULL COMMENT '유형명', + `icon` varchar(10) DEFAULT NULL COMMENT '아이콘 이모지', + `color` varchar(20) DEFAULT NULL COMMENT '표시 색상', + `display_order` int(11) DEFAULT 0, + `is_active` tinyint(1) DEFAULT 1, + PRIMARY KEY (`type_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `item_types` +-- + +LOCK TABLES `item_types` WRITE; +/*!40000 ALTER TABLE `item_types` DISABLE KEYS */; +INSERT INTO `item_types` VALUES +('container','용기','📦','#3b82f6',1,1), +('material','자재','🧱','#f59e0b',3,1), +('other','기타','📍','#6b7280',5,1), +('plate','플레이트','🔲','#10b981',2,1), +('tool','공구/장비','🔧','#8b5cf6',4,1); +/*!40000 ALTER TABLE `item_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `knex_migrations` +-- + +DROP TABLE IF EXISTS `knex_migrations`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `knex_migrations` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) DEFAULT NULL, + `batch` int(11) DEFAULT NULL, + `migration_time` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=53 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `knex_migrations` +-- + +LOCK TABLES `knex_migrations` WRITE; +/*!40000 ALTER TABLE `knex_migrations` DISABLE KEYS */; +INSERT INTO `knex_migrations` VALUES +(1,'20251219003210_20251219_initial_schema.js',1,'2026-01-19 00:47:40'), +(2,'20251219010000_add_columns_to_projects.js',1,'2026-01-19 00:47:40'), +(3,'20260106083251_create_permissions_tables.js',2,'2026-01-19 00:49:25'), +(4,'20260106083318_populate_permissions_data.js',3,'2026-01-19 00:49:29'), +(5,'20260107140000_update_worker_schema.js',3,'2026-01-19 00:49:29'), +(6,'20260119000000_simplify_permissions_and_add_page_access.js',3,'2026-01-19 00:49:29'), +(7,'20260119120000_add_worker_fields.js',3,'2026-01-19 00:49:46'), +(9,'20260119120001_create_attendance_tables.js',3,'2026-01-19 01:34:26'), +(11,'20260119120002_create_accounts_for_existing_workers.js',5,'2026-01-19 10:40:56'), +(12,'20260119120003_add_guest_role.js',5,'2026-01-19 10:40:56'), +(13,'20260119095549_add_worker_display_fields.js',6,'2026-01-19 01:46:21'), +(14,'20260120000000_create_tbm_system.js',7,'2026-01-20 15:30:51'), +(15,'20260120000001_add_tbm_page.js',8,'2026-01-20 15:34:53'), +(16,'20260126000001_create_workplace_categories.js',9,'2026-01-26 14:27:40'), +(17,'20260126000002_create_workplaces.js',9,'2026-01-26 14:27:40'), +(18,'20260126010002_create_tasks.js',10,'2026-01-26 15:05:01'), +(20,'20260126010003_add_work_type_task_to_tbm.js',11,'2026-01-27 06:30:46'), +(21,'20260126010004_add_work_details_to_team_assignments.js',11,'2026-01-27 06:30:46'), +(22,'20260127000001_remove_unused_tbm_fields.js',12,'2026-01-27 07:03:06'), +(23,'20260127000002_add_workplace_map_images.js',13,'2026-01-27 07:30:47'), +(24,'20260127010000_add_workplace_purpose_fields.js',14,'2026-01-27 08:15:49'), +(25,'20260127020000_make_leader_id_nullable.js',15,'2026-01-27 08:48:02'), +(26,'20260127030000_add_tbm_fields_to_work_reports.js',16,'2026-01-27 10:38:52'), +(27,'20260127040000_update_pages_for_current_system.js',17,'2026-01-27 14:59:17'), +(28,'20260128000000_add_layout_image_to_workplaces.js',18,'2026-01-28 08:24:33'), +(29,'20260128010000_create_equipments_table.js',19,'2026-01-28 09:01:32'), +(30,'20260129000000_create_vacation_requests.js',20,'2026-01-28 14:54:20'), +(31,'20260129000001_register_attendance_pages.js',21,'2026-01-28 14:55:06'), +(32,'20260129000003_update_vacation_pages.js',22,'2026-01-29 12:49:41'), +(33,'20260129000002_add_attendance_is_present.js',23,'2026-01-29 13:09:34'), +(37,'20260129000004_extend_vacation_types.js',24,'2026-01-29 13:33:11'), +(38,'20260129000005_create_vacation_balance_details.js',24,'2026-01-29 13:33:11'), +(39,'20260129000006_register_vacation_pages.js',24,'2026-01-29 13:33:11'), +(40,'20260129010000_create_visit_request_system.js',25,'2026-01-29 14:26:17'), +(41,'20260129010001_register_visit_pages.js',25,'2026-01-29 14:26:17'), +(42,'20260130000001_create_work_issue_system.js',26,'2026-02-02 00:23:42'), +(44,'20260130000002_register_issue_pages.js',27,'2026-02-02 01:19:22'), +(45,'20260202000001_create_work_report_defects.js',28,'2026-02-02 01:19:31'), +(46,'20260202100000_expand_safety_checklist.js',29,'2026-02-02 01:44:54'), +(48,'20260202200000_reorganize_pages.js',30,'2026-02-02 23:15:51'), +(49,'20260203100000_link_defects_to_issues.js',31,'2026-02-02 23:16:00'), +(50,'20260203090000_add_category_to_defects.js',32,'2026-02-02 23:55:34'), +(51,'20260204100000_add_equipment_purchase_fields.js',33,'2026-02-04 01:44:41'), +(52,'20260204100000_create_daily_patrol_system.js',34,'2026-02-04 01:47:33'); +/*!40000 ALTER TABLE `knex_migrations` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `knex_migrations_lock` +-- + +DROP TABLE IF EXISTS `knex_migrations_lock`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `knex_migrations_lock` ( + `index` int(10) unsigned NOT NULL AUTO_INCREMENT, + `is_locked` int(11) DEFAULT NULL, + PRIMARY KEY (`index`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `knex_migrations_lock` +-- + +LOCK TABLES `knex_migrations_lock` WRITE; +/*!40000 ALTER TABLE `knex_migrations_lock` DISABLE KEYS */; +INSERT INTO `knex_migrations_lock` VALUES +(1,0); +/*!40000 ALTER TABLE `knex_migrations_lock` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `login_logs` +-- + +DROP TABLE IF EXISTS `login_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `login_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL, + `login_time` datetime DEFAULT current_timestamp(), + `logout_time` datetime DEFAULT NULL, + `ip_address` varchar(45) DEFAULT NULL, + `user_agent` text DEFAULT NULL, + `login_status` enum('success','failed','locked') DEFAULT 'success', + `failure_reason` varchar(100) DEFAULT NULL, + PRIMARY KEY (`log_id`), + KEY `idx_user_login` (`user_id`,`login_time`), + CONSTRAINT `login_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=224 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `login_logs` +-- + +LOCK TABLES `login_logs` WRITE; +/*!40000 ALTER TABLE `login_logs` DISABLE KEYS */; +INSERT INTO `login_logs` VALUES +(146,3,'2025-11-02 23:53:02',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(147,3,'2025-11-03 02:10:26',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(148,3,'2025-11-03 02:10:33',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(149,1,'2025-11-03 02:11:06',NULL,'::ffff:185.199.111.133','curl/8.7.1','failed','invalid_password'), +(150,1,'2025-11-03 02:11:06',NULL,'::ffff:185.199.111.133','curl/8.7.1','failed','invalid_password'), +(151,3,'2025-11-03 02:11:43',NULL,'::ffff:185.199.111.133','curl/8.7.1','success',NULL), +(152,3,'2025-11-03 02:11:49',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(153,3,'2025-11-03 02:12:44',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(154,3,'2025-11-03 02:12:58',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(155,3,'2025-11-03 02:12:58',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(156,3,'2025-11-03 02:13:02',NULL,'::ffff:185.199.111.133','curl/8.7.1','success',NULL), +(157,3,'2025-11-03 02:13:43',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(158,3,'2025-11-03 02:15:28',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(159,3,'2025-11-03 03:07:23',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(160,3,'2025-11-03 03:27:50',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(161,3,'2025-11-03 03:44:52',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(162,3,'2025-11-03 04:02:14',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(163,3,'2025-11-03 04:36:14',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(164,3,'2025-11-03 06:21:57',NULL,'::ffff:185.199.111.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(165,3,'2025-11-03 06:50:04',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(166,3,'2025-11-03 22:39:38',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(167,1,'2025-11-04 01:38:28',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(168,1,'2025-11-04 01:58:20',NULL,'::ffff:192.168.65.1','curl/8.7.1','failed','invalid_password'), +(169,1,'2025-11-04 21:34:47',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(170,1,'2025-11-04 23:55:43',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(171,1,'2025-11-04 23:56:47',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','failed','invalid_password'), +(172,1,'2025-11-04 23:56:59',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(173,1,'2025-11-05 01:35:01',NULL,'::ffff:185.199.109.133','curl/8.7.1','failed','invalid_password'), +(174,1,'2025-11-05 01:36:09',NULL,'::ffff:185.199.109.133','curl/8.7.1','failed','invalid_password'), +(175,1,'2025-11-05 01:37:45',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(176,1,'2025-11-05 01:44:59',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(177,6,'2025-11-05 01:46:07',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(178,3,'2025-11-05 01:46:14',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(179,5,'2025-11-05 01:47:15',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(180,3,'2025-11-05 01:49:12',NULL,'::ffff:185.199.109.133','curl/8.7.1','failed','invalid_password'), +(181,3,'2025-11-05 01:49:27',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(182,6,'2025-11-05 01:49:37',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(183,5,'2025-11-05 01:49:44',NULL,'::ffff:185.199.109.133','curl/8.7.1','success',NULL), +(184,5,'2025-11-05 01:50:08',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(185,5,'2025-11-05 01:55:59',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(186,6,'2025-11-05 01:56:13',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(187,3,'2025-11-05 01:56:20',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(188,1,'2025-11-05 01:56:35',NULL,'::ffff:185.199.109.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(189,1,'2025-11-05 02:01:27',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(190,3,'2025-11-05 02:01:53',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(191,5,'2025-11-05 02:02:02',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(192,1,'2025-11-05 02:03:10',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','failed','invalid_password'), +(193,1,'2025-11-05 02:03:20',NULL,'::ffff:192.168.65.1','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(194,5,'2025-11-05 02:18:31',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(195,7,'2025-11-05 02:20:22',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(196,1,'2025-11-05 02:20:37',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(197,7,'2025-11-05 02:23:43',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(198,1,'2025-11-05 02:25:08',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(199,3,'2025-11-05 02:25:45',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(200,7,'2025-11-05 02:25:54',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(201,7,'2025-11-05 02:26:31',NULL,'::ffff:185.199.110.133','curl/8.7.1','failed','invalid_password'), +(202,7,'2025-11-05 02:27:52',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(205,1,'2025-11-05 02:52:20',NULL,'::ffff:185.199.110.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.6 Safari/605.1.15','success',NULL), +(206,3,'2026-02-03 04:54:17',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(207,1,'2026-02-03 04:56:05',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(208,3,'2026-02-03 05:43:08',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36','success',NULL), +(209,1,'2026-02-03 05:43:42',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36','success',NULL), +(210,1,'2026-02-03 06:14:57',NULL,'::ffff:185.199.108.133','curl/8.7.1','failed','invalid_password'), +(211,1,'2026-02-03 06:25:29',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(212,1,'2026-02-03 06:26:54',NULL,'::ffff:185.199.108.133','curl/8.7.1','failed','invalid_password'), +(213,1,'2026-02-03 06:55:48',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(214,1,'2026-02-03 21:24:20',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(215,1,'2026-02-03 22:53:39',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(216,1,'2026-02-04 05:31:13',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(217,1,'2026-02-04 07:25:57',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(218,1,'2026-02-04 23:46:38',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(219,1,'2026-02-05 01:01:31',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(220,1,'2026-02-05 03:56:31',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(221,1,'2026-02-05 05:22:15',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.2 Safari/605.1.15','success',NULL), +(222,1,'2026-02-05 21:37:09',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36','success',NULL), +(223,1,'2026-02-05 22:40:53',NULL,'::ffff:185.199.108.133','Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36','success',NULL); +/*!40000 ALTER TABLE `login_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `notification_recipients` +-- + +DROP TABLE IF EXISTS `notification_recipients`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `notification_recipients` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `notification_type` enum('repair','safety','nonconformity','equipment','maintenance','system') NOT NULL, + `user_id` int(11) NOT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `created_by` int(11) DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `unique_type_user` (`notification_type`,`user_id`), + KEY `user_id` (`user_id`), + KEY `idx_nr_type` (`notification_type`), + KEY `idx_nr_active` (`is_active`), + CONSTRAINT `notification_recipients_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `notification_recipients` +-- + +LOCK TABLES `notification_recipients` WRITE; +/*!40000 ALTER TABLE `notification_recipients` DISABLE KEYS */; +/*!40000 ALTER TABLE `notification_recipients` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `notifications` +-- + +DROP TABLE IF EXISTS `notifications`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `notifications` ( + `notification_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) DEFAULT NULL COMMENT '특정 사용자에게만 표시 (NULL이면 전체)', + `type` enum('repair','safety','system','equipment','maintenance') NOT NULL DEFAULT 'system', + `title` varchar(200) NOT NULL, + `message` text DEFAULT NULL, + `link_url` varchar(500) DEFAULT NULL COMMENT '클릭시 이동할 URL', + `reference_type` varchar(50) DEFAULT NULL COMMENT '연관 테이블', + `reference_id` int(11) DEFAULT NULL COMMENT '연관 레코드 ID', + `is_read` tinyint(1) DEFAULT 0, + `read_at` datetime DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `created_by` int(11) DEFAULT NULL, + PRIMARY KEY (`notification_id`), + KEY `idx_notifications_user` (`user_id`), + KEY `idx_notifications_type` (`type`), + KEY `idx_notifications_is_read` (`is_read`), + KEY `idx_notifications_created` (`created_at` DESC) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `notifications` +-- + +LOCK TABLES `notifications` WRITE; +/*!40000 ALTER TABLE `notifications` DISABLE KEYS */; +INSERT INTO `notifications` VALUES +(1,NULL,'repair','수리 신청: TIG용접기','기계 고장 수리가 신청되었습니다.','/pages/admin/equipment-detail.html?id=18','work_issue_reports',7,1,'2026-02-04 06:08:30','2026-02-04 05:35:54',NULL), +(2,NULL,'repair','수리 신청: TIG용접기','기계 고장 수리가 신청되었습니다.','/pages/admin/repair-management.html','work_issue_reports',7,0,NULL,'2026-02-04 05:35:54',NULL); +/*!40000 ALTER TABLE `notifications` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `pages` +-- + +DROP TABLE IF EXISTS `pages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `pages` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `page_key` varchar(100) NOT NULL, + `page_name` varchar(100) NOT NULL, + `page_path` varchar(255) NOT NULL, + `category` varchar(50) DEFAULT NULL, + `description` varchar(255) DEFAULT NULL, + `is_admin_only` tinyint(1) DEFAULT 0, + `display_order` int(11) DEFAULT 0, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `is_default_accessible` tinyint(1) DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `pages_page_key_unique` (`page_key`) +) ENGINE=InnoDB AUTO_INCREMENT=55 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `pages` +-- + +LOCK TABLES `pages` WRITE; +/*!40000 ALTER TABLE `pages` DISABLE KEYS */; +INSERT INTO `pages` VALUES +(11,'dashboard','대시보드','/pages/dashboard.html','common','전체 현황 대시보드',0,1,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(12,'work.tbm','TBM','/pages/work/tbm.html','work','TBM (Tool Box Meeting) 관리',0,10,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(13,'work.report-create','작업보고서 작성','/pages/work/report-create.html','work','일일 작업보고서 작성',0,11,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(14,'work.report-view','작업보고서 조회','/pages/work/report-view.html','work','작업보고서 조회 및 검색',0,12,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(15,'work.analysis','작업 분석','/pages/work/analysis.html','work','작업 통계 및 분석',0,13,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(16,'admin.accounts','계정 관리','/pages/admin/accounts.html','admin','사용자 계정 관리',1,20,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(18,'admin.workers','작업자 관리','/pages/admin/workers.html','admin','작업자 정보 관리',1,22,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(19,'admin.projects','프로젝트 관리','/pages/admin/projects.html','admin','프로젝트 관리',1,23,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(20,'admin.workplaces','작업장 관리','/pages/admin/workplaces.html','admin','작업장소 관리',1,24,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(21,'admin.codes','코드 관리','/pages/admin/codes.html','admin','시스템 코드 관리',1,25,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(22,'admin.tasks','작업 관리','/pages/admin/tasks.html','admin','작업 유형 관리',1,26,'2026-01-27 05:59:17','2026-01-27 05:59:17',0), +(23,'profile.info','내 정보','/pages/profile/info.html','profile','내 프로필 정보',0,30,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(24,'profile.password','비밀번호 변경','/pages/profile/password.html','profile','비밀번호 변경',0,31,'2026-01-27 05:59:17','2026-01-27 05:59:17',1), +(25,'admin.equipments','설비 관리','/pages/admin/equipments.html','admin','작업장별 설비 정보를 등록하고 관리합니다',1,35,'2026-01-28 00:17:01','2026-01-28 00:17:01',0), +(26,'common.daily-attendance','일일 출퇴근 입력','/pages/common/daily-attendance.html','common','일일 출퇴근 기록 입력 페이지 (관리자/조장)',0,50,'2026-01-28 05:55:06','2026-01-28 05:55:06',1), +(27,'common.monthly-attendance','월별 출퇴근 현황','/pages/common/monthly-attendance.html','common','월별 출퇴근 현황 조회 페이지',0,51,'2026-01-28 05:55:06','2026-01-28 05:55:06',1), +(29,'admin.attendance-report-comparison','출퇴근-작업보고서 대조','/pages/admin/attendance-report-comparison.html','admin','출퇴근 기록과 작업보고서 대조 페이지 (관리자)',1,120,'2026-01-28 05:55:06','2026-01-28 05:55:06',0), +(34,'common.vacation-request','휴가 신청','/pages/common/vacation-request.html','common','작업자가 휴가를 신청하고 본인의 신청 내역을 확인하는 페이지',0,51,'2026-01-29 04:10:29','2026-01-29 04:10:29',1), +(35,'common.vacation-management','휴가 관리','/pages/common/vacation-management.html','common','관리자가 휴가 승인, 직접 입력, 전체 내역을 관리하는 페이지',1,52,'2026-01-29 04:10:29','2026-01-29 04:10:29',0), +(36,'common.annual-vacation-overview','연간 연차 현황','/pages/common/annual-vacation-overview.html','common','모든 작업자의 연간 연차 현황을 차트로 시각화',1,54,'2026-01-29 04:33:11','2026-01-29 04:33:11',0), +(37,'common.vacation-allocation','휴가 발생 입력','/pages/common/vacation-allocation.html','common','작업자별 휴가 발생 입력 및 특별 휴가 관리',1,55,'2026-01-29 04:33:11','2026-01-29 04:33:11',0), +(38,'work.visit-request','출입 신청','/pages/work/visit-request.html','work','작업장 출입 신청 및 안전교육 신청',0,15,'2026-01-29 05:26:17','2026-01-29 05:26:17',1), +(39,'admin.safety-management','안전관리','/pages/admin/safety-management.html','admin','출입 신청 승인 및 안전교육 관리',0,60,'2026-01-29 05:26:17','2026-01-29 05:26:17',0), +(40,'admin.safety-training-conduct','안전교육 진행','/pages/admin/safety-training-conduct.html','admin','안전교육 실시 및 서명 관리',0,61,'2026-01-29 05:26:17','2026-01-29 05:26:17',0), +(41,'work.issue-report','문제 신고','/pages/work/issue-report.html','work','작업 중 문제(부적합/안전) 신고 등록',0,16,'2026-02-02 00:24:55','2026-02-02 00:24:55',1), +(42,'work.issue-list','신고 목록','/pages/work/issue-list.html','work','문제 신고 목록 조회 및 관리',0,17,'2026-02-02 00:24:55','2026-02-02 00:24:55',1), +(43,'work.issue-detail','신고 상세','/pages/work/issue-detail.html','work','문제 신고 상세 조회',0,18,'2026-02-02 00:24:55','2026-02-02 00:24:55',1), +(44,'safety.issue_report','이슈 신고','/pages/safety/issue-report.html','safety','작업 중 문제(부적합/안전) 신고 등록',0,16,'2026-02-02 01:19:22','2026-02-02 01:19:22',0), +(45,'safety.issue_list','이슈 목록','/pages/safety/issue-list.html','safety','문제 신고 목록 조회 및 관리',0,17,'2026-02-02 01:19:22','2026-02-02 01:19:22',0), +(46,'safety.issue_detail','이슈 상세','/pages/safety/issue-detail.html','safety','문제 신고 상세 조회',0,18,'2026-02-02 01:19:22','2026-02-02 01:19:22',0), +(50,'safety.checklist_manage','안전 체크리스트 관리','/pages/safety/checklist-manage.html','safety','안전 체크리스트 항목 관리',1,50,'2026-02-02 23:15:51','2026-02-02 23:15:51',0), +(51,'attendance.vacation_approval','휴가 승인 관리','/pages/attendance/vacation-approval.html','attendance','휴가 신청 승인/거부',1,65,'2026-02-02 23:15:51','2026-02-02 23:15:51',0), +(52,'attendance.vacation_input','휴가 직접 입력','/pages/attendance/vacation-input.html','attendance','관리자 휴가 직접 입력',1,66,'2026-02-02 23:15:51','2026-02-02 23:15:51',0), +(53,'admin.departments','부서 관리','/pages/admin/departments.html','admin',NULL,1,3,'2026-02-03 05:06:48','2026-02-03 05:06:48',0), +(54,'inspection.daily_patrol','일일순회점검','/pages/inspection/daily-patrol.html','inspection','작업장 일일순회점검 페이지',0,1,'2026-02-04 02:17:23','2026-02-04 02:17:23',1); +/*!40000 ALTER TABLE `pages` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `password_change_logs` +-- + +DROP TABLE IF EXISTS `password_change_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `password_change_logs` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `user_id` int(11) NOT NULL, + `changed_by_user_id` int(11) DEFAULT NULL, + `changed_at` datetime DEFAULT current_timestamp(), + `change_type` enum('self','admin','reset','initial') DEFAULT 'self', + `ip_address` varchar(45) DEFAULT NULL, + PRIMARY KEY (`log_id`), + KEY `changed_by_user_id` (`changed_by_user_id`), + KEY `idx_user_changes` (`user_id`,`changed_at`), + CONSTRAINT `password_change_logs_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE, + CONSTRAINT `password_change_logs_ibfk_2` FOREIGN KEY (`changed_by_user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `password_change_logs` +-- + +LOCK TABLES `password_change_logs` WRITE; +/*!40000 ALTER TABLE `password_change_logs` DISABLE KEYS */; +/*!40000 ALTER TABLE `password_change_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `patrol_check_records` +-- + +DROP TABLE IF EXISTS `patrol_check_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `patrol_check_records` ( + `record_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL COMMENT '순회점검 세션 ID', + `workplace_id` int(10) unsigned NOT NULL COMMENT '작업장 ID', + `check_item_id` int(10) unsigned NOT NULL COMMENT '체크항목 ID', + `is_checked` tinyint(1) DEFAULT 0 COMMENT '체크 여부', + `check_result` enum('good','warning','bad') DEFAULT NULL COMMENT '점검 결과', + `note` text DEFAULT NULL COMMENT '비고', + `checked_at` timestamp NULL DEFAULT NULL COMMENT '체크 시간', + PRIMARY KEY (`record_id`), + UNIQUE KEY `pcr_session_wp_item_unique` (`session_id`,`workplace_id`,`check_item_id`), + KEY `pcr_session_wp_idx` (`session_id`,`workplace_id`), + KEY `patrol_check_records_workplace_id_foreign` (`workplace_id`), + KEY `patrol_check_records_check_item_id_foreign` (`check_item_id`), + CONSTRAINT `patrol_check_records_check_item_id_foreign` FOREIGN KEY (`check_item_id`) REFERENCES `patrol_checklist_items` (`item_id`) ON DELETE CASCADE, + CONSTRAINT `patrol_check_records_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `daily_patrol_sessions` (`session_id`) ON DELETE CASCADE, + CONSTRAINT `patrol_check_records_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `patrol_check_records` +-- + +LOCK TABLES `patrol_check_records` WRITE; +/*!40000 ALTER TABLE `patrol_check_records` DISABLE KEYS */; +/*!40000 ALTER TABLE `patrol_check_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `patrol_checklist_items` +-- + +DROP TABLE IF EXISTS `patrol_checklist_items`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `patrol_checklist_items` ( + `item_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `workplace_id` int(10) unsigned DEFAULT NULL COMMENT '특정 작업장 전용 (NULL=공통)', + `category_id` int(10) unsigned DEFAULT NULL COMMENT '특정 공장 전용 (NULL=공통)', + `check_category` varchar(50) NOT NULL COMMENT '분류 (안전, 정리정돈, 설비 등)', + `check_item` varchar(200) NOT NULL COMMENT '점검 항목', + `description` text DEFAULT NULL COMMENT '설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_required` tinyint(1) DEFAULT 1 COMMENT '필수 체크 여부', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`item_id`), + KEY `patrol_checklist_items_workplace_id_index` (`workplace_id`), + KEY `patrol_checklist_items_category_id_index` (`category_id`), + KEY `patrol_checklist_items_check_category_index` (`check_category`), + CONSTRAINT `patrol_checklist_items_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE CASCADE, + CONSTRAINT `patrol_checklist_items_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `patrol_checklist_items` +-- + +LOCK TABLES `patrol_checklist_items` WRITE; +/*!40000 ALTER TABLE `patrol_checklist_items` DISABLE KEYS */; +INSERT INTO `patrol_checklist_items` VALUES +(1,NULL,NULL,'SAFETY','소화기 상태 확인',NULL,1,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(2,NULL,NULL,'SAFETY','비상구 통로 확보 확인',NULL,2,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(3,NULL,NULL,'SAFETY','안전표지판 부착 상태',NULL,3,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(4,NULL,NULL,'SAFETY','위험물 관리 상태',NULL,4,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(5,NULL,NULL,'ORGANIZATION','작업장 정리정돈 상태',NULL,10,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(6,NULL,NULL,'ORGANIZATION','통로 장애물 여부',NULL,11,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(7,NULL,NULL,'ORGANIZATION','폐기물 처리 상태',NULL,12,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(8,NULL,NULL,'ORGANIZATION','자재 적재 상태',NULL,13,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(9,NULL,NULL,'EQUIPMENT','설비 외관 이상 여부',NULL,20,0,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(10,NULL,NULL,'EQUIPMENT','설비 작동 상태',NULL,21,0,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(11,NULL,NULL,'EQUIPMENT','설비 청결 상태',NULL,22,0,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(12,NULL,NULL,'ENVIRONMENT','조명 상태',NULL,30,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(13,NULL,NULL,'ENVIRONMENT','환기 상태',NULL,31,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'), +(14,NULL,NULL,'ENVIRONMENT','누수/누유 여부',NULL,32,1,1,'2026-02-04 01:47:33','2026-02-04 01:47:33'); +/*!40000 ALTER TABLE `patrol_checklist_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `permissions` +-- + +DROP TABLE IF EXISTS `permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `permissions` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL, + `description` varchar(255) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `permissions_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `permissions` +-- + +LOCK TABLES `permissions` WRITE; +/*!40000 ALTER TABLE `permissions` DISABLE KEYS */; +INSERT INTO `permissions` VALUES +(1,'user:create','사용자 생성','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(2,'user:read','사용자 정보 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(3,'user:update','사용자 정보 수정','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(4,'user:delete','사용자 삭제','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(5,'project:create','프로젝트 생성','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(6,'project:read','프로젝트 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(7,'project:update','프로젝트 수정','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(8,'project:delete','프로젝트 삭제','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(9,'work-report:create','작업 보고서 생성','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(10,'work-report:read-own','자신의 작업 보고서 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(11,'work-report:read-team','팀의 작업 보고서 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(12,'work-report:read-all','모든 작업 보고서 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(13,'work-report:update','작업 보고서 수정','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(14,'work-report:delete','작업 보고서 삭제','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(15,'system:read-logs','시스템 로그 조회','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(16,'system:manage-settings','시스템 설정 관리','2026-01-19 00:49:29','2026-01-19 00:49:29'); +/*!40000 ALTER TABLE `permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `projects` +-- + +DROP TABLE IF EXISTS `projects`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `projects` ( + `project_id` int(11) NOT NULL AUTO_INCREMENT, + `job_no` varchar(50) NOT NULL, + `project_name` varchar(255) NOT NULL, + `contract_date` date DEFAULT NULL, + `due_date` date DEFAULT NULL, + `delivery_method` varchar(100) DEFAULT NULL, + `site` varchar(100) DEFAULT NULL, + `pm` varchar(100) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `is_active` tinyint(1) DEFAULT 1, + `project_status` varchar(50) DEFAULT 'active', + `completed_date` date DEFAULT NULL, + PRIMARY KEY (`project_id`) +) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `projects` +-- + +LOCK TABLES `projects` WRITE; +/*!40000 ALTER TABLE `projects` DISABLE KEYS */; +INSERT INTO `projects` VALUES +(1,'TKO-24008P','YHP Project',NULL,NULL,NULL,'Quang Ninh(Vietnam)','장형태','2025-04-15 22:40:28','2025-04-15 22:40:28',0,'active',NULL), +(2,'TKG-24009P','한화에어로스페이스 순천',NULL,NULL,NULL,'순천','장형태','2025-04-15 22:42:41','2025-04-15 22:42:41',0,'active',NULL), +(3,'TKG-24011P','효성화학 에틸렌 탱크 건설공사',NULL,NULL,NULL,'울산','김길종','2025-04-15 22:43:53','2025-04-15 22:43:53',0,'active',NULL), +(4,'TKG-24013P','김천 솔라 파워 그린 수소 Project',NULL,NULL,NULL,'김천','김길종','2025-04-15 22:44:57','2025-04-15 22:44:57',0,'active',NULL), +(5,'TKG-24016P','LG Chem P3RE Project',NULL,NULL,NULL,'.','장형태','2025-04-15 22:46:36','2025-04-15 22:46:36',0,'active',NULL), +(7,'TKO-25003F','25년 안전보건시설설비',NULL,NULL,NULL,'.','.','2025-04-15 22:47:32','2025-04-15 22:47:32',0,'active',NULL), +(8,'TKG-25007P','P Project',NULL,NULL,NULL,'오창읍','장형태','2025-04-15 22:48:50','2025-04-15 22:48:50',0,'active',NULL), +(10,'TKR-25008P','DIG Airgas LG CHEM',NULL,NULL,NULL,'여수','서태원','2025-04-15 22:50:05','2025-04-15 22:50:05',0,'active',NULL), +(11,'TKR-25010P','FK FISCHER Project',NULL,NULL,NULL,'울산','전상신','2025-04-15 22:51:12','2025-04-15 22:51:12',0,'active',NULL), +(12,'TKO-24007P','MP7 Project',NULL,NULL,NULL,'.','윤지민','2025-04-15 23:56:26','2025-04-15 23:56:26',0,'active',NULL), +(13,'연차/휴무','연차/휴무','2025-01-01','2025-12-31','.','.','.','2025-04-16 01:58:23','2025-04-16 01:58:23',1,'active',NULL), +(14,'TKO-25009R','M Project',NULL,NULL,NULL,NULL,'이민후','2025-09-28 22:13:33','2025-09-28 22:13:33',1,'active',NULL), +(15,'TKR-25013P','HAS MCS Plnat',NULL,'2026-03-31',NULL,NULL,NULL,'2026-01-06 06:16:37','2026-01-06 06:16:37',1,'active',NULL), +(16,'TKO-26003F','안전보건시설설비','2026-01-01','2026-12-31',NULL,NULL,NULL,'2026-01-06 06:17:33','2026-01-06 06:17:33',1,'active',NULL), +(17,'TKO-25014P','OT1-MPR-002',NULL,NULL,NULL,'말레이시아','윤지민','2026-02-04 21:35:22','2026-02-04 21:35:22',1,'active',NULL), +(18,'TKO025024P','H2 Gas Scrubber',NULL,'2026-07-31',NULL,NULL,'윤지민','2026-02-04 21:36:50','2026-02-04 21:36:50',1,'active',NULL); +/*!40000 ALTER TABLE `projects` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `role_default_pages` +-- + +DROP TABLE IF EXISTS `role_default_pages`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `role_default_pages` ( + `role_id` int(10) unsigned NOT NULL, + `page_id` int(10) unsigned NOT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`role_id`,`page_id`), + KEY `role_default_pages_page_id_foreign` (`page_id`), + CONSTRAINT `role_default_pages_page_id_foreign` FOREIGN KEY (`page_id`) REFERENCES `pages` (`id`) ON DELETE CASCADE, + CONSTRAINT `role_default_pages_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `role_default_pages` +-- + +LOCK TABLES `role_default_pages` WRITE; +/*!40000 ALTER TABLE `role_default_pages` DISABLE KEYS */; +/*!40000 ALTER TABLE `role_default_pages` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `role_permissions` +-- + +DROP TABLE IF EXISTS `role_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `role_permissions` ( + `role_id` int(10) unsigned NOT NULL, + `permission_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`role_id`,`permission_id`), + KEY `role_permissions_permission_id_foreign` (`permission_id`), + CONSTRAINT `role_permissions_permission_id_foreign` FOREIGN KEY (`permission_id`) REFERENCES `permissions` (`id`) ON DELETE CASCADE, + CONSTRAINT `role_permissions_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `role_permissions` +-- + +LOCK TABLES `role_permissions` WRITE; +/*!40000 ALTER TABLE `role_permissions` DISABLE KEYS */; +INSERT INTO `role_permissions` VALUES +(1,1), +(1,2), +(1,3), +(1,4), +(1,5), +(1,6), +(1,7), +(1,8), +(1,9), +(1,10), +(1,11), +(1,12), +(1,13), +(1,14), +(1,15), +(1,16), +(2,1), +(2,2), +(2,3), +(2,4), +(2,5), +(2,6), +(2,7), +(2,8), +(2,12), +(2,13), +(2,14), +(4,2), +(4,5), +(4,6), +(4,7), +(4,9), +(4,10), +(4,11), +(4,12), +(4,13), +(4,14); +/*!40000 ALTER TABLE `role_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `roles` +-- + +DROP TABLE IF EXISTS `roles`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `roles` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL, + `description` varchar(255) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `roles_name_unique` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `roles` +-- + +LOCK TABLES `roles` WRITE; +/*!40000 ALTER TABLE `roles` DISABLE KEYS */; +INSERT INTO `roles` VALUES +(1,'System Admin','시스템 전체 관리자. 모든 권한을 가짐.','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(2,'Admin','관리자. 사용자 및 프로젝트 관리 등 대부분의 권한을 가짐.','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(4,'User','일반 사용자. 작업 보고서 및 프로젝트 관리 등 모든 일반 기능을 사용할 수 있음.','2026-01-19 00:49:29','2026-01-19 00:49:29'), +(5,'Guest','게스트 (계정 없이 특정 기능 접근 가능)','2026-01-19 01:40:56','2026-01-19 01:40:56'); +/*!40000 ALTER TABLE `roles` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `safety_training_records` +-- + +DROP TABLE IF EXISTS `safety_training_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `safety_training_records` ( + `training_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '교육 기록 ID', + `request_id` int(10) unsigned NOT NULL COMMENT '출입 신청 ID', + `trainer_id` int(11) NOT NULL COMMENT '교육 진행자 user_id', + `training_date` date NOT NULL COMMENT '교육 날짜', + `training_start_time` time NOT NULL COMMENT '교육 시작 시간', + `training_end_time` time DEFAULT NULL COMMENT '교육 종료 시간', + `training_topics` text DEFAULT NULL COMMENT '교육 내용 (JSON 배열)', + `signature_data` longtext DEFAULT NULL COMMENT '교육 이수자 서명 (Base64 PNG)', + `completed_at` timestamp NULL DEFAULT NULL COMMENT '교육 완료 시간', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`training_id`), + KEY `safety_training_records_trainer_id_foreign` (`trainer_id`), + KEY `idx_training_date` (`training_date`), + KEY `idx_request_id` (`request_id`), + CONSTRAINT `safety_training_records_request_id_foreign` FOREIGN KEY (`request_id`) REFERENCES `workplace_visit_requests` (`request_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `safety_training_records_trainer_id_foreign` FOREIGN KEY (`trainer_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `safety_training_records` +-- + +LOCK TABLES `safety_training_records` WRITE; +/*!40000 ALTER TABLE `safety_training_records` DISABLE KEYS */; +INSERT INTO `safety_training_records` VALUES +(1,1,1,'2026-01-29','15:04:41','15:04:41',NULL,NULL,NULL,'2026-01-29 06:04:41','2026-01-29 06:04:41'), +(2,1,1,'2026-01-29','15:04:41','15:04:41',NULL,NULL,NULL,'2026-01-29 06:04:41','2026-01-29 06:04:41'), +(3,1,1,'2026-01-29','15:08:41','15:08:41',NULL,NULL,NULL,'2026-01-29 06:08:41','2026-01-29 06:08:41'), +(4,1,1,'2026-01-29','15:08:41','15:08:41',NULL,NULL,NULL,'2026-01-29 06:08:41','2026-01-29 06:08:41'), +(5,2,1,'2026-01-29','15:12:11','15:12:11',NULL,NULL,NULL,'2026-01-29 06:12:11','2026-01-29 06:12:11'), +(6,2,1,'2026-01-29','15:12:11','15:12:11',NULL,NULL,NULL,'2026-01-29 06:12:11','2026-01-29 06:12:11'); +/*!40000 ALTER TABLE `safety_training_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tasks` +-- + +DROP TABLE IF EXISTS `tasks`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tasks` ( + `task_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '작업 ID', + `work_type_id` int(11) DEFAULT NULL COMMENT '공정 ID (work_types 참조)', + `task_name` varchar(255) NOT NULL COMMENT '작업명', + `description` text DEFAULT NULL COMMENT '작업 설명', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성화 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '생성일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정일시', + PRIMARY KEY (`task_id`), + KEY `tasks_work_type_id_index` (`work_type_id`), + KEY `tasks_is_active_index` (`is_active`), + CONSTRAINT `tasks_work_type_id_foreign` FOREIGN KEY (`work_type_id`) REFERENCES `work_types` (`id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tasks` +-- + +LOCK TABLES `tasks` WRITE; +/*!40000 ALTER TABLE `tasks` DISABLE KEYS */; +INSERT INTO `tasks` VALUES +(1,1,'H빔 절단',NULL,1,'2026-01-26 21:54:17','2026-01-26 21:54:17'), +(2,1,'H빔 가공','끝단 가공 등 전부 포함',1,'2026-02-04 21:47:35','2026-02-04 21:47:35'), +(3,1,'용접',NULL,1,'2026-02-04 21:47:53','2026-02-04 21:47:53'), +(4,1,'서포트 제작(홀 가공 포함)',NULL,1,'2026-02-04 21:48:15','2026-02-04 21:48:15'), +(5,2,'Plate 하차',NULL,1,'2026-02-04 21:48:30','2026-02-04 21:48:30'), +(6,2,'Plate 마킹',NULL,1,'2026-02-04 21:48:38','2026-02-04 21:48:38'), +(7,2,'Plate 가공 출하',NULL,1,'2026-02-04 21:48:59','2026-02-04 21:48:59'), +(8,2,'동체 L심 용접',NULL,1,'2026-02-04 21:49:19','2026-02-04 21:49:19'), +(9,2,'C심 용접',NULL,1,'2026-02-04 21:49:29','2026-02-04 21:49:29'), +(10,2,'노즐 용접',NULL,1,'2026-02-04 21:49:36','2026-02-04 21:49:48'), +(11,2,'자재 절단',NULL,1,'2026-02-04 21:49:55','2026-02-04 21:49:55'), +(12,2,'검사 지원',NULL,1,'2026-02-04 21:50:16','2026-02-04 21:50:16'), +(13,3,'pipe 절단',NULL,1,'2026-02-04 21:50:31','2026-02-04 21:50:31'), +(14,3,'배관 취부',NULL,1,'2026-02-04 21:50:39','2026-02-04 21:50:39'), +(15,3,'용접',NULL,1,'2026-02-04 21:50:43','2026-02-04 21:50:43'), +(16,3,'선 작업(용접전 작업 준비)','갭링, 면취 등 모든 선 작업',1,'2026-02-04 21:51:22','2026-02-04 21:51:22'), +(17,3,'1차 조립',NULL,1,'2026-02-04 21:51:31','2026-02-04 21:51:31'), +(18,3,'검사 지원',NULL,1,'2026-02-04 21:51:36','2026-02-04 21:51:36'), +(19,3,'2차 조립',NULL,1,'2026-02-04 21:51:41','2026-02-04 21:51:41'), +(20,11,'배우자출산휴가',NULL,1,'2026-02-04 22:41:40','2026-02-04 22:41:40'), +(21,11,'연차',NULL,1,'2026-02-04 22:41:46','2026-02-04 22:41:46'), +(22,11,'반차',NULL,1,'2026-02-04 22:41:51','2026-02-04 22:41:51'), +(23,11,'반반차',NULL,1,'2026-02-04 22:41:57','2026-02-04 22:41:57'), +(24,11,'조퇴',NULL,1,'2026-02-04 22:42:05','2026-02-04 22:42:05'), +(25,12,'설비제작',NULL,1,'2026-02-04 23:47:01','2026-02-04 23:47:01'), +(26,2,'자재 가공',NULL,1,'2026-02-05 01:01:48','2026-02-05 01:01:48'); +/*!40000 ALTER TABLE `tasks` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tasks_old_backup` +-- + +DROP TABLE IF EXISTS `tasks_old_backup`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tasks_old_backup` ( + `task_id` int(11) NOT NULL AUTO_INCREMENT, + `category` varchar(255) NOT NULL, + `subcategory` varchar(255) DEFAULT NULL, + `task_name` varchar(255) NOT NULL, + `description` text DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + PRIMARY KEY (`task_id`) +) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tasks_old_backup` +-- + +LOCK TABLES `tasks_old_backup` WRITE; +/*!40000 ALTER TABLE `tasks_old_backup` DISABLE KEYS */; +INSERT INTO `tasks_old_backup` VALUES +(1,'Base','Fabrication','용접','...','2025-04-15 10:41:43','2025-04-15 10:41:43'), +(3,'Vessel','MI and Marking','Marking','..','2025-04-15 22:25:58','2025-04-15 22:25:58'), +(4,'Vessel','Cutting','자재 커팅','..','2025-04-15 22:26:17','2025-04-15 22:26:17'), +(5,'Vessel','Fabrication','용접','..','2025-04-15 22:26:43','2025-04-15 22:26:43'), +(7,'PKG','Pipe Pre-Fabrication','취부&용접','배관사 1명\n용접사 1명','2025-04-15 22:37:14','2025-04-15 22:37:14'), +(8,'PKG','1st Piping Assembly','1차 조립','.','2025-04-15 22:38:49','2025-04-15 22:38:49'), +(9,'PKG','Re-Assembly','재조립','.','2025-04-15 22:39:18','2025-04-15 22:39:18'), +(13,'작업지원','구매팀','.','.','2025-04-16 03:03:40','2025-04-16 03:03:40'), +(14,'기타','시설설비제작','.','.','2025-04-16 03:30:53','2025-04-16 03:30:53'), +(15,'기타','휴가/연차/휴무','.','.','2025-04-16 05:18:13','2025-04-16 05:18:13'), +(16,'PKG','제품설치','설치작업','Skid, 용기 등 설치','2025-04-29 04:39:36','2025-04-29 04:39:36'), +(18,'작업지원','품질팀','test지원','.','2025-06-25 07:07:08','2025-06-25 07:07:08'); +/*!40000 ALTER TABLE `tasks_old_backup` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_safety_checks` +-- + +DROP TABLE IF EXISTS `tbm_safety_checks`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_safety_checks` ( + `check_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `check_category` varchar(50) NOT NULL COMMENT '카테고리 (장비, PPE, 환경 등)', + `check_type` enum('basic','weather','task') DEFAULT 'basic', + `weather_condition` varchar(50) DEFAULT NULL, + `task_id` int(10) unsigned DEFAULT NULL, + `check_item` varchar(200) NOT NULL COMMENT '체크 항목', + `description` text DEFAULT NULL COMMENT '설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_required` tinyint(1) DEFAULT 1 COMMENT '필수 체크 여부', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`check_id`), + KEY `tbm_safety_checks_check_category_index` (`check_category`), + KEY `tbm_safety_checks_check_type_index` (`check_type`), + KEY `tbm_safety_checks_weather_condition_index` (`weather_condition`), + KEY `tbm_safety_checks_task_id_index` (`task_id`) +) ENGINE=InnoDB AUTO_INCREMENT=41 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_safety_checks` +-- + +LOCK TABLES `tbm_safety_checks` WRITE; +/*!40000 ALTER TABLE `tbm_safety_checks` DISABLE KEYS */; +INSERT INTO `tbm_safety_checks` VALUES +(1,'PPE','basic',NULL,NULL,'안전모 착용 확인',NULL,1,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(2,'PPE','basic',NULL,NULL,'안전화 착용 확인',NULL,2,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(3,'PPE','basic',NULL,NULL,'안전조끼 착용 확인',NULL,3,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(4,'PPE','basic',NULL,NULL,'안전벨트 착용 확인 (고소작업 시)',NULL,4,0,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(5,'PPE','basic',NULL,NULL,'보안경/마스크 착용 확인',NULL,5,0,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(6,'EQUIPMENT','basic',NULL,NULL,'작업 도구 점검 완료',NULL,10,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(7,'EQUIPMENT','basic',NULL,NULL,'전동공구 안전 점검',NULL,11,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(8,'EQUIPMENT','basic',NULL,NULL,'사다리/비계 안전 확인',NULL,12,0,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(9,'EQUIPMENT','basic',NULL,NULL,'차량/중장비 점검 완료',NULL,13,0,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(10,'ENVIRONMENT','basic',NULL,NULL,'작업 장소 정리정돈 확인',NULL,20,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(11,'ENVIRONMENT','basic',NULL,NULL,'위험 구역 표시 확인',NULL,21,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(12,'ENVIRONMENT','basic',NULL,NULL,'기상 상태 확인 (우천, 강풍 등)',NULL,22,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(13,'ENVIRONMENT','basic',NULL,NULL,'작업 동선 안전 확인',NULL,23,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(14,'EMERGENCY','basic',NULL,NULL,'비상연락망 공유 완료',NULL,30,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(15,'EMERGENCY','basic',NULL,NULL,'소화기 위치 확인',NULL,31,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(16,'EMERGENCY','basic',NULL,NULL,'응급처치 키트 위치 확인',NULL,32,1,1,'2026-01-20 06:30:51','2026-01-20 06:30:51'), +(17,'WEATHER','weather','rain',NULL,'우의/우산 준비 확인','비 오는 날 우의 또는 우산 준비 여부',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(18,'WEATHER','weather','rain',NULL,'미끄럼 방지 조치 확인','빗물로 인한 미끄러움 방지 조치',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(19,'WEATHER','weather','rain',NULL,'전기 작업 중단 여부 확인','우천 시 전기 작업 중단 필요성 확인',3,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(20,'WEATHER','weather','rain',NULL,'배수 상태 확인','작업장 배수 상태 점검',4,0,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(21,'WEATHER','weather','snow',NULL,'제설 작업 완료 확인','작업장 주변 제설 작업 완료 여부',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(22,'WEATHER','weather','snow',NULL,'동파 방지 조치 확인','배관 및 설비 동파 방지 조치',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(23,'WEATHER','weather','snow',NULL,'미끄럼 방지 모래/염화칼슘 비치','미끄럼 방지를 위한 모래 또는 염화칼슘 비치',3,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(24,'WEATHER','weather','heat',NULL,'그늘막/휴게소 확보','무더위 휴식을 위한 그늘막 또는 휴게소 확보',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(25,'WEATHER','weather','heat',NULL,'음료수/식염 포도당 비치','열사병 예방을 위한 음료수 및 염분 보충제 비치',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(26,'WEATHER','weather','heat',NULL,'무더위 휴식 시간 확보','10~15시 사이 충분한 휴식 시간 확보',3,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(27,'WEATHER','weather','heat',NULL,'작업자 건강 상태 확인','열사병 증상 체크 및 건강 상태 확인',4,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(28,'WEATHER','weather','cold',NULL,'방한복/방한장갑 착용 확인','동상 방지를 위한 방한복 및 방한장갑 착용',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(29,'WEATHER','weather','cold',NULL,'난방시설 가동 확인','휴게 공간 난방시설 가동 상태 확인',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(30,'WEATHER','weather','cold',NULL,'온열 음료 비치','체온 유지를 위한 따뜻한 음료 비치',3,0,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(31,'WEATHER','weather','wind',NULL,'고소 작업 중단 여부 확인','강풍 시 고소 작업 중단 필요성 확인',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(32,'WEATHER','weather','wind',NULL,'자재/장비 결박 확인','바람에 날릴 수 있는 자재 및 장비 고정',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(33,'WEATHER','weather','wind',NULL,'가설물 안전 점검','가설 구조물 및 비계 안전 상태 점검',3,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(34,'WEATHER','weather','wind',NULL,'크레인 작업 중단 여부 확인','강풍 시 크레인 작업 중단 필요성 확인',4,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(35,'WEATHER','weather','fog',NULL,'경광등/조명 확보','시정 확보를 위한 경광등 및 조명 설치',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(36,'WEATHER','weather','fog',NULL,'차량 운행 주의 안내','안개로 인한 차량 운행 주의 안내',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(37,'WEATHER','weather','fog',NULL,'작업 구역 표시 강화','시인성 확보를 위한 작업 구역 표시 강화',3,0,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(38,'WEATHER','weather','dust',NULL,'보호 마스크 착용 확인','KF94 이상 마스크 착용 여부 확인',1,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(39,'WEATHER','weather','dust',NULL,'실외 작업 시간 조정','미세먼지 농도에 따른 실외 작업 시간 조정',2,1,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'), +(40,'WEATHER','weather','dust',NULL,'호흡기 질환자 실내 배치','호흡기 질환 작업자 실내 작업 배치',3,0,1,'2026-02-02 01:44:54','2026-02-02 01:44:54'); +/*!40000 ALTER TABLE `tbm_safety_checks` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_safety_records` +-- + +DROP TABLE IF EXISTS `tbm_safety_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_safety_records` ( + `record_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL COMMENT 'TBM 세션 ID', + `check_id` int(10) unsigned NOT NULL COMMENT '체크 항목 ID', + `is_checked` tinyint(1) DEFAULT 0 COMMENT '체크 여부', + `notes` text DEFAULT NULL COMMENT '비고/특이사항', + `checked_by` int(11) DEFAULT NULL COMMENT '체크한 user_id', + `checked_at` timestamp NULL DEFAULT NULL COMMENT '체크 시간', + PRIMARY KEY (`record_id`), + UNIQUE KEY `tbm_safety_records_session_id_check_id_unique` (`session_id`,`check_id`), + KEY `tbm_safety_records_check_id_foreign` (`check_id`), + KEY `tbm_safety_records_checked_by_foreign` (`checked_by`), + CONSTRAINT `tbm_safety_records_check_id_foreign` FOREIGN KEY (`check_id`) REFERENCES `tbm_safety_checks` (`check_id`), + CONSTRAINT `tbm_safety_records_checked_by_foreign` FOREIGN KEY (`checked_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `tbm_safety_records_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_safety_records` +-- + +LOCK TABLES `tbm_safety_records` WRITE; +/*!40000 ALTER TABLE `tbm_safety_records` DISABLE KEYS */; +/*!40000 ALTER TABLE `tbm_safety_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_sessions` +-- + +DROP TABLE IF EXISTS `tbm_sessions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_sessions` ( + `session_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_date` date NOT NULL COMMENT 'TBM 날짜', + `leader_id` int(11) DEFAULT NULL, + `project_id` int(11) DEFAULT NULL COMMENT '프로젝트 ID', + `work_location` varchar(200) DEFAULT NULL COMMENT '작업 장소', + `status` enum('draft','completed','cancelled') DEFAULT 'draft' COMMENT '상태', + `end_time` time DEFAULT NULL COMMENT 'TBM 종료 시간', + `created_by` int(11) NOT NULL COMMENT '생성자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `work_type_id` int(11) DEFAULT NULL COMMENT '공정 ID (work_types 참조)', + `task_id` int(10) unsigned DEFAULT NULL COMMENT '작업 ID (tasks 참조)', + PRIMARY KEY (`session_id`), + KEY `tbm_sessions_session_date_leader_id_index` (`session_date`,`leader_id`), + KEY `tbm_sessions_project_id_foreign` (`project_id`), + KEY `tbm_sessions_created_by_foreign` (`created_by`), + KEY `tbm_sessions_work_type_id_index` (`work_type_id`), + KEY `tbm_sessions_task_id_index` (`task_id`), + KEY `tbm_sessions_leader_id_foreign` (`leader_id`), + CONSTRAINT `tbm_sessions_created_by_foreign` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `tbm_sessions_leader_id_foreign` FOREIGN KEY (`leader_id`) REFERENCES `workers` (`worker_id`) ON DELETE SET NULL, + CONSTRAINT `tbm_sessions_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE SET NULL, + CONSTRAINT `tbm_sessions_task_id_foreign` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`task_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_sessions_work_type_id_foreign` FOREIGN KEY (`work_type_id`) REFERENCES `work_types` (`id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=15 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_sessions` +-- + +LOCK TABLES `tbm_sessions` WRITE; +/*!40000 ALTER TABLE `tbm_sessions` DISABLE KEYS */; +/*!40000 ALTER TABLE `tbm_sessions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_team_assignments` +-- + +DROP TABLE IF EXISTS `tbm_team_assignments`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_team_assignments` ( + `assignment_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL COMMENT 'TBM 세션 ID', + `worker_id` int(11) NOT NULL COMMENT '팀원 worker_id', + `assigned_role` varchar(100) DEFAULT NULL COMMENT '역할/담당', + `work_detail` text DEFAULT NULL COMMENT '세부 작업 내용', + `is_present` tinyint(1) DEFAULT 1 COMMENT '출석 여부', + `absence_reason` text DEFAULT NULL COMMENT '결석 사유', + `assigned_at` timestamp NOT NULL DEFAULT current_timestamp(), + `project_id` int(11) DEFAULT NULL COMMENT '작업자별 프로젝트 ID', + `work_type_id` int(11) DEFAULT NULL COMMENT '작업자별 공정 ID', + `task_id` int(10) unsigned DEFAULT NULL COMMENT '작업자별 작업 ID', + `workplace_category_id` int(10) unsigned DEFAULT NULL COMMENT '작업자별 작업장 대분류 (공장)', + `workplace_id` int(10) unsigned DEFAULT NULL COMMENT '작업자별 작업장 ID', + PRIMARY KEY (`assignment_id`), + UNIQUE KEY `tbm_team_assignments_session_id_worker_id_unique` (`session_id`,`worker_id`), + KEY `tbm_team_assignments_worker_id_foreign` (`worker_id`), + KEY `tbm_team_assignments_project_id_foreign` (`project_id`), + KEY `tbm_team_assignments_work_type_id_foreign` (`work_type_id`), + KEY `tbm_team_assignments_task_id_foreign` (`task_id`), + KEY `tbm_team_assignments_workplace_category_id_foreign` (`workplace_category_id`), + KEY `tbm_team_assignments_workplace_id_foreign` (`workplace_id`), + CONSTRAINT `tbm_team_assignments_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_team_assignments_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE, + CONSTRAINT `tbm_team_assignments_task_id_foreign` FOREIGN KEY (`task_id`) REFERENCES `tasks` (`task_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_team_assignments_work_type_id_foreign` FOREIGN KEY (`work_type_id`) REFERENCES `work_types` (`id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_team_assignments_worker_id_foreign` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `tbm_team_assignments_workplace_category_id_foreign` FOREIGN KEY (`workplace_category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `tbm_team_assignments_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=49 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_team_assignments` +-- + +LOCK TABLES `tbm_team_assignments` WRITE; +/*!40000 ALTER TABLE `tbm_team_assignments` DISABLE KEYS */; +/*!40000 ALTER TABLE `tbm_team_assignments` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `tbm_weather_records` +-- + +DROP TABLE IF EXISTS `tbm_weather_records`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `tbm_weather_records` ( + `record_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL, + `weather_date` date NOT NULL, + `temperature` decimal(4,1) DEFAULT NULL, + `humidity` int(11) DEFAULT NULL, + `wind_speed` decimal(4,1) DEFAULT NULL, + `precipitation` decimal(5,1) DEFAULT NULL, + `sky_condition` varchar(50) DEFAULT NULL, + `weather_condition` varchar(50) DEFAULT NULL, + `weather_conditions` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`weather_conditions`)), + `data_source` varchar(50) DEFAULT 'api', + `fetched_at` timestamp NULL DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`record_id`), + UNIQUE KEY `tbm_weather_records_session_id_unique` (`session_id`), + KEY `tbm_weather_records_weather_date_index` (`weather_date`), + CONSTRAINT `tbm_weather_records_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `tbm_weather_records` +-- + +LOCK TABLES `tbm_weather_records` WRITE; +/*!40000 ALTER TABLE `tbm_weather_records` DISABLE KEYS */; +INSERT INTO `tbm_weather_records` VALUES +(1,12,'2026-02-02',20.0,50,2.0,0.0,NULL,'clear','[\"clear\"]','api','2026-02-02 04:00:40','2026-02-02 04:00:40'); +/*!40000 ALTER TABLE `tbm_weather_records` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `team_handovers` +-- + +DROP TABLE IF EXISTS `team_handovers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `team_handovers` ( + `handover_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `session_id` int(10) unsigned NOT NULL COMMENT 'TBM 세션 ID', + `from_leader_id` int(11) NOT NULL COMMENT '인계자 worker_id', + `to_leader_id` int(11) NOT NULL COMMENT '인수자 worker_id', + `handover_date` date NOT NULL COMMENT '인계 날짜', + `handover_time` time DEFAULT NULL COMMENT '인계 시간', + `reason` enum('half_day','early_leave','emergency','other') NOT NULL COMMENT '인계 사유', + `handover_notes` text DEFAULT NULL COMMENT '인계 내용', + `worker_ids` text DEFAULT NULL COMMENT '인계하는 작업자 IDs (JSON array)', + `is_confirmed` tinyint(1) DEFAULT 0 COMMENT '인수 확인 여부', + `confirmed_at` timestamp NULL DEFAULT NULL COMMENT '인수 확인 시간', + `confirmed_by` int(11) DEFAULT NULL COMMENT '인수 확인자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`handover_id`), + KEY `team_handovers_session_id_handover_date_index` (`session_id`,`handover_date`), + KEY `team_handovers_from_leader_id_foreign` (`from_leader_id`), + KEY `team_handovers_to_leader_id_foreign` (`to_leader_id`), + KEY `team_handovers_confirmed_by_foreign` (`confirmed_by`), + CONSTRAINT `team_handovers_confirmed_by_foreign` FOREIGN KEY (`confirmed_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `team_handovers_from_leader_id_foreign` FOREIGN KEY (`from_leader_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `team_handovers_session_id_foreign` FOREIGN KEY (`session_id`) REFERENCES `tbm_sessions` (`session_id`) ON DELETE CASCADE, + CONSTRAINT `team_handovers_to_leader_id_foreign` FOREIGN KEY (`to_leader_id`) REFERENCES `workers` (`worker_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `team_handovers` +-- + +LOCK TABLES `team_handovers` WRITE; +/*!40000 ALTER TABLE `team_handovers` DISABLE KEYS */; +/*!40000 ALTER TABLE `team_handovers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `uploaded_documents` +-- + +DROP TABLE IF EXISTS `uploaded_documents`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `uploaded_documents` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `title` varchar(255) NOT NULL, + `tags` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `original_name` varchar(255) DEFAULT NULL, + `stored_name` varchar(255) NOT NULL, + `file_path` varchar(500) DEFAULT NULL, + `file_type` varchar(50) DEFAULT NULL, + `file_size` int(11) DEFAULT NULL, + `submitted_by` varchar(100) DEFAULT NULL, + `dt_imported` tinyint(1) DEFAULT 0, + `dt_uuid` varchar(100) DEFAULT NULL, + `of_task_created` tinyint(1) DEFAULT 0, + `created_at` datetime DEFAULT current_timestamp(), + `updated_at` datetime DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `uploaded_documents` +-- + +LOCK TABLES `uploaded_documents` WRITE; +/*!40000 ALTER TABLE `uploaded_documents` DISABLE KEYS */; +/*!40000 ALTER TABLE `uploaded_documents` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user_page_access` +-- + +DROP TABLE IF EXISTS `user_page_access`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user_page_access` ( + `user_id` int(11) NOT NULL, + `page_id` int(10) unsigned NOT NULL, + `can_access` tinyint(1) DEFAULT 1, + `granted_at` timestamp NOT NULL DEFAULT current_timestamp(), + `granted_by` int(11) DEFAULT NULL, + PRIMARY KEY (`user_id`,`page_id`), + KEY `user_page_access_page_id_foreign` (`page_id`), + KEY `user_page_access_granted_by_foreign` (`granted_by`), + CONSTRAINT `user_page_access_granted_by_foreign` FOREIGN KEY (`granted_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, + CONSTRAINT `user_page_access_page_id_foreign` FOREIGN KEY (`page_id`) REFERENCES `pages` (`id`) ON DELETE CASCADE, + CONSTRAINT `user_page_access_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user_page_access` +-- + +LOCK TABLES `user_page_access` WRITE; +/*!40000 ALTER TABLE `user_page_access` DISABLE KEYS */; +INSERT INTO `user_page_access` VALUES +(1,26,1,'2026-01-28 05:55:06',1), +(1,27,1,'2026-01-28 05:55:06',1), +(1,29,1,'2026-01-28 05:55:06',1), +(27,12,1,'2026-02-02 01:01:57',NULL), +(27,13,1,'2026-02-02 01:01:57',NULL), +(27,14,0,'2026-02-02 01:01:57',NULL), +(27,15,0,'2026-02-02 01:01:57',NULL), +(27,16,0,'2026-02-02 01:01:57',NULL), +(27,18,0,'2026-02-02 01:01:57',NULL), +(27,19,0,'2026-02-02 01:01:57',NULL), +(27,20,0,'2026-02-02 01:01:57',NULL), +(27,21,0,'2026-02-02 01:01:57',NULL), +(27,22,1,'2026-02-02 01:01:57',NULL), +(27,25,0,'2026-02-02 01:01:57',NULL), +(27,26,0,'2026-02-02 01:01:57',NULL), +(27,27,0,'2026-02-02 01:01:57',NULL), +(27,29,0,'2026-02-02 01:01:57',NULL), +(27,34,0,'2026-02-02 01:01:57',NULL), +(27,35,0,'2026-02-02 01:01:57',NULL), +(27,36,0,'2026-02-02 01:01:57',NULL), +(27,37,0,'2026-02-02 01:01:57',NULL), +(27,38,0,'2026-02-02 01:01:57',NULL), +(27,39,0,'2026-02-02 01:01:57',NULL), +(27,40,0,'2026-02-02 01:01:57',NULL), +(27,41,0,'2026-02-02 01:01:57',NULL), +(27,42,0,'2026-02-02 01:01:57',NULL), +(27,43,0,'2026-02-02 01:01:57',NULL); +/*!40000 ALTER TABLE `user_page_access` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `user_permissions` +-- + +DROP TABLE IF EXISTS `user_permissions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `user_permissions` ( + `user_id` int(10) unsigned NOT NULL, + `permission_id` int(10) unsigned NOT NULL, + PRIMARY KEY (`user_id`,`permission_id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `user_permissions` +-- + +LOCK TABLES `user_permissions` WRITE; +/*!40000 ALTER TABLE `user_permissions` DISABLE KEYS */; +/*!40000 ALTER TABLE `user_permissions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `users` +-- + +DROP TABLE IF EXISTS `users`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `users` ( + `user_id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(100) NOT NULL, + `password` varchar(255) NOT NULL, + `_role_old` varchar(30) DEFAULT NULL, + `created_at` timestamp NULL DEFAULT current_timestamp(), + `_access_level_old` varchar(30) DEFAULT NULL, + `worker_id` int(11) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `last_login_at` datetime DEFAULT NULL, + `password_changed_at` datetime DEFAULT NULL, + `failed_login_attempts` int(11) DEFAULT 0, + `locked_until` datetime DEFAULT NULL, + `name` varchar(50) DEFAULT NULL, + `email` varchar(255) DEFAULT NULL, + `role_id` int(10) unsigned DEFAULT NULL, + `updated_at` timestamp NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`user_id`), + UNIQUE KEY `username` (`username`), + UNIQUE KEY `email` (`email`), + KEY `fk_worker` (`worker_id`), + KEY `idx_username` (`username`), + KEY `idx_active_users` (`is_active`,`_access_level_old`), + KEY `users_role_id_foreign` (`role_id`), + CONSTRAINT `fk_worker` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`), + CONSTRAINT `users_role_id_foreign` FOREIGN KEY (`role_id`) REFERENCES `roles` (`id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `users` +-- + +LOCK TABLES `users` WRITE; +/*!40000 ALTER TABLE `users` DISABLE KEYS */; +INSERT INTO `users` VALUES +(1,'hyungi','$2b$10$lwSfKipx0fQ.9nfMUBmzt.WXzerdxuT5MVX4b3YhFeHxyYlUjM7bi',NULL,'2025-05-06 05:03:02','system',NULL,1,'2026-02-05 22:40:53','2025-05-06 05:03:02',0,NULL,'안현기',NULL,2,'2026-02-05 22:40:53'), +(3,'김두수','$2a$10$z3i2EVOotRFBj.KHzx5LQOKlXD0QHLNFEvJcd6FlO6/1TCYGk6SSu',NULL,'2025-06-07 23:48:35',NULL,1,1,'2026-02-03 05:43:08','2025-06-15 07:40:39',0,NULL,'김두수',NULL,4,'2026-02-03 21:44:25'), +(5,'임영규','$2a$10$66ps/MEEi4BVABfJc5P0y.yCap09NhTMyd1A/7rFVxESytQGlB3wC',NULL,'2025-06-15 07:41:02',NULL,2,1,'2025-12-10 15:55:48','2025-06-15 07:41:02',0,NULL,'임영규',NULL,4,'2026-02-03 21:44:32'), +(6,'반치원','$2a$10$jcn6f7flRLZlr5yKQcXDIePodRK0rsM4deNnNGjuOlredeTVsRYZ6',NULL,'2025-06-15 07:41:32',NULL,3,1,'2025-11-05 01:56:13','2025-06-15 07:41:32',5,'2025-11-25 16:22:46','반치원',NULL,4,'2026-02-03 21:44:36'), +(7,'khahn','$2a$10$vQcJ3C37TPGweYF8rok2quzN2DK9lgxiqDAXV38vvPVjRdz3l6M8y',NULL,'2025-11-05 02:18:15',NULL,NULL,1,'2025-11-05 15:56:23',NULL,0,NULL,'khahn',NULL,2,'2025-11-05 06:56:23'); +/*!40000 ALTER TABLE `users` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vacation_balance_details` +-- + +DROP TABLE IF EXISTS `vacation_balance_details`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vacation_balance_details` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `vacation_type_id` int(10) unsigned NOT NULL COMMENT '휴가 유형 ID', + `year` int(11) NOT NULL COMMENT '연도', + `total_days` decimal(4,1) DEFAULT 0.0 COMMENT '총 발생 일수', + `used_days` decimal(4,1) DEFAULT 0.0 COMMENT '사용 일수', + `notes` text DEFAULT NULL COMMENT '비고', + `created_by` int(11) NOT NULL COMMENT '생성자 ID', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `remaining_days` decimal(4,1) GENERATED ALWAYS AS (`total_days` - `used_days`) STORED COMMENT '잔여 일수', + PRIMARY KEY (`id`), + UNIQUE KEY `unique_worker_vacation_year` (`worker_id`,`vacation_type_id`,`year`), + KEY `idx_worker_year` (`worker_id`,`year`), + KEY `idx_vacation_type` (`vacation_type_id`), + KEY `vacation_balance_details_created_by_foreign` (`created_by`), + CONSTRAINT `vacation_balance_details_created_by_foreign` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `vacation_balance_details_vacation_type_id_foreign` FOREIGN KEY (`vacation_type_id`) REFERENCES `vacation_types` (`id`), + CONSTRAINT `vacation_balance_details_worker_id_foreign` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=61 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vacation_balance_details` +-- + +LOCK TABLES `vacation_balance_details` WRITE; +/*!40000 ALTER TABLE `vacation_balance_details` DISABLE KEYS */; +INSERT INTO `vacation_balance_details` VALUES +(1,1,1,2026,17.0,0.0,NULL,1,'2026-01-19 01:40:31','2026-02-05 06:17:09',17.0), +(2,2,1,2026,17.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',17.0), +(3,4,1,2026,17.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',17.0), +(4,5,1,2026,16.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',16.0), +(5,6,1,2026,17.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',17.0), +(6,7,1,2026,15.0,0.0,'Migrated from worker_vacation_balance',1,'2026-01-19 01:40:56','2026-01-19 01:40:56',15.0), +(7,8,1,2026,16.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',16.0), +(8,9,1,2026,15.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',15.0), +(9,10,1,2026,15.0,0.0,NULL,1,'2026-01-19 01:40:56','2026-02-05 06:17:09',15.0), +(10,12,1,2026,15.0,0.0,'Migrated from worker_vacation_balance',1,'2026-01-19 01:40:56','2026-01-19 01:40:56',15.0), +(14,3,1,2026,16.0,0.0,NULL,1,'2026-02-05 06:12:39','2026-02-05 06:17:09',16.0), +(16,11,1,2026,11.0,0.0,NULL,1,'2026-02-05 06:12:39','2026-02-05 06:17:09',11.0), +(31,1,6,2026,2.3,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',2.3), +(33,1,7,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0), +(34,6,6,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0), +(36,6,7,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0), +(37,9,6,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(39,9,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(40,3,6,2026,1.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',1.0), +(42,3,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(43,2,6,2026,1.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',1.0), +(45,2,7,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0), +(46,11,6,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(48,11,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(49,10,6,2026,-0.8,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',-0.8), +(51,10,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(52,8,6,2026,2.3,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',2.3), +(54,8,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(55,5,6,2026,2.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',2.0), +(57,5,7,2026,0.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.0), +(58,4,6,2026,0.8,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',0.8), +(60,4,7,2026,3.0,0.0,NULL,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',3.0); +/*!40000 ALTER TABLE `vacation_balance_details` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vacation_requests` +-- + +DROP TABLE IF EXISTS `vacation_requests`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vacation_requests` ( + `request_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '휴가 신청 ID', + `worker_id` int(11) NOT NULL COMMENT '작업자 ID', + `vacation_type_id` int(10) unsigned NOT NULL COMMENT '휴가 유형 ID', + `start_date` date NOT NULL COMMENT '휴가 시작일', + `end_date` date NOT NULL COMMENT '휴가 종료일', + `days_used` decimal(4,1) NOT NULL COMMENT '사용 일수 (0.5일 단위)', + `reason` text DEFAULT NULL COMMENT '휴가 사유', + `status` enum('pending','approved','rejected') NOT NULL DEFAULT 'pending' COMMENT '승인 상태: pending(대기), approved(승인), rejected(거부)', + `requested_by` int(11) NOT NULL COMMENT '신청자 user_id', + `reviewed_by` int(11) DEFAULT NULL COMMENT '승인/거부자 user_id', + `reviewed_at` timestamp NULL DEFAULT NULL COMMENT '승인/거부 일시', + `review_note` text DEFAULT NULL COMMENT '승인/거부 메모', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '신청 일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정 일시', + PRIMARY KEY (`request_id`), + KEY `vacation_requests_vacation_type_id_foreign` (`vacation_type_id`), + KEY `vacation_requests_requested_by_foreign` (`requested_by`), + KEY `vacation_requests_reviewed_by_foreign` (`reviewed_by`), + KEY `idx_vacation_requests_worker` (`worker_id`), + KEY `idx_vacation_requests_status` (`status`), + KEY `idx_vacation_requests_dates` (`start_date`,`end_date`), + CONSTRAINT `vacation_requests_requested_by_foreign` FOREIGN KEY (`requested_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `vacation_requests_reviewed_by_foreign` FOREIGN KEY (`reviewed_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, + CONSTRAINT `vacation_requests_vacation_type_id_foreign` FOREIGN KEY (`vacation_type_id`) REFERENCES `vacation_types` (`id`), + CONSTRAINT `vacation_requests_worker_id_foreign` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vacation_requests` +-- + +LOCK TABLES `vacation_requests` WRITE; +/*!40000 ALTER TABLE `vacation_requests` DISABLE KEYS */; +/*!40000 ALTER TABLE `vacation_requests` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `vacation_types` +-- + +DROP TABLE IF EXISTS `vacation_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `vacation_types` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `type_code` varchar(20) NOT NULL COMMENT '휴가 코드', + `type_name` varchar(50) NOT NULL COMMENT '휴가 이름', + `deduct_days` decimal(3,1) DEFAULT 1.0 COMMENT '차감 일수', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + `is_special` tinyint(1) DEFAULT 0 COMMENT '특별 휴가 여부 (장기근속, 출산 등)', + `priority` int(11) DEFAULT 99 COMMENT '차감 우선순위 (낮을수록 먼저 차감)', + `description` text DEFAULT NULL COMMENT '휴가 설명', + `is_system` tinyint(1) DEFAULT 1 COMMENT '시스템 기본 휴가 (삭제 불가)', + PRIMARY KEY (`id`), + UNIQUE KEY `vacation_types_type_code_unique` (`type_code`) +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `vacation_types` +-- + +LOCK TABLES `vacation_types` WRITE; +/*!40000 ALTER TABLE `vacation_types` DISABLE KEYS */; +INSERT INTO `vacation_types` VALUES +(1,'ANNUAL_FULL','연차',1.0,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,1,'하루 전체 연차',1), +(2,'ANNUAL_HALF','반차',0.5,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,2,'반일 연차',1), +(3,'ANNUAL_QUARTER','반반차',0.3,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,3,'1/4일 연차',1), +(4,'SICK_FULL','병가',1.0,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,4,'하루 전체 병가',1), +(5,'SICK_HALF','반일병가',0.5,1,'2025-11-03 06:48:45','2025-11-03 06:48:45',0,5,'반일 병가',1), +(6,'CARRYOVER','이월',1.0,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',1,1,NULL,0), +(7,'LONG_SERVICE','장기근속',1.0,1,'2026-02-05 06:17:09','2026-02-05 06:17:09',1,3,NULL,0); +/*!40000 ALTER TABLE `vacation_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `visit_purpose_types` +-- + +DROP TABLE IF EXISTS `visit_purpose_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `visit_purpose_types` ( + `purpose_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '방문 목적 ID', + `purpose_name` varchar(100) NOT NULL COMMENT '방문 목적명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`purpose_id`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `visit_purpose_types` +-- + +LOCK TABLES `visit_purpose_types` WRITE; +/*!40000 ALTER TABLE `visit_purpose_types` DISABLE KEYS */; +INSERT INTO `visit_purpose_types` VALUES +(1,'외주작업',1,1,'2026-01-29 05:26:17'), +(2,'검사',2,1,'2026-01-29 05:26:17'), +(3,'견학',3,1,'2026-01-29 05:26:17'), +(4,'기타',99,1,'2026-01-29 05:26:17'); +/*!40000 ALTER TABLE `visit_purpose_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `weather_conditions` +-- + +DROP TABLE IF EXISTS `weather_conditions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `weather_conditions` ( + `condition_code` varchar(50) NOT NULL, + `condition_name` varchar(100) NOT NULL, + `description` text DEFAULT NULL, + `icon` varchar(50) DEFAULT NULL, + `temp_threshold_min` decimal(4,1) DEFAULT NULL, + `temp_threshold_max` decimal(4,1) DEFAULT NULL, + `wind_threshold` decimal(4,1) DEFAULT NULL, + `precip_threshold` decimal(5,1) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `display_order` int(11) DEFAULT 0, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`condition_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `weather_conditions` +-- + +LOCK TABLES `weather_conditions` WRITE; +/*!40000 ALTER TABLE `weather_conditions` DISABLE KEYS */; +INSERT INTO `weather_conditions` VALUES +('clear','맑음','맑은 날씨','sunny',NULL,NULL,NULL,NULL,1,1,'2026-02-02 01:44:54'), +('cold','한파','기온 영하 10도 이하','cold',NULL,-10.0,NULL,NULL,1,5,'2026-02-02 01:44:54'), +('dust','미세먼지','미세먼지 나쁨 이상','dusty',NULL,NULL,NULL,NULL,1,8,'2026-02-02 01:44:54'), +('fog','안개','시정 1km 미만','foggy',NULL,NULL,NULL,NULL,1,7,'2026-02-02 01:44:54'), +('heat','폭염','기온 35도 이상','hot',35.0,NULL,NULL,NULL,1,4,'2026-02-02 01:44:54'), +('rain','비','비 오는 날씨','rainy',NULL,NULL,NULL,0.1,1,2,'2026-02-02 01:44:54'), +('snow','눈','눈 오는 날씨','snowy',NULL,NULL,NULL,NULL,1,3,'2026-02-02 01:44:54'), +('wind','강풍','풍속 10m/s 이상','windy',NULL,NULL,10.0,NULL,1,6,'2026-02-02 01:44:54'); +/*!40000 ALTER TABLE `weather_conditions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_attendance_types` +-- + +DROP TABLE IF EXISTS `work_attendance_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_attendance_types` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `type_code` varchar(20) NOT NULL COMMENT '유형 코드', + `type_name` varchar(50) NOT NULL COMMENT '유형 이름', + `description` text DEFAULT NULL COMMENT '설명', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `work_attendance_types_type_code_unique` (`type_code`) +) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_attendance_types` +-- + +LOCK TABLES `work_attendance_types` WRITE; +/*!40000 ALTER TABLE `work_attendance_types` DISABLE KEYS */; +INSERT INTO `work_attendance_types` VALUES +(1,'REGULAR','정시근로','8시간 정규 근무',1,'2025-11-03 06:48:45','2025-11-03 06:48:45'), +(2,'OVERTIME','연장근로','8시간 초과 근무',1,'2025-11-03 06:48:45','2025-11-03 06:48:45'), +(3,'PARTIAL','부분근로','8시간 미만 근무',1,'2025-11-03 06:48:45','2025-11-03 06:48:45'), +(4,'VACATION','휴가근로','휴가와 함께하는 부분 근무',1,'2025-11-03 06:48:45','2025-11-03 06:48:45'); +/*!40000 ALTER TABLE `work_attendance_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_issue_reports` +-- + +DROP TABLE IF EXISTS `work_issue_reports`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_issue_reports` ( + `report_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '신고 ID', + `reporter_id` int(11) NOT NULL COMMENT '신고자 user_id', + `report_date` datetime DEFAULT current_timestamp() COMMENT '신고 일시', + `factory_category_id` int(10) unsigned DEFAULT NULL COMMENT '공장 카테고리 ID (지도 외 위치 시 null)', + `workplace_id` int(10) unsigned DEFAULT NULL COMMENT '작업장 ID (지도 외 위치 시 null)', + `custom_location` varchar(200) DEFAULT NULL COMMENT '기타 위치 (지도 외 선택 시)', + `tbm_session_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 TBM 세션', + `visit_request_id` int(10) unsigned DEFAULT NULL COMMENT '연결된 출입 신청', + `equipment_id` int(10) unsigned DEFAULT NULL COMMENT '관련 설비 ID', + `issue_category_id` int(10) unsigned NOT NULL COMMENT '신고 카테고리 ID', + `issue_item_id` int(10) unsigned DEFAULT NULL COMMENT '사전 정의 신고 항목 ID', + `additional_description` text DEFAULT NULL COMMENT '추가 설명', + `photo_path1` varchar(255) DEFAULT NULL COMMENT '사진 1', + `photo_path2` varchar(255) DEFAULT NULL COMMENT '사진 2', + `photo_path3` varchar(255) DEFAULT NULL COMMENT '사진 3', + `photo_path4` varchar(255) DEFAULT NULL COMMENT '사진 4', + `photo_path5` varchar(255) DEFAULT NULL COMMENT '사진 5', + `status` enum('reported','received','in_progress','completed','closed') DEFAULT 'reported' COMMENT '상태: 신고→접수→처리중→완료→종료', + `assigned_department` varchar(100) DEFAULT NULL COMMENT '담당 부서', + `assigned_user_id` int(11) DEFAULT NULL COMMENT '담당자 user_id', + `assigned_at` datetime DEFAULT NULL COMMENT '배정 일시', + `assigned_by` int(11) DEFAULT NULL COMMENT '배정자 user_id', + `resolution_notes` text DEFAULT NULL COMMENT '처리 내용', + `resolution_photo_path1` varchar(255) DEFAULT NULL COMMENT '처리 완료 사진 1', + `resolution_photo_path2` varchar(255) DEFAULT NULL COMMENT '처리 완료 사진 2', + `resolved_at` datetime DEFAULT NULL COMMENT '처리 완료 일시', + `resolved_by` int(11) DEFAULT NULL COMMENT '처리 완료자 user_id', + `modification_history` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '수정 이력 추적' CHECK (json_valid(`modification_history`)), + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`report_id`), + KEY `work_issue_reports_workplace_id_foreign` (`workplace_id`), + KEY `work_issue_reports_issue_item_id_foreign` (`issue_item_id`), + KEY `work_issue_reports_assigned_by_foreign` (`assigned_by`), + KEY `work_issue_reports_resolved_by_foreign` (`resolved_by`), + KEY `idx_wir_reporter_id` (`reporter_id`), + KEY `idx_wir_status` (`status`), + KEY `idx_wir_report_date` (`report_date`), + KEY `idx_wir_workplace` (`factory_category_id`,`workplace_id`), + KEY `idx_wir_issue_category` (`issue_category_id`), + KEY `idx_wir_assigned_user` (`assigned_user_id`), + KEY `idx_wir_equipment_id` (`equipment_id`), + CONSTRAINT `fk_wir_equipment` FOREIGN KEY (`equipment_id`) REFERENCES `equipments` (`equipment_id`) ON DELETE SET NULL, + CONSTRAINT `work_issue_reports_assigned_by_foreign` FOREIGN KEY (`assigned_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_assigned_user_id_foreign` FOREIGN KEY (`assigned_user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_factory_category_id_foreign` FOREIGN KEY (`factory_category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_issue_category_id_foreign` FOREIGN KEY (`issue_category_id`) REFERENCES `issue_report_categories` (`category_id`) ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_issue_item_id_foreign` FOREIGN KEY (`issue_item_id`) REFERENCES `issue_report_items` (`item_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_reporter_id_foreign` FOREIGN KEY (`reporter_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_resolved_by_foreign` FOREIGN KEY (`resolved_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `work_issue_reports_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_issue_reports` +-- + +LOCK TABLES `work_issue_reports` WRITE; +/*!40000 ALTER TABLE `work_issue_reports` DISABLE KEYS */; +INSERT INTO `work_issue_reports` VALUES +(7,1,'2026-02-04 05:35:54',NULL,2,NULL,NULL,NULL,18,11,38,'전원인 안들어옴(Test)',NULL,NULL,NULL,NULL,NULL,'reported',NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'2026-02-04 05:35:54','2026-02-04 05:35:54'); +/*!40000 ALTER TABLE `work_issue_reports` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_issue_status_logs` +-- + +DROP TABLE IF EXISTS `work_issue_status_logs`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_issue_status_logs` ( + `log_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '로그 ID', + `report_id` int(10) unsigned NOT NULL COMMENT '신고 ID', + `previous_status` varchar(50) DEFAULT NULL COMMENT '이전 상태', + `new_status` varchar(50) NOT NULL COMMENT '새 상태', + `changed_by` int(11) NOT NULL COMMENT '변경자 user_id', + `change_reason` text DEFAULT NULL COMMENT '변경 사유', + `changed_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`log_id`), + KEY `work_issue_status_logs_changed_by_foreign` (`changed_by`), + KEY `idx_wisl_report_id` (`report_id`), + KEY `idx_wisl_changed_at` (`changed_at`), + CONSTRAINT `work_issue_status_logs_changed_by_foreign` FOREIGN KEY (`changed_by`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE, + CONSTRAINT `work_issue_status_logs_report_id_foreign` FOREIGN KEY (`report_id`) REFERENCES `work_issue_reports` (`report_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_issue_status_logs` +-- + +LOCK TABLES `work_issue_status_logs` WRITE; +/*!40000 ALTER TABLE `work_issue_status_logs` DISABLE KEYS */; +INSERT INTO `work_issue_status_logs` VALUES +(1,1,NULL,'reported',1,NULL,'2026-02-02 22:16:33'), +(2,2,NULL,'reported',1,NULL,'2026-02-02 22:44:48'), +(3,3,NULL,'reported',1,NULL,'2026-02-02 23:39:13'), +(4,4,NULL,'reported',1,NULL,'2026-02-03 00:10:10'), +(5,5,NULL,'reported',1,NULL,'2026-02-03 00:10:39'), +(6,6,NULL,'reported',1,NULL,'2026-02-03 00:11:29'); +/*!40000 ALTER TABLE `work_issue_status_logs` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_report_audit_log` +-- + +DROP TABLE IF EXISTS `work_report_audit_log`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_report_audit_log` ( + `log_id` int(11) NOT NULL AUTO_INCREMENT, + `action` enum('ADD_ACCUMULATE','DELETE_SINGLE','UPDATE','DELETE','CREATE','DELETE_BATCH') NOT NULL COMMENT '작업 유형', + `report_id` int(11) DEFAULT NULL COMMENT '관련 보고서 ID', + `old_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 전 값' CHECK (json_valid(`old_values`)), + `new_values` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL COMMENT '변경 후 값' CHECK (json_valid(`new_values`)), + `changed_by` int(11) NOT NULL COMMENT '변경자 ID', + `change_reason` varchar(500) DEFAULT NULL COMMENT '변경 사유', + `ip_address` varchar(45) DEFAULT NULL COMMENT 'IP 주소', + `user_agent` text DEFAULT NULL COMMENT '사용자 에이전트', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '변경 시간', + PRIMARY KEY (`log_id`), + KEY `idx_action_date` (`action`,`created_at`), + KEY `idx_changed_by` (`changed_by`), + KEY `idx_report_id` (`report_id`) +) ENGINE=InnoDB AUTO_INCREMENT=880 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_report_audit_log` +-- + +LOCK TABLES `work_report_audit_log` WRITE; +/*!40000 ALTER TABLE `work_report_audit_log` DISABLE KEYS */; +INSERT INTO `work_report_audit_log` VALUES +(1,'ADD_ACCUMULATE',12,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 02:56:12'), +(2,'DELETE_SINGLE',12,'{\"worker_name\":\"김두수\",\"project_name\":\"MP7 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-16 03:17:36'), +(3,'DELETE_SINGLE',11,'{\"worker_name\":\"김두수\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-16 03:17:39'), +(4,'DELETE_SINGLE',7,'{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-16 03:17:41'), +(5,'ADD_ACCUMULATE',13,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":1,\"my_total\":\"1.00\",\"grand_total\":1,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"1.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 03:18:37'), +(6,'DELETE_SINGLE',13,'{\"worker_name\":\"임영규\",\"project_name\":\"연차/휴무\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-16 03:19:23'), +(7,'ADD_ACCUMULATE',14,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(8,'ADD_ACCUMULATE',15,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(9,'ADD_ACCUMULATE',16,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(10,'ADD_ACCUMULATE',17,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(11,'ADD_ACCUMULATE',18,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(12,'ADD_ACCUMULATE',19,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:23'), +(13,'ADD_ACCUMULATE',20,NULL,'{\"report_date\":\"2025-06-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:10:47'), +(14,'ADD_ACCUMULATE',21,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(15,'ADD_ACCUMULATE',22,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(16,'ADD_ACCUMULATE',23,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(17,'ADD_ACCUMULATE',24,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(18,'ADD_ACCUMULATE',25,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(19,'ADD_ACCUMULATE',26,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:11:37'), +(20,'ADD_ACCUMULATE',27,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:07'), +(21,'ADD_ACCUMULATE',28,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:07'), +(22,'ADD_ACCUMULATE',29,NULL,'{\"report_date\":\"2025-06-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:07'), +(23,'ADD_ACCUMULATE',30,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(24,'ADD_ACCUMULATE',31,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(25,'ADD_ACCUMULATE',32,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(26,'ADD_ACCUMULATE',33,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(27,'ADD_ACCUMULATE',34,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(28,'ADD_ACCUMULATE',35,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:12:57'), +(29,'ADD_ACCUMULATE',36,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:13:56'), +(30,'ADD_ACCUMULATE',37,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:13:56'), +(31,'ADD_ACCUMULATE',38,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:13:56'), +(32,'ADD_ACCUMULATE',39,NULL,'{\"report_date\":\"2025-06-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":null,\"hours\":\"8.00\"}]}',1,'누적 추가 by hyungi - 삭제 없음',NULL,NULL,'2025-06-16 05:13:56'), +(33,'ADD_ACCUMULATE',40,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:12:01'), +(34,'ADD_ACCUMULATE',41,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:12:01'), +(35,'ADD_ACCUMULATE',42,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:12:01'), +(36,'ADD_ACCUMULATE',43,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:12:01'), +(37,'DELETE_SINGLE',42,'{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-16 06:12:33'), +(38,'ADD_ACCUMULATE',44,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:13:02'), +(39,'ADD_ACCUMULATE',45,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:13:50'), +(40,'DELETE_SINGLE',41,'{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-16 06:14:48'), +(41,'ADD_ACCUMULATE',46,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-16 06:15:22'), +(42,'DELETE_SINGLE',1,'{\"worker_name\":\"김두수\",\"project_name\":\"25년 안전보건시설설비\",\"work_hours\":\"1.00\",\"report_date\":\"2025-06-01T00:00:00.000Z\"}',NULL,1,'개별 항목 삭제',NULL,NULL,'2025-06-16 06:20:38'), +(43,'ADD_ACCUMULATE',48,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 06:46:44'), +(44,'ADD_ACCUMULATE',49,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 06:46:44'), +(45,'ADD_ACCUMULATE',50,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 06:46:44'), +(46,'DELETE_SINGLE',49,'{\"worker_name\":\"박현수\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-16T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-16 06:47:54'), +(47,'ADD_ACCUMULATE',51,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-16 06:48:29'), +(48,'ADD_ACCUMULATE',52,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-16 06:50:09'), +(49,'ADD_ACCUMULATE',54,NULL,'{\"report_date\":\"2025-06-16\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-16 06:50:09'), +(50,'ADD_ACCUMULATE',56,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-17 08:23:41'), +(51,'ADD_ACCUMULATE',58,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-17 08:23:41'), +(52,'ADD_ACCUMULATE',60,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-17 08:24:33'), +(53,'ADD_ACCUMULATE',62,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-17 08:24:33'), +(54,'ADD_ACCUMULATE',64,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:24:44'), +(55,'ADD_ACCUMULATE',65,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:25:24'), +(56,'DELETE_SINGLE',64,'{\"worker_name\":\"황인용\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"4.00\",\"report_date\":\"2025-06-17T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-06-17 08:26:17'), +(57,'ADD_ACCUMULATE',66,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:27:06'), +(58,'ADD_ACCUMULATE',67,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:27:06'), +(59,'ADD_ACCUMULATE',68,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:31:06'), +(60,'ADD_ACCUMULATE',69,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:31:06'), +(61,'ADD_ACCUMULATE',70,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:31:06'), +(62,'ADD_ACCUMULATE',71,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:33:06'), +(63,'ADD_ACCUMULATE',72,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:33:06'), +(64,'ADD_ACCUMULATE',73,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-17 08:33:06'), +(65,'ADD_ACCUMULATE',74,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-17 08:34:11'), +(66,'ADD_ACCUMULATE',76,NULL,'{\"report_date\":\"2025-06-17\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-17 08:34:11'), +(67,'ADD_ACCUMULATE',78,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:40:27'), +(68,'ADD_ACCUMULATE',79,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:40:27'), +(69,'ADD_ACCUMULATE',80,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:40:27'), +(70,'ADD_ACCUMULATE',81,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:41:02'), +(71,'ADD_ACCUMULATE',82,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:41:03'), +(72,'ADD_ACCUMULATE',83,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:41:03'), +(73,'ADD_ACCUMULATE',84,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-18 08:41:45'), +(74,'ADD_ACCUMULATE',86,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-18 08:47:55'), +(75,'ADD_ACCUMULATE',88,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-18 08:47:55'), +(76,'ADD_ACCUMULATE',90,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-18 08:50:19'), +(77,'ADD_ACCUMULATE',92,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-18 08:50:19'), +(78,'ADD_ACCUMULATE',94,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-18 08:50:19'), +(79,'ADD_ACCUMULATE',96,NULL,'{\"report_date\":\"2025-06-18\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-18 09:00:17'), +(80,'ADD_ACCUMULATE',98,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-19 06:37:59'), +(81,'ADD_ACCUMULATE',99,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-19 06:37:59'), +(82,'ADD_ACCUMULATE',100,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-19 06:59:36'), +(83,'ADD_ACCUMULATE',101,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-19 06:59:36'), +(84,'ADD_ACCUMULATE',102,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-19 06:59:36'), +(85,'ADD_ACCUMULATE',103,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(86,'ADD_ACCUMULATE',105,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(87,'ADD_ACCUMULATE',107,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(88,'ADD_ACCUMULATE',109,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(89,'ADD_ACCUMULATE',111,NULL,'{\"report_date\":\"2025-06-19\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-19 07:01:02'), +(90,'ADD_ACCUMULATE',113,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:01'), +(91,'ADD_ACCUMULATE',115,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:01'), +(92,'ADD_ACCUMULATE',117,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:01'), +(93,'ADD_ACCUMULATE',119,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:02'), +(94,'ADD_ACCUMULATE',121,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:02'), +(95,'ADD_ACCUMULATE',123,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-20 06:44:02'), +(96,'ADD_ACCUMULATE',125,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-20 06:45:30'), +(97,'ADD_ACCUMULATE',126,NULL,'{\"report_date\":\"2025-06-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-20 06:45:31'), +(98,'ADD_ACCUMULATE',127,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-23 06:42:58'), +(99,'ADD_ACCUMULATE',128,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-23 06:42:58'), +(100,'ADD_ACCUMULATE',129,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(101,'ADD_ACCUMULATE',131,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(102,'ADD_ACCUMULATE',133,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(103,'ADD_ACCUMULATE',135,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(104,'ADD_ACCUMULATE',137,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(105,'ADD_ACCUMULATE',139,NULL,'{\"report_date\":\"2025-06-23\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-23 06:51:28'), +(106,'ADD_ACCUMULATE',141,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-24 11:10:32'), +(107,'ADD_ACCUMULATE',142,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-24 11:10:32'), +(108,'ADD_ACCUMULATE',143,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(109,'ADD_ACCUMULATE',145,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(110,'ADD_ACCUMULATE',147,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(111,'ADD_ACCUMULATE',149,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(112,'ADD_ACCUMULATE',151,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(113,'ADD_ACCUMULATE',153,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:00'), +(114,'ADD_ACCUMULATE',155,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:05'), +(115,'ADD_ACCUMULATE',157,NULL,'{\"report_date\":\"2025-06-24\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-24 11:11:05'), +(116,'ADD_ACCUMULATE',159,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-25 11:08:04'), +(117,'ADD_ACCUMULATE',161,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-25 11:08:05'), +(118,'ADD_ACCUMULATE',163,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-25 11:11:30'), +(119,'ADD_ACCUMULATE',164,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-25 11:11:30'), +(120,'ADD_ACCUMULATE',165,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-25 11:11:30'), +(121,'ADD_ACCUMULATE',166,NULL,'{\"report_date\":\"2025-06-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-25 11:11:30'), +(122,'ADD_ACCUMULATE',167,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(123,'ADD_ACCUMULATE',168,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(124,'ADD_ACCUMULATE',169,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(125,'ADD_ACCUMULATE',170,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(126,'ADD_ACCUMULATE',171,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-26 10:29:38'), +(127,'ADD_ACCUMULATE',172,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-26 11:11:31'), +(128,'ADD_ACCUMULATE',174,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-26 11:11:32'), +(129,'ADD_ACCUMULATE',176,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"12.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-26 11:11:32'), +(130,'ADD_ACCUMULATE',178,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-26 11:19:34'), +(131,'ADD_ACCUMULATE',179,NULL,'{\"report_date\":\"2025-06-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":12,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"12.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-26 11:19:34'), +(132,'ADD_ACCUMULATE',180,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-27 01:54:21'), +(133,'ADD_ACCUMULATE',181,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-27 01:54:21'), +(134,'ADD_ACCUMULATE',182,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-27 01:54:40'), +(135,'ADD_ACCUMULATE',183,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(136,'ADD_ACCUMULATE',184,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(137,'ADD_ACCUMULATE',185,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(138,'ADD_ACCUMULATE',186,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(139,'ADD_ACCUMULATE',187,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(140,'ADD_ACCUMULATE',188,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-06-27 06:47:43'), +(141,'ADD_ACCUMULATE',189,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-27 06:49:08'), +(142,'ADD_ACCUMULATE',190,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-27 06:49:08'), +(143,'DELETE_SINGLE',190,'{\"worker_name\":\"김윤섭\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}',NULL,6,'개별 항목 삭제',NULL,NULL,'2025-06-27 06:58:25'), +(144,'ADD_ACCUMULATE',191,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"4.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-06-27 06:58:46'), +(145,'DELETE_SINGLE',181,'{\"worker_name\":\"박현수\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-27 06:59:37'), +(146,'DELETE_SINGLE',180,'{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-06-27T00:00:00.000Z\"}',NULL,5,'개별 항목 삭제',NULL,NULL,'2025-06-27 06:59:42'), +(147,'ADD_ACCUMULATE',192,NULL,'{\"report_date\":\"2025-06-27\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-06-27 07:00:10'), +(148,'ADD_ACCUMULATE',193,NULL,'{\"report_date\":\"2025-06-30\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:37:29'), +(149,'ADD_ACCUMULATE',195,NULL,'{\"report_date\":\"2025-06-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:38:19'), +(150,'ADD_ACCUMULATE',196,NULL,'{\"report_date\":\"2025-06-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:38:19'), +(151,'ADD_ACCUMULATE',197,NULL,'{\"report_date\":\"2025-06-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:38:19'), +(152,'ADD_ACCUMULATE',198,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(153,'ADD_ACCUMULATE',199,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(154,'ADD_ACCUMULATE',200,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(155,'ADD_ACCUMULATE',201,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(156,'ADD_ACCUMULATE',202,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(157,'ADD_ACCUMULATE',203,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:21'), +(158,'ADD_ACCUMULATE',204,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:48'), +(159,'ADD_ACCUMULATE',205,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:48'), +(160,'ADD_ACCUMULATE',206,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:48'), +(161,'ADD_ACCUMULATE',207,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"14.00\",\"grand_total\":14,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"14.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:39:48'), +(162,'ADD_ACCUMULATE',208,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:40:10'), +(163,'ADD_ACCUMULATE',209,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"12.00\",\"grand_total\":12,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"12.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:40:10'), +(164,'ADD_ACCUMULATE',210,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:42:57'), +(165,'ADD_ACCUMULATE',212,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:42:57'), +(166,'ADD_ACCUMULATE',214,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:42:57'), +(167,'ADD_ACCUMULATE',216,NULL,'{\"report_date\":\"2025-07-01\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:42:57'), +(168,'ADD_ACCUMULATE',218,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(169,'ADD_ACCUMULATE',219,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(170,'ADD_ACCUMULATE',220,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(171,'ADD_ACCUMULATE',221,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(172,'ADD_ACCUMULATE',222,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(173,'ADD_ACCUMULATE',223,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(174,'ADD_ACCUMULATE',224,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:43:36'), +(175,'ADD_ACCUMULATE',225,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:44:11'), +(176,'ADD_ACCUMULATE',227,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:44:11'), +(177,'ADD_ACCUMULATE',229,NULL,'{\"report_date\":\"2025-07-02\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:44:11'), +(178,'ADD_ACCUMULATE',231,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:45:44'), +(179,'ADD_ACCUMULATE',232,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:45:45'), +(180,'ADD_ACCUMULATE',233,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:45:45'), +(181,'ADD_ACCUMULATE',234,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:45:45'), +(182,'ADD_ACCUMULATE',235,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:07'), +(183,'ADD_ACCUMULATE',236,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:07'), +(184,'ADD_ACCUMULATE',237,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:08'), +(185,'ADD_ACCUMULATE',238,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:08'), +(186,'ADD_ACCUMULATE',239,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:08'), +(187,'ADD_ACCUMULATE',240,NULL,'{\"report_date\":\"2025-07-03\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:46:08'), +(188,'ADD_ACCUMULATE',241,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(189,'ADD_ACCUMULATE',243,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(190,'ADD_ACCUMULATE',245,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(191,'ADD_ACCUMULATE',247,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(192,'ADD_ACCUMULATE',249,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(193,'ADD_ACCUMULATE',251,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(194,'ADD_ACCUMULATE',253,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(195,'ADD_ACCUMULATE',255,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(196,'ADD_ACCUMULATE',257,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(197,'ADD_ACCUMULATE',259,NULL,'{\"report_date\":\"2025-07-04\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-05 01:51:47'), +(198,'ADD_ACCUMULATE',261,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:38'), +(199,'ADD_ACCUMULATE',262,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:38'), +(200,'ADD_ACCUMULATE',263,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:39'), +(201,'ADD_ACCUMULATE',264,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:39'), +(202,'ADD_ACCUMULATE',265,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:39'), +(203,'ADD_ACCUMULATE',266,NULL,'{\"report_date\":\"2025-07-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-05 05:36:39'), +(204,'ADD_ACCUMULATE',267,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(205,'ADD_ACCUMULATE',268,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(206,'ADD_ACCUMULATE',269,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(207,'ADD_ACCUMULATE',270,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(208,'ADD_ACCUMULATE',271,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(209,'ADD_ACCUMULATE',272,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(210,'ADD_ACCUMULATE',273,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(211,'ADD_ACCUMULATE',274,NULL,'{\"report_date\":\"2025-07-06\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-06 05:34:32'), +(212,'ADD_ACCUMULATE',275,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(213,'ADD_ACCUMULATE',276,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(214,'ADD_ACCUMULATE',277,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(215,'ADD_ACCUMULATE',278,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(216,'ADD_ACCUMULATE',279,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(217,'ADD_ACCUMULATE',280,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(218,'ADD_ACCUMULATE',281,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(219,'ADD_ACCUMULATE',282,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(220,'ADD_ACCUMULATE',283,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(221,'ADD_ACCUMULATE',284,NULL,'{\"report_date\":\"2025-07-07\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-07-07 06:49:31'), +(222,'ADD_ACCUMULATE',285,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:57'), +(223,'ADD_ACCUMULATE',286,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(224,'ADD_ACCUMULATE',287,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(225,'ADD_ACCUMULATE',288,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(226,'ADD_ACCUMULATE',289,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(227,'ADD_ACCUMULATE',290,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(228,'ADD_ACCUMULATE',291,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(229,'ADD_ACCUMULATE',292,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(230,'ADD_ACCUMULATE',293,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(231,'ADD_ACCUMULATE',294,NULL,'{\"report_date\":\"2025-07-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-08 06:36:58'), +(232,'ADD_ACCUMULATE',295,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:40'), +(233,'ADD_ACCUMULATE',296,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:40'), +(234,'ADD_ACCUMULATE',297,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:40'), +(235,'ADD_ACCUMULATE',298,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:41'), +(236,'ADD_ACCUMULATE',299,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:41'), +(237,'ADD_ACCUMULATE',300,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:41'), +(238,'ADD_ACCUMULATE',301,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:42'), +(239,'ADD_ACCUMULATE',302,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:42'), +(240,'ADD_ACCUMULATE',303,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:08:42'), +(241,'ADD_ACCUMULATE',304,NULL,'{\"report_date\":\"2025-07-09\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-09 22:09:10'), +(242,'ADD_ACCUMULATE',305,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:58'), +(243,'ADD_ACCUMULATE',306,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:58'), +(244,'ADD_ACCUMULATE',307,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:58'), +(245,'ADD_ACCUMULATE',308,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(246,'ADD_ACCUMULATE',309,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(247,'ADD_ACCUMULATE',310,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(248,'ADD_ACCUMULATE',311,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(249,'ADD_ACCUMULATE',312,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(250,'ADD_ACCUMULATE',313,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(251,'ADD_ACCUMULATE',314,NULL,'{\"report_date\":\"2025-07-10\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-10 06:33:59'), +(252,'ADD_ACCUMULATE',315,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(253,'ADD_ACCUMULATE',316,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(254,'ADD_ACCUMULATE',317,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(255,'ADD_ACCUMULATE',318,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(256,'ADD_ACCUMULATE',319,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(257,'ADD_ACCUMULATE',320,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(258,'ADD_ACCUMULATE',321,NULL,'{\"report_date\":\"2025-07-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-12 05:41:30'), +(259,'ADD_ACCUMULATE',322,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:30'), +(260,'ADD_ACCUMULATE',323,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(261,'ADD_ACCUMULATE',324,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(262,'ADD_ACCUMULATE',325,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(263,'ADD_ACCUMULATE',326,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(264,'ADD_ACCUMULATE',327,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(265,'ADD_ACCUMULATE',328,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(266,'ADD_ACCUMULATE',329,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(267,'ADD_ACCUMULATE',330,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-14 06:46:57'), +(268,'ADD_ACCUMULATE',331,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:57:06'), +(269,'ADD_ACCUMULATE',332,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:57:06'), +(270,'ADD_ACCUMULATE',333,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:57:47'), +(271,'ADD_ACCUMULATE',335,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(272,'ADD_ACCUMULATE',336,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(273,'ADD_ACCUMULATE',337,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(274,'ADD_ACCUMULATE',338,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(275,'ADD_ACCUMULATE',339,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(276,'ADD_ACCUMULATE',340,NULL,'{\"report_date\":\"2025-07-15\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-15 05:58:19'), +(277,'ADD_ACCUMULATE',341,NULL,'{\"report_date\":\"2025-07-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-15 06:57:26'), +(278,'ADD_ACCUMULATE',342,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":4,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:46:46'), +(279,'ADD_ACCUMULATE',345,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":5,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:46:46'), +(280,'ADD_ACCUMULATE',348,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":10,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:47:53'), +(281,'ADD_ACCUMULATE',351,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":6,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:47:53'), +(282,'ADD_ACCUMULATE',354,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:48:32'), +(283,'ADD_ACCUMULATE',355,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:48:32'), +(284,'ADD_ACCUMULATE',356,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:48:32'), +(285,'ADD_ACCUMULATE',357,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-16 06:48:32'), +(286,'ADD_ACCUMULATE',358,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-16 06:51:31'), +(287,'ADD_ACCUMULATE',359,NULL,'{\"report_date\":\"2025-07-16\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-16 06:51:31'), +(288,'ADD_ACCUMULATE',360,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-17 06:45:22'), +(289,'ADD_ACCUMULATE',361,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:46:48'), +(290,'ADD_ACCUMULATE',363,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:46:48'), +(291,'ADD_ACCUMULATE',365,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:46:48'), +(292,'ADD_ACCUMULATE',367,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(293,'ADD_ACCUMULATE',368,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(294,'ADD_ACCUMULATE',369,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(295,'ADD_ACCUMULATE',370,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(296,'ADD_ACCUMULATE',371,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(297,'ADD_ACCUMULATE',372,NULL,'{\"report_date\":\"2025-07-17\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-17 06:47:19'), +(298,'ADD_ACCUMULATE',373,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"2.00\",\"grand_total\":2,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"2.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 05:54:47'), +(299,'ADD_ACCUMULATE',374,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"2.00\",\"grand_total\":2,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"2.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 05:54:48'), +(300,'ADD_ACCUMULATE',375,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":5,\"work_entries_count\":3,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 05:58:33'), +(301,'DELETE_SINGLE',375,'{\"worker_name\":\"표영진\",\"project_name\":\"김천 솔라 파워 그린 수소 Project\",\"work_hours\":\"2.00\",\"report_date\":\"2025-07-18T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-07-18 05:58:49'), +(302,'ADD_ACCUMULATE',378,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 05:59:42'), +(303,'ADD_ACCUMULATE',379,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-18 06:00:15'), +(304,'ADD_ACCUMULATE',380,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(305,'ADD_ACCUMULATE',381,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(306,'ADD_ACCUMULATE',382,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(307,'ADD_ACCUMULATE',383,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(308,'ADD_ACCUMULATE',384,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(309,'ADD_ACCUMULATE',385,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(310,'ADD_ACCUMULATE',386,NULL,'{\"report_date\":\"2025-07-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-18 06:36:13'), +(311,'ADD_ACCUMULATE',387,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:08'), +(312,'ADD_ACCUMULATE',389,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:08'), +(313,'ADD_ACCUMULATE',391,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(314,'ADD_ACCUMULATE',392,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(315,'ADD_ACCUMULATE',393,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(316,'ADD_ACCUMULATE',394,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(317,'ADD_ACCUMULATE',395,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(318,'ADD_ACCUMULATE',396,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(319,'ADD_ACCUMULATE',397,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-21 06:40:32'), +(320,'ADD_ACCUMULATE',398,NULL,'{\"report_date\":\"2025-07-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-21 06:53:37'), +(321,'ADD_ACCUMULATE',399,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:47'), +(322,'ADD_ACCUMULATE',400,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(323,'ADD_ACCUMULATE',401,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(324,'ADD_ACCUMULATE',402,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(325,'ADD_ACCUMULATE',403,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(326,'ADD_ACCUMULATE',404,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(327,'ADD_ACCUMULATE',405,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:45:48'), +(328,'ADD_ACCUMULATE',406,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-22 06:46:11'), +(329,'ADD_ACCUMULATE',407,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-22 06:46:11'), +(330,'ADD_ACCUMULATE',408,NULL,'{\"report_date\":\"2025-07-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-22 06:46:11'), +(331,'ADD_ACCUMULATE',409,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:06'), +(332,'ADD_ACCUMULATE',410,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:28'), +(333,'ADD_ACCUMULATE',411,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:28'), +(334,'ADD_ACCUMULATE',412,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(335,'ADD_ACCUMULATE',413,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(336,'ADD_ACCUMULATE',414,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(337,'ADD_ACCUMULATE',415,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(338,'ADD_ACCUMULATE',416,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(339,'ADD_ACCUMULATE',417,NULL,'{\"report_date\":\"2025-07-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-23 06:45:30'), +(340,'ADD_ACCUMULATE',418,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:36:55'), +(341,'ADD_ACCUMULATE',419,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(342,'ADD_ACCUMULATE',420,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(343,'ADD_ACCUMULATE',421,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(344,'ADD_ACCUMULATE',422,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(345,'ADD_ACCUMULATE',423,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(346,'ADD_ACCUMULATE',424,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-24 06:37:18'), +(347,'ADD_ACCUMULATE',425,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-24 06:47:04'), +(348,'ADD_ACCUMULATE',426,NULL,'{\"report_date\":\"2025-07-24\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-24 06:47:04'), +(349,'ADD_ACCUMULATE',427,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:44:23'), +(350,'ADD_ACCUMULATE',428,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(351,'ADD_ACCUMULATE',429,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(352,'ADD_ACCUMULATE',430,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(353,'ADD_ACCUMULATE',431,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(354,'ADD_ACCUMULATE',432,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(355,'ADD_ACCUMULATE',433,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:15'), +(356,'ADD_ACCUMULATE',434,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:18'), +(357,'ADD_ACCUMULATE',435,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:19'), +(358,'ADD_ACCUMULATE',436,NULL,'{\"report_date\":\"2025-07-25\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-25 06:45:19'), +(359,'ADD_ACCUMULATE',437,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-28 06:30:39'), +(360,'ADD_ACCUMULATE',438,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-28 06:30:39'), +(361,'ADD_ACCUMULATE',439,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-28 06:30:39'), +(362,'ADD_ACCUMULATE',440,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:08'), +(363,'ADD_ACCUMULATE',442,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(364,'ADD_ACCUMULATE',443,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(365,'ADD_ACCUMULATE',444,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(366,'ADD_ACCUMULATE',445,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(367,'ADD_ACCUMULATE',446,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(368,'ADD_ACCUMULATE',447,NULL,'{\"report_date\":\"2025-07-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-28 06:33:34'), +(369,'ADD_ACCUMULATE',448,NULL,'{\"report_date\":\"2025-07-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-29 06:39:13'), +(370,'ADD_ACCUMULATE',449,NULL,'{\"report_date\":\"2025-07-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-29 06:39:13'), +(371,'ADD_ACCUMULATE',450,NULL,'{\"report_date\":\"2025-07-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-29 06:39:13'), +(372,'ADD_ACCUMULATE',451,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-30 06:50:30'), +(373,'ADD_ACCUMULATE',452,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-30 06:50:30'), +(374,'ADD_ACCUMULATE',453,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-30 06:50:30'), +(375,'ADD_ACCUMULATE',454,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(376,'ADD_ACCUMULATE',455,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(377,'ADD_ACCUMULATE',456,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(378,'ADD_ACCUMULATE',457,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(379,'ADD_ACCUMULATE',458,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(380,'ADD_ACCUMULATE',459,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(381,'ADD_ACCUMULATE',460,NULL,'{\"report_date\":\"2025-07-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-30 06:52:16'), +(382,'ADD_ACCUMULATE',461,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:42:56'), +(383,'ADD_ACCUMULATE',462,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:43:32'), +(384,'ADD_ACCUMULATE',464,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:43:32'), +(385,'ADD_ACCUMULATE',466,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(386,'ADD_ACCUMULATE',467,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(387,'ADD_ACCUMULATE',468,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(388,'ADD_ACCUMULATE',469,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(389,'ADD_ACCUMULATE',470,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(390,'ADD_ACCUMULATE',471,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(391,'ADD_ACCUMULATE',472,NULL,'{\"report_date\":\"2025-07-31\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-07-31 06:44:00'), +(392,'ADD_ACCUMULATE',473,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(393,'ADD_ACCUMULATE',474,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(394,'ADD_ACCUMULATE',475,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(395,'ADD_ACCUMULATE',476,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(396,'ADD_ACCUMULATE',477,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(397,'ADD_ACCUMULATE',478,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(398,'ADD_ACCUMULATE',479,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(399,'ADD_ACCUMULATE',480,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(400,'ADD_ACCUMULATE',481,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(401,'ADD_ACCUMULATE',482,NULL,'{\"report_date\":\"2025-07-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-07-31 22:24:47'), +(402,'ADD_ACCUMULATE',483,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(403,'ADD_ACCUMULATE',484,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(404,'ADD_ACCUMULATE',485,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(405,'ADD_ACCUMULATE',486,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(406,'ADD_ACCUMULATE',487,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(407,'ADD_ACCUMULATE',488,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:47'), +(408,'ADD_ACCUMULATE',489,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-01 04:57:48'), +(409,'ADD_ACCUMULATE',490,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-01 05:02:28'), +(410,'ADD_ACCUMULATE',492,NULL,'{\"report_date\":\"2025-08-01\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-01 05:02:28'), +(411,'ADD_ACCUMULATE',494,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:42:39'), +(412,'ADD_ACCUMULATE',496,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":7,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:42:39'), +(413,'ADD_ACCUMULATE',498,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:14'), +(414,'ADD_ACCUMULATE',499,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:15'), +(415,'ADD_ACCUMULATE',500,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:15'), +(416,'ADD_ACCUMULATE',501,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:39'), +(417,'ADD_ACCUMULATE',502,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:39'), +(418,'ADD_ACCUMULATE',503,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:39'), +(419,'ADD_ACCUMULATE',504,NULL,'{\"report_date\":\"2025-08-07\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-07 06:43:52'), +(420,'ADD_ACCUMULATE',505,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-08 06:45:20'), +(421,'ADD_ACCUMULATE',506,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:58:42'), +(422,'ADD_ACCUMULATE',507,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:58:42'), +(423,'ADD_ACCUMULATE',508,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:18'), +(424,'ADD_ACCUMULATE',509,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:19'), +(425,'ADD_ACCUMULATE',510,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:19'), +(426,'ADD_ACCUMULATE',511,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:19'), +(427,'ADD_ACCUMULATE',512,NULL,'{\"report_date\":\"2025-08-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-08 06:59:19'), +(428,'ADD_ACCUMULATE',513,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-11 06:27:37'), +(429,'ADD_ACCUMULATE',514,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"16.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"16.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-11 06:27:37'), +(430,'ADD_ACCUMULATE',515,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:23'), +(431,'ADD_ACCUMULATE',516,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:23'), +(432,'ADD_ACCUMULATE',517,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:49'), +(433,'ADD_ACCUMULATE',518,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:49'), +(434,'ADD_ACCUMULATE',519,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:50'), +(435,'ADD_ACCUMULATE',520,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:50'), +(436,'ADD_ACCUMULATE',521,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:50'), +(437,'ADD_ACCUMULATE',522,NULL,'{\"report_date\":\"2025-08-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-11 06:46:50'), +(438,'ADD_ACCUMULATE',523,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(439,'ADD_ACCUMULATE',524,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(440,'ADD_ACCUMULATE',525,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(441,'ADD_ACCUMULATE',526,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(442,'ADD_ACCUMULATE',527,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(443,'ADD_ACCUMULATE',528,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(444,'ADD_ACCUMULATE',529,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(445,'ADD_ACCUMULATE',530,NULL,'{\"report_date\":\"2025-08-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-12 06:47:24'), +(446,'ADD_ACCUMULATE',531,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-13 06:31:32'), +(447,'ADD_ACCUMULATE',532,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:13'), +(448,'ADD_ACCUMULATE',534,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(449,'ADD_ACCUMULATE',535,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(450,'ADD_ACCUMULATE',536,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(451,'ADD_ACCUMULATE',537,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(452,'ADD_ACCUMULATE',538,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(453,'ADD_ACCUMULATE',539,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(454,'ADD_ACCUMULATE',540,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:36:48'), +(455,'ADD_ACCUMULATE',541,NULL,'{\"report_date\":\"2025-08-13\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-13 06:37:19'), +(456,'ADD_ACCUMULATE',542,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":1,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-14 06:35:27'), +(457,'ADD_ACCUMULATE',544,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:39:03'), +(458,'ADD_ACCUMULATE',546,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:39:44'), +(459,'ADD_ACCUMULATE',548,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(460,'ADD_ACCUMULATE',549,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(461,'ADD_ACCUMULATE',550,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(462,'ADD_ACCUMULATE',551,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(463,'ADD_ACCUMULATE',552,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(464,'ADD_ACCUMULATE',553,NULL,'{\"report_date\":\"2025-08-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-14 06:40:10'), +(465,'ADD_ACCUMULATE',554,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:21:36'), +(466,'ADD_ACCUMULATE',555,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:21:36'), +(467,'ADD_ACCUMULATE',556,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:22:01'), +(468,'ADD_ACCUMULATE',557,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:22:53'), +(469,'ADD_ACCUMULATE',559,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-18 06:23:34'), +(470,'ADD_ACCUMULATE',561,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:41:24'), +(471,'ADD_ACCUMULATE',562,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:41:24'), +(472,'ADD_ACCUMULATE',563,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:41:24'), +(473,'ADD_ACCUMULATE',564,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:10'), +(474,'ADD_ACCUMULATE',565,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:10'), +(475,'ADD_ACCUMULATE',566,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:10'), +(476,'ADD_ACCUMULATE',567,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:35'), +(477,'ADD_ACCUMULATE',568,NULL,'{\"report_date\":\"2025-08-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-18 06:43:35'), +(478,'ADD_ACCUMULATE',569,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"6.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:02:49'), +(479,'ADD_ACCUMULATE',570,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:03:30'), +(480,'ADD_ACCUMULATE',571,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:03:30'), +(481,'ADD_ACCUMULATE',572,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:03:30'), +(482,'ADD_ACCUMULATE',573,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:03:30'), +(483,'ADD_ACCUMULATE',574,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(484,'ADD_ACCUMULATE',575,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(485,'ADD_ACCUMULATE',576,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(486,'ADD_ACCUMULATE',577,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(487,'ADD_ACCUMULATE',578,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-19 08:04:05'), +(488,'ADD_ACCUMULATE',579,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-19 08:36:51'), +(489,'ADD_ACCUMULATE',580,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-19 08:36:51'), +(490,'ADD_ACCUMULATE',581,NULL,'{\"report_date\":\"2025-08-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-19 08:36:51'), +(491,'ADD_ACCUMULATE',582,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-20 06:19:36'), +(492,'ADD_ACCUMULATE',583,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-20 06:21:28'), +(493,'ADD_ACCUMULATE',585,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-20 06:21:28'), +(494,'ADD_ACCUMULATE',587,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:43:46'), +(495,'ADD_ACCUMULATE',588,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:23'), +(496,'ADD_ACCUMULATE',589,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:23'), +(497,'ADD_ACCUMULATE',590,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:23'), +(498,'ADD_ACCUMULATE',591,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:24'), +(499,'ADD_ACCUMULATE',592,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:24'), +(500,'ADD_ACCUMULATE',593,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:24'), +(501,'ADD_ACCUMULATE',594,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:26'), +(502,'ADD_ACCUMULATE',595,NULL,'{\"report_date\":\"2025-08-20\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-20 06:44:26'), +(503,'ADD_ACCUMULATE',596,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-21 06:30:36'), +(504,'ADD_ACCUMULATE',597,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-21 06:30:36'), +(505,'ADD_ACCUMULATE',598,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:50:38'), +(506,'ADD_ACCUMULATE',599,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:50:38'), +(507,'ADD_ACCUMULATE',600,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:51:23'), +(508,'ADD_ACCUMULATE',602,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:51:23'), +(509,'ADD_ACCUMULATE',604,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:51:23'), +(510,'ADD_ACCUMULATE',606,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:51:23'), +(511,'ADD_ACCUMULATE',608,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:54:46'), +(512,'ADD_ACCUMULATE',610,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-21 07:55:25'), +(513,'ADD_ACCUMULATE',612,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-21 08:24:50'), +(514,'ADD_ACCUMULATE',613,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-21 08:24:50'), +(515,'ADD_ACCUMULATE',614,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-22 06:21:15'), +(516,'ADD_ACCUMULATE',615,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-22 06:23:12'), +(517,'ADD_ACCUMULATE',617,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-22 06:23:55'), +(518,'ADD_ACCUMULATE',618,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:27:43'), +(519,'ADD_ACCUMULATE',619,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(520,'ADD_ACCUMULATE',620,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(521,'ADD_ACCUMULATE',621,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(522,'ADD_ACCUMULATE',622,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(523,'ADD_ACCUMULATE',623,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(524,'ADD_ACCUMULATE',624,NULL,'{\"report_date\":\"2025-08-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-22 06:28:15'), +(525,'ADD_ACCUMULATE',625,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:02'), +(526,'ADD_ACCUMULATE',627,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:25'), +(527,'ADD_ACCUMULATE',628,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(528,'ADD_ACCUMULATE',629,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(529,'ADD_ACCUMULATE',630,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(530,'ADD_ACCUMULATE',631,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(531,'ADD_ACCUMULATE',632,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(532,'ADD_ACCUMULATE',633,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(533,'ADD_ACCUMULATE',634,NULL,'{\"report_date\":\"2025-08-23\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-23 04:57:54'), +(534,'ADD_ACCUMULATE',635,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(535,'ADD_ACCUMULATE',636,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(536,'ADD_ACCUMULATE',637,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(537,'ADD_ACCUMULATE',638,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(538,'ADD_ACCUMULATE',639,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(539,'ADD_ACCUMULATE',640,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(540,'ADD_ACCUMULATE',641,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(541,'ADD_ACCUMULATE',642,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(542,'ADD_ACCUMULATE',643,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(543,'ADD_ACCUMULATE',644,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-25 06:48:34'), +(544,'ADD_ACCUMULATE',645,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-25 06:49:16'), +(545,'ADD_ACCUMULATE',646,NULL,'{\"report_date\":\"2025-08-25\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-25 06:49:17'), +(546,'ADD_ACCUMULATE',647,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:28:03'), +(547,'ADD_ACCUMULATE',649,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:28:35'), +(548,'ADD_ACCUMULATE',650,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(549,'ADD_ACCUMULATE',651,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(550,'ADD_ACCUMULATE',652,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(551,'ADD_ACCUMULATE',653,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(552,'ADD_ACCUMULATE',654,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(553,'ADD_ACCUMULATE',655,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(554,'ADD_ACCUMULATE',656,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:02'), +(555,'ADD_ACCUMULATE',657,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-26 07:29:03'), +(556,'ADD_ACCUMULATE',658,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-26 08:22:12'), +(557,'ADD_ACCUMULATE',659,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-26 08:22:12'), +(558,'ADD_ACCUMULATE',660,NULL,'{\"report_date\":\"2025-08-26\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-26 08:22:12'), +(559,'ADD_ACCUMULATE',661,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(560,'ADD_ACCUMULATE',662,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(561,'ADD_ACCUMULATE',663,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(562,'ADD_ACCUMULATE',664,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(563,'ADD_ACCUMULATE',665,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(564,'ADD_ACCUMULATE',666,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(565,'ADD_ACCUMULATE',667,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:47'), +(566,'ADD_ACCUMULATE',668,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-27 06:44:48'), +(567,'ADD_ACCUMULATE',669,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-27 06:45:32'), +(568,'ADD_ACCUMULATE',671,NULL,'{\"report_date\":\"2025-08-27\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-27 06:45:32'), +(569,'ADD_ACCUMULATE',673,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-28 08:31:42'), +(570,'ADD_ACCUMULATE',675,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-28 08:31:42'), +(571,'ADD_ACCUMULATE',677,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-28 08:31:42'), +(572,'ADD_ACCUMULATE',679,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-28 08:31:42'), +(573,'ADD_ACCUMULATE',681,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:37:46'), +(574,'ADD_ACCUMULATE',683,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:38:15'), +(575,'ADD_ACCUMULATE',685,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:38:50'), +(576,'ADD_ACCUMULATE',687,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:39:24'), +(577,'ADD_ACCUMULATE',688,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(578,'ADD_ACCUMULATE',689,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(579,'ADD_ACCUMULATE',690,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(580,'ADD_ACCUMULATE',691,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(581,'ADD_ACCUMULATE',692,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(582,'ADD_ACCUMULATE',693,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":18,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:40:00'), +(583,'ADD_ACCUMULATE',694,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:44:56'), +(584,'ADD_ACCUMULATE',695,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:44:56'), +(585,'ADD_ACCUMULATE',696,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:44:56'), +(586,'ADD_ACCUMULATE',697,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(587,'ADD_ACCUMULATE',698,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(588,'ADD_ACCUMULATE',699,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(589,'ADD_ACCUMULATE',700,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(590,'ADD_ACCUMULATE',701,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(591,'ADD_ACCUMULATE',702,NULL,'{\"report_date\":\"2025-08-28\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":2,\"my_total\":\"10.00\",\"grand_total\":20,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"},{\"name\":\"반치원\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-28 08:45:19'), +(592,'DELETE',693,'{\"id\":693,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:05'), +(593,'DELETE',702,'{\"id\":702,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:16'), +(594,'DELETE',697,'{\"id\":697,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:26'), +(595,'DELETE',688,'{\"id\":688,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:32'), +(596,'DELETE',691,'{\"id\":691,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:41'), +(597,'DELETE',700,'{\"id\":700,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:48'), +(598,'DELETE',692,'{\"id\":692,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":4,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-28T08:40:00.000Z\",\"updated_at\":\"2025-08-28T08:40:00.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:46:56'), +(599,'DELETE',701,'{\"id\":701,\"report_date\":\"2025-08-28T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-28T08:45:19.000Z\",\"updated_at\":\"2025-08-28T08:45:19.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-28 08:47:01'), +(600,'ADD_ACCUMULATE',703,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(601,'ADD_ACCUMULATE',704,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(602,'ADD_ACCUMULATE',705,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(603,'ADD_ACCUMULATE',706,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(604,'ADD_ACCUMULATE',707,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(605,'ADD_ACCUMULATE',708,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(606,'ADD_ACCUMULATE',709,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(607,'ADD_ACCUMULATE',710,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:02'), +(608,'ADD_ACCUMULATE',711,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:35'), +(609,'ADD_ACCUMULATE',713,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:35'), +(610,'ADD_ACCUMULATE',715,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":3,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:35'), +(611,'ADD_ACCUMULATE',717,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":6,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-08-29 06:47:35'), +(612,'DELETE',705,'{\"id\":705,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":8,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:55:28'), +(613,'ADD_ACCUMULATE',719,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-29 21:55:56'), +(614,'ADD_ACCUMULATE',720,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-29 21:55:56'), +(615,'ADD_ACCUMULATE',721,NULL,'{\"report_date\":\"2025-08-29\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-29 21:55:56'), +(616,'DELETE',711,'{\"id\":711,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"6.00\",\"created_at\":\"2025-08-29T06:47:35.000Z\",\"updated_at\":\"2025-08-29T06:47:35.000Z\",\"created_by\":6,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:56:26'), +(617,'DELETE',712,'{\"id\":712,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":1,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-29T06:47:35.000Z\",\"updated_at\":\"2025-08-29T06:47:35.000Z\",\"created_by\":6,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:56:43'), +(618,'DELETE',707,'{\"id\":707,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:57:03'), +(619,'DELETE',708,'{\"id\":708,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:57:16'), +(620,'DELETE',709,'{\"id\":709,\"report_date\":\"2025-08-29T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":2,\"error_type_id\":5,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-29T06:47:02.000Z\",\"updated_at\":\"2025-08-29T06:47:02.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-08-29 21:57:26'), +(621,'ADD_ACCUMULATE',722,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-30 05:12:03'), +(622,'ADD_ACCUMULATE',723,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-30 05:12:03'), +(623,'ADD_ACCUMULATE',724,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-08-30 05:12:03'), +(624,'ADD_ACCUMULATE',725,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(625,'ADD_ACCUMULATE',726,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(626,'ADD_ACCUMULATE',727,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(627,'ADD_ACCUMULATE',728,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(628,'ADD_ACCUMULATE',729,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(629,'ADD_ACCUMULATE',730,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(630,'ADD_ACCUMULATE',731,NULL,'{\"report_date\":\"2025-08-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-08-30 05:36:49'), +(631,'ADD_ACCUMULATE',732,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:18:28'), +(632,'ADD_ACCUMULATE',733,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:18:28'), +(633,'ADD_ACCUMULATE',734,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:11'), +(634,'ADD_ACCUMULATE',735,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:11'), +(635,'ADD_ACCUMULATE',736,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"4.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:11'), +(636,'ADD_ACCUMULATE',737,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:35'), +(637,'ADD_ACCUMULATE',738,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:35'), +(638,'ADD_ACCUMULATE',739,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:19:35'), +(639,'ADD_ACCUMULATE',740,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 06:20:03'), +(640,'DELETE',650,'{\"id\":650,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:13:55'), +(641,'DELETE',654,'{\"id\":654,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:14:02'), +(642,'DELETE',656,'{\"id\":656,\"report_date\":\"2025-08-26T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-26T07:29:02.000Z\",\"updated_at\":\"2025-08-26T07:29:02.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:14:11'), +(643,'DELETE',572,'{\"id\":572,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":7,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:15:09'), +(644,'DELETE',571,'{\"id\":571,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:15:17'), +(645,'DELETE',570,'{\"id\":570,\"report_date\":\"2025-08-19T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"10.00\",\"created_at\":\"2025-08-19T08:03:30.000Z\",\"updated_at\":\"2025-08-19T08:03:30.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:15:27'), +(646,'DELETE',599,'{\"id\":599,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":7,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:50:38.000Z\",\"updated_at\":\"2025-08-21T07:50:38.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:15:59'), +(647,'DELETE',604,'{\"id\":604,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:14'), +(648,'DELETE',605,'{\"id\":605,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:19'), +(649,'DELETE',606,'{\"id\":606,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:28'), +(650,'DELETE',607,'{\"id\":607,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"2.00\",\"created_at\":\"2025-08-21T07:51:23.000Z\",\"updated_at\":\"2025-08-21T07:51:23.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:33'), +(651,'DELETE',598,'{\"id\":598,\"report_date\":\"2025-08-21T00:00:00.000Z\",\"worker_id\":1,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-21T07:50:38.000Z\",\"updated_at\":\"2025-08-21T07:50:38.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:16:54'), +(652,'ADD_ACCUMULATE',741,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 23:18:03'), +(653,'ADD_ACCUMULATE',742,NULL,'{\"report_date\":\"2025-08-21\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-01 23:18:03'), +(654,'DELETE',588,'{\"id\":588,\"report_date\":\"2025-08-20T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-20T06:44:23.000Z\",\"updated_at\":\"2025-08-20T06:44:23.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:26:52'), +(655,'DELETE',592,'{\"id\":592,\"report_date\":\"2025-08-20T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-20T06:44:24.000Z\",\"updated_at\":\"2025-08-20T06:44:24.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:26:58'), +(656,'DELETE',639,'{\"id\":639,\"report_date\":\"2025-08-25T00:00:00.000Z\",\"worker_id\":6,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-25T06:48:34.000Z\",\"updated_at\":\"2025-08-25T06:48:34.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:27:26'), +(657,'DELETE',642,'{\"id\":642,\"report_date\":\"2025-08-25T00:00:00.000Z\",\"worker_id\":3,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-08-25T06:48:34.000Z\",\"updated_at\":\"2025-08-25T06:48:34.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,3,'Manual deletion',NULL,NULL,'2025-09-01 23:27:31'), +(658,'ADD_ACCUMULATE',743,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:34:20'), +(659,'ADD_ACCUMULATE',744,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:34:20'), +(660,'DELETE_SINGLE',744,'{\"worker_name\":\"이창호\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-09-02T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-09-02 07:35:18'), +(661,'DELETE_SINGLE',743,'{\"worker_name\":\"최광욱\",\"project_name\":\"효성화학 에틸렌 탱크 건설공사\",\"work_hours\":\"8.00\",\"report_date\":\"2025-09-02T00:00:00.000Z\"}',NULL,3,'개별 항목 삭제',NULL,NULL,'2025-09-02 07:35:21'), +(662,'ADD_ACCUMULATE',745,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(663,'ADD_ACCUMULATE',746,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(664,'ADD_ACCUMULATE',747,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(665,'ADD_ACCUMULATE',748,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(666,'ADD_ACCUMULATE',749,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(667,'ADD_ACCUMULATE',750,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:04'), +(668,'ADD_ACCUMULATE',751,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(669,'ADD_ACCUMULATE',752,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(670,'ADD_ACCUMULATE',753,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(671,'ADD_ACCUMULATE',754,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(672,'ADD_ACCUMULATE',755,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(673,'ADD_ACCUMULATE',756,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:36:31'), +(674,'ADD_ACCUMULATE',757,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:37:19'), +(675,'ADD_ACCUMULATE',758,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"10.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-02 07:37:19'), +(676,'ADD_ACCUMULATE',759,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-02 08:16:14'), +(677,'ADD_ACCUMULATE',761,NULL,'{\"report_date\":\"2025-09-02\",\"worker_id\":4,\"work_entries_count\":2,\"added_hours\":10,\"my_total\":\"10.00\",\"grand_total\":10,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"10.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-02 08:16:14'), +(678,'ADD_ACCUMULATE',763,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:47'), +(679,'ADD_ACCUMULATE',764,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:47'), +(680,'ADD_ACCUMULATE',765,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(681,'ADD_ACCUMULATE',766,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(682,'ADD_ACCUMULATE',767,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(683,'ADD_ACCUMULATE',768,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(684,'ADD_ACCUMULATE',769,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(685,'ADD_ACCUMULATE',770,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-03 06:34:48'), +(686,'ADD_ACCUMULATE',771,NULL,'{\"report_date\":\"2025-09-03\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-03 06:44:18'), +(687,'ADD_ACCUMULATE',772,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:32'), +(688,'ADD_ACCUMULATE',773,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:32'), +(689,'ADD_ACCUMULATE',774,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:32'), +(690,'ADD_ACCUMULATE',775,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:32'), +(691,'ADD_ACCUMULATE',776,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:33'), +(692,'ADD_ACCUMULATE',777,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:33'), +(693,'ADD_ACCUMULATE',778,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:33'), +(694,'ADD_ACCUMULATE',779,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-04 06:41:33'), +(695,'ADD_ACCUMULATE',780,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-04 06:48:34'), +(696,'ADD_ACCUMULATE',781,NULL,'{\"report_date\":\"2025-09-04\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-04 06:48:34'), +(697,'ADD_ACCUMULATE',782,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:30'), +(698,'ADD_ACCUMULATE',783,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:30'), +(699,'ADD_ACCUMULATE',784,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:30'), +(700,'ADD_ACCUMULATE',785,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:31'), +(701,'ADD_ACCUMULATE',786,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:31'), +(702,'ADD_ACCUMULATE',787,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:31'), +(703,'ADD_ACCUMULATE',788,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-05 06:39:31'), +(704,'ADD_ACCUMULATE',789,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-05 22:09:55'), +(705,'ADD_ACCUMULATE',790,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-05 22:09:55'), +(706,'ADD_ACCUMULATE',791,NULL,'{\"report_date\":\"2025-09-05\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-05 22:09:55'), +(707,'ADD_ACCUMULATE',792,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-06 04:21:10'), +(708,'ADD_ACCUMULATE',793,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-06 04:21:10'), +(709,'ADD_ACCUMULATE',794,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-06 04:21:10'), +(710,'ADD_ACCUMULATE',795,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:18'), +(711,'ADD_ACCUMULATE',796,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:18'), +(712,'ADD_ACCUMULATE',797,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:18'), +(713,'ADD_ACCUMULATE',798,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:19'), +(714,'ADD_ACCUMULATE',799,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:19'), +(715,'ADD_ACCUMULATE',800,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:19'), +(716,'ADD_ACCUMULATE',801,NULL,'{\"report_date\":\"2025-09-06\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-06 05:28:19'), +(717,'ADD_ACCUMULATE',802,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(718,'ADD_ACCUMULATE',803,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(719,'ADD_ACCUMULATE',804,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(720,'ADD_ACCUMULATE',805,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(721,'ADD_ACCUMULATE',806,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(722,'ADD_ACCUMULATE',807,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(723,'ADD_ACCUMULATE',808,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-08 06:15:43'), +(724,'ADD_ACCUMULATE',809,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-08 06:47:37'), +(725,'ADD_ACCUMULATE',810,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-08 06:47:37'), +(726,'ADD_ACCUMULATE',811,NULL,'{\"report_date\":\"2025-09-08\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-08 06:47:37'), +(727,'ADD_ACCUMULATE',812,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(728,'ADD_ACCUMULATE',813,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(729,'ADD_ACCUMULATE',814,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(730,'ADD_ACCUMULATE',815,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(731,'ADD_ACCUMULATE',816,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(732,'ADD_ACCUMULATE',817,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(733,'ADD_ACCUMULATE',818,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-09 06:03:27'), +(734,'ADD_ACCUMULATE',819,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-09 06:44:29'), +(735,'ADD_ACCUMULATE',820,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-09 06:44:29'), +(736,'ADD_ACCUMULATE',821,NULL,'{\"report_date\":\"2025-09-09\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-09 06:44:29'), +(737,'ADD_ACCUMULATE',822,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(738,'ADD_ACCUMULATE',823,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(739,'ADD_ACCUMULATE',824,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(740,'ADD_ACCUMULATE',825,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(741,'ADD_ACCUMULATE',826,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(742,'ADD_ACCUMULATE',827,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(743,'ADD_ACCUMULATE',828,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-10 06:27:52'), +(744,'ADD_ACCUMULATE',829,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-10 06:48:43'), +(745,'ADD_ACCUMULATE',830,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-10 06:48:43'), +(746,'ADD_ACCUMULATE',831,NULL,'{\"report_date\":\"2025-09-10\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-10 06:48:43'), +(747,'ADD_ACCUMULATE',832,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":2,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:37:11'), +(748,'ADD_ACCUMULATE',834,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":4,\"work_entries_count\":3,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:38:24'), +(749,'ADD_ACCUMULATE',837,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:39:38'), +(750,'ADD_ACCUMULATE',838,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:40:48'), +(751,'ADD_ACCUMULATE',839,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:46'), +(752,'ADD_ACCUMULATE',840,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(753,'ADD_ACCUMULATE',841,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(754,'ADD_ACCUMULATE',842,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(755,'ADD_ACCUMULATE',843,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(756,'ADD_ACCUMULATE',844,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',6,'누적 추가 by 반치원 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:47'), +(757,'ADD_ACCUMULATE',845,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":10,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:51'), +(758,'ADD_ACCUMULATE',847,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":9,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:51'), +(759,'ADD_ACCUMULATE',849,NULL,'{\"report_date\":\"2025-09-11\",\"worker_id\":5,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":16,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"},{\"name\":\"반치원\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-11 06:41:51'), +(760,'DELETE',849,'{\"id\":849,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"4.00\",\"created_at\":\"2025-09-11T06:41:51.000Z\",\"updated_at\":\"2025-09-11T06:41:51.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-11 06:42:40'), +(761,'DELETE',850,'{\"id\":850,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":5,\"project_id\":3,\"work_type_id\":3,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"4.00\",\"created_at\":\"2025-09-11T06:41:51.000Z\",\"updated_at\":\"2025-09-11T06:41:51.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-11 06:42:49'), +(762,'DELETE',839,'{\"id\":839,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":10,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-11T06:41:46.000Z\",\"updated_at\":\"2025-09-11T06:41:46.000Z\",\"created_by\":6,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-11 06:43:07'), +(763,'DELETE',837,'{\"id\":837,\"report_date\":\"2025-09-11T00:00:00.000Z\",\"worker_id\":8,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-11T06:39:38.000Z\",\"updated_at\":\"2025-09-11T06:39:38.000Z\",\"created_by\":5,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-11 06:43:16'), +(764,'ADD_ACCUMULATE',851,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(765,'ADD_ACCUMULATE',852,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(766,'ADD_ACCUMULATE',853,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(767,'ADD_ACCUMULATE',854,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(768,'ADD_ACCUMULATE',855,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(769,'ADD_ACCUMULATE',856,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(770,'ADD_ACCUMULATE',857,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(771,'ADD_ACCUMULATE',858,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(772,'ADD_ACCUMULATE',859,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(773,'ADD_ACCUMULATE',860,NULL,'{\"report_date\":\"2025-09-12\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-12 06:45:29'), +(774,'ADD_ACCUMULATE',861,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(775,'ADD_ACCUMULATE',862,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(776,'ADD_ACCUMULATE',863,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(777,'ADD_ACCUMULATE',864,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(778,'ADD_ACCUMULATE',865,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(779,'ADD_ACCUMULATE',866,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(780,'ADD_ACCUMULATE',867,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(781,'ADD_ACCUMULATE',868,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(782,'ADD_ACCUMULATE',869,NULL,'{\"report_date\":\"2025-09-13\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-13 06:38:14'), +(783,'ADD_ACCUMULATE',870,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:40'), +(784,'ADD_ACCUMULATE',871,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:40'), +(785,'ADD_ACCUMULATE',872,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:40'), +(786,'ADD_ACCUMULATE',873,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:40'), +(787,'ADD_ACCUMULATE',874,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(788,'ADD_ACCUMULATE',875,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(789,'ADD_ACCUMULATE',876,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(790,'ADD_ACCUMULATE',877,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(791,'ADD_ACCUMULATE',878,NULL,'{\"report_date\":\"2025-09-14\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-14 04:47:41'), +(792,'ADD_ACCUMULATE',879,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:00'), +(793,'ADD_ACCUMULATE',880,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:00'), +(794,'ADD_ACCUMULATE',881,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:00'), +(795,'ADD_ACCUMULATE',882,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:00'), +(796,'ADD_ACCUMULATE',883,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(797,'ADD_ACCUMULATE',884,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(798,'ADD_ACCUMULATE',885,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(799,'ADD_ACCUMULATE',886,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(800,'ADD_ACCUMULATE',887,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(801,'ADD_ACCUMULATE',888,NULL,'{\"report_date\":\"2025-09-15\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-15 06:50:01'), +(802,'ADD_ACCUMULATE',889,NULL,'{\"report_date\":\"2025-09-16\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-16 06:51:19'), +(803,'ADD_ACCUMULATE',890,NULL,'{\"report_date\":\"2025-09-16\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-16 06:51:19'), +(804,'ADD_ACCUMULATE',891,NULL,'{\"report_date\":\"2025-09-16\",\"worker_id\":8,\"work_entries_count\":2,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-16 06:52:12'), +(805,'ADD_ACCUMULATE',893,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-17 06:43:08'), +(806,'ADD_ACCUMULATE',894,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-17 06:43:08'), +(807,'ADD_ACCUMULATE',895,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(808,'ADD_ACCUMULATE',896,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(809,'ADD_ACCUMULATE',897,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(810,'ADD_ACCUMULATE',898,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(811,'ADD_ACCUMULATE',899,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(812,'ADD_ACCUMULATE',900,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(813,'ADD_ACCUMULATE',901,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(814,'ADD_ACCUMULATE',902,NULL,'{\"report_date\":\"2025-09-17\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-17 06:45:06'), +(815,'ADD_ACCUMULATE',903,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:43:40'), +(816,'ADD_ACCUMULATE',904,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:43:40'), +(817,'ADD_ACCUMULATE',905,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(818,'ADD_ACCUMULATE',906,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(819,'ADD_ACCUMULATE',907,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(820,'ADD_ACCUMULATE',908,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(821,'ADD_ACCUMULATE',909,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:44:42'), +(822,'ADD_ACCUMULATE',910,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-18 06:46:39'), +(823,'ADD_ACCUMULATE',911,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-18 06:54:48'), +(824,'ADD_ACCUMULATE',912,NULL,'{\"report_date\":\"2025-09-18\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-18 06:54:48'), +(825,'ADD_ACCUMULATE',913,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:51:40'), +(826,'ADD_ACCUMULATE',914,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:51:40'), +(827,'ADD_ACCUMULATE',915,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(828,'ADD_ACCUMULATE',916,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(829,'ADD_ACCUMULATE',917,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(830,'ADD_ACCUMULATE',918,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(831,'ADD_ACCUMULATE',919,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:05'), +(832,'ADD_ACCUMULATE',920,NULL,'{\"report_date\":\"2025-09-19\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":4,\"my_total\":\"4.00\",\"grand_total\":4,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"4.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-19 06:52:23'), +(833,'ADD_ACCUMULATE',921,NULL,'{\"report_date\":\"2025-09-20\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-20 05:30:19'), +(834,'ADD_ACCUMULATE',922,NULL,'{\"report_date\":\"2025-09-20\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-20 05:30:19'), +(835,'ADD_ACCUMULATE',923,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(836,'ADD_ACCUMULATE',924,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(837,'ADD_ACCUMULATE',925,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(838,'ADD_ACCUMULATE',926,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(839,'ADD_ACCUMULATE',927,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(840,'ADD_ACCUMULATE',928,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-22 06:47:25'), +(841,'ADD_ACCUMULATE',929,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-22 06:50:29'), +(842,'ADD_ACCUMULATE',930,NULL,'{\"report_date\":\"2025-09-22\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-22 06:50:29'), +(843,'ADD_ACCUMULATE',931,NULL,'{\"report_date\":\"2025-09-23\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-23 05:46:40'), +(844,'ADD_ACCUMULATE',932,NULL,'{\"report_date\":\"2025-09-23\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-23 05:46:40'), +(845,'ADD_ACCUMULATE',933,NULL,'{\"report_date\":\"2025-09-24\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-25 01:14:58'), +(846,'ADD_ACCUMULATE',934,NULL,'{\"report_date\":\"2025-09-24\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-25 01:14:58'), +(847,'ADD_ACCUMULATE',935,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:07'), +(848,'ADD_ACCUMULATE',936,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:07'), +(849,'ADD_ACCUMULATE',937,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(850,'ADD_ACCUMULATE',938,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(851,'ADD_ACCUMULATE',939,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(852,'ADD_ACCUMULATE',940,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(853,'ADD_ACCUMULATE',941,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(854,'ADD_ACCUMULATE',942,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(855,'ADD_ACCUMULATE',943,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(856,'ADD_ACCUMULATE',944,NULL,'{\"report_date\":\"2025-09-29\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-29 06:36:47'), +(857,'ADD_ACCUMULATE',945,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(858,'ADD_ACCUMULATE',946,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(859,'ADD_ACCUMULATE',947,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(860,'ADD_ACCUMULATE',948,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(861,'ADD_ACCUMULATE',949,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(862,'ADD_ACCUMULATE',950,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:26'), +(863,'ADD_ACCUMULATE',951,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":3,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:27'), +(864,'ADD_ACCUMULATE',952,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:27'), +(865,'ADD_ACCUMULATE',953,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-09-30 06:52:27'), +(866,'DELETE',952,'{\"id\":952,\"report_date\":\"2025-09-30T00:00:00.000Z\",\"worker_id\":2,\"project_id\":3,\"work_type_id\":2,\"work_status_id\":1,\"error_type_id\":null,\"work_hours\":\"8.00\",\"created_at\":\"2025-09-30T06:52:27.000Z\",\"updated_at\":\"2025-09-30T06:52:27.000Z\",\"created_by\":3,\"updated_by\":null}',NULL,5,'Manual deletion',NULL,NULL,'2025-09-30 06:56:36'), +(867,'ADD_ACCUMULATE',954,NULL,'{\"report_date\":\"2025-09-30\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"임영규\",\"hours\":\"8.00\"}]}',5,'누적 추가 by 임영규 - 삭제 없음',NULL,NULL,'2025-09-30 06:56:55'), +(868,'ADD_ACCUMULATE',955,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":5,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 05:25:58'), +(869,'ADD_ACCUMULATE',956,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":6,\"my_total\":\"6.00\",\"grand_total\":6,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"6.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 05:25:59'), +(870,'ADD_ACCUMULATE',957,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":10,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:32'), +(871,'ADD_ACCUMULATE',958,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":9,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:32'), +(872,'ADD_ACCUMULATE',959,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":7,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:32'), +(873,'ADD_ACCUMULATE',960,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":6,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:32'), +(874,'ADD_ACCUMULATE',961,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:33'), +(875,'ADD_ACCUMULATE',962,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:33'), +(876,'ADD_ACCUMULATE',963,NULL,'{\"report_date\":\"2025-10-02\",\"worker_id\":1,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-02 06:22:33'), +(877,'ADD_ACCUMULATE',964,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":8,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-10 23:35:07'), +(878,'ADD_ACCUMULATE',965,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":4,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-10 23:35:07'), +(879,'ADD_ACCUMULATE',966,NULL,'{\"report_date\":\"2025-09-01\",\"worker_id\":2,\"work_entries_count\":1,\"added_hours\":8,\"my_total\":\"8.00\",\"grand_total\":8,\"contributors\":[{\"name\":\"김두수\",\"hours\":\"8.00\"}]}',3,'누적 추가 by 김두수 - 삭제 없음',NULL,NULL,'2025-10-10 23:35:07'); +/*!40000 ALTER TABLE `work_report_audit_log` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_report_defects` +-- + +DROP TABLE IF EXISTS `work_report_defects`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_report_defects` ( + `defect_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `report_id` int(11) NOT NULL COMMENT 'daily_work_reports의 id', + `error_type_id` int(11) DEFAULT NULL COMMENT 'error_types의 id (부적합 원인) - 레거시, issue_report_id 사용 권장', + `issue_report_id` int(10) unsigned DEFAULT NULL COMMENT 'work_issue_reports의 report_id (신고된 이슈 연결)', + `category_id` int(10) unsigned DEFAULT NULL COMMENT 'issue_report_categories의 category_id (직접 입력 시)', + `item_id` int(10) unsigned DEFAULT NULL COMMENT 'issue_report_items의 item_id (직접 입력 시)', + `defect_hours` decimal(4,1) NOT NULL DEFAULT 0.0 COMMENT '해당 원인의 부적합 시간', + `note` text DEFAULT NULL COMMENT '추가 메모', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`defect_id`), + UNIQUE KEY `work_report_defects_report_issue_unique` (`report_id`,`issue_report_id`), + KEY `work_report_defects_report_id_index` (`report_id`), + KEY `work_report_defects_error_type_id_index` (`error_type_id`), + KEY `work_report_defects_issue_report_id_index` (`issue_report_id`), + KEY `work_report_defects_category_id_foreign` (`category_id`), + KEY `work_report_defects_item_id_foreign` (`item_id`), + CONSTRAINT `work_report_defects_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `issue_report_categories` (`category_id`) ON DELETE SET NULL, + CONSTRAINT `work_report_defects_issue_report_id_foreign` FOREIGN KEY (`issue_report_id`) REFERENCES `work_issue_reports` (`report_id`) ON DELETE SET NULL, + CONSTRAINT `work_report_defects_item_id_foreign` FOREIGN KEY (`item_id`) REFERENCES `issue_report_items` (`item_id`) ON DELETE SET NULL, + CONSTRAINT `work_report_defects_report_id_foreign` FOREIGN KEY (`report_id`) REFERENCES `daily_work_reports` (`id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=21 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_report_defects` +-- + +LOCK TABLES `work_report_defects` WRITE; +/*!40000 ALTER TABLE `work_report_defects` DISABLE KEYS */; +INSERT INTO `work_report_defects` VALUES +(1,970,1,NULL,NULL,NULL,2.0,NULL,'2026-01-27 05:00:13'), +(2,972,1,NULL,NULL,NULL,4.0,NULL,'2026-01-27 05:09:53'), +(3,991,1,NULL,NULL,NULL,2.0,NULL,'2026-01-30 00:13:02'), +(4,973,5,NULL,NULL,NULL,4.0,NULL,'2026-01-27 05:11:47'), +(5,987,5,NULL,NULL,NULL,2.0,NULL,'2026-01-29 22:16:36'), +(6,990,5,NULL,NULL,NULL,2.0,NULL,'2026-01-29 22:16:36'), +(8,995,NULL,NULL,2,6,2.0,'치수가 nmm 안맞음(포인트 많이 고침)','2026-02-03 00:29:52'), +(9,995,NULL,3,NULL,NULL,1.0,NULL,'2026-02-03 00:29:52'), +(10,1639,NULL,3,NULL,NULL,1.0,NULL,'2026-02-03 04:28:40'), +(11,1639,NULL,NULL,1,2,2.0,NULL,'2026-02-03 04:28:40'), +(12,1644,NULL,NULL,5,42,4.0,NULL,'2026-02-04 22:52:41'), +(13,1676,NULL,NULL,13,43,2.0,NULL,'2026-02-04 23:22:54'), +(14,1679,NULL,NULL,4,44,8.0,'잘못된 정보를 전달함','2026-02-04 23:22:54'), +(15,1706,NULL,NULL,4,15,4.0,NULL,'2026-02-04 23:36:37'), +(16,1707,NULL,NULL,4,15,8.0,'설치 지연','2026-02-04 23:36:37'), +(17,1708,NULL,NULL,4,15,8.0,'설치 지연','2026-02-04 23:36:37'), +(18,1719,NULL,NULL,13,43,8.0,NULL,'2026-02-04 23:44:26'), +(19,1792,NULL,NULL,4,15,8.0,NULL,'2026-02-05 00:37:01'), +(20,1793,NULL,NULL,4,15,8.0,NULL,'2026-02-05 00:37:02'); +/*!40000 ALTER TABLE `work_report_defects` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_status_types` +-- + +DROP TABLE IF EXISTS `work_status_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_status_types` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(50) NOT NULL COMMENT '상태명', + `description` text DEFAULT NULL COMMENT '상태 설명', + `is_error` tinyint(1) DEFAULT 0 COMMENT '에러 상태 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_status_types` +-- + +LOCK TABLES `work_status_types` WRITE; +/*!40000 ALTER TABLE `work_status_types` DISABLE KEYS */; +INSERT INTO `work_status_types` VALUES +(1,'정규','정상적으로 완료된 작업',0,'2025-06-16 02:21:16'), +(2,'에러','오류가 발생한 작업',1,'2025-06-16 02:21:16'); +/*!40000 ALTER TABLE `work_status_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `work_types` +-- + +DROP TABLE IF EXISTS `work_types`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `work_types` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `name` varchar(100) NOT NULL COMMENT '작업 유형명', + `description` text DEFAULT NULL COMMENT '작업 유형 설명', + `category` varchar(50) DEFAULT NULL COMMENT '작업 카테고리', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `work_types` +-- + +LOCK TABLES `work_types` WRITE; +/*!40000 ALTER TABLE `work_types` DISABLE KEYS */; +INSERT INTO `work_types` VALUES +(1,'Base(구조물)',NULL,NULL,'2025-06-16 02:21:32','2025-06-16 03:03:42'), +(2,'Vessel(용기)',NULL,NULL,'2025-06-16 02:21:32','2025-06-16 03:03:47'), +(3,'Piping Assembly(배관)',NULL,NULL,'2025-06-16 02:21:32','2025-06-16 03:03:50'), +(4,'작업대기',NULL,NULL,'2025-06-16 02:21:32','2025-06-16 03:03:56'), +(11,'휴무','연차사용 등',NULL,'2025-11-04 05:53:46','2025-11-04 05:53:46'), +(12,'시설설비',NULL,NULL,'2026-02-04 21:52:07','2026-02-04 21:52:07'); +/*!40000 ALTER TABLE `work_types` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `worker_groups` +-- + +DROP TABLE IF EXISTS `worker_groups`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `worker_groups` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `group_leader_id` int(11) NOT NULL, + `worker_id` int(11) NOT NULL, + `group_name` varchar(100) DEFAULT NULL, + `is_active` tinyint(1) DEFAULT 1, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `uk_leader_worker` (`group_leader_id`,`worker_id`), + KEY `idx_group_leader` (`group_leader_id`), + KEY `idx_worker` (`worker_id`), + KEY `idx_is_active` (`is_active`), + CONSTRAINT `fk_group_leader` FOREIGN KEY (`group_leader_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE, + CONSTRAINT `fk_group_worker` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `worker_groups` +-- + +LOCK TABLES `worker_groups` WRITE; +/*!40000 ALTER TABLE `worker_groups` DISABLE KEYS */; +/*!40000 ALTER TABLE `worker_groups` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `worker_vacation_balance` +-- + +DROP TABLE IF EXISTS `worker_vacation_balance`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `worker_vacation_balance` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `worker_id` int(11) NOT NULL, + `year` int(11) NOT NULL, + `total_annual_leave` decimal(4,1) DEFAULT 15.0, + `used_annual_leave` decimal(4,1) DEFAULT 0.0, + `notes` text DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`id`), + UNIQUE KEY `unique_worker_year` (`worker_id`,`year`), + CONSTRAINT `worker_vacation_balance_ibfk_1` FOREIGN KEY (`worker_id`) REFERENCES `workers` (`worker_id`) ON DELETE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=20 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `worker_vacation_balance` +-- + +LOCK TABLES `worker_vacation_balance` WRITE; +/*!40000 ALTER TABLE `worker_vacation_balance` DISABLE KEYS */; +INSERT INTO `worker_vacation_balance` VALUES +(1,1,2026,15.0,0.0,NULL,'2026-01-19 01:40:31','2026-01-19 01:40:31'), +(11,2,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(12,4,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(13,5,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(14,6,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(15,7,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(16,8,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(17,9,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(18,10,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'), +(19,12,2026,15.0,0.0,NULL,'2026-01-19 01:40:56','2026-01-19 01:40:56'); +/*!40000 ALTER TABLE `worker_vacation_balance` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workers` +-- + +DROP TABLE IF EXISTS `workers`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workers` ( + `worker_id` int(11) NOT NULL AUTO_INCREMENT, + `worker_name` varchar(100) NOT NULL, + `join_date` date DEFAULT NULL, + `job_type` varchar(100) DEFAULT NULL, + `salary` decimal(10,2) DEFAULT NULL, + `annual_leave` int(11) DEFAULT NULL, + `status` enum('active','inactive') DEFAULT 'active' COMMENT '작업자 상태 (active: 활성, inactive: 비활성)', + `created_at` timestamp NULL DEFAULT current_timestamp(), + `updated_at` timestamp NULL DEFAULT current_timestamp(), + `phone_number` varchar(20) DEFAULT NULL COMMENT '전화번호', + `email` varchar(100) DEFAULT NULL COMMENT '이메일', + `hire_date` date DEFAULT NULL COMMENT '입사일', + `department` varchar(100) DEFAULT NULL COMMENT '부서', + `department_id` int(11) DEFAULT NULL, + `notes` text DEFAULT NULL COMMENT '비고', + `employment_status` enum('employed','resigned') NOT NULL DEFAULT 'employed' COMMENT '재직 상태 (employed: 재직, resigned: 퇴사)', + PRIMARY KEY (`worker_id`), + KEY `idx_workers_status` (`status`), + KEY `idx_workers_hire_date` (`hire_date`), + KEY `department_id` (`department_id`), + CONSTRAINT `workers_ibfk_1` FOREIGN KEY (`department_id`) REFERENCES `departments` (`department_id`) ON DELETE SET NULL +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workers` +-- + +LOCK TABLES `workers` WRITE; +/*!40000 ALTER TABLE `workers` DISABLE KEYS */; +INSERT INTO `workers` VALUES +(1,'김두수',NULL,'leader',NULL,NULL,'active','2025-04-15 13:23:17','2025-04-15 13:23:17',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(2,'임영규',NULL,'leader',NULL,NULL,'active','2025-04-15 13:23:17','2025-04-15 13:23:17',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(3,'반치원',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:22','2025-04-15 13:23:22',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(4,'황인용',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:33','2025-04-15 13:23:33',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(5,'표영진',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:38','2025-04-15 13:23:38',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(6,'김윤섭',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:46','2025-04-15 13:23:46',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(7,'이창호',NULL,'worker',NULL,NULL,'inactive','2025-04-15 13:23:51','2025-04-15 13:23:51',NULL,NULL,NULL,NULL,1,NULL,'resigned'), +(8,'최광욱',NULL,'worker',NULL,NULL,'active','2025-04-15 13:23:57','2025-04-15 13:23:57',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(9,'박현수',NULL,'worker',NULL,NULL,'active','2025-04-15 13:24:01','2025-04-15 13:24:01',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(10,'조윤호',NULL,'worker',NULL,NULL,'active','2025-04-15 13:24:07','2025-04-15 13:24:07',NULL,NULL,NULL,NULL,1,NULL,'employed'), +(11,'조승민',NULL,'worker',NULL,NULL,'active','2026-01-06 06:18:27','2026-01-06 06:18:27',NULL,NULL,'2026-01-05','생산팀',1,'용접사','employed'); +/*!40000 ALTER TABLE `workers` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_categories` +-- + +DROP TABLE IF EXISTS `workplace_categories`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_categories` ( + `category_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '카테고리 ID', + `category_name` varchar(100) NOT NULL COMMENT '카테고리명 (예: 제 1공장)', + `description` text DEFAULT NULL COMMENT '설명', + `display_order` int(11) DEFAULT 0 COMMENT '표시 순서', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성화 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '생성일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정일시', + `layout_image` varchar(500) DEFAULT NULL COMMENT '공장 배치도 이미지 경로', + PRIMARY KEY (`category_id`), + KEY `workplace_categories_is_active_index` (`is_active`), + KEY `workplace_categories_display_order_index` (`display_order`) +) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_categories` +-- + +LOCK TABLES `workplace_categories` WRITE; +/*!40000 ALTER TABLE `workplace_categories` DISABLE KEYS */; +INSERT INTO `workplace_categories` VALUES +(1,'제 1공장',NULL,1,1,'2026-01-26 05:28:52','2026-01-27 03:52:45','/uploads/workplace-layout-1769485965188-143426330.jpg'), +(2,'제 2공장',NULL,2,1,'2026-01-26 05:28:59','2026-01-26 05:28:59',NULL); +/*!40000 ALTER TABLE `workplace_categories` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_items` +-- + +DROP TABLE IF EXISTS `workplace_items`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_items` ( + `item_id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `workplace_id` int(10) unsigned NOT NULL COMMENT '작업장 ID', + `patrol_session_id` int(10) unsigned DEFAULT NULL COMMENT '등록한 순회점검 세션', + `project_id` int(11) DEFAULT NULL COMMENT '관련 프로젝트', + `item_type` enum('container','plate','material','tool','other') NOT NULL COMMENT '물품 유형', + `item_name` varchar(100) DEFAULT NULL COMMENT '물품명/설명', + `quantity` int(11) DEFAULT 1 COMMENT '수량', + `x_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 X 위치 (%)', + `y_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 Y 위치 (%)', + `width_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 너비 (%)', + `height_percent` decimal(5,2) DEFAULT NULL COMMENT '지도상 높이 (%)', + `is_active` tinyint(1) DEFAULT 1 COMMENT '현재 존재 여부', + `created_by` int(11) NOT NULL COMMENT '등록자 user_id', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_by` int(11) DEFAULT NULL COMMENT '최종 수정자 user_id', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`item_id`), + KEY `workplace_items_workplace_id_is_active_index` (`workplace_id`,`is_active`), + KEY `workplace_items_project_id_index` (`project_id`), + KEY `workplace_items_patrol_session_id_foreign` (`patrol_session_id`), + KEY `workplace_items_created_by_foreign` (`created_by`), + KEY `workplace_items_updated_by_foreign` (`updated_by`), + CONSTRAINT `workplace_items_created_by_foreign` FOREIGN KEY (`created_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `workplace_items_patrol_session_id_foreign` FOREIGN KEY (`patrol_session_id`) REFERENCES `daily_patrol_sessions` (`session_id`) ON DELETE SET NULL, + CONSTRAINT `workplace_items_project_id_foreign` FOREIGN KEY (`project_id`) REFERENCES `projects` (`project_id`) ON DELETE SET NULL, + CONSTRAINT `workplace_items_updated_by_foreign` FOREIGN KEY (`updated_by`) REFERENCES `users` (`user_id`), + CONSTRAINT `workplace_items_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_items` +-- + +LOCK TABLES `workplace_items` WRITE; +/*!40000 ALTER TABLE `workplace_items` DISABLE KEYS */; +/*!40000 ALTER TABLE `workplace_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_map_regions` +-- + +DROP TABLE IF EXISTS `workplace_map_regions`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_map_regions` ( + `region_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '영역 ID', + `workplace_id` int(10) unsigned NOT NULL COMMENT '작업장 ID', + `category_id` int(10) unsigned NOT NULL COMMENT '공장 카테고리 ID', + `x_start` decimal(5,2) NOT NULL COMMENT '시작 X 좌표 (%)', + `y_start` decimal(5,2) NOT NULL COMMENT '시작 Y 좌표 (%)', + `x_end` decimal(5,2) NOT NULL COMMENT '끝 X 좌표 (%)', + `y_end` decimal(5,2) NOT NULL COMMENT '끝 Y 좌표 (%)', + `shape` varchar(20) DEFAULT 'rect' COMMENT '영역 모양 (rect, circle, polygon)', + `polygon_points` text DEFAULT NULL COMMENT '다각형인 경우 좌표 배열 (JSON)', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`region_id`), + KEY `workplace_map_regions_workplace_id_foreign` (`workplace_id`), + KEY `workplace_map_regions_category_id_foreign` (`category_id`), + CONSTRAINT `workplace_map_regions_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE CASCADE ON UPDATE CASCADE, + CONSTRAINT `workplace_map_regions_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=12 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_map_regions` +-- + +LOCK TABLES `workplace_map_regions` WRITE; +/*!40000 ALTER TABLE `workplace_map_regions` DISABLE KEYS */; +INSERT INTO `workplace_map_regions` VALUES +(1,12,1,29.43,57.36,34.43,66.06,'rect',NULL,'2026-01-26 23:05:13','2026-01-26 23:05:13'), +(2,11,1,46.05,7.85,51.68,24.75,'rect',NULL,'2026-01-26 23:05:23','2026-01-26 23:05:23'), +(3,4,1,35.18,0.12,46.05,23.79,'rect',NULL,'2026-01-26 23:05:53','2026-01-26 23:05:53'), +(4,9,1,50.68,29.10,54.93,38.52,'rect',NULL,'2026-01-26 23:06:03','2026-01-26 23:06:03'), +(5,10,1,50.80,43.35,55.05,52.05,'rect',NULL,'2026-01-26 23:06:08','2026-01-26 23:06:08'), +(6,5,1,55.30,8.33,58.55,24.27,'rect',NULL,'2026-01-26 23:06:15','2026-01-26 23:06:15'), +(7,3,1,59.30,8.09,80.93,55.67,'rect',NULL,'2026-01-26 23:06:29','2026-01-26 23:06:29'), +(8,1,1,58.93,62.92,72.93,74.03,'rect',NULL,'2026-01-26 23:06:37','2026-01-26 23:06:37'), +(9,8,1,56.43,28.38,58.55,39.25,'rect',NULL,'2026-01-26 23:06:46','2026-01-26 23:06:46'), +(10,7,1,0.18,1.32,25.68,21.37,'rect',NULL,'2026-01-26 23:06:51','2026-01-26 23:06:51'), +(11,2,1,34.93,29.10,47.93,61.95,'rect',NULL,'2026-01-26 23:06:59','2026-01-26 23:06:59'); +/*!40000 ALTER TABLE `workplace_map_regions` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_visit_requests` +-- + +DROP TABLE IF EXISTS `workplace_visit_requests`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_visit_requests` ( + `request_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '신청 ID', + `requester_id` int(11) NOT NULL COMMENT '신청자 user_id', + `visitor_company` varchar(200) NOT NULL COMMENT '방문자 소속 (회사명 또는 "일용직")', + `visitor_count` int(11) DEFAULT 1 COMMENT '방문 인원', + `category_id` int(10) unsigned NOT NULL COMMENT '방문 구역 (공장)', + `workplace_id` int(10) unsigned NOT NULL COMMENT '방문 작업장', + `visit_date` date NOT NULL COMMENT '방문 날짜', + `visit_time` time NOT NULL COMMENT '방문 시간', + `purpose_id` int(10) unsigned NOT NULL COMMENT '방문 목적 ID', + `notes` text DEFAULT NULL COMMENT '비고', + `status` enum('pending','approved','rejected','training_completed') DEFAULT 'pending' COMMENT '신청 상태', + `approved_by` int(11) DEFAULT NULL COMMENT '승인자 user_id', + `approved_at` timestamp NULL DEFAULT NULL COMMENT '승인 시간', + `rejection_reason` text DEFAULT NULL COMMENT '반려 사유', + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`request_id`), + KEY `workplace_visit_requests_requester_id_foreign` (`requester_id`), + KEY `workplace_visit_requests_category_id_foreign` (`category_id`), + KEY `workplace_visit_requests_workplace_id_foreign` (`workplace_id`), + KEY `workplace_visit_requests_purpose_id_foreign` (`purpose_id`), + KEY `workplace_visit_requests_approved_by_foreign` (`approved_by`), + KEY `idx_visit_date` (`visit_date`), + KEY `idx_status` (`status`), + KEY `idx_visit_date_status` (`visit_date`,`status`), + CONSTRAINT `workplace_visit_requests_approved_by_foreign` FOREIGN KEY (`approved_by`) REFERENCES `users` (`user_id`) ON DELETE SET NULL ON UPDATE CASCADE, + CONSTRAINT `workplace_visit_requests_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON UPDATE CASCADE, + CONSTRAINT `workplace_visit_requests_purpose_id_foreign` FOREIGN KEY (`purpose_id`) REFERENCES `visit_purpose_types` (`purpose_id`) ON UPDATE CASCADE, + CONSTRAINT `workplace_visit_requests_requester_id_foreign` FOREIGN KEY (`requester_id`) REFERENCES `users` (`user_id`) ON UPDATE CASCADE, + CONSTRAINT `workplace_visit_requests_workplace_id_foreign` FOREIGN KEY (`workplace_id`) REFERENCES `workplaces` (`workplace_id`) ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_visit_requests` +-- + +LOCK TABLES `workplace_visit_requests` WRITE; +/*!40000 ALTER TABLE `workplace_visit_requests` DISABLE KEYS */; +INSERT INTO `workplace_visit_requests` VALUES +(1,1,'test',1,1,2,'2026-01-29','15:48:00',3,NULL,'approved',1,'2026-01-29 05:54:04',NULL,'2026-01-29 05:48:54','2026-01-29 05:54:04'), +(2,1,'테스트',2,1,1,'2026-01-29','16:11:00',2,NULL,'training_completed',1,'2026-01-29 06:11:38',NULL,'2026-01-29 06:11:23','2026-01-29 06:12:11'), +(3,1,'test',2,1,2,'2026-01-30','10:13:00',1,NULL,'approved',1,'2026-01-30 00:13:57',NULL,'2026-01-30 00:13:49','2026-01-30 00:13:57'); +/*!40000 ALTER TABLE `workplace_visit_requests` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplace_zone_items` +-- + +DROP TABLE IF EXISTS `workplace_zone_items`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplace_zone_items` ( + `item_id` int(11) NOT NULL AUTO_INCREMENT, + `workplace_id` int(11) NOT NULL, + `item_name` varchar(200) NOT NULL COMMENT '물품/시설물 명칭', + `item_type` varchar(50) DEFAULT 'general' COMMENT '유형 (heavy_equipment, hazardous, storage, general 등)', + `description` text DEFAULT NULL COMMENT '상세 설명', + `x_percent` decimal(5,2) NOT NULL COMMENT '영역 시작 X 좌표 (%)', + `y_percent` decimal(5,2) NOT NULL COMMENT '영역 시작 Y 좌표 (%)', + `width_percent` decimal(5,2) DEFAULT 10.00 COMMENT '영역 너비 (%)', + `height_percent` decimal(5,2) DEFAULT 10.00 COMMENT '영역 높이 (%)', + `color` varchar(20) DEFAULT '#3b82f6' COMMENT '표시 색상', + `warning_level` varchar(20) DEFAULT 'normal' COMMENT '주의 수준 (normal, caution, danger)', + `quantity` int(11) DEFAULT 1 COMMENT '수량', + `unit` varchar(20) DEFAULT '개' COMMENT '단위', + `weight_kg` decimal(10,2) DEFAULT NULL COMMENT '중량 (kg)', + `is_active` tinyint(1) DEFAULT 1, + `created_by` int(11) DEFAULT NULL, + `created_at` timestamp NOT NULL DEFAULT current_timestamp(), + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(), + PRIMARY KEY (`item_id`), + KEY `idx_workplace` (`workplace_id`), + KEY `idx_type` (`item_type`) +) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='구역 내 등록 물품/시설물'; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplace_zone_items` +-- + +LOCK TABLES `workplace_zone_items` WRITE; +/*!40000 ALTER TABLE `workplace_zone_items` DISABLE KEYS */; +INSERT INTO `workplace_zone_items` VALUES +(1,2,'용기 동체(대기중)','temp_storage','',21.28,1.37,77.27,29.64,'#3b82f6','good',1,'개',NULL,1,1,'2026-02-05 06:28:36','2026-02-05 06:28:36'); +/*!40000 ALTER TABLE `workplace_zone_items` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Table structure for table `workplaces` +-- + +DROP TABLE IF EXISTS `workplaces`; +/*!40101 SET @saved_cs_client = @@character_set_client */; +/*!40101 SET character_set_client = utf8 */; +CREATE TABLE `workplaces` ( + `workplace_id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '작업장 ID', + `category_id` int(10) unsigned DEFAULT NULL COMMENT '카테고리 ID (공장)', + `workplace_name` varchar(255) NOT NULL COMMENT '작업장명', + `description` text DEFAULT NULL COMMENT '설명', + `is_active` tinyint(1) DEFAULT 1 COMMENT '활성화 여부', + `created_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '생성일시', + `updated_at` timestamp NOT NULL DEFAULT current_timestamp() COMMENT '수정일시', + `workplace_purpose` varchar(50) DEFAULT NULL COMMENT '작업장 용도 (작업구역, 설비, 휴게시설, 회의실 등)', + `display_priority` int(11) DEFAULT 0 COMMENT '표시 우선순위 (숫자가 작을수록 먼저 표시)', + `layout_image` varchar(500) DEFAULT NULL COMMENT '작업장 레이아웃 이미지 경로', + PRIMARY KEY (`workplace_id`), + KEY `workplaces_category_id_index` (`category_id`), + KEY `workplaces_is_active_index` (`is_active`), + CONSTRAINT `workplaces_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `workplace_categories` (`category_id`) ON DELETE SET NULL ON UPDATE CASCADE +) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; +/*!40101 SET character_set_client = @saved_cs_client */; + +-- +-- Dumping data for table `workplaces` +-- + +LOCK TABLES `workplaces` WRITE; +/*!40000 ALTER TABLE `workplaces` DISABLE KEYS */; +INSERT INTO `workplaces` VALUES +(1,1,'서스작업장',NULL,1,'2026-01-26 05:29:18','2026-01-26 23:28:46','작업구역',1,NULL), +(2,1,'조립구역',NULL,1,'2026-01-26 05:29:30','2026-02-04 00:26:04','작업구역',0,'/uploads/workplace-layout-1770162560033-681774067.jpg'), +(3,1,'외부작업장',NULL,1,'2026-01-26 05:29:36','2026-01-26 23:28:35','작업구역',2,NULL), +(4,1,'입고장',NULL,1,'2026-01-26 05:29:41','2026-01-26 23:28:30','작업구역',2,NULL), +(5,1,'생산팀 창고',NULL,1,'2026-01-26 05:29:48','2026-01-26 23:28:16','창고',3,NULL), +(6,1,'검사장비 창고',NULL,1,'2026-01-26 05:29:57','2026-01-26 23:28:21','창고',3,NULL), +(7,1,'2층 가공장',NULL,1,'2026-01-26 05:30:04','2026-01-26 23:28:08','작업구역',2,NULL), +(8,1,'1층 가공장',NULL,1,'2026-01-26 05:30:09','2026-01-26 23:25:00','작업구역',2,NULL), +(9,1,'조방A',NULL,1,'2026-01-26 05:30:17','2026-01-26 23:24:56','작업구역',1,NULL), +(10,1,'조방B',NULL,1,'2026-01-26 05:30:26','2026-01-26 23:24:51','작업구역',1,NULL), +(11,1,'NDE룸',NULL,1,'2026-01-26 05:30:36','2026-01-26 23:24:45','설비',2,NULL), +(12,1,'휴게실',NULL,1,'2026-01-26 05:30:44','2026-01-26 23:24:38','휴게시설',3,NULL), +(13,NULL,'테스트 구역',NULL,1,'2026-02-05 06:48:37','2026-02-05 06:48:37','설비',0,NULL); +/*!40000 ALTER TABLE `workplaces` ENABLE KEYS */; +UNLOCK TABLES; + +-- +-- Dumping routines for database 'hyungi' +-- +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +-- Dump completed on 2026-02-05 23:53:06 diff --git a/deploy/tkfb-package/deploy.sh b/deploy/tkfb-package/deploy.sh new file mode 100755 index 0000000..1157b20 --- /dev/null +++ b/deploy/tkfb-package/deploy.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# ============================================================================= +# TK-FB-Project Synology NAS 배포 스크립트 +# ============================================================================= + +set -e + +echo "==========================================" +echo "TK-FB-Project 배포 시작" +echo "==========================================" + +# 1. 환경 변수 파일 확인 +if [ ! -f .env ]; then + echo "❌ .env 파일이 없습니다." + echo " .env.synology 파일을 복사하고 값을 수정하세요:" + echo " cp .env.synology .env" + exit 1 +fi + +# 2. Cloudflare Tunnel 토큰 확인 +if grep -q "여기에_터널_토큰_입력" .env; then + echo "⚠️ Cloudflare Tunnel 토큰이 설정되지 않았습니다." + echo " .env 파일에서 CLOUDFLARE_TUNNEL_TOKEN을 설정하세요." +fi + +# 3. Docker 이미지 빌드 +echo "" +echo "🔨 Docker 이미지 빌드 중..." +docker-compose -f docker-compose.synology.yml build --no-cache + +# 4. 기존 컨테이너 중지 +echo "" +echo "🛑 기존 컨테이너 중지 중..." +docker-compose -f docker-compose.synology.yml down 2>/dev/null || true + +# 5. 컨테이너 시작 +echo "" +echo "🚀 컨테이너 시작 중..." +docker-compose -f docker-compose.synology.yml up -d + +# 6. DB 초기화 대기 +echo "" +echo "⏳ 데이터베이스 초기화 대기 중 (30초)..." +sleep 30 + +# 7. 데이터베이스 복원 (백업 파일이 있는 경우) +BACKUP_FILE=$(ls -t backup_*.sql 2>/dev/null | head -1) +if [ -n "$BACKUP_FILE" ]; then + echo "" + echo "📦 데이터베이스 복원 중: $BACKUP_FILE" + docker exec -i tkfb_db mysql -u root -p"$MYSQL_ROOT_PASSWORD" < "$BACKUP_FILE" + echo "✅ 데이터베이스 복원 완료" +fi + +# 8. 상태 확인 +echo "" +echo "==========================================" +echo "📊 컨테이너 상태" +echo "==========================================" +docker-compose -f docker-compose.synology.yml ps + +echo "" +echo "==========================================" +echo "✅ 배포 완료!" +echo "==========================================" +echo "" +echo "접속 URL:" +echo " - Web UI: http://localhost:80" +echo " - API: http://localhost:3005" +echo " - phpMyAdmin: http://localhost:8080" +echo "" +echo "Cloudflare Tunnel 설정 시:" +echo " - 외부 접속: https://your-domain.com" +echo "" diff --git a/deploy/tkfb-package/docker-compose.yml b/deploy/tkfb-package/docker-compose.yml new file mode 100644 index 0000000..6adf764 --- /dev/null +++ b/deploy/tkfb-package/docker-compose.yml @@ -0,0 +1,150 @@ +version: "3.8" + +services: + # MariaDB 데이터베이스 + db: + image: mariadb:10.9 + container_name: tkfb_db + restart: unless-stopped + environment: + - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} + - MYSQL_DATABASE=${MYSQL_DATABASE:-hyungi} + - MYSQL_USER=${MYSQL_USER:-hyungi_user} + - MYSQL_PASSWORD=${MYSQL_PASSWORD} + volumes: + - db_data:/var/lib/mysql + - ./init-db:/docker-entrypoint-initdb.d + ports: + - "3306:3306" + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + timeout: 20s + retries: 10 + networks: + - tkfb_network + + # Node.js API 서버 + api: + build: + context: ./api.hyungi.net + dockerfile: Dockerfile + container_name: tkfb_api + env_file: + - ./.env + depends_on: + db: + condition: service_healthy + redis: + condition: service_started + restart: unless-stopped + ports: + - "3005:3005" + environment: + - NODE_ENV=production + - PORT=3005 + - DB_HOST=db + - DB_PORT=3306 + - DB_USER=${MYSQL_USER:-hyungi_user} + - DB_PASSWORD=${MYSQL_PASSWORD} + - DB_NAME=${MYSQL_DATABASE:-hyungi} + - DB_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} + - JWT_SECRET=${JWT_SECRET} + - JWT_EXPIRES_IN=${JWT_EXPIRES_IN:-7d} + - JWT_REFRESH_SECRET=${JWT_REFRESH_SECRET} + - JWT_REFRESH_EXPIRES_IN=${JWT_REFRESH_EXPIRES_IN:-30d} + - REDIS_HOST=redis + - REDIS_PORT=6379 + - WEATHER_API_URL=${WEATHER_API_URL:-} + - WEATHER_API_KEY=${WEATHER_API_KEY:-} + volumes: + - ./api.hyungi.net/uploads:/usr/src/app/uploads + - ./api.hyungi.net/logs:/usr/src/app/logs + logging: + driver: "json-file" + options: + max-size: "10m" + max-file: "3" + networks: + - tkfb_network + + # Web UI (Nginx) + web: + build: + context: ./web-ui + dockerfile: Dockerfile + container_name: tkfb_web + restart: unless-stopped + ports: + - "80:80" + volumes: + - ./web-ui:/usr/share/nginx/html:ro + depends_on: + - api + networks: + - tkfb_network + + # FastAPI Bridge + fastapi: + build: + context: ./fastapi-bridge + dockerfile: Dockerfile + container_name: tkfb_fastapi + restart: unless-stopped + ports: + - "8000:8000" + environment: + - API_BASE_URL=http://api:3005 + depends_on: + - api + networks: + - tkfb_network + + # Redis Cache + redis: + image: redis:6-alpine + container_name: tkfb_redis + restart: unless-stopped + expose: + - "6379" + networks: + - tkfb_network + + # Cloudflare Tunnel + cloudflared: + image: cloudflare/cloudflared:latest + container_name: tkfb_cloudflared + restart: unless-stopped + command: tunnel --no-autoupdate run + environment: + - TUNNEL_TOKEN=${CLOUDFLARE_TUNNEL_TOKEN} + depends_on: + - web + - api + networks: + - tkfb_network + + # phpMyAdmin (선택사항 - 보안상 제거 권장) + phpmyadmin: + image: phpmyadmin/phpmyadmin:latest + container_name: tkfb_phpmyadmin + depends_on: + - db + restart: unless-stopped + ports: + - "8080:80" + environment: + - PMA_HOST=db + - PMA_USER=root + - PMA_PASSWORD=${MYSQL_ROOT_PASSWORD} + - UPLOAD_LIMIT=50M + networks: + - tkfb_network + +volumes: + db_data: + driver: local + +networks: + tkfb_network: + driver: bridge + name: tkfb_network diff --git a/deploy/tkfb-package/fastapi-bridge/Dockerfile b/deploy/tkfb-package/fastapi-bridge/Dockerfile new file mode 100644 index 0000000..9d73f64 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/Dockerfile @@ -0,0 +1,21 @@ +FROM python:3.9-slim + +WORKDIR /app + +# 시스템 패키지 업데이트 및 필요한 패키지 설치 +RUN apt-get update && apt-get install -y \ + gcc \ + && rm -rf /var/lib/apt/lists/* + +# Python 의존성 설치 +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +# 애플리케이션 코드 복사 +COPY . . + +# 포트 노출 +EXPOSE 8000 + +# 애플리케이션 실행 +CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/README.md b/deploy/tkfb-package/fastapi-bridge/README.md new file mode 100644 index 0000000..abce877 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/README.md @@ -0,0 +1,69 @@ +# FastAPI 브릿지 + +## 📋 개요 + +Technical Korea 생산팀 포털의 FastAPI 브릿지입니다. Express.js API의 성능을 향상시키고 확장성을 제공합니다. + +## 🏗️ 아키텍처 + +``` +브라우저 → FastAPI (포트 8000) → Express.js API (포트 3005) +``` + +## 🚀 빠른 시작 + +### 개발 환경 + +```bash +# 가상환경 생성 +python -m venv venv +source venv/bin/activate # Windows: venv\Scripts\activate + +# 의존성 설치 +pip install -r requirements.txt + +# 서버 실행 +python main.py +``` + +### Docker 실행 + +```bash +# 이미지 빌드 +docker build -t tk-fastapi-bridge . + +# 컨테이너 실행 +docker run -p 8000:8000 tk-fastapi-bridge +``` + +## 📡 API 엔드포인트 + +### 헬스체크 +- `GET /` - 루트 정보 +- `GET /health` - 전체 시스템 헬스체크 + +### 프록시 +- `ALL /api/*` - Express.js API로 프록시 + +## 🔧 설정 + +`config.py`에서 설정을 변경할 수 있습니다: + +- `FASTAPI_PORT`: FastAPI 서버 포트 (기본: 8000) +- `EXPRESS_API_URL`: Express.js API URL (기본: http://localhost:3005) +- `CORS_ORIGINS`: CORS 허용 오리진 + +## 📊 Phase 1 목표 + +- [x] 기본 FastAPI 설정 +- [x] Express.js API 프록시 +- [x] 헬스체크 및 모니터링 +- [x] Docker 지원 +- [x] CORS 설정 + +## 🔮 다음 단계 (Phase 2) + +- [ ] 정적 파일 서빙 +- [ ] 단일 포트 통합 +- [ ] Redis 캐싱 +- [ ] 성능 최적화 \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/analytics.py b/deploy/tkfb-package/fastapi-bridge/analytics.py new file mode 100644 index 0000000..0b4122c --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/analytics.py @@ -0,0 +1,314 @@ +""" +FastAPI 브릿지 분석 시스템 +Phase 4: 데이터 분석 및 성능 모니터링 +""" +import time +import json +import asyncio +from typing import Dict, List, Any, Optional +from collections import defaultdict, deque +from dataclasses import dataclass, asdict +from datetime import datetime, timedelta + +import aiohttp +from fastapi import Request, Response + +from config import settings + +@dataclass +class RequestMetric: + """요청 메트릭 데이터 클래스""" + timestamp: float + method: str + path: str + status_code: int + response_time: float + cache_hit: bool = False + user_agent: Optional[str] = None + ip_address: Optional[str] = None + +class AnalyticsManager: + """분석 데이터 관리자""" + + def __init__(self, max_entries: int = 10000): + self.max_entries = max_entries + self.metrics: deque = deque(maxlen=max_entries) + self.cache_stats = { + "hits": 0, + "misses": 0, + "total_requests": 0 + } + + # 실시간 통계 + self.hourly_stats = defaultdict(lambda: { + "requests": 0, + "avg_response_time": 0, + "cache_hit_rate": 0, + "errors": 0 + }) + + # API 엔드포인트별 통계 + self.endpoint_stats = defaultdict(lambda: { + "requests": 0, + "avg_response_time": 0, + "min_response_time": float('inf'), + "max_response_time": 0, + "cache_hits": 0, + "errors": 0 + }) + + # 클라이언트 IP별 통계 + self.client_stats = defaultdict(lambda: { + "requests": 0, + "last_request": None, + "user_agents": set() + }) + + def record_request(self, metric: RequestMetric): + """요청 메트릭 기록""" + self.metrics.append(metric) + + # 전체 통계 업데이트 + self.cache_stats["total_requests"] += 1 + if metric.cache_hit: + self.cache_stats["hits"] += 1 + else: + self.cache_stats["misses"] += 1 + + # 시간대별 통계 업데이트 + hour_key = datetime.fromtimestamp(metric.timestamp).strftime("%Y-%m-%d_%H") + hourly = self.hourly_stats[hour_key] + hourly["requests"] += 1 + + # 평균 응답시간 계산 (이동평균) + if hourly["avg_response_time"] == 0: + hourly["avg_response_time"] = metric.response_time + else: + hourly["avg_response_time"] = ( + hourly["avg_response_time"] * 0.9 + metric.response_time * 0.1 + ) + + if metric.status_code >= 400: + hourly["errors"] += 1 + + # 엔드포인트별 통계 업데이트 + endpoint_key = f"{metric.method}:{metric.path}" + endpoint = self.endpoint_stats[endpoint_key] + endpoint["requests"] += 1 + + # 응답시간 통계 + if endpoint["avg_response_time"] == 0: + endpoint["avg_response_time"] = metric.response_time + else: + endpoint["avg_response_time"] = ( + endpoint["avg_response_time"] * 0.9 + metric.response_time * 0.1 + ) + + endpoint["min_response_time"] = min( + endpoint["min_response_time"], metric.response_time + ) + endpoint["max_response_time"] = max( + endpoint["max_response_time"], metric.response_time + ) + + if metric.cache_hit: + endpoint["cache_hits"] += 1 + + if metric.status_code >= 400: + endpoint["errors"] += 1 + + # 클라이언트별 통계 업데이트 + if metric.ip_address: + client = self.client_stats[metric.ip_address] + client["requests"] += 1 + client["last_request"] = metric.timestamp + if metric.user_agent: + client["user_agents"].add(metric.user_agent) + + def get_summary_stats(self) -> Dict[str, Any]: + """요약 통계 반환""" + total_requests = self.cache_stats["total_requests"] + cache_hit_rate = 0 + if total_requests > 0: + cache_hit_rate = (self.cache_stats["hits"] / total_requests) * 100 + + # 최근 1시간 통계 + recent_metrics = [ + m for m in self.metrics + if time.time() - m.timestamp < 3600 + ] + + avg_response_time = 0 + if recent_metrics: + avg_response_time = sum(m.response_time for m in recent_metrics) / len(recent_metrics) + + return { + "total_requests": total_requests, + "cache_hit_rate": round(cache_hit_rate, 2), + "recent_hour_requests": len(recent_metrics), + "avg_response_time_ms": round(avg_response_time * 1000, 2), + "active_clients": len([ + ip for ip, stats in self.client_stats.items() + if time.time() - (stats["last_request"] or 0) < 3600 + ]), + "total_endpoints": len(self.endpoint_stats) + } + + def get_top_endpoints(self, limit: int = 10) -> List[Dict[str, Any]]: + """상위 엔드포인트 통계""" + sorted_endpoints = sorted( + self.endpoint_stats.items(), + key=lambda x: x[1]["requests"], + reverse=True + ) + + result = [] + for endpoint, stats in sorted_endpoints[:limit]: + method, path = endpoint.split(":", 1) + cache_rate = 0 + if stats["requests"] > 0: + cache_rate = (stats["cache_hits"] / stats["requests"]) * 100 + + result.append({ + "method": method, + "path": path, + "requests": stats["requests"], + "avg_response_time_ms": round(stats["avg_response_time"] * 1000, 2), + "min_response_time_ms": round(stats["min_response_time"] * 1000, 2) if stats["min_response_time"] != float('inf') else 0, + "max_response_time_ms": round(stats["max_response_time"] * 1000, 2), + "cache_hit_rate": round(cache_rate, 2), + "error_count": stats["errors"] + }) + + return result + + def get_hourly_trends(self, hours: int = 24) -> Dict[str, List]: + """시간대별 트렌드 데이터""" + now = datetime.now() + trends = { + "hours": [], + "requests": [], + "avg_response_times": [], + "error_rates": [] + } + + for i in range(hours): + hour = now - timedelta(hours=i) + hour_key = hour.strftime("%Y-%m-%d_%H") + + stats = self.hourly_stats.get(hour_key, { + "requests": 0, + "avg_response_time": 0, + "errors": 0 + }) + + error_rate = 0 + if stats["requests"] > 0: + error_rate = (stats["errors"] / stats["requests"]) * 100 + + trends["hours"].insert(0, hour.strftime("%H:00")) + trends["requests"].insert(0, stats["requests"]) + trends["avg_response_times"].insert(0, round(stats["avg_response_time"] * 1000, 2)) + trends["error_rates"].insert(0, round(error_rate, 2)) + + return trends + + def get_client_analysis(self) -> Dict[str, Any]: + """클라이언트 분석""" + total_clients = len(self.client_stats) + active_clients = len([ + ip for ip, stats in self.client_stats.items() + if time.time() - (stats["last_request"] or 0) < 3600 + ]) + + # 상위 클라이언트 + top_clients = sorted( + self.client_stats.items(), + key=lambda x: x[1]["requests"], + reverse=True + )[:10] + + client_list = [] + for ip, stats in top_clients: + client_list.append({ + "ip": ip, + "requests": stats["requests"], + "last_request": datetime.fromtimestamp(stats["last_request"]).isoformat() if stats["last_request"] else None, + "user_agents": len(stats["user_agents"]) + }) + + return { + "total_clients": total_clients, + "active_clients_1h": active_clients, + "top_clients": client_list + } + + def predict_load(self) -> Dict[str, Any]: + """간단한 부하 예측""" + recent_hours = [] + for i in range(3): # 최근 3시간 + hour = datetime.now() - timedelta(hours=i) + hour_key = hour.strftime("%Y-%m-%d_%H") + stats = self.hourly_stats.get(hour_key, {"requests": 0}) + recent_hours.append(stats["requests"]) + + if len(recent_hours) >= 2: + # 단순 선형 트렌드 + trend = recent_hours[0] - recent_hours[1] if len(recent_hours) > 1 else 0 + predicted_next_hour = max(0, recent_hours[0] + trend) + else: + predicted_next_hour = recent_hours[0] if recent_hours else 0 + + return { + "current_hour_requests": recent_hours[0] if recent_hours else 0, + "predicted_next_hour": round(predicted_next_hour), + "trend": "increasing" if trend > 0 else "decreasing" if trend < 0 else "stable" if 'trend' in locals() else "unknown" + } + +# 전역 분석 매니저 +analytics_manager = AnalyticsManager() + +class AnalyticsMiddleware: + """분석 미들웨어""" + + def __init__(self, app): + self.app = app + + async def __call__(self, scope, receive, send): + if scope["type"] != "http": + await self.app(scope, receive, send) + return + + request = Request(scope, receive) + start_time = time.time() + + # 응답 캡처를 위한 래퍼 + response_data = {"status_code": 200} + + async def send_wrapper(message): + if message["type"] == "http.response.start": + response_data["status_code"] = message["status"] + await send(message) + + # 요청 처리 + await self.app(scope, receive, send_wrapper) + + # 메트릭 기록 + end_time = time.time() + response_time = end_time - start_time + + # 캐시 히트 여부는 로그에서 추측 (간단한 구현) + cache_hit = "/cache/" in request.url.path or response_time < 0.01 + + metric = RequestMetric( + timestamp=start_time, + method=request.method, + path=request.url.path, + status_code=response_data["status_code"], + response_time=response_time, + cache_hit=cache_hit, + user_agent=request.headers.get("user-agent"), + ip_address=request.client.host if request.client else None + ) + + analytics_manager.record_request(metric) \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/cache.py b/deploy/tkfb-package/fastapi-bridge/cache.py new file mode 100644 index 0000000..8d12cfc --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/cache.py @@ -0,0 +1,204 @@ +""" +FastAPI 브릿지 캐싱 시스템 +Phase 3: Redis 캐싱 (메모리 캐시로 폴백) +""" +import asyncio +import hashlib +import json +import time +from typing import Any, Dict, Optional, Union +from functools import wraps + +import redis.asyncio as redis + +from config import settings + +class CacheManager: + """캐시 관리자 - Redis 우선, 메모리 캐시 폴백""" + + def __init__(self): + self.redis_client: Optional[redis.Redis] = None + self.memory_cache: Dict[str, Dict[str, Any]] = {} + self.is_redis_available = False + + async def connect(self): + """Redis 연결 시도, 실패시 메모리 캐시 사용""" + try: + self.redis_client = redis.from_url( + settings.REDIS_URL, + decode_responses=True, + socket_connect_timeout=5, + socket_timeout=5 + ) + + # Redis 연결 테스트 + await self.redis_client.ping() + self.is_redis_available = True + print("✅ Redis 연결 성공") + + except Exception as e: + print(f"⚠️ Redis 연결 실패, 메모리 캐시 사용: {e}") + self.is_redis_available = False + self.redis_client = None + + async def disconnect(self): + """연결 종료""" + if self.redis_client: + await self.redis_client.close() + + def _generate_key(self, prefix: str, *args, **kwargs) -> str: + """캐시 키 생성""" + # 파라미터들을 문자열로 변환 + key_data = f"{prefix}:{':'.join(map(str, args))}" + if kwargs: + key_data += f":{json.dumps(kwargs, sort_keys=True)}" + + # 긴 키는 해시로 단축 + if len(key_data) > 100: + key_hash = hashlib.md5(key_data.encode()).hexdigest() + return f"{prefix}:{key_hash}" + + return key_data + + async def get(self, key: str) -> Optional[Any]: + """캐시에서 값 조회""" + if self.is_redis_available and self.redis_client: + try: + value = await self.redis_client.get(key) + if value: + return json.loads(value) + except Exception as e: + print(f"Redis GET 오류: {e}") + + # 메모리 캐시 폴백 + if key in self.memory_cache: + cache_entry = self.memory_cache[key] + if cache_entry['expires_at'] > time.time(): + return cache_entry['data'] + else: + # 만료된 캐시 삭제 + del self.memory_cache[key] + + return None + + async def set(self, key: str, value: Any, ttl: int = 300) -> bool: + """캐시에 값 저장""" + json_value = json.dumps(value, ensure_ascii=False) + + if self.is_redis_available and self.redis_client: + try: + await self.redis_client.setex(key, ttl, json_value) + return True + except Exception as e: + print(f"Redis SET 오류: {e}") + + # 메모리 캐시 폴백 + self.memory_cache[key] = { + 'data': value, + 'expires_at': time.time() + ttl + } + + # 메모리 캐시 크기 제한 (최대 1000개) + if len(self.memory_cache) > 1000: + # 가장 오래된 10개 항목 제거 + sorted_keys = sorted( + self.memory_cache.keys(), + key=lambda k: self.memory_cache[k]['expires_at'] + ) + for key_to_remove in sorted_keys[:10]: + del self.memory_cache[key_to_remove] + + return True + + async def delete(self, key: str) -> bool: + """캐시에서 값 삭제""" + deleted = False + + if self.is_redis_available and self.redis_client: + try: + result = await self.redis_client.delete(key) + deleted = result > 0 + except Exception as e: + print(f"Redis DELETE 오류: {e}") + + # 메모리 캐시에서도 삭제 + if key in self.memory_cache: + del self.memory_cache[key] + deleted = True + + return deleted + + async def clear_pattern(self, pattern: str) -> int: + """패턴 매칭으로 키 삭제""" + deleted_count = 0 + + if self.is_redis_available and self.redis_client: + try: + keys = await self.redis_client.keys(pattern) + if keys: + deleted_count = await self.redis_client.delete(*keys) + except Exception as e: + print(f"Redis CLEAR_PATTERN 오류: {e}") + + # 메모리 캐시에서 패턴 매칭 삭제 + import fnmatch + keys_to_delete = [ + key for key in self.memory_cache.keys() + if fnmatch.fnmatch(key, pattern) + ] + + for key in keys_to_delete: + del self.memory_cache[key] + deleted_count += 1 + + return deleted_count + + def get_stats(self) -> Dict[str, Any]: + """캐시 통계""" + stats = { + "redis_available": self.is_redis_available, + "memory_cache_size": len(self.memory_cache), + "cache_type": "Redis" if self.is_redis_available else "Memory" + } + + # 만료된 메모리 캐시 정리 + current_time = time.time() + expired_keys = [ + key for key, entry in self.memory_cache.items() + if entry['expires_at'] <= current_time + ] + + for key in expired_keys: + del self.memory_cache[key] + + stats["expired_keys_cleaned"] = len(expired_keys) + + return stats + +# 전역 캐시 매니저 +cache_manager = CacheManager() + +def cached(prefix: str = "default", ttl: int = 300): + """캐싱 데코레이터""" + def decorator(func): + @wraps(func) + async def wrapper(*args, **kwargs): + # 캐시 키 생성 + cache_key = cache_manager._generate_key(prefix, *args, **kwargs) + + # 캐시에서 조회 + cached_result = await cache_manager.get(cache_key) + if cached_result is not None: + print(f"🟢 캐시 히트: {cache_key}") + return cached_result + + # 캐시 미스 - 함수 실행 + print(f"🟡 캐시 미스: {cache_key}") + result = await func(*args, **kwargs) + + # 결과 캐싱 + await cache_manager.set(cache_key, result, ttl) + + return result + return wrapper + return decorator \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/config.py b/deploy/tkfb-package/fastapi-bridge/config.py new file mode 100644 index 0000000..65696b3 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/config.py @@ -0,0 +1,40 @@ +""" +FastAPI 브릿지 설정 +""" +import os +from typing import List + +class Settings: + # 기본 설정 + FASTAPI_PORT: int = int(os.getenv("FASTAPI_PORT", "8000")) + EXPRESS_API_URL: str = os.getenv("EXPRESS_API_URL", "http://api:20005") + REDIS_URL: str = os.getenv("REDIS_URL", "redis://localhost:6379") + NODE_ENV: str = os.getenv("NODE_ENV", "development") + + # CORS 설정 + CORS_ORIGINS: List[str] = [ + "http://localhost:3000", + "http://localhost:8000", + "https://api.technicalkorea.com" + ] + + # 로깅 + LOG_LEVEL: str = os.getenv("LOG_LEVEL", "INFO") + + # API 설정 + API_V1_PREFIX: str = "/api" + PROJECT_NAME: str = "TK FastAPI Bridge" + VERSION: str = "1.0.0" + + # 프록시 설정 + PROXY_TIMEOUT: int = 30 + MAX_CONNECTIONS: int = 100 + + # 캐시 설정 + CACHE_DEFAULT_TTL: int = 300 # 5분 + CACHE_HEALTH_TTL: int = 60 # 1분 + CACHE_AUTH_TTL: int = 900 # 15분 + CACHE_API_TTL: int = 180 # 3분 + CACHE_STATIC_TTL: int = 3600 # 1시간 + +settings = Settings() \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/docker-compose.yml b/deploy/tkfb-package/fastapi-bridge/docker-compose.yml new file mode 100644 index 0000000..a737188 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/docker-compose.yml @@ -0,0 +1,17 @@ +version: "3.8" + +services: + fastapi-bridge: + build: + context: . + dockerfile: Dockerfile + container_name: fastapi_bridge_hyungi + restart: unless-stopped + ports: + - "20010:8000" + networks: + - hyungi_network + +networks: + hyungi_network: + external: true diff --git a/deploy/tkfb-package/fastapi-bridge/main.py b/deploy/tkfb-package/fastapi-bridge/main.py new file mode 100644 index 0000000..52e266b --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/main.py @@ -0,0 +1,294 @@ +""" +FastAPI 브릿지 메인 애플리케이션 +Phase 1: 기본 프록시 기능 +""" +import asyncio +import logging +from typing import Any, Dict + +import aiohttp +import uvicorn +from fastapi import FastAPI, Request, HTTPException +from fastapi.middleware.cors import CORSMiddleware +from fastapi.responses import JSONResponse, FileResponse +from fastapi.staticfiles import StaticFiles + +from config import settings +from cache import cache_manager, cached +from analytics import analytics_manager, AnalyticsMiddleware + +# 로깅 설정 +logging.basicConfig(level=getattr(logging, settings.LOG_LEVEL)) +logger = logging.getLogger(__name__) + +# FastAPI 앱 생성 +app = FastAPI( + title=settings.PROJECT_NAME, + version=settings.VERSION, + description="Technical Korea FastAPI Bridge - Express.js API 프록시" +) + +# CORS 설정 +app.add_middleware( + CORSMiddleware, + allow_origins=settings.CORS_ORIGINS, + allow_credentials=True, + allow_methods=["*"], + allow_headers=["*"], +) + +# 분석 미들웨어 추가 +app.add_middleware(AnalyticsMiddleware) + +# 정적 파일 서빙 설정 +app.mount("/static", StaticFiles(directory="static"), name="static") +app.mount("/css", StaticFiles(directory="static/css"), name="css") +app.mount("/js", StaticFiles(directory="static/js"), name="js") +app.mount("/img", StaticFiles(directory="static/img"), name="img") +app.mount("/pages", StaticFiles(directory="static/pages"), name="pages") +app.mount("/components", StaticFiles(directory="static/components"), name="components") + +# HTTP 클라이언트 세션 (전역) +http_session: aiohttp.ClientSession = None + +@app.on_event("startup") +async def startup_event(): + """앱 시작시 초기화""" + global http_session + + # 캐시 매니저 연결 + await cache_manager.connect() + + # HTTP 클라이언트 세션 생성 + connector = aiohttp.TCPConnector( + limit=settings.MAX_CONNECTIONS, + ttl_dns_cache=300, + use_dns_cache=True, + ) + + timeout = aiohttp.ClientTimeout(total=settings.PROXY_TIMEOUT) + http_session = aiohttp.ClientSession( + connector=connector, + timeout=timeout + ) + + logger.info(f"🚀 {settings.PROJECT_NAME} v{settings.VERSION} 시작됨") + logger.info(f"📍 포트: {settings.FASTAPI_PORT}") + logger.info(f"🔗 Express.js API: {settings.EXPRESS_API_URL}") + + # 캐시 상태 로깅 + cache_stats = cache_manager.get_stats() + logger.info(f"💾 캐시: {cache_stats['cache_type']} ({'연결됨' if cache_stats['redis_available'] else '메모리 모드'})") + +@app.on_event("shutdown") +async def shutdown_event(): + """앱 종료시 정리""" + global http_session + + # 캐시 매니저 연결 종료 + await cache_manager.disconnect() + + if http_session: + await http_session.close() + + logger.info("✅ FastAPI 브릿지가 정상적으로 종료되었습니다") + +@app.get("/") +async def root(): + """루트 경로 - index.html 서빙""" + return FileResponse("static/index.html") + +@app.get("/status") +async def status(): + """서비스 상태 정보""" + return { + "service": settings.PROJECT_NAME, + "version": settings.VERSION, + "status": "healthy", + "express_api": settings.EXPRESS_API_URL + } + +@app.get("/health") +@cached(prefix="health", ttl=settings.CACHE_HEALTH_TTL) +async def health_check(): + """헬스체크 엔드포인트 (캐싱 적용)""" + try: + # Express.js API 헬스체크 + async with http_session.get(f"{settings.EXPRESS_API_URL}/api/health") as response: + express_status = "healthy" if response.status == 200 else "unhealthy" + express_data = await response.json() if response.status == 200 else None + except Exception as e: + logger.error(f"Express.js 헬스체크 실패: {e}") + express_status = "unhealthy" + express_data = None + + import datetime + return { + "fastapi_bridge": "healthy", + "express_api": express_status, + "express_data": express_data, + "timestamp": datetime.datetime.utcnow().isoformat() + "Z", + "cached": True + } + +@app.get("/cache/stats") +async def cache_stats(): + """캐시 통계 조회""" + stats = cache_manager.get_stats() + return { + "cache_stats": stats, + "settings": { + "default_ttl": settings.CACHE_DEFAULT_TTL, + "health_ttl": settings.CACHE_HEALTH_TTL, + "auth_ttl": settings.CACHE_AUTH_TTL, + "api_ttl": settings.CACHE_API_TTL, + "static_ttl": settings.CACHE_STATIC_TTL + } + } + +@app.delete("/cache/clear") +async def clear_cache(): + """캐시 전체 삭제""" + cleared_count = await cache_manager.clear_pattern("*") + return { + "message": "캐시가 삭제되었습니다", + "cleared_keys": cleared_count + } + +# ========================================== +# Phase 4: 분석 및 모니터링 API +# ========================================== + +@app.get("/analytics/summary") +async def analytics_summary(): + """분석 요약 통계""" + return { + "analytics": analytics_manager.get_summary_stats(), + "cache": cache_manager.get_stats(), + "prediction": analytics_manager.predict_load() + } + +@app.get("/analytics/endpoints") +async def analytics_endpoints(limit: int = 20): + """엔드포인트별 성능 통계""" + return { + "top_endpoints": analytics_manager.get_top_endpoints(limit), + "total_tracked": len(analytics_manager.endpoint_stats) + } + +@app.get("/analytics/trends") +async def analytics_trends(hours: int = 24): + """시간대별 트렌드 분석""" + return { + "trends": analytics_manager.get_hourly_trends(hours), + "period_hours": hours + } + +@app.get("/analytics/clients") +async def analytics_clients(): + """클라이언트 분석""" + return analytics_manager.get_client_analysis() + +@app.get("/analytics/dashboard") +async def analytics_dashboard(): + """종합 대시보드 데이터""" + return { + "summary": analytics_manager.get_summary_stats(), + "top_endpoints": analytics_manager.get_top_endpoints(10), + "trends_6h": analytics_manager.get_hourly_trends(6), + "clients": analytics_manager.get_client_analysis(), + "cache_stats": cache_manager.get_stats(), + "prediction": analytics_manager.predict_load(), + "server_info": { + "version": settings.VERSION, + "environment": settings.NODE_ENV, + "redis_available": cache_manager.is_redis_available + } + } + +@app.api_route("/api/{path:path}", methods=["GET", "POST", "PUT", "DELETE", "PATCH"]) +async def proxy_to_express(path: str, request: Request) -> Dict[str, Any]: + """Express.js API로 모든 요청을 프록시 (GET 요청은 캐싱 적용)""" + + # Express.js API URL 구성 + target_url = f"{settings.EXPRESS_API_URL}/api/{path}" + + # 요청 데이터 준비 + headers = dict(request.headers) + headers.pop("host", None) # host 헤더 제거 + + params = dict(request.query_params) + + # GET 요청에 대해서만 캐싱 적용 + if request.method == "GET": + cache_key = cache_manager._generate_key("api", path, **params) + cached_result = await cache_manager.get(cache_key) + + if cached_result is not None: + logger.info(f"🟢 캐시 히트: GET {target_url}") + return JSONResponse( + content=cached_result, + status_code=200 + ) + + try: + # 요청 바디 읽기 (있는 경우) + body = None + if request.method in ["POST", "PUT", "PATCH"]: + body = await request.body() + if body: + body = body.decode("utf-8") if isinstance(body, bytes) else body + + logger.info(f"🔗 프록시: {request.method} {target_url}") + + # Express.js API로 요청 전달 + async with http_session.request( + method=request.method, + url=target_url, + headers=headers, + params=params, + data=body + ) as response: + + # 응답 데이터 읽기 + response_data = await response.text() + + # JSON으로 파싱 시도 + try: + response_json = await response.json() + except: + response_json = {"data": response_data} + + logger.info(f"✅ 응답: {response.status} ({len(response_data)} bytes)") + + # GET 요청 성공시 캐시에 저장 + if request.method == "GET" and response.status == 200: + await cache_manager.set(cache_key, response_json, settings.CACHE_API_TTL) + logger.info(f"💾 캐시 저장: GET {target_url}") + + return JSONResponse( + content=response_json, + status_code=response.status, + headers=dict(response.headers) + ) + + except aiohttp.ClientTimeout: + logger.error(f"⏰ 타임아웃: {target_url}") + raise HTTPException(status_code=504, detail="Gateway Timeout") + + except aiohttp.ClientError as e: + logger.error(f"🚫 클라이언트 오류: {e}") + raise HTTPException(status_code=502, detail="Bad Gateway") + + except Exception as e: + logger.error(f"💥 예상치 못한 오류: {e}") + raise HTTPException(status_code=500, detail="Internal Server Error") + +if __name__ == "__main__": + uvicorn.run( + "main:app", + host="0.0.0.0", + port=settings.FASTAPI_PORT, + reload=settings.NODE_ENV == "development", + log_level=settings.LOG_LEVEL.lower() + ) \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/requirements.txt b/deploy/tkfb-package/fastapi-bridge/requirements.txt new file mode 100644 index 0000000..e643d5d --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/requirements.txt @@ -0,0 +1,6 @@ +fastapi==0.104.1 +uvicorn[standard]==0.24.0 +aiohttp==3.9.1 +python-multipart==0.0.6 +redis==5.0.1 +python-dotenv==1.0.0 \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/Minutes/safety.html b/deploy/tkfb-package/fastapi-bridge/static/Minutes/safety.html new file mode 100644 index 0000000..677861e --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/Minutes/safety.html @@ -0,0 +1,1635 @@ + + + + + + 안전회의록 작성 + + + +
+
+

🏭 월간 안전회의록

+

테크니컬코리아 안전회의록 작성 및 관리 시스템

+
+ +
+ +
+ + + + +
+ + +
+
+
+ 하주현 선임 → 업무 인수인계 + 출산/육아휴직 대비 +
+
+
+ + + + +
+
+ +
+
+
+
+ + +
+
+
기존 회의록 참조 (미완료 항목)
+
+
+ + + + + +
+ +
+ 미완료 항목 0 | + 0개 표시됨 | + 완료된 항목 0 +
+ +
+ + +
+ +
+ +
+
+
+
+ + +
+
+
정기점검 사항
+
+
+ + + + +
+
+ 정기점검 사항 | + 0개 긴급, + 0개 예정 +
+
+ + +
+
+ +
+
+
+
+ + +
+ +
+
회의 기본정보
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ 논의사항 + +
+
+
+ +
+
+
+ +
+ + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/Minutes/인수인계관련/안전회의록 2025년 5월.xlsx b/deploy/tkfb-package/fastapi-bridge/static/Minutes/인수인계관련/안전회의록 2025년 5월.xlsx new file mode 100644 index 0000000..a8f1800 Binary files /dev/null and b/deploy/tkfb-package/fastapi-bridge/static/Minutes/인수인계관련/안전회의록 2025년 5월.xlsx differ diff --git a/deploy/tkfb-package/fastapi-bridge/static/components/navbar.html b/deploy/tkfb-package/fastapi-bridge/static/components/navbar.html new file mode 100644 index 0000000..dd96e0c --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/components/navbar.html @@ -0,0 +1,351 @@ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/components/sections/admin-sections.html b/deploy/tkfb-package/fastapi-bridge/static/components/sections/admin-sections.html new file mode 100644 index 0000000..6ec008d --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/components/sections/admin-sections.html @@ -0,0 +1,48 @@ + + + +
+

📄 작업 보고서

+ +
+ +
+

📊 출근/공수 관리

+ +
+ +
+

🔧 시스템 관리

+ +
+ +
+

🏭 공장 정보

+ +
+ +
+

📊 이슈 리포트

+ +
\ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/components/sidebar.html b/deploy/tkfb-package/fastapi-bridge/static/components/sidebar.html new file mode 100644 index 0000000..532fd6a --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/components/sidebar.html @@ -0,0 +1,136 @@ + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/admin.css b/deploy/tkfb-package/fastapi-bridge/static/css/admin.css new file mode 100644 index 0000000..14a27fe --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/admin.css @@ -0,0 +1,25 @@ +body { + font-family: 'Malgun Gothic', sans-serif; + margin: 0; + background: #f0f2f5; +} +.main-layout { + display: flex; +} +#sidebar-container { + width: 250px; + background: #1a237e; + color: white; + min-height: 100vh; +} +#content-container { + flex: 1; + padding: 30px; +} +h1, h2 { + color: #1976d2; +} +a { + color: #1976d2; + text-decoration: none; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/attendance-validation.css b/deploy/tkfb-package/fastapi-bridge/static/css/attendance-validation.css new file mode 100644 index 0000000..15184a3 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/attendance-validation.css @@ -0,0 +1,883 @@ +/* 근태 검증 관리 시스템 - 개선된 스타일 */ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + color: #333; + line-height: 1.6; + min-height: 100vh; +} + +/* 뒤로가기 버튼 */ +.back-btn { + background: rgba(255,255,255,0.95); + color: #667eea; + border: 3px solid #667eea; + padding: 12px 24px; + border-radius: 12px; + text-decoration: none; + font-weight: 700; + font-size: 16px; + display: inline-flex; + align-items: center; + gap: 8px; + margin-bottom: 24px; + transition: all 0.3s ease; + box-shadow: 0 3px 12px rgba(102, 126, 234, 0.2); +} + +.back-btn:hover { + background: #667eea; + color: white; + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3); +} + +/* 페이지 헤더 */ +.page-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border-radius: 16px; + padding: 2.5rem; + margin-bottom: 2rem; + box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +/* 메인 카드 */ +.main-card { + background: white; + border-radius: 16px; + padding: 2rem; + margin-bottom: 2rem; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + border: 1px solid rgba(255, 255, 255, 0.8); + backdrop-filter: blur(10px); + transition: all 0.3s ease; +} + +.main-card:hover { + transform: translateY(-2px); + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); +} + +.loading-card { + background: white; + border-radius: 16px; + padding: 3rem; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + text-align: center; +} + +/* 캘린더 헤더 */ +.calendar-header { + display: flex; + align-items: center; + justify-content: between; + margin-bottom: 2rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f0f0f0; +} + +.nav-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border: none; + border-radius: 12px; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); +} + +.nav-btn:hover { + transform: translateY(-2px) scale(1.05); + box-shadow: 0 6px 24px rgba(102, 126, 234, 0.4); +} + +/* 월간 요약 */ +.summary-section { + margin-bottom: 2rem; + padding: 1.5rem; + background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); + border-radius: 16px; + border: 1px solid rgba(102, 126, 234, 0.2); +} + +.summary-title { + text-align: center; + font-size: 1.25rem; + font-weight: 700; + color: #333; + margin-bottom: 1rem; +} + +.summary-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1.5rem; +} + +.summary-card { + background: white; + border-radius: 12px; + padding: 1.5rem; + text-align: center; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + border: 2px solid transparent; +} + +.summary-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.summary-card.normal { + border-color: #10b981; +} + +.summary-card.warning { + border-color: #f59e0b; +} + +.summary-card.error { + border-color: #ef4444; +} + +.summary-number { + font-size: 2rem; + font-weight: 800; + margin-bottom: 0.5rem; +} + +.summary-card.normal .summary-number { + color: #10b981; +} + +.summary-card.warning .summary-number { + color: #f59e0b; +} + +.summary-card.error .summary-number { + color: #ef4444; +} + +.summary-label { + font-size: 0.875rem; + font-weight: 600; + color: #666; +} + +/* 요일 헤더 */ +.weekday-header { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 0.5rem; + margin-bottom: 1rem; +} + +.weekday { + padding: 1rem; + text-align: center; + font-size: 0.875rem; + font-weight: 700; + color: #64748b; + background: #f8fafc; + border-radius: 8px; +} + +.weekday.sunday { + color: #ef4444; +} + +.weekday.saturday { + color: #3b82f6; +} + +/* 캘린더 그리드 */ +.calendar-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 0.5rem; + margin-bottom: 2rem; +} + +.calendar-day { + position: relative; + min-height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 12px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + background: white; + border: 2px solid #e2e8f0; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.calendar-day.hover-enabled:hover { + transform: translateY(-3px); + box-shadow: 0 6px 24px rgba(0, 0, 0, 0.15); + border-color: #3b82f6; +} + +.calendar-day.selected { + transform: scale(1.05); + z-index: 10; + border-color: #3b82f6; + box-shadow: 0 8px 32px rgba(59, 130, 246, 0.3); +} + +.calendar-day.loading-state { + background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%); + border-color: #3b82f6; + animation: loading-pulse 1.5s infinite; +} + +@keyframes loading-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.7; } +} + +.calendar-day.error-state { + background: linear-gradient(135deg, #fecaca 0%, #fca5a5 100%); + border-color: #ef4444; + color: #991b1b; +} + +.calendar-day.normal { + background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%); + border-color: #10b981; + color: #064e3b; +} + +.calendar-day.needs-review { + background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); + border-color: #f59e0b; + color: #92400e; +} + +.calendar-day.missing { + background: linear-gradient(135deg, #fecaca 0%, #fca5a5 100%); + border-color: #ef4444; + color: #991b1b; +} + +.calendar-day.no-data { + background: #f9fafb; + border-color: #e5e7eb; + color: #9ca3af; + position: relative; +} + +.calendar-day.no-data::after { + content: "클릭하여 확인"; + position: absolute; + bottom: 4px; + font-size: 10px; + color: #6b7280; + opacity: 0; + transition: opacity 0.3s; +} + +.calendar-day.no-data.hover-enabled:hover::after { + opacity: 1; +} + +.status-dot { + position: absolute; + top: 8px; + right: 8px; + width: 12px; + height: 12px; + border-radius: 50%; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; +} + +.status-dot.pulse { + animation: pulse 1s infinite; +} + +@keyframes pulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.2); } +} + +.status-dot.normal { + background: #10b981; +} + +.status-dot.warning { + background: #f59e0b; +} + +.status-dot.error { + background: #ef4444; +} + +/* 범례 */ +.legend { + display: flex; + justify-content: center; + gap: 2rem; + flex-wrap: wrap; +} + +.legend-item { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; + font-weight: 600; + color: #64748b; +} + +.legend-dot { + width: 16px; + height: 16px; + border-radius: 50%; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +.legend-dot.normal { + background: #10b981; +} + +.legend-dot.warning { + background: #f59e0b; +} + +.legend-dot.error { + background: #ef4444; +} + +/* 빈 상태 */ +.empty-state { + text-align: center; + padding: 4rem 2rem; +} + +.empty-icon { + font-size: 4rem; + margin-bottom: 1.5rem; +} + +.empty-title { + font-size: 1.5rem; + font-weight: 700; + color: #374151; + margin-bottom: 1rem; +} + +.empty-description { + color: #6b7280; + font-size: 1rem; + max-width: 500px; + margin: 0 auto; +} + +/* 작업자 카드 */ +.worker-card { + background: white; + border-radius: 16px; + padding: 1.5rem; + margin-bottom: 1.5rem; + border: 2px solid transparent; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); +} + +.worker-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.worker-card.normal { + background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%); + border-color: #10b981; +} + +.worker-card.needs-review { + background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%); + border-color: #f59e0b; +} + +.worker-card.missing { + background: linear-gradient(135deg, #fef2f2 0%, #fecaca 100%); + border-color: #ef4444; +} + +.worker-header { + display: flex; + justify-content: between; + align-items: center; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid rgba(0, 0, 0, 0.1); +} + +.worker-info { + display: flex; + align-items: center; + gap: 1rem; +} + +.worker-avatar { + width: 48px; + height: 48px; + background: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 1.25rem; + color: #374151; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.worker-name { + font-size: 1.25rem; + font-weight: 700; + color: #374151; +} + +.worker-id { + font-size: 0.875rem; + color: #6b7280; + margin-top: 0.25rem; +} + +.status-badge { + font-size: 1.5rem; + filter: drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.1)); +} + +/* 데이터 행 */ +.data-section { + background: rgba(255, 255, 255, 0.7); + border-radius: 12px; + padding: 1.5rem; + margin-bottom: 1rem; +} + +.data-row { + display: flex; + justify-content: between; + align-items: center; + padding: 0.75rem 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.data-row:last-child { + border-bottom: none; +} + +.data-label { + font-weight: 600; + color: #4b5563; +} + +.data-value { + font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace; + font-weight: 700; + font-size: 1rem; +} + +.difference-positive { + color: #dc2626; + background: rgba(220, 38, 38, 0.1); + padding: 0.25rem 0.75rem; + border-radius: 6px; + font-weight: 700; +} + +.difference-negative { + color: #2563eb; + background: rgba(37, 99, 235, 0.1); + padding: 0.25rem 0.75rem; + border-radius: 6px; + font-weight: 700; +} + +/* 버튼 */ +.btn-primary { + background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 12px; + font-weight: 700; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(59, 130, 246, 0.3); + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 6px 24px rgba(59, 130, 246, 0.4); +} + +.btn-secondary { + background: #6b7280; + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 12px; + font-weight: 700; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(107, 114, 128, 0.3); +} + +.btn-secondary:hover { + background: #4b5563; + transform: translateY(-2px); +} + +.edit-btn { + background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 8px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + font-size: 0.875rem; + width: 100%; + margin-top: 1rem; +} + +.edit-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(59, 130, 246, 0.3); +} + +.delete-btn { + background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); + color: white; + border: none; + padding: 0.5rem 1rem; + border-radius: 6px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + font-size: 0.75rem; + margin-left: 0.5rem; +} + +.delete-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3); +} + +/* 필터 */ +.filter-container { + display: flex; + justify-content: between; + align-items: center; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f0f0f0; +} + +.filter-select { + background: white; + border: 2px solid #e5e7eb; + border-radius: 8px; + padding: 0.75rem 1rem; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.filter-select:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* 모달 */ +.modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.75); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + animation: fadeIn 0.3s ease; +} + +.modal.hidden { + display: none; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.modal-content { + background: white; + border-radius: 20px; + width: 90%; + max-width: 500px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); + animation: slideIn 0.3s ease; +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-50px) scale(0.9); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.modal-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 1.5rem; + border-radius: 20px 20px 0 0; + display: flex; + justify-content: between; + align-items: center; +} + +.modal-header h3 { + margin: 0; + font-size: 1.25rem; + font-weight: 700; +} + +.close-btn { + background: rgba(255, 255, 255, 0.2); + color: white; + border: none; + border-radius: 50%; + width: 36px; + height: 36px; + cursor: pointer; + font-size: 1.25rem; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; +} + +.close-btn:hover { + background: rgba(255, 255, 255, 0.3); + transform: rotate(90deg); +} + +.modal-body { + padding: 1.5rem; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 1rem; + padding: 1.5rem; + border-top: 2px solid #f0f0f0; + background: #f8fafc; + border-radius: 0 0 20px 20px; +} + +/* 폼 요소 */ +.form-group { + margin-bottom: 1.5rem; +} + +.form-group label { + display: block; + margin-bottom: 0.5rem; + font-weight: 700; + color: #374151; + font-size: 0.875rem; +} + +.form-input { + width: 100%; + padding: 0.75rem 1rem; + border: 2px solid #e5e7eb; + border-radius: 8px; + font-size: 1rem; + transition: all 0.3s ease; +} + +.form-input:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.form-textarea { + width: 100%; + padding: 0.75rem 1rem; + border: 2px solid #e5e7eb; + border-radius: 8px; + font-size: 1rem; + resize: vertical; + min-height: 80px; + transition: all 0.3s ease; +} + +.form-textarea:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* 메시지 */ +.message { + padding: 1rem 1.5rem; + border-radius: 12px; + margin-bottom: 1.5rem; + font-weight: 600; + border: 2px solid transparent; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); +} + +.message.success { + background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%); + color: #065f46; + border-color: #10b981; +} + +.message.error { + background: linear-gradient(135deg, #fecaca 0%, #fca5a5 100%); + color: #991b1b; + border-color: #ef4444; +} + +.message.warning { + background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); + color: #92400e; + border-color: #f59e0b; +} + +.message.loading { + background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%); + color: #1e40af; + border-color: #3b82f6; +} + +/* 로딩 스피너 */ +.loading-spinner { + width: 32px; + height: 32px; + border: 3px solid #e5e7eb; + border-top: 3px solid #3b82f6; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* 애니메이션 */ +.fade-in { + animation: fadeInUp 0.5s ease-out; +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .summary-grid { + grid-template-columns: 1fr; + gap: 1rem; + } + + .calendar-day { + min-height: 60px; + font-size: 0.875rem; + } + + .worker-header { + flex-direction: column; + gap: 1rem; + text-align: center; + } + + .legend { + flex-direction: column; + gap: 1rem; + } + + .modal-content { + width: 95%; + margin: 1rem; + } + + .main-card { + padding: 1.5rem; + } + + .page-header { + padding: 2rem; + } +} + +@media (max-width: 480px) { + .calendar-day { + min-height: 50px; + font-size: 0.75rem; + } + + .summary-card { + padding: 1rem; + } + + .summary-number { + font-size: 1.5rem; + } + + .worker-card { + padding: 1rem; + } + + .modal-body, .modal-footer { + padding: 1rem; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/attendance.css b/deploy/tkfb-package/fastapi-bridge/static/css/attendance.css new file mode 100644 index 0000000..0b77e15 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/attendance.css @@ -0,0 +1,72 @@ +body { + font-family: Arial, sans-serif; + margin: 20px; + background: #f8f9fa; +} +h2 { + text-align: center; + color: #343a40; +} +.controls { + display: flex; + flex-wrap: wrap; + gap: 12px; + justify-content: center; + align-items: center; + margin-bottom: 16px; +} +.controls label { + font-weight: bold; +} +.controls select, +.controls button { + padding: 6px 10px; + border-radius: 4px; + border: 1px solid #ccc; + font-weight: bold; + cursor: pointer; +} +button#loadAttendance { + background-color: #4CAF50; + color: white; + border: none; +} +button#downloadPdf { + background-color: #007BFF; + color: white; + border: none; +} +#attendanceTableContainer { + max-height: 600px; + overflow: auto; +} +table { + width: 100%; + border-collapse: collapse; + margin-top: 10px; + font-size: 14px; +} +th, td { + border: 1px solid #ddd; + padding: 6px; + text-align: center; + background: white; +} +th { + background: #f2f2f2; +} +.divider { + border-left: 3px solid #333 !important; +} +tr.separator td { + border-bottom: 2px solid #999; + padding: 0; + height: 4px; + background: transparent; +} +.overtime-cell { background: #e9e5ff !important; } +.leave { background: #f5e0d6 !important; } +.holiday { background: #ffd6d6 !important; } +.paid-leave { background: #d6f0ff !important; } +.no-data { background: #ddd !important; } +.overtime-sum { background: #e9e5ff !important; } \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/daily-issue.css b/deploy/tkfb-package/fastapi-bridge/static/css/daily-issue.css new file mode 100644 index 0000000..827e7c7 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/daily-issue.css @@ -0,0 +1,90 @@ +/* /css/daily-issue.css */ + +body { + font-family: Arial, sans-serif; + background: #f5f7fa; + margin: 0; + padding: 40px 20px; +} + +.container { + max-width: 500px; + margin: auto; + background: #fff; + border-radius: 12px; + box-shadow: 0 0 10px rgba(0,0,0,0.05); + padding: 32px; +} + +h2 { + text-align: center; + color: #333; + margin-bottom: 24px; +} + +label { + display: block; + margin-top: 20px; + font-weight: bold; + color: #333; +} + +select, input[type="date"], button { + width: 100%; + padding: 10px; + margin-top: 6px; + border: 1px solid #ccc; + border-radius: 6px; + box-sizing: border-box; + font-size: 1rem; +} + +button#submitBtn { + margin-top: 30px; + background: #1976d2; + color: white; + border: none; + font-size: 1rem; + border-radius: 6px; + cursor: pointer; + transition: background 0.2s; +} + +button#submitBtn:hover { + background: #125cb1; +} + +.multi-select-box { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 8px; +} + +.multi-select-box .btn { + flex: 1 0 30%; + padding: 8px; + border: 1px solid #1976d2; + border-radius: 4px; + background: white; + color: #1976d2; + text-align: center; + cursor: pointer; + transition: background 0.2s, color 0.2s; +} + +.multi-select-box .btn.selected { + background: #1976d2; + color: white; +} + +.time-range { + display: flex; + gap: 8px; + align-items: center; + margin-top: 6px; +} + +.time-range select { + flex: 1; +} diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/daily-report-viewer.css b/deploy/tkfb-package/fastapi-bridge/static/css/daily-report-viewer.css new file mode 100644 index 0000000..6fc187b --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/daily-report-viewer.css @@ -0,0 +1,548 @@ +/* daily-report-viewer.css */ + +/* 전체 레이아웃 */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', -apple-system, BlinkMacSystemFont, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + color: #333; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; + min-height: 100vh; +} + +/* 헤더 */ +.page-header { + text-align: center; + margin-bottom: 30px; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 20px; + padding: 30px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); +} + +.page-header h1 { + font-size: 2.5rem; + font-weight: 700; + margin-bottom: 10px; + background: linear-gradient(135deg, #667eea, #764ba2); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.subtitle { + color: #666; + font-size: 1.1rem; + font-weight: 400; +} + +/* 날짜 선택기 */ +.date-selector { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 15px; + padding: 25px; + margin-bottom: 30px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); +} + +.date-input-group { + display: flex; + align-items: center; + gap: 15px; + flex-wrap: wrap; + justify-content: center; +} + +.date-input-group label { + font-weight: 600; + color: #333; + font-size: 1.1rem; +} + +.date-input { + padding: 12px 16px; + border: 2px solid #e1e5e9; + border-radius: 10px; + font-size: 1rem; + transition: all 0.3s ease; + background: white; + min-width: 150px; +} + +.date-input:focus { + outline: none; + border-color: #667eea; + box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); +} + +.search-btn, .today-btn { + padding: 12px 24px; + border: none; + border-radius: 10px; + font-size: 1rem; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.search-btn { + background: linear-gradient(135deg, #667eea, #764ba2); + color: white; +} + +.search-btn:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(102, 126, 234, 0.3); +} + +.today-btn { + background: #f8f9fa; + color: #667eea; + border: 2px solid #667eea; +} + +.today-btn:hover { + background: #667eea; + color: white; +} + +/* 로딩 스피너 */ +.loading-spinner { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 50px; + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 15px; + margin: 30px 0; +} + +.spinner { + width: 50px; + height: 50px; + border: 4px solid #f3f3f3; + border-top: 4px solid #667eea; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 15px; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.loading-spinner p { + color: #666; + font-size: 1.1rem; +} + +/* 에러 메시지 */ +.error-message { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 15px; + padding: 25px; + margin: 30px 0; + border-left: 5px solid #e74c3c; +} + +.error-content { + display: flex; + align-items: center; + gap: 12px; +} + +.error-icon { + font-size: 1.5rem; +} + +.error-text { + color: #e74c3c; + font-weight: 600; + font-size: 1.1rem; +} + +/* 데이터 없음 메시지 */ +.no-data-message { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 15px; + padding: 50px; + text-align: center; + margin: 30px 0; +} + +.no-data-content { + color: #666; +} + +.no-data-icon { + font-size: 3rem; + display: block; + margin-bottom: 20px; +} + +.no-data-content h3 { + font-size: 1.5rem; + margin-bottom: 10px; + color: #333; +} + +/* 요약 카드 */ +.report-summary { + margin-bottom: 30px; +} + +.summary-cards { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 20px; + margin-bottom: 30px; +} + +.summary-card { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 15px; + padding: 25px; + text-align: center; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + transition: transform 0.3s ease; +} + +.summary-card:hover { + transform: translateY(-5px); +} + +.summary-card.error-card { + border-left: 5px solid #e74c3c; +} + +.card-header { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + margin-bottom: 15px; +} + +.card-icon { + font-size: 1.5rem; +} + +.card-title { + font-weight: 600; + color: #666; + font-size: 0.9rem; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.card-value { + font-size: 2rem; + font-weight: 700; + color: #333; +} + +.error-card .card-value { + color: #e74c3c; +} + +/* 작업자 리포트 */ +.workers-report { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 15px; + padding: 30px; + margin-bottom: 30px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); +} + +.section-title { + font-size: 1.5rem; + font-weight: 700; + margin-bottom: 25px; + color: #333; + border-bottom: 3px solid #667eea; + padding-bottom: 10px; +} + +.workers-list { + display: flex; + flex-direction: column; + gap: 20px; +} + +.worker-card { + background: #f8f9fa; + border-radius: 12px; + padding: 20px; + border-left: 5px solid #667eea; + transition: all 0.3s ease; +} + +.worker-card:hover { + box-shadow: 0 5px 15px rgba(0, 0, 0, 0.1); + transform: translateX(5px); +} + +.worker-header { + display: flex; + justify-content: between; + align-items: center; + margin-bottom: 15px; + flex-wrap: wrap; + gap: 10px; +} + +.worker-name { + font-size: 1.3rem; + font-weight: 700; + color: #333; + display: flex; + align-items: center; + gap: 8px; +} + +.worker-total-hours { + background: linear-gradient(135deg, #667eea, #764ba2); + color: white; + padding: 8px 16px; + border-radius: 20px; + font-weight: 600; + font-size: 0.9rem; +} + +.work-entries { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 15px; +} + +.work-entry { + background: white; + border-radius: 8px; + padding: 15px; + border: 1px solid #e1e5e9; + transition: all 0.3s ease; +} + +.work-entry:hover { + border-color: #667eea; + box-shadow: 0 3px 10px rgba(102, 126, 234, 0.1); +} + +.work-entry.error-entry { + border-left: 4px solid #e74c3c; + background: #fff5f5; +} + +.entry-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 10px; +} + +.project-name { + font-weight: 600; + color: #333; + font-size: 1rem; +} + +.work-hours { + background: #e8f4f8; + color: #2c5aa0; + padding: 4px 12px; + border-radius: 15px; + font-weight: 600; + font-size: 0.9rem; +} + +.work-entry.error-entry .work-hours { + background: #ffebee; + color: #c62828; +} + +.entry-details { + display: flex; + flex-direction: column; + gap: 5px; + font-size: 0.9rem; + color: #666; +} + +.entry-detail { + display: flex; + justify-content: space-between; + align-items: center; +} + +.detail-label { + font-weight: 500; +} + +.detail-value { + color: #333; +} + +.error-type { + color: #e74c3c; + font-weight: 600; +} + +/* 내보내기 섹션 */ +.export-section { + background: rgba(255, 255, 255, 0.95); + backdrop-filter: blur(10px); + border-radius: 15px; + padding: 25px; + text-align: center; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); +} + +.export-section h3 { + font-size: 1.3rem; + font-weight: 700; + margin-bottom: 20px; + color: #333; +} + +.export-buttons { + display: flex; + justify-content: center; + gap: 15px; + flex-wrap: wrap; +} + +.export-btn { + padding: 12px 24px; + border: none; + border-radius: 10px; + font-size: 1rem; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + display: flex; + align-items: center; + gap: 8px; +} + +.excel-btn { + background: #217346; + color: white; +} + +.excel-btn:hover { + background: #1a5a37; + transform: translateY(-2px); +} + +.print-btn { + background: #495057; + color: white; +} + +.print-btn:hover { + background: #343a40; + transform: translateY(-2px); +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .container { + padding: 15px; + } + + .page-header { + padding: 20px; + } + + .page-header h1 { + font-size: 2rem; + } + + .date-input-group { + flex-direction: column; + align-items: stretch; + } + + .date-input-group > * { + width: 100%; + text-align: center; + } + + .summary-cards { + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + gap: 15px; + } + + .work-entries { + grid-template-columns: 1fr; + } + + .worker-header { + flex-direction: column; + align-items: flex-start; + } + + .export-buttons { + flex-direction: column; + } +} + +/* 인쇄 스타일 */ +@media print { + body { + background: white; + } + + .container { + max-width: none; + margin: 0; + padding: 20px; + } + + .date-selector, + .export-section { + display: none; + } + + .summary-card, + .workers-report, + .worker-card, + .work-entry { + background: white !important; + box-shadow: none !important; + border: 1px solid #ddd !important; + } + + .page-header { + background: white !important; + box-shadow: none !important; + border-bottom: 2px solid #333; + } + + .page-header h1 { + color: #333 !important; + -webkit-text-fill-color: #333 !important; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/daily-work-report.css b/deploy/tkfb-package/fastapi-bridge/static/css/daily-work-report.css new file mode 100644 index 0000000..71be400 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/daily-work-report.css @@ -0,0 +1,756 @@ +/* daily-work-report.css - 덮어쓰기 방지 완전 스타일 */ + +/* 기본 레이아웃 */ +.daily-work-report-container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; + font-family: 'Noto Sans KR', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; +} + +/* 단계 표시 */ +.steps-container { + display: flex; + justify-content: center; + margin-bottom: 30px; + position: relative; +} + +.step { + display: flex; + align-items: center; + margin: 0 20px; + opacity: 0.5; + transition: all 0.3s ease; +} + +.step.active { + opacity: 1; + transform: scale(1.1); +} + +.step.completed { + opacity: 1; +} + +.step-number { + width: 40px; + height: 40px; + border-radius: 50%; + background: linear-gradient(135deg, #e9ecef 0%, #adb5bd 100%); + display: flex; + align-items: center; + justify-content: center; + font-weight: bold; + color: #495057; + margin-right: 10px; + transition: all 0.3s ease; +} + +.step.active .step-number { + background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); + color: white; + box-shadow: 0 4px 15px rgba(0, 123, 255, 0.3); +} + +.step.completed .step-number { + background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%); + color: white; +} + +/* 🛡️ 보호 모드 표시기 */ +.protection-indicator { + position: fixed; + top: 20px; + right: 20px; + background: linear-gradient(135deg, #27ae60 0%, #229954 100%); + color: white; + padding: 10px 15px; + border-radius: 25px; + font-size: 12px; + font-weight: bold; + box-shadow: 0 2px 10px rgba(39, 174, 96, 0.3); + z-index: 1000; + border: 2px solid #1e8449; + animation: pulse-protection 2s infinite; +} + +.protection-indicator::before { + content: "🛡️"; + margin-right: 8px; +} + +@keyframes pulse-protection { + 0%, 100% { box-shadow: 0 2px 10px rgba(39, 174, 96, 0.3); } + 50% { box-shadow: 0 4px 20px rgba(39, 174, 96, 0.5); } +} + +/* 메시지 컨테이너 */ +.message-container { + margin-bottom: 20px; +} + +.message { + padding: 15px; + border-radius: 8px; + margin-bottom: 10px; + font-weight: 500; + border: 2px solid transparent; + transition: all 0.3s ease; +} + +.message.success { + background: linear-gradient(135deg, #28a745 0%, #20c997 100%); + color: white; + border-color: #1e7e34; + box-shadow: 0 4px 15px rgba(40, 167, 69, 0.3); +} + +.message.error { + background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); + color: white; + border-color: #bd2130; + box-shadow: 0 4px 15px rgba(220, 53, 69, 0.3); +} + +.message.warning { + background: linear-gradient(135deg, #f39c12 0%, #e67e22 100%); + color: white; + border-color: #d68910; + box-shadow: 0 4px 15px rgba(243, 156, 18, 0.3); + animation: fadeInShake 0.5s ease-out; +} + +.message.loading { + background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); + color: white; + border-color: #2471a3; + position: relative; + overflow: hidden; +} + +.message.loading::after { + content: ""; + position: absolute; + top: 0; + left: -100%; + width: 100%; + height: 100%; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.3), transparent); + animation: loading-shimmer 1.5s infinite; +} + +@keyframes loading-shimmer { + 0% { left: -100%; } + 100% { left: 100%; } +} + +@keyframes fadeInShake { + 0% { + opacity: 0; + transform: translateX(-10px); + } + 50% { + opacity: 1; + transform: translateX(5px); + } + 100% { + opacity: 1; + transform: translateX(0); + } +} + +/* 단계별 콘텐츠 */ +.step-content { + background: white; + border-radius: 12px; + padding: 30px; + margin-bottom: 20px; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1); + border: 2px solid #e9ecef; +} + +/* 1단계: 날짜 선택 */ +.date-selection { + text-align: center; +} + +.date-input { + padding: 15px; + font-size: 18px; + border: 2px solid #dee2e6; + border-radius: 8px; + width: 200px; + margin: 20px 0; + transition: all 0.3s ease; +} + +.date-input:focus { + border-color: #007bff; + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25); + outline: none; +} + +/* 2단계: 작업자 선택 */ +.worker-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 15px; + margin: 20px 0; +} + +.worker-btn { + padding: 15px; + border: 2px solid #dee2e6; + border-radius: 10px; + background: white; + cursor: pointer; + transition: all 0.3s ease; + font-weight: 500; + font-size: 14px; + position: relative; +} + +.worker-btn:hover { + border-color: #007bff; + background: #f8f9fa; + transform: translateY(-2px); + box-shadow: 0 4px 15px rgba(0, 123, 255, 0.2); +} + +.worker-btn.selected { + background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); + color: white; + border-color: #0056b3; + box-shadow: 0 4px 15px rgba(0, 123, 255, 0.3); +} + +/* 🚫 차단된 작업자 버튼 스타일 */ +.worker-btn.blocked { + background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%) !important; + color: white !important; + border: 2px solid #a93226 !important; + opacity: 0.7; + cursor: not-allowed !important; + position: relative; + animation: pulse-blocked 2s infinite; +} + +.worker-btn.blocked:hover { + transform: none !important; + box-shadow: none !important; +} + +.worker-btn.blocked::after { + content: "🚫"; + position: absolute; + top: -5px; + right: -5px; + background: #fff; + border-radius: 50%; + width: 20px; + height: 20px; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + border: 2px solid #e74c3c; +} + +@keyframes pulse-blocked { + 0%, 100% { opacity: 0.7; } + 50% { opacity: 0.5; } +} + +/* 3단계: 작업 입력 */ +.work-entries-container { + margin: 20px 0; +} + +.work-entry { + background: #f8f9fa; + border: 2px solid #e9ecef; + border-radius: 12px; + padding: 20px; + margin-bottom: 20px; + transition: all 0.3s ease; +} + +.work-entry:hover { + border-color: #007bff; + box-shadow: 0 4px 15px rgba(0, 123, 255, 0.1); +} + +.work-entry-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; +} + +.work-entry-title { + font-size: 18px; + font-weight: bold; + color: #495057; +} + +.remove-work-btn { + background: #dc3545; + color: white; + border: none; + border-radius: 50%; + width: 30px; + height: 30px; + cursor: pointer; + font-size: 18px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; +} + +.remove-work-btn:hover { + background: #c82333; + transform: scale(1.1); +} + +.work-entry-row { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 20px; + margin-bottom: 20px; +} + +.form-group { + display: flex; + flex-direction: column; +} + +.form-group label { + font-weight: bold; + margin-bottom: 8px; + color: #495057; + font-size: 14px; +} + +.large-select { + padding: 12px; + border: 2px solid #dee2e6; + border-radius: 8px; + font-size: 14px; + transition: all 0.3s ease; + background: white; +} + +.large-select:focus { + border-color: #007bff; + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.25); + outline: none; +} + +/* 에러 유형 섹션 */ +.error-type-section { + opacity: 0.5; + transition: all 0.3s ease; +} + +.error-type-section.visible { + opacity: 1; +} + +/* 시간 입력 */ +.time-input-row { + grid-column: 1 / -1; +} + +.quick-time-buttons { + display: flex; + gap: 10px; + margin-top: 10px; +} + +.quick-time-btn { + padding: 8px 15px; + background: #e9ecef; + border: 2px solid #dee2e6; + border-radius: 20px; + cursor: pointer; + font-size: 12px; + font-weight: bold; + transition: all 0.3s ease; +} + +.quick-time-btn:hover { + background: #007bff; + color: white; + border-color: #0056b3; + transform: translateY(-2px); +} + +/* 총 시간 표시 */ +.total-hours-display { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 15px; + border-radius: 10px; + text-align: center; + font-size: 18px; + font-weight: bold; + margin: 20px 0; + box-shadow: 0 4px 15px rgba(102, 126, 234, 0.3); +} + +/* 버튼 스타일 */ +.btn { + padding: 12px 25px; + border: 2px solid transparent; + border-radius: 8px; + font-weight: bold; + cursor: pointer; + transition: all 0.3s ease; + font-size: 14px; + text-decoration: none; + display: inline-block; +} + +.btn-primary { + background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); + color: white; + border-color: #0056b3; +} + +.btn-primary:hover { + background: linear-gradient(135deg, #0056b3 0%, #004085 100%); + transform: translateY(-2px); + box-shadow: 0 4px 15px rgba(0, 123, 255, 0.3); +} + +.btn-success { + background: linear-gradient(135deg, #28a745 0%, #1e7e34 100%); + color: white; + border-color: #1e7e34; +} + +.btn-success:hover { + background: linear-gradient(135deg, #1e7e34 0%, #155724 100%); + transform: translateY(-2px); + box-shadow: 0 4px 15px rgba(40, 167, 69, 0.3); +} + +.btn:disabled { + opacity: 0.6; + cursor: not-allowed; + transform: none !important; + box-shadow: none !important; +} + +/* 작업 추가 버튼 */ +.add-work-container { + text-align: center; + margin: 30px 0; +} + +.add-work-btn { + background: linear-gradient(135deg, #17a2b8 0%, #138496 100%); + color: white; + border: 2px solid #138496; + padding: 15px 30px; + border-radius: 25px; + font-size: 16px; + font-weight: bold; + cursor: pointer; + transition: all 0.3s ease; +} + +.add-work-btn:hover { + background: linear-gradient(135deg, #138496 0%, #0f6674 100%); + transform: translateY(-3px); + box-shadow: 0 6px 20px rgba(23, 162, 184, 0.3); +} + +/* 저장 버튼 */ +.submit-container { + text-align: center; + margin: 40px 0; +} + +.submit-btn { + background: linear-gradient(135deg, #28a745 0%, #20c997 100%); + color: white; + border: 2px solid #1e7e34; + padding: 18px 40px; + border-radius: 30px; + font-size: 18px; + font-weight: bold; + cursor: pointer; + transition: all 0.3s ease; +} + +.submit-btn:hover { + background: linear-gradient(135deg, #1e7e34 0%, #17a2b8 100%); + transform: translateY(-3px); + box-shadow: 0 8px 25px rgba(40, 167, 69, 0.4); +} + +/* 오늘 작업자 현황 */ +.daily-workers-section { + margin-top: 40px; + padding: 20px; + background: #f8f9fa; + border-radius: 12px; + border: 2px solid #e9ecef; +} + +.daily-workers-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 20px; + padding: 15px; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 10px; + border: 2px solid #5a6fd8; +} + +.daily-workers-header h4 { + margin: 0; + font-size: 16px; + font-weight: bold; +} + +.refresh-btn { + background: rgba(255, 255, 255, 0.2); + color: white; + border: 2px solid rgba(255, 255, 255, 0.3); + padding: 8px 15px; + border-radius: 20px; + cursor: pointer; + font-size: 12px; + font-weight: bold; + transition: all 0.3s ease; +} + +.refresh-btn:hover { + background: rgba(255, 255, 255, 0.3); + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2); +} + +/* 작업자 현황 그리드 */ +.worker-status-grid { + display: grid; + gap: 20px; +} + +.worker-status-item { + background: white; + border: 2px solid #e9ecef; + border-radius: 12px; + padding: 20px; + transition: all 0.3s ease; +} + +.worker-status-item:hover { + border-color: #007bff; + box-shadow: 0 4px 15px rgba(0, 123, 255, 0.1); +} + +.worker-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 15px; + padding-bottom: 10px; + border-bottom: 2px solid #e9ecef; +} + +.worker-name { + font-size: 18px; + font-weight: bold; + color: #495057; +} + +.worker-total-hours { + background: linear-gradient(135deg, #17a2b8 0%, #138496 100%); + color: white; + padding: 5px 15px; + border-radius: 15px; + font-size: 14px; + font-weight: bold; +} + +/* 개별 작업 항목 */ +.individual-works-container { + margin-top: 15px; +} + +.individual-work-item { + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + border: 2px solid #dee2e6; + border-radius: 10px; + padding: 15px; + margin-bottom: 10px; + transition: all 0.3s ease; +} + +.individual-work-item:hover { + background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%); + border-color: #adb5bd; + transform: translateY(-2px); + box-shadow: 0 4px 15px rgba(0, 0, 0, 0.1); +} + +.work-details-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 15px; + margin-bottom: 15px; +} + +.detail-item { + display: flex; + flex-direction: column; + gap: 5px; +} + +.detail-label { + font-size: 12px; + font-weight: bold; + color: #6c757d; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.detail-value { + font-size: 14px; + font-weight: 600; + color: #212529; + padding: 8px 12px; + background: white; + border: 1px solid #ced4da; + border-radius: 6px; +} + +/* 액션 버튼들 */ +.action-buttons { + display: flex; + gap: 10px; + justify-content: flex-end; +} + +.edit-btn, .delete-btn { + padding: 8px 15px; + border: none; + border-radius: 6px; + font-size: 12px; + font-weight: bold; + cursor: pointer; + transition: all 0.3s ease; +} + +.edit-btn { + background: linear-gradient(135deg, #3498db 0%, #2980b9 100%); + color: white; + border: 2px solid #2471a3; +} + +.edit-btn:hover { + background: linear-gradient(135deg, #2980b9 0%, #2471a3 100%); + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(52, 152, 219, 0.3); +} + +.delete-btn { + background: linear-gradient(135deg, #e74c3c 0%, #c0392b 100%); + color: white; + border: 2px solid #a93226; +} + +.delete-btn:hover { + background: linear-gradient(135deg, #c0392b 0%, #a93226 100%); + transform: translateY(-2px); + box-shadow: 0 4px 10px rgba(231, 76, 60, 0.3); +} + +/* 데이터 없음 메시지 */ +.no-data-message { + text-align: center; + padding: 40px; + color: #6c757d; + font-size: 16px; + line-height: 1.6; +} + +.no-data-message small { + display: block; + margin-top: 10px; + font-size: 14px; + color: #adb5bd; +} + +/* 로딩 스피너 */ +.loading-spinner { + text-align: center; + padding: 40px; + font-size: 16px; + color: #007bff; + font-weight: bold; +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .daily-work-report-container { + padding: 10px; + } + + .work-entry-row { + grid-template-columns: 1fr; + } + + .worker-grid { + grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); + gap: 10px; + } + + .work-details-grid { + grid-template-columns: 1fr; + } + + .daily-workers-header { + flex-direction: column; + gap: 10px; + text-align: center; + } + + .protection-indicator { + position: relative; + top: auto; + right: auto; + margin: 10px auto; + text-align: center; + } + + .steps-container { + flex-direction: column; + align-items: center; + } + + .step { + margin: 10px 0; + } +} + +@media (max-width: 480px) { + .worker-grid { + grid-template-columns: 1fr 1fr; + } + + .action-buttons { + flex-direction: column; + } + + .date-input { + width: 100%; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/factory.css b/deploy/tkfb-package/fastapi-bridge/static/css/factory.css new file mode 100644 index 0000000..e7dcd68 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/factory.css @@ -0,0 +1,61 @@ +body { + font-family: 'Segoe UI', sans-serif; + background-color: #f9f9f9; + margin: 0; + padding: 0; +} + +.container { + max-width: 600px; + margin: 50px auto; + background: #fff; + border-radius: 12px; + box-shadow: 0 4px 12px rgba(0,0,0,0.1); + padding: 30px; +} + +h2 { + text-align: center; + margin-bottom: 20px; + color: #333; +} + +form label { + display: block; + margin-bottom: 6px; + font-weight: bold; + color: #444; +} + +form input[type="text"], +form input[type="file"], +form textarea { + width: 100%; + padding: 10px; + margin-bottom: 16px; + border: 1px solid #ccc; + border-radius: 8px; + font-size: 14px; + box-sizing: border-box; +} + +form textarea { + resize: vertical; + min-height: 100px; +} + +button { + width: 100%; + background-color: #007bff; + color: white; + border: none; + padding: 12px; + font-size: 16px; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +button:hover { + background-color: #0056b3; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/login.css b/deploy/tkfb-package/fastapi-bridge/static/css/login.css new file mode 100644 index 0000000..3f9061e --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/login.css @@ -0,0 +1,54 @@ +body { + margin: 0; + padding: 0; + background: url('/img/login-bg.jpeg') no-repeat center center fixed; + background-size: cover; + font-family: 'Malgun Gothic', sans-serif; +} + +.login-container { + background: rgba(0, 0, 0, 0.65); + width: 400px; + padding: 40px; + margin: 100px auto; + border-radius: 12px; + text-align: center; + color: white; + box-shadow: 0 0 20px rgba(0,0,0,0.3); +} + +.logo { + width: 200px; + margin-bottom: 20px; +} + +input { + display: block; + width: 100%; + margin: 15px 0; + padding: 12px; + font-size: 1rem; + border-radius: 6px; + border: none; +} + +button { + padding: 12px 20px; + font-size: 1rem; + cursor: pointer; + border: none; + background-color: #1976d2; + color: white; + border-radius: 6px; + transition: background-color 0.3s; +} + +button:hover { + background-color: #1565c0; +} + +.error-message { + margin-top: 10px; + color: #ff6b6b; + font-weight: bold; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/main-layout.css b/deploy/tkfb-package/fastapi-bridge/static/css/main-layout.css new file mode 100644 index 0000000..6467328 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/main-layout.css @@ -0,0 +1,160 @@ +/* ✅ /css/main-layout.css - 공통 레이아웃 스타일 */ + +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + font-family: 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif; + background-color: #f5f5f5; +} + +/* 메인 레이아웃 구조 */ +.main-layout { + display: flex; + min-height: 100vh; + flex-direction: column; +} + +#navbar-container { + position: sticky; + top: 0; + z-index: 1000; +} + +.content-wrapper { + display: flex; + flex: 1; +} + +#sidebar-container { + flex-shrink: 0; +} + +#content-container, +#sections-container, +#admin-sections, +#user-sections { + flex: 1; + padding: 24px; + max-width: 1200px; + margin: 0 auto; + width: 100%; +} + +/* 카드 스타일 */ +.card { + background: white; + border-radius: 8px; + padding: 24px; + margin-bottom: 24px; + box-shadow: 0 2px 4px rgba(0,0,0,0.08); +} + +/* 섹션 스타일 */ +section { + background: white; + border-radius: 8px; + padding: 20px; + margin-bottom: 20px; + box-shadow: 0 2px 4px rgba(0,0,0,0.08); +} + +section h2 { + font-size: 18px; + margin: 0 0 16px 0; + color: #333; + border-bottom: 2px solid #1976d2; + padding-bottom: 8px; +} + +section ul { + list-style: none; + padding: 0; + margin: 0; +} + +section li { + padding: 8px 0; + border-bottom: 1px solid #f0f0f0; +} + +section li:last-child { + border-bottom: none; +} + +section a { + color: #1976d2; + text-decoration: none; + display: block; + padding: 4px 0; + transition: all 0.3s; +} + +section a:hover { + color: #0d47a1; + padding-left: 8px; +} + +/* 로딩 상태 */ +.loading { + text-align: center; + padding: 60px 20px; + color: #666; +} + +.loading::after { + content: '.'; + animation: dots 1.5s steps(3, end) infinite; +} + +@keyframes dots { + 0%, 20% { content: '.'; } + 40% { content: '..'; } + 60%, 100% { content: '...'; } +} + +/* 에러 상태 */ +.error-state { + text-align: center; + padding: 60px 20px; + color: #d32f2f; +} + +.error-state button { + margin-top: 16px; + padding: 8px 24px; + background: #1976d2; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.error-state button:hover { + background: #1565c0; +} + +/* 반응형 디자인 */ +@media (max-width: 1024px) { + #content-container, + #sections-container { + padding: 16px; + } +} + +@media (max-width: 768px) { + .content-wrapper { + flex-direction: column; + } + + #sidebar-container { + order: -1; + } + + section h2 { + font-size: 16px; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/management-dashboard.css b/deploy/tkfb-package/fastapi-bridge/static/css/management-dashboard.css new file mode 100644 index 0000000..08524ef --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/management-dashboard.css @@ -0,0 +1,1005 @@ +/* management-dashboard.css - 관리자 대시보드 전용 스타일 */ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', 'Noto Sans KR', Tahoma, Geneva, Verdana, sans-serif; + background-color: #f5f7fa; + color: #333; + line-height: 1.6; +} + +/* 메인 레이아웃 */ +.main-layout-with-navbar { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.content-wrapper { + flex: 1; + padding: 20px; +} + +.dashboard-container { + max-width: 1400px; + margin: 0 auto; +} + +/* 페이지 헤더 */ +.page-header { + text-align: center; + margin-bottom: 2.5rem; + padding: 3rem 2rem; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 16px; + box-shadow: 0 6px 24px rgba(0,0,0,0.12); + position: relative; +} + +.page-header h1 { + font-size: 2.5rem; + margin-bottom: 0.8rem; + font-weight: 700; +} + +.subtitle { + font-size: 1.1rem; + opacity: 0.9; + margin-bottom: 1rem; +} + +.permission-badge { + display: inline-block; + background: rgba(255,255,255,0.2); + color: white; + padding: 8px 20px; + border-radius: 25px; + font-size: 14px; + font-weight: 600; + border: 2px solid rgba(255,255,255,0.3); +} + +/* 뒤로가기 버튼 */ +.back-btn { + background: rgba(255,255,255,0.95); + color: #667eea; + border: 3px solid #667eea; + padding: 16px 32px; + border-radius: 12px; + text-decoration: none; + font-weight: 700; + font-size: 18px; + display: inline-flex; + align-items: center; + gap: 12px; + margin-bottom: 24px; + transition: all 0.3s ease; + box-shadow: 0 3px 12px rgba(102, 126, 234, 0.2); +} + +.back-btn:hover { + background: #667eea; + color: white; + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3); +} + +/* 메시지 스타일 */ +.message { + padding: 20px 32px; + border-radius: 12px; + margin-bottom: 32px; + font-weight: 600; + font-size: 18px; + box-shadow: 0 3px 12px rgba(0,0,0,0.1); +} + +.message.warning { + background: #fff3cd; + color: #856404; + border: 2px solid #ffeaa7; +} + +.message.error { + background: #f8d7da; + color: #721c24; + border: 2px solid #f5c6cb; +} + +.message.success { + background: #d4edda; + color: #155724; + border: 2px solid #c3e6cb; +} + +.message.loading { + background: #cce5ff; + color: #0066cc; + border: 2px solid #99d6ff; +} + +/* 날짜 선택 카드 */ +.date-selection-card { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); + margin-bottom: 2rem; +} + +.date-selection-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f0f0f0; +} + +.date-selection-header h3 { + margin: 0; + color: #333; + font-size: 1.4rem; +} + +.refresh-btn { + background: #28a745; + color: white; + border: none; + border-radius: 8px; + padding: 12px 20px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + transition: all 0.3s; + display: flex; + align-items: center; + gap: 8px; +} + +.refresh-btn:hover { + background: #1e7e34; + transform: translateY(-1px); +} + +.date-selection-body { + display: flex; + gap: 20px; + align-items: center; + justify-content: center; +} + +.date-input { + padding: 15px 20px; + font-size: 18px; + border: 3px solid #e1e5e9; + border-radius: 12px; + background: white; + transition: border-color 0.3s; + min-width: 200px; +} + +.date-input:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 4px rgba(0, 123, 255, 0.15); +} + +/* 버튼 스타일 */ +.btn { + padding: 15px 30px; + border: none; + border-radius: 12px; + font-size: 16px; + font-weight: 700; + cursor: pointer; + transition: all 0.3s; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + text-decoration: none; + box-shadow: 0 3px 12px rgba(0,0,0,0.1); +} + +.btn-primary { + background: #007bff; + color: white; +} + +.btn-primary:hover { + background: #0056b3; + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(0, 123, 255, 0.3); +} + +.btn-secondary { + background: #6c757d; + color: white; +} + +.btn-secondary:hover { + background: #545b62; + transform: translateY(-2px); +} + +/* 요약 섹션 */ +.summary-section { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); + margin-bottom: 2rem; +} + +.summary-section h3 { + margin-bottom: 1.5rem; + color: #333; + font-size: 1.4rem; +} + +.summary-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 20px; +} + +.summary-card { + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + border-radius: 12px; + padding: 1.5rem; + display: flex; + align-items: center; + gap: 15px; + border: 2px solid #dee2e6; + transition: all 0.3s ease; +} + +.summary-card:hover { + transform: translateY(-3px); + box-shadow: 0 8px 25px rgba(0,0,0,0.1); +} + +.summary-icon { + font-size: 2rem; + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background: rgba(255,255,255,0.8); +} + +.summary-content { + flex: 1; +} + +.summary-number { + font-size: 2rem; + font-weight: 700; + color: #333; + line-height: 1; +} + +.summary-label { + font-size: 0.9rem; + color: #666; + margin-top: 4px; +} + +/* 개별 요약 카드 색상 */ +.summary-card.total-workers { + background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); + border-color: #2196f3; +} + +.summary-card.completed-workers { + background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%); + border-color: #4caf50; +} + +.summary-card.missing-workers { + background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%); + border-color: #f44336; +} + +.summary-card.total-hours { + background: linear-gradient(135deg, #f3e5f5 0%, #e1bee7 100%); + border-color: #9c27b0; +} + +.summary-card.total-entries { + background: linear-gradient(135deg, #fff3e0 0%, #ffcc02 100%); + border-color: #ff9800; +} + +.summary-card.error-count { + background: linear-gradient(135deg, #fce4ec 0%, #f8bbd9 100%); + border-color: #e91e63; +} + +/* 액션 바 */ +.action-bar { + background: white; + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 4px 16px rgba(0,0,0,0.06); + margin-bottom: 2rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.filter-section { + display: flex; + gap: 20px; + align-items: center; +} + +.filter-checkbox { + display: flex; + align-items: center; + gap: 10px; + cursor: pointer; + font-weight: 600; + font-size: 16px; + color: #333; +} + +.filter-checkbox input[type="checkbox"] { + display: none; +} + +.checkmark { + width: 20px; + height: 20px; + border: 2px solid #007bff; + border-radius: 4px; + position: relative; + transition: all 0.3s ease; +} + +.filter-checkbox input[type="checkbox"]:checked + .checkmark { + background: #007bff; +} + +.filter-checkbox input[type="checkbox"]:checked + .checkmark::after { + content: "✓"; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; + font-weight: bold; + font-size: 12px; +} + +/* 작업자 섹션 */ +.workers-section { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); + margin-bottom: 2rem; +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f0f0f0; +} + +.section-header h3 { + margin: 0; + color: #333; + font-size: 1.4rem; +} + +.legend { + display: flex; + gap: 15px; +} + +.legend-item { + font-size: 14px; + font-weight: 600; + padding: 6px 12px; + border-radius: 20px; + border: 2px solid; +} + +.legend-item.completed { + color: #28a745; + border-color: #28a745; + background: rgba(40, 167, 69, 0.1); +} + +.legend-item.missing { + color: #dc3545; + border-color: #dc3545; + background: rgba(220, 53, 69, 0.1); +} + +.legend-item.partial { + color: #ffc107; + border-color: #ffc107; + background: rgba(255, 193, 7, 0.1); +} + +/* 작업자 테이블 스타일 */ +.table-container { + background: white; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 4px 16px rgba(0,0,0,0.06); +} + +.workers-table { + width: 100%; + border-collapse: collapse; + font-size: 14px; +} + +.workers-table thead { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; +} + +.workers-table th { + padding: 16px 12px; + text-align: left; + font-weight: 700; + font-size: 14px; + border-bottom: 2px solid rgba(255,255,255,0.2); +} + +.workers-table th:first-child { + padding-left: 20px; +} + +.workers-table th:last-child { + padding-right: 20px; +} + +.workers-table tbody tr { + border-bottom: 1px solid #e9ecef; + transition: all 0.3s ease; +} + +.workers-table tbody tr:hover { + background: #f8f9fa; + transform: scale(1.01); + box-shadow: 0 2px 8px rgba(0,0,0,0.1); +} + +.workers-table tbody tr:last-child { + border-bottom: none; +} + +.workers-table td { + padding: 16px 12px; + vertical-align: middle; + line-height: 1.4; +} + +.workers-table td:first-child { + padding-left: 20px; +} + +.workers-table td:last-child { + padding-right: 20px; +} + +/* 작업자 이름 스타일 */ +.worker-name-cell { + font-weight: 700; + color: #333; + display: flex; + align-items: center; + gap: 8px; +} + +/* 상태 배지 스타일 */ +.status-badge { + padding: 6px 12px; + border-radius: 20px; + font-size: 12px; + font-weight: 700; + color: white; + white-space: nowrap; + text-align: center; + min-width: 70px; +} + +.status-badge.completed { + background: linear-gradient(135deg, #28a745 0%, #20c997 100%); +} + +.status-badge.missing { + background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); +} + +.status-badge.partial { + background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%); + color: #333; +} + +/* 시간 표시 스타일 */ +.hours-cell { + font-weight: 700; + font-size: 16px; + color: #495057; +} + +.hours-cell.zero { + color: #dc3545; + opacity: 0.7; +} + +.hours-cell.partial { + color: #ffc107; +} + +.hours-cell.full { + color: #28a745; +} + +/* 작업 유형 태그 */ +.work-types-container { + display: flex; + flex-wrap: wrap; + gap: 4px; + max-width: 120px; +} + +.work-type-tag { + background: #e3f2fd; + color: #1565c0; + padding: 4px 8px; + border-radius: 12px; + font-size: 11px; + font-weight: 600; + white-space: nowrap; + border: 1px solid #bbdefb; +} + +/* 프로젝트 태그 */ +.projects-container { + display: flex; + flex-wrap: wrap; + gap: 4px; + max-width: 150px; +} + +.project-tag { + background: #f3e5f5; + color: #7b1fa2; + padding: 4px 8px; + border-radius: 12px; + font-size: 11px; + font-weight: 600; + white-space: nowrap; + border: 1px solid #e1bee7; +} + +/* 기여자 태그 */ +.contributors-container { + display: flex; + flex-wrap: wrap; + gap: 4px; + max-width: 120px; +} + +.contributor-tag { + background: #e8f5e8; + color: #2e7d32; + padding: 4px 8px; + border-radius: 12px; + font-size: 11px; + font-weight: 600; + white-space: nowrap; + border: 1px solid #c8e6c9; +} + +/* 업데이트 시간 스타일 */ +.update-time { + font-size: 12px; + color: #666; + white-space: nowrap; +} + +.update-time.recent { + color: #28a745; + font-weight: 600; +} + +.update-time.old { + color: #dc3545; +} + +/* 상세 버튼 */ +.detail-btn { + background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); + color: white; + border: none; + border-radius: 20px; + padding: 8px 16px; + cursor: pointer; + font-size: 12px; + font-weight: 600; + transition: all 0.3s; + white-space: nowrap; +} + +.detail-btn:hover { + background: linear-gradient(135deg, #0056b3 0%, #004085 100%); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 123, 255, 0.3); +} + +/* 데이터 없음 행 */ +.no-data-row { + text-align: center; + padding: 40px 20px; + color: #666; + font-style: italic; +} + +/* 테이블 반응형 */ +@media (max-width: 1200px) { + .workers-table { + font-size: 13px; + } + + .workers-table th, + .workers-table td { + padding: 12px 8px; + } + + .work-types-container, + .projects-container, + .contributors-container { + max-width: 100px; + } +} + +@media (max-width: 992px) { + .table-container { + overflow-x: auto; + } + + .workers-table { + min-width: 800px; + font-size: 12px; + } + + .workers-table th, + .workers-table td { + padding: 10px 6px; + } + + .work-types-container, + .projects-container, + .contributors-container { + max-width: 80px; + } + + .work-type-tag, + .project-tag, + .contributor-tag { + font-size: 10px; + padding: 3px 6px; + } +} + +@media (max-width: 768px) { + .workers-table { + min-width: 700px; + font-size: 11px; + } + + .workers-table th, + .workers-table td { + padding: 8px 4px; + } + + .status-badge { + font-size: 10px; + padding: 4px 8px; + min-width: 60px; + } + + .detail-btn { + font-size: 10px; + padding: 6px 12px; + } +} + +/* 로딩 스피너 */ +.loading-spinner { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 4rem 2rem; + background: white; + border-radius: 16px; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); +} + +.spinner { + width: 50px; + height: 50px; + border: 4px solid #f3f3f3; + border-top: 4px solid #007bff; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 1rem; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.loading-spinner p { + color: #666; + font-size: 1.1rem; + font-weight: 600; +} + +/* 데이터 없음 메시지 */ +.no-data-message { + text-align: center; + padding: 4rem 2rem; + background: white; + border-radius: 16px; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); +} + +.no-data-icon { + font-size: 4rem; + margin-bottom: 1rem; +} + +.no-data-message h3 { + color: #333; + margin-bottom: 1rem; + font-size: 1.5rem; +} + +.no-data-message p { + color: #666; + font-size: 1.1rem; + line-height: 1.6; +} + +/* 작업자 상세 모달 */ +.worker-detail-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.7); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + animation: fadeIn 0.3s ease; +} + +.modal-content { + background: white; + border-radius: 16px; + width: 90%; + max-width: 800px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 10px 40px rgba(0,0,0,0.3); + animation: slideIn 0.3s ease; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 24px; + border-bottom: 2px solid #f0f0f0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 16px 16px 0 0; +} + +.modal-header h3 { + margin: 0; + font-size: 20px; + font-weight: 700; +} + +.close-modal-btn { + background: rgba(255,255,255,0.2); + color: white; + border: none; + border-radius: 50%; + width: 32px; + height: 32px; + cursor: pointer; + font-size: 18px; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s; +} + +.close-modal-btn:hover { + background: rgba(255,255,255,0.3); + transform: rotate(90deg); +} + +.modal-body { + padding: 24px; +} + +/* 사용법 안내 */ +.guide-section { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); + margin-top: 2rem; +} + +.guide-section h3 { + margin-bottom: 1.5rem; + color: #333; + font-size: 1.4rem; + text-align: center; +} + +.guide-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 20px; +} + +.guide-item { + text-align: center; + padding: 20px; + background: #f8f9fa; + border-radius: 12px; + border: 2px solid #e9ecef; + transition: all 0.3s ease; +} + +.guide-item:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(0,0,0,0.1); + border-color: #667eea; +} + +.guide-icon { + font-size: 28px; + margin-bottom: 12px; +} + +.guide-item strong { + display: block; + font-size: 16px; + font-weight: 700; + margin-bottom: 8px; + color: #333; +} + +/* 애니메이션 */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-50px) scale(0.9); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +/* 수정 모달 스타일 */ +.edit-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.7); + display: flex; + justify-content: center; + align-items: center; + z-index: 1001; /* 상세 모달보다 위에 */ + animation: fadeIn 0.3s ease; +} + +.edit-modal-content { + background: white; + border-radius: 16px; + width: 90%; + max-width: 600px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 10px 40px rgba(0,0,0,0.3); + animation: slideIn 0.3s ease; +} + +.edit-modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 24px; + border-bottom: 2px solid #f0f0f0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 16px 16px 0 0; +} + +.edit-modal-header h3 { + margin: 0; + font-size: 20px; + font-weight: 700; +} + +.edit-modal-body { + padding: 24px; +} + +.edit-form-group { + margin-bottom: 20px; +} + +.edit-form-group label { + display: block; + margin-bottom: 8px; + font-weight: 700; + color: #555; + font-size: 14px; +} + +.edit-select, .edit-input { + width: 100%; + padding: 12px 16px; + border: 2px solid #e1e5e9; + border-radius: 8px; + font-size: 16px; + background: white; + transition: border-color 0.3s; +} + +.edit-select:focus, .edit-input:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1); +} + +.edit-modal-footer { + display: flex; + justify-content: flex-end; + gap: 12px; + padding: 24px; + border-top: 2px solid #f0f0f0; + background: #f8f9fa; + border-radius: 0 0 16px 16px; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/user.css b/deploy/tkfb-package/fastapi-bridge/static/css/user.css new file mode 100644 index 0000000..c6a4562 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/user.css @@ -0,0 +1,57 @@ +body { + font-family: 'Malgun Gothic', sans-serif; + background-color: #f5f5f5; + margin: 0; + padding: 0; +} + +header { + background: linear-gradient(135deg, #4caf50 0%, #45a049 100%); + color: white; + padding: 30px; + text-align: center; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +main { + padding: 30px; + max-width: 1200px; + margin: auto; +} + +.card { + background: white; + padding: 24px; + border-radius: 12px; + margin-bottom: 24px; + box-shadow: 0 2px 8px rgba(0,0,0,0.08); +} + +.quick-menu { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 16px; + margin-top: 16px; +} + +.menu-item { + display: flex; + align-items: center; + gap: 12px; + padding: 16px; + background: #f8f9fa; + border-radius: 8px; + text-decoration: none; + color: #333; + transition: all 0.3s ease; +} + +.menu-item:hover { + background: #e8f5e9; + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,0,0,0.1); +} + +.icon { + font-size: 24px; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/work-report.css b/deploy/tkfb-package/fastapi-bridge/static/css/work-report.css new file mode 100644 index 0000000..fa928cb --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/work-report.css @@ -0,0 +1,108 @@ +/* ✅ /css/workreport.css */ + +body { + font-family: 'Malgun Gothic', sans-serif; + background-color: #f8f9fa; + margin: 0; + padding: 30px; + color: #333; +} + +h2 { + text-align: center; + color: #1976d2; + margin-bottom: 20px; +} + +#calendar { + max-width: 500px; + margin: 0 auto 30px; + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 4px; + text-align: center; +} + +#calendar .nav { + grid-column: span 7; + display: flex; + justify-content: space-between; + margin-bottom: 10px; +} + +#calendar button { + padding: 8px; + background-color: #ffffff; + border: 1px solid #ccc; + cursor: pointer; + border-radius: 4px; +} + +#calendar button:hover { + background-color: #e3f2fd; +} + +.selected-date { + background-color: #4caf50 !important; + color: white; + font-weight: bold; +} + +table { + width: 100%; + max-width: 1200px; + margin: auto; + border-collapse: collapse; + background-color: white; + box-shadow: 0 2px 5px rgba(0,0,0,0.05); +} + +th, td { + border: 1px solid #ddd; + padding: 10px; + text-align: center; +} + +th { + background-color: #f1f3f4; + color: #333; +} + +select, +input[type="text"] { + width: 100%; + padding: 6px; + border: 1px solid #ccc; + border-radius: 4px; + box-sizing: border-box; +} + +.remove-btn { + background-color: #d9534f; + color: white; + border: none; + padding: 6px 12px; + border-radius: 4px; + cursor: pointer; +} + +.remove-btn:hover { + background-color: #c9302c; +} + +.submit-btn { + display: block; + margin: 30px auto; + padding: 12px 30px; + font-size: 1rem; + font-weight: bold; + background-color: #1976d2; + color: white; + border: none; + border-radius: 6px; + cursor: pointer; +} + +.submit-btn:hover { + background-color: #1565c0; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/css/work-review.css b/deploy/tkfb-package/fastapi-bridge/static/css/work-review.css new file mode 100644 index 0000000..daaec2c --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/css/work-review.css @@ -0,0 +1,839 @@ +/* work-review.css - 작업 검토 페이지 전용 스타일 (개선된 버전) */ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background-color: #f5f7fa; + color: #333; + line-height: 1.4; +} + +.main-layout-with-navbar { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.content-wrapper { + flex: 1; + padding: 20px; +} + +.review-container { + max-width: 1400px; + margin: 0 auto; +} + +/* 페이지 헤더 */ +.page-header { + text-align: center; + margin-bottom: 2rem; + padding: 2rem; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 16px; + box-shadow: 0 6px 24px rgba(0,0,0,0.12); +} + +.page-header h1 { + font-size: 2.2rem; + margin-bottom: 0.5rem; + font-weight: 700; +} + +.subtitle { + font-size: 1rem; + opacity: 0.9; +} + +/* 뒤로가기 버튼 */ +.back-btn { + background: rgba(255,255,255,0.95); + color: #667eea; + border: 3px solid #667eea; + padding: 12px 24px; + border-radius: 12px; + text-decoration: none; + font-weight: 700; + font-size: 16px; + display: inline-flex; + align-items: center; + gap: 8px; + margin-bottom: 20px; + transition: all 0.3s ease; +} + +.back-btn:hover { + background: #667eea; + color: white; + transform: translateY(-2px); +} + +/* 컨트롤 패널 */ +.control-panel { + background: white; + border-radius: 16px; + padding: 2rem; + margin-bottom: 2rem; + box-shadow: 0 4px 16px rgba(0,0,0,0.08); + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: 1rem; +} + +.month-navigation { + display: flex; + align-items: center; + gap: 1rem; +} + +.nav-btn, .today-btn { + background: #007bff; + color: white; + border: none; + border-radius: 8px; + padding: 12px 16px; + cursor: pointer; + font-weight: 600; + transition: all 0.3s; + font-size: 16px; +} + +.nav-btn:hover, .today-btn:hover { + background: #0056b3; + transform: translateY(-2px); +} + +.today-btn { + background: #28a745; +} + +.today-btn:hover { + background: #1e7e34; +} + +.current-month { + font-size: 1.5rem; + font-weight: 700; + color: #333; + min-width: 200px; + text-align: center; +} + +.control-actions { + display: flex; + gap: 12px; +} + +/* 사용법 안내 */ +.usage-guide { + background: white; + border-radius: 16px; + padding: 2rem; + margin-bottom: 2rem; + box-shadow: 0 4px 16px rgba(0,0,0,0.08); +} + +.usage-guide h3 { + margin-bottom: 1.5rem; + color: #333; + font-size: 1.3rem; + text-align: center; +} + +.guide-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); + gap: 1.5rem; +} + +.guide-item { + display: flex; + align-items: center; + gap: 15px; + padding: 1rem; + border-radius: 12px; + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + border: 2px solid #dee2e6; + transition: all 0.3s ease; +} + +.guide-item:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0,0,0,0.1); +} + +.guide-icon { + font-size: 2rem; + width: 50px; + text-align: center; +} + +.guide-text { + flex: 1; +} + +.guide-text strong { + color: #007bff; + font-size: 1.1rem; +} + +/* 캘린더 */ +.calendar-container { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 4px 16px rgba(0,0,0,0.08); + margin-bottom: 2rem; +} + +.calendar-container h3 { + color: #333; + font-size: 1.3rem; +} + +.calendar-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 2px; + border: 3px solid #dee2e6; + border-radius: 12px; + overflow: hidden; +} + +.day-header { + background: #343a40; + color: white; + padding: 15px; + text-align: center; + font-weight: 700; + font-size: 1.1rem; +} + +.day-cell { + background: white; + border: 1px solid #dee2e6; + min-height: 80px; + padding: 8px; + position: relative; + transition: all 0.3s ease; + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: center; +} + +.day-cell:hover { + transform: scale(1.05); + box-shadow: 0 4px 12px rgba(0,0,0,0.15); + z-index: 10; +} + +.day-cell.other-month { + background: #f8f9fa; + color: #6c757d; + cursor: not-allowed; +} + +.day-cell.today { + border: 3px solid #007bff; + background: #e7f3ff; +} + +.day-cell.selected { + background: #d4edda; + border: 3px solid #28a745; + transform: scale(1.02); +} + +.day-cell.selected .day-number { + color: #155724; + font-weight: 800; +} + +.day-number { + font-size: 1.2rem; + font-weight: 700; + margin-bottom: 5px; +} + +/* 선택된 날짜 정보 패널 */ +.day-info-panel { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 4px 16px rgba(0,0,0,0.08); + margin-bottom: 2rem; +} + +.day-info-placeholder { + text-align: center; + padding: 3rem; + color: #6c757d; +} + +.day-info-placeholder h3 { + font-size: 1.5rem; + margin-bottom: 1rem; + color: #495057; +} + +.day-info-content { + animation: fadeIn 0.3s ease; +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(20px); } + to { opacity: 1; transform: translateY(0); } +} + +.day-info-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 2rem; + padding-bottom: 1rem; + border-bottom: 3px solid #dee2e6; +} + +.day-info-header h3 { + color: #333; + font-size: 1.5rem; + margin: 0; +} + +.day-info-actions { + display: flex; + gap: 12px; +} + +.review-toggle, .refresh-day-btn { + padding: 10px 20px; + border: none; + border-radius: 8px; + cursor: pointer; + font-weight: 600; + transition: all 0.3s; + font-size: 14px; +} + +.review-toggle { + background: #007bff; + color: white; +} + +.review-toggle.reviewed { + background: #28a745; +} + +.review-toggle:hover { + transform: translateY(-2px); +} + +.refresh-day-btn { + background: #6c757d; + color: white; +} + +.refresh-day-btn:hover { + background: #545b62; + transform: translateY(-2px); +} + +/* 일별 요약 정보 */ +.day-summary { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1rem; + margin-bottom: 2rem; + padding: 1.5rem; + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + border-radius: 12px; + border: 2px solid #dee2e6; +} + +.summary-item { + display: flex; + flex-direction: column; + align-items: center; + gap: 8px; +} + +.summary-label { + font-weight: 600; + color: #6c757d; + font-size: 0.9rem; +} + +.summary-value { + font-size: 1.3rem; + font-weight: 700; + color: #333; +} + +.summary-value.normal-work { + color: #28a745; +} + +.summary-value.overtime { + color: #6f42c1; +} + +.summary-value.vacation { + color: #ffc107; +} + +.summary-value.reviewed { + color: #28a745; +} + +.summary-value.unreviewed { + color: #fd7e14; +} + +/* 작업자별 상세 섹션 */ +.workers-detail-container h4 { + margin-bottom: 1rem; + color: #333; + font-size: 1.2rem; +} + +.worker-detail-section { + border: 2px solid #dee2e6; + border-radius: 12px; + margin-bottom: 1rem; + overflow: hidden; + box-shadow: 0 2px 8px rgba(0,0,0,0.05); +} + +.worker-header-detail { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 1rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.delete-worker-btn { + background: rgba(220, 53, 69, 0.9); + color: white; + border: none; + border-radius: 6px; + padding: 8px 16px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + transition: all 0.3s; +} + +.delete-worker-btn:hover { + background: #c82333; + transform: translateY(-1px); +} + +.worker-work-items { + padding: 1rem; + background: white; +} + +.work-item-detail { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem; + margin-bottom: 0.5rem; + background: #f8f9fa; + border-radius: 8px; + border-left: 4px solid #007bff; + transition: all 0.3s ease; +} + +.work-item-detail:hover { + background: #e9ecef; + transform: translateX(5px); +} + +.work-item-info { + flex: 1; +} + +.work-item-actions { + display: flex; + gap: 8px; +} + +.edit-work-btn, .delete-work-btn { + padding: 8px 16px; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + transition: all 0.3s; + white-space: nowrap; +} + +.edit-work-btn { + background: #007bff; + color: white; +} + +.edit-work-btn:hover { + background: #0056b3; + transform: translateY(-1px); +} + +.delete-work-btn { + background: #dc3545; + color: white; +} + +.delete-work-btn:hover { + background: #c82333; + transform: translateY(-1px); +} + +/* 메시지 */ +.message { + padding: 15px 20px; + border-radius: 8px; + margin-bottom: 20px; + font-weight: 600; + animation: slideInDown 0.3s ease; +} + +@keyframes slideInDown { + from { + opacity: 0; + transform: translateY(-20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.message.loading { + background: #cce5ff; + color: #0066cc; + border: 2px solid #99d6ff; +} + +.message.success { + background: #d4edda; + color: #155724; + border: 2px solid #c3e6cb; +} + +.message.error { + background: #f8d7da; + color: #721c24; + border: 2px solid #f5c6cb; +} + +.message.warning { + background: #fff3cd; + color: #856404; + border: 2px solid #ffeaa7; +} + +/* 수정 모달 스타일 */ +.edit-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.7); + display: flex; + justify-content: center; + align-items: center; + z-index: 1001; + animation: fadeIn 0.3s ease; +} + +.edit-modal-content { + background: white; + border-radius: 16px; + width: 90%; + max-width: 500px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 10px 40px rgba(0,0,0,0.3); + animation: slideInUp 0.3s ease; +} + +@keyframes slideInUp { + from { + opacity: 0; + transform: translateY(50px) scale(0.9); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.edit-modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 24px; + border-bottom: 2px solid #f0f0f0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 16px 16px 0 0; +} + +.edit-modal-header h3 { + margin: 0; + font-size: 18px; + font-weight: 700; +} + +.close-modal-btn { + background: rgba(255,255,255,0.2); + color: white; + border: none; + border-radius: 50%; + width: 30px; + height: 30px; + cursor: pointer; + font-size: 16px; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s; +} + +.close-modal-btn:hover { + background: rgba(255,255,255,0.3); + transform: rotate(90deg); +} + +.edit-modal-body { + padding: 24px; +} + +.edit-form-group { + margin-bottom: 20px; +} + +.edit-form-group label { + display: block; + margin-bottom: 8px; + font-weight: 700; + color: #555; + font-size: 14px; +} + +.edit-select, .edit-input { + width: 100%; + padding: 12px 16px; + border: 2px solid #e1e5e9; + border-radius: 8px; + font-size: 14px; + background: white; + transition: border-color 0.3s; +} + +.edit-select:focus, .edit-input:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1); +} + +.edit-modal-footer { + display: flex; + justify-content: flex-end; + gap: 12px; + padding: 24px; + border-top: 2px solid #f0f0f0; + background: #f8f9fa; + border-radius: 0 0 16px 16px; +} + +/* 확인 모달 */ +.confirm-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.8); + display: flex; + justify-content: center; + align-items: center; + z-index: 1002; + animation: fadeIn 0.3s ease; +} + +.confirm-modal-content { + background: white; + border-radius: 16px; + width: 90%; + max-width: 400px; + box-shadow: 0 10px 40px rgba(0,0,0,0.3); + animation: slideInUp 0.3s ease; +} + +.confirm-modal-header { + padding: 24px 24px 16px; + border-bottom: 2px solid #f0f0f0; +} + +.confirm-modal-header h3 { + margin: 0; + font-size: 18px; + font-weight: 700; + color: #dc3545; +} + +.confirm-modal-body { + padding: 16px 24px; +} + +.confirm-modal-footer { + display: flex; + justify-content: flex-end; + gap: 12px; + padding: 16px 24px 24px; + border-top: 2px solid #f0f0f0; + background: #f8f9fa; + border-radius: 0 0 16px 16px; +} + +/* 버튼 스타일 */ +.btn { + padding: 10px 20px; + border: none; + border-radius: 6px; + cursor: pointer; + font-weight: 600; + transition: all 0.3s; + font-size: 14px; +} + +.btn-secondary { + background: #6c757d; + color: white; +} + +.btn-secondary:hover { + background: #545b62; + transform: translateY(-1px); +} + +.btn-success { + background: #28a745; + color: white; +} + +.btn-success:hover { + background: #1e7e34; + transform: translateY(-1px); +} + +.btn-danger { + background: #dc3545; + color: white; +} + +.btn-danger:hover { + background: #c82333; + transform: translateY(-1px); +} + +/* 반응형 */ +@media (max-width: 768px) { + .content-wrapper { + padding: 10px; + } + + .control-panel { + flex-direction: column; + text-align: center; + } + + .month-navigation { + flex-direction: column; + gap: 0.5rem; + } + + .guide-grid { + grid-template-columns: 1fr; + } + + .guide-item { + flex-direction: column; + text-align: center; + } + + .day-cell { + min-height: 60px; + padding: 5px; + } + + .day-number { + font-size: 1rem; + } + + .day-summary { + grid-template-columns: 1fr 1fr; + } + + .day-info-header { + flex-direction: column; + gap: 15px; + text-align: center; + } + + .day-info-actions { + flex-direction: column; + width: 100%; + } + + .review-toggle, .refresh-day-btn { + width: 100%; + } + + .work-item-detail { + flex-direction: column; + align-items: stretch; + gap: 12px; + } + + .work-item-actions { + justify-content: center; + } + + .worker-header-detail { + flex-direction: column; + gap: 10px; + text-align: center; + } + + .edit-modal-content { + width: 95%; + margin: 20px; + } + + .edit-modal-footer, .confirm-modal-footer { + flex-direction: column; + } + + .edit-work-btn, .delete-work-btn { + flex: 1; + padding: 12px; + font-size: 14px; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/assets/css/style.css b/deploy/tkfb-package/fastapi-bridge/static/docs/assets/css/style.css new file mode 100644 index 0000000..7775b56 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/assets/css/style.css @@ -0,0 +1,394 @@ +/* 테크니컬코리아 문서 시스템 CSS */ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + min-height: 100vh; + color: #333; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; + min-height: 100vh; + display: flex; + flex-direction: column; +} + +/* 헤더 스타일 */ +.header { + text-align: center; + background: rgba(255, 255, 255, 0.95); + padding: 40px 30px; + border-radius: 20px; + margin-bottom: 30px; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); + backdrop-filter: blur(10px); +} + +.header h1 { + font-size: 2.5rem; + margin-bottom: 10px; + background: linear-gradient(45deg, #667eea, #764ba2); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +.header p { + font-size: 1.2rem; + color: #666; + opacity: 0.8; +} + +/* 메인 콘텐츠 */ +.main-content { + flex: 1; + margin-bottom: 30px; +} + +/* 카드 그리드 */ +.card-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); + gap: 25px; + margin-bottom: 30px; +} + +/* 카드 스타일 */ +.card { + background: rgba(255, 255, 255, 0.95); + border-radius: 20px; + padding: 30px; + text-align: center; + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + backdrop-filter: blur(10px); + border: 1px solid rgba(255, 255, 255, 0.2); +} + +.card:hover { + transform: translateY(-10px); + box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15); +} + +.card-icon { + font-size: 3rem; + margin-bottom: 20px; + display: block; +} + +.card h3 { + font-size: 1.4rem; + margin-bottom: 15px; + color: #333; +} + +.card p { + color: #666; + margin-bottom: 20px; + line-height: 1.6; +} + +.card-link { + display: inline-block; + background: linear-gradient(45deg, #667eea, #764ba2); + color: white; + text-decoration: none; + padding: 12px 30px; + border-radius: 25px; + font-weight: 500; + transition: all 0.3s ease; + box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3); +} + +.card-link:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4); +} + +/* 검색 카드 특별 스타일 */ +.search-card { + grid-column: 1 / -1; + max-width: 600px; + margin: 0 auto; + width: 100%; +} + +.search-box { + display: flex; + gap: 10px; + margin-top: 20px; +} + +.search-box input { + flex: 1; + padding: 15px 20px; + border: 2px solid #e1e5e9; + border-radius: 25px; + font-size: 1rem; + outline: none; + transition: all 0.3s ease; +} + +.search-box input:focus { + border-color: #667eea; + box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1); +} + +.search-box button { + background: linear-gradient(45deg, #667eea, #764ba2); + color: white; + border: none; + padding: 15px 30px; + border-radius: 25px; + font-size: 1rem; + font-weight: 500; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 5px 15px rgba(102, 126, 234, 0.3); +} + +.search-box button:hover { + transform: translateY(-2px); + box-shadow: 0 8px 25px rgba(102, 126, 234, 0.4); +} + +/* 문서 목록 스타일 */ +.document-list { + display: grid; + gap: 20px; +} + +.document-item { + background: rgba(255, 255, 255, 0.95); + border-radius: 15px; + padding: 25px; + display: flex; + align-items: center; + gap: 20px; + box-shadow: 0 5px 20px rgba(0, 0, 0, 0.1); + transition: all 0.3s ease; + backdrop-filter: blur(10px); +} + +.document-item:hover { + transform: translateX(10px); + box-shadow: 0 10px 30px rgba(0, 0, 0, 0.15); +} + +.document-icon { + font-size: 2rem; + width: 60px; + text-align: center; +} + +.document-content { + flex: 1; +} + +.document-content h3 { + font-size: 1.2rem; + margin-bottom: 5px; + color: #333; +} + +.document-content p { + color: #666; + font-size: 0.9rem; +} + +.document-meta { + display: flex; + flex-direction: column; + align-items: flex-end; + gap: 5px; +} + +.document-date { + font-size: 0.8rem; + color: #999; +} + +.download-btn { + background: #28a745; + color: white; + text-decoration: none; + padding: 8px 16px; + border-radius: 20px; + font-size: 0.9rem; + transition: all 0.3s ease; +} + +.download-btn:hover { + background: #218838; + transform: translateY(-2px); +} + +/* 네비게이션 브레드크럼 */ +.breadcrumb { + background: rgba(255, 255, 255, 0.9); + padding: 15px 25px; + border-radius: 15px; + margin-bottom: 20px; + backdrop-filter: blur(10px); +} + +.breadcrumb a { + color: #667eea; + text-decoration: none; + font-weight: 500; +} + +.breadcrumb a:hover { + text-decoration: underline; +} + +.breadcrumb span { + color: #999; + margin: 0 10px; +} + +/* 페이지 헤더 */ +.page-header { + background: rgba(255, 255, 255, 0.95); + padding: 30px; + border-radius: 20px; + margin-bottom: 30px; + text-align: center; + backdrop-filter: blur(10px); +} + +.page-header h2 { + font-size: 2rem; + margin-bottom: 10px; + background: linear-gradient(45deg, #667eea, #764ba2); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; +} + +/* 푸터 */ +.footer { + background: rgba(255, 255, 255, 0.9); + padding: 25px; + border-radius: 15px; + text-align: center; + backdrop-filter: blur(10px); + margin-top: auto; +} + +.footer p { + color: #666; + font-size: 0.9rem; + margin-bottom: 5px; +} + +.footer p:last-child { + margin-bottom: 0; + font-family: 'Courier New', monospace; + color: #999; +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .container { + padding: 15px; + } + + .header { + padding: 25px 20px; + } + + .header h1 { + font-size: 2rem; + } + + .card-grid { + grid-template-columns: 1fr; + gap: 20px; + } + + .card { + padding: 25px 20px; + } + + .search-box { + flex-direction: column; + } + + .search-box button { + width: 100%; + } + + .document-item { + flex-direction: column; + text-align: center; + } + + .document-meta { + align-items: center; + } +} + +@media (max-width: 480px) { + .header h1 { + font-size: 1.8rem; + } + + .header p { + font-size: 1rem; + } + + .card { + padding: 20px 15px; + } + + .card h3 { + font-size: 1.2rem; + } +} + +/* 로딩 애니메이션 */ +.loading { + display: inline-block; + width: 20px; + height: 20px; + border: 3px solid rgba(255, 255, 255, 0.3); + border-radius: 50%; + border-top-color: #fff; + animation: spin 1s ease-in-out infinite; +} + +@keyframes spin { + to { transform: rotate(360deg); } +} + +/* 알림 메시지 */ +.alert { + padding: 15px 20px; + border-radius: 10px; + margin-bottom: 20px; + background: rgba(255, 255, 255, 0.9); + border-left: 5px solid #667eea; + backdrop-filter: blur(10px); +} + +.alert-success { + border-left-color: #28a745; +} + +.alert-warning { + border-left-color: #ffc107; +} + +.alert-error { + border-left-color: #dc3545; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/assets/js/main.js b/deploy/tkfb-package/fastapi-bridge/static/docs/assets/js/main.js new file mode 100644 index 0000000..77f1784 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/assets/js/main.js @@ -0,0 +1,60 @@ +// 문서 검색 기능 +function searchDocuments() { + const searchTerm = document.getElementById('searchInput').value.toLowerCase(); + if (searchTerm.trim() === '') { + alert('검색어를 입력해주세요.'); + return; + } + + // 간단한 검색 구현 (실제로는 서버 검색 또는 더 복잡한 로직 필요) + window.location.href = `search.html?q=${encodeURIComponent(searchTerm)}`; +} + +// 문서 필터링 기능 (문서 목록 페이지용) +function filterDocuments(searchTerm) { + const documents = document.querySelectorAll('.document-item'); + const term = searchTerm.toLowerCase(); + + documents.forEach(doc => { + const keywords = doc.getAttribute('data-keywords').toLowerCase(); + const title = doc.querySelector('h3').textContent.toLowerCase(); + const description = doc.querySelector('p').textContent.toLowerCase(); + + if (keywords.includes(term) || title.includes(term) || description.includes(term)) { + doc.style.display = 'flex'; + } else { + doc.style.display = 'none'; + } + }); +} + +// QR 코드 생성 (선택사항) +function generateQR() { + const url = 'http://192.168.0.3:10080'; + const qrAPI = `https://api.qrserver.com/v1/create-qr-code/?size=200x200&data=${encodeURIComponent(url)}`; + + const qrModal = document.createElement('div'); + qrModal.innerHTML = ` +
+
+

QR 코드로 접속

+ QR Code +

${url}

+ +
+
+ `; + document.body.appendChild(qrModal); +} + +// Enter 키 검색 +document.addEventListener('DOMContentLoaded', function() { + const searchInput = document.getElementById('searchInput'); + if (searchInput) { + searchInput.addEventListener('keypress', function(e) { + if (e.key === 'Enter') { + searchDocuments(); + } + }); + } +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/hr.html b/deploy/tkfb-package/fastapi-bridge/static/docs/hr.html new file mode 100644 index 0000000..ef0fdc5 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/hr.html @@ -0,0 +1,357 @@ + + + + + + 인사규정 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

HR-001 인사관리 규정

+

채용, 승진, 전보, 퇴직 등 인사관리 전반

+
+
+ + +
+
+

HR-002 급여관리 규정

+

급여체계, 수당, 상여금 지급 기준

+
+
+ + +
+
+

HR-003 근무시간 관리규정

+

근무시간, 휴게시간, 연장근무 규정

+
+
+ + +
+
+

HR-004 휴가 및 휴직규정

+

연차, 병가, 특별휴가, 휴직 관련 규정

+
+
+ + +
+
+

HR-005 복리후생 규정

+

건강보험, 퇴직금, 각종 지원금 규정

+
+
+ + +
+
+

HR-006 성과평가 관리규정

+

성과평가 기준, 절차, 결과 활용 방안

+
+
+ + +
+
+

HR-007 교육훈련 관리규정

+

신입사원 교육, 직무교육, 외부교육 지원

+
+
+ + +
+
+

HR-008 징계 관리규정

+

징계사유, 절차, 징계양정 기준

+
+
+ + +
+
+

HR-009 정보보안 및 기밀유지

+

회사 정보보안 및 기밀유지 의무

+
+
+ + +
+
+

HR-010 복무 및 행동강령

+

직원 복무 기준 및 윤리 행동강령

+
+
+
+ + +
+

인사규정 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

인사 문의: hr@technicalkorea.co.kr | 내선: 3456

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/hse.html b/deploy/tkfb-package/fastapi-bridge/static/docs/hse.html new file mode 100644 index 0000000..af4c9a2 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/hse.html @@ -0,0 +1,447 @@ + + + + + + HSE 관리시스템 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

TK-HSE-001 ISO 45001:2018 HSE 관리시스템 매뉴얼

+

ISO 45001:2018 기반 보건, 안전 및 환경 관리시스템 최상위 문서 (한/영 이중언어)

+
+
+ + +
+
+

TK-HSE-P-410 조직 상황 이해 및 HSE 관리시스템 운영 절차

+

조직의 내외부 상황 파악 및 HSE 관리시스템 전반 운영

+
+
+ + +
+
+

TK-HSE-P-510 리더십 및 정책 수립 절차

+

최고경영자 리더십 및 HSE 정책 수립·운영 절차

+
+
+ +
+
+

TK-HSE-P-520 조직 편성 및 직무 배정 절차

+

HSE 관련 조직 구성 및 역할·책임·권한 배정

+
+
+ + +
+
+

TK-HSE-P-610 기획 및 위험 관리 절차

+

HSE 관리시스템 기획 및 위험과 기회 관리

+
+
+ +
+
+

TK-HSE-P-620 위험 평가 절차

+

유해요인 식별 및 위험성 평가 실시 절차

+
+
+ +
+
+

TK-HSE-P-630 HSE 법적 요구사항 관리 절차

+

HSE 관련 법령 및 기타 요구사항 관리

+
+
+ +
+
+

TK-HSE-P-640 HSE 목표 관리 절차

+

HSE 목표 설정, 달성 계획 수립 및 관리

+
+
+ + +
+
+

TK-HSE-P-710 자원 관리 절차

+

HSE 관리시스템 운영에 필요한 자원 관리

+
+
+ +
+
+

TK-HSE-P-720 교육 및 훈련 관리 절차

+

HSE 관련 교육·훈련 계획 수립 및 실시

+
+
+ +
+
+

TK-HSE-P-730 인식 및 의사소통 절차

+

HSE 인식 제고 및 내외부 의사소통 관리

+
+
+ +
+
+

TK-HSE-P-740 문서화된 정보 관리 절차

+

HSE 문서 및 기록의 작성, 관리, 보관

+
+
+ + +
+
+

TK-HSE-P-810 운영 기획 및 관리 절차

+

HSE 운영 기획, 작업허가, 변경관리, 조달관리

+
+
+ +
+
+

TK-HSE-P-820 비상 대비 및 대응 절차

+

비상상황 대비, 대응 계획 및 훈련

+
+
+ + +
+
+

TK-HSE-P-910 프로세스 성과 관리 절차

+

HSE 관리시스템 프로세스 성과 관리

+
+
+ +
+
+

TK-HSE-P-920 HSE 모니터링 및 측정 관리 절차

+

HSE 성과 모니터링, 측정 및 분석

+
+
+ +
+
+

TK-HSE-P-930 내부 심사 절차

+

HSE 관리시스템 내부 심사 계획 및 실시

+
+
+ +
+
+

TK-HSE-P-940 경영 검토 절차

+

HSE 관리시스템 경영진 검토

+
+
+ + +
+
+

TK-HSE-P-1010 사건, 부적합 및 시정조치 절차

+

사건·사고 조사, 부적합 처리 및 시정조치

+
+
+ +
+
+

TK-HSE-P-1020 지속적 개선 절차

+

HSE 관리시스템 지속적 개선 활동

+
+
+ + +
+
+

TK-HSE-W-001 개인보호구 관리 지침

+

개인보호구 지급, 관리, 점검 실무 지침

+
+
+ +
+
+

TK-HSE-W-002 화학물질 관리 지침

+

화학물질 보관, 사용, 폐기 실무 지침

+
+
+ +
+
+

TK-HSE-W-003 응급처치 및 의료관리 지침

+

응급상황 대응 및 응급처치 실무 지침

+
+
+
+ + +
+

HSE 문서 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

HSE 문의: safety@technicalkorea.co.kr | 내선: 1234

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-410.html b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-410.html new file mode 100644 index 0000000..b6cd015 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-410.html @@ -0,0 +1,1208 @@ + + + + + + TK-HSE-P-410 조직 상황 이해 및 HSE 관리시스템 운영 절차 + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-410

+

조직 상황 이해 및 HSE 관리시스템 운영 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목조직 상황 이해 및 HSE 관리시스템 운영 절차
문서 번호TK-HSE-P-410
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 6
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+
+

1. 목적

+
+

본 절차의 목적은 다음과 같습니다:

+
    +
  • 조직의 내부 및 외부 상황을 체계적으로 파악하고 분석
  • +
  • 이해관계자의 요구사항과 기대사항을 식별하고 관리
  • +
  • HSE 관리시스템의 적용 범위를 명확히 정의
  • +
  • HSE 관리시스템의 효과적인 수립, 실행, 유지 및 개선
  • +
  • ISO 45001:2018 표준 4조 요구사항의 체계적 이행
  • +
+
+ + +
+
+

2. 적용 범위

+
+

본 절차는 테크니컬코리아의 다음 영역에 적용됩니다:

+
    +
  • 전 부서 및 모든 사업장
  • +
  • HSE 관리시스템 구축 및 운영 활동
  • +
  • 조직 상황 분석 및 이해관계자 관리 업무
  • +
  • HSE 관리시스템 적용 범위 설정 및 관리
  • +
  • 관련 계약업체 및 공급업체
  • +
+
+ + +
+
+

3. 인용 표준 및 관련 문서

+
+

3.1 인용 표준

+
    +
  • ISO 45001:2018 - 직장 보건안전 관리시스템 - 요구사항 및 사용 지침
  • +
  • 산업안전보건법 및 관련 법령
  • +
+ +

3.2 관련 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-510 - 리더십 및 정책 수립 절차
  • +
  • TK-HSE-P-610 - 기획 및 위험 관리 절차
  • +
  • TK-HSE-P-740 - 문서화된 정보 관리 절차
  • +
+
+ + +
+
+

4. 용어와 정의

+
+ +
+

4.1 조직의 상황 (Context of the organization)

+

목표를 달성하기 위한 조직의 접근 방식을 개발하는 데 영향을 줄 수 있는 내부 및 외부 이슈의 조합

+ +

4.2 이해관계자 (Interested party)

+

결정이나 활동에 영향을 주거나, 영향을 받거나, 영향을 받는다고 인식하는 개인이나 조직

+ +

4.3 요구사항 (Requirements)

+

명시되거나, 일반적으로 함축되거나, 의무적인 필요나 기대

+ +

4.4 적용 범위 (Scope)

+

관리시스템이 적용되는 조직의 활동, 제품 및 서비스의 범위와 경계

+
+
+ + +
+
+

5. 역할과 책임

+
+ + + + + + + + + + + + + + + + + + + + + + +
역할책임사항
최고경영자 + • 조직 상황 분석 결과 승인
+ • HSE 관리시스템 적용 범위 최종 결정
+ • 이해관계자 관리 전략 승인
+ • 필요 자원 제공 결정 +
HSE 관리책임자 + • 조직 상황 분석 총괄 관리
+ • 이해관계자 식별 및 분석 주관
+ • HSE 관리시스템 적용 범위 제안
+ • 관련 문서 작성 및 관리 +
각 부서장 + • 부서별 내외부 이슈 식별
+ • 부서 관련 이해관계자 정보 제공
+ • 조직 상황 분석 협조
+ • 관련 정보 업데이트 보고 +
HSE 담당자 + • 조직 상황 분석 실무 수행
+ • 이해관계자 정보 수집 및 정리
+ • 관련 문서 작성 지원
+ • 정기적 검토 및 업데이트 실시 +
+
+ + +
+
+

6. 프로세스 흐름도

+
+ +
+
조직 상황 분석 계획
+
+
내부/외부 이슈 식별
+
+
이해관계자 식별 및 분석
+
+
HSE 관리시스템 적용 범위 설정
+
+
문서화 및 승인
+
+
정기적 검토 및 업데이트
+
+
+ + +
+
+

7. 세부 절차

+
+ +
+

7.1 조직 상황 분석 계획 수립

+

7.1.1 절차

+
    +
  1. HSE 관리책임자는 연 1회 또는 필요시 조직 상황 분석 계획을 수립한다
  2. +
  3. 분석 범위, 방법, 일정, 담당자를 명확히 정의한다
  4. +
  5. 각 부서장에게 협조 요청을 공문으로 발송한다
  6. +
  7. 분석에 필요한 자료와 정보원을 사전에 확보한다
  8. +
+ +

7.1.2 고려사항

+
    +
  • 사업 환경의 변화 여부
  • +
  • 새로운 법규 및 규제 도입
  • +
  • 조직 구조 및 전략의 변경
  • +
  • 이전 분석 결과의 유효성
  • +
+
+ +
+

7.2 내부 및 외부 이슈 식별

+

7.2.1 외부 이슈 분석

+
    +
  1. 법적 환경 +
      +
    • 산업안전보건법 및 관련 법령 변화
    • +
    • 환경 관련 법규 동향
    • +
    • 국제 표준 및 규격 변화
    • +
    +
  2. +
  3. 경제적 환경 +
      +
    • 시장 경제 상황 및 전망
    • +
    • 업계 경기 동향
    • +
    • 경쟁업체 현황
    • +
    +
  4. +
  5. 기술적 환경 +
      +
    • 안전보건 기술 발전 동향
    • +
    • 새로운 위험요소 출현
    • +
    • 디지털 기술 적용 가능성
    • +
    +
  6. +
  7. 사회적 환경 +
      +
    • 사회적 안전 의식 변화
    • +
    • 근로자 권익 보호 요구
    • +
    • 지역사회 관심사항
    • +
    +
  8. +
+ +

7.2.2 내부 이슈 분석

+
    +
  1. 조직 구조 +
      +
    • 조직도 및 보고 체계
    • +
    • 역할 및 책임 분담
    • +
    • 의사결정 프로세스
    • +
    +
  2. +
  3. 인적 자원 +
      +
    • 인력 현황 및 역량
    • +
    • 교육훈련 수준
    • +
    • 근로자 참여도
    • +
    +
  4. +
  5. 물적 자원 +
      +
    • 시설 및 장비 현황
    • +
    • 안전보건 시설 수준
    • +
    • 기술적 능력
    • +
    +
  6. +
  7. 조직 문화 +
      +
    • 안전보건 문화 수준
    • +
    • 의사소통 체계
    • +
    • 학습 및 개선 의지
    • +
    +
  8. +
+
+ +
+

7.3 이해관계자 식별 및 분석

+

7.3.1 이해관계자 식별

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
구분이해관계자주요 관심사항
내부근로자안전한 작업환경, 건강보호, 참여 기회
경영진법적 준수, 비용 절감, 생산성 향상
주주기업 이미지, 재무 성과, 지속가능성
노동조합근로자 권익, 안전보건 조건 개선
외부고객제품 안전성, 기업 신뢰도
공급업체/계약업체안전한 작업 조건, 계약 이행
정부/규제기관법적 준수, 사고 예방
지역사회환경 영향, 사회적 책임
보험회사위험 관리, 사고율 감소
+ +

7.3.2 이해관계자 요구사항 분석

+
    +
  1. 각 이해관계자별 구체적 요구사항을 조사한다
  2. +
  3. 법적 요구사항과 자발적 요구사항을 구분한다
  4. +
  5. 요구사항의 우선순위와 중요도를 평가한다
  6. +
  7. 상충되는 요구사항에 대한 조정 방안을 마련한다
  8. +
  9. 요구사항 변화를 모니터링할 체계를 구축한다
  10. +
+
+ +
+

7.4 HSE 관리시스템 적용 범위 설정

+

7.4.1 적용 범위 결정 기준

+
    +
  • 조직의 통제 또는 영향 하에 있는 활동
  • +
  • HSE 성과에 영향을 줄 수 있는 활동
  • +
  • 법적 요구사항이 적용되는 영역
  • +
  • 이해관계자의 기대가 반영되는 영역
  • +
+ +

7.4.2 적용 범위 문서화

+
    +
  1. 물리적 위치 및 시설 명시
  2. +
  3. 포함되는 활동, 제품, 서비스 기술
  4. +
  5. 조직의 권한과 통제 범위 정의
  6. +
  7. 제외 사항 및 그 사유 명시
  8. +
  9. 적용 범위의 가용성 보장
  10. +
+
+ +
+

7.5 정기적 검토 및 업데이트

+

7.5.1 검토 주기

+
    +
  • 정기 검토: 매년 1회 이상
  • +
  • 임시 검토: 중대한 변화 발생 시
  • +
  • 경영 검토 시 함께 검토
  • +
+ +

7.5.2 업데이트 절차

+
    +
  1. 변화 요인 식별 및 영향 분석
  2. +
  3. 관련 부서와 협의
  4. +
  5. 업데이트 내용 문서화
  6. +
  7. 승인 및 공유
  8. +
  9. 관련 문서 연동 업데이트
  10. +
+
+
+ + +
+
+

8. 기록 관리

+
+ +

8.1 작성 기록

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
기록명작성자보관 기간보관 장소
조직 상황 분석 보고서HSE 관리책임자3년HSE 관리부서
이해관계자 등록부HSE 담당자3년HSE 관리부서
HSE 관리시스템 적용 범위서HSE 관리책임자영구HSE 관리부서
검토 및 업데이트 기록HSE 담당자3년HSE 관리부서
+ +

8.2 기록 관리 요구사항

+
    +
  • 모든 기록은 읽기 쉽고 식별 가능해야 함
  • +
  • 기록의 검색, 보관, 보호가 용이해야 함
  • +
  • 보관 기간 만료 시 적절히 처분
  • +
  • 전자 문서의 경우 백업 및 보안 조치
  • +
+
+ + +
+
+

9. 첨부 서식

+
+ +
    +
  • 첨부 1: 조직 상황 분석 체크리스트
  • +
  • 첨부 2: 이해관계자 등록 양식
  • +
  • 첨부 3: HSE 관리시스템 적용 범위 양식
  • +
  • 첨부 4: 검토 및 업데이트 기록 양식
  • +
+
+
+ + +
+ +
+

TK-HSE-P-410

+

Understanding Organizational Context and HSE Management System Operation Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleUnderstanding Organizational Context and HSE Management System Operation Procedure
Document NumberTK-HSE-P-410
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 6
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+
+

1. PURPOSE

+
+

The purpose of this procedure is to:

+
    +
  • Systematically identify and analyze the internal and external context of the organization
  • +
  • Identify and manage the needs and expectations of interested parties
  • +
  • Clearly define the scope of application of the HSE management system
  • +
  • Effectively establish, implement, maintain and improve the HSE management system
  • +
  • Systematically implement the requirements of ISO 45001:2018 Clause 4
  • +
+
+ + +
+
+

2. SCOPE

+
+

This procedure applies to the following areas of Technicalkorea:

+
    +
  • All departments and business sites
  • +
  • HSE management system establishment and operation activities
  • +
  • Organizational context analysis and stakeholder management tasks
  • +
  • Setting and managing the scope of HSE management system application
  • +
  • Related contractors and suppliers
  • +
+
+ + +
+
+

3. NORMATIVE REFERENCES AND RELATED DOCUMENTS

+
+

3.1 Normative References

+
    +
  • ISO 45001:2018 - Occupational health and safety management systems - Requirements with guidance for use
  • +
  • Occupational Safety and Health Act and related regulations
  • +
+ +

3.2 Related Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-510 - Leadership and Policy Establishment Procedure
  • +
  • TK-HSE-P-610 - Planning and Risk Management Procedure
  • +
  • TK-HSE-P-740 - Documented Information Management Procedure
  • +
+
+ + +
+
+

4. TERMS AND DEFINITIONS

+
+ +
+

4.1 Context of the organization

+

Combination of internal and external issues that can influence the organization's approach to developing and achieving its objectives

+ +

4.2 Interested party

+

Person or organization that can affect, be affected by, or perceive themselves to be affected by a decision or activity

+ +

4.3 Requirements

+

Need or expectation that is stated, generally implied or obligatory

+ +

4.4 Scope

+

Extent and boundaries of activities, products and services of an organization to which the management system applies

+
+
+ + +
+
+

5. ROLES AND RESPONSIBILITIES

+
+ + + + + + + + + + + + + + + + + + + + + + +
RoleResponsibilities
Top Management + • Approve organizational context analysis results
+ • Make final decisions on HSE management system scope
+ • Approve stakeholder management strategies
+ • Decide on provision of necessary resources +
HSE Management Representative + • Overall management of organizational context analysis
+ • Lead stakeholder identification and analysis
+ • Propose HSE management system scope
+ • Prepare and manage related documents +
Department Heads + • Identify internal and external issues by department
+ • Provide stakeholder information related to departments
+ • Cooperate in organizational context analysis
+ • Report updates on relevant information +
HSE Personnel + • Perform practical organizational context analysis
+ • Collect and organize stakeholder information
+ • Support preparation of related documents
+ • Conduct regular reviews and updates +
+
+ + +
+
+

6. PROCESS FLOW CHART

+
+ +
+
Organizational Context Analysis Planning
+
+
Internal/External Issues Identification
+
+
Stakeholder Identification and Analysis
+
+
HSE Management System Scope Setting
+
+
Documentation and Approval
+
+
Regular Review and Update
+
+
+ + +
+
+

7. DETAILED PROCEDURES

+
+ +
+

7.1 Establishing Organizational Context Analysis Plan

+

7.1.1 Procedure

+
    +
  1. The HSE Management Representative establishes an organizational context analysis plan annually or as needed
  2. +
  3. Clearly define the analysis scope, method, schedule, and responsible persons
  4. +
  5. Send cooperation requests to each department head via official document
  6. +
  7. Secure necessary data and information sources in advance for analysis
  8. +
+ +

7.1.2 Considerations

+
    +
  • Changes in business environment
  • +
  • Introduction of new laws and regulations
  • +
  • Changes in organizational structure and strategy
  • +
  • Validity of previous analysis results
  • +
+
+ +
+

7.2 Internal and External Issues Identification

+

7.2.1 External Issues Analysis

+
    +
  1. Legal Environment +
      +
    • Changes in Occupational Safety and Health Act and related laws
    • +
    • Environmental regulatory trends
    • +
    • Changes in international standards and specifications
    • +
    +
  2. +
  3. Economic Environment +
      +
    • Market economic conditions and prospects
    • +
    • Industry business trends
    • +
    • Competitor status
    • +
    +
  4. +
  5. Technological Environment +
      +
    • Safety and health technology development trends
    • +
    • Emergence of new risk factors
    • +
    • Digital technology application possibilities
    • +
    +
  6. +
  7. Social Environment +
      +
    • Changes in social safety awareness
    • +
    • Demands for worker rights protection
    • +
    • Local community concerns
    • +
    +
  8. +
+ +

7.2.2 Internal Issues Analysis

+
    +
  1. Organizational Structure +
      +
    • Organizational chart and reporting system
    • +
    • Role and responsibility distribution
    • +
    • Decision-making process
    • +
    +
  2. +
  3. Human Resources +
      +
    • Personnel status and capabilities
    • +
    • Education and training level
    • +
    • Worker participation level
    • +
    +
  4. +
  5. Physical Resources +
      +
    • Facilities and equipment status
    • +
    • Safety and health facility level
    • +
    • Technical capabilities
    • +
    +
  6. +
  7. Organizational Culture +
      +
    • Safety and health culture level
    • +
    • Communication system
    • +
    • Learning and improvement willingness
    • +
    +
  8. +
+
+ +
+

7.3 Stakeholder Identification and Analysis

+

7.3.1 Stakeholder Identification

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryStakeholderKey Concerns
InternalWorkersSafe working environment, health protection, participation opportunities
ManagementLegal compliance, cost reduction, productivity improvement
ShareholdersCorporate image, financial performance, sustainability
Labor UnionWorker rights, improvement of safety and health conditions
ExternalCustomersProduct safety, corporate reliability
Suppliers/ContractorsSafe working conditions, contract fulfillment
Government/Regulatory AgenciesLegal compliance, accident prevention
Local CommunityEnvironmental impact, social responsibility
Insurance CompaniesRisk management, accident rate reduction
+ +

7.3.2 Stakeholder Requirements Analysis

+
    +
  1. Investigate specific requirements for each stakeholder
  2. +
  3. Distinguish between legal requirements and voluntary requirements
  4. +
  5. Evaluate priority and importance of requirements
  6. +
  7. Establish coordination measures for conflicting requirements
  8. +
  9. Establish a system to monitor changes in requirements
  10. +
+
+ +
+

7.4 Setting HSE Management System Scope

+

7.4.1 Scope Determination Criteria

+
    +
  • Activities under the organization's control or influence
  • +
  • Activities that can affect HSE performance
  • +
  • Areas where legal requirements apply
  • +
  • Areas where stakeholder expectations are reflected
  • +
+ +

7.4.2 Scope Documentation

+
    +
  1. Specify physical locations and facilities
  2. +
  3. Describe included activities, products, and services
  4. +
  5. Define the organization's authority and control scope
  6. +
  7. Specify exclusions and their rationale
  8. +
  9. Ensure availability of the scope
  10. +
+
+ +
+

7.5 Regular Review and Update

+

7.5.1 Review Cycle

+
    +
  • Regular review: At least once a year
  • +
  • Ad-hoc review: When significant changes occur
  • +
  • Review together during management review
  • +
+ +

7.5.2 Update Procedure

+
    +
  1. Identify change factors and analyze impact
  2. +
  3. Consult with related departments
  4. +
  5. Document update contents
  6. +
  7. Approve and share
  8. +
  9. Update related linked documents
  10. +
+
+
+ + +
+
+

8. RECORDS MANAGEMENT

+
+ +

8.1 Records to be Maintained

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Record NamePrepared byRetention PeriodStorage Location
Organizational Context Analysis ReportHSE Management Representative3 yearsHSE Management Department
Stakeholder RegisterHSE Personnel3 yearsHSE Management Department
HSE Management System Scope DocumentHSE Management RepresentativePermanentHSE Management Department
Review and Update RecordsHSE Personnel3 yearsHSE Management Department
+ +

8.2 Records Management Requirements

+
    +
  • All records must be legible and identifiable
  • +
  • Records must be easily retrievable, stored, and protected
  • +
  • Appropriate disposal when retention period expires
  • +
  • Backup and security measures for electronic documents
  • +
+
+ + +
+
+

9. APPENDIX FORMS

+
+ +
    +
  • Appendix 1: Organizational Context Analysis Checklist
  • +
  • Appendix 2: Stakeholder Registration Form
  • +
  • Appendix 3: HSE Management System Scope Form
  • +
  • Appendix 4: Review and Update Record Form
  • +
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-510.html b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-510.html new file mode 100644 index 0000000..808a9f1 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-510.html @@ -0,0 +1,1529 @@ + + + + + + TK-HSE-P-510 리더십 및 정책 수립 절차 + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-510

+

리더십 및 정책 수립 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목리더십 및 정책 수립 절차
문서 번호TK-HSE-P-510
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 7
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+
+

1. 목적

+
+

본 절차의 목적은 다음과 같습니다:

+
    +
  • 최고경영자의 HSE 관리시스템에 대한 리더십과 의지 실증
  • +
  • HSE 정책의 체계적 수립, 실행, 유지 및 의사소통
  • +
  • 조직 내 HSE 역할, 책임 및 권한의 명확한 정의
  • +
  • 근로자의 협의와 참여를 위한 체계적 프레임워크 구축
  • +
  • ISO 45001:2018 표준 5조 요구사항의 효과적 이행
  • +
+
+ + +
+
+

2. 적용 범위

+
+

본 절차는 테크니컬코리아의 다음 영역에 적용됩니다:

+
    +
  • 최고경영자의 리더십 활동
  • +
  • HSE 정책 수립, 승인, 실행 및 유지 관리
  • +
  • 조직 내 HSE 관련 역할과 책임 배정
  • +
  • 근로자 협의 및 참여 프로세스
  • +
  • HSE 관리시스템 적용 범위 내 모든 활동
  • +
+
+ + +
+
+

3. 인용 표준 및 관련 문서

+
+

3.1 인용 표준

+
    +
  • ISO 45001:2018 - 직장 보건안전 관리시스템 - 요구사항 및 사용 지침
  • +
  • 산업안전보건법 및 관련 법령
  • +
  • 근로자참여 및 협력증진에 관한 법률
  • +
+ +

3.2 관련 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-410 - 조직 상황 이해 및 HSE 관리시스템 운영 절차
  • +
  • TK-HSE-P-520 - 조직 편성 및 직무 배정 절차
  • +
  • TK-HSE-P-730 - 인식 및 의사소통 절차
  • +
+
+ + +
+
+

4. 용어와 정의

+
+ +
+

4.1 최고경영자 (Top management)

+

최고 수준에서 조직을 지휘하고 통제하는 개인 또는 집단

+ +

4.2 정책 (Policy)

+

최고경영자가 공식적으로 표현한 조직의 의도와 방향

+ +

4.3 협의 (Consultation)

+

결정을 내리기 전에 견해를 구하는 것

+ +

4.4 참여 (Participation)

+

의사결정 과정에 관여하는 것

+ +

4.5 리더십 (Leadership)

+

목표를 달성하기 위해 다른 사람들에게 영향을 미치고 동기를 부여하는 능력

+
+
+ + +
+
+

5. 역할과 책임

+
+ + + + + + + + + + + + + + + + + + + + + + +
역할책임사항
최고경영자 + • HSE 관리시스템에 대한 리더십과 의지 실증
+ • HSE 정책 승인 및 대외 의사소통
+ • 조직 내 HSE 역할과 책임 최종 승인
+ • 근로자 협의 및 참여 프로세스 승인
+ • HSE 관리시스템 효과성 보장
+ • 필요 자원 제공 및 지원 +
HSE 관리책임자 + • HSE 정책 초안 작성 및 개정
+ • 조직 내 HSE 역할과 책임 체계 구축
+ • 근로자 협의 및 참여 프로그램 운영
+ • HSE 정책 교육 및 전파
+ • 정책 이행 상황 모니터링 +
각 부서장 + • 부서 내 HSE 정책 전파 및 실행
+ • 부서원의 HSE 역할과 책임 명확화
+ • 근로자 의견 수렴 및 상급자 보고
+ • 부서 HSE 성과 관리
+ • HSE 개선 활동 참여 +
근로자 + • HSE 정책 이해 및 준수
+ • 배정된 HSE 역할과 책임 수행
+ • HSE 협의 및 참여 활동 적극 참여
+ • HSE 개선 의견 제시
+ • 동료 근로자의 HSE 활동 지원 +
+
+ + +
+
+

6. 프로세스 흐름도

+
+ +
+
HSE 정책 수립 필요성 검토
+
+
정책 초안 작성
+
+
근로자 협의 및 의견 수렴
+
+
정책 검토 및 수정
+
+
최고경영자 승인
+
+
정책 공표 및 교육
+
+
역할과 책임 배정
+
+
이행 모니터링 및 검토
+
+
+ + +
+
+

7. HSE 정책

+
+ +
+
테크니컬코리아 HSE 정책
+ +

우리 테크니컬코리아는 모든 임직원과 이해관계자의 건강과 안전을 최우선 가치로 여기며, 환경보호를 통한 지속가능한 경영을 추구합니다.

+ +
+

우리의 약속 (Our Commitments)

+
    +
  1. 안전하고 건강한 작업환경 제공 +
      +
    • 무재해 사업장 구현을 위한 지속적 노력
    • +
    • 근로자의 신체적, 정신적 건강 보호
    • +
    • 안전한 작업 조건과 환경 조성
    • +
    +
  2. + +
  3. 법적 요구사항 및 기타 요구사항 준수 +
      +
    • 산업안전보건법 등 관련 법령 완전 준수
    • +
    • 국제 표준 및 모범 사례 적극 적용
    • +
    • 고객 및 이해관계자 요구사항 충족
    • +
    +
  4. + +
  5. 유해요인 제거 및 HSE 위험 감소 +
      +
    • 체계적인 위험 평가 및 관리
    • +
    • 사전 예방적 안전관리 시스템 운영
    • +
    • 최신 안전기술 도입 및 적용
    • +
    +
  6. + +
  7. 지속적 개선 +
      +
    • HSE 성과의 지속적 향상
    • +
    • 혁신적 개선 아이디어 발굴 및 적용
    • +
    • 학습하는 조직문화 구축
    • +
    +
  8. + +
  9. 근로자 협의 및 참여 +
      +
    • 모든 HSE 의사결정에 근로자 참여 보장
    • +
    • 열린 의사소통 문화 조성
    • +
    • 근로자 의견의 적극적 수렴 및 반영
    • +
    +
  10. + +
  11. 목표 설정 및 성과 관리 +
      +
    • 명확하고 측정 가능한 HSE 목표 설정
    • +
    • 정기적 성과 검토 및 평가
    • +
    • 목표 달성을 위한 체계적 실행
    • +
    +
  12. +
+
+ +

모든 임직원은 이 정책을 이해하고 실천하여 안전하고 건강한 일터를 만드는데 적극 참여해야 합니다.

+ +
+

2025년 1월 3일

+

테크니컬코리아 대표이사

+

________________

+

[서명]

+
+
+
+ + +
+
+

8. 세부 절차

+
+ +
+

8.1 HSE 정책 수립 절차

+

8.1.1 정책 수립 필요성 검토

+
    +
  1. 정기 검토: 매년 1회 정책의 적절성 검토
  2. +
  3. 임시 검토: 다음 상황 발생 시 즉시 검토 +
      +
    • 관련 법령의 개정
    • +
    • 조직 구조나 사업 영역의 변경
    • +
    • 중대한 사고나 사건 발생
    • +
    • 이해관계자의 요구사항 변화
    • +
    +
  4. +
  5. 검토 결과 문서화: 검토 내용과 결론을 기록
  6. +
+ +

8.1.2 정책 초안 작성

+
    +
  1. HSE 관리책임자가 초안 작성 주관
  2. +
  3. 다음 요소를 필수적으로 포함: +
      +
    • 안전하고 건강한 작업조건 제공 의지
    • +
    • HSE 목표 설정을 위한 프레임워크
    • +
    • 법적 요구사항 및 기타 요구사항 준수 의지
    • +
    • 유해요인 제거 및 HSE 위험 감소 의지
    • +
    • 지속적 개선 의지
    • +
    • 근로자 협의 및 참여 의지
    • +
    +
  4. +
  5. 조직의 특성과 사업 영역을 반영
  6. +
  7. 이해하기 쉽고 명확한 언어로 작성
  8. +
+ +

8.1.3 근로자 협의 및 의견 수렴

+
    +
  1. 정책 초안을 전 근로자에게 공개
  2. +
  3. 다양한 채널을 통한 의견 수렴: +
      +
    • 부서별 설명회 개최
    • +
    • 서면 의견서 접수
    • +
    • 온라인 의견 제출 시스템 활용
    • +
    • 근로자 대표와 개별 면담
    • +
    +
  4. +
  5. 수렴 기간: 최소 2주간
  6. +
  7. 의견 검토 및 반영 여부 결정
  8. +
+
+ +
+

8.2 조직 내 역할과 책임 체계

+

8.2.1 HSE 조직도 작성

+
    +
  1. 최고경영자를 정점으로 하는 HSE 조직 체계 구성
  2. +
  3. 각 계층별 역할과 책임 명확히 정의
  4. +
  5. 보고 체계와 의사소통 경로 명시
  6. +
  7. 의사결정 권한과 범위 규정
  8. +
+ +

8.2.2 역할과 책임 문서 작성

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
직급/역할주요 HSE 책임권한
최고경영자• HSE 관리시스템 총괄
• 정책 승인 및 자원 제공
• 리더십 실증
• 최종 의사결정
• 예산 승인
• 조직 변경
HSE 관리책임자• HSE 시스템 운영
• 법규 준수 관리
• 성과 모니터링
• 시스템 개선
• 교육 시행
• 점검 및 감사
부서장• 부서 HSE 관리
• 근로자 교육
• 사고 보고
• 부서 내 결정
• 시정조치
• 자원 요청
안전관리자• 기술적 지원
• 위험 평가
• 안전 점검
• 기술 지도
• 작업 중지
• 개선 권고
근로자• 안전 수칙 준수
• 위험 신고
• 교육 참여
• 작업 거부권
• 의견 제시
• 참여 권리
+
+ +
+

8.3 근로자 협의 및 참여 체계

+

8.3.1 협의 및 참여 체계 구축

+
    +
  1. HSE 위원회 구성 +
      +
    • 사용자 측 위원: 3명 (경영진, HSE 관리책임자 등)
    • +
    • 근로자 측 위원: 3명 (근로자 대표, 현장 대표 등)
    • +
    • 분기별 정기 회의 개최
    • +
    • 임시 회의: 필요시 수시 개최
    • +
    +
  2. + +
  3. 부서별 HSE 담당자 지정 +
      +
    • 각 부서에서 HSE 담당자 1명 지정
    • +
    • 월 1회 HSE 담당자 회의 개최
    • +
    • 부서 내 HSE 이슈 수집 및 전달
    • +
    +
  4. + +
  5. 의견 수렴 채널 운영 +
      +
    • HSE 제안함 설치 및 운영
    • +
    • 온라인 의견 제출 시스템
    • +
    • 익명 신고 시스템 운영
    • +
    • 정기적 간담회 개최
    • +
    +
  6. +
+ +

8.3.2 협의 및 참여 영역

+
    +
  • HSE 정책 수립 및 개정
  • +
  • HSE 목표 설정 및 계획 수립
  • +
  • 위험 평가 및 관리 방안
  • +
  • 안전보건 교육 프로그램
  • +
  • 사고 조사 및 재발 방지 대책
  • +
  • 작업 환경 개선 사항
  • +
  • 개인보호구 선정 및 지급
  • +
  • HSE 성과 평가 및 개선
  • +
+
+
+ + +
+
+

9. 리더십 실증 활동

+
+ +
+

9.1 최고경영자 리더십 활동

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
활동 영역구체적 활동실행 주기
정책 의사소통• 신년 HSE 메시지 발표
• 주요 회의에서 HSE 중요성 강조
• HSE 정책 서명 및 게시
연 1회 이상
월 1회
정책 수립 시
현장 방문• 정기적 현장 안전 순회
• 근로자와 직접 대화
• 안전 문제 즉석 해결
월 2회 이상
분기 1회
즉시
자원 제공• HSE 예산 승인
• 안전시설 투자 결정
• 교육 프로그램 지원
연간 예산
필요시
지속적
성과 검토• 월간 HSE 성과 보고 청취
• 경영 검토 회의 주관
• 개선 지시 및 확인
월 1회
분기 1회
수시
+
+ +
+

9.2 중간 관리자 리더십 활동

+
    +
  • 일일 안전 점검: 작업 시작 전 안전 상태 확인
  • +
  • 주간 안전 회의: 부서별 안전 이슈 논의
  • +
  • 즉석 교육: 위험 상황 발견 시 즉시 교육 실시
  • +
  • 모범 행동: 안전 수칙 준수의 모범 사례 제시
  • +
  • 격려와 인정: 우수 안전 활동에 대한 칭찬과 보상
  • +
+
+
+ + +
+
+

10. 성과 모니터링 및 검토

+
+ +
+

10.1 정책 이행 모니터링

+

10.1.1 모니터링 지표

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
영역지표측정 방법목표
정책 인식도정책 이해도 (%)설문조사90% 이상
근로자 참여HSE 위원회 참석률 (%)출석 체크95% 이상
리더십 활동현장 방문 횟수방문 기록월 2회 이상
의사소통의견 제출 건수접수 현황월 5건 이상
+ +

10.1.2 검토 및 개선

+
    +
  1. 월간 검토: HSE 관리책임자가 지표 현황 분석
  2. +
  3. 분기 검토: HSE 위원회에서 성과 평가
  4. +
  5. 연간 검토: 경영 검토 시 종합 평가
  6. +
  7. 개선 조치: 미달 지표에 대한 구체적 개선 계획 수립
  8. +
+
+
+ + +
+
+

11. 기록 관리

+
+ +

11.1 작성 기록

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
기록명작성자보관 기간보관 장소
HSE 정책서최고경영자영구HSE 관리부서
역할과 책임 매트릭스HSE 관리책임자3년HSE 관리부서
HSE 위원회 회의록HSE 담당자3년HSE 관리부서
리더십 활동 기록각 부서장3년각 부서
근로자 의견 수렴 기록HSE 담당자3년HSE 관리부서
정책 교육 기록교육 담당자3년교육 담당부서
+
+ + +
+
+

12. 첨부 서식

+
+ +
    +
  • 첨부 1: HSE 정책 승인 요청서
  • +
  • 첨부 2: 역할과 책임 매트릭스 양식
  • +
  • 첨부 3: HSE 위원회 회의록 양식
  • +
  • 첨부 4: 근로자 의견 제출서
  • +
  • 첨부 5: 리더십 활동 체크리스트
  • +
  • 첨부 6: 정책 이행 모니터링 표
  • +
+
+
+ + +
+ +
+

TK-HSE-P-510

+

Leadership and Policy Establishment Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleLeadership and Policy Establishment Procedure
Document NumberTK-HSE-P-510
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 7
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+
+

1. Purpose

+
+

The purpose of this procedure is as follows:

+
    +
  • Demonstrate top management's leadership and commitment to the HSE management system
  • +
  • Systematic establishment, implementation, maintenance, and communication of HSE policy
  • +
  • Clear definition of HSE roles, responsibilities, and authorities within the organization
  • +
  • Establish a systematic framework for worker consultation and participation
  • +
  • Effective implementation of ISO 45001:2018 standard clause 5 requirements
  • +
+
+ + +
+
+

2. Scope

+
+

This procedure applies to the following areas of Technicalkorea:

+
    +
  • Top management leadership activities
  • +
  • HSE policy establishment, approval, implementation, and maintenance
  • +
  • Assignment of HSE-related roles and responsibilities within the organization
  • +
  • Worker consultation and participation processes
  • +
  • All activities within the scope of the HSE management system
  • +
+
+ + +
+
+

3. Referenced Standards and Related Documents

+
+

3.1 Referenced Standards

+
    +
  • ISO 45001:2018 - Occupational health and safety management systems - Requirements with guidance for use
  • +
  • Occupational Safety and Health Act and related regulations
  • +
  • Act on the Promotion of Worker Participation and Cooperation
  • +
+ +

3.2 Related Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-410 - Understanding Organizational Context and HSE Management System Operation Procedure
  • +
  • TK-HSE-P-520 - Organizational Structure and Job Assignment Procedure
  • +
  • TK-HSE-P-730 - Awareness and Communication Procedure
  • +
+
+ + +
+
+

4. Terms and Definitions

+
+ +
+

4.1 Top management

+

Person or group of people who directs and controls an organization at the highest level

+ +

4.2 Policy

+

Intentions and direction of an organization as formally expressed by its top management

+ +

4.3 Consultation

+

Seeking views before making a decision

+ +

4.4 Participation

+

Involvement in decision-making

+ +

4.5 Leadership

+

Ability to influence and motivate others to achieve objectives

+
+
+ + +
+
+

5. Roles and Responsibilities

+
+ + + + + + + + + + + + + + + + + + + + + + +
RoleResponsibilities
Top Management + • Demonstrate leadership and commitment to the HSE management system
+ • Approve HSE policy and communicate externally
+ • Final approval of HSE roles and responsibilities within the organization
+ • Approve worker consultation and participation processes
+ • Ensure effectiveness of the HSE management system
+ • Provide necessary resources and support +
HSE Manager + • Draft and revise HSE policy
+ • Establish HSE roles and responsibility system within the organization
+ • Operate worker consultation and participation programs
+ • HSE policy training and dissemination
+ • Monitor policy implementation status +
Department Heads + • Disseminate and implement HSE policy within departments
+ • Clarify HSE roles and responsibilities of department members
+ • Collect worker opinions and report to superiors
+ • Manage department HSE performance
+ • Participate in HSE improvement activities +
Workers + • Understand and comply with HSE policy
+ • Perform assigned HSE roles and responsibilities
+ • Actively participate in HSE consultation and participation activities
+ • Submit HSE improvement suggestions
+ • Support fellow workers' HSE activities +
+
+ + +
+
+

6. Process Flow Chart

+
+ +
+
Review Need for HSE Policy Establishment
+
+
Draft Policy
+
+
Worker Consultation and Opinion Collection
+
+
Policy Review and Modification
+
+
Top Management Approval
+
+
Policy Announcement and Training
+
+
Assign Roles and Responsibilities
+
+
Implementation Monitoring and Review
+
+
+ + +
+
+

7. HSE Policy

+
+ +
+
Technicalkorea HSE Policy
+ +

We, Technicalkorea, regard the health and safety of all employees and stakeholders as our highest priority value and pursue sustainable management through environmental protection.

+ +
+

Our Commitments

+
    +
  1. Providing Safe and Healthy Work Environment +
      +
    • Continuous efforts to achieve zero-accident workplace
    • +
    • Protection of workers' physical and mental health
    • +
    • Creation of safe working conditions and environment
    • +
    +
  2. + +
  3. Compliance with Legal Requirements and Other Requirements +
      +
    • Full compliance with Occupational Safety and Health Act and related laws
    • +
    • Active application of international standards and best practices
    • +
    • Meeting customer and stakeholder requirements
    • +
    +
  4. + +
  5. Elimination of Hazards and Reduction of HSE Risks +
      +
    • Systematic risk assessment and management
    • +
    • Operation of proactive safety management system
    • +
    • Introduction and application of latest safety technologies
    • +
    +
  6. + +
  7. Continual Improvement +
      +
    • Continuous improvement of HSE performance
    • +
    • Discovery and application of innovative improvement ideas
    • +
    • Building a learning organizational culture
    • +
    +
  8. + +
  9. Worker Consultation and Participation +
      +
    • Ensuring worker participation in all HSE decision-making
    • +
    • Creating an open communication culture
    • +
    • Active collection and reflection of worker opinions
    • +
    +
  10. + +
  11. Goal Setting and Performance Management +
      +
    • Setting clear and measurable HSE objectives
    • +
    • Regular performance review and evaluation
    • +
    • Systematic implementation to achieve objectives
    • +
    +
  12. +
+
+ +

All employees must understand and practice this policy to actively participate in creating a safe and healthy workplace.

+ +
+

January 3, 2025

+

CEO, Technicalkorea

+

________________

+

[Signature]

+
+
+
+ + +
+
+

8. Detailed Procedures

+
+ +
+

8.1 HSE Policy Establishment Procedure

+

8.1.1 Review of Policy Establishment Need

+
    +
  1. Regular Review: Review policy adequacy once a year
  2. +
  3. Ad-hoc Review: Immediate review when the following situations occur: +
      +
    • Amendment of related laws and regulations
    • +
    • Changes in organizational structure or business areas
    • +
    • Occurrence of major accidents or incidents
    • +
    • Changes in stakeholder requirements
    • +
    +
  4. +
  5. Document Review Results: Record review contents and conclusions
  6. +
+ +

8.1.2 Policy Draft Preparation

+
    +
  1. HSE Manager leads draft preparation
  2. +
  3. Must include the following elements: +
      +
    • Commitment to provide safe and healthy working conditions
    • +
    • Framework for setting HSE objectives
    • +
    • Commitment to comply with legal requirements and other requirements
    • +
    • Commitment to eliminate hazards and reduce HSE risks
    • +
    • Commitment to continual improvement
    • +
    • Commitment to worker consultation and participation
    • +
    +
  4. +
  5. Reflect organizational characteristics and business areas
  6. +
  7. Write in clear and understandable language
  8. +
+ +

8.1.3 Worker Consultation and Opinion Collection

+
    +
  1. Disclose policy draft to all workers
  2. +
  3. Collect opinions through various channels: +
      +
    • Hold departmental briefings
    • +
    • Receive written opinion submissions
    • +
    • Utilize online opinion submission system
    • +
    • Individual interviews with worker representatives
    • +
    +
  4. +
  5. Collection period: Minimum 2 weeks
  6. +
  7. Review opinions and decide on reflection
  8. +
+
+ +
+

8.2 Organizational Roles and Responsibility System

+

8.2.1 HSE Organization Chart Preparation

+
    +
  1. Establish HSE organizational system with top management at the apex
  2. +
  3. Clearly define roles and responsibilities at each level
  4. +
  5. Specify reporting system and communication channels
  6. +
  7. Define decision-making authority and scope
  8. +
+ +

8.2.2 Roles and Responsibility Document Preparation

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Position/RoleMain HSE ResponsibilitiesAuthority
Top Management• Overall HSE management system
• Policy approval and resource provision
• Leadership demonstration
• Final decision-making
• Budget approval
• Organizational changes
HSE Manager• HSE system operation
• Legal compliance management
• Performance monitoring
• System improvement
• Training implementation
• Inspection and audit
Department Head• Department HSE management
• Worker training
• Accident reporting
• Departmental decisions
• Corrective actions
• Resource requests
Safety Manager• Technical support
• Risk assessment
• Safety inspection
• Technical guidance
• Work stoppage
• Improvement recommendations
Worker• Safety rule compliance
• Risk reporting
• Training participation
• Right to refuse work
• Opinion submission
• Participation rights
+
+ +
+

8.3 Worker Consultation and Participation System

+

8.3.1 Consultation and Participation System Establishment

+
    +
  1. HSE Committee Formation +
      +
    • Employer representatives: 3 members (management, HSE Manager, etc.)
    • +
    • Worker representatives: 3 members (worker representatives, field representatives, etc.)
    • +
    • Hold quarterly regular meetings
    • +
    • Ad-hoc meetings: Hold as needed
    • +
    +
  2. + +
  3. Departmental HSE Representative Designation +
      +
    • Designate 1 HSE representative from each department
    • +
    • Hold monthly HSE representative meetings
    • +
    • Collect and communicate HSE issues within departments
    • +
    +
  4. + +
  5. Opinion Collection Channel Operation +
      +
    • Install and operate HSE suggestion boxes
    • +
    • Online opinion submission system
    • +
    • Anonymous reporting system operation
    • +
    • Regular round-table meetings
    • +
    +
  6. +
+ +

8.3.2 Consultation and Participation Areas

+
    +
  • HSE policy establishment and revision
  • +
  • HSE objective setting and planning
  • +
  • Risk assessment and management measures
  • +
  • Occupational health and safety training programs
  • +
  • Accident investigation and recurrence prevention measures
  • +
  • Work environment improvement matters
  • +
  • Personal protective equipment selection and distribution
  • +
  • HSE performance evaluation and improvement
  • +
+
+
+ + +
+
+

9. Leadership Demonstration Activities

+
+ +
+

9.1 Top Management Leadership Activities

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Activity AreaSpecific ActivitiesImplementation Frequency
Policy Communication• Announce New Year HSE message
• Emphasize HSE importance in major meetings
• Sign and post HSE policy
Once a year or more
Monthly
When policy is established
Field Visits• Regular field safety rounds
• Direct dialogue with workers
• Immediate resolution of safety issues
Twice a month or more
Quarterly
Immediately
Resource Provision• HSE budget approval
• Safety facility investment decisions
• Training program support
Annual budget
As needed
Continuously
Performance Review• Listen to monthly HSE performance reports
• Chair management review meetings
• Issue and confirm improvement directives
Monthly
Quarterly
As needed
+
+ +
+

9.2 Middle Management Leadership Activities

+
    +
  • Daily Safety Inspection: Check safety conditions before work starts
  • +
  • Weekly Safety Meetings: Discuss departmental safety issues
  • +
  • On-the-spot Training: Immediate training when hazardous situations are discovered
  • +
  • Model Behavior: Present best practice examples of safety rule compliance
  • +
  • Encouragement and Recognition: Praise and reward excellent safety activities
  • +
+
+
+ + +
+
+

10. Performance Monitoring and Review

+
+ +
+

10.1 Policy Implementation Monitoring

+

10.1.1 Monitoring Indicators

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AreaIndicatorMeasurement MethodTarget
Policy AwarenessPolicy Understanding (%)Survey90% or higher
Worker ParticipationHSE Committee Attendance Rate (%)Attendance Check95% or higher
Leadership ActivitiesNumber of Field VisitsVisit RecordsTwice a month or more
CommunicationNumber of Opinion SubmissionsReception Status5 or more per month
+ +

10.1.2 Review and Improvement

+
    +
  1. Monthly Review: HSE Manager analyzes indicator status
  2. +
  3. Quarterly Review: HSE Committee evaluates performance
  4. +
  5. Annual Review: Comprehensive evaluation during management review
  6. +
  7. Improvement Actions: Establish specific improvement plans for underperforming indicators
  8. +
+
+
+ + +
+
+

11. Records Management

+
+ +

11.1 Records to be Created

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Record NamePrepared byRetention PeriodStorage Location
HSE Policy DocumentTop ManagementPermanentHSE Management Department
Roles and Responsibility MatrixHSE Manager3 yearsHSE Management Department
HSE Committee Meeting MinutesHSE Officer3 yearsHSE Management Department
Leadership Activity RecordsEach Department Head3 yearsEach Department
Worker Opinion Collection RecordsHSE Officer3 yearsHSE Management Department
Policy Training RecordsTraining Officer3 yearsTraining Department
+
+ + +
+
+

12. Attached Forms

+
+ +
    +
  • Attachment 1: HSE Policy Approval Request Form
  • +
  • Attachment 2: Roles and Responsibility Matrix Form
  • +
  • Attachment 3: HSE Committee Meeting Minutes Form
  • +
  • Attachment 4: Worker Opinion Submission Form
  • +
  • Attachment 5: Leadership Activity Checklist
  • +
  • Attachment 6: Policy Implementation Monitoring Table
  • +
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-520.html b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-520.html new file mode 100644 index 0000000..ef7cc5f --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-520.html @@ -0,0 +1,1826 @@ + + + + + + TK-HSE-P-520 조직 편성 및 직무 배정 절차 + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-520

+

조직 편성 및 직무 배정 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목조직 편성 및 직무 배정 절차
문서 번호TK-HSE-P-520
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 8
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+
+

1. 목적

+
+

본 절차의 목적은 다음과 같습니다:

+
    +
  • HSE 관리시스템 운영을 위한 효과적인 조직 구조 설계
  • +
  • 각 역할과 책임의 명확한 정의 및 배정
  • +
  • 권한과 의사소통 체계의 체계적 구축
  • +
  • HSE 성과 향상을 위한 적절한 인력 배치
  • +
  • 조직 변화에 따른 유연한 조직 운영 체계 확립
  • +
+
+ + +
+
+

2. 적용 범위

+
+

본 절차는 테크니컬코리아의 다음 영역에 적용됩니다:

+
    +
  • HSE 관리시스템 관련 모든 조직 및 직책
  • +
  • 본사, 공장, 지사 등 모든 사업장
  • +
  • 정규직, 계약직, 파견직 등 모든 근로자
  • +
  • HSE 업무에 관련된 계약업체 및 협력업체
  • +
  • 조직 개편 및 인사 발령 업무
  • +
+
+ + +
+
+

3. 인용 표준 및 관련 문서

+
+

3.1 인용 표준

+
    +
  • ISO 45001:2018 - 직장 보건안전 관리시스템 - 요구사항 및 사용 지침
  • +
  • 산업안전보건법 및 시행령, 시행규칙
  • +
  • 안전보건관리책임자 등의 선임 및 직무에 관한 고시
  • +
+ +

3.2 관련 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-510 - 리더십 및 정책 수립 절차
  • +
  • TK-HSE-P-710 - 자원 관리 절차
  • +
  • TK-HSE-P-720 - 교육 및 훈련 관리 절차
  • +
+
+ + +
+
+

4. 용어와 정의

+
+ +
+

4.1 조직 (Organization)

+

목표를 달성하기 위해 책임, 권한 및 상호관계가 배치된 개인 또는 집단

+ +

4.2 역할 (Role)

+

특정 상황에서 개인이나 그룹에게 기대되는 행동이나 업무의 집합

+ +

4.3 책임 (Responsibility)

+

할당된 업무나 의무를 수행해야 하는 의무

+ +

4.4 권한 (Authority)

+

결정을 내리고 자원을 사용할 수 있는 권리와 권력

+ +

4.5 역량 (Competence)

+

의도된 결과를 달성하기 위해 지식과 기술을 적용하는 능력

+
+
+ + +
+
+

5. HSE 조직 구조

+
+ +
+
+
최고경영자 (CEO)
+
+
+
+
HSE 관리책임자
+
+
├──────┼──────┼──────┤
+
+
안전관리자
+
보건관리자
+
환경관리자
+
HSE 담당자
+
+
+
+
부서별 HSE 담당자
+
+
+
+
현장 작업자
+
+
+ +
+

5.1 조직 구조 설계 원칙

+
    +
  • 명확성: 역할과 책임의 명확한 구분
  • +
  • 효율성: 의사결정과 업무 수행의 효율성 추구
  • +
  • 유연성: 조직 변화에 대한 적응 능력
  • +
  • 소통성: 원활한 의사소통 체계 구축
  • +
  • 전문성: 각 분야별 전문 역량 확보
  • +
+
+
+ + +
+
+

6. 역할과 책임

+
+ +
+

6.1 최고경영자 (CEO)

+ + + + + + + + + + + + + + + + + + + + + +
책임 영역구체적 책임사항권한
전략 수립• HSE 비전 및 전략 수립
• HSE 정책 승인
• 중장기 HSE 목표 결정
• 최종 의사결정
• 예산 승인
• 조직 개편
자원 제공• HSE 예산 승인
• 인적 자원 배정
• 시설 및 장비 투자
• 예산 집행
• 인사 발령
• 투자 결정
성과 관리• HSE 성과 검토
• 경영 검토 주관
• 개선 지시
• 성과 평가
• 포상 및 징계
• 시정 명령
+
+ +
+

6.2 HSE 관리책임자

+ + + + + + + + + + + + + + + + + + + + + +
책임 영역구체적 책임사항권한
시스템 운영• HSE 관리시스템 총괄 운영
• 시스템 개선 및 발전
• 법규 준수 관리
• 시스템 변경
• 절차 승인
• 법규 해석
조직 관리• HSE 조직 운영
• 업무 분장 및 조정
• 성과 관리
• 업무 배정
• 성과 평가
• 교육 지시
대외 업무• 정부 기관 업무
• 감사 및 점검 대응
• 외부 기관 협력
• 대외 협상
• 공문 발송
• 계약 체결
+
+ +
+

6.3 안전관리자

+
+

📋 주요 업무

+
    +
  • 안전관리계획의 수립 및 시행
  • +
  • 근로자의 안전·보건교육
  • +
  • 작업환경의 점검 및 개선
  • +
  • 산업재해 원인조사 및 재발방지 대책 수립
  • +
  • 안전장치 및 보호구의 점검 및 관리
  • +
  • 기계·기구류의 안전성 검토
  • +
  • 안전보건 관리규정의 작성 및 변경
  • +
+ +

🎯 필요 자격

+
    +
  • 안전관리자 선임 자격 (산업안전보건법)
  • +
  • 관련 분야 학위 또는 경력
  • +
  • 안전관리 실무 경험 3년 이상
  • +
+
+
+ +
+

6.4 보건관리자

+
+

📋 주요 업무

+
    +
  • 작업환경의 측정 및 평가
  • +
  • 근로자의 건강진단 및 사후관리
  • +
  • 직업성질병 예방 및 관리
  • +
  • 작업환경 개선 및 보건교육
  • +
  • 유해·위험 요인의 발굴 및 개선
  • +
  • 보건 관련 통계의 유지·관리
  • +
  • 응급처치 및 구급처치
  • +
+ +

🎯 필요 자격

+
    +
  • 보건관리자 선임 자격 (산업안전보건법)
  • +
  • 간호사, 위생사 등 보건 관련 자격
  • +
  • 산업보건 실무 경험 2년 이상
  • +
+
+
+ +
+

6.5 환경관리자

+
+

📋 주요 업무

+
    +
  • 환경영향 평가 및 관리
  • +
  • 환경법규 준수 관리
  • +
  • 폐기물 관리 및 처리
  • +
  • 대기, 수질, 토양 오염 방지
  • +
  • 환경 모니터링 및 측정
  • +
  • 환경 개선 계획 수립 및 시행
  • +
  • 환경 사고 대응 및 복구
  • +
+ +

🎯 필요 자격

+
    +
  • 환경 관련 기사 이상 자격증
  • +
  • 환경공학 또는 관련 분야 학위
  • +
  • 환경관리 실무 경험 3년 이상
  • +
+
+
+ +
+

6.6 부서장

+ + + + + + + + + + + + + + + + + +
책임 영역구체적 책임사항
부서 HSE 관리• 부서 HSE 계획 수립
• 부서원 HSE 교육
• 일일 안전점검 실시
• 사고 예방 활동 주관
근로자 관리• 부서원 HSE 역할 배정
• 안전수칙 준수 지도
• HSE 성과 평가
• 위험 행동 시정
보고 및 소통• HSE 현황 상급자 보고
• 근로자 의견 수렴
• 개선사항 건의
• 사고 즉시 보고
+
+
+ + +
+
+

7. 조직 편성 절차

+
+ +
+

7.1 HSE 조직 설계

+

7.1.1 조직 설계 단계

+
    +
  1. 현황 분석 +
      +
    • 현재 조직 구조 분석
    • +
    • 업무량 및 업무 특성 파악
    • +
    • 인력 현황 및 역량 평가
    • +
    • 법적 요구사항 검토
    • +
    +
  2. + +
  3. 조직 설계 +
      +
    • 최적 조직 구조 설계
    • +
    • 역할과 책임 정의
    • +
    • 보고 체계 및 권한 설정
    • +
    • 의사소통 채널 구축
    • +
    +
  4. + +
  5. 승인 및 공표 +
      +
    • 최고경영자 승인
    • +
    • 조직도 및 업무분장 공표
    • +
    • 전 직원 교육 실시
    • +
    • 시행 및 모니터링
    • +
    +
  6. +
+ +

7.1.2 조직 설계 시 고려사항

+ + + + + + + + + + + + + + + + + + + + + +
고려 요소세부 사항
법적 요구사항• 산업안전보건법상 관리자 선임 의무
• 사업장 규모별 선임 기준
• 자격 요건 및 직무 범위
사업 특성• 업종 및 업무 위험도
• 사업장 위치 및 규모
• 작업 형태 및 근무 시간
인적 자원• 현재 인력 현황
• 필요 역량 및 자격
• 교육 및 개발 계획
예산 및 자원• 인건비 예산
• 교육 및 훈련 비용
• 시설 및 장비 투자
+
+ +
+

7.2 직무 배정 절차

+

7.2.1 직무 분석

+
    +
  1. 업무 내용 분석 +
      +
    • 주요 업무 및 세부 업무 파악
    • +
    • 업무의 중요도 및 난이도 평가
    • +
    • 업무량 및 소요 시간 산정
    • +
    • 다른 업무와의 연관성 분석
    • +
    +
  2. + +
  3. 필요 역량 정의 +
      +
    • 학력, 경력, 자격증 요건
    • +
    • 필요 지식 및 기술
    • +
    • 개인적 특성 및 능력
    • +
    • 의사소통 및 리더십 역량
    • +
    +
  4. + +
  5. 성과 지표 설정 +
      +
    • 정량적 성과 지표
    • +
    • 정성적 평가 기준
    • +
    • 목표 설정 및 평가 방법
    • +
    • 피드백 및 개선 체계
    • +
    +
  6. +
+ +

7.2.2 인력 배정

+
+
직무 요구사항 검토
+
+
후보자 선정
+
+
역량 평가
+
+
배정 결정
+
+
발령 및 교육
+
+
성과 모니터링
+
+
+
+ + +
+
+

8. 역량 관리

+
+ +
+

8.1 역량 요구사항

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
직책학력/경력자격증핵심 역량
HSE 관리책임자대졸 이상, 5년 이상 경력안전관리자 또는 관련 자격리더십, 의사소통, 문제해결
안전관리자관련 학과 졸업, 3년 이상 경력안전관리자 선임 자격위험 평가, 기술 지도, 교육
보건관리자보건 관련 학과, 2년 이상 경력간호사, 위생사 등건강 관리, 상담, 응급처치
환경관리자환경공학 관련, 3년 이상 경력환경 관련 기사 이상환경 분석, 법규 해석, 개선
HSE 담당자고졸 이상, 1년 이상 경력관련 자격 우대업무 수행, 협조, 학습
+
+ +
+

8.2 역량 개발 계획

+

8.2.1 교육 훈련 체계

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
교육 구분대상내용주기
신입 교육신규 배정자• 조직 소개
• 역할 및 책임
• 기본 업무 교육
배정 후 1개월 내
정기 교육전체 HSE 조직• 법규 변경사항
• 새로운 기술
• 모범 사례
분기별
전문 교육관리자급• 전문 기술
• 리더십
• 의사소통
연 2회
보수 교육자격 보유자• 법정 보수교육
• 자격 갱신
• 최신 동향
법정 기준
+ +

8.2.2 역량 평가

+
    +
  • 정기 평가: 연 2회 (상/하반기)
  • +
  • 평가 방법: 서면 평가, 실무 평가, 360도 평가
  • +
  • 평가 기준: 업무 성과, 전문 지식, 협업 능력
  • +
  • 개선 계획: 평가 결과에 따른 개인별 개발 계획 수립
  • +
+
+
+ + +
+
+

9. 의사소통 체계

+
+ +
+

9.1 의사소통 채널

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
채널 유형참여자주기내용
경영진 회의CEO, HSE 관리책임자월 1회• HSE 성과 보고
• 주요 이슈 논의
• 의사결정
HSE 관리자 회의HSE 조직 전체주 1회• 업무 현황 공유
• 협조 사항
• 개선 방안
부서별 간담회부서장, HSE 담당자월 1회• 부서 HSE 현황
• 애로사항
• 지원 요청
전사 HSE 회의전체 임직원분기 1회• 정책 전파
• 성과 공유
• 우수사례
+
+ +
+

9.2 보고 체계

+

9.2.1 정기 보고

+
    +
  • 일일 보고: 현장 → 부서장 → HSE 담당자
  • +
  • 주간 보고: HSE 담당자 → HSE 관리책임자
  • +
  • 월간 보고: HSE 관리책임자 → 최고경영자
  • +
  • 분기 보고: 전사 HSE 성과 종합 보고
  • +
+ +

9.2.2 비상 보고

+
    +
  • 사고 발생 시: 즉시 보고 (30분 내)
  • +
  • 중대 위험 발견 시: 즉시 보고 (1시간 내)
  • +
  • 법규 위반 시: 즉시 보고 (당일)
  • +
  • 외부 점검 시: 사전 보고 및 결과 보고
  • +
+
+
+ + +
+
+

10. 성과 관리

+
+ +
+

10.1 성과 지표

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
지표 구분세부 지표목표측정 방법
조직 효율성업무 처리 시간기준 대비 90% 이하업무 처리 기록
의사결정 속도3일 이내결재 시스템
업무 만족도4.0/5.0 이상만족도 조사
역량 수준교육 이수율100%교육 기록
자격 보유율100%자격 대장
역량 평가 점수80점 이상평가 결과
의사소통회의 참석률95% 이상참석 기록
정보 공유 속도24시간 내시스템 로그
+
+ +
+

10.2 개선 관리

+

10.2.1 정기 검토

+
    +
  1. 월간 검토: 각 부서별 성과 분석
  2. +
  3. 분기 검토: 전체 조직 효율성 평가
  4. +
  5. 연간 검토: 조직 구조 및 운영 체계 전면 검토
  6. +
  7. 수시 검토: 중대한 문제 발생 시 즉시 검토
  8. +
+ +

10.2.2 개선 조치

+
    +
  • 업무 프로세스 개선: 비효율적 절차 간소화
  • +
  • 조직 구조 조정: 필요시 조직 개편
  • +
  • 역량 강화: 교육 및 훈련 확대
  • +
  • 시스템 개선: IT 시스템 및 도구 개선
  • +
+
+
+ + +
+
+

11. 기록 관리

+
+ +

11.1 작성 기록

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
기록명작성자보관 기간보관 장소
HSE 조직도HSE 관리책임자영구HSE 관리부서
업무분장표HSE 관리책임자3년HSE 관리부서
인사발령장인사담당자영구인사부서
역량 평가서각 부서장5년각 부서
교육 기록교육담당자3년교육담당부서
회의록회의 간사3년HSE 관리부서
+
+ + +
+
+

12. 첨부 서식

+
+ +
    +
  • 첨부 1: HSE 조직도 양식
  • +
  • 첨부 2: 업무분장표 양식
  • +
  • 첨부 3: 역할 및 책임 매트릭스
  • +
  • 첨부 4: 역량 요구사항 체크리스트
  • +
  • 첨부 5: 역량 평가표
  • +
  • 첨부 6: 교육 계획서 양식
  • +
  • 첨부 7: 성과 평가표
  • +
  • 첨부 8: 의사소통 매트릭스
  • +
+
+
+ + +
+ +
+

TK-HSE-P-520

+

Organization and Job Assignment Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleOrganization and Job Assignment Procedure
Document NumberTK-HSE-P-520
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 8
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+
+

1. Purpose

+
+

The purpose of this procedure is as follows:

+
    +
  • Design effective organizational structure for HSE management system operation
  • +
  • Clear definition and assignment of roles and responsibilities
  • +
  • Systematic establishment of authority and communication systems
  • +
  • Appropriate personnel deployment for HSE performance improvement
  • +
  • Establishment of flexible organizational operation system according to organizational changes
  • +
+
+ + +
+
+

2. Scope

+
+

This procedure applies to the following areas of Technicalkorea:

+
    +
  • All organizations and positions related to HSE management system
  • +
  • All business sites including headquarters, factories, and branches
  • +
  • All workers including regular, contract, and temporary employees
  • +
  • Contractors and partners related to HSE work
  • +
  • Organizational restructuring and personnel assignment work
  • +
+
+ + +
+
+

3. Referenced Standards and Related Documents

+
+

3.1 Referenced Standards

+
    +
  • ISO 45001:2018 - Occupational health and safety management systems - Requirements with guidance for use
  • +
  • Occupational Safety and Health Act and its enforcement decree and rules
  • +
  • Notice on the appointment and duties of safety and health management supervisors
  • +
+ +

3.2 Related Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-510 - Leadership and Policy Development Procedure
  • +
  • TK-HSE-P-710 - Resource Management Procedure
  • +
  • TK-HSE-P-720 - Education and Training Management Procedure
  • +
+
+ + +
+
+

4. Terms and Definitions

+
+ +
+

4.1 Organization

+

Person or group of people that has its own functions with responsibilities, authorities and relationships to achieve its objectives

+ +

4.2 Role

+

Set of behaviors or tasks expected of a person or group in a specific situation

+ +

4.3 Responsibility

+

Obligation to perform assigned tasks or duties

+ +

4.4 Authority

+

Right and power to make decisions and use resources

+ +

4.5 Competence

+

Ability to apply knowledge and skills to achieve intended results

+
+
+ + +
+
+

5. HSE Organization Structure

+
+ +
+
+
Chief Executive Officer (CEO)
+
+
+
+
HSE Management Representative
+
+
├──────┼──────┼──────┤
+
+
Safety Manager
+
Health Manager
+
Environmental Manager
+
HSE Officer
+
+
+
+
Departmental HSE Officers
+
+
+
+
Field Workers
+
+
+ +
+

5.1 Organizational Structure Design Principles

+
    +
  • Clarity: Clear distinction of roles and responsibilities
  • +
  • Efficiency: Pursuit of efficiency in decision-making and task performance
  • +
  • Flexibility: Adaptability to organizational changes
  • +
  • Communication: Establishment of smooth communication system
  • +
  • Professionalism: Securing professional competency in each field
  • +
+
+
+ + +
+
+

6. Roles and Responsibilities

+
+ +
+

6.1 Chief Executive Officer (CEO)

+ + + + + + + + + + + + + + + + + + + + + +
Responsibility AreaSpecific ResponsibilitiesAuthority
Strategy Development• Establish HSE vision and strategy
• Approve HSE policy
• Determine medium-long term HSE objectives
• Final decision making
• Budget approval
• Organizational restructuring
Resource Provision• Approve HSE budget
• Allocate human resources
• Invest in facilities and equipment
• Budget execution
• Personnel appointment
• Investment decision
Performance Management• Review HSE performance
• Lead management review
• Direct improvements
• Performance evaluation
• Rewards and disciplinary actions
• Corrective orders
+
+ +
+

6.2 HSE Management Representative

+ + + + + + + + + + + + + + + + + + + + + +
Responsibility AreaSpecific ResponsibilitiesAuthority
System Operation• Overall operation of HSE management system
• System improvement and development
• Legal compliance management
• System modification
• Procedure approval
• Legal interpretation
Organization Management• HSE organization operation
• Work assignment and coordination
• Performance management
• Task assignment
• Performance evaluation
• Training direction
External Affairs• Government agency affairs
• Audit and inspection response
• External organization cooperation
• External negotiation
• Official document dispatch
• Contract conclusion
+
+ +
+

6.3 Safety Manager

+
+

📋 Main Duties

+
    +
  • Establishment and implementation of safety management plans
  • +
  • Safety and health education for workers
  • +
  • Inspection and improvement of work environment
  • +
  • Investigation of industrial accident causes and establishment of recurrence prevention measures
  • +
  • Inspection and management of safety devices and protective equipment
  • +
  • Safety review of machinery and equipment
  • +
  • Preparation and modification of safety and health management regulations
  • +
+ +

🎯 Required Qualifications

+
    +
  • Safety manager appointment qualification (Occupational Safety and Health Act)
  • +
  • Related field degree or experience
  • +
  • Safety management practical experience of 3 years or more
  • +
+
+
+ +
+

6.4 Health Manager

+
+

📋 Main Duties

+
    +
  • Measurement and evaluation of work environment
  • +
  • Health examination and follow-up management of workers
  • +
  • Prevention and management of occupational diseases
  • +
  • Work environment improvement and health education
  • +
  • Discovery and improvement of harmful and dangerous factors
  • +
  • Maintenance and management of health-related statistics
  • +
  • Emergency treatment and first aid
  • +
+ +

🎯 Required Qualifications

+
    +
  • Health manager appointment qualification (Occupational Safety and Health Act)
  • +
  • Health-related qualifications such as nurse, hygienist
  • +
  • Industrial health practical experience of 2 years or more
  • +
+
+
+ +
+

6.5 Environmental Manager

+
+

📋 Main Duties

+
    +
  • Environmental impact assessment and management
  • +
  • Environmental regulation compliance management
  • +
  • Waste management and treatment
  • +
  • Prevention of air, water, and soil pollution
  • +
  • Environmental monitoring and measurement
  • +
  • Establishment and implementation of environmental improvement plans
  • +
  • Environmental accident response and recovery
  • +
+ +

🎯 Required Qualifications

+
    +
  • Environmental-related engineer certification or higher
  • +
  • Environmental engineering or related field degree
  • +
  • Environmental management practical experience of 3 years or more
  • +
+
+
+ +
+

6.6 Department Manager

+ + + + + + + + + + + + + + + + + +
Responsibility AreaSpecific Responsibilities
Department HSE Management• Establish department HSE plans
• HSE education for department members
• Conduct daily safety inspections
• Lead accident prevention activities
Worker Management• Assign HSE roles to department members
• Guide compliance with safety rules
• Evaluate HSE performance
• Correct dangerous behaviors
Reporting and Communication• Report HSE status to superiors
• Collect worker opinions
• Suggest improvements
• Immediately report accidents
+
+
+ + +
+
+

7. Organization Procedures

+
+ +
+

7.1 HSE Organization Design

+

7.1.1 Organization Design Stages

+
    +
  1. Current Status Analysis +
      +
    • Analysis of current organizational structure
    • +
    • Identification of workload and work characteristics
    • +
    • Evaluation of personnel status and competency
    • +
    • Review of legal requirements
    • +
    +
  2. + +
  3. Organization Design +
      +
    • Design optimal organizational structure
    • +
    • Define roles and responsibilities
    • +
    • Set reporting system and authority
    • +
    • Establish communication channels
    • +
    +
  4. + +
  5. Approval and Announcement +
      +
    • CEO approval
    • +
    • Announcement of organization chart and job assignment
    • +
    • Training for all employees
    • +
    • Implementation and monitoring
    • +
    +
  6. +
+ +

7.1.2 Considerations in Organization Design

+ + + + + + + + + + + + + + + + + + + + + +
Consideration FactorDetails
Legal Requirements• Mandatory appointment of managers under Occupational Safety and Health Act
• Appointment criteria by workplace size
• Qualification requirements and job scope
Business Characteristics• Industry type and work risk level
• Workplace location and size
• Work type and working hours
Human Resources• Current personnel status
• Required competency and qualifications
• Education and development plans
Budget and Resources• Personnel cost budget
• Education and training costs
• Facility and equipment investment
+
+ +
+

7.2 Job Assignment Procedure

+

7.2.1 Job Analysis

+
    +
  1. Work Content Analysis +
      +
    • Identification of main tasks and detailed tasks
    • +
    • Evaluation of task importance and difficulty
    • +
    • Calculation of workload and required time
    • +
    • Analysis of relationships with other tasks
    • +
    +
  2. + +
  3. Required Competency Definition +
      +
    • Education, experience, certification requirements
    • +
    • Required knowledge and skills
    • +
    • Personal characteristics and abilities
    • +
    • Communication and leadership competency
    • +
    +
  4. + +
  5. Performance Indicator Setting +
      +
    • Quantitative performance indicators
    • +
    • Qualitative evaluation criteria
    • +
    • Goal setting and evaluation methods
    • +
    • Feedback and improvement system
    • +
    +
  6. +
+ +

7.2.2 Personnel Assignment

+
+
Review Job Requirements
+
+
Select Candidates
+
+
Competency Assessment
+
+
Assignment Decision
+
+
Appointment and Training
+
+
Performance Monitoring
+
+
+
+ + +
+
+

8. Competency Management

+
+ +
+

8.1 Competency Requirements

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PositionEducation/ExperienceCertificationCore Competency
HSE Management RepresentativeBachelor's degree or higher, 5+ years experienceSafety manager or related qualificationLeadership, communication, problem-solving
Safety ManagerRelated field graduate, 3+ years experienceSafety manager appointment qualificationRisk assessment, technical guidance, education
Health ManagerHealth-related field, 2+ years experienceNurse, hygienist, etc.Health management, counseling, first aid
Environmental ManagerEnvironmental engineering related, 3+ years experienceEnvironmental engineer or higherEnvironmental analysis, regulation interpretation, improvement
HSE OfficerHigh school graduate or higher, 1+ years experienceRelated qualification preferredTask performance, cooperation, learning
+
+ +
+

8.2 Competency Development Plan

+

8.2.1 Education and Training System

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Education TypeTargetContentFrequency
New Employee TrainingNewly assigned personnel• Organization introduction
• Roles and responsibilities
• Basic job training
Within 1 month of assignment
Regular TrainingAll HSE organization• Regulatory changes
• New technologies
• Best practices
Quarterly
Professional TrainingManagement level• Professional skills
• Leadership
• Communication
Twice a year
Refresher TrainingCertificate holders• Legal refresher training
• Qualification renewal
• Latest trends
As per legal requirements
+ +

8.2.2 Competency Assessment

+
    +
  • Regular Assessment: Twice a year (first/second half)
  • +
  • Assessment Method: Written assessment, practical assessment, 360-degree assessment
  • +
  • Assessment Criteria: Job performance, professional knowledge, collaboration ability
  • +
  • Improvement Plan: Individual development plan based on assessment results
  • +
+
+
+ + +
+
+

9. Communication System

+
+ +
+

9.1 Communication Channels

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Channel TypeParticipantsFrequencyContent
Management MeetingCEO, HSE Management RepresentativeMonthly• HSE performance reporting
• Major issue discussion
• Decision making
HSE Manager MeetingEntire HSE organizationWeekly• Work status sharing
• Cooperation matters
• Improvement measures
Departmental MeetingDepartment managers, HSE officersMonthly• Department HSE status
• Difficulties
• Support requests
Company-wide HSE MeetingAll employeesQuarterly• Policy dissemination
• Performance sharing
• Best practices
+
+ +
+

9.2 Reporting System

+

9.2.1 Regular Reporting

+
    +
  • Daily Report: Field → Department Manager → HSE Officer
  • +
  • Weekly Report: HSE Officer → HSE Management Representative
  • +
  • Monthly Report: HSE Management Representative → CEO
  • +
  • Quarterly Report: Company-wide HSE performance comprehensive report
  • +
+ +

9.2.2 Emergency Reporting

+
    +
  • Accident Occurrence: Immediate report (within 30 minutes)
  • +
  • Major Risk Discovery: Immediate report (within 1 hour)
  • +
  • Regulatory Violation: Immediate report (same day)
  • +
  • External Inspection: Advance report and result report
  • +
+
+
+ + +
+
+

10. Performance Management

+
+ +
+

10.1 Performance Indicators

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Indicator CategoryDetailed IndicatorTargetMeasurement Method
Organizational EfficiencyTask processing time90% or less of standardTask processing records
Decision-making speedWithin 3 daysApproval system
Job satisfaction4.0/5.0 or higherSatisfaction survey
Competency LevelTraining completion rate100%Training records
Qualification holding rate100%Qualification register
Competency assessment score80 points or higherAssessment results
CommunicationMeeting attendance rate95% or higherAttendance records
Information sharing speedWithin 24 hoursSystem logs
+
+ +
+

10.2 Improvement Management

+

10.2.1 Regular Review

+
    +
  1. Monthly Review: Performance analysis by each department
  2. +
  3. Quarterly Review: Overall organizational efficiency evaluation
  4. +
  5. Annual Review: Comprehensive review of organizational structure and operation system
  6. +
  7. Ad-hoc Review: Immediate review when major problems occur
  8. +
+ +

10.2.2 Improvement Measures

+
    +
  • Work Process Improvement: Streamlining inefficient procedures
  • +
  • Organizational Structure Adjustment: Organizational restructuring when necessary
  • +
  • Competency Enhancement: Expansion of education and training
  • +
  • System Improvement: IT system and tool improvement
  • +
+
+
+ + +
+
+

11. Records Management

+
+ +

11.1 Prepared Records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Record NamePreparerRetention PeriodStorage Location
HSE Organization ChartHSE Management RepresentativePermanentHSE Management Department
Job Assignment TableHSE Management Representative3 yearsHSE Management Department
Personnel Appointment OrderHR PersonnelPermanentHR Department
Competency Assessment ReportEach Department Manager5 yearsEach Department
Training RecordsTraining Officer3 yearsTraining Department
Meeting MinutesMeeting Secretary3 yearsHSE Management Department
+
+ + +
+
+

12. Appendix Forms

+
+ +
    +
  • Appendix 1: HSE Organization Chart Form
  • +
  • Appendix 2: Job Assignment Table Form
  • +
  • Appendix 3: Role and Responsibility Matrix
  • +
  • Appendix 4: Competency Requirements Checklist
  • +
  • Appendix 5: Competency Assessment Form
  • +
  • Appendix 6: Training Plan Form
  • +
  • Appendix 7: Performance Evaluation Form
  • +
  • Appendix 8: Communication Matrix
  • +
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-610.html b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-610.html new file mode 100644 index 0000000..af89870 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-610.html @@ -0,0 +1,1671 @@ + + + + + + TK-HSE-P-610 기획 및 위험 관리 절차 + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-610

+

기획 및 위험 관리 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목기획 및 위험 관리 절차
문서 번호TK-HSE-P-610
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 9
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+
+

1. 목적

+
+

본 절차의 목적은 다음과 같습니다:

+
    +
  • HSE 관리시스템의 체계적인 기획과 실행
  • +
  • 위험과 기회를 다루기 위한 효과적인 조치 수립
  • +
  • 유해요인 식별 및 HSE 위험 평가의 체계적 수행
  • +
  • 법적 요구사항 및 기타 요구사항의 체계적 관리
  • +
  • 측정 가능한 HSE 목표 설정 및 달성 계획 수립
  • +
  • ISO 45001:2018 표준 6조 요구사항의 효과적 이행
  • +
+
+ + +
+
+

2. 적용 범위

+
+

본 절차는 테크니컬코리아의 다음 영역에 적용됩니다:

+
    +
  • HSE 관리시스템 적용 범위 내 모든 활동
  • +
  • 본사, 공장, 지사 등 모든 사업장
  • +
  • 정규직, 비정규직, 계약업체 근로자
  • +
  • 제품 생산, 서비스 제공, 지원 활동
  • +
  • 일상 및 비일상 업무, 비상 상황
  • +
  • 과거, 현재, 계획된 미래 활동
  • +
+
+ + +
+
+

3. 인용 표준 및 관련 문서

+
+

3.1 인용 표준

+
    +
  • ISO 45001:2018 - 직장 보건안전 관리시스템 - 요구사항 및 사용 지침
  • +
  • ISO 31000:2018 - 리스크 관리 - 지침
  • +
  • 산업안전보건법 및 관련 법령
  • +
  • 환경정책기본법 및 관련 법령
  • +
+ +

3.2 관련 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-410 - 조직 상황 이해 및 HSE 관리시스템 운영 절차
  • +
  • TK-HSE-P-620 - 위험 평가 절차
  • +
  • TK-HSE-P-630 - HSE 법적 요구사항 관리 절차
  • +
  • TK-HSE-P-640 - HSE 목표 관리 절차
  • +
+
+ + +
+
+

4. 용어와 정의

+
+ +
+

4.1 위험 (Risk)

+

불확실성의 영향으로, 목표에 대한 긍정적 또는 부정적 편차

+ +

4.2 기회 (Opportunity)

+

HSE 성과 향상, 폐기물 감소, 사고 예방 등 긍정적 결과를 가져올 가능성

+ +

4.3 유해요인 (Hazard)

+

부상과 건강악화를 일으킬 잠재성을 가진 근원

+ +

4.4 위험 평가 (Risk Assessment)

+

위험을 식별, 분석, 평가하는 전체적인 과정

+ +

4.5 법적 요구사항 (Legal Requirements)

+

조직이 준수해야 하는 법률, 규정, 명령 등

+ +

4.6 목표 (Objective)

+

달성해야 할 결과나 성과

+
+
+ + +
+
+

5. 프로세스 흐름도

+
+ +
+
기획 프로세스 시작
+
+
위험과 기회 식별
+
+
유해요인 식별
+
+
위험 평가
+
+
법적 요구사항 파악
+
+
HSE 목표 설정
+
+
실행 계획 수립
+
+
승인 및 실행
+
+
모니터링 및 검토
+
+
+ + +
+
+

6. 위험과 기회 관리

+
+ +
+

6.1 위험과 기회 식별

+

6.1.1 식별 대상

+ + + + + + + + + + + + + + + + + + + + + +
구분식별 대상고려사항
내부 위험• 설비 고장
• 인적 오류
• 조직 변화
• 자원 부족
• 발생 가능성
• 영향 정도
• 통제 가능성
• 대응 시간
외부 위험• 자연재해
• 법규 변경
• 시장 변화
• 공급업체 문제
• 예측 가능성
• 대응 능력
• 회복 시간
• 비용 영향
기회• 기술 개선
• 비용 절감
• 효율성 향상
• 이미지 개선
• 실현 가능성
• 투자 대비 효과
• 경쟁 우위
• 지속 가능성
+ +

6.1.2 식별 방법

+
    +
  • 브레인스토밍: 다학제팀 구성하여 아이디어 도출
  • +
  • 체크리스트: 표준화된 체크리스트 활용
  • +
  • 시나리오 분석: 가상의 상황 설정하여 분석
  • +
  • 과거 사례 분석: 내외부 사고 사례 검토
  • +
  • 전문가 판단: 해당 분야 전문가 의견 수렴
  • +
  • 현장 관찰: 직접 현장을 관찰하여 위험 요소 파악
  • +
+
+ +
+

6.2 위험과 기회 평가

+
+

📊 위험 평가 매트릭스

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
발생가능성영향도
1 (경미)2 (보통)3 (중간)4 (심각)5 (치명적)
5 (매우 높음)510152025
4 (높음)48121620
3 (보통)3691215
2 (낮음)246810
1 (매우 낮음)12345
+ +

🎯 위험 수준별 대응 기준

+
    +
  • 고위험 (15-25): 즉시 조치 필요, 작업 중단 고려
  • +
  • 중위험 (8-12): 단기간 내 개선 조치 필요
  • +
  • 저위험 (3-6): 계획적 개선 조치
  • +
  • 수용 가능 (1-2): 현재 수준 유지, 정기 모니터링
  • +
+
+
+ +
+

6.3 조치 계획 수립

+

6.3.1 위험 대응 전략

+
+

🔺 위험 관리 우선순위

+
    +
  1. 제거 (Elimination): 위험 요소 자체를 제거
  2. +
  3. 대체 (Substitution): 더 안전한 대안으로 교체
  4. +
  5. 공학적 통제 (Engineering Controls): 기술적 방법으로 위험 감소
  6. +
  7. 관리적 통제 (Administrative Controls): 절차, 교육, 훈련을 통한 관리
  8. +
  9. 개인보호구 (PPE): 개인보호장비 착용으로 보호
  10. +
+
+ +

6.3.2 기회 활용 전략

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
전략설명예시
적극 추진기회 실현 가능성을 높이기 위한 적극적 투자• 신기술 도입
• 전문 인력 채용
• 시설 개선
공유다른 조직과 협력하여 기회 공유• 파트너십 구축
• 컨소시엄 참여
• 외부 협력
수용별도 조치 없이 자연스러운 기회 활용• 시장 변화 대응
• 법규 변경 활용
• 트렌드 추종
모니터링기회 발생을 지속적으로 관찰• 정기 검토
• 성과 추적
• 트렌드 분석
+
+
+ + +
+
+

7. 유해요인 식별 및 위험 평가

+
+ +
+

7.1 유해요인 분류

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
분류세부 유형주요 예시
물리적 유해요인기계적 위험• 회전체, 압착, 충돌
• 낙하, 전도, 추락
환경적 위험• 소음, 진동, 온도
• 조명, 방사선
전기적 위험• 감전, 화재, 폭발
• 정전기, 낙뢰
화학적 유해요인유독물질• 산, 알칼리, 용매
• 중금속, 발암물질
가스/증기• 독성가스, 질식가스
• 인화성 가스
생물학적 유해요인병원체• 세균, 바이러스, 곰팡이
• 기생충, 독소
알레르기원• 꽃가루, 먼지
• 동물털, 식품
인간공학적 유해요인작업 자세• 부적절한 자세
• 반복 작업, 중량물
작업 설계• 작업대 높이
• 도구 설계, 공간
심리사회적 유해요인업무 스트레스• 과도한 업무량
• 시간 압박, 책임
조직 문화• 괴롭힘, 폭력
• 의사소통 부족
+
+ +
+

7.2 식별 절차

+

7.2.1 체계적 접근

+
    +
  1. 작업 분석 +
      +
    • 작업 공정별 세부 단계 분석
    • +
    • 사용 장비 및 재료 파악
    • +
    • 작업 환경 조건 확인
    • +
    • 작업자 특성 고려
    • +
    +
  2. + +
  3. 현장 조사 +
      +
    • 직접 현장 관찰 및 측정
    • +
    • 작업자 인터뷰 실시
    • +
    • 과거 사고 사례 검토
    • +
    • 유사 업종 사례 조사
    • +
    +
  4. + +
  5. 문서 검토 +
      +
    • 물질안전보건자료(MSDS) 검토
    • +
    • 장비 매뉴얼 및 사양서 확인
    • +
    • 법규 및 기준 검토
    • +
    • 감사 및 점검 결과 분석
    • +
    +
  6. + +
  7. 전문가 자문 +
      +
    • 산업보건 전문가 의견
    • +
    • 안전 기술 전문가 자문
    • +
    • 의학 전문가 상담
    • +
    • 법무 전문가 검토
    • +
    +
  8. +
+
+ +
+

7.3 위험 평가 방법

+

7.3.1 정량적 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + +
방법적용 대상장점단점
확률론적 평가통계 데이터가 충분한 경우• 객관적 결과
• 정확한 수치
• 데이터 확보 어려움
• 복잡한 계산
노출 평가화학물질, 물리적 인자• 직접 측정
• 과학적 근거
• 비용 소요
• 시간 제약
모델링복잡한 시스템• 시나리오 분석
• 예측 가능
• 가정 의존
• 불확실성
+ +

7.3.2 정성적 평가

+
    +
  • 매트릭스 방법: 발생가능성 × 영향도
  • +
  • 순위 결정법: 상대적 중요도 비교
  • +
  • 시나리오 분석: 가정 상황 설정
  • +
  • 전문가 판단: 경험과 지식 활용
  • +
+
+
+ + +
+
+

8. 법적 요구사항 관리

+
+ +
+

8.1 법적 요구사항 식별

+

8.1.1 주요 법령

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
분야주요 법령핵심 요구사항
안전산업안전보건법• 안전보건관리체계 구축
• 위험성 평가 실시
• 안전보건교육 실시
건설기계관리법• 건설기계 검사
• 조종사 면허
• 안전운행
화학물질관리법• 화학물질 등록
• 취급기준 준수
• 사고 신고
보건산업안전보건법• 작업환경측정
• 건강진단 실시
• 직업병 예방
감염병예방법• 감염병 예방조치
• 신고 의무
• 방역 활동
환경환경정책기본법• 환경오염 방지
• 환경영향 최소화
• 지속가능 발전
대기환경보전법• 배출허용기준 준수
• 방지시설 설치
• 측정 및 보고
폐기물관리법• 폐기물 분리수거
• 위탁처리
• 처리 현황 보고
+ +

8.1.2 기타 요구사항

+
    +
  • 고객 요구사항: 계약서, 사양서상 안전보건 조건
  • +
  • 자발적 표준: ISO 표준, 업계 모범사례
  • +
  • 보험 요구사항: 보험회사 안전 기준
  • +
  • 사회적 기대: 지역사회, NGO 요구사항
  • +
+
+ +
+

8.2 준수 관리 체계

+

8.2.1 법령 모니터링

+
    +
  1. 정보 수집: 정부 공고, 전문 기관 정보
  2. +
  3. 변경 분석: 기존 대비 변경사항 파악
  4. +
  5. 영향 평가: 조직에 미치는 영향 분석
  6. +
  7. 대응 계획: 필요 조치사항 계획 수립
  8. +
  9. 실행 및 추적: 계획 실행 및 결과 확인
  10. +
+ +

8.2.2 준수 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
평가 방법주기담당자결과 조치
자체 점검월 1회각 부서 담당자즉시 개선
내부 감사분기 1회HSE 담당자시정조치 계획
외부 평가연 1회외부 전문기관종합 개선 계획
정부 점검수시관계 공무원행정조치 대응
+
+
+ + +
+
+

9. HSE 목표 설정 및 관리

+
+ +
+

9.1 목표 설정 원칙

+
+

🎯 SMART 원칙

+
    +
  • Specific (구체적): 명확하고 구체적인 목표
  • +
  • Measurable (측정가능): 정량적으로 측정 가능
  • +
  • Achievable (달성가능): 현실적으로 달성 가능
  • +
  • Relevant (관련성): HSE 정책과 연관성
  • +
  • Time-bound (시한설정): 명확한 달성 기한
  • +
+ +

📋 목표 설정 고려사항

+
    +
  • HSE 정책과의 일치성
  • +
  • 법적 요구사항 반영
  • +
  • 위험 평가 결과 반영
  • +
  • 기술적, 재정적 실현가능성
  • +
  • 이해관계자 기대사항
  • +
  • 지속적 개선 의지
  • +
+
+
+ +
+

9.2 목표 영역별 설정

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
영역목표 예시측정 지표목표값
안전재해율 감소재해율 (%)전년 대비 20% 감소
위험성 평가 완료평가 완료율 (%)100% 완료
안전교육 강화교육 이수율 (%)95% 이상
보건직업병 발생 Zero직업병 발생 건수0건
건강진단 실시수진율 (%)100%
환경폐기물 감량폐기물 발생량 (톤)전년 대비 10% 감소
에너지 절약에너지 사용량 (kWh)전년 대비 5% 감소
+
+ +
+

9.3 실행 계획 수립

+

9.3.1 계획 수립 절차

+
    +
  1. 세부 과제 도출: 목표 달성을 위한 구체적 과제
  2. +
  3. 일정 계획: 단계별 추진 일정 수립
  4. +
  5. 책임자 지정: 과제별 담당자 및 책임자 배정
  6. +
  7. 자원 배정: 필요 인력, 예산, 자원 확보
  8. +
  9. 성과 지표: 중간 및 최종 성과 측정 지표
  10. +
  11. 점검 체계: 정기적 진행상황 점검 방법
  12. +
+ +

9.3.2 모니터링 및 검토

+
    +
  • 월별 점검: 진행상황 및 성과 확인
  • +
  • 분기별 평가: 목표 달성도 종합 평가
  • +
  • 연간 검토: 목표 적절성 및 달성 결과 종합 분석
  • +
  • 개선 조치: 미달성 원인 분석 및 개선 방안 수립
  • +
+
+
+ + +
+
+

10. 기록 관리

+
+ +

10.1 작성 기록

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
기록명작성자보관 기간보관 장소
위험과 기회 등록부HSE 담당자3년HSE 관리부서
유해요인 식별표각 부서장3년각 부서
위험 평가서HSE 담당자5년HSE 관리부서
법적 요구사항 목록HSE 관리책임자영구HSE 관리부서
HSE 목표 및 계획서HSE 관리책임자5년HSE 관리부서
진행상황 점검표각 부서장3년각 부서
+
+ + +
+
+

11. 첨부 서식

+
+ +
    +
  • 첨부 1: 위험과 기회 식별 체크리스트
  • +
  • 첨부 2: 유해요인 식별표 양식
  • +
  • 첨부 3: 위험 평가 매트릭스
  • +
  • 첨부 4: 위험 평가서 양식
  • +
  • 첨부 5: 법적 요구사항 등록부
  • +
  • 첨부 6: HSE 목표 설정 템플릿
  • +
  • 첨부 7: 실행 계획서 양식
  • +
  • 첨부 8: 진행상황 점검표
  • +
+
+
+ + +
+ +
+

TK-HSE-P-610

+

Planning and Risk Management Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitlePlanning and Risk Management Procedure
Document NumberTK-HSE-P-610
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 9
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+
+

1. PURPOSE

+
+

The purpose of this procedure is to:

+
    +
  • Systematic planning and implementation of HSE management system
  • +
  • Establish effective actions to address risks and opportunities
  • +
  • Systematic performance of hazard identification and HSE risk assessment
  • +
  • Systematic management of legal requirements and other requirements
  • +
  • Establish measurable HSE objectives and achievement plans
  • +
  • Effective implementation of ISO 45001:2018 Clause 6 requirements
  • +
+
+ + +
+
+

2. SCOPE

+
+

This procedure applies to the following areas of Technicalkorea:

+
    +
  • All activities within the scope of HSE management system application
  • +
  • All business sites including head office, factories, and branches
  • +
  • Regular, irregular, and contractor workers
  • +
  • Product production, service provision, and support activities
  • +
  • Routine and non-routine work, emergency situations
  • +
  • Past, present, and planned future activities
  • +
+
+ + +
+
+

3. NORMATIVE REFERENCES AND RELATED DOCUMENTS

+
+

3.1 Normative References

+
    +
  • ISO 45001:2018 - Occupational health and safety management systems - Requirements with guidance for use
  • +
  • ISO 31000:2018 - Risk management - Guidelines
  • +
  • Occupational Safety and Health Act and related regulations
  • +
  • Framework Act on Environmental Policy and related regulations
  • +
+ +

3.2 Related Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-410 - Understanding Organizational Context and HSE Management System Operation Procedure
  • +
  • TK-HSE-P-620 - Risk Assessment Procedure
  • +
  • TK-HSE-P-630 - HSE Legal Requirements Management Procedure
  • +
  • TK-HSE-P-640 - HSE Objectives Management Procedure
  • +
+
+ + +
+
+

4. TERMS AND DEFINITIONS

+
+ +
+

4.1 Risk

+

Effect of uncertainty, positive or negative deviation from objectives

+ +

4.2 Opportunity

+

Possibility of bringing positive results such as HSE performance improvement, waste reduction, accident prevention

+ +

4.3 Hazard

+

Source with a potential to cause injury and ill health

+ +

4.4 Risk Assessment

+

Overall process of risk identification, analysis and evaluation

+ +

4.5 Legal Requirements

+

Laws, regulations, orders, etc. that the organization must comply with

+ +

4.6 Objective

+

Result or performance to be achieved

+
+
+ + +
+
+

5. PROCESS FLOW

+
+ +
+
Planning Process Start
+
+
Risk and Opportunity Identification
+
+
Hazard Identification
+
+
Risk Assessment
+
+
Legal Requirements Identification
+
+
HSE Objectives Setting
+
+
Implementation Plan Development
+
+
Approval and Implementation
+
+
Monitoring and Review
+
+
+ + +
+
+

6. RISK AND OPPORTUNITY MANAGEMENT

+
+ +
+

6.1 Risk and Opportunity Identification

+

6.1.1 Identification Targets

+ + + + + + + + + + + + + + + + + + + + + +
CategoryIdentification TargetsConsiderations
Internal Risks• Equipment failure
• Human error
• Organizational change
• Resource shortage
• Probability of occurrence
• Impact level
• Controllability
• Response time
External Risks• Natural disasters
• Regulatory changes
• Market changes
• Supplier issues
• Predictability
• Response capability
• Recovery time
• Cost impact
Opportunities• Technology improvement
• Cost reduction
• Efficiency enhancement
• Image improvement
• Feasibility
• Return on investment
• Competitive advantage
• Sustainability
+
+ +
+

6.2 Risk and Opportunity Assessment

+
+

📊 Risk Assessment Matrix

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LikelihoodConsequence
1 (Minor)2 (Moderate)3 (Major)4 (Severe)5 (Catastrophic)
5 (Very High)510152025
4 (High)48121620
3 (Moderate)3691215
2 (Low)246810
1 (Very Low)12345
+ +

🎯 Risk Level Response Criteria

+
    +
  • High Risk (15-25): Immediate action required, consider work stoppage
  • +
  • Medium Risk (8-12): Improvement measures required in short term
  • +
  • Low Risk (3-6): Planned improvement measures
  • +
  • Acceptable (1-2): Maintain current level, regular monitoring
  • +
+
+
+ +
+

6.3 Action Plan Development

+

6.3.1 Risk Response Strategy

+
+

🔺 Risk Management Hierarchy

+
    +
  1. Elimination: Remove the risk factor itself
  2. +
  3. Substitution: Replace with safer alternatives
  4. +
  5. Engineering Controls: Reduce risk through technical methods
  6. +
  7. Administrative Controls: Management through procedures, education, training
  8. +
  9. Personal Protective Equipment (PPE): Protection through personal protective equipment
  10. +
+
+
+
+ + +
+
+

7. HAZARD IDENTIFICATION AND RISK ASSESSMENT

+
+ +
+

7.1 Hazard Classification

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ClassificationSub-typesMain Examples
Physical HazardsMechanical risks• Rotating parts, crushing, collision
• Falling, overturning, falling from height
Environmental risks• Noise, vibration, temperature
• Lighting, radiation
Electrical risks• Electric shock, fire, explosion
• Static electricity, lightning
Chemical HazardsToxic substances• Acids, alkalis, solvents
• Heavy metals, carcinogens
Gases/vapors• Toxic gases, asphyxiant gases
• Flammable gases
Biological HazardsPathogens• Bacteria, viruses, fungi
• Parasites, toxins
Allergens• Pollen, dust
• Animal fur, food
Ergonomic HazardsWork posture• Inappropriate posture
• Repetitive work, heavy objects
Work design• Workbench height
• Tool design, space
Psychosocial HazardsWork stress• Excessive workload
• Time pressure, responsibility
Organizational culture• Harassment, violence
• Lack of communication
+
+
+ + +
+
+

8. LEGAL REQUIREMENTS MANAGEMENT

+
+ +
+

8.1 Legal Requirements Identification

+

8.1.1 Major Laws

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldMajor LawsKey Requirements
SafetyOccupational Safety and Health Act• Establish safety and health management system
• Conduct risk assessment
• Implement safety and health education
Construction Equipment Management Act• Construction equipment inspection
• Operator license
• Safe operation
Chemical Control Act• Chemical registration
• Comply with handling standards
• Accident reporting
HealthOccupational Safety and Health Act• Work environment measurement
• Health examination
• Occupational disease prevention
Infectious Disease Control and Prevention Act• Infectious disease prevention measures
• Reporting obligation
• Quarantine activities
EnvironmentFramework Act on Environmental Policy• Environmental pollution prevention
• Minimize environmental impact
• Sustainable development
Clean Air Conservation Act• Comply with emission standards
• Install prevention facilities
• Measurement and reporting
Waste Management Act• Waste separation
• Consignment treatment
• Treatment status reporting
+
+
+ + +
+
+

9. HSE OBJECTIVES SETTING AND MANAGEMENT

+
+ +
+

9.1 Objective Setting Principles

+
+

🎯 SMART Principles

+
    +
  • Specific: Clear and specific objectives
  • +
  • Measurable: Quantitatively measurable
  • +
  • Achievable: Realistically achievable
  • +
  • Relevant: Related to HSE policy
  • +
  • Time-bound: Clear achievement deadline
  • +
+ +

📋 Objective Setting Considerations

+
    +
  • Consistency with HSE policy
  • +
  • Reflection of legal requirements
  • +
  • Reflection of risk assessment results
  • +
  • Technical and financial feasibility
  • +
  • Stakeholder expectations
  • +
  • Commitment to continuous improvement
  • +
+
+
+ +
+

9.2 Objectives by Area

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AreaObjective ExamplesMeasurement IndicatorsTarget Values
SafetyReduce accident rateAccident rate (%)20% reduction from previous year
Complete risk assessmentAssessment completion rate (%)100% completion
Strengthen safety educationEducation completion rate (%)95% or higher
HealthZero occupational disease occurrenceNumber of occupational disease cases0 cases
Conduct health examinationsExamination rate (%)100%
EnvironmentWaste reductionWaste generation (tons)10% reduction from previous year
Energy savingEnergy consumption (kWh)5% reduction from previous year
+
+
+ + +
+
+

10. RECORDS MANAGEMENT

+
+ +

10.1 Records to be Created

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Record NameCreatorRetention PeriodStorage Location
Risk and Opportunity RegisterHSE Staff3 yearsHSE Management Department
Hazard Identification TableEach Department Head3 yearsEach Department
Risk Assessment ReportHSE Staff5 yearsHSE Management Department
Legal Requirements ListHSE ManagerPermanentHSE Management Department
HSE Objectives and PlansHSE Manager5 yearsHSE Management Department
Progress Monitoring SheetEach Department Head3 yearsEach Department
+
+ + +
+
+

11. APPENDIX FORMS

+
+ +
    +
  • Appendix 1: Risk and Opportunity Identification Checklist
  • +
  • Appendix 2: Hazard Identification Table Form
  • +
  • Appendix 3: Risk Assessment Matrix
  • +
  • Appendix 4: Risk Assessment Report Form
  • +
  • Appendix 5: Legal Requirements Register
  • +
  • Appendix 6: HSE Objectives Setting Template
  • +
  • Appendix 7: Implementation Plan Form
  • +
  • Appendix 8: Progress Monitoring Sheet
  • +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-620.html b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-620.html new file mode 100644 index 0000000..c552dcd --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-620.html @@ -0,0 +1,1784 @@ + + + + + + TK-HSE-P-620 위험 평가 절차 + + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-620

+

위험 평가 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목위험 평가 절차
문서 번호TK-HSE-P-620
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+

1. 목적

+
+

본 절차는 테크니컬코리아의 모든 사업장 및 활동에서 발생할 수 있는 보건, 안전 및 환경(HSE) 위험요소를 체계적으로 식별, 평가 및 관리하기 위한 표준화된 방법론을 제공함을 목적으로 합니다.

+

이를 통해 근로자의 안전과 건강을 보호하고, 환경 영향을 최소화하며, ISO 45001:2018 요구사항에 부합하는 위험 관리 체계를 구축합니다.

+ + +
+

2. 적용 범위

+
+

본 절차는 다음에 적용됩니다:

+
    +
  • 테크니컬코리아의 모든 사업장, 시설 및 작업 현장
  • +
  • 정규직, 계약직, 파견직, 협력업체 직원을 포함한 모든 근로자
  • +
  • 일상적 및 비일상적 작업 활동
  • +
  • 제품 및 서비스의 전체 생명주기
  • +
  • 계획된 변경사항 및 비상상황
  • +
  • 모든 방문자 및 외부 이해관계자
  • +
+ + +
+

3. 관련 문서

+
+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-610 - 기획 및 위험 관리 절차
  • +
  • TK-HSE-P-630 - HSE 법적 요구사항 관리 절차
  • +
  • TK-HSE-P-810 - 운영 기획 및 관리 절차
  • +
  • TK-HSE-P-1010 - 사건, 부적합 및 시정조치 절차
  • +
  • ISO 45001:2018 - 보건안전경영시스템 요구사항
  • +
  • 산업안전보건법 및 관련 시행령, 시행규칙
  • +
  • 환경정책기본법 및 관련 법령
  • +
+ + +
+

4. 용어의 정의

+
+
+

4.1 유해요인(Hazard)

+

부상과 건강악화를 일으킬 잠재성을 가진 근원으로, 물리적, 화학적, 생물학적, 인간공학적, 심리사회적 요인을 포함합니다.

+ +

4.2 위험(Risk)

+

유해요인에 노출될 확률과 그로 인한 부상이나 건강악화의 심각성을 조합한 개념입니다.

+ +

4.3 위험 평가(Risk Assessment)

+

유해요인을 식별하고, 관련 위험을 분석 및 평가하는 전체적인 과정입니다.

+ +

4.4 허용 가능한 위험(Acceptable Risk)

+

조직의 법적 의무와 HSE 정책에 따라 수용 가능한 수준까지 감소된 위험입니다.

+ +

4.5 잔류 위험(Residual Risk)

+

위험 대응 조치를 실행한 후에도 남아있는 위험입니다.

+
+ + +
+

5. 역할과 책임

+
+
+

5.1 최고경영자

+
    +
  • 위험 평가 프로세스에 대한 최종 책임
  • +
  • 위험 평가에 필요한 자원 배정
  • +
  • 중대한 위험에 대한 의사결정
  • +
+ +

5.2 HSE 관리책임자

+
    +
  • 위험 평가 절차의 수립 및 유지
  • +
  • 위험 평가 팀 구성 및 교육
  • +
  • 위험 평가 결과의 검토 및 승인
  • +
  • 위험 평가 현황 모니터링
  • +
+ +

5.3 부서장/현장 관리자

+
    +
  • 담당 영역의 위험 평가 실시
  • +
  • 위험 통제 조치의 실행
  • +
  • 근로자의 위험 평가 참여 보장
  • +
  • 위험 평가 결과의 현장 적용
  • +
+ +

5.4 근로자

+
    +
  • 위험 평가 과정에 적극 참여
  • +
  • 유해요인 및 위험 상황 보고
  • +
  • 위험 통제 조치 준수
  • +
  • 안전 교육 및 훈련 참석
  • +
+ +

5.5 위험 평가팀

+
    +
  • 체계적인 위험 평가 수행
  • +
  • 위험 평가 보고서 작성
  • +
  • 위험 통제 조치 제안
  • +
  • 위험 평가 결과의 지속적 모니터링
  • +
+
+ + +
+

6. 위험 평가 프로세스

+
+ +
+
준비 및 기획
+ +
유해요인 식별
+ +
위험 분석
+

+
위험 평가
+ +
위험 대응
+ +
모니터링 및 검토
+
+ +
+

6.1 준비 및 기획 단계

+

6.1.1 위험 평가 범위 설정

+
    +
  • 평가 대상 작업, 활동, 시설의 명확한 정의
  • +
  • 평가 기간 및 주기 결정
  • +
  • 관련 법규 및 표준 확인
  • +
  • 이전 평가 결과 및 사고 이력 검토
  • +
+ +

6.1.2 위험 평가팀 구성

+
    +
  • 팀장: HSE 관리책임자 또는 지정된 담당자
  • +
  • 팀원: 해당 분야 전문가, 현장 관리자, 근로자 대표
  • +
  • 필요시 외부 전문가 참여
  • +
  • 팀원에 대한 위험 평가 교육 실시
  • +
+ +

6.1.3 정보 수집

+
    +
  • 작업 절차서 및 매뉴얼
  • +
  • 물질안전보건자료(MSDS)
  • +
  • 장비 및 기계 사양서
  • +
  • 과거 사고 및 아차사고 기록
  • +
  • 건강 검진 결과 및 직업병 발생 현황
  • +
  • 환경 모니터링 데이터
  • +
+
+ +
+

6.2 유해요인 식별

+

6.2.1 식별 방법

+
    +
  • 현장 조사 및 관찰
  • +
  • 작업 분석 및 작업 조건 검토
  • +
  • 근로자 면담 및 설문조사
  • +
  • 과거 사고 및 질병 기록 분석
  • +
  • 체크리스트 활용
  • +
  • 브레인스토밍 세션
  • +
+ +

6.2.2 유해요인 분류

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
분류유해요인 예시
물리적 유해요인소음, 진동, 온도, 조명, 방사선, 전기
화학적 유해요인독성물질, 부식성물질, 가연성물질, 분진, 가스, 증기
생물학적 유해요인세균, 바이러스, 곰팡이, 기생충
인간공학적 유해요인반복작업, 과도한 힘, 부자연스러운 자세, 진동
심리사회적 유해요인업무 스트레스, 작업 강도, 인간관계, 직장 내 괴롭힘
환경적 유해요인대기오염, 수질오염, 토양오염, 폐기물
+ +

6.2.3 노출 상황 고려사항

+
    +
  • 일상적 작업과 비일상적 작업
  • +
  • 정상 운영 조건과 비정상 조건
  • +
  • 비상상황 및 잠재적 사고 시나리오
  • +
  • 모든 작업자 및 방문자의 노출
  • +
  • 작업장 접근 경로 및 주변 영향
  • +
+
+ +
+

6.3 위험 분석

+

6.3.1 발생가능성 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
등급설명기준
5 (매우 높음)거의 확실히 발생주 1회 이상 또는 연간 50회 이상
4 (높음)발생 가능성이 높음월 1회 이상 또는 연간 12-50회
3 (보통)가끔 발생 가능년 1회 이상 또는 연간 1-12회
2 (낮음)발생 가능성이 낮음수년에 1회 또는 10년에 1-10회
1 (매우 낮음)거의 발생하지 않음10년에 1회 미만
+ +

6.3.2 심각성 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
등급설명인명 피해환경 영향
5 (치명적)사망 또는 영구장애사망 또는 영구 전신장애심각한 환경오염, 복구 불가능
4 (심각)중대한 부상 또는 질병중상, 만성질환, 부분장애중대한 환경영향, 복구 어려움
3 (보통)의료처치 필요의료처치 필요한 부상보통의 환경영향, 복구 가능
2 (경미)응급처치 필요응급처치 수준의 부상경미한 환경영향
1 (무시)부상 없음부상이나 건강영향 없음환경영향 무시할 수준
+
+ +
+

6.4 위험 평가

+

6.4.1 위험도 계산

+

위험도 = 발생가능성 × 심각성

+ +

6.4.2 위험도 매트릭스

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
심각성발생가능성
12345
5510152025
448121620
33691215
2246810
112345
+ +

6.4.3 위험도 분류 및 대응방안

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
위험도분류대응방안대응시한
20-25매우 높음즉시 작업 중단, 긴급 대책 수립즉시
10-19높음상세한 대책 수립 및 즉시 실행1주 이내
5-9보통대책 수립 및 계획에 따라 실행1개월 이내
1-4낮음현재 수준 유지, 정기 모니터링3개월 이내
+
+ + +
+

7. 위험 통제

+
+
+

7.1 통제 위계 (Hierarchy of Controls)

+
    +
  1. 제거 (Elimination): 유해요인 자체를 제거
  2. +
  3. 대체 (Substitution): 덜 위험한 방법, 재료, 장비로 대체
  4. +
  5. 공학적 통제 (Engineering Controls): 환기시설, 차폐, 격리 등
  6. +
  7. 관리적 통제 (Administrative Controls): 절차, 교육, 훈련, 표지판 등
  8. +
  9. 개인보호구 (Personal Protective Equipment): 마지막 수단으로 사용
  10. +
+ +

7.2 통제 조치 선정 기준

+
    +
  • 효과성: 위험 감소 효과
  • +
  • 실현가능성: 기술적, 경제적 실현 가능성
  • +
  • 수용성: 근로자 및 조직의 수용도
  • +
  • 지속성: 장기간 유지 가능성
  • +
  • 법적 요구사항 부합성
  • +
+ +

7.3 통제 조치 실행

+
    +
  • 실행 계획 수립 (담당자, 일정, 예산)
  • +
  • 필요한 자원 확보
  • +
  • 관련 인원 교육 및 훈련
  • +
  • 실행 상황 모니터링
  • +
  • 효과성 검증
  • +
+
+ + +
+

8. 문서화

+
+
+

8.1 위험 평가 보고서

+

모든 위험 평가 결과는 다음 내용을 포함하여 문서화해야 합니다:

+
    +
  • 평가 대상 및 범위
  • +
  • 평가팀 구성 및 역할
  • +
  • 평가 방법론
  • +
  • 식별된 유해요인 목록
  • +
  • 위험 분석 및 평가 결과
  • +
  • 제안된 통제 조치
  • +
  • 실행 계획
  • +
  • 모니터링 계획
  • +
+ +

8.2 위험 등록부 (Risk Register)

+

조직 차원의 통합 위험 등록부를 유지하며 다음 정보를 포함합니다:

+
    +
  • 위험 식별번호
  • +
  • 위험 설명
  • +
  • 영향 범위
  • +
  • 현재 통제 조치
  • +
  • 잔류 위험도
  • +
  • 추가 조치 계획
  • +
  • 담당자 및 일정
  • +
  • 검토 일정
  • +
+
+ + +
+

9. 모니터링 및 검토

+
+
+

9.1 정기 검토

+
    +
  • 일상 점검: 현장 관리자의 일일 안전 점검
  • +
  • 월간 검토: 부서별 위험 평가 현황 검토
  • +
  • 분기 검토: HSE 위원회의 위험 관리 현황 검토
  • +
  • 연간 검토: 전사 위험 평가의 전면적 재검토
  • +
+ +

9.2 검토 트리거

+

다음 상황에서는 즉시 위험 평가를 재검토해야 합니다:

+
    +
  • 사고 또는 아차사고 발생
  • +
  • 새로운 법규 또는 표준 시행
  • +
  • 작업 방법 또는 절차 변경
  • +
  • 새로운 장비 또는 화학물질 도입
  • +
  • 조직 구조 또는 인원 변경
  • +
  • 통제 조치의 실패 또는 부적절함 확인
  • +
+ +

9.3 성과 지표

+
    +
  • 위험 평가 완료율
  • +
  • 고위험 요소 감소율
  • +
  • 통제 조치 실행율
  • +
  • 사고 발생률 감소
  • +
  • 근로자 참여도
  • +
+
+ + +
+

10. 교육 및 훈련

+
+
+

10.1 교육 대상 및 내용

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
대상교육 내용주기
위험 평가팀위험 평가 방법론, 기법, 도구 사용법연 1회
관리자위험 관리 원칙, 통제 조치 선정 및 실행연 1회
근로자유해요인 인식, 위험 보고, 안전 수칙분기 1회
신입사원HSE 정책, 위험 평가 개념, 참여 방법입사시
+ +

10.2 교육 방법

+
    +
  • 집합 교육 및 워크숍
  • +
  • 온라인 교육 프로그램
  • +
  • 현장 실습 및 사례 연구
  • +
  • 외부 전문 교육 과정
  • +
+
+ + +
+
+

11. 위험 평가 양식

+
+ +
+

위험 평가 기본 정보

+ + + + + + + + + + + + + + + + + + + + + + + +
평가 번호평가 일자
평가 대상평가 유형□ 정기 □ 수시 □ 변경
평가팀장부서/현장
참여자
+
+ +
+

유해요인 식별 및 위험 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
작업/활동유해요인잠재적 결과현재 통제조치발생가능성심각성위험도위험 수준
+
+ +
+

위험 통제 조치

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
제안 조치우선순위담당자완료 예정일예상 효과잔류 위험도
+
+ +
+

승인

+ + + + + + + + + + + + + + + + + + + +
작성자성명:서명:일자:
검토자성명:서명:일자:
승인자성명:서명:일자:
+
+
+ + +
+

12. 문서 관리

+
+

이것은 통제 문서입니다

+

승인 없이 복사하지 마십시오

+

최신 버전은 회사 인트라넷에서 확인할 수 있습니다

+

이 문서에 대한 문의사항은 HSE 관리부서로 연락하십시오

+
+ + +
+ +
+

TK-HSE-P-620

+

Risk Assessment Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleRisk Assessment Procedure
Document NumberTK-HSE-P-620
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+

1. PURPOSE

+
+

This procedure aims to provide a standardized methodology for systematically identifying, assessing, and managing health, safety, and environmental (HSE) risk factors that may occur in all workplaces and activities of Technicalkorea.

+

Through this, we protect the safety and health of workers, minimize environmental impacts, and establish a risk management system that complies with ISO 45001:2018 requirements.

+ + +
+

2. SCOPE

+
+

This procedure applies to:

+
    +
  • All workplaces, facilities, and work sites of Technicalkorea
  • +
  • All workers including permanent, contract, temporary, and contractor personnel
  • +
  • Routine and non-routine work activities
  • +
  • Entire life cycle of products and services
  • +
  • Planned changes and emergency situations
  • +
  • All visitors and external stakeholders
  • +
+ + +
+

3. RELATED DOCUMENTS

+
+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-610 - Planning and Risk Management Procedure
  • +
  • TK-HSE-P-630 - HSE Legal Requirements Management Procedure
  • +
  • TK-HSE-P-810 - Operational Planning and Control Procedure
  • +
  • TK-HSE-P-1010 - Incident, Nonconformity and Corrective Action Procedure
  • +
  • ISO 45001:2018 - Occupational Health and Safety Management Systems Requirements
  • +
  • Occupational Safety and Health Act and related enforcement decrees and rules
  • +
  • Framework Act on Environmental Policy and related laws
  • +
+ + +
+

4. TERMS AND DEFINITIONS

+
+
+

4.1 Hazard

+

Source with a potential to cause injury and ill health, including physical, chemical, biological, ergonomic, and psychosocial factors.

+ +

4.2 Risk

+

A concept that combines the probability of exposure to hazards and the severity of resulting injury or ill health.

+ +

4.3 Risk Assessment

+

The overall process of identifying hazards and analyzing and evaluating related risks.

+ +

4.4 Acceptable Risk

+

Risk that has been reduced to a level that can be tolerated by the organization having regard to its legal obligations and HSE policy.

+ +

4.5 Residual Risk

+

Risk remaining after risk treatment measures have been implemented.

+
+ + +
+

5. ROLES AND RESPONSIBILITIES

+
+
+

5.1 Top Management

+
    +
  • Ultimate responsibility for risk assessment process
  • +
  • Allocation of resources required for risk assessment
  • +
  • Decision-making on significant risks
  • +
+ +

5.2 HSE Manager

+
    +
  • Establishment and maintenance of risk assessment procedures
  • +
  • Formation and training of risk assessment teams
  • +
  • Review and approval of risk assessment results
  • +
  • Monitoring risk assessment status
  • +
+ +

5.3 Department Heads/Site Managers

+
    +
  • Conducting risk assessments in their areas of responsibility
  • +
  • Implementation of risk control measures
  • +
  • Ensuring worker participation in risk assessment
  • +
  • Field application of risk assessment results
  • +
+ +

5.4 Workers

+
    +
  • Active participation in risk assessment process
  • +
  • Reporting hazards and risk situations
  • +
  • Compliance with risk control measures
  • +
  • Attendance at safety education and training
  • +
+ +

5.5 Risk Assessment Team

+
    +
  • Systematic risk assessment performance
  • +
  • Preparation of risk assessment reports
  • +
  • Proposal of risk control measures
  • +
  • Continuous monitoring of risk assessment results
  • +
+
+ + +
+

6. RISK ASSESSMENT PROCESS

+
+ +
+
Preparation & Planning
+ +
Hazard Identification
+ +
Risk Analysis
+

+
Risk Evaluation
+ +
Risk Treatment
+ +
Monitoring & Review
+
+ +
+

6.1 Preparation and Planning Phase

+

6.1.1 Risk Assessment Scope Setting

+
    +
  • Clear definition of work, activities, and facilities to be assessed
  • +
  • Determination of assessment period and cycle
  • +
  • Confirmation of relevant regulations and standards
  • +
  • Review of previous assessment results and incident history
  • +
+ +

6.1.2 Risk Assessment Team Formation

+
    +
  • Team Leader: HSE Manager or designated person
  • +
  • Team Members: Subject matter experts, site managers, worker representatives
  • +
  • External experts participation when necessary
  • +
  • Risk assessment training for team members
  • +
+ +

6.1.3 Information Collection

+
    +
  • Work procedures and manuals
  • +
  • Material Safety Data Sheets (MSDS)
  • +
  • Equipment and machinery specifications
  • +
  • Past accident and near-miss records
  • +
  • Health examination results and occupational disease status
  • +
  • Environmental monitoring data
  • +
+
+ +
+

6.2 Hazard Identification

+

6.2.1 Identification Methods

+
    +
  • Site inspection and observation
  • +
  • Work analysis and working condition review
  • +
  • Worker interviews and surveys
  • +
  • Analysis of past accident and disease records
  • +
  • Checklist utilization
  • +
  • Brainstorming sessions
  • +
+ +

6.2.2 Hazard Classification

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ClassificationHazard Examples
Physical HazardsNoise, vibration, temperature, lighting, radiation, electricity
Chemical HazardsToxic substances, corrosive substances, flammable substances, dust, gas, vapor
Biological HazardsBacteria, viruses, fungi, parasites
Ergonomic HazardsRepetitive work, excessive force, awkward postures, vibration
Psychosocial HazardsWork stress, work intensity, human relations, workplace harassment
Environmental HazardsAir pollution, water pollution, soil contamination, waste
+ +

6.2.3 Exposure Situation Considerations

+
    +
  • Routine and non-routine work
  • +
  • Normal and abnormal operating conditions
  • +
  • Emergency situations and potential accident scenarios
  • +
  • Exposure of all workers and visitors
  • +
  • Workplace access routes and surrounding impacts
  • +
+
+ +
+

6.3 Risk Analysis

+

6.3.1 Likelihood Assessment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LevelDescriptionCriteria
5 (Very High)Almost certain to occurMore than once a week or 50+ times per year
4 (High)Likely to occurMore than once a month or 12-50 times per year
3 (Medium)May occur occasionallyMore than once a year or 1-12 times per year
2 (Low)Unlikely to occurOnce in several years or 1-10 times in 10 years
1 (Very Low)Rare occurrenceLess than once in 10 years
+ +

6.3.2 Severity Assessment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LevelDescriptionHuman ImpactEnvironmental Impact
5 (Fatal)Death or permanent disabilityDeath or permanent total disabilitySevere environmental pollution, irreversible
4 (Serious)Major injury or illnessSerious injury, chronic disease, partial disabilityMajor environmental impact, difficult to recover
3 (Moderate)Medical treatment requiredInjury requiring medical treatmentModerate environmental impact, recoverable
2 (Minor)First aid requiredFirst aid level injuryMinor environmental impact
1 (Negligible)No injuryNo injury or health impactNegligible environmental impact
+
+ +
+

6.4 Risk Evaluation

+

6.4.1 Risk Level Calculation

+

Risk Level = Likelihood × Severity

+ +

6.4.2 Risk Matrix

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SeverityLikelihood
12345
5510152025
448121620
33691215
2246810
112345
+ +

6.4.3 Risk Level Classification and Response

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Risk LevelClassificationResponseTimeline
20-25Very HighImmediate work stoppage, emergency measuresImmediate
10-19HighDetailed measures development and immediate implementationWithin 1 week
5-9MediumMeasures development and planned implementationWithin 1 month
1-4LowMaintain current level, regular monitoringWithin 3 months
+
+ + +
+

7. RISK CONTROL

+
+
+

7.1 Hierarchy of Controls

+
    +
  1. Elimination: Remove the hazard entirely
  2. +
  3. Substitution: Replace with less hazardous methods, materials, or equipment
  4. +
  5. Engineering Controls: Ventilation, shielding, isolation, etc.
  6. +
  7. Administrative Controls: Procedures, training, education, signage, etc.
  8. +
  9. Personal Protective Equipment (PPE): Use as last resort
  10. +
+ +

7.2 Control Measure Selection Criteria

+
    +
  • Effectiveness: Risk reduction effect
  • +
  • Feasibility: Technical and economic feasibility
  • +
  • Acceptability: Worker and organizational acceptance
  • +
  • Sustainability: Long-term maintainability
  • +
  • Legal compliance
  • +
+ +

7.3 Control Measure Implementation

+
    +
  • Implementation plan development (responsible person, schedule, budget)
  • +
  • Securing necessary resources
  • +
  • Training and education of relevant personnel
  • +
  • Implementation status monitoring
  • +
  • Effectiveness verification
  • +
+
+ + +
+

8. DOCUMENTATION

+
+
+

8.1 Risk Assessment Report

+

All risk assessment results must be documented including the following content:

+
    +
  • Assessment target and scope
  • +
  • Assessment team composition and roles
  • +
  • Assessment methodology
  • +
  • List of identified hazards
  • +
  • Risk analysis and evaluation results
  • +
  • Proposed control measures
  • +
  • Implementation plan
  • +
  • Monitoring plan
  • +
+ +

8.2 Risk Register

+

Maintain an integrated organizational risk register including the following information:

+
    +
  • Risk identification number
  • +
  • Risk description
  • +
  • Impact scope
  • +
  • Current control measures
  • +
  • Residual risk level
  • +
  • Additional measure plans
  • +
  • Responsible person and schedule
  • +
  • Review schedule
  • +
+
+ + +
+

9. MONITORING AND REVIEW

+
+
+

9.1 Regular Review

+
    +
  • Daily Inspection: Daily safety inspections by site managers
  • +
  • Monthly Review: Departmental risk assessment status review
  • +
  • Quarterly Review: HSE committee risk management status review
  • +
  • Annual Review: Comprehensive review of company-wide risk assessments
  • +
+ +

9.2 Review Triggers

+

Risk assessments must be immediately re-reviewed in the following situations:

+
    +
  • Occurrence of accidents or near-misses
  • +
  • Implementation of new regulations or standards
  • +
  • Changes in work methods or procedures
  • +
  • Introduction of new equipment or chemicals
  • +
  • Changes in organizational structure or personnel
  • +
  • Identification of control measure failure or inadequacy
  • +
+ +

9.3 Performance Indicators

+
    +
  • Risk assessment completion rate
  • +
  • High-risk factor reduction rate
  • +
  • Control measure implementation rate
  • +
  • Accident occurrence rate reduction
  • +
  • Worker participation rate
  • +
+
+ + +
+

10. TRAINING AND EDUCATION

+
+
+

10.1 Training Target and Content

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
TargetTraining ContentFrequency
Risk Assessment TeamRisk assessment methodology, techniques, tool usageAnnual
ManagersRisk management principles, control measure selection and implementationAnnual
WorkersHazard recognition, risk reporting, safety rulesQuarterly
New EmployeesHSE policy, risk assessment concepts, participation methodsUpon hiring
+ +

10.2 Training Methods

+
    +
  • Group training and workshops
  • +
  • Online training programs
  • +
  • Field practice and case studies
  • +
  • External professional training courses
  • +
+
+ + +
+
+

11. RISK ASSESSMENT FORM

+
+ +
+

Risk Assessment Basic Information

+ + + + + + + + + + + + + + + + + + + + + + + +
Assessment No.Assessment Date
Assessment TargetAssessment Type□ Regular □ Ad-hoc □ Change
Team LeaderDepartment/Site
Participants
+
+ +
+

Hazard Identification and Risk Assessment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Work/ActivityHazardPotential ConsequenceCurrent ControlsLikelihoodSeverityRisk LevelRisk Rating
+
+ +
+

Risk Control Measures

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Proposed MeasuresPriorityResponsible PersonTarget DateExpected EffectResidual Risk
+
+ +
+

Approval

+ + + + + + + + + + + + + + + + + + + +
Prepared byName:Signature:Date:
Reviewed byName:Signature:Date:
Approved byName:Signature:Date:
+
+
+ + +
+

12. DOCUMENT CONTROL

+
+

This is a controlled document

+

Do not copy without authorization

+

The latest version can be found on the company intranet

+

For inquiries about this document, contact the HSE Management Department

+
+
+ + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-630.html b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-630.html new file mode 100644 index 0000000..1f3f431 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/hse/TK-HSE-P-630.html @@ -0,0 +1,1894 @@ + + + + + + TK-HSE-P-630 HSE 법적 요구사항 관리 절차 + + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-630

+

HSE 법적 요구사항 관리 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목HSE 법적 요구사항 관리 절차
문서 번호TK-HSE-P-630
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+

1. 목적

+
+

본 절차는 테크니컬코리아의 사업 활동과 관련된 보건, 안전 및 환경(HSE) 법적 요구사항을 체계적으로 식별, 접근, 평가 및 관리하기 위한 프레임워크를 제공함을 목적으로 합니다.

+

이를 통해 법적 요구사항의 준수를 보장하고, 법규 위반으로 인한 리스크를 최소화하며, 지속적인 개선을 통한 HSE 성과 향상을 달성합니다.

+ +
+ 중요: 법적 요구사항의 식별과 준수는 조직의 HSE 경영시스템의 핵심 요소이며, ISO 45001:2018 및 ISO 14001:2015의 필수 요구사항입니다. +
+ + +
+

2. 적용 범위

+
+

본 절차는 다음에 적용됩니다:

+
    +
  • 테크니컬코리아의 모든 사업장 및 운영 활동
  • +
  • 국내외 모든 자회사 및 관계회사
  • +
  • 협력업체 및 계약업체와의 HSE 관련 활동
  • +
  • 제품 및 서비스의 전체 생명주기
  • +
  • 다음 분야의 법적 요구사항: +
      +
    • 산업안전보건 관련 법규
    • +
    • 환경보호 관련 법규
    • +
    • 화학물질 관리 관련 법규
    • +
    • 건설안전 관련 법규
    • +
    • 소방안전 관련 법규
    • +
    • 기타 HSE 관련 규제 및 표준
    • +
    +
  • +
+ + +
+

3. 관련 문서

+
+
+

3.1 내부 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-610 - 기획 및 위험 관리 절차
  • +
  • TK-HSE-P-620 - 위험 평가 절차
  • +
  • TK-HSE-P-810 - 운영 기획 및 관리 절차
  • +
  • TK-HSE-P-1010 - 사건, 부적합 및 시정조치 절차
  • +
+ +

3.2 외부 참조 표준

+
    +
  • ISO 45001:2018 - 보건안전경영시스템 요구사항
  • +
  • ISO 14001:2015 - 환경경영시스템 요구사항
  • +
  • ISO 9001:2015 - 품질경영시스템 요구사항
  • +
+ +

3.3 주요 법적 요구사항

+
    +
  • 산업안전보건법 및 시행령, 시행규칙
  • +
  • 환경정책기본법 및 관련 법령
  • +
  • 대기환경보전법
  • +
  • 수질 및 수생태계 보전에 관한 법률
  • +
  • 폐기물관리법
  • +
  • 화학물질관리법
  • +
  • 소방기본법
  • +
  • 건설기술 진흥법
  • +
+
+ + +
+

4. 용어의 정의

+
+
+

4.1 법적 요구사항(Legal Requirements)

+

국가 또는 지역의 법률, 규정, 조례, 허가, 라이선스 및 기타 형태의 정부 인가에 따라 조직이 준수해야 하는 요구사항입니다.

+ +

4.2 기타 요구사항(Other Requirements)

+

조직이 준수하기로 선택하거나 채택한 기타 요구사항으로, 업계 표준, 고객 요구사항, 자발적 약속 등을 포함합니다.

+ +

4.3 준수 평가(Compliance Evaluation)

+

조직이 법적 요구사항 및 기타 요구사항에 얼마나 잘 부합하는지를 판단하는 과정입니다.

+ +

4.4 규제 감시(Regulatory Monitoring)

+

조직의 활동에 적용되는 법적 요구사항의 변경사항을 지속적으로 추적하고 식별하는 과정입니다.

+ +

4.5 법적 등록부(Legal Register)

+

조직에 적용되는 모든 법적 요구사항과 기타 요구사항을 체계적으로 문서화한 데이터베이스 또는 목록입니다.

+
+ + +
+

5. 역할과 책임

+
+
+

5.1 최고경영자

+
    +
  • 법적 요구사항 관리에 대한 최종 책임
  • +
  • 법적 요구사항 준수를 위한 자원 할당
  • +
  • 중대한 법적 이슈에 대한 의사결정
  • +
  • 법적 위반 사항에 대한 최종 승인 및 조치
  • +
+ +

5.2 HSE 관리책임자

+
    +
  • 법적 요구사항 관리 체계의 수립 및 운영
  • +
  • 법적 등록부의 구축 및 유지관리
  • +
  • 준수 평가 프로그램의 기획 및 실행
  • +
  • 법적 요구사항 변경에 대한 영향 평가
  • +
  • 관련 부서에 대한 교육 및 지원
  • +
+ +

5.3 법무팀

+
    +
  • 법적 요구사항의 해석 및 자문
  • +
  • 규제 변경사항의 법적 영향 분석
  • +
  • 허가 및 인가 절차 지원
  • +
  • 법적 분쟁 및 위반 사항 대응
  • +
+ +

5.4 부서장/현장 관리자

+
    +
  • 담당 영역의 법적 요구사항 식별 지원
  • +
  • 해당 법적 요구사항의 현장 적용 및 준수
  • +
  • 법적 요구사항 위반 가능성 보고
  • +
  • 개선 조치의 실행 및 모니터링
  • +
+ +

5.5 모든 근로자

+
    +
  • 적용 가능한 법적 요구사항의 숙지 및 준수
  • +
  • 법적 요구사항 위반 상황의 즉시 보고
  • +
  • 관련 교육 및 훈련 참여
  • +
+
+ + +
+

6. 법적 요구사항 관리 프로세스

+
+ +
+
식별
+ +
접근 및 확보
+ +
분석 및 평가
+

+
등록부 업데이트
+ +
의무사항 전파
+ +
준수 모니터링
+
+ +
+

6.1 법적 요구사항 식별

+

6.1.1 식별 방법

+
    +
  • 체계적 검토: 정기적인 법규 데이터베이스 검색
  • +
  • 전문 서비스 활용: 법률 자문 및 규제 모니터링 서비스
  • +
  • 업계 정보: 협회, 세미나, 컨퍼런스를 통한 정보 수집
  • +
  • 정부 기관: 관련 부처 및 지방자치단체 공지사항
  • +
  • 내부 제보: 직원, 고객, 협력업체로부터의 정보
  • +
+ +

6.1.2 식별 대상

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

6.2 법적 요구사항 접근 및 확보

+

6.2.1 정보 소스

+
    +
  • 공식 채널 +
      +
    • 국가법령정보센터 (www.law.go.kr)
    • +
    • 행정안전부 자치법규정보시스템
    • +
    • 관련 부처 공식 웹사이트
    • +
    +
  • +
  • 전문 서비스 +
      +
    • 법률 자문 서비스
    • +
    • 규제 모니터링 전문업체
    • +
    • 업계 전문 컨설팅
    • +
    +
  • +
  • 업계 네트워크 +
      +
    • 산업별 협회 및 단체
    • +
    • 전문 세미나 및 워크숍
    • +
    • 동종업계 정보 교류
    • +
    +
  • +
+ +

6.2.2 문서 관리

+
    +
  • 모든 법규 문서의 전자 파일 보관
  • +
  • 최신 버전 유지 및 이력 관리
  • +
  • 접근 권한 설정 및 보안 관리
  • +
  • 백업 및 복구 체계 구축
  • +
+
+ +
+

6.3 법적 요구사항 분석 및 평가

+

6.3.1 적용성 평가

+

다음 기준에 따라 각 법적 요구사항의 조직 적용성을 평가합니다:

+
    +
  • 지리적 범위: 사업장 위치에 따른 적용 법규
  • +
  • 업종별 적용: 사업 분야에 따른 특화 법규
  • +
  • 규모별 적용: 기업 규모, 시설 규모에 따른 차등 적용
  • +
  • 활동별 적용: 특정 활동 또는 공정에 대한 법규
  • +
+ +

6.3.2 영향 분석

+ + + + + + + + + + + + + + + + + + + + + + + +

6.3.3 갭 분석

+

현재 조직 상태와 법적 요구사항 간의 차이를 분석:

+
    +
  • 현재 준수 수준 평가
  • +
  • 필요한 개선사항 식별
  • +
  • 추가 자원 소요 분석
  • +
  • 이행 일정 수립
  • +
+
+ + +
+

7. 법적 등록부 관리

+
+
+

7.1 등록부 구조

+

법적 등록부는 다음 정보를 포함해야 합니다:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

7.2 등록부 유지관리

+
    +
  • 정기 업데이트: 월 1회 이상 내용 검토 및 업데이트
  • +
  • 버전 관리: 변경 이력 및 승인 기록 유지
  • +
  • 접근 관리: 부서별 차등 접근 권한 설정
  • +
  • 백업 관리: 정기적 백업 및 복구 테스트
  • +
+ +

7.3 등록부 품질 관리

+
    +
  • 데이터 정확성 검증
  • +
  • 중복 항목 제거
  • +
  • 폐지된 법규 아카이빙
  • +
  • 관련 문서 링크 유지
  • +
+
+ + +
+

8. 준수 평가

+
+
+

8.1 평가 계획

+

8.1.1 평가 주기

+ + + + + + + + + + + + + + + + + + + + + + + +

8.1.2 평가 방법

+
    +
  • 현장 점검: 직접 현장 방문을 통한 준수 상태 확인
  • +
  • 문서 검토: 관련 기록 및 보고서 분석
  • +
  • 인터뷰: 담당자 및 작업자 면담
  • +
  • 테스트: 필요시 측정 및 시험 실시
  • +
+ +

8.2 평가 실행

+

8.2.1 평가팀 구성

+
    +
  • 팀장: HSE 관리책임자 또는 지정된 담당자
  • +
  • 팀원: 관련 부서 전문가, 외부 전문가
  • +
  • 관찰자: 해당 부서 담당자
  • +
+ +

8.2.2 평가 절차

+
    +
  1. 평가 계획 수립 및 통보
  2. +
  3. 관련 자료 사전 검토
  4. +
  5. 현장 평가 실시
  6. +
  7. 발견사항 정리 및 확인
  8. +
  9. 평가 보고서 작성
  10. +
  11. 개선계획 수립
  12. +
+ +

8.3 준수 상태 분류

+ + + + + + + + + + + + + + + + + + + + + + +
+ + +
+

9. 의사소통 및 교육

+
+
+

9.1 내부 의사소통

+

9.1.1 의사소통 채널

+
    +
  • 정기 회의: HSE 위원회, 부서별 회의
  • +
  • 교육 및 훈련: 신입사원, 보수교육
  • +
  • 공지사항: 인트라넷, 게시판, 이메일
  • +
  • 보고서: 월간/분기별 HSE 보고서
  • +
+ +

9.1.2 의사소통 내용

+
    +
  • 새로운 법적 요구사항 및 변경사항
  • +
  • 준수 평가 결과 및 개선계획
  • +
  • 위반 사례 및 교훈사항
  • +
  • 모범 사례 및 성공 스토리
  • +
+ +

9.2 교육 및 훈련

+

9.2.1 교육 프로그램

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

9.2.2 교육 효과성 평가

+
    +
  • 교육 이해도 테스트
  • +
  • 현장 적용 상황 점검
  • +
  • 참가자 만족도 조사
  • +
  • 행동 변화 모니터링
  • +
+
+ + +
+

10. 모니터링 및 검토

+
+
+

10.1 규제 변화 모니터링

+

10.1.1 모니터링 시스템

+
    +
  • 자동 알림 서비스: 법규 변경 알림 시스템 구축
  • +
  • 정기 검색: 주간 단위 법규 데이터베이스 검색
  • +
  • 전문가 네트워크: 법률 자문사, 컨설턴트 활용
  • +
  • 업계 정보: 협회, 세미나 참여를 통한 정보 수집
  • +
+ +

10.1.2 변경사항 대응

+
    +
  1. 변경사항 식별 및 분석
  2. +
  3. 조직 영향도 평가
  4. +
  5. 대응 계획 수립
  6. +
  7. 관련 부서 통보
  8. +
  9. 필요시 절차 및 시스템 업데이트
  10. +
  11. 교육 및 훈련 실시
  12. +
+ +

10.2 성과 모니터링

+

10.2.1 핵심 성과 지표 (KPI)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

10.2.2 보고 체계

+
    +
  • 월간 보고: 부서별 준수 현황
  • +
  • 분기 보고: 전사 종합 현황
  • +
  • 연간 보고: 성과 평가 및 개선계획
  • +
  • 특별 보고: 중대 위반 또는 변경사항
  • +
+ +

10.3 시스템 검토

+

10.3.1 정기 검토

+
    +
  • 분기 검토: 절차 적정성 및 효과성
  • +
  • 연간 검토: 전체 시스템 종합 평가
  • +
  • 특별 검토: 중대 변경 또는 사고 발생시
  • +
+ +

10.3.2 개선 활동

+
    +
  • 검토 결과에 따른 개선계획 수립
  • +
  • 절차 및 시스템 업데이트
  • +
  • 교육 프로그램 개선
  • +
  • 모니터링 시스템 강화
  • +
+
+ + +
+
+

11. 양식 및 서식

+
+ +
+

11.1 법적 요구사항 등록 양식

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

11.2 준수 평가 체크리스트

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

11.3 법규 변경 통보서

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+

12. 문서 관리

+
+
+ 문서 통제
+ 이 문서는 통제 문서입니다. 승인 없이 복사하거나 배포하지 마십시오.
+ 최신 버전은 회사 인트라넷에서 확인할 수 있습니다.
+ 문의사항은 HSE 관리부서로 연락하십시오. +
+
+ + +
+ +
+

TK-HSE-P-630

+

HSE Legal Requirements Management Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleHSE Legal Requirements Management Procedure
Document NumberTK-HSE-P-630
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+

1. PURPOSE

+
+

This procedure aims to provide a framework for systematically identifying, accessing, evaluating, and managing health, safety, and environmental (HSE) legal requirements related to Technicalkorea's business activities.

+

Through this, we ensure compliance with legal requirements, minimize risks from regulatory violations, and achieve improved HSE performance through continuous improvement.

+ +
+ Important: Identification and compliance with legal requirements is a core element of the organization's HSE management system and a mandatory requirement of ISO 45001:2018 and ISO 14001:2015. +
+ + +
+

2. SCOPE

+
+

This procedure applies to:

+
    +
  • All workplaces and operational activities of Technicalkorea
  • +
  • All domestic and international subsidiaries and affiliates
  • +
  • HSE-related activities with contractors and subcontractors
  • +
  • Entire life cycle of products and services
  • +
  • Legal requirements in the following areas: +
      +
    • Occupational health and safety regulations
    • +
    • Environmental protection regulations
    • +
    • Chemical substance management regulations
    • +
    • Construction safety regulations
    • +
    • Fire safety regulations
    • +
    • Other HSE-related regulations and standards
    • +
    +
  • +
+ + + + +
+

3. RELATED DOCUMENTS

+
+
+

3.1 Internal Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-610 - Planning and Risk Management Procedure
  • +
  • TK-HSE-P-620 - Risk Assessment Procedure
  • +
  • TK-HSE-P-810 - Operational Planning and Control Procedure
  • +
  • TK-HSE-P-1010 - Incident, Nonconformity and Corrective Action Procedure
  • +
+ +

3.2 External Reference Standards

+
    +
  • ISO 45001:2018 - Occupational Health and Safety Management Systems Requirements
  • +
  • ISO 14001:2015 - Environmental Management Systems Requirements
  • +
  • ISO 9001:2015 - Quality Management Systems Requirements
  • +
+ +

3.3 Key Legal Requirements

+
    +
  • Occupational Safety and Health Act and enforcement decrees and rules
  • +
  • Framework Act on Environmental Policy and related laws
  • +
  • Clean Air Conservation Act
  • +
  • Water Quality and Aquatic Ecosystem Conservation Act
  • +
  • Waste Management Act
  • +
  • Chemical Substances Control Act
  • +
  • Framework Act on Fire Services
  • +
  • Construction Technology Promotion Act
  • +
+
+ + +
+

4. TERMS AND DEFINITIONS

+
+
+

4.1 Legal Requirements

+

Requirements that an organization must comply with according to national or regional laws, regulations, ordinances, permits, licenses, and other forms of governmental authorization.

+ +

4.2 Other Requirements

+

Other requirements that the organization chooses to comply with or adopt, including industry standards, customer requirements, voluntary commitments, etc.

+ +

4.3 Compliance Evaluation

+

The process of determining how well an organization conforms to legal requirements and other requirements.

+ +

4.4 Regulatory Monitoring

+

The process of continuously tracking and identifying changes in legal requirements applicable to the organization's activities.

+ +

4.5 Legal Register

+

A database or list that systematically documents all legal requirements and other requirements applicable to the organization.

+
+ + +
+

5. ROLES AND RESPONSIBILITIES

+
+
+

5.1 Top Management

+
    +
  • Ultimate responsibility for legal requirements management
  • +
  • Resource allocation for legal requirements compliance
  • +
  • Decision-making on significant legal issues
  • +
  • Final approval and action on legal violations
  • +
+ +

5.2 HSE Manager

+
    +
  • Establishment and operation of legal requirements management system
  • +
  • Construction and maintenance of legal register
  • +
  • Planning and execution of compliance evaluation programs
  • +
  • Impact assessment of legal requirements changes
  • +
  • Training and support for related departments
  • +
+ +

5.3 Legal Team

+
    +
  • Interpretation and consultation on legal requirements
  • +
  • Legal impact analysis of regulatory changes
  • +
  • Support for permit and authorization procedures
  • +
  • Response to legal disputes and violations
  • +
+ +

5.4 Department Heads/Site Managers

+
    +
  • Support identification of legal requirements in their areas
  • +
  • Site application and compliance with applicable legal requirements
  • +
  • Report potential legal requirement violations
  • +
  • Implementation and monitoring of improvement measures
  • +
+ +

5.5 All Workers

+
    +
  • Understanding and compliance with applicable legal requirements
  • +
  • Immediate reporting of legal requirement violation situations
  • +
  • Participation in related education and training
  • +
+
+ + +
+

6. LEGAL REQUIREMENTS MANAGEMENT PROCESS

+
+ +
+
Identification
+ +
Access & Acquisition
+ +
Analysis & Evaluation
+

+
Register Update
+ +
Dissemination
+ +
Compliance Monitoring
+
+ +
+

6.1 Legal Requirements Identification

+

6.1.1 Identification Methods

+
    +
  • Systematic Review: Regular legal database searches
  • +
  • Professional Services: Legal consultation and regulatory monitoring services
  • +
  • Industry Information: Information gathering through associations, seminars, conferences
  • +
  • Government Agencies: Notices from relevant ministries and local governments
  • +
  • Internal Reports: Information from employees, customers, contractors
  • +
+ +

6.1.2 Identification Targets

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

6.2 Legal Requirements Access and Acquisition

+

6.2.1 Information Sources

+
    +
  • Official Channels +
      +
    • Korea Law Information Center (www.law.go.kr)
    • +
    • Local Regulations Information System
    • +
    • Official websites of relevant ministries
    • +
    +
  • +
  • Professional Services +
      +
    • Legal consultation services
    • +
    • Regulatory monitoring specialists
    • +
    • Industry-specific consulting
    • +
    +
  • +
  • Industry Networks +
      +
    • Industry associations and organizations
    • +
    • Professional seminars and workshops
    • +
    • Peer industry information exchange
    • +
    +
  • +
+ +

6.2.2 Document Management

+
    +
  • Electronic file storage of all regulatory documents
  • +
  • Latest version maintenance and history management
  • +
  • Access permission settings and security management
  • +
  • Backup and recovery system establishment
  • +
+
+ +
+

6.3 Legal Requirements Analysis and Evaluation

+

6.3.1 Applicability Assessment

+

Evaluate the organizational applicability of each legal requirement according to the following criteria:

+
    +
  • Geographic Scope: Applicable regulations by workplace location
  • +
  • Industry-specific Application: Specialized regulations by business sector
  • +
  • Scale-based Application: Differential application by company size, facility scale
  • +
  • Activity-specific Application: Regulations for specific activities or processes
  • +
+ +

6.3.2 Impact Analysis

+ + + + + + + + + + + + + + + + + + + + + + + +

6.3.3 Gap Analysis

+

Analyze differences between current organizational status and legal requirements:

+
    +
  • Current compliance level assessment
  • +
  • Identification of necessary improvements
  • +
  • Additional resource requirement analysis
  • +
  • Implementation schedule establishment
  • +
+
+ + +
+

7. LEGAL REGISTER MANAGEMENT

+
+
+

7.1 Register Structure

+

The legal register must include the following information:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

7.2 Register Maintenance

+
    +
  • Regular Updates: Content review and update at least monthly
  • +
  • Version Control: Maintain change history and approval records
  • +
  • Access Management: Set differential access permissions by department
  • +
  • Backup Management: Regular backup and recovery testing
  • +
+ +

7.3 Register Quality Management

+
    +
  • Data accuracy verification
  • +
  • Duplicate item removal
  • +
  • Archiving of repealed regulations
  • +
  • Maintenance of related document links
  • +
+
+ + +
+

8. COMPLIANCE EVALUATION

+
+
+

8.1 Evaluation Planning

+

8.1.1 Evaluation Frequency

+ + + + + + + + + + + + + + + + + + + + + + + +

8.1.2 Evaluation Methods

+
    +
  • Site Inspection: Direct site visits to verify compliance status
  • +
  • Document Review: Analysis of related records and reports
  • +
  • Interviews: Interviews with responsible persons and workers
  • +
  • Testing: Measurement and testing when necessary
  • +
+ +

8.2 Evaluation Implementation

+

8.2.1 Evaluation Team Composition

+
    +
  • Team Leader: HSE Manager or designated person
  • +
  • Team Members: Related department experts, external experts
  • +
  • Observers: Department representatives
  • +
+ +

8.2.2 Evaluation Procedure

+
    +
  1. Evaluation plan establishment and notification
  2. +
  3. Preliminary review of related materials
  4. +
  5. Site evaluation implementation
  6. +
  7. Findings compilation and confirmation
  8. +
  9. Evaluation report preparation
  10. +
  11. Improvement plan establishment
  12. +
+ +

8.3 Compliance Status Classification

+ + + + + + + + + + + + + + + + + + + + + + +
+ + +
+

9. COMMUNICATION AND TRAINING

+
+
+

9.1 Internal Communication

+

9.1.1 Communication Channels

+
    +
  • Regular Meetings: HSE committee, departmental meetings
  • +
  • Education and Training: New employee, refresher training
  • +
  • Announcements: Intranet, bulletin boards, email
  • +
  • Reports: Monthly/quarterly HSE reports
  • +
+ +

9.1.2 Communication Content

+
    +
  • New legal requirements and changes
  • +
  • Compliance evaluation results and improvement plans
  • +
  • Violation cases and lessons learned
  • +
  • Best practices and success stories
  • +
+ +

9.2 Education and Training

+

9.2.1 Training Programs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

9.2.2 Training Effectiveness Evaluation

+
    +
  • Training comprehension tests
  • +
  • Field application situation checks
  • +
  • Participant satisfaction surveys
  • +
  • Behavioral change monitoring
  • +
+
+ + +
+

10. MONITORING AND REVIEW

+
+
+

10.1 Regulatory Change Monitoring

+

10.1.1 Monitoring System

+
    +
  • Automatic Alert Service: Regulatory change alert system establishment
  • +
  • Regular Search: Weekly regulatory database searches
  • +
  • Expert Network: Utilization of legal advisors, consultants
  • +
  • Industry Information: Information gathering through associations, seminars
  • +
+ +

10.1.2 Change Response

+
    +
  1. Change identification and analysis
  2. +
  3. Organizational impact assessment
  4. +
  5. Response plan establishment
  6. +
  7. Notification to related departments
  8. +
  9. Procedure and system updates when necessary
  10. +
  11. Education and training implementation
  12. +
+ +

10.2 Performance Monitoring

+

10.2.1 Key Performance Indicators (KPI)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

10.2.2 Reporting Structure

+
    +
  • Monthly Report: Departmental compliance status
  • +
  • Quarterly Report: Company-wide comprehensive status
  • +
  • Annual Report: Performance evaluation and improvement plan
  • +
  • Special Report: Major violations or changes
  • +
+ +

10.3 System Review

+

10.3.1 Regular Review

+
    +
  • Quarterly Review: Procedure adequacy and effectiveness
  • +
  • Annual Review: Comprehensive evaluation of entire system
  • +
  • Special Review: Upon major changes or incident occurrence
  • +
+ +

10.3.2 Improvement Activities

+
    +
  • Improvement plan establishment based on review results
  • +
  • Procedure and system updates
  • +
  • Training program improvements
  • +
  • Monitoring system enhancement
  • +
+
+ + +
+
+

11. FORMS AND TEMPLATES

+
+ +
+

11.1 Legal Requirements Registration Form

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

11.2 Compliance Evaluation Checklist

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

11.3 Regulatory Change Notification

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+

12. DOCUMENT CONTROL

+
+
+ Document Control
+ This is a controlled document. Do not copy or distribute without authorization.
+ The latest version can be found on the company intranet.
+ For inquiries, contact the HSE Management Department. +
+
+
+ + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/index.html b/deploy/tkfb-package/fastapi-bridge/static/docs/index.html new file mode 100644 index 0000000..7cec773 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/index.html @@ -0,0 +1,295 @@ + + + + + + 테크니컬코리아 문서 시스템 + + + +
+
+

테크니컬코리아 문서 시스템

+

회사 규정 및 절차서 열람 시스템

+
+ +
+
+ +
+

HSE 관리시스템

+

ISO 45001:2018 기반 안전보건환경 관련 절차서

+ 바로가기 +
+ + +
+

품질 관리시스템

+

ISO 9001 기반 품질관리 절차 및 매뉴얼

+ 바로가기 +
+ + +
+

인사 규정

+

인사관리 규정 및 지침서

+ 바로가기 +
+ + +
+

기술 문서

+

설계 표준, 용접절차, BOM 시스템 가이드라인

+ 바로가기 +
+ + +
+

경영 방침

+

회사 방침, 윤리강령 및 정책 문서

+ 바로가기 +
+ + +
+

문서 검색

+ +
+
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

http://192.168.0.3:10080/docs

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/iso45001_bilingual_manual.html b/deploy/tkfb-package/fastapi-bridge/static/docs/iso45001_bilingual_manual.html new file mode 100644 index 0000000..d187ab0 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/iso45001_bilingual_manual.html @@ -0,0 +1,1469 @@ + + + + + + ISO 45001:2018 HSE 관리시스템 매뉴얼 + + + +
+ +
+ + +
+ + +
+ +
+

ISO 45001:2018

+

보건, 안전 및 환경 관리시스템 매뉴얼

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목HSE 관리시스템 매뉴얼
문서 번호TK-HSE-001
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+

목차 및 개정 이력

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
번호제목개정 번호개정 일자
1목차 및 개정 이력
21. 적용 범위
32. 인용 표준
43. 용어와 정의
54. 조직의 상황
65. 리더십과 근로자 참여
76. 기획
87. 지원
98. 운영
109. 성과 평가
1110. 개선
+ +

문서 개정 이력

+ + + + + + + + + + + + + + + + + + + + + + + + + +
개정일자수정 문서개정 내용 및 사유
02025.01.03ISO 45001:2018 HSE 관리시스템 구현 - 초기 생성
1
2
+
+ + +
+
+

1. 적용 범위

+
+ +

본 보건, 안전 및 환경 관리시스템 매뉴얼은 테크니컬코리아(이하 "회사"라 함)의 HSE 관리시스템 문서 중 최상위 문서로서, 국제표준 ISO 45001:2018의 요구사항에 따라 작성, 운영 및 유지됩니다.

+ +

본 HSE 관리시스템 매뉴얼은 테크니컬코리아가 수행하는 사업 범위 내에서 조직 관리부터 기획, 영업, 계약, 자재 조달 및 제조, 공정 실행, 관련 제품 및 서비스 활동에 이르기까지 전체 사업 범위에 걸쳐 보건, 안전 및 환경 활동을 수행하는 임직원에게 적용되며, 모든 이해관계자로부터 지속적으로 신뢰를 확보하고 향상시키기 위해 작성, 운영 및 유지됩니다.

+
+ + +
+
+

2. 인용 표준

+
+ +

본 HSE 관리시스템 매뉴얼은 국제표준 "ISO 45001:2018"의 요구사항을 적용하여 작성되었습니다. 본 HSE 관리시스템 매뉴얼 및 관련 문서는 국제표준의 개정이나 업무 개선의 필요에 따라 수정되어야 합니다.

+
+ + +
+
+

3. 용어와 정의

+
+ +

본 매뉴얼에서 사용하는 모든 용어는 "ISO 45001:2018"의 정의를 따르며, 정의되지 않은 용어는 관련 법령 및 테크니컬코리아의 규정이나 규칙에서 정한 정의를 따릅니다. 다만, 하위 규정에서 필요한 용어의 정의는 별도로 정할 수 있습니다.

+ +
+
조직의 상황:
+
목표를 달성하기 위한 조직의 접근 방식을 개발하는 데 영향을 줄 수 있는 내부 및 외부 이슈의 조합
+ +
이해관계자:
+
결정이나 활동에 영향을 주거나, 영향을 받거나, 영향을 받는다고 인식하는 개인이나 조직
+ +
의사소통:
+
조직 구성원 간에 생각이나 감정을 교환하는 포괄적인 행위
+ +
위험:
+
불확실성의 영향
+ +
위험과 기회:
+
잠재적 부정적 영향(위협)과 잠재적 유익한 영향(기회)
+ +
문서화된 정보:
+
조직이 관리하고 유지해야 하는 정보와 이를 포함하는 매체
+ +
HSE 관리시스템:
+
HSE 정책을 달성하기 위해 사용되는 관리시스템 또는 관리시스템의 일부
+ +
준수 의무:
+
조직이 준수해야 하거나 준수하기로 선택한 법적 요구사항 및 기타 요구사항
+ +
근로자:
+
조직의 통제 하에서 일이나 일과 관련된 활동을 수행하는 사람
+ +
참여:
+
의사결정 과정에 관여하는 것
+ +
협의:
+
결정을 내리기 전에 견해를 구하는 것
+ +
작업장:
+
근로 목적으로 사람이 있어야 하거나 가야 하는 조직의 통제 하에 있는 장소
+ +
계약업체:
+
합의된 규격, 조건에 따라 조직에 서비스를 제공하는 외부 조직
+ +
부상과 건강악화:
+
사람의 신체적, 정신적 또는 인지적 상태에 대한 부정적 영향
+ +
유해요인:
+
부상과 건강악화를 일으킬 잠재성을 가진 근원
+ +
사건:
+
일로부터 발생하거나 일의 과정에서 발생하여 부상과 건강악화를 일으킬 수 있거나 일으키는 사건
+
+
+ + + + + +
+
+

4. 조직의 상황

+
+ +
+

4.1 조직과 조직의 상황 이해

+

조직은 조직의 목적과 관련이 있고 HSE 관리시스템의 의도된 결과를 달성하는 능력에 영향을 주는 외부 및 내부 이슈를 결정해야 합니다.

+ +

외부 이슈에는 다음이 포함됩니다:

+
    +
  • 문화적, 사회적, 정치적, 법적, 재정적, 기술적, 경제적 및 자연 환경
  • +
  • 새로운 경쟁업체, 계약업체, 공급업체, 파트너 및 제공업체
  • +
  • 제품 및 OH&S 영향에 대한 새로운 지식
  • +
  • 산업 또는 부문과 관련된 주요 동향 및 추진요인
  • +
  • 외부 이해관계자의 관계, 인식 및 가치
  • +
+ +

내부 이슈에는 다음이 포함됩니다:

+
    +
  • 거버넌스, 조직 구조, 역할 및 책임
  • +
  • 정책, 목표 및 이를 달성하기 위한 전략
  • +
  • 자원, 지식 및 역량 측면에서의 능력
  • +
  • 정보 시스템, 정보 흐름 및 의사결정 과정
  • +
  • 근로자와의 관계, 그들의 인식 및 가치
  • +
  • 조직 문화
  • +
+
+ +
+

4.2 근로자 및 기타 이해관계자의 필요와 기대 이해

+

조직은 다음을 결정해야 합니다:

+
    +
  • HSE 관리시스템과 관련된 근로자 및 기타 이해관계자
  • +
  • 이러한 근로자 및 기타 이해관계자의 필요와 기대
  • +
  • 이러한 필요와 기대 중 법적 요구사항 및 기타 요구사항인 것
  • +
+
+ +
+

4.3 HSE 관리시스템의 적용 범위 결정

+

조직은 적용 범위를 정하기 위해 HSE 관리시스템의 경계와 적용 가능성을 결정해야 합니다. 적용 범위는 조직의 HSE 성과에 영향을 줄 수 있는 조직의 통제 또는 영향 하에 있는 활동, 제품 및 서비스를 포함해야 합니다.

+
+ +
+

4.4 HSE 관리시스템

+

조직은 이 국제표준의 요구사항에 따라 필요한 프로세스와 그들의 상호작용을 포함하여 HSE 관리시스템을 수립, 실행, 유지 및 지속적으로 개선해야 합니다.

+
+
+ + +
+
+

5. 리더십과 근로자 참여

+
+ +
+

5.1 리더십과 의지

+

최고경영자는 다음을 통해 HSE 관리시스템에 대한 리더십과 의지를 실증해야 합니다:

+
    +
  • 업무 관련 부상과 건강악화 예방에 대한 전반적인 책임지기
  • +
  • HSE 정책과 목표가 수립되고 전략적 방향과 양립할 수 있도록 보장
  • +
  • HSE 관리시스템 요구사항의 사업 프로세스 통합 보장
  • +
  • 필요한 자원을 이용할 수 있도록 보장
  • +
  • 효과적인 HSE 관리의 중요성 의사소통
  • +
  • HSE 관리시스템이 의도된 결과를 달성하도록 보장
  • +
  • 지속적 개선 촉진
  • +
  • 사건, 유해요인, 위험 및 기회를 보고할 때 근로자를 보복으로부터 보호
  • +
+
+ +
+

5.2 HSE 정책

+

최고경영자는 다음과 같은 HSE 정책을 수립, 실행 및 유지해야 합니다:

+
    +
  • 안전하고 건강한 작업 조건을 제공하겠다는 의지 포함
  • +
  • HSE 목표 설정을 위한 프레임워크 제공
  • +
  • 법적 요구사항 및 기타 요구사항을 충족하겠다는 의지 포함
  • +
  • 유해요인을 제거하고 HSE 위험을 감소시키겠다는 의지 포함
  • +
  • 지속적 개선에 대한 의지 포함
  • +
  • 근로자의 협의와 참여에 대한 의지 포함
  • +
+
+ +
+

5.3 조직의 역할, 책임 및 권한

+

최고경영자는 관련 역할에 대한 책임과 권한이 조직 내에서 할당, 의사소통 및 이해되도록 보장해야 합니다. 모든 수준의 근로자는 자신이 통제하는 OH&S 관리시스템의 측면에 대해 책임을 져야 합니다.

+
+ +
+

5.4 근로자의 협의와 참여

+

조직은 OH&S 관리시스템의 개발, 기획, 실행, 성과 평가 및 개선을 위한 조치에서 근로자의 협의와 참여를 위한 프로세스를 수립해야 합니다.

+
+
+ + +
+
+

6. 기획

+
+ +
+

6.1 위험과 기회를 다루는 조치

+

6.1.1 일반

+

HSE 관리시스템을 기획할 때, 조직은 다음을 위해 다루어야 할 위험과 기회를 결정해야 합니다:

+
    +
  • HSE 관리시스템이 의도된 결과를 달성할 수 있다는 확신 제공
  • +
  • 바람직하지 않은 영향 예방 또는 감소
  • +
  • 지속적 개선 달성
  • +
+ +

6.1.2 유해요인 식별 및 위험과 기회의 평가

+

조직은 다음을 고려하여 지속적이고 사전 예방적인 유해요인 식별을 위한 프로세스를 수립해야 합니다:

+
    +
  • 업무가 조직되는 방법, 사회적 요인, 리더십 및 조직 문화
  • +
  • 일상적 및 비일상적 활동과 상황
  • +
  • 기반시설, 장비, 재료, 물질 및 물리적 조건
  • +
  • 과거의 관련 사건 및 잠재적 비상 상황
  • +
  • 작업장에 접근하는 사람들
  • +
+ +

6.1.3 법적 요구사항 및 기타 요구사항의 결정

+

조직은 유해요인, HSE 위험 및 HSE 관리시스템에 적용되는 최신 법적 요구사항 및 기타 요구사항을 결정하고 접근할 수 있는 프로세스를 수립해야 합니다.

+ +

6.1.4 조치 기획

+

조직은 위험과 기회, 법적 요구사항 및 비상 상황을 다루기 위한 조치를 기획해야 합니다.

+
+ +
+

6.2 HSE 목표 및 이를 달성하기 위한 기획

+

조직은 관련 기능과 수준에서 HSE 목표를 수립해야 합니다. HSE 목표는 다음과 같아야 합니다:

+
    +
  • HSE 정책과 일치
  • +
  • 측정 가능하거나 성과 평가가 가능
  • +
  • 적용 가능한 요구사항 고려
  • +
  • 모니터링되고 의사소통됨
  • +
  • 적절하게 갱신됨
  • +
+
+
+ + +
+
+

7. 지원

+
+ +
+

7.1 자원

+

조직은 HSE 관리시스템의 수립, 실행, 유지 및 지속적 개선에 필요한 자원을 결정하고 제공해야 합니다.

+
+ +
+

7.2 역량

+

조직은 다음을 해야 합니다:

+
    +
  • HSE 성과에 영향을 주는 근로자의 필요한 역량 결정
  • +
  • 적절한 교육, 훈련 또는 경험에 기반하여 근로자가 역량을 갖추도록 보장
  • +
  • 필요한 역량을 획득하고 유지하기 위한 조치 취하기
  • +
  • 역량의 증거로서 문서화된 정보 보존
  • +
+
+ +
+

7.3 인식

+

근로자는 다음에 대해 인식하도록 해야 합니다:

+
    +
  • HSE 정책과 HSE 목표
  • +
  • HSE 관리시스템의 효과성에 대한 자신의 기여
  • +
  • HSE 관리시스템 요구사항에 부합하지 않는 것의 의미
  • +
  • 자신과 관련된 사건 및 조사 결과
  • +
  • 자신과 관련된 유해요인, HSE 위험 및 결정된 조치
  • +
+
+ +
+

7.4 의사소통

+

조직은 HSE 관리시스템과 관련된 내부 및 외부 의사소통을 위한 프로세스를 수립하여 무엇을, 언제, 누구와, 어떻게 의사소통할지를 결정해야 합니다.

+
+ +
+

7.5 문서화된 정보

+

조직의 HSE 관리시스템은 이 표준에서 요구하는 문서화된 정보와 HSE 관리시스템의 효과성에 필요하다고 조직이 결정한 문서화된 정보를 포함해야 합니다.

+
+
+ + +
+
+

8. 운영

+
+ +
+

8.1 운영 기획 및 관리

+

조직은 프로세스에 대한 기준을 수립하고 기준에 따라 관리를 실행함으로써 HSE 관리시스템 요구사항을 충족하는 데 필요한 프로세스를 기획, 실행, 관리 및 유지해야 합니다.

+ +

8.1.2 유해요인 제거 및 HSE 위험 감소

+

조직은 다음 관리 체계를 사용하여 유해요인 제거 및 HSE 위험 감소를 위한 프로세스를 수립해야 합니다:

+
    +
  • 유해요인 제거
  • +
  • 덜 위험한 프로세스, 운영, 재료 또는 장비로 대체
  • +
  • 공학적 관리 및 업무 재조직 사용
  • +
  • 훈련을 포함한 관리적 관리 사용
  • +
  • 적절한 개인보호장비 사용
  • +
+ +

8.1.3 변경 관리

+

조직은 OH&S 성과에 영향을 주는 계획된 임시 및 영구 변경의 실행 및 관리를 위한 프로세스를 수립해야 합니다.

+ +

8.1.4 조달

+

조직은 제품 및 서비스의 조달을 관리하고 계약업체와 협력하여 유해요인을 식별하고 HSE 위험을 평가 및 관리하는 프로세스를 수립해야 합니다.

+
+ +
+

8.2 비상 대비 및 대응

+

조직은 다음을 통해 잠재적 비상 상황을 대비하고 대응하는 프로세스를 수립해야 합니다:

+
    +
  • 비상 상황에 대한 계획된 대응 수립
  • +
  • 계획된 대응을 위한 훈련 제공
  • +
  • 계획된 대응 능력을 주기적으로 시험 및 연습
  • +
  • 성과를 평가하고 필요시 계획된 대응 수정
  • +
  • 모든 관련 당사자에게 의무와 책임 의사소통
  • +
+
+
+ + +
+
+

9. 성과 평가

+
+ +
+

9.1 모니터링, 측정, 분석 및 성과 평가

+

조직은 모니터링과 측정이 필요한 것, 모니터링 방법, 평가 기준, 모니터링과 측정을 수행해야 하는 시기를 결정하기 위해 모니터링, 측정, 분석 및 성과 평가를 위한 프로세스를 수립해야 합니다.

+ +

9.1.2 준수 평가

+

조직은 법적 요구사항 및 기타 요구사항에 대한 준수를 평가하는 프로세스를 수립해야 합니다.

+
+ +
+

9.2 내부 심사

+

조직은 HSE 관리시스템이 조직의 요구사항과 이 국제표준에 적합한지, 효과적으로 실행되고 유지되는지에 대한 정보를 제공하기 위해 계획된 주기로 내부 심사를 실시해야 합니다.

+
+ +
+

9.3 경영 검토

+

최고경영자는 조직의 HSE 관리시스템이 지속적으로 적절하고, 충분하며, 효과적임을 보장하기 위해 계획된 주기로 검토해야 합니다. 경영 검토는 다음을 고려해야 합니다:

+
    +
  • 이전 경영 검토의 조치 상태
  • +
  • 외부 및 내부 이슈의 변화
  • +
  • HSE 성과에 대한 정보
  • +
  • 자원의 적절성
  • +
  • 지속적 개선 기회
  • +
+
+
+ + +
+
+

10. 개선

+
+ +
+

10.1 일반

+

조직은 HSE 관리시스템의 의도된 결과를 달성하기 위해 개선 기회를 결정하고 필요한 조치를 실행해야 합니다.

+
+ +
+

10.2 사건, 부적합 및 시정조치

+

사건이나 부적합이 발생할 때, 조직은 다음을 해야 합니다:

+
    +
  • 사건이나 부적합에 시기적절하게 대응
  • +
  • 근본 원인을 제거하기 위한 시정조치의 필요성 평가
  • +
  • 시정조치를 포함하여 필요한 모든 조치 실행
  • +
  • 취한 조치의 효과성 검토
  • +
  • 필요시 HSE 관리시스템 변경
  • +
+
+ +
+

10.3 지속적 개선

+

조직은 다음을 위해 HSE 관리시스템의 적절성, 충분성 및 효과성을 지속적으로 개선해야 합니다:

+
    +
  • HSE 성과 향상
  • +
  • HSE 관리시스템을 지원하는 문화 촉진
  • +
  • 지속적 개선을 위한 조치 실행에서 근로자 참여 촉진
  • +
  • 지속적 개선의 관련 결과를 근로자에게 의사소통
  • +
+
+
+ + +
+
+

관련 문서

+
+ +
    +
  1. TK-HSE-P-410 - 조직 상황 이해 및 HSE 관리시스템 운영 절차
  2. +
  3. TK-HSE-P-510 - 리더십 및 정책 수립 절차
  4. +
  5. TK-HSE-P-520 - 조직 편성 및 직무 배정 절차
  6. +
  7. TK-HSE-P-610 - 기획 및 위험 관리 절차
  8. +
  9. TK-HSE-P-620 - 위험 평가 절차
  10. +
  11. TK-HSE-P-630 - HSE 법적 요구사항 관리 절차
  12. +
  13. TK-HSE-P-640 - HSE 목표 관리 절차
  14. +
  15. TK-HSE-P-710 - 자원 관리 절차
  16. +
  17. TK-HSE-P-720 - 교육 및 훈련 관리 절차
  18. +
  19. TK-HSE-P-730 - 인식 및 의사소통 절차
  20. +
  21. TK-HSE-P-740 - 문서화된 정보 관리 절차
  22. +
  23. TK-HSE-P-810 - 운영 기획 및 관리 절차
  24. +
  25. TK-HSE-P-820 - 비상 대비 및 대응 절차
  26. +
  27. TK-HSE-P-910 - 프로세스 성과 관리 절차
  28. +
  29. TK-HSE-P-920 - HSE 모니터링 및 측정 관리 절차
  30. +
  31. TK-HSE-P-930 - 내부 심사 절차
  32. +
  33. TK-HSE-P-940 - 경영 검토 절차
  34. +
  35. TK-HSE-P-1010 - 사건, 부적합 및 시정조치 절차
  36. +
  37. TK-HSE-P-1020 - 지속적 개선 절차
  38. +
+
+ + +
+
+

문서 관리

+
+ +

이것은 통제 문서입니다

+

승인 없이 복사하지 마십시오

+

최신 버전은 회사 인트라넷에서 확인할 수 있습니다

+

이 문서에 대한 문의사항은 HSE 관리부서로 연락하십시오

+
+ +
+ + +
+ +
+

ISO 45001:2018

+

Health, Safety and Environment Management System Manual

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleHSE Management System Manual
Document NumberTK-HSE-001
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+

TABLE OF CONTENTS AND REVISION HISTORY

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No.TitleRevision No.Revision Date
1Table of Contents and Revision History
21. Scope
32. Normative References
43. Terms and Definitions
54. Context of the Organization
65. Leadership and Worker Participation
76. Planning
87. Support
98. Operation
109. Performance Evaluation
1110. Improvement
+ +

Document Revision History

+ + + + + + + + + + + + + + + + + + + + + + + + + +
RevisionDateModified DocumentContent and Reason for Revision
02025.01.03ISO 45001:2018 HSE Management System Implementation - Initial Creation
1
2
+
+ + +
+
+

1. SCOPE

+
+ +

This Health, Safety and Environment Management System Manual is the highest-level document among the HSE management system documents of Technicalkorea (hereinafter referred to as "the Company"). It is prepared, operated, and maintained in accordance with the requirements of the international standard ISO 45001:2018.

+ +

This HSE Management System Manual applies to employees who perform health, safety and environment activities throughout the entire business scope, from organizational management to planning, sales, contracting, procurement and manufacturing of materials, process execution, and related product and service activities within the business scope that Technicalkorea performs. It is prepared, operated, and maintained to continuously secure and improve trust from all stakeholders.

+
+ + +
+
+

2. NORMATIVE REFERENCES

+
+ +

This HSE Management System Manual is prepared by applying the requirements of the international standard "ISO 45001:2018". This HSE Management System Manual and related documents shall be revised when necessary for the revision of international standards or improvement of work.

+
+ + +
+
+

3. TERMS AND DEFINITIONS

+
+ +

All terms used in this manual follow the definitions in "ISO 45001:2018", and undefined terms shall follow the definitions prescribed in related laws and regulations and Technicalkorea's regulations or rules. However, definitions of necessary terms in subordinate regulations may be separately established.

+ +
+
Context of the organization:
+
Combination of internal and external issues that can influence the organization's approach to developing and achieving its objectives
+ +
Interested party:
+
Person or organization that can affect, be affected by, or perceive themselves to be affected by a decision or activity
+ +
Communication:
+
Comprehensive act of exchanging thoughts or feelings among organization members
+ +
Risk:
+
Effect of uncertainty
+ +
Risk and opportunities:
+
Potential adverse effects (threats) and potential beneficial effects (opportunities)
+ +
Documented information:
+
Information required to be controlled and maintained by the organization and the medium containing it
+ +
HSE management system:
+
Management system or part of a management system used to achieve the HSE policy
+ +
Compliance obligations:
+
Legal requirements and other requirements that an organization has to comply with or chooses to comply with
+ +
Worker:
+
Person performing work or work-related activities under the control of the organization
+ +
Participation:
+
Involvement in decision-making processes
+ +
Consultation:
+
Seeking views before making a decision
+ +
Workplace:
+
Place under the control of the organization where a person needs to be or to go for work purposes
+ +
Contractor:
+
External organization providing services to the organization according to agreed specifications, terms and conditions
+ +
Injury and ill health:
+
Adverse effect on the physical, mental or cognitive condition of a person
+ +
Hazard:
+
Source with a potential to cause injury and ill health
+ +
Incident:
+
Occurrence arising from or in the course of work that could or does result in injury and ill health
+
+
+ + +
+
+

4. CONTEXT OF THE ORGANIZATION

+
+ +
+

4.1 Understanding the organization and its context

+

The organization shall determine external and internal issues that are relevant to its purpose and that affect its ability to achieve the intended outcomes of its HSE management system.

+ +

External issues include:

+
    +
  • Cultural, social, political, legal, financial, technological, economic and natural environment
  • +
  • New competitors, contractors, suppliers, partners and providers
  • +
  • New knowledge about products and OH&S impacts
  • +
  • Key trends and drivers related to the industry or sector
  • +
  • Relationships, perceptions and values of external interested parties
  • +
+ +

Internal issues include:

+
    +
  • Governance, organizational structure, roles and accountabilities
  • +
  • Policies, objectives and strategies to achieve them
  • +
  • Capabilities in terms of resources, knowledge and competencies
  • +
  • Information systems, information flows and decision-making processes
  • +
  • Relationships with workers, their perceptions and values
  • +
  • Organizational culture
  • +
+
+ +
+

4.2 Understanding the needs and expectations of workers and other interested parties

+

The organization shall determine:

+
    +
  • Workers and other interested parties relevant to the HSE management system
  • +
  • The needs and expectations of these workers and other interested parties
  • +
  • Which of these needs and expectations are legal requirements and other requirements
  • +
+
+ +
+

4.3 Determining the scope of the HSE management system

+

The organization shall determine the boundaries and applicability of the HSE management system to establish its scope. The scope shall include activities, products and services within the organization's control or influence that can affect the organization's HSE performance.

+
+ +
+

4.4 HSE management system

+

The organization shall establish, implement, maintain and continually improve an HSE management system, including the processes needed and their interactions, in accordance with the requirements of this international standard.

+
+
+ + +
+
+

5. LEADERSHIP AND WORKER PARTICIPATION

+
+ +
+

5.1 Leadership and commitment

+

Top management shall demonstrate leadership and commitment with respect to the HSE management system by:

+
    +
  • Taking overall responsibility for the prevention of work-related injury and ill health
  • +
  • Ensuring that the HSE policy and objectives are established and compatible with strategic direction
  • +
  • Ensuring integration of HSE management system requirements into business processes
  • +
  • Ensuring that necessary resources are available
  • +
  • Communicating the importance of effective HSE management
  • +
  • Ensuring the HSE management system achieves its intended outcomes
  • +
  • Promoting continual improvement
  • +
  • Protecting workers from reprisals when reporting incidents, hazards, risks and opportunities
  • +
+
+ +
+

5.2 HSE policy

+

Top management shall establish, implement and maintain an HSE policy that:

+
    +
  • Includes a commitment to provide safe and healthy working conditions
  • +
  • Provides a framework for setting HSE objectives
  • +
  • Includes a commitment to fulfill legal requirements and other requirements
  • +
  • Includes a commitment to eliminate hazards and reduce HSE risks
  • +
  • Includes a commitment to continual improvement
  • +
  • Includes a commitment to consultation and participation of workers
  • +
+
+ +
+

5.3 Organizational roles, responsibilities and authorities

+

Top management shall ensure that responsibilities and authorities for relevant roles are assigned, communicated and understood within the organization. Workers at all levels shall take responsibility for those aspects of the OH&S management system over which they have control.

+
+ +
+

5.4 Consultation and participation of workers

+

The organization shall establish processes for consultation and participation of workers in the development, planning, implementation, performance evaluation and actions for improvement of the OH&S management system.

+
+
+ + +
+
+

6. PLANNING

+
+ +
+

6.1 Actions to address risks and opportunities

+

6.1.1 General

+

When planning for the HSE management system, the organization shall determine the risks and opportunities that need to be addressed to:

+
    +
  • Give assurance that the HSE management system can achieve its intended outcomes
  • +
  • Prevent, or reduce, undesired effects
  • +
  • Achieve continual improvement
  • +
+ +

6.1.2 Hazard identification and assessment of risks and opportunities

+

The organization shall establish processes for ongoing and proactive hazard identification considering:

+
    +
  • How work is organized, social factors, leadership, and organizational culture
  • +
  • Routine and non-routine activities and situations
  • +
  • Infrastructure, equipment, materials, substances and physical conditions
  • +
  • Past relevant incidents and potential emergency situations
  • +
  • People with access to the workplace
  • +
+ +

6.1.3 Determination of legal requirements and other requirements

+

The organization shall establish processes to determine and have access to up-to-date legal requirements and other requirements applicable to its hazards, HSE risks and HSE management system.

+ +

6.1.4 Planning action

+

The organization shall plan actions to address risks and opportunities, legal requirements, and emergency situations.

+
+ +
+

6.2 HSE objectives and planning to achieve them

+

The organization shall establish HSE objectives at relevant functions and levels. HSE objectives shall be:

+
    +
  • Consistent with the HSE policy
  • +
  • Measurable or capable of performance evaluation
  • +
  • Take into account applicable requirements
  • +
  • Be monitored and communicated
  • +
  • Be updated as appropriate
  • +
+
+
+ + +
+
+

7. SUPPORT

+
+ +
+

7.1 Resources

+

The organization shall determine and provide the resources needed for the establishment, implementation, maintenance and continual improvement of the HSE management system.

+
+ +
+

7.2 Competence

+

The organization shall:

+
    +
  • Determine necessary competence of workers that affects HSE performance
  • +
  • Ensure workers are competent based on appropriate education, training or experience
  • +
  • Take actions to acquire and maintain necessary competence
  • +
  • Retain documented information as evidence of competence
  • +
+
+ +
+

7.3 Awareness

+

Workers shall be made aware of:

+
    +
  • The HSE policy and HSE objectives
  • +
  • Their contribution to the effectiveness of the HSE management system
  • +
  • The implications of not conforming to HSE management system requirements
  • +
  • Incidents and investigation results relevant to them
  • +
  • Hazards, HSE risks and determined actions relevant to them
  • +
+
+ +
+

7.4 Communication

+

The organization shall establish processes for internal and external communications relevant to the HSE management system, determining what, when, with whom, and how to communicate.

+
+ +
+

7.5 Documented information

+

The organization's HSE management system shall include documented information required by this standard and determined by the organization as necessary for the effectiveness of the HSE management system.

+
+
+ + +
+
+

8. OPERATION

+
+ +
+

8.1 Operational planning and control

+

The organization shall plan, implement, control and maintain the processes needed to meet HSE management system requirements by establishing criteria for processes and implementing control in accordance with the criteria.

+ +

8.1.2 Eliminating hazards and reducing HSE risks

+

The organization shall establish processes for elimination of hazards and reduction of HSE risks using the following hierarchy of controls:

+
    +
  • Eliminate the hazard
  • +
  • Substitute with less hazardous processes, operations, materials or equipment
  • +
  • Use engineering controls and reorganization of work
  • +
  • Use administrative controls, including training
  • +
  • Use adequate personal protective equipment
  • +
+ +

8.1.3 Management of change

+

The organization shall establish processes for the implementation and control of planned temporary and permanent changes that impact OH&S performance.

+ +

8.1.4 Procurement

+

The organization shall establish processes to control the procurement of products and services and coordinate with contractors to identify hazards and assess and control HSE risks.

+
+ +
+

8.2 Emergency preparedness and response

+

The organization shall establish processes to prepare for and respond to potential emergency situations by:

+
    +
  • Establishing a planned response to emergency situations
  • +
  • Providing training for the planned response
  • +
  • Periodically testing and exercising the planned response capability
  • +
  • Evaluating performance and revising the planned response when necessary
  • +
  • Communicating duties and responsibilities to all relevant parties
  • +
+
+
+ + +
+
+

9. PERFORMANCE EVALUATION

+
+ +
+

9.1 Monitoring, measurement, analysis and performance evaluation

+

The organization shall establish processes for monitoring, measurement, analysis and performance evaluation to determine what needs to be monitored and measured, methods for monitoring, criteria for evaluation, and when monitoring and measurement shall be performed.

+ +

9.1.2 Evaluation of compliance

+

The organization shall establish processes for evaluating compliance with legal requirements and other requirements.

+
+ +
+

9.2 Internal audit

+

The organization shall conduct internal audits at planned intervals to provide information on whether the HSE management system conforms to the organization's requirements and this international standard, and is effectively implemented and maintained.

+
+ +
+

9.3 Management review

+

Top management shall review the organization's HSE management system at planned intervals to ensure its continuing suitability, adequacy and effectiveness. The management review shall consider:

+
    +
  • Status of actions from previous management reviews
  • +
  • Changes in external and internal issues
  • +
  • Information on HSE performance
  • +
  • Adequacy of resources
  • +
  • Opportunities for continual improvement
  • +
+
+
+ + +
+
+

10. IMPROVEMENT

+
+ +
+

10.1 General

+

The organization shall determine opportunities for improvement and implement necessary actions to achieve the intended outcomes of its HSE management system.

+
+ +
+

10.2 Incident, nonconformity and corrective action

+

When an incident or nonconformity occurs, the organization shall:

+
    +
  • React to the incident or nonconformity in a timely manner
  • +
  • Evaluate the need for corrective action to eliminate root causes
  • +
  • Implement any action needed, including corrective action
  • +
  • Review the effectiveness of any action taken
  • +
  • Make changes to the HSE management system, if necessary
  • +
+
+ +
+

10.3 Continual improvement

+

The organization shall continually improve the suitability, adequacy and effectiveness of the HSE management system to:

+
    +
  • Enhance HSE performance
  • +
  • Promote a culture that supports an HSE management system
  • +
  • Promote worker participation in implementing actions for continual improvement
  • +
  • Communicate relevant results of continual improvement to workers
  • +
+
+
+ + +
+
+

RELATED DOCUMENTS

+
+ +
    +
  1. TK-HSE-P-410 - Understanding Organizational Context and HSE Management System Operation Procedure
  2. +
  3. TK-HSE-P-510 - Leadership and Policy Establishment Procedure
  4. +
  5. TK-HSE-P-520 - Organization and Job Assignment Procedure
  6. +
  7. TK-HSE-P-610 - Planning and Risk Management Procedure
  8. +
  9. TK-HSE-P-620 - Risk Assessment Procedure
  10. +
  11. TK-HSE-P-630 - HSE Legal Requirements Management Procedure
  12. +
  13. TK-HSE-P-640 - HSE Objectives Management Procedure
  14. +
  15. TK-HSE-P-710 - Resource Management Procedure
  16. +
  17. TK-HSE-P-720 - Education and Training Management Procedure
  18. +
  19. TK-HSE-P-730 - Awareness and Communication Procedure
  20. +
  21. TK-HSE-P-740 - Documented Information Management Procedure
  22. +
  23. TK-HSE-P-810 - Operational Planning and Control Procedure
  24. +
  25. TK-HSE-P-820 - Emergency Preparedness and Response Procedure
  26. +
  27. TK-HSE-P-910 - Process Performance Management Procedure
  28. +
  29. TK-HSE-P-920 - HSE Monitoring and Measurement Management Procedure
  30. +
  31. TK-HSE-P-930 - Internal Audit Procedure
  32. +
  33. TK-HSE-P-940 - Management Review Procedure
  34. +
  35. TK-HSE-P-1010 - Incident, Nonconformity and Corrective Action Procedure
  36. +
  37. TK-HSE-P-1020 - Continual Improvement Procedure
  38. +
+
+ + +
+
+

DOCUMENT CONTROL

+
+ +

This is a controlled document

+

Do not copy without authorization

+

Latest version available on company intranet

+

For questions regarding this document, contact the HSE Management Department

+
+ +
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/policy.html b/deploy/tkfb-package/fastapi-bridge/static/docs/policy.html new file mode 100644 index 0000000..84e87cd --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/policy.html @@ -0,0 +1,317 @@ + + + + + + 경영방침 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

MP-001 경영방침서

+

테크니컬코리아 경영이념 및 기본방침

+
+
+ + +
+
+

MP-002 윤리강령

+

임직원 윤리행동 기준 및 가이드라인

+
+
+ + +
+
+

MP-003 정보보안 정책

+

회사 정보자산 보호 및 보안 정책

+
+
+ + +
+
+

MP-004 조직도

+

회사 조직도 및 부서별 역할

+
+
+ + +
+
+

MP-005 권한위임 규정

+

의사결정 권한 및 위임 규정

+
+
+
+ + +
+

경영방침 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

경영방침 문의: policy@technicalkorea.co.kr | 내선: 5678

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/quality.html b/deploy/tkfb-package/fastapi-bridge/static/docs/quality.html new file mode 100644 index 0000000..9ae8382 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/quality.html @@ -0,0 +1,373 @@ + + + + + + 품질 관리시스템 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

QM-001 품질매뉴얼

+

ISO 9001 기반 품질경영시스템 매뉴얼

+
+
+ + +
+
+

QP-001 문서 및 기록관리 절차

+

품질문서 작성, 승인, 배포, 보관 절차

+
+
+ + +
+
+

QP-002 고객만족 관리절차

+

고객 요구사항 파악 및 만족도 관리

+
+
+ + +
+
+

QP-003 설계 및 개발관리

+

설계입력, 검토, 검증, 타당성확인 절차

+
+
+ + +
+
+

QP-004 구매 및 외주관리

+

협력업체 평가, 구매품 검증 절차

+
+
+ + +
+
+

QP-005 생산 및 서비스 제공

+

생산공정 관리 및 제품 식별추적성

+
+
+ + +
+
+

QP-006 검사 및 시험관리

+

원자재, 중간품, 최종제품 검사 절차

+
+
+ + +
+
+

QP-007 부적합 및 시정조치

+

부적합품 관리 및 시정예방조치 절차

+
+
+ + +
+
+

QP-008 내부심사 절차

+

품질경영시스템 내부심사 실시 절차

+
+
+ + +
+
+

QP-009 경영검토 절차

+

품질경영시스템 경영검토 실시 절차

+
+
+ + +
+
+

QP-010 측정장비 관리절차

+

측정장비 교정, 점검, 관리 절차

+
+
+ + +
+
+

QP-011 교육훈련 관리절차

+

품질 관련 교육훈련 계획 및 실시

+
+
+
+ + +
+

품질문서 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

품질 문의: quality@technicalkorea.co.kr | 내선: 2345

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/docs/technical.html b/deploy/tkfb-package/fastapi-bridge/static/docs/technical.html new file mode 100644 index 0000000..7178527 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/docs/technical.html @@ -0,0 +1,333 @@ + + + + + + 기술문서 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

TD-001 배관설계 표준

+

배관 설계 기준 및 표준 사양서

+
+
+ + +
+
+

TD-002 용접절차서 (WPS)

+

배관 용접 절차 및 품질 기준

+
+
+ + +
+
+

TD-003 재료사양서

+

배관재료 규격 및 선정 기준

+
+
+ + +
+
+

TD-004 CAD 도면 표준

+

도면 작성 기준 및 CAD 표준

+
+
+ + +
+
+

TD-005 배관 검사기준서

+

배관 제작 및 설치 검사 기준

+
+
+ + +
+
+

TD-006 압력시험 절차서

+

배관계통 압력시험 절차 및 기준

+
+
+ + +
+
+

TD-007 BOM 시스템 사용자 매뉴얼

+

자재관리 시스템 사용 가이드

+
+
+
+ + +
+

기술문서 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

기술 문의: tech@technicalkorea.co.kr | 내선: 4567

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/img/login-bg.jpeg b/deploy/tkfb-package/fastapi-bridge/static/img/login-bg.jpeg new file mode 100644 index 0000000..1681fd4 Binary files /dev/null and b/deploy/tkfb-package/fastapi-bridge/static/img/login-bg.jpeg differ diff --git a/deploy/tkfb-package/fastapi-bridge/static/img/logo.png b/deploy/tkfb-package/fastapi-bridge/static/img/logo.png new file mode 100644 index 0000000..5bbd962 Binary files /dev/null and b/deploy/tkfb-package/fastapi-bridge/static/img/logo.png differ diff --git a/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea Logo.jpg b/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea Logo.jpg new file mode 100644 index 0000000..8ff1b35 Binary files /dev/null and b/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea Logo.jpg differ diff --git a/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.ai b/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.ai new file mode 100644 index 0000000..6eee406 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.ai @@ -0,0 +1,28071 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: Adobe Illustrator by AutoTrace version 0.31.1 +%%Title: /var/www/autotracer.org/temp_dir_m/e8c501b501b02912ca28ab93d5cd0777/technicalkorea_Logo.ai +%%CreationDate: Tue Jul 1 05:01:59 2025 +%%BoundingBox: 0 0 2094 600 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +/bd { bind def } bind def +/incompound false def +/m { moveto } bd +/l { lineto } bd +/c { curveto } bd +/F { incompound not {fill} if } bd +/f { closepath F } bd +/S { stroke } bd +/*u { /incompound true def } bd +/*U { /incompound false def f} bd +/k { setcmykcolor } bd +/K { k } bd +%%EndProlog +%%BeginSetup +%%EndSetup +0.000 0.000 0.000 0.000 k +*u +0 600 m +0 395 l +2.656 400.517 3 406.612 6.468 412 c +15.646 426.865 33.640 436.640 51 437 c +50 438.783 50 438.594 48 439 c +57.403 441.779 69.218 440 79 440 c +142 440 l +348 440 l +1023 440 l +1013.597 437.221 1001.782 439 992 439 c +929 439 l +724 439 l +53 439 l +59.678 436.198 69.784 438 77 438 c +130 438 l +313 438 l +802 438 l +953 438 l +1000 438 l +1006.746 438 1015.382 436.560 1021.910 438.318 c +1028.865 440.190 1035.484 451.822 1040.170 457 c +1051.647 469.684 1064.752 480.969 1078 491.739 c +1115.698 522.386 1162.655 542.211 1211 546.830 c +1270.668 552.532 1330.755 531 1377 493.540 c +1391.785 481.543 1405.287 468.291 1417.845 454 c +1422.293 448.938 1428.382 437 1435 435.318 c +1440.178 433.942 1446.752 435 1452 435 c +1488 435 l +1603 435 l +1975 435 l +1975 410 l +1598 410 l +1480 410 l +1443 410 l +1436.570 410 1429.295 409 1423 410.529 c +1414.316 412.540 1409.882 421.408 1404.870 428 c +1395.994 439.674 1385.879 450.987 1375 460.830 c +1339.790 492.687 1295.380 518.597 1247 521.911 c +1189.677 525.836 1137.711 505.369 1093 470.338 c +1078.487 458.967 1065.337 445.924 1053.289 432 c +1045.483 422.979 1040.211 412.343 1027 412 c +951.439 410 875.588 412 800 412 c +346 412 l +143 412 l +79 412 l +68.784 412 56.989 413.612 47 411.319 c +25.723 406.435 28 384.934 28 368 c +28 236 l +28 219.459 23.618 191.367 46 188 c +45.350 189.300 45.853 189 44 189 c +48 190 l +47.350 191.300 47.853 191 46 191 c +55.963 193.945 68.631 192 79 192 c +147 192 l +367 192 l +812 192 l +958 192 l +985 192 1013 193.925 1040 191 c +1029 186.711 1017.488 188 1006 188 c +949 188 l +746 188 l +513.345 188 280.567 188.358 48 189 c +48 187 l +708 187 l +925 187 l +997 187 l +1008.831 187 1021.229 188 1033 186.895 c +1043.211 185.875 1048.521 174.214 1054.211 167 c +1066 151.956 1079.889 138.204 1095 126.424 c +1137.864 93 1187.948 76.740 1242 77 c +1293.516 77.249 1341.887 99.730 1380 133.285 c +1392 143.903 1402.337 156.917 1411.576 170 c +1416 176.377 1419.345 185.301 1428 186.775 c +1434.378 187.862 1441.539 187 1448 187 c +1486 187 l +1605 187 l +1973 187 l +1973 228 l +1991.816 213.537 2013.250 202 2033 189 c +2040.776 183.821 2051.203 179.405 2057 172 c +2046.379 167.980 2036.523 159.845 2027 153.691 c +2009 142 1990.829 130.798 1973 119 c +1973 162 l +1607 162 l +1493 162 l +1458 162 l +1452.692 162 1446.176 163 1441 161.682 c +1434.719 160 1430 149.848 1426.338 145 c +1415.872 131.643 1403.990 119.341 1391 108.438 c +1351.307 75 1298.445 52.254 1246 52 c +1186.955 51.716 1132 66.518 1084 101.884 c +1068 113.547 1053.250 127.194 1040.286 142 c +1035.508 147.457 1029.281 159.806 1021.985 161.682 c +1016.820 163 1010.312 162 1005 162 c +970 162 l +859 162 l +502 162 l +118 162 l +94 162 l +63.275 162 22.657 155.452 5.493 188 c +3 192.609 1.452 197.822 1 203 c +-1.292 197.538 0 189.887 0 184 c +0 143 l +0 0 l +2094 0 l +2094 600 l +0 600 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1220.667 547.667 m +1220.222 547.222 1221.278 547.278 1221.333 547.333 c +1221.778 547.778 1220.722 547.722 1220.667 547.667 c +f +*U +0.000 0.000 0.000 0.408 k +*u +1222 548 m +1223.506 547.317 1224.315 547.174 1226 547 c +1224.494 547.683 1223.685 547.826 1222 548 c +f +*U +0.000 0.000 0.000 0.498 k +*u +1226 548 m +1228.890 546.787 1231.874 547 1235 547 c +1232 548.213 1229 547.998 1226 548 c +f +*U +0.000 0.000 0.000 0.259 k +*u +1235 548 m +1236.769 547.221 1238 547 1240 547 c +1238.231 547.779 1236.964 547.912 1235 548 c +f +*U +0.000 0.000 0.000 0.435 k +*u +1208 547 m +1209.249 546.315 1209.548 546.251 1211 546 c +1209.752 546.685 1209.451 546.749 1208 547 c +f +*U +0.000 0.000 0.000 0.706 k +*u +1211 547 m +1212 546 l +1211 547 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1097 505 m +1102.506 505.267 1106.507 504.498 1112 504 c +1111.402 505.195 1111.534 504.978 1110 506 c +1111.798 508.376 1112 511 1113 514 c +1117.498 511.951 1123 512.486 1128 512 c +1127 520 l +1133.353 520.383 1138 520.728 1144 523 c +1143.417 525.914 1144.588 524.930 1142 527 c +1144 527.529 1145.875 527.948 1148 528 c +1148.986 529.479 1149 529.203 1149 531 c +1152 529.921 1154.825 528.604 1158 528 c +1156 532 l +1164.214 535.235 1170 536.679 1179 536 c +1177.777 537.195 1177.580 537.317 1176 538 c +1192 536 l +1190.211 537.422 1189.294 537.697 1187 538 c +1189.974 539.754 1192.648 542 1196 543 c +1202.709 544.728 1209.612 543.318 1216 546 c +1218.673 542.941 1223.233 544.168 1227 544.305 c +1235.305 544.606 1243.588 544.364 1251.884 544.219 c +1256.600 544 1263.284 544.889 1264 539 c +1267 540 l +1265.564 538.550 1264.885 537.778 1264 536 c +1269 536 l +1270.582 538 1271 537.733 1273 536 c +1277 536 l +1278 540 l +1280 540 l +1281 536 l +1285 539 l +1285 537.203 1285 537.479 1286 536 c +1289.458 536.692 1293.276 537.234 1297 535 c +1296 534 l +1302 534 l +1299.979 533 1298 532.504 1296 532 c +1297.684 530.717 1299.572 529.475 1300 532 c +1305 529 l +1304 528 l +1307.472 528.329 1310.633 529 1314 530 c +1309.697 533.253 1304 534.641 1299 536.333 c +1286.644 540.449 1273.894 543.338 1261 545 c +1218.743 551 1176 544 1137 527.421 c +1123.816 521.779 1107.527 514.888 1097 505 c +f +*U +0.000 0.000 0.000 0.714 k +*u +1248.667 546.667 m +1248.223 546.223 1249.277 546.277 1249.333 546.333 c +1249.778 546.778 1248.722 546.722 1248.667 546.667 c +f +*U +0.000 0.000 0.000 0.471 k +*u +1250.667 546.667 m +1250.222 546.222 1251.278 546.278 1251.333 546.333 c +1251.778 546.778 1250.722 546.722 1250.667 546.667 c +f +*U +0.000 0.000 0.000 0.212 k +*u +1252.667 546.667 m +1252.222 546.222 1253.278 546.278 1253.333 546.333 c +1253.778 546.778 1252.722 546.722 1252.667 546.667 c +f +*U +0.000 0.000 0.000 0.333 k +*u +1199 546 m +1200 545 l +1199 546 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1200.667 545.667 m +1200.222 545.222 1201.278 545.278 1201.333 545.333 c +1201.778 545.778 1200.722 545.722 1200.667 545.667 c +f +*U +0.000 0.000 0.000 0.996 k +*u +1187 539 m +1188.648 538 1190.175 537.551 1192 537 c +1186.275 536.347 1181.495 537.749 1176 539 c +1177 537.985 1177.612 537.691 1179 537 c +1170.375 535.591 1164 536.497 1156 532 c +1156.406 529.907 1156.217 529.980 1158 529 c +1154.812 529 1152 530.303 1149 531 c +1148 528 l +1145.646 528 1144.232 527.791 1142 527 c +1144 523 l +1138.183 521.579 1132.916 520.993 1127 520 c +1128 512 l +1122.997 512.954 1117.879 512.549 1113 514 c +1111.862 511.207 1110 507.540 1112 505 c +1108 504.450 1104.859 506.945 1101 506 c +1094 504.285 1088.645 500 1083 495.846 c +1072.743 488.290 1063 479.954 1054 471 c +1048.283 465.376 1038.172 458.932 1040 450 c +1038.271 449 1037.406 448.392 1036 447 c +1036 449 l +1031.474 445.298 1030.846 441.527 1032 436 c +1030 437 l +1030.768 435.686 1030.686 435.768 1032 435 c +1030.723 433 1030.723 433.915 1032 432 c +1029 434 l +1026.227 431.732 1022.444 432.412 1019 432 c +1020 434 l +1008.634 430.453 995.831 432 984 432 c +921 432 l +710 432 l +271 432 l +127 432 l +101.328 432 74.463 429.782 49 433 c +53 434 l +51.542 435 50.752 435.436 49 436 c +48 432 l +43 434 l +44 432 l +39.342 432.898 35.518 432.375 31 431 c +30.695 424 23.491 425.482 20 421 c +24 421 l +22.469 419 20.951 417.532 19 416 c +19 420 l +16.912 418.828 15.321 411.481 13 414 c +11.275 412.723 10.221 412.314 12 411 c +10.316 410.776 9.687 410.782 8 411 c +8.980 409.217 8.908 409.406 11 409 c +8.299 407.261 7 406 6 403 c +7.267 401.457 7.489 400.952 8 399 c +4 400 l +6.466 394.711 7 390.778 8 385 c +6.814 386 6.396 386.339 5 387 c +6 384 l +4.373 385.717 4 385.899 5 388 c +4 393 l +-1.639 383.933 0 373.290 0 363 c +0 305 l +24 305 l +24 391 l +25 389 l +25.751 391 25.656 391.596 24 393 c +24.727 395.753 24.607 398.517 26 401 c +24 404 l +25.915 402.723 25 402.723 27 404 c +28 399 l +29.187 401.180 29.234 402.514 29 405 c +34.487 405.255 32.224 409 34.895 412.489 c +36.307 414.307 38.989 415 41 416 c +40.489 414 40.267 413.543 39 412 c +40 414 l +38.217 413 38.406 413 38 411 c +39.878 411.176 41.199 411.438 43 412 c +42 415 l +44.592 415 45.707 414.737 48 414 c +47 416 l +86.624 411 127.988 414 168 414 c +378 414 l +1024 414 l +1016.841 417 1005.744 415 998 415 c +941 415 l +743 415 l +56 415 l +64.280 417.448 74.393 416 83 416 c +137 416 l +312 416 l +886 416 l +995 416 l +1004.996 416 1015 416 1025 415.995 c +1030.506 415.905 1034.575 414.502 1039.826 417 c +1043.661 418.902 1046 422.759 1048.600 426 c +1052.525 430.910 1056.589 435.507 1060.985 439.999 c +1076.853 456.214 1093.284 471.210 1112 484 c +1126.948 494.423 1143 502.860 1160 509.550 c +1165.691 511.808 1175.917 512.565 1178 519 c +1179 517.466 1178.805 517.598 1180 517 c +1183.857 518.867 1189.271 518.625 1192 522 c +1195 521.472 1197 522 1200 523 c +1197.812 524.885 1195.713 526 1193 527 c +1196.767 526.871 1200.391 524.566 1203 528 c +1205.934 527.360 1208 527.360 1211 528 c +1209.952 526 1209.487 525 1209 523 c +1217 525 l +1214.761 525.811 1213.353 525.529 1211 525 c +1213 527 1214.000 528.429 1217 528 c +1219 527 l +1222.348 527.279 1226.657 528.965 1231 528 c +1232 527.747 1233.863 526.284 1235 526 c +1237.340 525.415 1239.191 526.397 1241 527 c +1242 526 l +1242 528 l +1243 526 l +1244.300 526.650 1244 526 1244 528 c +1244.986 526.521 1245 526.797 1245 525 c +1245.685 526.248 1245.749 526.549 1246 528 c +1248.855 527.294 1251 527.513 1254 528 c +1253 524 l +1255.378 524.181 1257.628 524.233 1260 524 c +1260 528 l +1261 525.538 1261.334 524.568 1264 524 c +1263 521 l +1271.274 520.324 1277.667 518.358 1286 520 c +1284.843 518.183 1284.855 518 1285 516 c +1286.528 517.474 1286.840 517.918 1287 520 c +1289.409 519.728 1291.581 519.799 1294 520 c +1294.307 517.877 1294.382 517.314 1296 516 c +1295 513 l +1298.604 512 1301.263 511.594 1304 509 c +1310.537 511.439 1311.791 507.453 1316 503 c +1318.992 503 1321.189 502.883 1324 504 c +1323 500 l +1325.420 501.382 1326 502.363 1327 505 c +1327.506 503 1327.686 502.268 1329 501 c +1327.744 499.263 1327.345 498 1327 496 c +1349.291 482.355 1368.859 466.798 1387 447.996 c +1396.451 438.263 1406.258 427.833 1413 416 c +1415.741 415.723 1417.586 414.291 1420 413 c +1420 414.797 1419.986 414.522 1419 416 c +1968 416 l +1968 432 l +1586 432 l +1480 432 l +1463.783 432 1443.713 428.891 1429 436 c +1427.990 434.831 1427.516 434.685 1426 434 c +1424 440 l +1418.649 440.829 1416.401 443.682 1416 449 c +1417 445 l +1418.739 448.573 1415.598 458.891 1411 455 c +1409.287 456.647 1408.306 456.631 1408 459 c +1409.478 458 1409.203 458 1411 458 c +1409.465 467.785 1397 476.545 1389.999 482.834 c +1374.955 496.309 1358.416 507.820 1341 517.988 c +1333.655 522.277 1323.626 528.946 1315 529.748 c +1311.380 530 1307.517 528.743 1304 528 c +1303.441 530.579 1302.466 530.972 1300 532 c +1300.000 529.312 1298.323 530.572 1296 531 c +1298 531.881 1299.854 532.496 1302 533 c +1299.948 533.874 1298.253 533.953 1296 534 c +1295.404 537.935 1289 536.731 1286 536 c +1285 539 l +1283 537.999 1282.901 537.923 1282 536 c +1280 540 l +1278 540 l +1277 536 l +1275.313 536.218 1274.684 536.224 1273 536 c +1271.722 538.898 1269.750 539.483 1269 536 c +1266.968 536.323 1266 536.340 1264 536 c +1267 539 l +1265.502 539.479 1265.650 539.400 1264 539 c +1263.720 545 1256.869 544.287 1252 544.487 c +1244 544.813 1235.971 544.989 1228 544.634 c +1223.594 544.438 1219.714 543.187 1216 546 c +1209.178 543.964 1201.981 544.830 1195 543 c +1192 542.248 1189.747 540.246 1187 539 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1258 546 m +1259 545 l +1258 546 l +f +*U +0.000 0.000 0.000 0.557 k +*u +1259 546 m +1260 545 l +1259 546 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1260 546 m +1261 545 l +1260 546 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1192 545 m +1193 544 l +1192 545 l +f +*U +0.000 0.000 0.000 0.424 k +*u +1193 545 m +1194 544 l +1193 545 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1194 545 m +1195 544 l +1194 545 l +f +*U +0.012 0.012 0.000 0.678 k +*u +1265 545 m +1266 544 l +1265 545 l +f +*U +0.008 0.008 0.000 0.435 k +*u +1266 545 m +1267 544 l +1266 545 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1267 545 m +1268 544 l +1267 545 l +f +*U +0.000 0.000 0.000 0.267 k +*u +1187 544 m +1188 543 l +1187 544 l +f +*U +0.000 0.000 0.000 0.553 k +*u +1188 544 m +1189 543 l +1188 544 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1189 544 m +1190 543 l +1189 544 l +f +*U +0.000 0.000 0.000 0.686 k +*u +1271 544 m +1272 543 l +1271 544 l +f +*U +0.000 0.000 0.000 0.314 k +*u +1272 544 m +1273 543 l +1272 544 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1182 543 m +1183 542 l +1182 543 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1183 543 m +1184 542 l +1183 543 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1276 543 m +1277 542 l +1276 543 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1277 543 m +1278 542 l +1277 543 l +f +*U +0.000 0.000 0.000 0.286 k +*u +1178 542 m +1179 541 l +1178 542 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1179 542 m +1180 541 l +1179 542 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1280 542 m +1281 541 l +1280 542 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1281 542 m +1282 541 l +1281 542 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1174 541 m +1175 540 l +1174 541 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1175 541 m +1176 540 l +1175 541 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1284 541 m +1285 540 l +1284 541 l +f +*U +0.000 0.000 0.000 0.424 k +*u +1285 541 m +1286 540 l +1285 541 l +f +*U +0.000 0.000 0.000 0.294 k +*u +1170 540 m +1171 539 l +1170 540 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1171 540 m +1172 539 l +1171 540 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1288 540 m +1289 539 l +1288 540 l +f +*U +0.000 0.000 0.000 0.302 k +*u +1289 540 m +1290 539 l +1289 540 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1166 539 m +1167 538 l +1166 539 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1167 539 m +1168 538 l +1167 539 l +f +*U +0.000 0.000 0.000 0.416 k +*u +1292 539 m +1293 538 l +1292 539 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1163 538 m +1164 537 l +1163 538 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1164 538 m +1165 537 l +1164 538 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1295 538 m +1296 537 l +1295 538 l +f +*U +0.000 0.000 0.000 0.376 k +*u +1160 537 m +1161 536 l +1160 537 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1161 537 m +1162 536 l +1161 537 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1298 537 m +1299 536 l +1298 537 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1299 537 m +1300 536 l +1299 537 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1157 536 m +1158 535 l +1157 536 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1158 536 m +1159 535 l +1158 536 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1301 536 m +1302 535 l +1301 536 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1302 536 m +1303 535 l +1302 536 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1154 535 m +1155 534 l +1154 535 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1304 535 m +1305 534 l +1304 535 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1151 534 m +1152 533 l +1151 534 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1152 534 m +1153 533 l +1152 534 l +f +*U +0.000 0.000 0.000 0.557 k +*u +1307 534 m +1308 533 l +1307 534 l +f +*U +0.000 0.000 0.000 0.576 k +*u +1149 533 m +1150 532 l +1149 533 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1309 533 m +1310 532 l +1309 533 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1310 533 m +1311 532 l +1310 533 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1146 532 m +1147 531 l +1146 532 l +f +*U +0.000 0.000 0.000 0.576 k +*u +1312 532 m +1313 531 l +1312 532 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1144 531 m +1145 530 l +1144 531 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1314 531 m +1315 530 l +1314 531 l +f +*U +0.000 0.000 0.000 0.278 k +*u +1141 530 m +1142 529 l +1141 530 l +f +*U +0.000 0.000 0.000 0.357 k +*u +1317 530 m +1318 529 l +1317 530 l +f +*U +0.000 0.000 0.000 0.392 k +*u +1139 529 m +1140 528 l +1139 529 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1319 529 m +1320 528 l +1319 529 l +f +*U +0.000 0.000 0.000 0.267 k +*u +1136 528 m +1137 527 l +1136 528 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1137 528 m +1138 527 l +1137 528 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1193 528 m +1195.187 525.968 1197 524.906 1200 524 c +1197.184 522.642 1195 521.920 1192 522 c +1189.177 519.689 1182.345 517 1179 519 c +1177.407 514.799 1183.789 517 1186 517.630 c +1194.832 519.818 1203.937 521.406 1213 522 c +1239.991 524 1266.293 521.434 1292 512.319 c +1303.849 508 1315 500.221 1327 497 c +1327.689 498.688 1327.676 499 1329 500 c +1327.825 501.879 1327.870 502.716 1328 505 c +1323 500 l +1324 504 l +1321.301 503.264 1318.766 503.253 1316 503 c +1312.638 508.242 1310.278 512.630 1304 509 c +1301.737 512 1298.686 512.301 1295 513 c +1295.986 514.479 1296 514.203 1296 516 c +1294.733 517.543 1294.511 518 1294 520 c +1287 520 l +1287 517.898 1286.455 517.629 1285 516 c +1284.930 517.952 1284.646 517.940 1286 519 c +1283 520 1280 518.908 1277 518.998 c +1272.265 519 1267.750 520.793 1263 521 c +1263.986 522.479 1264 522.203 1264 524 c +1261.965 525.226 1261.674 525.702 1261 528 c +1260.317 526.494 1260.174 525.685 1260 524 c +1257.353 524.578 1255.636 524.607 1253 524 c +1254 528 l +1250.641 527.802 1246.615 528.853 1246 525 c +1245 526.479 1245 526.203 1245 528 c +1243.804 527.402 1244 527.534 1243 526 c +1243 528 l +1241.700 527.350 1242 527.853 1242 526 c +1233.779 527 1217.519 531.663 1211 525 c +1217 526 l +1209 523 l +1211 528 l +1208.194 527.598 1205.806 527.598 1203 528 c +1199.774 525 1196.868 527.178 1193 528 c +f +*U +0.000 0.000 0.000 0.212 k +*u +1322 528 m +1323 527 l +1322 528 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1134 527 m +1135 526 l +1134 527 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1324 527 m +1325 526 l +1324 527 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1132 526 m +1133 525 l +1132 526 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1326 526 m +1327 525 l +1326 526 l +f +*U +0.000 0.000 0.000 0.341 k +*u +1130 525 m +1131 524 l +1130 525 l +f +*U +0.000 0.000 0.000 0.306 k +*u +1328 525 m +1329 524 l +1328 525 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1128 524 m +1129 523 l +1128 524 l +f +*U +0.000 0.000 0.000 0.427 k +*u +1330 524 m +1331 523 l +1330 524 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1126 523 m +1127 522 l +1126 523 l +f +*U +0.000 0.000 0.000 0.612 k +*u +1216.667 522.667 m +1216.223 522.223 1217.277 522.277 1217.333 522.333 c +1217.778 522.778 1216.722 522.722 1216.667 522.667 c +f +*U +0.000 0.000 0.000 0.478 k +*u +1218 523 m +1219.249 522.315 1219.548 522.251 1221 522 c +1219.752 522.685 1219.451 522.749 1218 523 c +f +*U +0.000 0.000 0.000 0.290 k +*u +1221 523 m +1222.248 522.315 1222.548 522.251 1224 522 c +1222.752 522.685 1222.451 522.749 1221 523 c +f +*U +0.024 0.000 0.020 0.125 k +*u +1224 523 m +1227.698 521.448 1232 522 1236 522 c +1232.303 523.552 1227.983 523 1224 523 c +f +*U +0.000 0.000 0.000 0.314 k +*u +1236 523 m +1237.769 522.221 1239 522 1241 522 c +1239.231 522.779 1237.964 522.912 1236 523 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1241.667 522.667 m +1241.222 522.222 1242.278 522.278 1242.333 522.333 c +1242.778 522.778 1241.722 522.722 1241.667 522.667 c +f +*U +0.000 0.000 0.000 0.867 k +*u +1243.667 522.667 m +1243.223 522.223 1244.277 522.277 1244.333 522.333 c +1244.778 522.778 1243.722 522.722 1243.667 522.667 c +f +*U +0.000 0.000 0.000 0.404 k +*u +1332 523 m +1333 522 l +1332 523 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1124 522 m +1125 521 l +1124 522 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1206 522 m +1207 521 l +1206 522 l +f +*U +0.000 0.000 0.000 0.427 k +*u +1207.667 521.667 m +1207.223 521.223 1208.277 521.277 1208.333 521.333 c +1208.778 521.778 1207.722 521.722 1207.667 521.667 c +f +*U +0.000 0.000 0.000 0.235 k +*u +1209 522 m +1210 521 l +1209 522 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1250 522 m +1251.248 521.315 1251.548 521.251 1253 521 c +1251.752 521.685 1251.451 521.749 1250 522 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1253 522 m +1254 521 l +1253 522 l +f +*U +0.000 0.000 0.000 0.459 k +*u +1334 522 m +1335 521 l +1334 522 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1122 521 m +1123 520 l +1122 521 l +f +*U +0.000 0.000 0.000 0.608 k +*u +1200 521 m +1201 520 l +1200 521 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1201 521 m +1202 520 l +1201 521 l +f +*U +0.000 0.000 0.000 0.310 k +*u +1258 521 m +1259 520 l +1258 521 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1259 521 m +1260 520 l +1259 521 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1260 521 m +1261 520 l +1260 521 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1336 521 m +1337 520 l +1336 521 l +f +*U +0.000 0.000 0.000 0.443 k +*u +1120 520 m +1121 519 l +1120 520 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1194 520 m +1195 519 l +1194 520 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1195 520 m +1196 519 l +1195 520 l +f +*U +0.012 0.012 0.000 0.341 k +*u +1264 520 m +1265 519 l +1264 520 l +f +*U +0.008 0.008 0.000 0.608 k +*u +1265 520 m +1266 519 l +1265 520 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1338 520 m +1339 519 l +1338 520 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1118 519 m +1119 518 l +1118 519 l +f +*U +0.000 0.000 0.008 0.733 k +*u +1189 519 m +1190 518 l +1189 519 l +f +*U +0.000 0.000 0.008 0.396 k +*u +1190 519 m +1191 518 l +1190 519 l +f +*U +0.000 0.000 0.008 0.310 k +*u +1269 519 m +1270 518 l +1269 519 l +f +*U +0.000 0.000 0.008 0.741 k +*u +1270 519 m +1271 518 l +1270 519 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1116 518 m +1117 517 l +1116 518 l +f +*U +0.008 0.008 0.000 0.627 k +*u +1185 518 m +1186 517 l +1185 518 l +f +*U +0.008 0.008 0.000 0.282 k +*u +1186 518 m +1187 517 l +1186 518 l +f +*U +0.008 0.008 0.000 0.224 k +*u +1273 518 m +1274 517 l +1273 518 l +f +*U +0.008 0.008 0.000 0.655 k +*u +1274 518 m +1275 517 l +1274 518 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1341 518 m +1342 517 l +1341 518 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1115 517 m +1116 516 l +1115 517 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1181 517 m +1182 516 l +1181 517 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1182 517 m +1183 516 l +1182 517 l +f +*U +0.012 0.012 0.000 0.184 k +*u +1277 517 m +1278 516 l +1277 517 l +f +*U +0.008 0.008 0.000 0.690 k +*u +1278 517 m +1279 516 l +1278 517 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1343 517 m +1344 516 l +1343 517 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1113 516 m +1114 515 l +1113 516 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1177 516 m +1178 515 l +1177 516 l +f +*U +0.000 0.000 0.000 0.384 k +*u +1178 516 m +1179 515 l +1178 516 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1281 516 m +1282 515 l +1281 516 l +f +*U +0.000 0.000 0.000 0.463 k +*u +1111 515 m +1112 514 l +1111 515 l +f +*U +0.000 0.000 0.000 0.510 k +*u +1174 515 m +1175 514 l +1174 515 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1284 515 m +1285 514 l +1284 515 l +f +*U +0.000 0.000 0.000 0.643 k +*u +1285 515 m +1286 514 l +1285 515 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1346 515 m +1347 514 l +1346 515 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1109 514 m +1110 513 l +1109 514 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1171 514 m +1172 513 l +1171 514 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1288 514 m +1289 513 l +1288 514 l +f +*U +0.000 0.000 0.000 0.412 k +*u +1348 514 m +1349 513 l +1348 514 l +f +*U +0.000 0.000 0.000 0.290 k +*u +1168 513 m +1169 512 l +1168 513 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1290 513 m +1291 512 l +1290 513 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1291 513 m +1292 512 l +1291 513 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1350 513 m +1351 512 l +1350 513 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1106 512 m +1107 511 l +1106 512 l +f +*U +0.000 0.000 0.000 0.502 k +*u +1165 512 m +1166 511 l +1165 512 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1294 512 m +1295 511 l +1294 512 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1351 512 m +1352 511 l +1351 512 l +f +*U +0.000 0.000 0.000 0.259 k +*u +1104 511 m +1105 510 l +1104 511 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1162 511 m +1163 510 l +1162 511 l +f +*U +0.000 0.000 0.000 0.380 k +*u +1296 511 m +1297 510 l +1296 511 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1353 511 m +1354 510 l +1353 511 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1103 510 m +1104 509 l +1103 510 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1159 510 m +1160 509 l +1159 510 l +f +*U +0.000 0.000 0.000 0.600 k +*u +1299 510 m +1300 509 l +1299 510 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1101 509 m +1102 508 l +1101 509 l +f +*U +0.000 0.000 0.000 0.455 k +*u +1157 509 m +1158 508 l +1157 509 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1301 509 m +1302 508 l +1301 509 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1302 509 m +1303 508 l +1302 509 l +f +*U +0.000 0.000 0.000 0.471 k +*u +1356 509 m +1357 508 l +1356 509 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1155 508 m +1156 507 l +1155 508 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1098 507 m +1099 506 l +1098 507 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1152 507 m +1153 506 l +1152 507 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1306 507 m +1307 506 l +1306 507 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1359 507 m +1360 506 l +1359 507 l +f +*U +0.000 0.000 0.000 0.420 k +*u +1150 506 m +1151 505 l +1150 506 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1308 506 m +1309 505 l +1308 506 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1360 506 m +1361 505 l +1360 506 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1095 505 m +1096 504 l +1095 505 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1148 505 m +1149 504 l +1148 505 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1310 505 m +1311 504 l +1310 505 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1362 505 m +1363 504 l +1362 505 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1145 504 m +1146 503 l +1145 504 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1146 504 m +1147 503 l +1146 504 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1313 504 m +1314 503 l +1313 504 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1363 504 m +1364 503 l +1363 504 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1092 503 m +1093 502 l +1092 503 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1143 503 m +1144 502 l +1143 503 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1314 503 m +1315 502 l +1314 503 l +f +*U +0.000 0.000 0.000 0.624 k +*u +1141 502 m +1142 501 l +1141 502 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1317 502 m +1318 501 l +1317 502 l +f +*U +0.000 0.000 0.000 0.310 k +*u +1366 502 m +1367 501 l +1366 502 l +f +*U +0.000 0.000 0.000 0.408 k +*u +1089 501 m +1090 500 l +1089 501 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1139 501 m +1140 500 l +1139 501 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1318 501 m +1319 500 l +1318 501 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1088 500 m +1089 499 l +1088 500 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1137 500 m +1138 499 l +1137 500 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1320 500 m +1321 499 l +1320 500 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1369 500 m +1370 499 l +1369 500 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1086 499 m +1087 498 l +1086 499 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1135 499 m +1136 498 l +1135 499 l +f +*U +0.000 0.000 0.000 0.235 k +*u +1322 499 m +1323 498 l +1322 499 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1370 499 m +1371 498 l +1370 499 l +f +*U +0.000 0.000 0.000 0.467 k +*u +1085 498 m +1086 497 l +1085 498 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1134 498 m +1135 497 l +1134 498 l +f +*U +0.000 0.000 0.000 0.353 k +*u +1324 498 m +1325 497 l +1324 498 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1326 497 m +1327 496 l +1326 497 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1373 497 m +1374 496 l +1373 497 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1082 496 m +1083 495 l +1082 496 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1130 496 m +1131 495 l +1130 496 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1374 496 m +1375 495 l +1374 496 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1081 495 m +1082 494 l +1081 495 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1128 495 m +1129 494 l +1128 495 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1126 494 m +1127 493 l +1126 494 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1331 494 m +1332 493 l +1331 494 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1377 494 m +1378 493 l +1377 494 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1078 493 m +1079 492 l +1078 493 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1125 493 m +1126 492 l +1125 493 l +f +*U +0.000 0.000 0.000 0.314 k +*u +1378 493 m +1379 492 l +1378 493 l +f +1077 492 m +1078 491 l +1077 492 l +f +*U +0.000 0.000 0.000 0.404 k +*u +1123 492 m +1124 491 l +1123 492 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1334 492 m +1335 491 l +1334 492 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1379 492 m +1380 491 l +1379 492 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1076 491 m +1077 490 l +1076 491 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1121 491 m +1122 490 l +1121 491 l +f +*U +0.000 0.000 0.000 0.627 k +*u +1336 491 m +1337 490 l +1336 491 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1380 491 m +1381 490 l +1380 491 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1120 490 m +1121 489 l +1120 490 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1337 490 m +1338 489 l +1337 490 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1118 489 m +1119 488 l +1118 489 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1339 489 m +1340 488 l +1339 489 l +f +*U +0.000 0.000 0.000 0.439 k +*u +1072 488 m +1073 487 l +1072 488 l +f +*U +0.000 0.000 0.000 0.525 k +*u +1384 488 m +1385 487 l +1384 488 l +f +*U +0.000 0.000 0.000 0.537 k +*u +1115 487 m +1116 486 l +1115 487 l +f +*U +0.000 0.000 0.000 0.490 k +*u +1342 487 m +1343 486 l +1342 487 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1385 487 m +1386 486 l +1385 487 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1113 486 m +1114 485 l +1113 486 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1386 486 m +1387 485 l +1386 486 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1112 485 m +1113 484 l +1112 485 l +f +*U +0.000 0.000 0.000 0.439 k +*u +1345 485 m +1346 484 l +1345 485 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1067 484 m +1068 483 l +1067 484 l +f +1346 484 m +1347 483 l +1346 484 l +f +*U +0.000 0.000 0.000 0.506 k +*u +1066 483 m +1067 482 l +1066 483 l +f +1109 483 m +1110 482 l +1109 483 l +f +*U +0.000 0.000 0.000 0.816 k +*u +1348 483 m +1349 482 l +1348 483 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1065 482 m +1066 481 l +1065 482 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1349 482 m +1350 481 l +1349 482 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1391 482 m +1392 481 l +1391 482 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1064 481 m +1065 480 l +1064 481 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1106 481 m +1107 480 l +1106 481 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1392 481 m +1393 480 l +1392 481 l +f +*U +0.000 0.000 0.000 0.816 k +*u +1063 480 m +1064 479 l +1063 480 l +f +*U +0.000 0.333 0.275 0.169 k +*u +1209 480 m +1210.769 479.221 1212 479 1214 479 c +1212.231 479.779 1210.964 479.912 1209 480 c +f +*U +0.000 0.310 0.216 0.306 k +*u +1214.667 479.667 m +1214.222 479.222 1215.278 479.278 1215.333 479.333 c +1215.778 479.778 1214.722 479.722 1214.667 479.667 c +f +*U +0.000 0.682 0.471 0.220 k +*u +1216.667 479.667 m +1216.222 479.222 1217.278 479.278 1217.333 479.333 c +1217.778 479.778 1216.722 479.722 1216.667 479.667 c +f +*U +0.000 0.584 0.416 0.416 k +*u +1218 480 m +1220.890 478.787 1223.874 479 1227 479 c +1224 480.213 1221 479.998 1218 480 c +f +*U +0.000 0.482 0.482 0.518 k +*u +1227 480 m +1228.769 479.221 1230 479 1232 479 c +1230.231 479.779 1228.964 479.912 1227 480 c +f +*U +0.000 0.549 0.522 0.380 k +*u +1232.667 479.667 m +1232.222 479.222 1233.278 479.278 1233.333 479.333 c +1233.778 479.778 1232.722 479.722 1232.667 479.667 c +f +*U +0.000 0.384 0.416 0.165 k +*u +1234 480 m +1235.249 479.315 1235.548 479.251 1237 479 c +1235.752 479.685 1235.452 479.749 1234 480 c +f +*U +0.000 0.145 0.255 0.161 k +*u +1237.667 479.667 m +1237.222 479.222 1238.278 479.278 1238.333 479.333 c +1238.778 479.777 1237.722 479.722 1237.667 479.667 c +f +*U +0.000 0.000 0.000 0.494 k +*u +1393 480 m +1394 479 l +1393 480 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1103 479 m +1104 478 l +1103 479 l +f +*U +0.000 0.239 0.208 0.008 k +*u +1201 479 m +1202 478 l +1201 479 l +f +*U +0.000 0.302 0.251 0.149 k +*u +1202 479 m +1203 478 l +1202 479 l +f +*U +0.000 0.392 0.310 0.290 k +*u +1203 479 m +1204 478 l +1203 479 l +f +*U +0.000 0.514 0.416 0.486 k +*u +1204 479 m +1205.506 478.317 1206.315 478.174 1208 478 c +1206.494 478.683 1205.685 478.826 1204 479 c +f +*U +0.000 0.851 0.698 0.149 k +*u +1208 477 m +1212 477.749 1215.899 477.997 1220 478 c +1216.479 479.478 1210.661 480 1208 477 c +f +*U +0.000 0.863 0.616 0.129 k +*u +1186 475 m +1187 472 l +1211.465 475.213 1236.492 471.285 1261 473 c +1258 477.519 1245.341 477.930 1240 478 c +1227.931 478.172 1216 478.866 1204 477.802 c +1197.857 477.262 1192.257 475 1186 475 c +f +*U +0.000 0.694 0.424 0.306 k +*u +1233 479 m +1235.332 478 1237.457 478 1240 478 c +1237.669 478.984 1235.543 478.981 1233 479 c +f +*U +0.000 0.451 0.435 0.549 k +*u +1240 479 m +1241.769 478.221 1243 478 1245 478 c +1243.231 478.779 1241.964 478.912 1240 479 c +f +*U +0.000 0.475 0.373 0.259 k +*u +1245 479 m +1246 478 l +1245 479 l +f +*U +0.000 0.435 0.325 0.000 k +*u +1246.667 478.667 m +1246.222 478.222 1247.278 478.278 1247.333 478.333 c +1247.778 478.778 1246.722 478.722 1246.667 478.667 c +f +*U +0.000 0.000 0.000 0.392 k +*u +1353 479 m +1354 478 l +1353 479 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1394 479 m +1395 478 l +1394 479 l +f +*U +0.000 0.000 0.000 0.494 k +*u +1102 478 m +1103 477 l +1102 478 l +f +*U +0.000 0.259 0.118 0.129 k +*u +1195 478 m +1196 477 l +1195 478 l +f +*U +0.000 0.388 0.204 0.286 k +*u +1196 478 m +1197 477 l +1196 478 l +f +*U +0.000 0.624 0.494 0.376 k +*u +1197 478 m +1198.769 477.221 1200 477 1202 477 c +1200.231 477.779 1198.964 477.912 1197 478 c +f +*U +0.000 0.518 0.349 0.482 k +*u +1248 478 m +1249.506 477.317 1250.315 477.174 1252 477 c +1250.494 477.683 1249.685 477.826 1248 478 c +f +*U +0.000 0.298 0.224 0.204 k +*u +1252.667 477.667 m +1252.222 477.222 1253.278 477.278 1253.333 477.333 c +1253.778 477.778 1252.722 477.722 1252.667 477.667 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1395 478 m +1396 477 l +1395 478 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1101 477 m +1102 476 l +1101 477 l +f +*U +0.000 0.341 0.263 0.141 k +*u +1190 477 m +1191 476 l +1190 477 l +f +*U +0.000 0.451 0.263 0.290 k +*u +1191 477 m +1192 476 l +1191 477 l +f +*U +0.000 0.741 0.659 0.259 k +*u +1192 477 m +1194 476 1195.747 476 1198 476 c +1195.948 476.874 1194.253 476.953 1192 477 c +f +*U +0.000 0.910 0.918 0.063 k +*u +1248 477 m +1249.769 476.221 1251 476 1253 476 c +1251.231 476.779 1249.964 476.912 1248 477 c +f +*U +0.000 0.718 0.667 0.282 k +*u +1253 477 m +1254.248 476.315 1254.548 476.251 1256 476 c +1254.752 476.685 1254.451 476.749 1253 477 c +f +*U +0.000 0.416 0.200 0.584 k +*u +1256 477 m +1257 476 l +1256 477 l +f +*U +0.000 0.373 0.267 0.337 k +*u +1257 477 m +1258 476 l +1257 477 l +f +*U +0.000 0.149 0.043 0.129 k +*u +1258.667 476.667 m +1258.222 476.222 1259.278 476.278 1259.333 476.333 c +1259.778 476.777 1258.722 476.722 1258.667 476.667 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1356 477 m +1357 476 l +1356 477 l +f +*U +0.000 0.043 0.204 0.290 k +*u +1184.667 475.667 m +1184.222 475.222 1185.278 475.278 1185.333 475.333 c +1185.778 475.778 1184.722 475.722 1184.667 475.667 c +f +*U +0.000 0.341 0.153 0.357 k +*u +1186 476 m +1187 475 l +1186 476 l +f +*U +0.000 0.675 0.412 0.325 k +*u +1187 476 m +1189.332 475 1191.457 475 1194 475 c +1191.668 475.984 1189.544 475.981 1187 476 c +f +*U +0.000 0.514 0.322 0.486 k +*u +1260 476 m +1261.249 475.315 1261.548 475.251 1263 475 c +1261.752 475.685 1261.451 475.749 1260 476 c +f +*U +0.000 0.412 0.137 0.078 k +*u +1263 476 m +1264 475 l +1263 476 l +f +*U +0.000 0.000 0.000 0.518 k +*u +1357 476 m +1358 475 l +1357 476 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1397 476 m +1398 475 l +1397 476 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1057 475 m +1058 474 l +1057 475 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1098 475 m +1099 474 l +1098 475 l +f +*U +0.000 0.275 0.231 0.059 k +*u +1181 475 m +1182 474 l +1181 475 l +f +*U +0.000 0.435 0.314 0.322 k +*u +1182 475 m +1183 474 l +1182 475 l +f +*U +0.000 0.635 0.655 0.345 k +*u +1183 475 m +1184.249 474.315 1184.548 474.251 1186 474 c +1184.752 474.685 1184.452 474.749 1183 475 c +f +*U +0.000 0.796 0.592 0.204 k +*u +1261 475 m +1262 473 l +1263.635 473.545 1263.455 473.365 1264 475 c +1261 475 l +f +*U +0.000 0.522 0.373 0.443 k +*u +1264.667 474.667 m +1264.222 474.222 1265.278 474.278 1265.333 474.333 c +1265.778 474.778 1264.722 474.722 1264.667 474.667 c +f +*U +0.000 0.435 0.278 0.227 k +*u +1266 475 m +1267 474 l +1266 475 l +f +*U +0.000 0.314 0.200 0.039 k +*u +1267 475 m +1268 474 l +1267 475 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1398 475 m +1399 474 l +1398 475 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1056 474 m +1057 473 l +1056 474 l +f +*U +0.000 0.000 0.000 0.231 k +*u +1097 474 m +1098 473 l +1097 474 l +f +*U +0.000 0.216 0.192 0.043 k +*u +1177 474 m +1178 473 l +1177 474 l +f +*U +0.000 0.333 0.239 0.337 k +*u +1178 474 m +1179 473 l +1178 474 l +f +*U +0.000 0.573 0.518 0.427 k +*u +1179.667 473.667 m +1179.222 473.222 1180.278 473.278 1180.333 473.333 c +1180.778 473.778 1179.722 473.722 1179.667 473.667 c +f +*U +0.000 0.859 0.694 0.141 k +*u +1181 474 m +1182.750 472.745 1183.857 472.386 1186 472 c +1184.460 473.803 1183.403 473.832 1181 474 c +f +*U +0.000 0.843 0.910 0.090 k +*u +1186.333 473.333 m +1186.278 473.278 1186.222 472.222 1186.667 472.667 c +1186.723 472.723 1186.777 473.778 1186.333 473.333 c +f +*U +0.000 0.910 0.788 0.090 k +*u +1258 473 m +1262.216 471.231 1267.459 472 1272 472 c +1267.693 474 1262.585 474.272 1258 473 c +f +*U +0.000 0.518 0.471 0.455 k +*u +1267 474 m +1268.248 473.315 1268.548 473.251 1270 473 c +1268.752 473.685 1268.452 473.749 1267 474 c +f +*U +0.000 0.263 0.263 0.341 k +*u +1270 474 m +1271 473 l +1270 474 l +f +*U +0.000 0.239 0.196 0.176 k +*u +1271 474 m +1272 473 l +1271 474 l +f +*U +0.000 0.000 0.000 0.745 k +*u +1399 474 m +1400 473 l +1399 474 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1055 473 m +1056 472 l +1055 473 l +f +*U +0.000 0.027 0.020 0.322 k +*u +1173 471 m +1176 471 l +1175 473 l +1173.365 472.455 1173.545 472.635 1173 471 c +f +*U +0.000 0.502 0.502 0.498 k +*u +1175 473 m +1176.248 472.315 1176.548 472.251 1178 472 c +1176.752 472.685 1176.451 472.749 1175 473 c +f +*U +0.000 0.973 0.914 0.027 k +*u +1178 473 m +1179.769 472.221 1181 472 1183 472 c +1181.231 472.779 1179.964 472.912 1178 473 c +f +*U +0.000 0.918 0.918 0.082 k +*u +1188.667 472.667 m +1188.222 472.222 1189.278 472.278 1189.333 472.333 c +1189.778 472.778 1188.722 472.722 1188.667 472.667 c +f +*U +0.000 1.000 1.000 0.000 k +*u +1191 473 m +1192.769 472.221 1194 472 1196 472 c +1194.231 472.779 1192.964 472.912 1191 473 c +f +*U +0.000 0.776 0.847 0.153 k +*u +1196 473 m +1198 472 1199.747 472 1202 472 c +1199.948 472.874 1198.253 472.953 1196 473 c +f +*U +0.000 1.000 1.000 0.000 k +*u +1202 473 m +1206.720 471 1212.920 472 1218 472 c +1251 472 l +1246.280 473.981 1240 473 1235 473 c +1202 473 l +f +*U +0.000 0.820 0.875 0.125 k +*u +1251 473 m +1252.769 472.221 1254 472 1256 472 c +1254.231 472.779 1252.964 472.912 1251 473 c +f +*U +0.000 0.467 0.333 0.506 k +*u +1272.667 472.667 m +1272.222 472.222 1273.278 472.278 1273.333 472.333 c +1273.778 472.778 1272.722 472.722 1272.667 472.667 c +f +*U +0.000 0.122 0.035 0.180 k +*u +1176 472 m +1184.358 468.493 1197.940 471 1207 471 c +1276 471 l +1273 472.638 1270.260 472 1267 472 c +1260.668 471.941 1254.332 472 1248 472 c +1176 472 l +f +*U +0.000 0.000 0.000 0.753 k +*u +1361 473 m +1362 472 l +1361 473 l +f +*U +0.000 0.000 0.004 0.827 k +*u +1400 473 m +1401 472 l +1400 473 l +f +*U +0.000 0.000 0.000 0.494 k +*u +1054 472 m +1055 471 l +1054 472 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1094 472 m +1095 471 l +1094 472 l +f +*U +0.000 0.000 0.000 0.471 k +*u +1362 472 m +1363 471 l +1362 472 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1053 471 m +1054 470 l +1053 471 l +f +*U +0.000 0.000 0.000 0.341 k +*u +1093 471 m +1094 470 l +1093 471 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1363 471 m +1364 470 l +1363 471 l +f +*U +0.008 0.008 0.000 0.745 k +*u +1402 471 m +1403 470 l +1402 471 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1052 470 m +1053 469 l +1052 470 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1051 469 m +1052 468 l +1051 469 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1050 468 m +1051 467 l +1050 468 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1089 468 m +1090 467 l +1089 468 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1049 467 m +1050 466 l +1049 467 l +f +*U +0.000 0.000 0.000 0.510 k +*u +1088 467 m +1089 466 l +1088 467 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1368 467 m +1369 466 l +1368 467 l +f +*U +0.000 0.000 0.008 0.765 k +*u +1406 467 m +1407 466 l +1406 467 l +f +*U +0.000 0.000 0.000 0.294 k +*u +1087 466 m +1088 465 l +1087 466 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1369 466 m +1370 465 l +1369 466 l +f +*U +0.000 0.000 0.008 0.639 k +*u +1407 466 m +1408 465 l +1407 466 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1047 465 m +1048 464 l +1047 465 l +f +*U +0.000 0.000 0.000 0.443 k +*u +1370 465 m +1371 464 l +1370 465 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1408 465 m +1409 464 l +1408 465 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1046 464 m +1047 463 l +1046 464 l +f +*U +0.000 0.000 0.000 0.251 k +*u +1371 464 m +1372 463 l +1371 464 l +f +*U +0.000 0.000 0.008 0.651 k +*u +1409 464 m +1410 463 l +1409 464 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1045 463 m +1046 462 l +1045 463 l +f +*U +0.000 0.000 0.008 0.663 k +*u +1410 463 m +1411 462 l +1410 463 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1044 462 m +1045 461 l +1044 462 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1082 462 m +1083 461 l +1082 462 l +f +*U +0.000 0.000 0.008 0.251 k +*u +1411 462 m +1412 461 l +1411 462 l +f +*U +0.000 0.000 0.000 0.729 k +*u +1043 461 m +1044 460 l +1043 461 l +f +*U +0.000 0.000 0.000 0.463 k +*u +1081 461 m +1082 460 l +1081 461 l +f +*U +0.000 0.271 0.192 0.224 k +*u +1145 461 m +1146 460 l +1145 461 l +f +*U +0.000 0.400 0.282 0.600 k +*u +1146 461 m +1152.202 458.397 1161.298 460 1168 460 c +1161.797 462.603 1152.702 461 1146 461 c +f +*U +0.000 0.569 0.451 0.431 k +*u +1168 461 m +1169.969 459.937 1171.798 459.468 1174 459 c +1171.943 460.582 1170.613 460.826 1168 461 c +f +*U +0.000 0.278 0.259 0.722 k +*u +1173 461 m +1174.249 460.315 1174.548 460.251 1176 460 c +1174.752 460.685 1174.452 460.749 1173 461 c +f +*U +0.004 0.000 0.000 0.741 k +*u +1176 461 m +1177 460 l +1176 461 l +f +*U +0.000 0.424 0.345 0.576 k +*u +1283 461 m +1288.469 458.705 1296 460 1302 460 c +1296.531 462.295 1288.901 461 1283 461 c +f +*U +0.000 0.286 0.200 0.333 k +*u +1302.667 460.667 m +1302.222 460.222 1303.278 460.278 1303.333 460.333 c +1303.778 460.778 1302.722 460.722 1302.667 460.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1411 461 m +1409.723 459 1409.723 459.915 1411 458 c +1408 459 l +1408.275 456.730 1409.181 456.721 1410 455 c +1415.614 458.509 1418 449.335 1418 445 c +1417 449 l +1414.756 443.432 1418.748 440.397 1424 440 c +1426 434 l +1428.670 434.534 1428.443 433.215 1429 436 c +1439.506 428.578 1458.445 432 1471 432 c +1574 432 l +1968 432 l +1968 415 l +1619 415 l +1552.427 415 1485.454 413 1419 416 c +1420 413 l +1418 414.486 1416 415.836 1414 417 c +1419 407 1438.511 411 1448 411 c +1549 411 l +1974 411 l +1974 435 l +1592 435 l +1481 435 l +1449 435 l +1444.596 435 1438.312 433.875 1434.184 435.603 c +1430.813 437 1428.585 441.253 1426.399 444 c +1421.695 449.910 1417 456.566 1411 461 c +f +*U +0.000 0.000 0.008 0.200 k +*u +1412 461 m +1413 460 l +1412 461 l +f +*U +0.000 0.000 0.000 0.682 k +*u +1042 460 m +1043 459 l +1042 460 l +f +*U +0.000 0.000 0.000 0.400 k +*u +1080 460 m +1081 459 l +1080 460 l +f +*U +0.000 0.153 0.137 0.180 k +*u +1143 460 m +1144 459 l +1143 460 l +f +*U +0.000 0.686 0.506 0.314 k +*u +1144 460 m +1145.248 459.315 1145.548 459.251 1147 459 c +1145.752 459.685 1145.451 459.749 1144 460 c +f +*U +0.000 0.875 0.620 0.125 k +*u +1133 452 m +1133 450 l +1143.965 447.389 1159.403 448.480 1166 459 c +1168 458.754 1169.874 458.769 1172 459 c +1168.565 460.441 1164.703 460 1161 460 c +1156 460 1150.724 460.623 1146 459.200 c +1141.257 457.771 1137.281 454.383 1133 452 c +f +*U +0.000 0.141 0.094 0.271 k +*u +1174 460 m +1175 459 l +1174 460 l +f +*U +0.000 0.671 0.498 0.329 k +*u +1283 460 m +1283.545 458.365 1283.365 458.545 1285 458 c +1285 460 l +1283 460 l +f +*U +0.000 0.863 0.624 0.133 k +*u +1284 457 m +1286 455 1287.676 452.259 1290.224 450.862 c +1297 447 1307.481 449 1315 449 c +1313.378 451.388 1312.428 453 1312 456 c +1309.291 455.352 1306.784 455 1304 455 c +1305.800 455.562 1307 455.824 1309 456 c +1304 460.863 1288.450 463.171 1284 457 c +f +*U +0.000 0.286 0.204 0.082 k +*u +1305 460 m +1306 459 l +1305 460 l +f +*U +0.000 0.000 0.000 0.612 k +*u +1041 459 m +1042 458 l +1041 459 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1079 459 m +1080 458 l +1079 459 l +f +*U +0.000 0.314 0.251 0.086 k +*u +1141 459 m +1142 458 l +1141 459 l +f +*U +0.000 0.663 0.506 0.337 k +*u +1142.667 458.667 m +1142.222 458.222 1143.278 458.278 1143.333 458.333 c +1143.778 458.778 1142.722 458.722 1142.667 458.667 c +f +*U +0.000 0.757 0.596 0.243 k +*u +1166 459 m +1165 458 l +1165 456 l +1167.364 456.482 1167.518 456.636 1168 459 c +1166 459 l +f +*U +0.000 0.545 0.431 0.455 k +*u +1169.667 458.667 m +1169.222 458.222 1170.278 458.278 1170.333 458.333 c +1170.778 458.778 1169.722 458.722 1169.667 458.667 c +f +*U +0.000 0.447 0.298 0.337 k +*u +1171 459 m +1172 458 l +1171 459 l +f +*U +0.000 0.243 0.161 0.082 k +*u +1172 459 m +1173 458 l +1172 459 l +f +*U +0.000 0.325 0.220 0.039 k +*u +1283 459 m +1284 458 l +1283 459 l +f +*U +0.000 0.549 0.380 0.329 k +*u +1305.667 458.667 m +1305.222 458.222 1306.278 458.278 1306.333 458.333 c +1306.778 458.778 1305.722 458.722 1305.667 458.667 c +f +*U +0.000 0.298 0.212 0.000 k +*u +1307 459 m +1308 458 l +1307 459 l +f +*U +0.000 0.000 0.000 0.361 k +*u +1040 458 m +1041 457 l +1040 458 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1078 458 m +1079 457 l +1078 458 l +f +*U +0.000 0.235 0.180 0.090 k +*u +1139 458 m +1140 457 l +1139 458 l +f +*U +0.000 0.749 0.565 0.251 k +*u +1139 456 m +1140.580 456.683 1140.777 456.805 1142 458 c +1140.420 457.316 1140.223 457.195 1139 456 c +f +*U +0.000 0.443 0.337 0.557 k +*u +1168 458 m +1169 457 l +1168 458 l +f +*U +0.000 0.404 0.267 0.192 k +*u +1169 458 m +1170 457 l +1169 458 l +f +*U +0.000 0.392 0.282 0.361 k +*u +1308 458 m +1309 457 l +1308 458 l +f +*U +0.000 0.000 0.000 0.722 k +*u +1378 458 m +1379 457 l +1378 458 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1039 457 m +1040 456 l +1039 457 l +f +*U +0.000 0.302 0.212 0.278 k +*u +1138 457 m +1139 456 l +1138 457 l +f +*U +0.000 0.278 0.271 0.122 k +*u +1284 457 m +1285 456 l +1284 457 l +f +*U +0.000 0.769 0.482 0.224 k +*u +1304 456 m +1306.332 455 1308.457 455 1311 455 c +1308.644 456.371 1306.743 456 1304 456 c +f +*U +0.000 0.298 0.208 0.306 k +*u +1310 457 m +1311 456 l +1310 457 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1038 456 m +1039 455 l +1038 456 l +f +*U +0.000 0.569 0.459 0.165 k +*u +1136 456 m +1137 455 l +1136 456 l +f +*U +0.000 0.741 0.506 0.259 k +*u +1136 454 m +1137.580 454.683 1137.778 454.805 1139 456 c +1137.420 455.316 1137.223 455.195 1136 454 c +f +*U +0.000 0.557 0.396 0.443 k +*u +1163.667 455.667 m +1163.222 455.222 1164.278 455.278 1164.333 455.333 c +1164.778 455.778 1163.722 455.722 1163.667 455.667 c +f +*U +0.000 0.278 0.212 0.212 k +*u +1165 456 m +1166 455 l +1165 456 l +f +*U +0.000 0.314 0.200 0.459 k +*u +1285 456 m +1286 455 l +1285 456 l +f +*U +0.000 0.596 0.396 0.404 k +*u +1286 456 m +1286 453 l +1286.696 454.554 1286.696 454.446 1286 456 c +f +*U +0.000 0.243 0.224 0.055 k +*u +1312 456 m +1313 455 l +1312 456 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1038 455 m +1033.585 449.946 1028.679 441.305 1022.826 438 c +1018.671 435.701 1011.614 437 1007 437 c +969 437 l +833 437 l +243 437 l +109 437 l +68 437 l +58.250 437 48.548 437.463 39 435 c +24.783 431.584 11 422.596 4.901 409 c +1.701 402 0.947 394.492 0 387 c +2 388.988 2.579 390 3 393 c +5 388 l +3 386.181 3.920 385.305 6 384 c +6 385.797 5.986 385.522 5 387 c +6.635 386.455 6.455 386.635 7 385 c +9 390.551 7 395.360 4 400 c +8 399 l +7.693 401 7.618 401.686 6 403 c +7.409 405.564 8.403 406.670 11 408 c +8 411 l +12 410 l +11.402 411.195 11.534 410.977 10 412 c +11.416 412.472 11.814 412.814 13 414 c +15.367 410.507 17.329 418.372 19 420 c +18.782 418.313 18.776 417.684 19 416 c +21.437 417.306 22.694 418.563 24 421 c +22.316 421.224 21.687 421.218 20 421 c +24 424.478 32 424.227 31 431 c +35.444 431.946 39.463 432.483 44 432 c +43 434 l +44.723 433 46 432.465 48 432 c +49 436 l +53 435 l +49 434 l +54.619 430.634 62.653 432 69 432 c +114 432 l +282 432 l +804 432 l +954 432 l +997 432 l +1004.677 432 1012.812 430.954 1020 434 c +1019 432 l +1022.312 432.552 1024 431.678 1028 433 c +1029 432 l +1029 434 l +1030.186 432.964 1030.604 432.661 1032 432 c +1031.548 433.863 1030.908 435.308 1030 437 c +1032 436 l +1031.454 441.569 1032.295 444.690 1036 449 c +1036 447 l +1040 450 l +1039.676 452.204 1039.433 453.328 1038 455 c +f +*U +0.000 0.192 0.114 0.153 k +*u +1134 455 m +1135 454 l +1134 455 l +f +*U +0.000 0.322 0.196 0.529 k +*u +1135 455 m +1136 454 l +1135 455 l +f +*U +0.000 0.482 0.388 0.518 k +*u +1161.667 454.667 m +1161.222 454.222 1162.278 454.278 1162.333 454.333 c +1162.778 454.777 1161.722 454.722 1161.667 454.667 c +f +*U +0.000 0.361 0.267 0.153 k +*u +1163 455 m +1164 454 l +1163 455 l +f +*U +0.000 0.369 0.357 0.475 k +*u +1312.667 454.667 m +1312.222 454.222 1313.278 454.278 1313.333 454.333 c +1313.778 454.778 1312.722 454.722 1312.667 454.667 c +f +*U +0.000 0.000 0.000 0.749 k +*u +1417 455 m +1418 454 l +1417 455 l +f +*U +0.000 0.349 0.220 0.263 k +*u +1133 454 m +1134 453 l +1133 454 l +f +*U +0.000 0.714 0.557 0.286 k +*u +1131 452 m +1133 451.590 1133.963 452 1136 453 c +1133.859 453.410 1133 452.968 1131 452 c +f +*U +0.000 0.369 0.318 0.631 k +*u +1160 454 m +1161 453 l +1160 454 l +f +*U +0.000 0.353 0.259 0.122 k +*u +1161 454 m +1162 453 l +1161 454 l +f +*U +0.000 0.812 0.600 0.188 k +*u +1312 454 m +1313.446 449.667 1316.885 449 1321 448 c +1318.952 451.731 1316 453.201 1312 454 c +f +*U +0.000 0.427 0.341 0.169 k +*u +1315 454 m +1316 453 l +1315 454 l +f +*U +0.020 0.024 0.000 0.753 k +*u +1382 454 m +1383 453 l +1382 454 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1418 454 m +1419 453 l +1418 454 l +f +*U +0.000 0.341 0.227 0.129 k +*u +1131 453 m +1132 452 l +1131 453 l +f +*U +0.000 0.533 0.388 0.345 k +*u +1157 453 m +1158.248 452.315 1158.548 452.251 1160 452 c +1158.752 452.685 1158.452 452.749 1157 453 c +f +*U +0.000 0.275 0.188 0.059 k +*u +1286 453 m +1287 452 l +1286 453 l +f +*U +0.000 0.529 0.357 0.471 k +*u +1287.333 452.333 m +1287.278 452.278 1287.222 451.222 1287.667 451.667 c +1287.723 451.723 1287.777 452.778 1287.333 452.333 c +f +*U +0.000 0.298 0.145 0.102 k +*u +1317 453 m +1318 452 l +1317 453 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1419 453 m +1420 452 l +1419 453 l +f +*U +0.000 0.282 0.188 0.310 k +*u +1130 452 m +1131 451 l +1130 452 l +f +*U +0.000 0.604 0.482 0.396 k +*u +1156 452 m +1157 451 l +1156 452 l +f +*U +0.000 0.396 0.286 0.220 k +*u +1157 452 m +1158 451 l +1157 452 l +f +*U +0.000 0.282 0.208 0.357 k +*u +1318 452 m +1319 451 l +1318 452 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1034 451 m +1035 450 l +1034 451 l +f +*U +0.000 0.435 0.239 0.094 k +*u +1128 451 m +1129 450 l +1128 451 l +f +*U +0.000 0.639 0.459 0.361 k +*u +1129.667 450.667 m +1129.222 450.222 1130.278 450.278 1130.333 450.333 c +1130.778 450.778 1129.722 450.722 1129.667 450.667 c +f +*U +0.000 0.867 0.675 0.133 k +*u +1129 450 m +1131 449 1132.747 449 1135 449 c +1132.787 450.393 1131.609 450.374 1129 450 c +f +*U +0.000 0.451 0.329 0.388 k +*u +1154.667 450.667 m +1154.222 450.222 1155.278 450.278 1155.333 450.333 c +1155.778 450.778 1154.722 450.722 1154.667 450.667 c +f +*U +0.000 0.251 0.188 0.122 k +*u +1156 451 m +1157 450 l +1156 451 l +f +*U +0.000 0.298 0.196 0.239 k +*u +1287 451 m +1288 450 l +1287 451 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1288 451 m +1289 450 l +1288 451 l +f +*U +0.000 0.608 0.443 0.341 k +*u +1289 451 m +1290.458 449.919 1291.248 449.564 1293 449 c +1291.457 450.267 1290.952 450.489 1289 451 c +f +*U +0.000 0.000 0.000 0.655 k +*u +1033 450 m +1034 449 l +1033 450 l +f +*U +0.000 0.275 0.196 0.396 k +*u +1127 450 m +1128 449 l +1127 450 l +f +*U +0.000 0.741 0.741 0.259 k +*u +1128 450 m +1131.989 445.435 1146 448 1152 448 c +1144.846 451 1135.658 448.177 1128 450 c +f +*U +0.000 0.510 0.416 0.490 k +*u +1153 450 m +1154 449 l +1153 450 l +f +*U +0.000 0.298 0.239 0.192 k +*u +1154 450 m +1155 449 l +1154 450 l +f +*U +0.000 0.208 0.169 0.141 k +*u +1290 450 m +1291 449 l +1290 450 l +f +*U +0.000 0.337 0.267 0.004 k +*u +1321 450 m +1322 449 l +1321 450 l +f +*U +0.000 0.000 0.000 0.361 k +*u +1032 449 m +1033 448 l +1032 449 l +f +*U +0.000 0.141 0.114 0.259 k +*u +1125 449 m +1126 448 l +1125 449 l +f +*U +0.000 0.271 0.271 0.729 k +*u +1126.667 448.667 m +1126.222 448.222 1127.278 448.278 1127.333 448.333 c +1127.778 448.778 1126.722 448.722 1126.667 448.667 c +f +*U +0.000 0.192 0.188 0.263 k +*u +1152 449 m +1153 448 l +1152 449 l +f +*U +0.000 0.573 0.514 0.427 k +*u +1292.667 448.667 m +1292.222 448.222 1293.278 448.278 1293.333 448.333 c +1293.778 448.778 1292.722 448.722 1292.667 448.667 c +f +*U +0.000 0.753 0.753 0.247 k +*u +1294 449 m +1301.169 445.992 1312.239 448 1320 448 c +1312.831 451 1301.761 449 1294 449 c +f +*U +0.000 0.373 0.282 0.549 k +*u +1321.667 448.667 m +1321.222 448.222 1322.278 448.278 1322.333 448.333 c +1322.778 448.778 1321.722 448.722 1321.667 448.667 c +f +*U +0.000 0.000 0.000 0.780 k +*u +1422 449 m +1423 448 l +1422 449 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1031 448 m +1032 447 l +1031 448 l +f +*U +0.094 0.000 0.027 0.216 k +*u +1294 448 m +1295.248 447.315 1295.548 447.251 1297 447 c +1295.752 447.685 1295.451 447.749 1294 448 c +f +*U +0.000 0.000 0.000 0.796 k +*u +1423 448 m +1424 447 l +1423 448 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1030 447 m +1031 446 l +1030 447 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1066 447 m +1067 446 l +1066 447 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1424 447 m +1425 446 l +1424 447 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1389 446 m +1390 445 l +1389 446 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1426 444 m +1427 443 l +1426 444 l +f +*U +0.000 0.000 0.000 0.541 k +*u +1027 443 m +1028 442 l +1027 443 l +f +*U +0.000 0.000 0.000 0.298 k +*u +1392 443 m +1393 442 l +1392 443 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1427 443 m +1428 442 l +1427 443 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1026 442 m +1027 441 l +1026 442 l +f +*U +0.000 0.000 0.000 0.545 k +*u +1393 442 m +1394 441 l +1393 442 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1428 442 m +1429 441 l +1428 442 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1025 441 m +1026 440 l +1025 441 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1394 441 m +1395 440 l +1394 441 l +f +*U +0.012 0.000 0.016 0.000 k +*u +48 440 m +52 437 l +58.834 440.647 68.400 439 76 439 c +129 439 l +322 439 l +1023 439 l +1015.841 442 1004.744 440 997 440 c +940 440 l +740 440 l +48 440 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1395 440 m +1396 439 l +1395 440 l +f +*U +0.000 0.000 0.000 0.729 k +*u +1024 439 m +1025 438 l +1024 439 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1059 439 m +1060 438 l +1059 439 l +f +*U +0.000 0.000 0.000 0.408 k +*u +1430 439 m +1431 438 l +1430 439 l +f +*U +0.000 0.000 0.000 0.004 k +*u +1439 436 m +1445.817 437.623 1453 437 1460 437 c +1495 437 l +1608 437 l +1969 437 l +1965.730 439.477 1962 439.000 1958 439 c +1939 439 l +1861 439 l +1558 439 l +1469 439 l +1448 439 l +1444.213 438.992 1441.171 439.349 1439 436 c +f +*U +0.024 0.000 0.027 0.102 k +*u +52 438 m +59 434.996 70.256 437 78 437 c +135 437 l +333 437 l +1022 437 l +1014.841 440 1003.744 438 996 438 c +939 438 l +740 438 l +52 438 l +f +*U +0.024 0.000 0.031 0.325 k +*u +1022.667 437.667 m +1022.222 437.222 1023.278 437.278 1023.333 437.333 c +1023.778 437.778 1022.722 437.722 1022.667 437.667 c +f +*U +0.000 0.000 0.000 0.200 k +*u +1058 438 m +1059 437 l +1058 438 l +f +*U +0.000 0.000 0.000 0.325 k +*u +1431 438 m +1432 437 l +1431 438 l +f +*U +0.000 0.000 0.000 0.420 k +*u +44 437 m +45 436 l +44 437 l +f +*U +0.000 0.000 0.000 0.588 k +*u +45 437 m +46 436 l +45 437 l +f +*U +0.000 0.000 0.000 0.824 k +*u +46 437 m +47 436 l +46 437 l +f +*U +0.000 0.000 0.000 0.263 k +*u +1057 437 m +1058 436 l +1057 437 l +f +*U +0.000 0.224 0.169 0.035 k +*u +1110 437 m +1111 436 l +1110 437 l +f +*U +0.000 0.529 0.408 0.471 k +*u +1111 437 m +1117.584 434.237 1125.949 436.679 1133 435 c +1129.196 439.354 1116.561 437 1111 437 c +f +*U +0.000 0.373 0.271 0.592 k +*u +1133.667 436.667 m +1133.222 436.222 1134.278 436.278 1134.333 436.333 c +1134.778 436.778 1133.722 436.722 1133.667 436.667 c +f +*U +0.000 0.514 0.420 0.486 k +*u +1298 435 m +1307.524 437.267 1318.247 436 1328 436 c +1321.814 438.596 1312.678 437 1306 437 c +1302.895 436.994 1300 437.407 1298 435 c +f +*U +0.000 0.604 0.486 0.396 k +*u +1328 437 m +1331.366 435.584 1335.373 435.673 1339 435 c +1335.734 437.474 1331.990 437.000 1328 437 c +f +*U +0.000 0.000 0.000 0.537 k +*u +40 436 m +41 435 l +40 436 l +f +*U +0.004 0.000 0.004 0.996 k +*u +57 436 m +63.919 433 74.520 435 82 435 c +139 435 l +335 435 l +1015 435 l +1008 437.903 997.480 436 990 436 c +933 436 l +737 436 l +57 436 l +f +*U +0.000 0.000 0.000 0.475 k +*u +1056 436 m +1057 435 l +1056 436 l +f +*U +0.000 0.263 0.204 0.357 k +*u +1109 436 m +1110 435 l +1109 436 l +f +*U +0.000 0.545 0.447 0.455 k +*u +1110 436 m +1111 435 l +1110 436 l +f +*U +0.000 0.863 0.604 0.137 k +*u +1106 427 m +1101 427 l +1101 425 l +1121 425 l +1123.329 429.352 1128.185 431.948 1132 435 c +1124.775 438 1104.947 438.189 1106 427 c +f +*U +0.000 0.353 0.259 0.176 k +*u +1133 436 m +1134 435 l +1133 436 l +f +*U +0.000 0.875 0.624 0.125 k +*u +1299 436 m +1298.808 431.871 1297.540 428.769 1296 425 c +1348 425 l +1338.944 441.346 1314.725 436 1299 436 c +f +*U +0.000 0.173 0.157 0.192 k +*u +1339 436 m +1340 435 l +1339 436 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1398 436 m +1399 435 l +1398 436 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1432 436 m +1433 435 l +1432 436 l +f +*U +0.000 0.000 0.000 0.451 k +*u +36 435 m +37 434 l +36 435 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1055 435 m +1056 434 l +1055 435 l +f +*U +0.000 0.282 0.239 0.176 k +*u +1108 435 m +1109 434 l +1108 435 l +f +*U +0.000 0.506 0.431 0.494 k +*u +1131 435 m +1132 434 l +1131 435 l +f +*U +0.000 0.227 0.176 0.122 k +*u +1132 435 m +1133 434 l +1132 435 l +f +*U +0.000 0.518 0.475 0.090 k +*u +1298.333 434.333 m +1298.278 434.278 1298.222 433.222 1298.667 433.667 c +1298.723 433.723 1298.777 434.777 1298.333 434.333 c +f +*U +0.000 0.725 0.549 0.275 k +*u +1339 435 m +1340.324 432.313 1341.313 431.324 1344 430 c +1342.451 432 1341 433.451 1339 435 c +f +*U +0.000 0.294 0.224 0.098 k +*u +1340 435 m +1341 434 l +1340 435 l +f +*U +0.000 0.000 0.000 0.475 k +*u +1399 435 m +1400 434 l +1399 435 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1974 435 m +1974 410 l +1976.413 415.750 1976.413 429.250 1974 435 c +f +*U +0.000 0.000 0.000 0.400 k +*u +33 434 m +34 433 l +33 434 l +f +*U +0.000 0.000 0.000 0.988 k +*u +55 434 m +61.919 431 72.520 433 80 433 c +137 433 l +334 433 l +1016 433 l +1009 435.903 998.480 434 991 434 c +934 434 l +737 434 l +55 434 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1054 434 m +1055 433 l +1054 434 l +f +*U +0.000 0.416 0.325 0.133 k +*u +1107 434 m +1108 433 l +1107 434 l +f +*U +0.000 0.529 0.392 0.318 k +*u +1129 434 m +1129 432 l +1130.635 432.545 1130.455 432.365 1131 434 c +1129 434 l +f +*U +0.000 0.294 0.235 0.220 k +*u +1341 434 m +1342 433 l +1341 434 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1400 434 m +1401 433 l +1400 434 l +f +*U +0.000 0.000 0.000 0.220 k +*u +30 433 m +31 432 l +30 433 l +f +*U +0.000 0.000 0.000 0.592 k +*u +31 433 m +32 432 l +31 433 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1053 433 m +1054 432 l +1053 433 l +f +*U +0.000 0.349 0.282 0.247 k +*u +1106 433 m +1107 432 l +1106 433 l +f +*U +0.000 0.514 0.369 0.427 k +*u +1298 433 m +1298 430 l +1298.696 431.554 1298.696 431.446 1298 433 c +f +*U +0.000 0.227 0.200 0.263 k +*u +1342 433 m +1343 432 l +1342 433 l +f +*U +0.000 0.000 0.000 0.384 k +*u +28 432 m +29 431 l +28 432 l +f +*U +0.000 0.412 0.314 0.208 k +*u +1105 432 m +1106 431 l +1105 432 l +f +*U +0.063 0.000 0.012 0.275 k +*u +1128 432 m +1129 431 l +1128 432 l +f +*U +0.000 0.624 0.522 0.067 k +*u +1343 432 m +1344 431 l +1343 432 l +f +*U +0.000 0.000 0.000 0.349 k +*u +26 431 m +27 430 l +26 431 l +f +*U +0.000 0.753 0.576 0.235 k +*u +1104 431 m +1102 427 l +1106 427 l +1106 431 l +1104 431 l +f +*U +0.000 0.478 0.349 0.416 k +*u +1124 428 m +1125.457 429 1125.897 429.543 1127 431 c +1124.876 430 1124.899 430 1124 428 c +f +*U +0.000 0.188 0.149 0.082 k +*u +1127 431 m +1128 430 l +1127 431 l +f +*U +0.000 0.137 0.145 0.412 k +*u +1344 431 m +1345 430 l +1344 431 l +f +*U +0.000 0.000 0.000 0.239 k +*u +24 430 m +25 429 l +24 430 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1051 430 m +1052 429 l +1051 430 l +f +*U +0.000 0.400 0.227 0.310 k +*u +1103 430 m +1104 429 l +1103 430 l +f +*U +0.000 0.263 0.216 0.090 k +*u +1297 430 m +1298 429 l +1297 430 l +f +*U +0.000 0.369 0.306 0.271 k +*u +1345 430 m +1346 429 l +1345 430 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1403 430 m +1404 429 l +1403 430 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1050 429 m +1051 428 l +1050 429 l +f +*U +0.000 0.553 0.455 0.447 k +*u +1297.333 428.333 m +1297.278 428.278 1297.222 427.222 1297.667 427.667 c +1297.722 427.722 1297.778 428.778 1297.333 428.333 c +f +*U +0.000 0.314 0.369 0.192 k +*u +1346 429 m +1347 428 l +1346 429 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1404 429 m +1405 428 l +1404 429 l +f +*U +0.000 0.000 0.000 0.451 k +*u +21 428 m +22 427 l +21 428 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1049 428 m +1050 427 l +1049 428 l +f +*U +0.000 0.325 0.267 0.298 k +*u +1101 428 m +1102 427 l +1101 428 l +f +*U +0.000 0.686 0.518 0.306 k +*u +1121 428 m +1121 426 l +1122.635 426.545 1122.455 426.365 1123 428 c +1121 428 l +f +*U +0.000 0.365 0.294 0.259 k +*u +1123 428 m +1124 427 l +1123 428 l +f +*U +0.000 0.227 0.192 0.086 k +*u +1296 428 m +1297 427 l +1296 428 l +f +*U +0.000 0.325 0.212 0.282 k +*u +1347 428 m +1348 427 l +1347 428 l +f +*U +0.000 0.412 0.325 0.341 k +*u +1100 427 m +1101 426 l +1100 427 l +f +*U +0.000 0.310 0.263 0.204 k +*u +1122 427 m +1123 426 l +1122 427 l +f +*U +0.000 0.420 0.392 0.580 k +*u +1347 427 m +1348 426 l +1347 427 l +f +*U +0.000 0.220 0.235 0.239 k +*u +1348 427 m +1349 426 l +1348 427 l +f +*U +0.000 0.000 0.000 0.188 k +*u +18 426 m +19 425 l +18 426 l +f +*U +0.000 0.349 0.263 0.290 k +*u +1099 426 m +1100 425 l +1099 426 l +f +*U +0.000 0.533 0.482 0.467 k +*u +1099 425 m +1100.769 424.221 1102 424 1104 424 c +1102 425 1101.229 425 1099 425 c +f +*U +0.000 0.357 0.255 0.192 k +*u +1121 426 m +1122 425 l +1121 426 l +f +*U +0.000 0.173 0.125 0.329 k +*u +1295 426 m +1296 425 l +1295 426 l +f +*U +0.000 0.592 0.471 0.408 k +*u +1303 425 m +1307.720 423 1313.920 424 1319 424 c +1350 424 l +1346.182 426.207 1340.402 425 1336 425 c +1303 425 l +f +*U +0.000 0.278 0.247 0.239 k +*u +1349 426 m +1350 425 l +1349 426 l +f +*U +0.000 0.000 0.000 0.275 k +*u +1406 426 m +1407 425 l +1406 426 l +f +*U +0.000 0.000 0.000 0.773 k +*u +17 425 m +18 424 l +17 425 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1047 425 m +1048 424 l +1047 425 l +f +*U +0.000 0.192 0.161 0.447 k +*u +1098 425 m +1099 424 l +1098 425 l +f +*U +0.000 0.616 0.518 0.384 k +*u +1104 425 m +1108.724 423 1114.910 424 1120 424 c +1115.276 425.982 1109 425 1104 425 c +f +*U +0.000 0.082 0.051 0.380 k +*u +1120 425 m +1121 424 l +1120 425 l +f +*U +0.000 0.239 0.180 0.576 k +*u +1294 425 m +1295 424 l +1294 425 l +f +*U +0.000 0.400 0.400 0.600 k +*u +1295 425 m +1297.613 423.902 1300 424 1303 424 c +1300.387 425 1297.836 424.993 1295 425 c +f +*U +0.000 0.239 0.129 0.278 k +*u +1350 425 m +1351 424 l +1350 425 l +f +*U +0.000 0.000 0.004 0.361 k +*u +1407 425 m +1408 424 l +1407 425 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1046 424 m +1047 423 l +1046 424 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1045 423 m +1046 422 l +1045 423 l +f +*U +0.008 0.008 0.000 0.200 k +*u +1409 422 m +1410 421 l +1409 422 l +f +*U +0.008 0.008 0.000 0.643 k +*u +1410 421 m +1411 420 l +1410 421 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1043 420 m +1044 419 l +1043 420 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1042 419 m +1043 418 l +1042 419 l +f +*U +0.000 0.000 0.000 0.792 k +*u +10 418 m +11 417 l +10 418 l +f +*U +0.008 0.008 0.000 0.494 k +*u +1412 418 m +1413 417 l +1412 418 l +f +*U +0.000 0.000 0.000 0.533 k +*u +9 417 m +10 416 l +9 417 l +f +*U +0.000 0.000 0.000 1.000 k +*u +56 416 m +63 412.996 74.256 415 82 415 c +139 415 l +337 415 l +1024 415 l +1014.317 412 1002 414 992 414 c +927 414 l +713 414 l +287 414 l +150 414 l +120.557 414 90.368 412 61 414 c +56.305 414.375 51.748 415.650 47 416 c +48 414 l +46.365 414.545 46.545 414.365 46 416 c +42 415 l +42 413.203 42 413.479 43 412 c +40.734 411.657 38.346 411.382 40 414 c +39 412 l +40.618 413.314 40.693 413.877 41 416 c +38.711 415.239 35.767 414.630 34.328 412.490 c +32 409.247 33.743 405.592 29 405 c +29 399 l +27 404 l +24 404 l +24.768 402.686 24.686 402.768 26 402 c +24 399 24.308 396.349 24 393 c +25.267 391.457 25.489 390.952 26 389 c +25 391 l +21.895 383.601 24 372 24 364 c +24 305 l +15.957 305 7.998 305.609 0 305 c +7.409 301.891 18.975 304 27 304 c +27 371 l +27 381.888 25.902 394 33.380 402.960 c +41.502 412.660 53.403 413 65 413 c +101 413 l +286 413 l +823 413 l +974 413 l +1015 413 l +1024 413 1032.654 412 1041 416 c +1038.167 416.926 1036.303 415.540 1033.424 415.394 c +1027 415 1020.376 416 1014 416 c +952 416 l +745 416 l +56 416 l +f +*U +0.000 0.000 0.000 0.212 k +*u +8 416 m +9 415 l +8 416 l +f +*U +0.024 0.024 0.000 0.976 k +*u +1424 416 m +1428.720 414 1434.920 415 1440 415 c +1472 415 l +1583 415 l +1968 415 l +1963.280 416.981 1957 416 1952 416 c +1921 416 l +1810 416 l +1424 416 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1037 415 m +1038 414 l +1037 415 l +f +*U +0.000 0.000 0.000 0.298 k +*u +1038 415 m +1039 414 l +1038 415 l +f +*U +0.008 0.000 0.012 0.988 k +*u +1422 415 m +1425.691 412.204 1430.515 413 1435 413 c +1461 413 l +1566 413 l +1969 413 l +1964.785 414.769 1959.536 414 1955 414 c +1926 414 l +1825 414 l +1555 414 l +1469 414 l +1453.686 414 1437 412.200 1422 415 c +f +*U +0.000 0.000 0.000 0.647 k +*u +7 414 m +8 413 l +7 414 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1035 414 m +1036 413 l +1035 414 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1036 414 m +1037 413 l +1036 414 l +f +*U +0.000 0.255 0.075 0.110 k +*u +1089 414 m +1093.471 412 1099.183 413 1104 413 c +1099.529 414.876 1093.817 414 1089 414 c +f +*U +0.000 0.361 0.220 0.047 k +*u +1104 414 m +1105.769 413.221 1107 413 1109 413 c +1107.231 413.779 1105.964 413.912 1104 414 c +f +*U +0.000 0.251 0.063 0.114 k +*u +1298 414 m +1303.217 411.811 1310.381 413 1316 413 c +1352 413 l +1346.784 415.189 1339.619 414 1334 414 c +1298 414 l +f +*U +0.000 0.231 0.161 0.118 k +*u +1352 414 m +1354.613 412.902 1357 413 1360 413 c +1357.387 414 1354.836 413.993 1352 414 c +f +*U +0.000 0.000 0.000 0.173 k +*u +1415 414 m +1416 413 l +1415 414 l +f +*U +0.000 0.000 0.000 0.239 k +*u +6 413 m +7 412 l +6 413 l +f +*U +0.000 0.000 0.000 0.812 k +*u +50 413 m +51 412 l +50 413 l +f +*U +0.000 0.000 0.000 0.490 k +*u +51 413 m +58 409.996 69.256 412 77 412 c +135 412 l +336 412 l +1033 412 l +1025.841 415 1014.744 413 1007 413 c +949 413 l +748 413 l +51 413 l +f +*U +0.000 0.690 0.486 0.310 k +*u +1088 413 m +1088 411 l +1090 411 l +1089.455 412.635 1089.635 412.455 1088 413 c +f +*U +0.000 0.733 0.722 0.267 k +*u +1089.667 412.667 m +1089.222 412.222 1090.278 412.278 1090.333 412.333 c +1090.778 412.778 1089.722 412.722 1089.667 412.667 c +f +*U +0.000 0.800 0.875 0.125 k +*u +1091 413 m +1095.724 411 1101.910 412 1107 412 c +1102.276 413.982 1096 413 1091 413 c +f +*U +0.000 0.475 0.525 0.475 k +*u +1107 413 m +1108 412 l +1107 413 l +f +*U +0.000 0.227 0.302 0.259 k +*u +1108 413 m +1109 412 l +1108 413 l +f +*U +0.000 0.565 0.420 0.396 k +*u +1298 413 m +1298 408 l +1298.830 410 1298.830 410.970 1298 413 c +f +*U +0.000 0.773 0.855 0.145 k +*u +1299 413 m +1303.969 410.915 1310.650 412 1316 412 c +1352 412 l +1347 414 1340.350 413 1335 413 c +1299 413 l +f +*U +0.000 0.859 0.612 0.137 k +*u +1352 413 m +1354 412 1355.747 412 1358 412 c +1358 410 l +1315 410 l +1306 410 1296.397 408.986 1291 401 c +1294.474 401.231 1297.560 402.704 1301 402.946 c +1314.869 403.916 1329 403 1343 403 c +1346.604 403 1358.640 401 1360.824 404.545 c +1363.322 408.491 1353.592 407.999 1352 408 c +1355.590 409 1358.703 408.815 1361 412 c +1357.959 412.900 1355.169 412.992 1352 413 c +f +*U +0.000 0.278 0.180 0.345 k +*u +1360 413 m +1361 412 l +1360 413 l +f +*U +0.000 0.000 0.000 0.525 k +*u +1417 413 m +1418 412 l +1417 413 l +f +*U +0.000 0.000 0.000 0.686 k +*u +46 412 m +47 411 l +46 412 l +f +*U +0.000 0.000 0.000 0.192 k +*u +47 412 m +48 411 l +47 412 l +f +*U +0.000 0.235 0.149 0.337 k +*u +1087 412 m +1088 411 l +1087 412 l +f +*U +0.000 0.851 0.596 0.141 k +*u +1082 401 m +1086.620 401 1093.403 399.742 1097.696 401.603 c +1100.704 402.908 1102.175 406.339 1105 408 c +1103.272 413.208 1093.657 413.509 1089.299 410.825 c +1086.243 408.943 1083.492 404 1082 401 c +f +*U +0.000 0.808 0.718 0.173 k +*u +1104 412 m +1105 410 l +1106.635 410.545 1106.455 410.365 1107 412 c +1104 412 l +f +*U +0.000 0.286 0.275 0.235 k +*u +1107 412 m +1108 411 l +1107 412 l +f +*U +0.000 0.925 0.663 0.075 k +*u +1299 412 m +1299 408 l +1318.474 410.576 1338.184 410 1358 410 c +1358 412 l +1338.254 411.592 1318.764 410.440 1299 412 c +f +*U +0.000 0.843 0.580 0.157 k +*u +1303 412 m +1307.720 410 1313.920 411 1319 411 c +1352 411 l +1347.280 412.981 1341 412 1336 412 c +1303 412 l +f +*U +0.000 0.263 0.173 0.157 k +*u +1361 412 m +1362 411 l +1361 412 l +f +*U +0.000 0.000 0.000 0.541 k +*u +1419 412 m +1420 411 l +1419 412 l +f +*U +0.000 0.000 0.000 0.341 k +*u +5 411 m +6 410 l +5 411 l +f +*U +0.000 0.000 0.000 0.624 k +*u +43 411 m +44 410 l +43 411 l +f +*U +0.000 0.365 0.243 0.173 k +*u +1086 411 m +1087 410 l +1086 411 l +f +*U +0.000 0.471 0.337 0.529 k +*u +1087 411 m +1088 410 l +1087 411 l +f +*U +0.000 0.333 0.310 0.275 k +*u +1106 411 m +1107 410 l +1106 411 l +f +*U +0.000 0.910 0.663 0.090 k +*u +1360 411 m +1357.440 409 1355.192 409 1352 409 c +1356.775 406.991 1359.915 407.950 1363 403 c +1296 403 l +1296 401 l +1367 401 l +1365 404.706 1362.922 408 1360 411 c +f +*U +0.000 0.702 0.498 0.298 k +*u +1361 411 m +1361.683 409.420 1361.805 409.223 1363 408 c +1362.316 409.580 1362.195 409.777 1361 411 c +f +*U +0.000 0.000 0.000 0.188 k +*u +1422 411 m +1423 410 l +1422 411 l +f +*U +0.055 0.063 0.000 0.580 k +*u +1423 411 m +1427.720 409 1433.920 410 1439 410 c +1471 410 l +1583 410 l +1974 410 l +1969.280 411.981 1963 411 1958 411 c +1926 411 l +1813 411 l +1423 411 l +f +*U +0.000 0.000 0.000 0.365 k +*u +41 410 m +42 409 l +41 410 l +f +*U +0.000 0.000 0.000 0.004 k +*u +56 410 m +56 408 l +1032 408 l +1023.793 411.476 1012.764 410 1004 410 c +947 410 l +748 410 l +56 410 l +f +*U +0.000 0.631 0.427 0.369 k +*u +1086 410 m +1085 408.521 1085 408.797 1085 407 c +1086.289 408.443 1086.401 408.234 1086 410 c +f +*U +0.000 0.506 0.247 0.275 k +*u +1105 410 m +1106 409 l +1105 410 l +f +*U +0.000 0.000 0.000 0.200 k +*u +4 409 m +5 408 l +4 409 l +f +*U +0.000 0.000 0.000 0.592 k +*u +39 409 m +40 408 l +39 409 l +f +*U +0.000 0.278 0.165 0.071 k +*u +1297 409 m +1298 408 l +1297 409 l +f +*U +0.000 0.325 0.208 0.306 k +*u +1363 409 m +1364 408 l +1363 409 l +f +*U +0.008 0.008 0.000 0.827 k +*u +35 408 m +36 407 l +35 408 l +f +*U +0.000 0.259 0.302 0.329 k +*u +1084 408 m +1085 407 l +1084 408 l +f +*U +0.000 0.776 0.627 0.071 k +*u +1086 408 m +1085 406 l +1087 406 l +1087 407.853 1087.300 407.350 1086 408 c +f +*U +0.000 0.565 0.439 0.435 k +*u +1102 408 m +1102 406 l +1103.635 406.545 1103.455 406.365 1104 408 c +1102 408 l +f +*U +0.000 0.635 0.486 0.051 k +*u +1296 408 m +1297 407 l +1296 408 l +f +*U +0.000 0.741 0.549 0.239 k +*u +1295 407 m +1297 406.249 1297.596 406.344 1299 408 c +1295 407 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1363.333 407.333 m +1363.278 407.278 1363.222 406.222 1363.667 406.667 c +1363.722 406.723 1363.777 407.778 1363.333 407.333 c +f +*U +0.000 0.204 0.180 0.145 k +*u +1364 408 m +1365 407 l +1364 408 l +f +*U +0.000 0.000 0.000 0.216 k +*u +3 407 m +4 406 l +3 407 l +f +*U +0.008 0.008 0.000 0.737 k +*u +36 407 m +37 406 l +36 407 l +f +*U +0.000 0.447 0.404 0.475 k +*u +1084 407 m +1085 406 l +1084 407 l +f +*U +0.000 0.341 0.224 0.145 k +*u +1294 407 m +1295 406 l +1294 407 l +f +*U +0.000 0.427 0.325 0.573 k +*u +1364 407 m +1365 406 l +1364 407 l +f +*U +0.000 0.000 0.000 0.678 k +*u +3 406 m +4 405 l +3 406 l +f +*U +0.008 0.008 0.000 0.192 k +*u +35 406 m +36 405 l +35 406 l +f +*U +0.000 0.733 0.557 0.267 k +*u +1083 406 m +1083 404 l +1084.635 404.545 1084.455 404.365 1085 406 c +1083 406 l +f +*U +0.000 0.278 0.204 0.063 k +*u +1102 406 m +1103 405 l +1102 406 l +f +*U +0.000 0.337 0.243 0.286 k +*u +1293 406 m +1294 405 l +1293 406 l +f +*U +0.000 0.584 0.451 0.416 k +*u +1365 406 m +1365.406 403.908 1365.217 403.980 1367 403 c +1366.309 404.388 1366 404.861 1365 406 c +f +*U +0.000 0.000 0.000 0.345 k +*u +34 405 m +35 404 l +34 405 l +f +*U +0.000 0.361 0.290 0.278 k +*u +1082 405 m +1083 404 l +1082 405 l +f +*U +0.000 0.325 0.235 0.184 k +*u +1101 405 m +1102 404 l +1101 405 l +f +*U +0.000 0.694 0.561 0.306 k +*u +1292 405 m +1292 403 l +1293.635 403.545 1293.455 403.365 1294 405 c +1292 405 l +f +*U +0.000 0.263 0.208 0.259 k +*u +1366 405 m +1367 404 l +1366 405 l +f +*U +0.000 0.000 0.000 0.173 k +*u +2 404 m +3 403 l +2 404 l +f +*U +0.000 0.000 0.000 0.314 k +*u +33 404 m +34 403 l +33 404 l +f +*U +0.000 0.255 0.220 0.094 k +*u +1081 404 m +1082 403 l +1081 404 l +f +*U +0.000 0.545 0.467 0.455 k +*u +1082 404 m +1083 403 l +1082 404 l +f +*U +0.000 0.353 0.255 0.227 k +*u +1100 404 m +1101 403 l +1100 404 l +f +*U +0.000 0.365 0.302 0.635 k +*u +1291 404 m +1292 403 l +1291 404 l +f +*U +0.000 0.733 0.573 0.267 k +*u +1361.667 403.667 m +1361.222 403.222 1362.278 403.278 1362.333 403.333 c +1362.778 403.778 1361.722 403.722 1361.667 403.667 c +f +*U +0.000 0.000 0.000 0.671 k +*u +2 403 m +3 402 l +2 403 l +f +*U +0.000 0.000 0.008 0.792 k +*u +32 403 m +33 402 l +32 403 l +f +*U +0.000 0.400 0.271 0.545 k +*u +1081 403 m +1080 400 l +1083 400 l +1082.309 401.388 1082 401.861 1081 403 c +f +*U +0.000 0.376 0.302 0.424 k +*u +1099 403 m +1100 402 l +1099 403 l +f +*U +0.000 0.612 0.490 0.388 k +*u +1289 400 m +1303 400 l +1300.722 402.278 1294.392 399.965 1291 402 c +1292 403 l +1289.876 402 1289.899 402 1289 400 c +f +*U +0.000 0.686 0.498 0.294 k +*u +1366 403 m +1366.000 400.649 1365.347 401 1363 401 c +1365.388 399.631 1369.689 400.928 1366 403 c +f +*U +0.000 0.412 0.247 0.239 k +*u +1080 402 m +1081 401 l +1080 402 l +f +*U +0.000 0.380 0.286 0.149 k +*u +1288 402 m +1289 401 l +1288 402 l +f +*U +0.000 0.137 0.086 0.369 k +*u +1368 402 m +1369 401 l +1368 402 l +f +*U +0.000 0.000 0.000 0.267 k +*u +31 401 m +32 400 l +31 401 l +f +*U +0.031 0.000 0.016 0.078 k +*u +1078.667 400.667 m +1078.222 400.222 1079.278 400.278 1079.333 400.333 c +1079.778 400.778 1078.722 400.722 1078.667 400.667 c +f +*U +0.000 0.596 0.439 0.400 k +*u +1083 401 m +1087.471 399 1093.183 400 1098 400 c +1093.529 401.876 1087.817 401 1083 401 c +f +*U +0.031 0.000 0.008 0.455 k +*u +1287 401 m +1288 400 l +1287 401 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1288 401 m +1289 400 l +1288 401 l +f +*U +0.000 0.522 0.400 0.447 k +*u +1303 401 m +1308.463 398.708 1316 400 1322 400 c +1363 400 l +1357.537 402.292 1349.887 401 1344 401 c +1303 401 l +f +*U +0.000 0.243 0.161 0.733 k +*u +1368 401 m +1369 400 l +1368 401 l +f +*U +0.000 0.000 0.000 0.545 k +*u +1 400 m +2 399 l +1 400 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1 399 m +2 398 l +1 399 l +f +*U +0.000 0.000 0.000 0.196 k +*u +30 399 m +31 398 l +30 399 l +f +*U +0.000 0.000 0.000 0.831 k +*u +29 398 m +30 397 l +29 398 l +f +*U +0.000 0.000 0.000 0.322 k +*u +29 397 m +30 396 l +29 397 l +f +*U +0.000 0.000 0.000 0.467 k +*u +0 395 m +0 392 l +0.696 393.554 0.696 393.446 0 395 c +f +*U +0.000 0.000 0.000 0.812 k +*u +28 395 m +29 394 l +28 395 l +f +*U +0.000 0.000 0.000 0.306 k +*u +28 394 m +29 393 l +28 394 l +f +*U +0.000 0.000 0.000 0.859 k +*u +0.333 391.333 m +0.278 391.278 0.222 390.222 0.667 390.667 c +0.722 390.722 0.778 391.778 0.333 391.333 c +f +*U +0.000 0.357 0.333 0.149 k +*u +1073 390 m +1077.974 387.913 1084.638 389 1090 389 c +1085 391 1078.362 390 1073 390 c +f +*U +0.000 0.329 0.247 0.192 k +*u +1285 390 m +1287.613 388.902 1290 389 1293 389 c +1290.387 390 1287.835 389.993 1285 390 c +f +*U +0.000 0.192 0.102 0.114 k +*u +1293.333 389.333 m +1293.278 389.278 1293.222 388.222 1293.667 388.667 c +1293.722 388.722 1293.778 389.778 1293.333 389.333 c +f +*U +0.000 0.369 0.329 0.137 k +*u +1295 388 m +1304.222 390.196 1314.559 389 1324 389 c +1376 389 l +1370.293 391.395 1362 390 1356 390 c +1314 390 l +1308.940 390 1298.508 392 1295 388 c +f +*U +0.000 0.000 0.000 0.812 k +*u +27 389 m +27 304 l +29.395 309.707 28 317.846 28 324 c +28 367 l +28 373.686 29.599 382.806 27 389 c +f +*U +0.000 0.875 0.612 0.125 k +*u +1072 389 m +1070 378 l +1083 378 l +1084 382 1086.260 385.235 1088 389 c +1072 389 l +f +*U +0.000 0.325 0.286 0.475 k +*u +1088 389 m +1088 387 l +1089.635 387.545 1089.455 387.365 1090 389 c +1088 389 l +f +*U +0.000 0.224 0.165 0.286 k +*u +1284 389 m +1285 388 l +1284 389 l +f +*U +0.000 0.635 0.514 0.365 k +*u +1285 389 m +1285 384 l +1285.830 386 1285.830 386.970 1285 389 c +f +*U +0.000 0.824 0.627 0.176 k +*u +1286 389 m +1287.506 388.317 1288.315 388.174 1290 388 c +1289.776 386.316 1289.782 385.687 1290 384 c +1291.255 385.751 1291.614 386.857 1292 389 c +1286 389 l +f +*U +0.000 0.490 0.478 0.510 k +*u +1292 389 m +1293 388 l +1292 389 l +f +*U +0.000 0.678 0.475 0.322 k +*u +1296 389 m +1296.477 385.223 1296 379.552 1299 377 c +1298 381 1298.405 385.480 1296 389 c +f +*U +0.000 0.831 0.643 0.169 k +*u +1297 387 m +1305.923 389 1315.866 388 1325 388 c +1376 388 l +1370.537 390.292 1362.887 389 1357 389 c +1316 389 l +1310.940 389 1300.508 391 1297 387 c +f +*U +0.000 0.165 0.114 0.204 k +*u +1376 389 m +1377 388 l +1376 389 l +f +*U +0.000 0.259 0.192 0.082 k +*u +1284 388 m +1285 387 l +1284 388 l +f +*U +0.000 0.882 0.620 0.118 k +*u +1286 388 m +1285 379 l +1283.814 380 1283.396 380.339 1282 381 c +1282.576 378.313 1284.968 376.798 1287.361 379.333 c +1289.461 381.558 1289.624 385 1290 388 c +1286 388 l +f +*U +0.000 0.341 0.302 0.243 k +*u +1292 388 m +1293 387 l +1292 388 l +f +*U +0.000 0.859 0.620 0.141 k +*u +1298 388 m +1299 382 l +1303 384 l +1303.640 378.907 1315.759 381 1320 381 c +1376 381 l +1369.564 383.701 1359.951 382 1353 382 c +1304 382 l +1311.717 384.281 1320.982 383 1329 383 c +1378 383 l +1374.413 390.540 1364.181 388 1357 388 c +1298 388 l +f +*U +0.000 0.565 0.427 0.435 k +*u +1376.333 387.333 m +1376.278 387.278 1376.222 386.222 1376.667 386.667 c +1376.722 386.722 1376.777 387.778 1376.333 387.333 c +f +*U +0.000 0.337 0.216 0.373 k +*u +1071 387 m +1072 386 l +1071 387 l +f +*U +0.000 0.588 0.451 0.412 k +*u +1086 387 m +1086 385 l +1087.635 385.545 1087.455 385.365 1088 387 c +1086 387 l +f +*U +0.000 0.388 0.290 0.122 k +*u +1377 387 m +1378 386 l +1377 387 l +f +*U +0.000 0.290 0.196 0.043 k +*u +1070 386 m +1071 385 l +1070 386 l +f +*U +0.000 0.667 0.447 0.333 k +*u +1071.333 385.333 m +1071.278 385.278 1071.222 384.222 1071.667 384.667 c +1071.722 384.723 1071.777 385.778 1071.333 385.333 c +f +*U +0.000 0.408 0.306 0.263 k +*u +1087 386 m +1088 385 l +1087 386 l +f +*U +0.000 0.278 0.188 0.106 k +*u +1291 386 m +1292 385 l +1291 386 l +f +*U +0.000 0.498 0.400 0.133 k +*u +1296 386 m +1297 385 l +1296 386 l +f +*U +0.000 0.620 0.459 0.380 k +*u +1377.333 385.333 m +1377.278 385.278 1377.222 384.222 1377.667 384.667 c +1377.722 384.723 1377.777 385.778 1377.333 385.333 c +f +*U +0.000 0.333 0.224 0.341 k +*u +1070 385 m +1071 384 l +1070 385 l +f +*U +0.000 0.435 0.333 0.420 k +*u +1085.667 384.667 m +1085.222 384.222 1086.278 384.278 1086.333 384.333 c +1086.778 384.778 1085.722 384.722 1085.667 384.667 c +f +*U +0.000 0.114 0.090 0.271 k +*u +1284 385 m +1285 384 l +1284 385 l +f +*U +0.000 0.404 0.369 0.004 k +*u +1296 385 m +1297 384 l +1296 385 l +f +*U +0.000 0.196 0.157 0.290 k +*u +1378 385 m +1379 384 l +1378 385 l +f +*U +0.000 0.396 0.263 0.000 k +*u +1069 384 m +1070 383 l +1069 384 l +f +*U +0.000 0.800 0.596 0.200 k +*u +1070 384 m +1069 381 1068.635 379 1071 377 c +1070 384 l +f +*U +0.000 0.698 0.522 0.302 k +*u +1084 384 m +1084 381 l +1084.696 382.554 1084.696 382.446 1084 384 c +f +*U +0.000 0.349 0.298 0.651 k +*u +1085 384 m +1086 383 l +1085 384 l +f +*U +0.000 0.086 0.075 0.169 k +*u +1086 384 m +1087 383 l +1086 384 l +f +*U +0.000 0.773 0.600 0.227 k +*u +1283 384 m +1281.511 381.696 1280 379.503 1279 377 c +1282.306 377 1285.727 376.399 1288 379 c +1284.966 378.476 1283.720 378.400 1282 381 c +1285 379 l +1285.481 381.201 1285.481 381.799 1285 384 c +1283 384 l +f +*U +0.000 0.620 0.522 0.345 k +*u +1289 384 m +1288 380 l +1289.303 381.668 1289.553 381.992 1289 384 c +f +*U +0.000 0.412 0.318 0.318 k +*u +1290 384 m +1291 383 l +1290 384 l +f +*U +0.000 0.890 0.627 0.106 k +*u +1298 384 m +1298 378 l +1378 378 l +1378 383 l +1304 383 l +1310.436 380.299 1320 382 1327 382 c +1376 382 l +1370.309 379.919 1363 381 1357 381 c +1320 381 l +1315.950 381 1303.743 378.929 1303 384 c +1300.987 383.499 1299.961 383.363 1298 384 c +f +*U +0.000 0.612 0.580 0.337 k +*u +1378.333 383.333 m +1378.278 383.278 1378.222 382.222 1378.667 382.667 c +1378.722 382.722 1378.778 383.778 1378.333 383.333 c +f +*U +0.000 0.353 0.255 0.247 k +*u +1085 383 m +1086 382 l +1085 383 l +f +*U +0.000 0.388 0.310 0.612 k +*u +1282 383 m +1283 382 l +1282 383 l +f +*U +0.000 0.329 0.271 0.051 k +*u +1290 383 m +1291 382 l +1290 383 l +f +*U +0.000 0.184 0.141 0.337 k +*u +1379 383 m +1380 382 l +1379 383 l +f +*U +0.000 0.286 0.216 0.051 k +*u +1068 382 m +1069 381 l +1068 382 l +f +*U +0.000 0.863 0.671 0.137 k +*u +1378 382 m +1378 378 l +1299 378 l +1305.436 375.299 1315 377 1322 377 c +1359 377 l +1365.834 377 1373.416 376 1380 378 c +1379.436 379.752 1379 380.542 1378 382 c +f +*U +0.000 0.678 0.518 0.322 k +*u +1379.333 381.333 m +1379.278 381.278 1379.222 380.222 1379.667 380.667 c +1379.722 380.722 1379.778 381.778 1379.333 381.333 c +f +*U +0.000 0.698 0.561 0.302 k +*u +1068 381 m +1068 377 l +1068.710 378.759 1068.710 379.241 1068 381 c +f +*U +0.000 0.443 0.318 0.431 k +*u +1083.333 380.333 m +1083.278 380.278 1083.222 379.222 1083.667 379.667 c +1083.722 379.723 1083.777 380.778 1083.333 380.333 c +f +*U +0.000 0.302 0.220 0.224 k +*u +1084 381 m +1085 380 l +1084 381 l +f +*U +0.000 0.396 0.263 0.192 k +*u +1280 381 m +1281 380 l +1280 381 l +f +*U +0.000 0.325 0.298 0.188 k +*u +1289 381 m +1290 380 l +1289 381 l +f +*U +0.000 0.239 0.145 0.051 k +*u +1296 381 m +1297 380 l +1296 381 l +f +*U +0.000 0.439 0.275 0.145 k +*u +1380 381 m +1381 380 l +1380 381 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1288 380 m +1289 379 l +1288 380 l +f +*U +0.000 0.294 0.192 0.290 k +*u +1296 380 m +1297 379 l +1296 380 l +f +*U +0.000 0.667 0.459 0.333 k +*u +1380 380 m +1379 377 l +1380.766 377.979 1380.956 378.222 1380 380 c +f +*U +0.000 0.361 0.278 0.373 k +*u +1067 379 m +1068 378 l +1067 379 l +f +*U +0.000 0.275 0.200 0.122 k +*u +1083 379 m +1084 378 l +1083 379 l +f +*U +0.000 0.227 0.243 0.400 k +*u +1279 379 m +1280 378 l +1279 379 l +f +*U +0.000 0.204 0.192 0.573 k +*u +1288 379 m +1289 378 l +1288 379 l +f +*U +0.000 0.365 0.325 0.635 k +*u +1296.333 378.333 m +1296.278 378.278 1296.222 377.222 1296.667 377.667 c +1296.723 377.723 1296.777 378.778 1296.333 378.333 c +f +*U +0.000 0.231 0.282 0.224 k +*u +1381 379 m +1382 378 l +1381 379 l +f +*U +0.000 0.396 0.369 0.604 k +*u +1067 378 m +1068 377 l +1067 378 l +f +*U +0.000 0.729 0.584 0.271 k +*u +1071 378 m +1074.698 376.448 1079 377 1083 377 c +1079.302 378.552 1074.983 378 1071 378 c +f +*U +0.000 0.227 0.231 0.173 k +*u +1278 378 m +1279 377 l +1278 378 l +f +*U +0.000 0.341 0.369 0.518 k +*u +1381.333 377.333 m +1381.278 377.278 1381.222 376.222 1381.667 376.667 c +1381.722 376.722 1381.777 377.778 1381.333 377.333 c +f +*U +0.008 0.000 0.039 0.235 k +*u +1066 377 m +1067 376 l +1066 377 l +f +*U +0.000 0.345 0.290 0.271 k +*u +1067 377 m +1068 376 l +1067 377 l +f +*U +0.000 0.345 0.337 0.141 k +*u +1068 377 m +1072.217 375.231 1077.459 376 1082 376 c +1077.783 377.769 1072.541 377 1068 377 c +f +*U +0.000 0.075 0.075 0.141 k +*u +1082 377 m +1083 376 l +1082 377 l +f +*U +0.000 0.078 0.098 0.200 k +*u +1277 377 m +1278 376 l +1277 377 l +f +*U +0.000 0.514 0.420 0.059 k +*u +1278 377 m +1280 376 1281.747 376 1284 376 c +1281.948 376.874 1280.253 376.953 1278 377 c +f +*U +0.000 0.224 0.251 0.192 k +*u +1284 377 m +1285.506 376.317 1286.315 376.174 1288 376 c +1286.494 376.683 1285.685 376.826 1284 377 c +f +*U +0.000 0.408 0.376 0.114 k +*u +1296 377 m +1303 373.996 1314.256 376 1322 376 c +1381 376 l +1373.841 379 1362.744 377 1355 377 c +1296 377 l +f +*U +0.000 0.051 0.055 0.212 k +*u +1061 366 m +1062 365 l +1061 366 l +f +*U +0.000 0.314 0.231 0.306 k +*u +1062 366 m +1063 365 l +1062 366 l +f +*U +0.000 0.388 0.278 0.451 k +*u +1063 366 m +1064 365 l +1063 366 l +f +*U +0.000 0.420 0.306 0.251 k +*u +1064 366 m +1067.432 364.560 1071.300 365 1075 365 c +1071.568 366.440 1067.700 366 1064 366 c +f +*U +0.000 0.204 0.157 0.592 k +*u +1075 366 m +1076 365 l +1075 366 l +f +*U +0.000 0.373 0.251 0.278 k +*u +1262 366 m +1269 362.998 1278.342 365.823 1286 364 c +1282 368.565 1267.868 366 1262 366 c +f +*U +0.000 0.169 0.122 0.188 k +*u +1292 366 m +1293 365 l +1292 366 l +f +*U +0.000 0.373 0.251 0.278 k +*u +1293 366 m +1300.879 362.694 1313.466 365 1322 365 c +1387 365 l +1379 368.306 1366.534 366 1358 366 c +1293 366 l +f +*U +0.000 0.333 0.239 0.298 k +*u +1061 365 m +1062 364 l +1061 365 l +f +*U +0.000 0.886 0.639 0.114 k +*u +1062 365 m +1060.848 361.339 1059.742 357.774 1059 354 c +1067.597 354 1073 355.555 1075 365 c +1062 365 l +f +*U +0.000 0.400 0.365 0.600 k +*u +1075 365 m +1076 364 l +1075 365 l +f +*U +0.000 0.267 0.208 0.145 k +*u +1261.333 364.333 m +1261.278 364.278 1261.222 363.222 1261.667 363.667 c +1261.723 363.723 1261.777 364.778 1261.333 364.333 c +f +*U +0.000 0.871 0.604 0.125 k +*u +1262 365 m +1259.401 357.925 1251.946 358.723 1246 361 c +1241 354 l +1256.413 352.714 1272.503 354 1288 354 c +1384 354 l +1379.785 355.769 1374.536 355 1370 355 c +1343 355 l +1248 355 l +1253.436 356.607 1259.360 356 1265 356 c +1292 356 l +1384 356 l +1379.785 357.769 1374.536 357 1370 357 c +1344 357 l +1252 357 l +1266.222 361.322 1283.269 359 1298 359 c +1384 359 l +1378.697 362.618 1369.285 360 1363 360 c +1310 360 l +1302.427 360 1289.233 357.173 1285 365 c +1262 365 l +f +*U +0.000 0.251 0.188 0.090 k +*u +1291 365 m +1292 364 l +1291 365 l +f +*U +0.000 0.714 0.510 0.286 k +*u +1291 363 m +1292.580 363.683 1292.777 363.805 1294 365 c +1292.420 364.316 1292.223 364.195 1291 363 c +f +*U +0.000 0.839 0.584 0.161 k +*u +1294 363 m +1308.271 366.398 1325.354 364 1340 364 c +1354.951 364 1372.432 366.468 1387 363 c +1383.394 367 1372.217 365 1367 365 c +1313 365 l +1307.940 365 1297.508 367 1294 363 c +f +*U +0.000 0.243 0.184 0.122 k +*u +1387 365 m +1388 364 l +1387 365 l +f +*U +0.000 0.498 0.396 0.502 k +*u +1061.333 363.333 m +1061.278 363.278 1061.222 362.222 1061.667 362.667 c +1061.722 362.722 1061.777 363.778 1061.333 363.333 c +f +*U +0.000 0.341 0.271 0.243 k +*u +1075 364 m +1076 363 l +1075 364 l +f +*U +0.000 0.067 0.067 0.176 k +*u +1088 364 m +1089 363 l +1088 364 l +f +*U +0.000 0.196 0.153 0.208 k +*u +1245 364 m +1246 363 l +1245 364 l +f +*U +0.000 0.694 0.561 0.306 k +*u +1285 364 m +1285.980 362.217 1285.908 362.406 1288 362 c +1286.861 363 1286.388 363.309 1285 364 c +f +*U +0.000 0.290 0.278 0.333 k +*u +1286 364 m +1287 363 l +1286 364 l +f +*U +0.000 0.318 0.227 0.149 k +*u +1290 364 m +1291 363 l +1290 364 l +f +*U +0.000 0.875 0.631 0.114 k +*u +1288 361 m +1295 357.996 1306.256 360 1314 360 c +1361 360 l +1368.555 360 1376.591 361.314 1384 360 c +1371.804 356.395 1355.711 359 1343 359 c +1259 359 l +1262.959 357.339 1267.740 358 1272 358 c +1297 358 l +1384 358 l +1384 354 l +1388 354 l +1386 357 l +1387.479 356 1387.203 356 1389 356 c +1386.575 367 1375 364 1366 364 c +1316 364 l +1306.514 364 1296.677 365.344 1288 361 c +f +*U +0.000 0.537 0.392 0.463 k +*u +1387.333 363.333 m +1387.278 363.278 1387.222 362.222 1387.667 362.667 c +1387.722 362.722 1387.777 363.778 1387.333 363.333 c +f +*U +0.000 0.200 0.141 0.067 k +*u +1060 363 m +1061 362 l +1060 363 l +f +*U +0.000 0.282 0.220 0.424 k +*u +1088 363 m +1089 362 l +1088 363 l +f +*U +0.000 0.204 0.169 0.133 k +*u +1089 363 m +1090 362 l +1089 363 l +f +*U +0.000 0.325 0.318 0.675 k +*u +1245 363 m +1246 362 l +1245 363 l +f +*U +0.000 0.706 0.533 0.294 k +*u +1246 363 m +1244.602 360.950 1243.749 359.354 1243 357 c +1244.867 358.548 1246.438 360 1248 362 c +1246 363 l +f +*U +0.000 0.349 0.271 0.322 k +*u +1261 363 m +1262 362 l +1261 363 l +f +*U +0.000 0.392 0.278 0.361 k +*u +1288 363 m +1289 362 l +1288 363 l +f +*U +0.000 0.753 0.569 0.247 k +*u +1288 361 m +1289.580 361.683 1289.777 361.805 1291 363 c +1289.420 362.316 1289.223 362.195 1288 361 c +f +*U +0.000 0.400 0.275 0.184 k +*u +1060 362 m +1061 361 l +1060 362 l +f +*U +0.000 0.420 0.286 0.251 k +*u +1074 362 m +1075 361 l +1074 362 l +f +*U +0.000 0.424 0.329 0.506 k +*u +1088 362 m +1088 360 l +1090 360 l +1090 362 l +1088 362 l +f +*U +0.000 0.255 0.192 0.149 k +*u +1244 362 m +1245 361 l +1244 362 l +f +*U +0.000 0.341 0.267 0.200 k +*u +1260 362 m +1261 361 l +1260 362 l +f +*U +0.000 0.306 0.224 0.047 k +*u +1388 362 m +1389 361 l +1388 362 l +f +*U +0.000 0.251 0.196 0.227 k +*u +1090 361 m +1091 360 l +1090 361 l +f +*U +0.000 0.365 0.235 0.604 k +*u +1248 361 m +1249 360 l +1248 361 l +f +*U +0.000 0.306 0.200 0.286 k +*u +1249 361 m +1250 360 l +1249 361 l +f +*U +0.000 0.169 0.110 0.098 k +*u +1250 361 m +1251 360 l +1250 361 l +f +*U +0.000 0.255 0.176 0.322 k +*u +1258 361 m +1259 360 l +1258 361 l +f +*U +0.000 0.714 0.580 0.286 k +*u +1259.667 360.667 m +1259.222 360.222 1260.278 360.278 1260.333 360.333 c +1260.778 360.778 1259.722 360.722 1259.667 360.667 c +f +*U +0.000 0.467 0.325 0.306 k +*u +1388 361 m +1389 360 l +1388 361 l +f +*U +0.000 0.290 0.216 0.055 k +*u +1059 360 m +1060 359 l +1059 360 l +f +*U +0.000 0.655 0.510 0.345 k +*u +1072 360 m +1069.176 353.787 1065.243 354 1059 354 c +1063.989 351.907 1074 352.287 1072 360 c +f +*U +0.000 0.247 0.176 0.310 k +*u +1073 360 m +1074 359 l +1073 360 l +f +*U +0.153 0.004 0.000 0.196 k +*u +1087 360 m +1088 359 l +1087 360 l +f +*U +0.000 0.843 0.647 0.157 k +*u +1088 360 m +1088 356 l +1092 356 l +1091 360 l +1088 360 l +f +*U +0.000 0.318 0.204 0.118 k +*u +1243 360 m +1244 359 l +1243 360 l +f +*U +0.000 0.671 0.537 0.329 k +*u +1248 360 m +1250.613 358.902 1253 359 1256 359 c +1253.387 360 1250.836 359.993 1248 360 c +f +*U +0.000 0.502 0.463 0.498 k +*u +1388.333 359.333 m +1388.278 359.278 1388.222 358.222 1388.667 358.667 c +1388.722 358.722 1388.778 359.778 1388.333 359.333 c +f +*U +0.000 0.420 0.294 0.278 k +*u +1059 359 m +1060 358 l +1059 359 l +f +*U +0.000 0.337 0.235 0.055 k +*u +1073 359 m +1074 358 l +1073 359 l +f +*U +0.000 0.220 0.259 0.239 k +*u +1087 359 m +1088 358 l +1087 359 l +f +*U +0.000 0.592 0.471 0.408 k +*u +1091.333 358.333 m +1091.278 358.278 1091.222 357.222 1091.667 357.667 c +1091.722 357.723 1091.777 358.778 1091.333 358.333 c +f +*U +0.000 0.192 0.188 0.278 k +*u +1389 359 m +1390 358 l +1389 359 l +f +*U +0.000 0.639 0.498 0.361 k +*u +1059.333 357.333 m +1059.278 357.278 1059.222 356.222 1059.667 356.667 c +1059.722 356.722 1059.777 357.778 1059.333 357.333 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1087.333 357.333 m +1087.278 357.278 1087.222 356.222 1087.667 356.667 c +1087.722 356.722 1087.777 357.778 1087.333 357.333 c +f +*U +0.000 0.443 0.294 0.004 k +*u +1092 358 m +1093 357 l +1092 358 l +f +*U +0.000 0.349 0.247 0.180 k +*u +1242 358 m +1243 357 l +1242 358 l +f +*U +0.000 0.824 0.620 0.153 k +*u +1252 358 m +1256.215 356.231 1261.465 357 1266 357 c +1292 357 l +1384 357 l +1379.785 358.769 1374.536 358 1370 358 c +1344 358 l +1252 358 l +f +*U +0.000 0.427 0.380 0.329 k +*u +1389 358 m +1390 357 l +1389 358 l +f +*U +0.000 0.337 0.204 0.000 k +*u +1058 357 m +1059 356 l +1058 357 l +f +*U +0.000 0.102 0.067 0.180 k +*u +1072 357 m +1073 356 l +1072 357 l +f +*U +0.000 0.478 0.384 0.224 k +*u +1086 357 m +1087 356 l +1086 357 l +f +*U +0.000 0.455 0.294 0.275 k +*u +1092 357 m +1093 356 l +1092 357 l +f +*U +0.000 0.035 0.067 0.153 k +*u +1210 357 m +1211 356 l +1210 357 l +f +*U +0.000 0.424 0.306 0.278 k +*u +1211.667 356.667 m +1211.222 356.222 1212.278 356.278 1212.333 356.333 c +1212.778 356.778 1211.722 356.722 1211.667 356.667 c +f +*U +0.000 0.592 0.592 0.408 k +*u +1213 357 m +1215 353 l +1215.683 354.506 1215.826 355.315 1216 357 c +1213 357 l +f +*U +0.012 0.149 0.000 0.208 k +*u +1239 357 m +1240 356 l +1239 357 l +f +*U +0.000 0.588 0.373 0.412 k +*u +1240 357 m +1241.249 356.315 1241.548 356.251 1243 356 c +1241.752 356.685 1241.452 356.749 1240 357 c +f +*U +0.000 0.898 0.537 0.102 k +*u +1386 357 m +1386.901 355 1387 355 1389 354 c +1388 355.923 1387.924 355.999 1386 357 c +f +*U +0.000 0.655 0.384 0.345 k +*u +1389 357 m +1389.406 354.908 1389.217 354.980 1391 354 c +1390.309 355.388 1390 355.861 1389 357 c +f +*U +0.000 0.255 0.094 0.118 k +*u +1390.333 356.333 m +1390.278 356.278 1390.222 355.222 1390.667 355.667 c +1390.722 355.722 1390.777 356.778 1390.333 356.333 c +f +*U +0.000 0.416 0.282 0.286 k +*u +1058 356 m +1059 355 l +1058 356 l +f +*U +0.000 0.122 0.176 0.220 k +*u +1082.667 355.667 m +1082.222 355.222 1083.278 355.278 1083.333 355.333 c +1083.778 355.778 1082.722 355.722 1082.667 355.667 c +f +*U +0.000 0.345 0.247 0.290 k +*u +1084 356 m +1085 355 l +1084 356 l +f +*U +0.000 0.686 0.514 0.314 k +*u +1085.667 355.667 m +1085.222 355.222 1086.278 355.278 1086.333 355.333 c +1086.778 355.778 1085.722 355.722 1085.667 355.667 c +f +*U +0.000 0.910 0.651 0.090 k +*u +1085 355 m +1086.506 354.317 1087.315 354.174 1089 354 c +1087.276 355 1087 355 1085 355 c +f +*U +0.000 0.678 0.482 0.216 k +*u +1088 356 m +1089.223 354.805 1089.420 354.684 1091 354 c +1090 355.783 1090 355.594 1088 356 c +f +*U +0.000 0.478 0.329 0.522 k +*u +1091 356 m +1091 353 l +1091.696 354.554 1091.696 354.446 1091 356 c +f +*U +0.000 0.263 0.153 0.067 k +*u +1092 356 m +1093 355 l +1092 356 l +f +*U +0.000 0.125 0.051 0.110 k +*u +1207 356 m +1208 355 l +1207 356 l +f +*U +0.000 0.898 0.643 0.102 k +*u +1208 356 m +1209.926 353.792 1212 354 1215 354 c +1215 356 l +1208 356 l +f +*U +0.000 0.620 0.518 0.380 k +*u +1209.667 355.667 m +1209.222 355.222 1210.278 355.278 1210.333 355.333 c +1210.778 355.778 1209.722 355.722 1209.667 355.667 c +f +*U +0.000 0.161 0.235 0.263 k +*u +1231 356 m +1232 355 l +1231 356 l +f +*U +0.000 0.475 0.380 0.478 k +*u +1232 356 m +1233 355 l +1232 356 l +f +*U +0.000 0.365 0.443 0.149 k +*u +1233 356 m +1234.248 355.315 1234.548 355.251 1236 355 c +1234.751 355.685 1234.452 355.749 1233 356 c +f +*U +0.000 0.467 0.302 0.059 k +*u +1236.667 355.667 m +1236.222 355.222 1237.278 355.278 1237.333 355.333 c +1237.778 355.778 1236.722 355.722 1236.667 355.667 c +f +*U +0.000 0.537 0.482 0.447 k +*u +1238.667 355.667 m +1238.222 355.222 1239.278 355.278 1239.333 355.333 c +1239.778 355.778 1238.722 355.722 1238.667 355.667 c +f +*U +0.000 0.714 0.502 0.286 k +*u +1240 356 m +1240.654 352.946 1242 353 1245 353 c +1241 355 l +1242 356 l +1240 356 l +f +*U +0.000 0.878 0.671 0.122 k +*u +1248 356 m +1252.215 354.231 1257.465 355 1262 355 c +1289 355 l +1384 355 l +1379.785 356.769 1374.536 356 1370 356 c +1343 356 l +1248 356 l +f +*U +0.000 0.361 0.361 0.639 k +*u +1058.333 354.333 m +1058.278 354.278 1058.222 353.222 1058.667 353.667 c +1058.722 353.722 1058.777 354.778 1058.333 354.333 c +f +*U +0.000 0.518 0.341 0.176 k +*u +1071 355 m +1072 354 l +1071 355 l +f +*U +0.000 0.208 0.165 0.027 k +*u +1079 355 m +1080 354 l +1079 355 l +f +*U +0.000 0.698 0.620 0.302 k +*u +1080 353 m +1091 353 l +1087.676 354.492 1082.641 355.976 1080 353 c +f +*U +0.000 0.208 0.137 0.067 k +*u +1204 355 m +1205 354 l +1204 355 l +f +*U +0.000 0.467 0.325 0.200 k +*u +1205 355 m +1206 354 l +1205 355 l +f +*U +0.000 0.780 0.635 0.220 k +*u +1206.667 354.667 m +1206.222 354.222 1207.278 354.278 1207.333 354.333 c +1207.778 354.778 1206.722 354.722 1206.667 354.667 c +f +*U +0.000 0.800 0.686 0.200 k +*u +1229 355 m +1230.223 353.805 1230.420 353.684 1232 353 c +1231 354.783 1231 354.594 1229 355 c +f +*U +0.000 0.741 0.784 0.196 k +*u +1232 353 m +1236 354 l +1233.954 354.751 1233.404 354.656 1232 353 c +f +*U +0.000 0.706 0.686 0.294 k +*u +1233 354 m +1235.332 353 1237.457 353 1240 353 c +1237.557 354.530 1235.855 354.392 1233 354 c +f +*U +0.000 0.831 0.776 0.149 k +*u +1238.667 354.667 m +1238.222 354.222 1239.278 354.278 1239.333 354.333 c +1239.778 354.778 1238.722 354.722 1238.667 354.667 c +f +*U +0.000 0.251 0.192 0.110 k +*u +1057 354 m +1058 353 l +1057 354 l +f +*U +0.000 0.357 0.216 0.102 k +*u +1071 354 m +1072 353 l +1071 354 l +f +*U +0.000 0.192 0.161 0.243 k +*u +1077 354 m +1078 353 l +1077 354 l +f +*U +0.000 0.400 0.361 0.600 k +*u +1078.667 353.667 m +1078.222 353.222 1079.278 353.278 1079.333 353.333 c +1079.778 353.778 1078.722 353.722 1078.667 353.667 c +f +*U +0.000 0.800 0.580 0.200 k +*u +1081.667 353.667 m +1081.222 353.222 1082.278 353.278 1082.333 353.333 c +1082.778 353.778 1081.722 353.722 1081.667 353.667 c +f +*U +0.000 0.047 0.031 0.192 k +*u +1092 354 m +1093 353 l +1092 354 l +f +*U +0.000 0.110 0.231 0.114 k +*u +1202 354 m +1203 353 l +1202 354 l +f +*U +0.000 0.365 0.365 0.635 k +*u +1203.667 353.667 m +1203.222 353.222 1204.278 353.278 1204.333 353.333 c +1204.778 353.778 1203.722 353.722 1203.667 353.667 c +f +*U +0.000 0.659 0.514 0.341 k +*u +1205 354 m +1208 352.673 1211.586 353 1215 353 c +1211.837 354.327 1208.415 354.000 1205 354 c +f +*U +0.000 0.145 0.114 0.263 k +*u +1227 354 m +1228 353 l +1227 354 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1228.667 353.667 m +1228.222 353.222 1229.278 353.278 1229.333 353.333 c +1229.778 353.778 1228.722 353.722 1228.667 353.667 c +f +*U +0.000 0.671 0.702 0.298 k +*u +1246 354 m +1250.215 352.231 1255.464 353 1260 353 c +1289 353 l +1390 353 l +1385.785 354.769 1380.536 354 1376 354 c +1347 354 l +1246 354 l +f +*U +0.000 0.345 0.345 0.655 k +*u +1390 354 m +1391 353 l +1390 354 l +f +*U +0.020 0.000 0.000 0.282 k +*u +1069.667 352.667 m +1069.222 352.222 1070.278 352.278 1070.333 352.333 c +1070.778 352.778 1069.722 352.722 1069.667 352.667 c +f +*U +0.082 0.000 0.082 0.129 k +*u +1081 353 m +1082 352 l +1081 353 l +f +*U +0.000 0.196 0.145 0.125 k +*u +1203.667 352.667 m +1203.222 352.222 1204.278 352.278 1204.333 352.333 c +1204.778 352.778 1203.722 352.722 1203.667 352.667 c +f +*U +0.000 0.271 0.153 0.094 k +*u +1213 353 m +1214.249 352.315 1214.548 352.251 1216 352 c +1214.752 352.685 1214.452 352.749 1213 353 c +f +*U +0.000 0.114 0.106 0.192 k +*u +1229.667 352.667 m +1229.222 352.222 1230.278 352.278 1230.333 352.333 c +1230.778 352.778 1229.722 352.722 1229.667 352.667 c +f +*U +0.000 0.302 0.125 0.067 k +*u +1388 353 m +1389.248 352.315 1389.548 352.251 1391 352 c +1389.752 352.685 1389.451 352.749 1388 353 c +f +*U +0.000 0.000 0.000 0.075 k +*u +38 344 m +38 342 l +248 342 l +248 328 l +169 328 l +169 308 l +171 308 l +171 326 l +221 326 l +228.998 326 238 324.805 245.941 326 c +251 327 252 340 248.397 342.972 c +245 345.544 236.929 344 233 344 c +193 344 l +38 344 l +f +*U +0.000 0.000 0.000 0.067 k +*u +283 344 m +283 342 l +303 342 324 340.473 344 343 c +338.293 345.395 330 344 324 344 c +283 344 l +f +*U +0.000 0.000 0.000 0.075 k +*u +381 344 m +381 342 l +402 342 l +402 317 l +402 313.346 400.779 308.904 405 308 c +403.315 310.695 404 313.738 404 317 c +404 334 l +404 336.397 405 341.905 402.833 343.500 c +401.413 344.522 398.639 344 397 344 c +381 344 l +f +*U +0.000 0.000 0.000 0.067 k +*u +476 344 m +476 342 l +498 342 l +498 344 l +476 344 l +f +*U +0.000 0.000 0.000 0.055 k +*u +523 344 m +525.431 341.218 529.491 342 533 342 c +533 344 l +523 344 l +f +*U +0.000 0.000 0.000 0.075 k +*u +613 343 m +619.202 340.397 628.298 342 635 342 c +635 344 l +627.863 344 619.871 345 613 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +658 256 m +661 263.399 659 274.993 659 283 c +659 342 l +663.930 342 673.587 340 677 344 c +672.386 343.703 661.217 346.237 658 342.258 c +656.459 340.299 657.287 337.229 657.576 335 c +658.219 330 658 324.999 658 320 c +658 256 l +f +*U +0.000 0.000 0.000 0.075 k +*u +723 344 m +728.261 340.406 736.835 342 743 342 c +791 342 l +783.828 345 774.666 344 767 344 c +723 344 l +f +855 339 m +861.361 343.592 871.617 342.758 879 341 c +878.203 344.720 875.390 344 872 344 c +866.888 344 855 346 855 339 c +f +*U +0.000 0.000 0.000 0.067 k +*u +937 344 m +937 342 l +958 342 l +958 271 l +960 271 l +960 325 l +960 329 961.939 340.167 958.397 342.972 c +956.719 344.301 953.992 343.986 952 343.999 c +937 344 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1424 343 m +1429.281 338.999 1439.557 341 1446 341 c +1446 305 l +1450 307 l +1445 318.691 1451.483 332.607 1446 344 c +1438.638 343 1431.415 343 1424 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1503 342 m +1509.638 339.215 1523 339.975 1530 342 c +1523.242 344.909 1509.979 344 1503 342 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1943 343 m +1948.750 338.644 1958 341.897 1965 339 c +1963 344 l +1956.487 342.449 1949.659 343 1943 343 c +f +*U +0.000 0.000 0.000 0.161 k +*u +268 341 m +272.467 339.644 278.216 341.960 283 342 c +278 344 272.854 342.539 268 341 c +f +*U +0.000 0.000 0.000 0.133 k +*u +340 343 m +343 341.673 346.586 342 350 342 c +346.837 343.327 343.414 343.000 340 343 c +f +*U +0.000 0.000 0.000 0.141 k +*u +380 343 m +380 254 l +402 254 l +396.639 256.249 386.863 252.344 382.603 256.603 c +378.748 260.459 381 272.899 381 278 c +381 324 l +381 329.509 382.740 338.261 380 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +519 343 m +520.934 332.581 520 321.567 520 311 c +520 256 l +522.802 262.678 521 272.785 521 280 c +521 320 l +521 327.591 520.233 335.578 522 343 c +519 343 l +f +*U +0.000 0.000 0.000 0.157 k +*u +533.667 342.667 m +533.222 342.222 534.278 342.278 534.333 342.333 c +534.778 342.778 533.722 342.722 533.667 342.667 c +f +*U +0.000 0.000 0.000 0.075 k +*u +678 343 m +680.338 333.181 679 322 679 312 c +679 256 l +681 256 l +681 321 l +681 327 683.405 339.182 678 343 c +f +*U +0.000 0.000 0.000 0.137 k +*u +716 343 m +718.890 341.787 721.874 342 725 342 c +722 343.213 719 342.998 716 343 c +f +*U +0.000 0.000 0.000 0.129 k +*u +936 343 m +936 277 l +936 271.319 933.549 257.889 938 254 c +936.473 262.226 937 270.661 937 279 c +937 318 l +937 322.989 936.823 328 937 333 c +937.204 336.798 938.331 339.800 936 343 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1541 333 m +1552.458 342.259 1563.919 341 1578 341 c +1632 341 l +1632 343 l +1609 343 1585.778 344.470 1563 342.910 c +1555.191 342.376 1543.470 341.855 1541 333 c +f +1678 342 m +1684.678 339.198 1694.784 341 1702 341 c +1740 341 l +1746.834 341 1754.416 340 1761 342 c +1754.322 344.802 1744.216 343 1737 343 c +1700 343 l +1692.719 343 1685 343.695 1678 342 c +f +1798 342 m +1805.639 338.794 1817.729 341 1826 341 c +1873 341 l +1880.722 341 1889.565 339.802 1897 342 c +1889 345.306 1876.534 343 1868 343 c +1823 343 l +1814.790 343 1806 343.910 1798 342 c +f +*U +0.000 0.000 0.000 0.149 k +*u +37 342 m +37 328 l +38.667 331.972 38.667 338 37 342 c +f +*U +0.000 0.000 0.000 0.843 k +*u +38 342 m +38 328 l +39.667 331.972 39.667 338 38 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +39 342 m +39 328 l +84 328 l +84 255 l +104 255 l +104 328 l +147 328 l +147 342 l +39 342 l +f +*U +0.000 0.000 0.000 0.502 k +*u +147 342 m +147 328 l +148.796 332.279 147.909 337.419 149 342 c +147 342 l +f +*U +0.000 0.000 0.000 1.000 k +*u +149 342 m +149 255 l +249 255 l +249 269 l +169 269 l +169 296 l +166.727 292.523 167.889 288.994 167.985 285 c +168 277.977 167.882 270.994 168 264 c +194.536 265.978 221.374 265 248 265 c +247.971 262.575 248.282 259.481 246.397 257.603 c +242.527 253.750 230 256 225 256 c +152 256 l +152 305 l +152 309.955 153.774 319.380 150 323 c +152.697 326.851 152 331.439 152 336 c +247 336 l +247 329 l +168 329 l +168 323.686 168.242 318.306 167.911 313 c +167.774 310.792 166.850 307.834 168.357 305.898 c +170.552 303 176.906 305 180 305 c +191.999 304.932 204 305 216 305 c +216 296 l +170 296 l +170 294 l +217 294 l +217 307 l +169 307 l +169 328 l +248 328 l +248 342 l +149 342 l +f +*U +0.000 0.000 0.000 0.565 k +*u +275 342 m +276 341 l +275 342 l +f +*U +0.000 0.000 0.000 0.835 k +*u +276.667 341.667 m +276.222 341.222 277.278 341.278 277.333 341.333 c +277.778 341.778 276.722 341.722 276.667 341.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +365 288 m +358.261 288 351.753 289.944 345 290 c +345 269 l +298 269 l +293.583 269 283.993 267.214 280.603 270.603 c +277.463 273.744 279 281.938 279 286 c +279 328 l +345 328 l +345 309 l +348.433 309.434 352.677 309.327 355 312 c +351 311 l +351 328 l +349.902 325.387 350 322.835 350 320 c +349.190 322.729 349 325 349 328 c +346.699 322.517 349.734 315.928 346 311 c +347.722 316.825 347 323 346 329 c +278 329 l +278 325 l +276.285 326.551 275.177 327.244 273 328 c +271.600 322 272.998 316 273 310 c +273 270 l +277 271 l +278 267 l +275 269 l +274.438 267.199 274.176 265.878 274 264 c +273.438 265.801 273.176 267 273 269 c +272 267 271.561 265 271 263 c +268.234 263.676 267.348 263.604 265 262 c +264 265.534 263.510 268.354 264 272 c +262 271 l +262.934 272.723 263.535 274 264 276 c +261 275 l +262 279 l +263 277 l +264.769 281.215 264 286.464 264 291 c +264 301.834 266.730 317 262 327 c +264 326 l +263.339 327.396 263 327.814 262 329 c +263.367 330.731 263.984 333 265.564 334.658 c +268.309 337.354 273.537 336.315 277 336 c +277.228 338 277 337.890 279 339 c +278 337.521 278 337.797 278 336 c +297.472 337.254 317.471 335.999 337 336 c +342.945 336 352.661 338.707 357.870 335 c +359.627 333.792 360.672 331.638 362 330 c +359 324.658 360 317.970 360 312 c +356 312 l +364.876 308.285 365 316.411 364.985 323 c +364.776 331.411 361.647 338.267 352.999 340.485 c +344.854 342.575 336.325 342 328 342 c +291 342 l +283 342 272.886 342.842 266 338 c +260.527 334 260 327.249 260 321 c +260 279 l +260 272 259.582 264.689 265.329 259.800 c +271.276 254.742 281.613 255 289 255 c +305.663 254.994 322.339 254.806 339 255 c +345.793 255 355.403 255.340 360.442 260.532 c +367 267.310 365 279.432 365 288 c +f +*U +0.000 0.000 0.000 0.784 k +*u +347.667 341.667 m +347.222 341.222 348.278 341.278 348.333 341.333 c +348.778 341.778 347.722 341.722 347.667 341.667 c +f +*U +0.000 0.000 0.000 0.514 k +*u +349 342 m +350 341 l +349 342 l +f +*U +0.000 0.000 0.000 0.196 k +*u +352.667 341.667 m +352.222 341.222 353.278 341.278 353.333 341.333 c +353.778 341.778 352.722 341.722 352.667 341.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +382 342 m +382 255 l +402 255 l +402 293 l +477 293 l +477 255 l +496 255 l +496 342 l +477 342 l +477 307 l +402 307 l +402 342 l +382 342 l +f +*U +0.000 0.000 0.000 0.145 k +*u +475 342 m +475 309 l +405 309 l +411.194 306.401 420.314 308 427 308 c +476 308 l +476 330 l +476 333.983 476.552 338.301 475 342 c +f +*U +0.000 0.000 0.000 0.635 k +*u +476 342 m +476 308 l +477.328 311 477.000 314.581 477 318 c +477 325.215 478.802 335.323 476 342 c +f +*U +0.000 0.000 0.000 0.855 k +*u +496 342 m +496 255 l +498.395 260.707 497 268.846 497 275 c +497 319 l +497 325.951 498.701 335.564 496 342 c +f +*U +0.000 0.000 0.000 0.161 k +*u +497 342 m +497 255 l +476 255 l +482.202 252.397 491.298 254 498 254 c +498 315 l +498 323 500 334.600 497 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +521 342 m +521 255 l +539 255 l +539 320 l +536.960 317.763 536.388 316.617 538 314 c +534.952 308.288 536 301.340 536 295 c +536 256 l +527 256 l +527 317 l +527 325 529.264 334.805 522 340 c +526 339.907 528.433 337.780 532 336 c +531 338 l +532.635 337.455 532.455 337.635 533 336 c +534.797 336 534.521 336 536 337 c +537 336 l +536.438 334.199 536.176 332.878 536 331 c +536.685 332.248 536.749 332.548 537 334 c +537.225 331.765 537 331 536 329 c +536.873 326.519 537 324.638 537 322 c +540.167 321.588 540.838 318.289 543 316 c +547 311.801 552.312 308.388 557 304.861 c +571 294.254 585 283.464 599 272.611 c +605.712 267.375 613.978 258.378 622 255.500 c +625.547 254.227 630.278 255 634 255 c +634 342 l +615 342 l +615 320.949 615 299.981 616 279 c +599.355 295.299 578.505 308 560 322.235 c +552 328.219 543.366 337.927 534 341.272 c +530 342.687 525 342 521 342 c +f +*U +0.000 0.000 0.000 0.725 k +*u +534 342 m +535 341 l +534 342 l +f +*U +0.000 0.000 0.000 0.145 k +*u +614 342 m +614 283 l +612.483 283.957 611.661 284.387 610 285 c +611.549 282.864 612.864 281.549 615 280 c +615 322 l +615 328 616.395 336.293 614 342 c +f +*U +0.000 0.000 0.000 0.153 k +*u +634 342 m +634 255 l +636.395 260.707 635 268.846 635 275 c +635 319 l +635 325.951 636.701 335.564 634 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +659 342 m +659 255 l +679 255 l +679 342 l +659 342 l +f +*U +0.000 0.000 0.000 0.200 k +*u +707 340 m +709.533 339.463 711.512 340.220 714 341 c +711.328 341.799 709.568 341 707 340 c +f +*U +0.000 0.000 0.000 0.569 k +*u +716 342 m +717 341 l +716 342 l +f +*U +0.000 0.000 0.000 0.882 k +*u +717.667 341.667 m +717.222 341.222 718.278 341.278 718.333 341.333 c +718.778 341.778 717.722 341.722 717.667 341.667 c +f +*U +0.000 0.000 0.000 0.996 k +*u +806 288 m +800.959 288.216 795.988 289.841 791 289 c +792.981 280.677 790.819 272.352 792 264 c +739 264 l +735 264 723.533 262.871 723 267 c +720 265 l +720.462 270 719 275.691 719 281 c +719 329 l +771 329 l +777 329 786.400 330.884 790 325 c +790.685 326.248 790.749 326.548 791 328 c +792.254 322.426 791.350 316.569 793 311 c +800 312 l +800 320.200 800.248 328.211 803 336 c +792 342.480 781.309 342 769 342 c +730 342 l +721.969 342 710.324 342.670 704.649 335.787 c +700.958 331.311 701 325.467 701 320 c +701 295 l +701 285.335 697.933 269.255 704.649 261.329 c +709.588 255.499 718.907 255 726 255 c +742.994 254.802 760 254.993 777 255 c +784.338 255 794.781 254.715 800.660 259.800 c +808 266.288 806 279.211 806 288 c +f +*U +0.000 0.000 0.000 0.788 k +*u +788.667 341.667 m +788.223 341.223 789.277 341.278 789.333 341.333 c +789.778 341.778 788.722 341.722 788.667 341.667 c +f +*U +0.000 0.000 0.000 0.525 k +*u +790 342 m +791 341 l +790 342 l +f +*U +0.000 0.000 0.000 0.098 k +*u +791 342 m +793.283 340.779 795.428 340.348 798 340 c +795.686 341.591 793.810 341.858 791 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +818 278 m +823 280 l +822 283 l +823.796 283.969 823.681 285.432 825.194 286.889 c +826.774 288.409 829 287.791 830.611 289.306 c +832.810 291.495 833 298.935 834 302 c +835.714 300.450 836.823 299.756 839 299 c +838 296 l +841 295 l +840.458 292.326 840.493 291.269 842 289 c +850 301.314 860.923 315 866 329 c +868 329 l +873.587 314.239 886.418 302.728 892 288 c +896 290 l +895 296 l +893.805 295.402 894 295.534 893 294 c +892 295.207 889.170 296.995 888 299 c +887.230 300.321 887.249 303.259 887 305 c +886.895 305.737 889 305.375 886 306 c +887.479 306.986 887.203 307 889 307 c +887.752 307.685 887.452 307.749 886 308 c +887 312 l +885.263 311.938 885.360 311.980 884 313 c +883 310 l +881.483 310.957 880.661 311.387 879 312 c +879.764 314.746 879.764 316.254 879 319 c +888 321 l +888.197 318.624 888.247 316.372 888 314 c +890.580 313 892.253 312.747 895 313 c +895.628 310 896.659 307.856 896 305 c +896.810 303.230 896.497 301.947 898 301 c +896.964 299.814 896.661 299.396 896 298 c +898.377 297.689 898.983 297.747 901 299 c +901 297.203 901 297.479 902 296 c +905 297 l +904 292.337 904.911 289.835 910 290 c +910.560 284.738 913.861 280.204 918 277 c +916.703 275.406 916.465 274.982 916 273 c +917.797 273 917.522 273 919 274 c +919.902 272 920 272 922 271 c +921.954 268.752 922 268 923 266 c +920.717 264.554 920.418 263.689 920 261 c +921 262.458 921.436 263.248 922 265 c +923.938 261.993 925.532 260 929 259 c +922.952 255.612 912.227 253.236 912 263 c +909.433 264.246 908.914 265 909 268 c +910 266.466 909.805 266.598 911 266 c +912 271.764 907.541 271.650 903 272 c +903.986 273.479 904 273.203 904 275 c +902.521 275.986 902.797 276 901 276 c +902 277.186 902.339 277.604 903 279 c +900.777 279.184 900.810 279.240 899 278 c +892.386 281.530 883.352 280 876 280 c +851 280 l +844.697 280 838.703 280.351 833.274 276.532 c +830.404 274.513 828.884 270.872 827 268 c +826 271 l +823 270 l +824.341 268.726 825.403 267.959 827 267 c +825.952 265 825.487 264 825 262 c +823 262 822.734 261.830 821 261 c +822 263 l +816 261 l +817 256 l +807 256 l +808.283 260.441 810.639 264 813 268 c +814 265 l +815.554 267.485 815.542 269 815 272 c +818 273 l +818 277 l +811.345 272.962 806.249 261.951 803 255 c +808.192 255 818.207 253 822.391 256.603 c +827.945 261.295 829.256 272.479 836.185 275.397 c +841 277.438 848.806 276 854 276 c +866.992 276 880 276.241 892.999 275.995 c +904 275.786 904.250 262.539 911.529 256.603 c +916 252.850 927.332 255 933 255 c +921.231 277 906 298 892.344 319 c +888.903 324.272 885.735 329.719 882.308 334.999 c +880.831 337.274 879.276 340.246 876.674 341.397 c +872.829 343 860.974 343.216 857.379 340.972 c +852.377 337.851 848.859 328.923 845.808 324 c +840 314.649 834.265 305.249 828.308 296 c +824.582 290.215 820 284.615 818 278 c +f +938 342 m +938 255 l +1033 255 l +1033 269 l +958 269 l +958 342 l +938 342 l +f +*U +0.000 0.427 0.302 0.239 k +*u +1054.333 341.333 m +1054.278 341.278 1054.222 340.222 1054.667 340.667 c +1054.723 340.723 1054.777 341.778 1054.333 341.333 c +f +*U +0.000 0.525 0.416 0.475 k +*u +1055 340 m +1066.604 342.763 1080 341 1092 341 c +1096.941 341 1102.923 342 1107 339 c +1108.703 343.519 1098.748 342 1096 342 c +1066 342 l +1062.385 342 1057.271 343 1055 340 c +f +*U +0.000 0.341 0.243 0.047 k +*u +1108.333 341.333 m +1108.278 341.278 1108.222 340.222 1108.667 340.667 c +1108.723 340.723 1108.777 341.778 1108.333 341.333 c +f +*U +0.000 0.420 0.369 0.282 k +*u +1191 342 m +1192 341 l +1191 342 l +f +*U +0.000 0.525 0.416 0.475 k +*u +1192 342 m +1197.462 339.708 1205 341 1211 341 c +1252 341 l +1394 341 l +1388.537 343.292 1380.887 342 1375 342 c +1334 342 l +1192 342 l +f +*U +0.000 0.388 0.267 0.031 k +*u +1394.333 341.333 m +1394.278 341.278 1394.222 340.222 1394.667 340.667 c +1394.723 340.723 1394.777 341.777 1394.333 341.333 c +f +*U +0.000 0.000 0.000 0.161 k +*u +1529 342 m +1530 340 l +1531.635 340.545 1531.455 340.365 1532 342 c +1529 342 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1632 342 m +1634.890 340.787 1637.874 341 1641 341 c +1638 342.213 1635 341.998 1632 342 c +f +*U +0.000 0.000 0.000 0.071 k +*u +1640 341 m +1641.769 340.221 1643 340 1645 340 c +1643 341.301 1642.372 341.330 1640 341 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1760 342 m +1762.332 341 1764.457 341 1767 341 c +1764.669 341.984 1762.543 341.981 1760 342 c +f +*U +0.000 0.000 0.000 0.133 k +*u +1896 342 m +1896 326 l +1897.812 330.319 1897.812 337.681 1896 342 c +f +*U +0.000 0.000 0.000 0.149 k +*u +1942 342 m +1940.286 339.376 1938.944 336.987 1938 334 c +1940.574 336.358 1942.298 338.952 1944 342 c +1942 342 l +f +*U +0.000 0.000 0.000 0.325 k +*u +148 341 m +148 328 l +149.591 331.791 149.591 337.209 148 341 c +f +*U +0.000 0.000 0.000 0.745 k +*u +353 341 m +354 340 l +353 341 l +f +*U +0.000 0.000 0.000 0.169 k +*u +355.667 340.667 m +355.222 340.222 356.278 340.278 356.333 340.333 c +356.778 340.778 355.722 340.722 355.667 340.667 c +f +*U +0.000 0.000 0.000 0.067 k +*u +381 341 m +381 256 l +383.395 261.707 382 269.846 382 276 c +382 319 l +382 325.686 383.599 334.806 381 341 c +f +*U +0.000 0.000 0.000 0.125 k +*u +519 341 m +519 256 l +521.395 261.707 520 269.846 520 276 c +520 319 l +520 325.686 521.599 334.806 519 341 c +f +*U +0.000 0.000 0.000 0.996 k +*u +522 340 m +528.915 333.235 527 324 527 315 c +527 256 l +536 256 l +536 294 l +536 300.340 534.952 307.288 538 313 c +537 316.780 538.349 318.645 540 322 c +538 323.277 538.915 323.277 537 322 c +537.284 324.853 537.557 326.603 536 329 c +537.336 330.826 537.690 331.753 538 334 c +537.315 332.752 537.251 332.452 537 331 c +536.660 333 536.677 333.968 537 336 c +536 337 l +531 338 l +532 336 l +528.566 338.505 526.390 340.606 522 340 c +f +*U +0.000 0.000 0.000 0.157 k +*u +536 341 m +537.223 339.805 537.420 339.684 539 339 c +537.777 340.195 537.580 340.316 536 341 c +f +*U +0.000 0.000 0.000 0.769 k +*u +794 341 m +795 340 l +794 341 l +f +*U +0.000 0.000 0.000 0.608 k +*u +878 341 m +879 340 l +878 341 l +f +*U +0.000 0.000 0.000 0.094 k +*u +879 341 m +879.564 339.248 879.919 338.458 881 337 c +880.689 339.291 880.634 339.320 879 341 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1053 336 m +1053.363 333.768 1053.363 332.232 1053 330 c +1112 330 l +1109.601 333.899 1107.435 336.220 1107 341 c +1072 341 l +1063.987 341 1058.563 342 1053 336 c +f +*U +0.000 0.341 0.318 0.008 k +*u +1190 341 m +1191 340 l +1190 341 l +f +*U +0.000 0.875 0.608 0.125 k +*u +1191 341 m +1191 339 l +1286 339 l +1276.597 336.221 1264.782 338 1255 338 c +1192 338 l +1199.639 334.794 1211.729 337 1220 337 c +1283 337 l +1283 333 l +1255.927 329.579 1227.296 332 1200 332 c +1207.400 328.895 1218.993 331 1227 331 c +1287 331 l +1288 338 l +1291.694 337 1295.214 337 1299 337 c +1297.752 337.685 1297.452 337.749 1296 338 c +1305.683 340.862 1317.924 339 1328 339 c +1392 339 l +1386.293 341.395 1378 340 1372 340 c +1331 340 l +1284.362 340 1237.700 341 1191 341 c +f +*U +0.000 0.882 0.635 0.118 k +*u +1296 341 m +1303.879 337.694 1316.466 340 1325 340 c +1392 340 l +1382.317 337 1370 339 1360 339 c +1296 339 l +1299.619 336.322 1300.850 334.591 1301 330 c +1395 330 l +1394.694 333.752 1393.759 337.320 1393 341 c +1296 341 l +f +*U +0.000 0.733 0.533 0.267 k +*u +1393 341 m +1393 338 l +1395 339 l +1394.455 340.635 1394.635 340.455 1393 341 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1425 341 m +1425 253 l +1446 253 l +1440.286 255.398 1432.169 254 1426 254 c +1426 314 l +1426 322 1428 333.601 1425 341 c +f +*U +0.000 0.000 0.000 0.855 k +*u +1426 341 m +1426 254 l +1428.701 260.436 1427 270 1427 277 c +1427 321 l +1427 327 1428.395 335.293 1426 341 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1427 341 m +1427 254 l +1446 254 l +1446 292 l +1459.982 283.441 1473.942 274.834 1488 266.400 c +1494.470 262.518 1501.682 256.505 1509 254.499 c +1517.380 252.203 1528.330 254 1537 254 c +1529.973 261 1518.663 265.461 1510 270.427 c +1493.561 279.852 1477.411 291.497 1460 299 c +1482.270 313.736 1506.223 326 1529 340 c +1525.565 341.441 1521.703 341 1518 341 c +1513.502 341 1508.356 341.663 1504 340.351 c +1496.680 338 1489.450 332 1483 328 c +1470.699 320.335 1458 313 1446 305 c +1446 341 l +1427 341 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1491 335 m +1495.302 333.994 1499.507 337.689 1503 340 c +1498.778 340.616 1494.663 336.949 1491 335 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1503 341 m +1504 340 l +1503 341 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1529 341 m +1530 340 l +1529 341 l +f +*U +0.000 0.000 0.000 0.506 k +*u +1554 341 m +1555 340 l +1554 341 l +f +*U +0.000 0.000 0.000 0.855 k +*u +1555.667 340.667 m +1555.222 340.222 1556.278 340.278 1556.333 340.333 c +1556.778 340.777 1555.722 340.722 1555.667 340.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1636 255 m +1630.194 257.303 1622.186 256 1616 256 c +1574 256 l +1563.575 256 1553.913 253.776 1548 264 c +1545 262 l +1543.393 267.482 1544.298 272.443 1543.826 278 c +1542.614 292.285 1543 306.647 1543 321 c +1541.231 316.785 1542 311.536 1542 307 c +1542 280 l +1540.304 284.639 1541 290 1541 295 c +1541 302.647 1539.780 311.446 1541 318.972 c +1541.455 320.915 1542.816 322.241 1543.361 324 c +1544 326.697 1542.720 330.297 1544 332.694 c +1547.265 338.455 1556.648 333.660 1558 340 c +1566.631 335.508 1576.540 336 1586 336 c +1628 336 l +1635.905 336 1643.682 337.177 1651 334 c +1650 330 l +1649 332 l +1647.833 328.992 1647.521 325.261 1650 323 c +1649 325 l +1653 324 l +1644.764 313.519 1650 295.666 1648.830 283 c +1648 275.920 1646.705 268 1651 262 c +1650 261 l +1648.483 261.957 1647.662 262.387 1646 263 c +1643.373 259.674 1641 257.375 1637 256 c +1644.933 252.766 1652.822 259.407 1654.481 267 c +1655.735 272.734 1655 279 1655 285 c +1655 319 l +1654.997 325.661 1654.998 333 1648.956 337.297 c +1642.231 342 1631.781 341 1624 341 c +1569 341 l +1561 341 1550.307 341.777 1544.214 335.775 c +1539.258 330.894 1539 322.545 1539 316 c +1538.933 302 1538.407 287.932 1539 274 c +1539.305 268 1540.919 261.234 1546 257.728 c +1549.735 255.202 1554.704 255 1559 254.425 c +1571.338 252.746 1584.555 254 1597 254 c +1609 254 1624.361 251.560 1636 255 c +f +*U +0.000 0.000 0.000 0.808 k +*u +1638.667 340.667 m +1638.222 340.222 1639.278 340.278 1639.333 340.333 c +1639.778 340.778 1638.722 340.722 1638.667 340.667 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1677 341 m +1677 254 l +1679.395 259.707 1678 267.846 1678 274 c +1678 318 l +1678 324.951 1679.701 334.564 1677 341 c +f +*U +0.000 0.000 0.000 0.851 k +*u +1678 341 m +1678 254 l +1680.395 259.707 1679 267.846 1679 274 c +1679 318 l +1679 324.951 1680.701 334.564 1678 341 c +f +*U +0.000 0.000 0.000 0.996 k +*u +1679 341 m +1679 338 l +1760 338 l +1760 336 l +1680 336 l +1680 256 l +1696 256 l +1696 266 1698 278.211 1696 288 c +1703.463 288.834 1711.460 288 1719 287.999 c +1723.253 287.979 1728.340 288.223 1732 286 c +1733.662 286.613 1734.483 287 1736 288 c +1735.522 286 1735.295 284.504 1734 283 c +1735.636 280.382 1735.730 278.558 1739 279 c +1739.777 277.298 1740.588 275.810 1741 274 c +1742.767 273 1743.608 272.434 1745 271 c +1747.502 271.402 1749.489 271.359 1752 271 c +1751 266.465 1753.520 264.181 1758 264 c +1759 262 1759 261.902 1761 261 c +1761.642 263.842 1763.253 265.681 1765 268 c +1762.460 269.693 1761.684 272.422 1761 269 c +1757 274 l +1752 272 l +1752 273.410 1752.851 279 1752 280 c +1750.303 281.980 1749.186 278.744 1750 282 c +1747.944 281.513 1746.856 281 1745 280 c +1744 281 l +1745.517 281.958 1746.338 282.387 1748 283 c +1746.494 283.683 1745.685 283.826 1744 284 c +1753.243 290.648 1766.731 283.345 1775.786 291.419 c +1778.777 294 1780 298 1780.699 302 c +1782.276 312.675 1783.853 333.465 1771.996 338.521 c +1762.259 342.672 1750.334 341 1740 341 c +1679 341 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1765 341 m +1766 340 l +1765 341 l +f +*U +0.000 0.000 0.000 0.502 k +*u +1766 341 m +1767 340 l +1766 341 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1767 341 m +1769 339.775 1770.658 339.355 1773 339 c +1770.958 340.416 1769.489 340.745 1767 341 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1797 341 m +1797 256 l +1799.395 261.707 1798 269.846 1798 276 c +1798 319 l +1798 325.686 1799.599 334.806 1797 341 c +f +*U +0.000 0.000 0.000 0.851 k +*u +1798 341 m +1798 254 l +1800.395 259.707 1799 267.846 1799 274 c +1799 318 l +1799 324.951 1800.701 334.564 1798 341 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1799 341 m +1799 254 l +1860 254 l +1878 254 l +1880.762 254 1884.206 253.505 1886.815 254.603 c +1891.372 256.523 1894.169 263.750 1896 268 c +1818 268 l +1818 276.954 1816.760 286.543 1820 295 c +1816 296 l +1816 285.911 1813.562 272.892 1819 264 c +1823 264 l +1827.782 267.623 1836.197 266 1842 266 c +1888 266 l +1881 263.970 1873 265 1866 265 c +1824 265 l +1828.720 263 1834.920 264 1840 264 c +1871 264 l +1877.237 264 1885 265.537 1890 261 c +1888 262 l +1887.835 253.173 1874 256 1868 256 c +1800 256 l +1800 336 l +1888 336 l +1888 328 l +1839 328 l +1831.722 328 1823 329.518 1816 328 c +1816.654 320 1816.359 311.882 1816 304 c +1831.677 305.519 1848.224 304 1864 304 c +1864 296 l +1832 296 l +1828 296 1822.666 297.177 1821 293 c +1865 293 l +1865 306 l +1818 306 l +1818 327 l +1896 327 l +1894.855 331.810 1894.855 336.190 1896 341 c +1799 341 l +f +1890 254 m +1894.853 254 1904.246 252.186 1908.366 255 c +1914.572 259.309 1914.958 269.959 1921.379 273.972 c +1925.246 276.389 1932.606 275 1937 275 c +1971 275 l +1977.708 275 1982.871 276 1987 270 c +1992 273 l +1991 278 l +1989.805 276.777 1989.684 276.580 1989 275 c +1987.328 275.338 1987.690 275.537 1987 274 c +1985.868 276.328 1985.484 276.978 1987 279 c +1975.641 282.358 1960.833 280 1949 280 c +1941.869 280 1933.868 281 1927 279 c +1928 277 l +1927 276 l +1923 278 l +1921.517 276 1916.355 277.250 1916 280 c +1911 276 l +1910.961 278.627 1910.839 280.664 1912 283 c +1912.532 287.842 1915.597 288.210 1920 288 c +1919.277 294 1920.394 299 1922 305 c +1923.672 304.662 1923.310 304.463 1924 306 c +1928 304 l +1927.805 306.424 1927.590 308.648 1927 311 c +1928.397 311.662 1928.813 311.964 1930 313 c +1930 311 l +1931.300 311.650 1931 311 1931 313 c +1932.944 312.598 1933 312.598 1935 313 c +1936 311 1936 310.902 1938 310 c +1935.182 306 1934.649 302.227 1929 302 c +1927 287 l +1944.985 287 1963 286.267 1981 288 c +1981 292 l +1982 288 l +1983.195 289.223 1983.316 289.420 1984 291 c +1986.877 288.691 1988.808 287.950 1992 290 c +1992.338 285.727 1993.331 283.397 1996 280 c +1997.797 280 1997.521 280 1999 281 c +1999.648 278.606 2000 277.464 2002 276 c +2000 269 l +2001.801 268.438 2003 268.176 2005 268 c +2003.521 267 2003.797 267 2002 267 c +2004.401 264.987 2005.890 264.657 2009 265 c +2010 262.229 2010.945 259.969 2011 257 c +2009 261 l +2006.749 256 2004.263 255.764 1999 257 c +1999.986 258.479 2000 258.203 2000 260 c +1998.584 259.528 1998.186 259.186 1997 258 c +1995 261.930 1992.625 266.562 1989 269 c +1990 264.302 1993.289 256.564 1998 254.603 c +2003.297 252.489 2011.444 254 2017 254 c +2014.701 260 2010.612 265.493 2007.192 271 c +2000.539 281.715 1993.696 292.313 1987 303 c +1984.198 300.326 1983 296.294 1981 293 c +1979.977 294.534 1980.196 294.402 1979 295 c +1977.701 294.350 1978 294.853 1978 293 c +1976 293 l +1976.175 296.585 1974.198 299.859 1976 303 c +1973.992 303.553 1973.667 303.303 1972 302 c +1970.343 303.664 1969 304.875 1967 306 c +1969.363 299.545 1973.778 294 1977 288 c +1929 288 l +1934 301.975 1945.877 313 1951 327 c +1944 328 l +1944.892 326 1945.402 325.481 1947 324 c +1944 324 l +1945 319 l +1942.622 318.617 1942.644 316.363 1942 314 c +1940.507 314.999 1940.734 314.968 1939 315 c +1937.741 317.498 1936.440 318.632 1934 320 c +1935 322.243 1935.182 322.577 1935 325 c +1936.822 325.990 1936.716 326.867 1937 329 c +1938.479 328 1938.203 328 1940 328 c +1939 330 l +1943 328 l +1943.494 331 1943 332.000 1940 333 c +1947 336.523 1953.786 334.868 1961 337 c +1960.636 335.505 1960.198 327.855 1962 332 c +1964.939 329 1969.397 327.339 1970 323 c +1978 314 l +1977 312.261 1976.308 310.445 1975 309 c +1977.799 307 1980.760 305.927 1984 305 c +1982.851 310.943 1978.871 315.940 1975.681 321 c +1972.297 326.370 1967.910 337.839 1961.816 340.397 c +1958.944 341.602 1955 341 1952 341 c +1949.243 340.999 1945.798 341.467 1943.329 339.972 c +1940.557 338.294 1939 334.672 1937.399 332 c +1927.600 316 l +1919.747 302.917 1911.642 289.953 1903.575 277 c +1898.951 269.576 1893 262.205 1890 254 c +f +*U +0.000 0.000 0.000 0.184 k +*u +266.667 339.667 m +266.222 339.222 267.278 339.278 267.333 339.333 c +267.778 339.778 266.722 339.722 266.667 339.667 c +f +*U +0.000 0.000 0.000 0.773 k +*u +268 340 m +269 339 l +268 340 l +f +*U +0.000 0.000 0.000 0.702 k +*u +356 340 m +357 339 l +356 340 l +f +*U +0.000 0.000 0.000 0.153 k +*u +357.667 339.667 m +357.222 339.222 358.278 339.278 358.333 339.333 c +358.778 339.778 357.722 339.722 357.667 339.667 c +f +*U +0.000 0.000 0.000 0.753 k +*u +709 340 m +710 339 l +709 340 l +f +*U +0.000 0.000 0.000 0.765 k +*u +797 340 m +798 339 l +797 340 l +f +*U +0.000 0.576 0.431 0.424 k +*u +1054 340 m +1054 336 l +1054.710 337.759 1054.710 338.241 1054 340 c +f +*U +0.000 0.408 0.357 0.114 k +*u +1108.333 339.333 m +1108.278 339.278 1108.222 338.222 1108.667 338.667 c +1108.722 338.722 1108.777 339.778 1108.333 339.333 c +f +*U +0.000 0.486 0.412 0.290 k +*u +1190 340 m +1191 339 l +1190 340 l +f +*U +0.000 0.000 0.000 0.075 k +*u +1525 338 m +1527.457 337.484 1528.502 338 1530 340 c +1528 339.453 1526.745 338.890 1525 338 c +f +*U +0.000 0.000 0.000 0.769 k +*u +1550 340 m +1551 339 l +1550 340 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1558 340 m +1554.752 334.808 1547.456 338.432 1544.169 333 c +1542.619 330.512 1543.697 327.184 1542.945 324.421 c +1539 310.450 1541 294.552 1541 280 c +1542.769 284.215 1542 289.465 1542 294 c +1542 321 l +1543.692 315.275 1543 308.940 1543 303 c +1543 294.265 1543.334 285.691 1543.791 277 c +1544 271.522 1542.600 267.230 1545 262 c +1546.396 262.661 1546.814 262.964 1548 264 c +1551.815 254.311 1560 256 1569 256 c +1624 256 l +1632.962 255.986 1640.944 253.814 1646 263 c +1650 261 l +1651 262 l +1647.318 269.250 1648.621 276.236 1648.961 284 c +1649.552 297.500 1646.300 311.964 1653 324 c +1649 325 l +1650 323 l +1648.348 325.719 1648.347 328.823 1648 332 c +1649 330.466 1648.805 330.598 1650 330 c +1651 334 l +1643.507 338.510 1632.561 336 1624 336 c +1602.813 336 1578 332.322 1558 340 c +f +*U +0.000 0.000 0.000 0.671 k +*u +1644 340 m +1645 339 l +1644 340 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1645 340 m +1646.458 338.919 1647.248 338.564 1649 338 c +1647.457 339.267 1646.952 339.489 1645 340 c +f +*U +0.000 0.000 0.000 0.827 k +*u +1769 340 m +1770 339 l +1769 340 l +f +*U +0.000 0.000 0.000 0.863 k +*u +1895 340 m +1895 328 l +1896.512 331.604 1896.512 336.396 1895 340 c +f +*U +0.000 0.000 0.000 0.114 k +*u +261 333 m +262.968 334.868 264.488 336.744 266 339 c +262.718 337.748 261.728 336.425 261 333 c +f +*U +0.000 0.000 0.000 0.725 k +*u +266 339 m +267 338 l +266 339 l +f +*U +0.000 0.000 0.000 0.996 k +*u +277 339 m +275.723 337 275.723 337.915 277 336 c +268.909 337.450 265.627 336.462 262 329 c +264 326 l +262 327 l +266.932 311.864 264 292.764 264 277 c +263 279 l +262 277.623 261.596 276.560 261 275 c +262.797 275 262.522 275 264 276 c +262 271 l +264 272 l +263.185 268.202 263.688 265.626 265 262 c +267.266 263 268.477 263.306 271 263 c +271.644 265 271.906 266.795 272 269 c +272.562 267.199 272.824 265.878 273 264 c +273.924 265.648 274.449 267.175 275 269 c +276.186 267.964 276.604 267.661 278 267 c +277 271 l +273 270 l +273 309 l +273 315.348 271.891 321.745 273 328 c +274.767 327 275.607 326.434 277 325 c +277.683 326.506 277.826 327.315 278 329 c +346 329 l +346.780 322.831 347.460 317 346 311 c +349.786 314.308 348 323.233 348 328 c +348.810 325.271 348.979 322.850 349 320 c +350 322.613 349.993 325 350 328 c +351.607 322.563 351 316.642 351 311 c +353.669 311.430 354.626 310.763 357 310 c +357 312.351 357.652 311.935 360 312 c +360 317.602 359.373 324 362 329 c +357.914 339.779 349.335 336 340 336 c +319.688 335.787 298 338.213 278 336 c +279 339 l +277 339 l +f +*U +0.000 0.000 0.000 0.675 k +*u +358 339 m +359 338 l +358 339 l +f +*U +0.000 0.000 0.000 0.212 k +*u +359 339 m +360 338 l +359 339 l +f +*U +0.000 0.000 0.000 0.682 k +*u +538 339 m +539 338 l +538 339 l +f +*U +0.000 0.000 0.000 0.118 k +*u +539 339 m +540.450 337.392 541 336.936 543 336 c +541.771 337.870 541 338.224 539 339 c +f +*U +0.000 0.000 0.000 0.133 k +*u +704 336 m +705.457 337 705.897 337.543 707 339 c +704.876 338 704.899 338 704 336 c +f +*U +0.000 0.000 0.000 0.733 k +*u +707 339 m +708 338 l +707 339 l +f +*U +0.000 0.000 0.000 0.765 k +*u +799 339 m +800 338 l +799 339 l +f +*U +0.000 0.000 0.000 0.267 k +*u +800 339 m +800.545 337.365 800.365 337.545 802 337 c +801.455 338.635 801.635 338.455 800 339 c +f +*U +0.000 0.000 0.000 0.235 k +*u +854 339 m +855 338 l +854 339 l +f +*U +0.000 0.690 0.631 0.251 k +*u +1107 339 m +1107 336 l +1107.696 337.554 1107.696 337.446 1107 339 c +f +*U +0.000 0.651 0.486 0.349 k +*u +1190 339 m +1190 336 1189.792 333.925 1192 332 c +1191.405 334.396 1191 336.767 1190 339 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1191 339 m +1191 335.922 1191.438 333 1192 330 c +1287 330 l +1279.600 333 1268 331 1260 331 c +1200 331 l +1207 333 1215.573 332 1223 332 c +1242.417 332 1263.893 329.453 1283 333 c +1283 337 l +1192 337 l +1201.403 339.779 1213.218 338 1223 338 c +1286 338 l +1278 341.306 1265.534 339 1257 339 c +1191 339 l +f +*U +0.000 0.580 0.392 0.416 k +*u +1394 339 m +1394 335.389 1395.207 332.211 1392 330 c +1393.506 329.317 1394.315 329.174 1396 329 c +1395.926 332.575 1395.692 335.818 1394 339 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1547 339 m +1548 338 l +1547 339 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1772 339 m +1773 338 l +1772 339 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1773.667 338.667 m +1773.222 338.222 1774.278 338.278 1774.333 338.333 c +1774.778 338.778 1773.722 338.722 1773.667 338.667 c +f +*U +0.000 0.000 0.000 0.651 k +*u +1964 339 m +1965 338 l +1964 339 l +f +*U +0.000 0.000 0.000 0.141 k +*u +1965 339 m +1965.547 337 1966 335.745 1967 334 c +1967.375 336.419 1966.693 337.218 1965 339 c +f +*U +0.000 0.000 0.000 0.220 k +*u +360 338 m +361 337 l +360 338 l +f +*U +0.000 0.000 0.000 0.831 k +*u +800 338 m +801 337 l +800 338 l +f +*U +0.000 0.000 0.000 0.075 k +*u +853 338 m +852 336.521 852 336.797 852 335 c +853.289 336.443 853.401 336.234 853 338 c +f +*U +0.000 0.000 0.000 0.655 k +*u +854 338 m +855 337 l +854 338 l +f +*U +0.000 0.000 0.000 0.071 k +*u +937 338 m +937 256 l +939.292 261.462 938 269 938 275 c +938 317 l +938 323.420 939.497 332 937 338 c +f +*U +0.000 0.259 0.192 0.090 k +*u +1053 338 m +1054 337 l +1053 338 l +f +*U +0.000 0.392 0.220 0.341 k +*u +1108.333 337.333 m +1108.278 337.278 1108.222 336.222 1108.667 336.667 c +1108.723 336.723 1108.777 337.778 1108.333 337.333 c +f +*U +0.000 0.388 0.306 0.286 k +*u +1288 338 m +1289 337 l +1288 338 l +f +*U +0.000 0.427 0.333 0.004 k +*u +1289 338 m +1290 337 l +1289 338 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1431 338 m +1427 330.610 1429 320 1429 312 c +1429 256 l +1440 256 l +1440 267 1441.209 279.000 1440 290 c +1442.979 290.596 1441.733 291.567 1444 291 c +1445 292 l +1444.466 294.670 1445.785 294.443 1443 295 c +1446.375 295.457 1448.391 295.223 1451 293 c +1455 294 l +1453.466 292.978 1453.598 293.195 1453 292 c +1456 291 l +1455 289 l +1458.629 286.899 1463 289 1466 287 c +1468 292 l +1464 290 l +1466 294 l +1463.851 295.236 1456.647 297 1458 300 c +1456.526 302.358 1455.440 306.306 1452 306.500 c +1448.447 306.700 1446.841 301 1443.333 304.167 c +1439.311 307.751 1441.765 309.947 1442 314 c +1442.422 321.278 1442 328.708 1442 336 c +1439.194 329.313 1441 319.233 1441 312 c +1438.801 319.438 1440 328.271 1440 336 c +1436.580 336 1434 336.325 1431 338 c +f +*U +0.000 0.000 0.000 0.584 k +*u +1524 338 m +1525 337 l +1524 338 l +f +*U +0.000 0.000 0.000 0.169 k +*u +1649 338 m +1650.330 336.248 1651.247 335.330 1653 334 c +1651.847 336.249 1651.249 336.847 1649 338 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1679 338 m +1679 254 l +1698 254 l +1698 287 l +1705.526 287 1717 289.170 1724 286 c +1727.728 284.311 1730.884 281 1734 278.414 c +1753 262.750 l +1756.344 259.987 1759.841 256 1764 254.600 c +1771.303 251.994 1782.278 254 1790 254 c +1781 263 1769 269.783 1759 277.373 c +1754.494 280.753 1749.901 285.603 1744 285 c +1745.506 284.317 1746.315 284.174 1748 284 c +1746.400 283 1745.337 282.280 1744 281 c +1745 280 l +1750 282 l +1749.613 279.910 1749.616 280.289 1752 280 c +1752 272 l +1757 274 l +1760 269 l +1761.195 269.598 1760.978 269.466 1762 271 c +1762.901 269 1763 269 1765 268 c +1762.665 265.716 1761.409 264.229 1761 261 c +1758 264 l +1753.965 264.429 1751.657 266.859 1752 271 c +1749.312 271.592 1747.659 271.675 1745 271 c +1743.771 272.870 1743 273.224 1741 274 c +1740.752 276 1740.213 277 1739 279 c +1737 278.622 1736.240 278 1735 281 c +1734.839 281.375 1737 281.377 1734 282 c +1735.333 284 1735.679 285.552 1736 288 c +1732 286 l +1729.777 288.437 1726.208 287.912 1723 287.975 c +1714.614 288 1704 289.749 1696 288 c +1696.876 277.482 1696 266.572 1696 256 c +1680 256 l +1680 336 l +1760 336 l +1760 338 l +1679 338 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1774 338 m +1775 337 l +1774 338 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1775 338 m +1776.755 335.287 1777.833 333.611 1781 333 c +1779.210 335.445 1777.895 337 1775 338 c +f +*U +0.000 0.000 0.000 0.812 k +*u +360 337 m +361 336 l +360 337 l +f +*U +0.000 0.000 0.000 0.224 k +*u +361 337 m +362 336 l +361 337 l +f +*U +0.000 0.000 0.000 0.996 k +*u +479 337 m +479 330 478.884 323 479 316 c +479 313 479.940 309.399 478 307 c +478.598 305.805 478.466 306 480 305 c +461.492 303 442.591 304 424 304 c +418.504 304 408.270 302 404 306 c +401 304 l +400 336 l +384 336 l +384 256 l +400 256 l +400 264.332 399.915 272.669 400 281 c +400 285.375 401.167 289.738 400 294 c +415.345 295 430.608 295 446 295 c +455.295 295 464.832 295.702 474 294 c +473 296 l +474.850 295.798 476 295.798 478 296 c +477.952 293.670 477.797 293.994 480 293 c +479.776 291.316 479.782 290.687 480 289 c +478 290 l +480 278.957 479 267.203 479 256 c +495 256 l +495 336 l +489.600 336 484.282 335.742 479 337 c +f +*U +0.000 0.000 0.000 0.827 k +*u +801 337 m +802 336 l +801 337 l +f +*U +0.000 0.000 0.000 0.227 k +*u +802 337 m +803 336 l +802 337 l +f +*U +0.000 0.000 0.000 0.216 k +*u +881 337 m +882 336 l +881 337 l +f +*U +0.000 0.271 0.196 0.255 k +*u +1053 337 m +1054 336 l +1053 337 l +f +*U +0.043 0.000 0.071 0.396 k +*u +1288 337 m +1289 336 l +1288 337 l +f +*U +0.000 0.451 0.353 0.180 k +*u +1292 337 m +1293 336 l +1292 337 l +f +*U +0.000 0.702 0.553 0.298 k +*u +1293 337 m +1294.248 336.315 1294.548 336.251 1296 336 c +1294.752 336.685 1294.451 336.749 1293 337 c +f +*U +0.000 0.584 0.584 0.416 k +*u +1296 337 m +1297.248 336.315 1297.548 336.251 1299 336 c +1297.752 336.685 1297.452 336.749 1296 337 c +f +*U +0.000 0.635 0.443 0.357 k +*u +1299 337 m +1300 333 l +1300.751 335 1300.656 335.596 1299 337 c +f +*U +0.000 0.106 0.067 0.122 k +*u +1395 337 m +1396 336 l +1395 337 l +f +*U +0.000 0.000 0.000 0.098 k +*u +1521 336 m +1522.809 335.426 1523 335.535 1525 336 c +1523.341 336.406 1522.758 336.309 1521 336 c +f +*U +0.000 0.000 0.000 0.788 k +*u +1544 337 m +1545 336 l +1544 337 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1960 337 m +1953.445 335 1946.674 336 1940 334 c +1942 331.998 1942.903 330.929 1943 328 c +1939 330 l +1940 328 l +1937 329 l +1936.501 327.201 1936.267 326.281 1935 325 c +1934.834 323 1934.555 321.804 1934 320 c +1942 314 l +1944 320 l +1945 319 l +1944 324 l +1945.915 322.723 1945 322.723 1947 324 c +1944 328 l +1946.590 327.435 1950.248 327.898 1952.572 326.601 c +1956 324.606 1958 319.366 1960 316 c +1963.171 310.633 1966.869 306.574 1971 302 c +1976 304 l +1973.470 300.177 1975.978 297.212 1976 293 c +1978 293.501 1979 293.637 1981 293 c +1984.465 297.246 1986.168 301.549 1985 307 c +1981.505 305.871 1978.520 307.387 1975 308 c +1978 313 l +1976 316.927 1973.812 320.679 1970 323 c +1969.776 327.728 1965.586 329.413 1962 332 c +1961.274 329.821 1961.561 330.220 1960 331 c +1960.452 333.241 1960.838 334.884 1960 337 c +f +40 336 m +40 329 l +55 329 74 332.196 88 326 c +87 318.526 88 310.551 88 303 c +88 256 l +103 256 l +103 329 l +144 329 l +144 336 l +40 336 l +f +152 336 m +152 331.354 152.313 327 150 323 c +153.524 318.323 152 309.597 152 304 c +152 256 l +225 256 l +230.330 256 235.670 255.904 240.999 256 c +242.984 256 245.590 255.865 246.972 257.603 c +248.468 259.484 247.992 262.768 248 265 c +199 265 l +188.695 265 178.210 265.561 168 264 c +169.301 274.446 166.876 285.466 168 296 c +169 294.466 168.805 294.598 170 294 c +173.701 296.622 179.518 295.979 184 295.999 c +194.666 296 205.334 296 216 296 c +216 305 l +204.357 305 192.635 304.604 181 305 c +178 305 171 303.824 168.983 305.948 c +167.236 307.701 167.906 310.802 167.965 313 c +168 318.328 168 323.671 168 329 c +247 329 l +247 336 l +152 336 l +f +*U +0.000 0.000 0.000 0.090 k +*u +362 336 m +364.278 327.651 365 320.686 365 312 c +367 312 l +367 319.634 367.930 330.355 362 336 c +f +*U +0.000 0.000 0.000 0.682 k +*u +542 336 m +543 335 l +542 336 l +f +*U +0.000 0.000 0.000 0.996 k +*u +616 336 m +616 299 l +616 291.661 615.447 283.624 619 277 c +623 280 l +622.976 276.554 622 274.713 620 272 c +619 275 l +616 274.700 614.652 274.995 614 272 c +610 282 l +609.315 280.752 609.251 280.452 609 279 c +606.715 280.588 604.754 280.700 602 281 c +603.186 282.186 603.584 282.528 605 283 c +602 285.478 599.167 287.871 596 290 c +594 288 l +593.658 290.602 593.459 291.946 595 294 c +590 296.451 586.648 300.786 582 303.667 c +580.295 304.723 578.583 304.813 577 306 c +576 303 l +574.814 304.186 574.416 304.528 573 305 c +573 301 l +576 301 l +576 296 l +580.731 295.471 583.468 293.995 582 289 c +584 289 583.724 289 584 287 c +591 288 l +591.195 283.869 591.189 280.197 596 280 c +597.222 278.267 598 277.849 600 277 c +600.796 272.450 604 271.911 607 269 c +612 271 l +612 267 l +612.683 268.506 612.826 269.315 613 271 c +616 263 l +619.199 263 620.875 262.386 620 259 c +624.291 257.179 627.247 256 632 256 c +632 336 l +616 336 l +f +*U +0.000 0.000 0.000 0.137 k +*u +657 336 m +657 254 l +662.715 254 676 251.540 680 256 c +675.303 254.882 663.409 252.798 659.603 256.603 c +655.862 260.345 658 272 658 277 c +658 317 l +658 322.887 659.292 330.538 657 336 c +f +*U +0.000 0.000 0.000 0.996 k +*u +664 336 m +664 256 l +673 256 l +673 336 l +664 336 l +f +*U +0.000 0.000 0.000 0.196 k +*u +703 336 m +704 335 l +703 336 l +f +*U +0.000 0.000 0.000 0.114 k +*u +803 336 m +804 332 l +804.751 334 804.656 334.596 803 336 c +f +*U +0.000 0.000 0.000 0.996 k +*u +944 336 m +944 256 l +1011 256 l +1015.400 256 1027.971 253.850 1030.972 257.602 c +1032.312 259.276 1031.976 262 1032 264 c +978 264 l +971 264 961 262.350 955 266 c +952 265 l +953.343 272.365 952 280.485 952 288 c +952 336 l +944 336 l +f +*U +0.000 0.561 0.463 0.318 k +*u +1108 336 m +1108 333 l +1108.696 334.554 1108.696 334.446 1108 336 c +f +*U +0.000 0.302 0.224 0.157 k +*u +1189 336 m +1189 333 l +1189.696 334.554 1189.696 334.446 1189 336 c +f +*U +0.000 0.698 0.537 0.302 k +*u +1287 336 m +1287 330 l +1287.951 332.285 1287.951 333.715 1287 336 c +f +*U +0.000 0.118 0.063 0.176 k +*u +1288 336 m +1288 329 l +1289 331.534 1289 333.466 1288 336 c +f +*U +0.000 0.431 0.310 0.090 k +*u +1395 336 m +1396 335 l +1395 336 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1495 336 m +1496 335 l +1495 336 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1543 336 m +1544 335 l +1543 336 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1800 336 m +1800 256 l +1868 256 l +1874.243 256 1888.339 252.975 1888 262 c +1890 261 l +1886.645 265.749 1878.243 264 1873 264 c +1824 264 l +1830.868 266 1838.869 265 1846 265 c +1888 265 l +1883.280 266.981 1877 266 1872 266 c +1839 266 l +1834.423 266 1826.197 267.658 1823 264 c +1821 264.402 1820.943 264.402 1819 264 c +1814.610 274.280 1816.439 285 1816 296 c +1821 293 l +1822 296 l +1835.586 294.506 1850.274 296 1864 296 c +1864 304 l +1853 304 1842.000 303.951 1831 304 c +1825.937 304 1820.979 305 1816 304 c +1816.761 311.353 1817.516 320.795 1816 328 c +1823.794 328.871 1832 328 1840 328 c +1888 328 l +1888 336 l +1800 336 l +f +*U +0.000 0.000 0.000 0.710 k +*u +262 335 m +263 334 l +262 335 l +f +*U +0.000 0.000 0.000 0.149 k +*u +544 335 m +545.223 333.805 545.420 333.684 547 333 c +545.777 334.195 545.580 334.316 544 335 c +f +*U +0.000 0.000 0.000 0.200 k +*u +702.333 334.333 m +702.278 334.278 702.222 333.222 702.667 333.667 c +702.722 333.722 702.778 334.778 702.333 334.333 c +f +*U +0.000 0.000 0.000 0.733 k +*u +703 335 m +704 334 l +703 335 l +f +*U +0.000 0.000 0.000 1.000 k +*u +802 335 m +799.654 327.528 800 319.764 800 312 c +797.558 311.891 795.377 311.572 793 311 c +791.660 316.627 791.872 322.254 792 328 c +791.315 326.752 791.251 326.451 791 325 c +786.553 330.882 777.644 329 771 329 c +719 329 l +719 307.660 718.430 286.235 720 265 c +721.314 265.768 721.232 265.686 722 267 c +724 264 l +731.213 265.221 739.599 264 747 264 c +761.998 264 777 264.185 792 264 c +791.510 272.494 791.417 281.523 792 290 c +786 291 l +786 269 l +740 269 l +735.281 269 726.390 267.311 722.318 270 c +718.716 272.431 720 279.309 720 283 c +720 315 l +720 318.565 719 324.610 722.434 326.972 c +726.403 329.704 735.362 328 740 328 c +786 328 l +786 309 l +790.704 309.371 800.650 308.986 804.397 312 c +806.351 313.608 805.985 316.769 805.999 319 c +806 324.758 806 330.621 802 335 c +f +*U +0.000 0.635 0.451 0.365 k +*u +1053 335 m +1053 331 l +1053.710 332.759 1053.710 333.241 1053 335 c +f +*U +0.000 0.000 0.000 0.675 k +*u +1519 335 m +1520 334 l +1519 335 l +f +*U +0.000 0.000 0.000 0.255 k +*u +1520 335 m +1521 334 l +1520 335 l +f +*U +0.000 0.000 0.000 0.133 k +*u +849 334 m +849 330 l +850.434 331.393 851 332.233 852 334 c +849 334 l +f +*U +0.000 0.424 0.325 0.098 k +*u +1109 334 m +1110 333 l +1109 334 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1517 334 m +1518 333 l +1517 334 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1653 334 m +1656.654 318 1656 302.349 1656 286 c +1656 278.680 1656.716 269.601 1652.911 263 c +1649.440 256.988 1642.787 257.507 1639 253 c +1644.525 253.748 1649.893 255.313 1653.347 260 c +1657 265 1656.998 272 1657 278 c +1657 309 l +1657 317 1658.856 327.485 1653 334 c +f +*U +0.000 0.000 0.000 0.180 k +*u +1937.333 333.333 m +1937.278 333.278 1937.222 332.222 1937.667 332.667 c +1937.722 332.722 1937.778 333.778 1937.333 333.333 c +f +*U +0.000 0.000 0.000 0.686 k +*u +1938 334 m +1939 333 l +1938 334 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1968 334 m +1968.899 331.876 1968.876 331.899 1971 331 c +1969.896 332.457 1969.457 332.897 1968 334 c +f +*U +0.000 0.000 0.000 0.129 k +*u +260 333 m +257.599 323.720 258 314.513 258 305 c +258 292.256 257.999 279.680 259 267 c +260.908 271.636 259 277 259 282 c +258.781 292.964 258.746 304 259 315 c +259 320.683 261.674 327.556 260 333 c +f +*U +0.000 0.000 0.000 0.710 k +*u +261 333 m +262 332 l +261 333 l +f +*U +0.000 0.000 0.000 0.600 k +*u +546 333 m +547 332 l +546 333 l +f +*U +0.000 0.000 0.000 0.110 k +*u +547 333 m +550.358 328.622 554.915 325 560 323 c +556.600 327.482 552.218 330.882 547 333 c +f +*U +0.000 0.000 0.000 0.118 k +*u +701 333 m +698 319 699 305 699 291 c +699 282 698 272.632 701 264 c +702.590 269.170 700.275 275.621 700 281 c +699.560 291.942 699.887 303 700 314 c +700 319.906 702.716 327.418 701 333 c +f +*U +0.000 0.000 0.000 0.671 k +*u +702 333 m +703 332 l +702 333 l +f +*U +0.000 0.000 0.000 0.114 k +*u +884 333 m +884.684 331.420 884.805 331.223 886 330 c +885.316 331.580 885.195 331.777 884 333 c +f +*U +0.000 0.243 0.180 0.259 k +*u +1052 333 m +1052 330 l +1052.696 331.554 1052.696 331.446 1052 333 c +f +*U +0.000 0.157 0.165 0.176 k +*u +1111 333 m +1112 332 l +1111 333 l +f +*U +0.000 0.506 0.392 0.494 k +*u +1300 333 m +1300 329 l +1304 329 l +1300 333 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1487 331 m +1488.580 331.683 1488.777 331.805 1490 333 c +1488.419 332.316 1488.223 332.196 1487 331 c +f +*U +0.000 0.000 0.000 0.718 k +*u +1490 333 m +1491 332 l +1490 333 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1513 331 m +1515.509 330.434 1516.220 331 1518 333 c +1516 332.453 1514.745 331.890 1513 331 c +f +1540 333 m +1538 326 l +1540.353 327.901 1540.877 330 1540 333 c +f +*U +0.000 0.000 0.000 0.765 k +*u +1541 333 m +1542 332 l +1541 333 l +f +*U +0.000 0.000 0.000 0.141 k +*u +805 332 m +806 324 l +807.232 327 806.825 329.328 805 332 c +f +*U +0.000 0.435 0.435 0.565 k +*u +1111 332 m +1112 331 l +1111 332 l +f +*U +0.000 0.184 0.137 0.361 k +*u +1112 332 m +1113 331 l +1112 332 l +f +*U +0.000 0.263 0.329 0.384 k +*u +1191 332 m +1192 331 l +1191 332 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1779 332 m +1780 331 l +1779 332 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1780.333 331.333 m +1780.278 331.278 1780.222 330.222 1780.667 330.667 c +1780.722 330.723 1780.777 331.778 1780.333 331.333 c +f +*U +0.000 0.549 0.490 0.451 k +*u +1105 330 m +1107.890 328.787 1110.874 329 1114 329 c +1111.184 330.629 1108.238 330 1105 330 c +f +*U +0.000 0.392 0.294 0.184 k +*u +1113 331 m +1114 330 l +1113 331 l +f +*U +0.000 0.220 0.153 0.102 k +*u +1396 331 m +1397 330 l +1396 331 l +f +*U +0.000 0.000 0.000 0.157 k +*u +1483 330 m +1484.809 329.426 1485 329.535 1487 330 c +1485.341 330.406 1484.758 330.309 1483 330 c +f +*U +0.000 0.000 0.000 0.753 k +*u +1512 331 m +1513 330 l +1512 331 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1969 331 m +1970 330 l +1969 331 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1970.333 330.333 m +1970.278 330.278 1970.222 329.222 1970.667 329.667 c +1970.722 329.722 1970.778 330.778 1970.333 330.333 c +f +*U +0.000 0.000 0.000 0.596 k +*u +260 330 m +261 329 l +260 330 l +f +*U +0.000 0.000 0.000 0.616 k +*u +701 330 m +702 329 l +701 330 l +f +*U +0.000 0.000 0.000 0.714 k +*u +849 330 m +850 329 l +849 330 l +f +*U +0.000 0.000 0.000 0.761 k +*u +885 330 m +886 329 l +885 330 l +f +*U +0.000 0.000 0.000 0.102 k +*u +886 330 m +886.944 327 888.286 324.624 890 322 c +890.962 325.672 888.789 327.790 886 330 c +f +*U +0.000 0.584 0.482 0.416 k +*u +1052 330 m +1053.506 329.317 1054.315 329.174 1056 329 c +1054.494 329.683 1053.685 329.826 1052 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1056 330 m +1060.720 328 1066.920 329 1072 329 c +1105 329 l +1100.280 330.981 1094 330 1089 330 c +1056 330 l +f +*U +0.000 0.169 0.149 0.224 k +*u +1114 330 m +1115 329 l +1114 330 l +f +*U +0.000 0.404 0.278 0.247 k +*u +1193 330 m +1194 329 l +1193 330 l +f +*U +0.000 0.541 0.431 0.459 k +*u +1194 330 m +1195.769 329.221 1197 329 1199 329 c +1197.231 329.779 1195.964 329.912 1194 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1199 330 m +1205.919 327 1216.520 329 1224 329 c +1280 329 l +1273 331.903 1262.480 330 1255 330 c +1199 330 l +f +*U +0.000 0.522 0.400 0.478 k +*u +1280 330 m +1282.613 328.902 1285 329 1288 329 c +1285.387 330 1282.835 329.993 1280 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1304 330 m +1311.399 326.895 1322.993 329 1331 329 c +1392 329 l +1384.600 332 1373 330 1365 330 c +1304 330 l +f +*U +0.000 0.216 0.141 0.404 k +*u +1396 330 m +1397 329 l +1396 330 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1508 328 m +1510 327.590 1510.963 328 1513 329 c +1510.860 329.410 1510 328.968 1508 328 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1780 330 m +1780 328 l +1782 328 l +1782 330 l +1780 330 l +f +*U +0.000 0.000 0.000 0.231 k +*u +1935 330 m +1936 329 l +1935 330 l +f +*U +0.000 0.000 0.000 0.655 k +*u +364 329 m +365 328 l +364 329 l +f +*U +0.000 0.000 0.000 0.808 k +*u +551 329 m +552 328 l +551 329 l +f +*U +0.000 0.000 0.000 0.612 k +*u +805 329 m +806 328 l +805 329 l +f +*U +0.000 0.000 0.000 0.000 k +*u +866.667 328.667 m +866.222 328.222 867.278 328.278 867.333 328.333 c +867.778 328.778 866.722 328.722 866.667 328.667 c +f +*U +0.000 0.169 0.114 0.063 k +*u +1195 329 m +1196 328 l +1195 329 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1558 327 m +1555.663 327.519 1554.360 327.480 1552 327 c +1558.248 321 1557 315 1557 307 c +1557 272 l +1555.308 277.725 1556 284 1556 290 c +1556 320 l +1554 315.531 1555 309.809 1555 305 c +1555 294 1552.890 280.522 1556 270 c +1552.911 274 1554 280 1554 285 c +1554 321 l +1552.231 316.785 1553 311.536 1553 307 c +1553 280 l +1552.994 276 1550.995 269.732 1554 267 c +1552.964 265.814 1552.661 265.396 1552 264 c +1555 264.614 1554.395 263.395 1557 266 c +1557 264 l +1562 268.917 1571.341 267 1578 267 c +1633 267 l +1631.723 265 1631.723 265.915 1633 264 c +1634 265 1634.308 265.611 1635 267 c +1636.757 265.267 1637.642 264.659 1640 264 c +1639.402 265.195 1639.534 264.978 1638 266 c +1641.511 269.368 1640 277.401 1640 282 c +1640 311 l +1640.000 315 1638.806 320.206 1640 324 c +1639 328 l +1619 327.290 1597.519 328 1577 328 c +1572.735 328 1568.242 327.588 1564 328 c +1561 328.277 1559.227 330 1558 327 c +f +*U +0.000 0.000 0.000 0.820 k +*u +1654 329 m +1655 328 l +1654 329 l +f +*U +0.000 0.000 0.000 0.243 k +*u +1934 329 m +1935 328 l +1934 329 l +f +*U +0.000 0.000 0.000 0.737 k +*u +1935 329 m +1936 328 l +1935 329 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1971 329 m +1972 328 l +1971 329 l +f +*U +0.000 0.000 0.000 0.000 k +*u +104 328 m +108.215 326.231 113.464 327 118 327 c +147 327 l +142.785 328.769 137.536 328 133 328 c +104 328 l +f +*U +0.000 0.000 0.000 0.133 k +*u +104 327 m +104 255 l +99.198 255 88.240 252.966 84.603 256.603 c +81 260 83 270.410 83 275 c +83 327 l +40 327 l +44.215 325.231 49.464 326 54 326 c +82 326 l +82 254 l +105 254 l +105 326 l +147 326 l +147 254 l +250 254 l +250 270 l +248 265.529 249 259.817 249 255 c +175 255 l +169 255 162.999 254.959 157 255 c +154.582 255 151.474 254.732 149.603 256.603 c +146 260 148 270.410 148 275 c +148 292.208 145.855 311 149 328 c +134.538 325.315 118.684 327 104 327 c +f +*U +0.000 0.000 0.000 0.867 k +*u +279 328 m +279 270 l +280.981 274.720 280 280.920 280 286 c +280 314 l +280 318.536 280.769 323.785 279 328 c +f +*U +0.000 0.000 0.000 0.000 k +*u +280 328 m +285.951 325.503 294.580 327 301 327 c +345 327 l +339 329.497 330.420 328 324 328 c +280 328 l +f +721 328 m +726.951 325.503 735.580 327 742 327 c +786 327 l +780 329.497 771.420 328 765 328 c +721 328 l +f +*U +0.000 0.000 0.000 0.082 k +*u +846 328 m +844.296 325 842.939 322.260 842 319 c +844.821 321.605 846.482 324.483 848 328 c +846 328 l +f +*U +0.000 0.000 0.000 0.102 k +*u +865 325 m +866.457 326 866.897 326.543 868 328 c +865.876 327 865.899 327 865 325 c +f +*U +0.000 0.000 0.000 0.125 k +*u +1472 321 m +1482 327 l +1477.705 327.702 1473.987 324.621 1472 321 c +f +*U +0.000 0.000 0.000 0.702 k +*u +1482 328 m +1483 327 l +1482 328 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1507 328 m +1508 327 l +1507 328 l +f +*U +0.000 0.000 0.000 0.890 k +*u +1780.333 327.333 m +1780.278 327.278 1780.222 326.222 1780.667 326.667 c +1780.722 326.723 1780.777 327.778 1780.333 327.333 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1781 328 m +1781 300 l +1783.604 306.207 1783.604 321.793 1781 328 c +f +*U +0.000 0.000 0.000 0.098 k +*u +1952 328 m +1952.684 326.420 1952.805 326.223 1954 325 c +1953.316 326.580 1953.195 326.777 1952 328 c +f +*U +0.000 0.000 0.000 0.686 k +*u +1971 328 m +1972 327 l +1971 328 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1972 328 m +1973.508 323.269 1976.410 319.216 1979 315 c +1980.187 319.889 1975.422 324.898 1972 328 c +f +*U +0.000 0.000 0.000 0.141 k +*u +280 327 m +280 272 l +282.189 277.217 281 284.381 281 290 c +281 326 l +344 326 l +338.293 328.395 330 327 324 327 c +280 327 l +f +*U +0.000 0.000 0.000 0.106 k +*u +344 327 m +342.423 321.665 341 310.732 346 307 c +344.820 313.355 346.459 321 344 327 c +f +*U +0.000 0.000 0.000 0.153 k +*u +721 327 m +721 270 l +786 270 l +780.293 272.395 772 271 766 271 c +722 271 l +722 326 l +784 326 l +784 319.757 783.222 313 785 307 c +787.709 307.648 790.216 307.942 793 308 c +791 308.871 788.187 308.991 786.603 310.603 c +783.338 313.925 785 322.689 785 327 c +721 327 l +f +*U +0.000 0.000 0.000 0.075 k +*u +785 327 m +785 310 l +786.883 314.486 786.883 322.514 785 327 c +f +*U +0.000 0.000 0.000 0.592 k +*u +847 327 m +848 326 l +847 327 l +f +*U +0.000 0.000 0.000 0.000 k +*u +867 327 m +863.441 323.609 861.755 319.216 858 316 c +857.516 312.696 856.536 311 854 309 c +852.926 302.808 847.781 296.667 845 291 c +889 291 l +886.655 296.373 883 300.984 880 305.996 c +875.946 312.991 872.250 320.731 867 327 c +f +*U +0.000 0.000 0.000 0.161 k +*u +868.333 326.333 m +868.278 326.278 868.222 325.222 868.667 325.667 c +868.722 325.722 868.778 326.778 868.333 326.333 c +f +*U +0.000 0.000 0.000 0.129 k +*u +1506.667 326.667 m +1506.222 326.222 1507.278 326.278 1507.333 326.333 c +1507.778 326.778 1506.722 326.722 1506.667 326.667 c +f +*U +0.000 0.000 0.000 0.012 k +*u +1559 325 m +1567.923 327 1577.866 326 1587 326 c +1636 326 l +1630.537 328.292 1622.887 327 1617 327 c +1577 327 l +1572 327 1562.407 328.899 1559 325 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1698 327 m +1703.217 324.811 1710.381 326 1716 326 c +1755 326 l +1749.783 328.189 1742.619 327 1737 327 c +1698 327 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1755 327 m +1756.717 325 1757.566 324.651 1760 324 c +1758.314 325.656 1757.254 326.251 1755 327 c +f +*U +0.000 0.000 0.000 0.761 k +*u +1757 327 m +1758 326 l +1757 327 l +f +*U +0.000 0.000 0.000 0.075 k +*u +1818 327 m +1818 320.654 1817.522 314.208 1819 308 c +1821 312.974 1820 319.638 1820 325 c +1897 325 l +1891.726 328.996 1881.423 327 1875 327 c +1818 327 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1951 327 m +1952 326 l +1951 327 l +f +*U +0.000 0.000 0.000 0.071 k +*u +148 326 m +148 256 l +150 260.969 149 267.650 149 273 c +149 307 l +149 312.887 150.292 320.538 148 326 c +f +*U +0.000 0.000 0.000 0.820 k +*u +555 326 m +556 325 l +555 326 l +f +*U +0.000 0.000 0.000 0.859 k +*u +720 326 m +720 270 l +721.769 274.215 721 279.465 721 284 c +721 311 l +721 315.809 721.875 321.531 720 326 c +f +*U +0.000 0.000 0.000 0.671 k +*u +864 326 m +865 325 l +864 326 l +f +*U +0.000 0.000 0.000 0.639 k +*u +869 326 m +870 325 l +869 326 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1503 324 m +1504.580 324.683 1504.777 324.805 1506 326 c +1504.420 325.316 1504.223 325.195 1503 324 c +f +*U +0.000 0.000 0.000 0.161 k +*u +1538 326 m +1538 268 l +1539.981 272.720 1539 278.920 1539 284 c +1539 312 l +1539 316.536 1539.769 321.785 1538 326 c +f +*U +0.000 0.000 0.000 0.600 k +*u +1539 326 m +1540 325 l +1539 326 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1559 269 m +1636 269 l +1636 326 l +1579 326 l +1574.766 326 1562.918 328 1560 324.397 c +1557.456 321 1559 312.929 1559 309 c +1559 269 l +f +*U +0.000 0.000 0.000 0.067 k +*u +1698 326 m +1698 302 l +1700.633 308.274 1699.858 319 1700 326 c +1698 326 l +f +*U +0.000 0.000 0.000 0.000 k +*u +1700 326 m +1700 302 l +1719 302 1740.201 299.510 1759 303 c +1759 308 1761.253 320.332 1757.397 324 c +1754 327.425 1746.315 326 1742 326 c +1700 326 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1932 326 m +1929 321.997 1926.230 317.784 1925 313 c +1928.309 316 1932.684 321.314 1932 326 c +f +*U +0.000 0.000 0.000 0.576 k +*u +1933 326 m +1934 325 l +1933 326 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1951 326 m +1949.286 323.376 1947.944 320.987 1947 318 c +1949.464 320.284 1951.502 322.551 1951 326 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1952 326 m +1950.218 322.226 1947.742 319.243 1948 315 c +1940 310.991 1935 297.600 1931 290 c +1945.210 290 1959.845 291 1974 290 c +1970.750 297.805 1965.749 304.792 1961.370 312 c +1958.365 316.945 1956.264 321.945 1952 326 c +f +*U +0.000 0.000 0.000 0.627 k +*u +1954 326 m +1955 325 l +1954 326 l +f +*U +0.000 0.000 0.000 0.141 k +*u +869 325 m +869.944 322 871.286 319.624 873 317 c +873.502 320.449 871.464 322.716 869 325 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1477 325 m +1478 324 l +1477 325 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1502 325 m +1503 324 l +1502 325 l +f +*U +0.000 0.000 0.000 0.882 k +*u +1539.333 324.333 m +1539.278 324.278 1539.222 323.222 1539.667 323.667 c +1539.723 323.723 1539.777 324.778 1539.333 324.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1560 325 m +1560 270 l +1635 270 l +1635 309 l +1635 312.731 1636.423 320.302 1633.972 323.397 c +1631 327 1619.234 325 1615 325 c +1560 325 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1954 325 m +1954.547 323 1955 321.744 1956 320 c +1956.375 322.419 1955.693 323.218 1954 325 c +f +*U +0.000 0.000 0.000 0.000 k +*u +700.333 323.333 m +700.277 323.278 700.222 322.222 700.667 322.667 c +700.722 322.722 700.778 323.778 700.333 323.333 c +f +*U +0.000 0.000 0.000 0.090 k +*u +806 324 m +806 311 l +808.794 314.688 808 319.519 808 324 c +806 324 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1496 321 m +1498.837 320.325 1500.522 321.495 1503 323 c +1500.311 323.405 1498.444 322.225 1496 321 c +f +*U +0.000 0.000 0.000 0.651 k +*u +1655.333 323.333 m +1655.278 323.278 1655.222 322.222 1655.667 322.667 c +1655.722 322.722 1655.777 323.778 1655.333 323.333 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1759 324 m +1759 303 l +1761.351 307.369 1761.449 319.711 1759 324 c +f +*U +0.000 0.000 0.000 0.780 k +*u +1949 324 m +1950 323 l +1949 324 l +f +*U +0.000 0.000 0.000 0.757 k +*u +559 323 m +560 322 l +559 323 l +f +*U +0.000 0.000 0.000 0.090 k +*u +560 323 m +562.319 320 564.622 318.432 568 317 c +565.709 320 563.641 321.761 560 323 c +f +*U +0.000 0.000 0.000 0.831 k +*u +871 323 m +872 322 l +871 323 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1474 323 m +1475 322 l +1474 323 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1760 323 m +1761 322 l +1760 323 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1956 323 m +1957 322 l +1956 323 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1974 323 m +1975 322 l +1974 323 l +f +*U +0.000 0.000 0.000 0.824 k +*u +560 322 m +561 321 l +560 322 l +f +*U +0.000 0.000 0.000 0.749 k +*u +844 322 m +845 321 l +844 322 l +f +*U +0.000 0.000 0.000 0.122 k +*u +862 322 m +861 320.255 860.547 318.875 860 317 c +861.693 318.782 862.375 319.581 862 322 c +f +*U +0.000 0.000 0.000 0.827 k +*u +890 322 m +891 321 l +890 322 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1471 322 m +1472 321 l +1471 322 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1497 322 m +1498 321 l +1497 322 l +f +*U +0.000 0.000 0.000 0.871 k +*u +1655 322 m +1655 274 l +1656.552 277.699 1656 282 1656 286 c +1656 309 l +1656 313.260 1656.661 318 1655 322 c +f +*U +0.000 0.000 0.000 0.616 k +*u +259 321 m +259 276 l +260.661 279.959 260 284.740 260 289 c +260 310 l +260 313.702 260.441 317.565 259 321 c +f +*U +0.000 0.000 0.000 0.635 k +*u +700 321 m +700 276 l +701.661 279.959 701 284.740 701 289 c +701 310 l +701 313.702 701.441 317.565 700 321 c +f +*U +0.000 0.000 0.000 0.996 k +*u +879 319 m +879.508 316.408 879.508 314.593 879 312 c +883 310 l +883.986 311.479 884 311.203 884 313 c +885.493 312 885.266 312 887 312 c +886.423 309.289 886.232 308.605 889 308 c +887.522 307 887.797 307 886 307 c +887.791 304 888.463 290.190 895 296 c +896 290 l +890.818 288.394 885.381 289 880 289 c +853 289 l +847.537 289 840.729 287.777 841 295 c +839.521 295.986 839.797 296 838 296 c +838.986 297.479 839 297.203 839 299 c +834 302 l +832.781 298.586 832.532 293.624 830.647 290.607 c +827.879 286.179 821.909 286.980 823 280 c +817 279 l +817.194 276.894 817.417 275 818 273 c +816.203 273 816.479 272.986 815 272 c +815.224 269.625 815.214 267.376 815 265 c +813 268 l +809.974 264.391 807.832 260.662 807 256 c +817 256 l +816 261 l +818.172 261.464 819.958 262 822 263 c +821 261 l +823.979 261.596 822.733 262.567 825 262 c +825.613 263.661 826 264.483 827 266 c +825.550 267.608 824.949 268 823 269 c +826 271 l +826 269.203 826 269.479 827 268 c +830.854 272 832.458 276 838 278.532 c +842.983 280.687 848.690 280 854 280 c +882 280 l +887.552 280 893 280.668 898 278 c +899.804 278.555 901 278.834 903 279 c +901 276 l +904 275 l +903 272 l +907.215 271.394 911.430 271.215 911 266 c +910 268 l +908.235 265.304 908.957 263.863 912 263 c +910.624 253 923 255.829 929 258 c +926.540 260.196 924.463 262 923 265 c +921.919 263.542 921.564 262.752 921 261 c +920.862 263.667 921 264 923 266 c +922.434 267.773 922 269 922 271 c +919 274 l +916 273 l +918 277 l +914.586 280.751 911 284.951 910 290 c +905.168 290 904.463 292.500 905 297 c +903.203 297 903.479 296.986 902 296 c +901 299 l +899.177 298.255 897.977 298 896 298 c +898 301 l +895.658 301.781 895.980 301.654 898 303 c +897.455 304.635 897.635 304.455 896 305 c +897.550 308 896.183 309.916 895 313 c +892.440 312.887 890.456 313.265 888 314 c +888.496 316.556 888.442 318.429 888 321 c +884.864 320.580 881.976 320 879 319 c +f +*U +0.000 0.000 0.000 0.157 k +*u +892.333 320.333 m +892.278 320.278 892.222 319.222 892.667 319.667 c +892.722 319.722 892.778 320.778 892.333 320.333 c +f +1464 318 m +1466.690 317.595 1468.556 318.775 1471 320 c +1468 320.675 1466.478 319.505 1464 318 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1760 321 m +1760 307 l +1761.667 310.972 1761.667 317 1760 321 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1930 321 m +1931 320 l +1930 321 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1957 321 m +1958 320 l +1957 321 l +f +*U +0.000 0.000 0.000 0.027 k +*u +539 320 m +539 317 l +539.696 318.554 539.696 318.446 539 320 c +f +*U +0.000 0.000 0.000 0.765 k +*u +563 320 m +564 319 l +563 320 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1469 320 m +1470 319 l +1469 320 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1699 320 m +1699 313.654 1699.478 307.208 1698 301 c +1701 301 l +1699.540 307 1701.403 314.274 1699 320 c +f +*U +0.000 0.000 0.000 0.647 k +*u +1976 320 m +1977 319 l +1976 320 l +f +*U +0.000 0.000 0.000 0.761 k +*u +540 319 m +541 318 l +540 319 l +f +*U +0.000 0.000 0.000 0.125 k +*u +841 319 m +840 317.255 839.547 315.875 839 314 c +840.693 315.782 841.375 316.581 841 319 c +f +*U +0.000 0.000 0.000 0.745 k +*u +842 319 m +843 318 l +842 319 l +f +*U +0.000 0.000 0.000 0.725 k +*u +892 319 m +893 318 l +892 319 l +f +*U +0.000 0.000 0.000 0.094 k +*u +893 319 m +893.684 317.420 893.805 317.223 895 316 c +894.316 317.580 894.195 317.777 893 319 c +f +*U +0.000 0.118 0.239 0.184 k +*u +1051 319 m +1052 318 l +1051 319 l +f +*U +0.000 0.216 0.047 0.082 k +*u +1052 319 m +1053 318 l +1052 319 l +f +*U +0.000 0.129 0.059 0.169 k +*u +1109 319 m +1110.506 318.317 1111.315 318.174 1113 318 c +1111.494 318.683 1110.685 318.826 1109 319 c +f +*U +0.000 0.169 0.122 0.137 k +*u +1126 319 m +1127.769 318.221 1129 318 1131 318 c +1129.231 318.779 1127.964 318.912 1126 319 c +f +*U +0.000 0.176 0.106 0.153 k +*u +1202 319 m +1203.249 318.315 1203.548 318.251 1205 318 c +1203.752 318.685 1203.451 318.749 1202 319 c +f +*U +0.000 0.251 0.184 0.110 k +*u +1281.667 318.667 m +1281.222 318.222 1282.278 318.278 1282.333 318.333 c +1282.778 318.778 1281.722 318.722 1281.667 318.667 c +f +*U +0.000 0.075 0.059 0.153 k +*u +1297.667 318.667 m +1297.222 318.222 1298.278 318.278 1298.333 318.333 c +1298.778 318.778 1297.722 318.722 1297.667 318.667 c +f +*U +0.000 0.098 0.078 0.227 k +*u +1396.667 318.667 m +1396.222 318.222 1397.278 318.278 1397.333 318.333 c +1397.778 318.778 1396.722 318.722 1396.667 318.667 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1492 319 m +1493 318 l +1492 319 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1946 319 m +1947 318 l +1946 319 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1958.333 318.333 m +1958.278 318.278 1958.222 317.222 1958.667 317.667 c +1958.723 317.723 1958.777 318.777 1958.333 318.333 c +f +540 318 m +540 255 l +542.395 260.707 541 268.846 541 275 c +541 316 l +543 314.242 544.581 313 547 312 c +544.951 314.832 543 316.520 540 318 c +f +*U +0.000 0.000 0.000 0.765 k +*u +859 318 m +860 317 l +859 318 l +f +*U +0.000 0.000 0.000 0.675 k +*u +874 318 m +875 317 l +874 318 l +f +*U +0.000 0.388 0.294 0.078 k +*u +1050 318 m +1050 315 l +1050.696 316.554 1050.696 316.446 1050 318 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1051 318 m +1056.707 315.605 1064.846 317 1071 317 c +1112 317 l +1106.293 319.395 1098 318 1092 318 c +1051 318 l +f +*U +0.000 0.235 0.204 0.765 k +*u +1112 318 m +1113 317 l +1112 318 l +f +*U +0.000 0.643 0.482 0.357 k +*u +1120 314 m +1124.336 312.848 1128 316.766 1133 316 c +1128.217 319.622 1124.585 316.330 1120 314 c +f +*U +0.000 0.263 0.180 0.149 k +*u +1132 318 m +1133 317 l +1132 318 l +f +*U +0.000 0.314 0.196 0.310 k +*u +1202 318 m +1203 317 l +1202 318 l +f +*U +0.000 0.580 0.467 0.420 k +*u +1203.667 317.667 m +1203.222 317.222 1204.278 317.278 1204.333 317.333 c +1204.778 317.778 1203.722 317.722 1203.667 317.667 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1204 317 m +1205.623 314.565 1208.716 314.819 1206 316 c +1213.999 318.364 1223.688 317 1232 317 c +1282 317 l +1281 312 l +1282.580 311.317 1282.777 311.195 1284 310 c +1284.985 312.806 1283.633 315 1283 318 c +1231 318 l +1222.393 318 1212.280 319.447 1204 317 c +f +*U +0.000 0.208 0.153 0.102 k +*u +1283 318 m +1283 315 l +1283.696 316.554 1283.696 316.446 1283 318 c +f +*U +0.000 0.878 0.627 0.122 k +*u +1296 318 m +1295.570 312.551 1295.260 311.437 1299 307.500 c +1298 307 l +1306 303.593 1319.203 306 1328 306 c +1397 306 l +1397 317 l +1331 317 l +1319.718 317 1307 315.379 1296 318 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1297 318 m +1305 314.593 1318.203 317 1327 317 c +1396 317 l +1387.882 320.407 1374.797 318 1366 318 c +1297 318 l +f +*U +0.000 0.600 0.616 0.376 k +*u +1396 318 m +1397 315 l +1397.685 316.248 1397.749 316.549 1398 318 c +1396 318 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1466 318 m +1467 317 l +1466 318 l +f +*U +0.000 0.000 0.000 0.792 k +*u +1490 318 m +1491 317 l +1490 318 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1946 318 m +1945 316.255 1944.547 314.875 1944 313 c +1948 315 l +1947.309 316.388 1947 316.861 1946 318 c +f +*U +0.000 0.000 0.000 0.576 k +*u +539.333 316.333 m +539.278 316.278 539.222 315.222 539.667 315.667 c +539.722 315.722 539.778 316.778 539.333 316.333 c +f +*U +0.000 0.000 0.000 0.659 k +*u +567 317 m +568 316 l +567 317 l +f +*U +0.000 0.000 0.000 0.051 k +*u +568 317 m +570 314.542 571.790 313.641 575 313 c +572.841 315 570.801 316 568 317 c +f +*U +0.000 0.000 0.000 0.114 k +*u +874 317 m +874.547 315 875 313.745 876 312 c +876.375 314.419 875.693 315.218 874 317 c +f +*U +0.000 0.682 0.776 0.188 k +*u +1051 317 m +1051 312 l +1051.830 314 1051.830 314.970 1051 317 c +f +*U +0.000 0.906 0.667 0.094 k +*u +1052 317 m +1051 306 l +1135 306 l +1133.239 309.561 1132.478 312 1133 316 c +1126.471 317.490 1123 311.750 1117 312.502 c +1113.762 312.910 1112.182 316.296 1108.896 316.852 c +1102.898 317.867 1096 317 1090 317 c +1052 317 l +f +*U +0.000 0.451 0.329 0.314 k +*u +1112.333 316.333 m +1112.278 316.278 1112.222 315.222 1112.667 315.667 c +1112.722 315.723 1112.777 316.778 1112.333 316.333 c +f +*U +0.000 0.235 0.176 0.110 k +*u +1124 317 m +1125 316 l +1124 317 l +f +*U +0.000 0.259 0.176 0.353 k +*u +1133 317 m +1134 316 l +1133 317 l +f +*U +0.000 0.380 0.247 0.129 k +*u +1203 317 m +1204 316 l +1203 317 l +f +*U +0.000 0.882 0.647 0.118 k +*u +1206 317 m +1207.364 315.181 1207.492 315.969 1207 314 c +1212 313 l +1210.952 311 1210.488 310 1210 308 c +1217.426 305 1226 307.997 1234 308 c +1252.180 308 1270 308.419 1288 306 c +1285.880 308.630 1284.237 310.917 1281 312 c +1281.562 313.801 1281.824 315 1282 317 c +1206 317 l +f +*U +0.000 0.310 0.224 0.200 k +*u +1295 317 m +1296 316 l +1295 317 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1457 314 m +1459.837 313.325 1461.522 314.495 1464 316 c +1461.311 316.405 1459.444 315.225 1457 314 c +f +*U +0.000 0.000 0.000 0.616 k +*u +1464 317 m +1465 316 l +1464 317 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1489.667 316.667 m +1489.222 316.222 1490.278 316.278 1490.333 316.333 c +1490.778 316.778 1489.722 316.722 1489.667 316.667 c +f +*U +0.000 0.000 0.000 0.118 k +*u +1959 317 m +1959.899 313.173 1961.819 310.249 1964 307 c +1964.572 310.923 1961.728 314.354 1959 317 c +f +*U +0.000 0.000 0.000 0.608 k +*u +894 316 m +895 315 l +894 316 l +f +*U +0.000 0.000 0.000 0.075 k +*u +895 316 m +895.547 314 896 312.745 897 311 c +897.710 313.531 897 314.516 895 316 c +f +*U +0.000 0.278 0.204 0.031 k +*u +1123 316 m +1124 315 l +1123 316 l +f +*U +0.000 0.569 0.404 0.431 k +*u +1133.333 315.333 m +1133.278 315.278 1133.222 314.222 1133.667 314.667 c +1133.722 314.722 1133.777 315.778 1133.333 315.333 c +f +*U +0.000 0.165 0.125 0.169 k +*u +1134 316 m +1135 315 l +1134 316 l +f +*U +0.000 0.275 0.200 0.145 k +*u +1294 316 m +1295 315 l +1294 316 l +f +*U +0.000 0.675 0.494 0.325 k +*u +1295 316 m +1294 314 l +1296 314 l +1296 315.853 1296.300 315.350 1295 316 c +f +*U +0.000 0.306 0.353 0.027 k +*u +1398.333 315.333 m +1398.278 315.278 1398.222 314.222 1398.667 314.667 c +1398.722 314.722 1398.777 315.778 1398.333 315.333 c +f +*U +0.000 0.000 0.000 0.106 k +*u +1481 312 m +1484.534 311.424 1486.762 313.397 1489 316 c +1486 314.955 1483.618 313.586 1481 312 c +f +*U +0.000 0.000 0.000 0.788 k +*u +1927 316 m +1928 315 l +1927 316 l +f +*U +0.000 0.000 0.000 0.859 k +*u +539 315 m +539 255 l +540.875 259.469 540 265.191 540 270 c +540 299 l +540 304 540.981 310.280 539 315 c +f +*U +0.000 0.000 0.000 0.125 k +*u +858 315 m +857 313.521 857 313.797 857 312 c +858.289 313.443 858.401 313.234 858 315 c +f +*U +0.000 0.459 0.424 0.192 k +*u +1050 315 m +1050 310 l +1050.830 312 1050.830 312.970 1050 315 c +f +*U +0.000 0.412 0.314 0.125 k +*u +1113 315 m +1114 314 l +1113 315 l +f +*U +0.000 0.286 0.208 0.231 k +*u +1121 315 m +1122 314 l +1121 315 l +f +*U +0.000 0.290 0.212 0.141 k +*u +1205 315 m +1206 314 l +1205 315 l +f +*U +0.000 0.396 0.286 0.176 k +*u +1283 315 m +1284 314 l +1283 315 l +f +*U +0.000 0.796 0.769 0.141 k +*u +1397 315 m +1397 306 l +1398.256 308.994 1398.256 312 1397 315 c +f +*U +0.000 0.000 0.000 0.816 k +*u +1461 315 m +1462 314 l +1461 315 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1485 315 m +1486 314 l +1485 315 l +f +1979 315 m +1980 314 l +1979 315 l +f +*U +0.000 0.000 0.000 0.710 k +*u +571 314 m +572 313 l +571 314 l +f +*U +0.000 0.000 0.000 0.094 k +*u +837 314 m +837 311 l +838.195 312.223 838.316 312.420 839 314 c +837 314 l +f +*U +0.000 0.000 0.000 0.816 k +*u +839 314 m +840 313 l +839 314 l +f +*U +0.000 0.533 0.424 0.467 k +*u +1113 314 m +1114.543 312.733 1115 312.511 1117 312 c +1115.542 313 1114.752 313.436 1113 314 c +f +*U +0.000 0.196 0.169 0.216 k +*u +1119 314 m +1120 313 l +1119 314 l +f +*U +0.000 0.427 0.376 0.573 k +*u +1132 314 m +1132 310 l +1132.710 311.759 1132.710 312.241 1132 314 c +f +*U +0.000 0.376 0.282 0.247 k +*u +1133 314 m +1134 313 l +1133 314 l +f +*U +0.000 0.188 0.165 0.110 k +*u +1206 314 m +1207 313 l +1206 314 l +f +*U +0.000 0.290 0.278 0.710 k +*u +1207 314 m +1208 313 l +1207 314 l +f +*U +0.000 0.710 0.490 0.290 k +*u +1208 314 m +1209 309 l +1210.274 310.341 1211 311.403 1212 313 c +1208 314 l +f +*U +0.000 0.467 0.373 0.533 k +*u +1294 314 m +1294 311 l +1294.696 312.554 1294.696 312.446 1294 314 c +f +*U +0.000 0.420 0.451 0.094 k +*u +1398 314 m +1398 309 l +1398.830 311 1398.830 311.970 1398 314 c +f +*U +0.000 0.000 0.000 0.733 k +*u +1943 314 m +1944 313 l +1943 314 l +f +*U +0.000 0.000 0.000 0.149 k +*u +1981 314 m +1982 310 l +1982.553 312 1982.303 312.332 1981 314 c +f +*U +0.000 0.000 0.000 0.792 k +*u +547 313 m +548 312 l +547 313 l +f +*U +0.000 0.000 0.000 0.137 k +*u +573 313 m +574.223 311.805 574.420 311.684 576 311 c +574.777 312.195 574.580 312.316 573 313 c +f +*U +0.000 0.000 0.000 0.663 k +*u +856 313 m +857 312 l +856 313 l +f +*U +0.000 0.000 0.000 0.620 k +*u +877 313 m +878 312 l +877 313 l +f +*U +0.000 0.341 0.271 0.118 k +*u +1117 313 m +1118 312 l +1117 313 l +f +*U +0.000 0.710 0.553 0.290 k +*u +1118.667 312.667 m +1118.222 312.222 1119.278 312.278 1119.333 312.333 c +1119.778 312.778 1118.722 312.722 1118.667 312.667 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1924 313 m +1923 311.255 1922.547 309.875 1922 308 c +1923.693 309.782 1924.375 310.581 1924 313 c +f +*U +0.000 0.000 0.000 0.631 k +*u +1925 313 m +1926 312 l +1925 313 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1929 313 m +1928.455 311.365 1928.635 311.545 1927 311 c +1928 304 l +1924 306 l +1923.274 303.821 1923.561 304.220 1922 305 c +1919.825 299.325 1918.419 294 1920 288 c +1915.576 288.690 1911.467 288.267 1912 283 c +1910 281 1910.814 278.697 1911 276 c +1916 280 l +1916.251 278.548 1916.315 278.248 1917 277 c +1919.259 277 1921.290 276.624 1923 278 c +1924.517 277 1925.339 276.613 1927 276 c +1928.276 277.915 1928.277 277 1927 279 c +1936.521 281.267 1947.251 280 1957 280 c +1966.749 280 1977.479 281.267 1987 279 c +1985.907 277 1985.838 276.265 1986 274 c +1987.819 275.365 1987 275.492 1989 275 c +1990 278 l +1992 273 l +1989.567 271.538 1988.823 270.712 1988 268 c +1992.365 267.405 1994.627 261.447 1997 258 c +1998.417 258.472 1998.814 258.814 2000 260 c +1999 257 l +2003.462 255.684 2008.227 255.219 2008 261 c +2008.957 259.483 2009.387 258.662 2010 257 c +2011.533 260 2010.509 262 2009 265 c +2006.539 265 2004.400 265.434 2002 266 c +2003.478 266.986 2003.204 267 2005 267 c +2003.352 267.924 2001.825 268.449 2000 269 c +2002 276 l +2000.488 277.653 1999.819 278.894 1999 281 c +1996 280 l +1994 283.445 1992.720 286 1992 290 c +1988.786 288.587 1986.946 289.231 1984 291 c +1983 288 l +1982 292 l +1981.317 290.494 1981.174 289.685 1981 288 c +1927 287 l +1927.931 292.260 1928.728 296.660 1929 302 c +1934.463 301.221 1935.407 305 1938 309 c +1935 313 l +1933 312.590 1932.298 312.465 1931 311 c +1929.977 312.534 1930.195 312.402 1929 313 c +f +*U +0.000 0.000 0.000 0.125 k +*u +1943 313 m +1942 311.255 1941.547 309.875 1941 308 c +1942.693 309.782 1943.375 310.581 1943 313 c +f +*U +0.000 0.000 0.000 0.627 k +*u +364 312 m +365 311 l +364 312 l +f +*U +0.000 0.000 0.000 0.259 k +*u +365 312 m +366 311 l +365 312 l +f +*U +0.000 0.000 0.000 0.106 k +*u +547 312 m +548.402 309.726 549.515 309 552 308 c +550.394 309.914 549.217 310.837 547 312 c +f +*U +0.000 0.000 0.000 0.600 k +*u +548 312 m +549 311 l +548 312 l +f +*U +0.000 0.000 0.000 0.624 k +*u +805 312 m +806 311 l +805 312 l +f +*U +0.000 0.000 0.000 0.137 k +*u +856 312 m +855 310.521 855 310.797 855 309 c +856.289 310.443 856.401 310.234 856 312 c +f +*U +0.000 0.522 0.341 0.000 k +*u +1208 312 m +1209 311 l +1208 312 l +f +*U +0.000 0.333 0.310 0.231 k +*u +1285 312 m +1286 311 l +1285 312 l +f +*U +0.000 0.612 0.420 0.373 k +*u +1295 312 m +1295 309 l +1295.696 310.554 1295.696 310.446 1295 312 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1453 312 m +1454 310 l +1455.635 310.545 1455.455 310.365 1456 312 c +1453 312 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1456 312 m +1457 311 l +1456 312 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1480 312 m +1481 311 l +1480 312 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1981 312 m +1982 311 l +1981 312 l +f +*U +0.000 0.000 0.000 0.537 k +*u +357 311 m +358 310 l +357 311 l +f +*U +0.000 0.000 0.000 0.129 k +*u +347 309 m +352.305 306.836 359.395 309.558 365 310 c +359.672 312.215 352.581 309.706 347 309 c +f +*U +0.000 0.000 0.000 0.671 k +*u +575 311 m +576 310 l +575 311 l +f +*U +0.000 0.000 0.000 0.098 k +*u +576 311 m +579.358 306.622 583.915 303 589 301 c +585.678 305.500 581 308.833 576 311 c +f +*U +0.000 0.000 0.000 0.545 k +*u +798 311 m +799 310 l +798 311 l +f +*U +0.000 0.000 0.000 0.141 k +*u +799 311 m +801.332 310 803.457 310 806 310 c +803.668 310.985 801.543 310.981 799 311 c +f +*U +0.000 0.000 0.000 0.110 k +*u +835 311 m +833 305 l +835.181 306.896 836 308.259 837 311 c +835 311 l +f +*U +0.000 0.000 0.000 0.620 k +*u +837 311 m +838 310 l +837 311 l +f +*U +0.000 0.000 0.000 0.078 k +*u +878 311 m +878.833 306.696 880.634 303.791 884 301 c +882.616 304.781 880.761 308 878 311 c +f +*U +0.000 0.000 0.000 0.224 k +*u +898 311 m +899 310 l +898 311 l +f +*U +0.000 0.251 0.208 0.102 k +*u +1133 311 m +1134 310 l +1133 311 l +f +*U +0.000 0.533 0.408 0.463 k +*u +1285 311 m +1285 308 l +1285.696 309.554 1285.696 309.446 1285 311 c +f +*U +0.000 0.329 0.239 0.224 k +*u +1294 311 m +1295 310 l +1294 311 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1449 309 m +1451.509 308.434 1452.220 309 1454 311 c +1449 309 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1476 309 m +1478 308.590 1478.962 309 1481 310 c +1478.860 310.410 1478 309.968 1476 309 c +f +*U +0.000 0.000 0.000 0.812 k +*u +1924 311 m +1925 310 l +1924 311 l +f +*U +0.000 0.000 0.000 0.878 k +*u +348.667 309.667 m +348.222 309.222 349.278 309.278 349.333 309.333 c +349.778 309.778 348.722 309.722 348.667 309.667 c +f +*U +0.000 0.000 0.000 0.569 k +*u +350 310 m +351 309 l +350 310 l +f +*U +0.000 0.000 0.000 0.643 k +*u +790.667 309.667 m +790.223 309.223 791.278 309.278 791.333 309.333 c +791.778 309.778 790.722 309.722 790.667 309.667 c +f +*U +0.000 0.000 0.000 0.188 k +*u +794 310 m +795.769 309.221 797 309 799 309 c +797.231 309.779 795.964 309.912 794 310 c +f +*U +0.000 0.000 0.000 0.749 k +*u +879 310 m +880 309 l +879 310 l +f +*U +0.000 0.000 0.000 0.129 k +*u +898 310 m +898.545 308.365 898.365 308.545 900 308 c +900 310 l +898 310 l +f +*U +0.000 0.471 0.400 0.412 k +*u +1050 310 m +1050 305 l +1050.830 307 1050.830 307.970 1050 310 c +f +*U +0.000 0.639 0.463 0.341 k +*u +1133 310 m +1133.684 308.420 1133.805 308.223 1135 307 c +1134.316 308.580 1134.195 308.777 1133 310 c +f +*U +0.000 0.294 0.243 0.118 k +*u +1134 310 m +1135 309 l +1134 310 l +f +*U +0.000 0.306 0.239 0.694 k +*u +1208 310 m +1209 309 l +1208 310 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1453 310 m +1454 309 l +1453 310 l +f +*U +0.000 0.000 0.000 0.000 k +*u +1818 310 m +1818 306 l +1865 306 l +1861.301 307.552 1856.983 307 1853 307 c +1832 307 l +1826.819 307 1821.973 306.207 1818 310 c +f +*U +0.000 0.000 0.000 0.090 k +*u +1983 310 m +1985 305 l +1985.710 307.530 1985 308.516 1983 310 c +f +*U +0.000 0.000 0.000 0.169 k +*u +171 309 m +174.699 307.448 179 308 183 308 c +203 308 l +206.567 308 211.649 308.869 214.852 306.972 c +219.877 303.997 219 294 212.956 293 c +199 290.846 183 293 169 293 c +172.699 291.448 177 292 181 292 c +204 292 l +207.652 292 213.326 290.952 216.682 292.603 c +220 294.282 220 304.700 217.972 307.397 c +215.739 310.216 209 309 206 309 c +171 309 l +f +*U +0.000 0.000 0.000 0.678 k +*u +552 309 m +553 308 l +552 309 l +f +*U +0.000 0.133 0.149 0.169 k +*u +1135 309 m +1136 308 l +1135 309 l +f +*U +0.000 0.294 0.239 0.051 k +*u +1286 309 m +1287 308 l +1286 309 l +f +*U +0.000 0.290 0.196 0.357 k +*u +1295 309 m +1296 308 l +1295 309 l +f +*U +0.000 0.478 0.478 0.522 k +*u +1296 309 m +1297 308 l +1296 309 l +f +*U +0.000 1.000 0.725 0.000 k +*u +1297 309 m +1298.223 307.805 1298.420 307.684 1300 307 c +1298.777 308.195 1298.580 308.316 1297 309 c +f +*U +0.000 0.463 0.361 0.443 k +*u +1398 309 m +1398 306 l +1398.696 307.554 1398.696 307.446 1398 309 c +f +*U +0.000 0.000 0.000 0.710 k +*u +1475 309 m +1476 308 l +1475 309 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1940 309 m +1941 308 l +1940 309 l +f +*U +0.000 0.000 0.000 0.000 k +*u +169 308 m +173.720 306 179.920 307 185 307 c +216 307 l +211.280 308.981 205 308 200 308 c +169 308 l +f +*U +0.000 0.000 0.000 0.859 k +*u +402 308 m +408.436 305.299 418 307 425 307 c +477 307 l +470.564 309.701 460.951 308 454 308 c +402 308 l +f +*U +0.000 0.000 0.000 0.149 k +*u +853 308 m +853 306 l +854.635 306.545 854.455 306.365 855 308 c +853 308 l +f +*U +0.000 0.000 0.000 0.765 k +*u +899 308 m +900 307 l +899 308 l +f +*U +0.000 0.000 0.000 0.122 k +*u +900 308 m +900.810 305.778 901.739 304 903 302 c +903.410 304.888 902 306 900 308 c +f +*U +0.000 0.537 0.416 0.463 k +*u +1135 308 m +1132.692 306.241 1130.908 306 1128 306 c +1130.278 304.900 1136.531 303.938 1135 308 c +f +*U +0.000 0.376 0.282 0.624 k +*u +1211 308 m +1212 307 l +1211 308 l +f +*U +0.000 0.882 0.592 0.118 k +*u +1216 307 m +1222.194 304.401 1231.314 306 1238 306 c +1285 306 l +1278.650 309.376 1269.998 308 1263 308 c +1247.304 308 1231.625 307 1216 307 c +f +*U +0.000 0.471 0.345 0.212 k +*u +1286 308 m +1287 307 l +1286 308 l +f +*U +0.000 0.392 0.322 0.267 k +*u +1296 308 m +1297 307 l +1296 308 l +f +*U +0.000 0.361 0.271 0.482 k +*u +1297.333 307.333 m +1297.278 307.278 1297.222 306.222 1297.667 306.667 c +1297.722 306.722 1297.778 307.778 1297.333 307.333 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1466 303 m +1470 302.321 1473.438 305 1476 308 c +1472.360 306.848 1469.252 304.988 1466 303 c +f +*U +0.000 0.000 0.000 0.173 k +*u +1819 308 m +1823.720 306 1829.920 307 1835 307 c +1845.467 307 1856.647 305.862 1867 307 c +1862.280 308.981 1856 308 1851 308 c +1819 308 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1922 308 m +1923 307 l +1922 308 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1940 308 m +1939 306.255 1938.547 304.875 1938 303 c +1939.693 304.782 1940.375 305.581 1940 308 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1965 308 m +1966 307 l +1965 308 l +f +*U +0.000 0.000 0.000 0.098 k +*u +553 307 m +554.223 305.805 554.420 305.684 556 305 c +554.777 306.195 554.580 306.316 553 307 c +f +*U +0.000 0.000 0.000 0.812 k +*u +881 307 m +882 306 l +881 307 l +f +*U +0.000 0.027 0.016 0.541 k +*u +1136 307 m +1137 306 l +1136 307 l +f +*U +0.000 0.302 0.208 0.086 k +*u +1211 307 m +1212 306 l +1211 307 l +f +*U +0.000 0.475 0.380 0.525 k +*u +1212 307 m +1214.718 303.890 1220 305 1224 305 c +1220.304 306.551 1215.951 306 1212 307 c +f +*U +0.000 0.518 0.404 0.482 k +*u +1280 306 m +1283.698 304.448 1288 305 1292 305 c +1288.552 307.402 1284 306 1280 306 c +f +*U +0.000 0.349 0.224 0.188 k +*u +1291 307 m +1292 306 l +1291 307 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1448 307 m +1449 306 l +1448 307 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1920.333 306.333 m +1920.278 306.278 1920.222 305.222 1920.667 305.667 c +1920.722 305.722 1920.778 306.778 1920.333 306.333 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1965 307 m +1965.526 304.457 1965.878 303.465 1968 302 c +1967.251 304.254 1966.656 305.313 1965 307 c +f +*U +0.000 0.000 0.000 0.000 k +*u +217 306 m +217 295 l +218.431 298.410 218.431 302.590 217 306 c +f +*U +0.000 0.000 0.000 0.765 k +*u +556 306 m +557 305 l +556 306 l +f +*U +0.000 0.000 0.000 0.816 k +*u +834 306 m +835 305 l +834 306 l +f +*U +0.000 0.000 0.000 0.145 k +*u +852.333 305.333 m +852.278 305.278 852.222 304.222 852.667 304.667 c +852.722 304.722 852.778 305.778 852.333 305.333 c +f +*U +0.000 0.392 0.298 0.608 k +*u +1051 306 m +1057.678 303.198 1067.784 305 1075 305 c +1128 305 l +1121.322 307.802 1111.216 306 1104 306 c +1051 306 l +f +*U +0.000 0.047 0.035 0.816 k +*u +1136 306 m +1137 305 l +1136 306 l +f +*U +0.000 0.392 0.298 0.608 k +*u +1224 306 m +1229.217 303.811 1236.381 305 1242 305 c +1280 305 l +1274.784 307.189 1267.619 306 1262 306 c +1224 306 l +f +*U +0.000 0.235 0.149 0.357 k +*u +1292 306 m +1293 305 l +1292 306 l +f +*U +0.000 0.333 0.227 0.435 k +*u +1298 306 m +1299 305 l +1298 306 l +f +*U +0.000 0.392 0.298 0.608 k +*u +1299 306 m +1307 302.593 1320.203 305 1329 305 c +1398 305 l +1389.882 308.407 1376.797 306 1368 306 c +1299 306 l +f +*U +0.000 0.247 0.216 0.349 k +*u +1398 306 m +1399 305 l +1398 306 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1470 306 m +1471 305 l +1470 306 l +f +*U +0.000 0.000 0.000 0.627 k +*u +1760 306 m +1761 305 l +1760 306 l +f +*U +0.000 0.000 0.000 0.851 k +*u +1865 306 m +1865 293 l +1866.591 296.791 1866.591 302.209 1865 306 c +f +*U +0.000 0.000 0.000 0.129 k +*u +1866 306 m +1866 292 l +1867.667 295.972 1867.667 302 1866 306 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1918 304 m +1921 304 l +1920 306 l +1918.365 305.455 1918.545 305.635 1918 304 c +f +*U +0.000 0.000 0.000 0.800 k +*u +1938 306 m +1939 305 l +1938 306 l +f +*U +0.000 0.000 0.000 0.718 k +*u +851 305 m +852 304 l +851 305 l +f +*U +0.000 0.000 0.000 0.690 k +*u +882 305 m +883 304 l +882 305 l +f +*U +0.000 0.000 0.000 0.682 k +*u +901 305 m +902 304 l +901 305 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1468 305 m +1469 304 l +1468 305 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1986 305 m +1987 304 l +1986 305 l +f +*U +0.000 0.875 0.624 0.125 k +*u +0 304 m +3.415 275.239 0.989 244.987 1 216 c +1 207 1.178 189 10 184 c +9 187 l +16 187 l +16 192 l +13.603 192 10.582 191.716 8.742 193.603 c +4.524 197.931 8 211.340 8 217 c +8 296 l +25 296 l +25 303 l +16.661 303 8.226 302.473 0 304 c +f +*U +0.000 0.745 0.553 0.137 k +*u +2 304 m +8.928 301 19.503 303 27 303 c +20 305.907 9.497 304 2 304 c +f +*U +0.000 0.529 0.424 0.471 k +*u +27 304 m +27 216 l +29.497 221.951 28 230.580 28 237 c +28 281 l +28 287.951 29.701 297.564 27 304 c +f +*U +0.000 0.000 0.000 0.827 k +*u +584 304 m +585 303 l +584 304 l +f +*U +0.000 0.000 0.000 0.212 k +*u +832 304 m +833 303 l +832 304 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1918 304 m +1917 300 l +1918.434 301.393 1919 302.233 1920 304 c +1918 304 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1937 304 m +1938 303 l +1937 304 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1986 304 m +1987 303 l +1986 304 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1987 304 m +1987.547 302 1988 300.745 1989 299 c +1989.566 301.509 1988.847 302.220 1987 304 c +f +*U +0.000 0.878 0.631 0.122 k +*u +25 303 m +25 296 l +8 296 l +8 217 l +8 211.280 7 205.681 7 200 c +6.995 197.774 6.812 194.596 8.742 193 c +10.581 191.534 13.806 192 16 192 c +16 187 l +9 187 l +14.729 166.871 38 164 56 164 c +53.463 166 51.218 166.670 48 167 c +58.732 170.394 70.870 169 82 169 c +143 169 l +347 169 l +573.316 169 799.773 168 1026 168 c +1023.904 166.957 1022.301 166.397 1020 166 c +1023.746 164.425 1028 164.434 1032 163 c +1026.917 159.292 1028.860 154.570 1034 152 c +1034.482 147.602 1037.710 144.720 1042 144 c +1043.302 137.874 1051.372 127.403 1058 127 c +1060 121 l +1065.645 117.731 1070.265 112.945 1075.455 108.999 c +1084.809 101.890 1094.383 95 1104.385 88.790 c +1134.840 69.853 1172.407 57.574 1208 53.835 c +1230.812 51.439 1255.294 52.482 1278 56.194 c +1287.576 57.760 1297.239 62.310 1307 62 c +1312.651 67 1322.939 65.752 1327 72 c +1332.257 72 1337.333 75 1342 77.400 c +1351.411 82 1360 86.993 1368.950 92.731 c +1372.926 95.325 1375.304 98.590 1380 100 c +1380 104 l +1387 103.403 1392.546 110.925 1397.458 115.326 c +1406 123 1415.699 131.761 1422.624 141 c +1426 145.676 1429.982 150.383 1433 155.286 c +1434.874 157.982 1436 161.339 1439 162.972 c +1441.710 164.417 1445 163.998 1448 164 c +1449.545 169 1453.191 168.990 1458 169 c +1478 169 l +1571 169 l +1827 169 l +1918 169 l +1932.570 169 1948.564 170.879 1962.985 168.856 c +1966.189 168.407 1968.792 166.496 1972 166 c +1971.613 163.910 1971.616 164.289 1974 164 c +1975 149.673 1975 135.396 1975 121 c +1982.528 124.210 1989 130.403 1996 134.640 c +2016 146.761 2035.364 160.180 2055 173 c +2051.417 177.778 2043.203 182.381 2037 186 c +2034 187.663 2030.666 188.867 2028 191 c +2029 192 l +2022.569 194 2017.566 198.699 2012 202.371 c +2005 206.960 1997.472 210.666 1990.434 215 c +1985.255 218.421 1981 222.529 1975 224 c +1975 212.795 1977.422 198.436 1973 188 c +1974.801 186.685 1974.833 186.277 1975 184 c +1973.814 185 1973.396 185.339 1972 186 c +1968.765 183.562 1963.922 184 1960 184 c +1933 184 l +1828 184 l +1560 184 l +1472 184 l +1457.950 184 1442.908 185.529 1429 184 c +1424.554 188.593 1420.781 180.451 1418.570 177.454 c +1414.841 172.400 1410.443 167.829 1406.669 162.831 c +1403.309 158.382 1400.831 152.978 1397 149 c +1397.661 147.603 1397.964 147.187 1399 146 c +1397 145.930 1397 145.646 1396 147 c +1388.668 143.421 1383.819 135.383 1378 130 c +1379.943 129.378 1380.949 129.564 1383 130 c +1379.505 128.242 1376 128.553 1374 125 c +1369.507 125 1366.900 121.701 1363.485 119 c +1359.730 116 1355.532 113.778 1351.579 111 c +1336.876 101.279 1321.828 93.423 1304.999 87.715 c +1298.627 85.554 1292.888 81.909 1286 83 c +1279.646 78 1268.692 78.522 1261 77.421 c +1240.338 74.461 1219.358 75.788 1199 79.625 c +1192.383 80.872 1185.525 80.815 1179 82.795 c +1170.709 85.311 1162 87.656 1154 91 c +1149.521 92.958 1146 96.249 1141 96 c +1137.817 100.206 1130 102.419 1125.428 105 c +1116.708 109.812 1108.985 116 1100.910 121.890 c +1098 123.857 1090.870 130.413 1088 128 c +1077.695 141 1064.620 151.726 1054.411 164.985 c +1049.525 171.332 1045.859 180.996 1037.780 184.219 c +1032.550 186.306 1022.720 184 1017 184 c +967 184 l +792 184 l +289 184 l +126 184 l +74 184 l +62.741 184 51 183.376 40 185 c +40.986 186.479 41 186.203 41 188 c +37 188 l +35.781 191.439 33.303 192.655 30 194 c +30.636 201.291 27 208.512 27 216 c +27 303 l +25 303 l +f +*U +0.000 0.000 0.000 0.220 k +*u +559 303 m +560 302 l +559 303 l +f +*U +0.000 0.000 0.000 0.800 k +*u +560 303 m +561 302 l +560 303 l +f +*U +0.000 0.000 0.000 0.090 k +*u +831 303 m +830 301.521 830 301.797 830 300 c +831.289 301.443 831.401 301.234 831 303 c +f +*U +0.000 0.000 0.000 0.733 k +*u +832 303 m +833 302 l +832 303 l +f +*U +0.000 0.000 0.000 0.133 k +*u +850 303 m +848.817 300.672 847.777 298.489 847 296 c +849.256 298 850.728 299.867 850 303 c +f +*U +0.000 0.000 0.000 0.624 k +*u +1465 303 m +1466 302 l +1465 303 l +f +*U +0.000 0.000 0.000 0.153 k +*u +1701 302 m +1706.217 299.811 1713.381 301 1719 301 c +1731.812 301 1746.506 299 1759 302 c +1753.902 303.568 1746.469 302 1741 302 c +1701 302 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1919 303 m +1920 302 l +1919 303 l +f +*U +0.000 0.000 0.000 0.275 k +*u +1937 303 m +1938 302 l +1937 303 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1968 303 m +1969 302 l +1968 303 l +f +*U +0.000 0.000 0.000 0.820 k +*u +849 302 m +850 301 l +849 302 l +f +*U +0.000 0.000 0.000 0.804 k +*u +884 302 m +885 301 l +884 302 l +f +*U +0.000 0.000 0.000 0.608 k +*u +903 302 m +904 301 l +903 302 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1463 302 m +1464 301 l +1463 302 l +f +*U +0.000 0.000 0.000 0.118 k +*u +1460 300 m +1462.187 297.968 1464 296.906 1467 296 c +1465.771 297.870 1465 298.224 1463 299 c +1466 301 l +1463.726 301.409 1462.219 300.788 1460 300 c +f +*U +0.000 0.000 0.000 0.596 k +*u +1757 302 m +1758 301 l +1757 302 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1936 302 m +1934.216 298.641 1932.268 295.810 1932 292 c +1934.509 294.996 1936.347 298.460 1938 302 c +1936 302 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1968 302 m +1968.683 300.420 1968.805 300.222 1970 299 c +1969.316 300.580 1969.195 300.777 1968 302 c +f +*U +0.000 0.631 0.420 0.365 k +*u +0 301 m +0 208 l +2.802 214.678 1 224.784 1 232 c +1 279 l +1 285.686 2.599 294.806 0 301 c +f +*U +0.000 0.000 0.000 0.106 k +*u +561 301 m +562.450 299.392 563 298.936 565 298 c +563.550 299.608 562.949 300 561 301 c +f +*U +0.000 0.000 0.000 0.796 k +*u +588 301 m +589 300 l +588 301 l +f +*U +0.000 0.000 0.000 0.133 k +*u +589 301 m +590.450 299.392 591 298.936 593 298 c +591.550 299.608 590.949 300 589 301 c +f +*U +0.000 0.000 0.000 0.106 k +*u +884 301 m +884.651 298.566 885 297.717 887 296 c +886.251 298.254 885.656 299.314 884 301 c +f +*U +0.000 0.000 0.000 0.137 k +*u +905 301 m +906 297 l +906.393 298.924 906 299.360 905 301 c +f +*U +0.000 0.000 0.000 0.843 k +*u +1698 301 m +1703.217 298.811 1710.381 300 1716 300 c +1753 300 l +1747.783 302.189 1740.619 301 1735 301 c +1698 301 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1780 301 m +1781 300 l +1780 301 l +f +*U +0.000 0.000 0.000 0.596 k +*u +830 300 m +831 299 l +830 300 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1916 300 m +1915 298.255 1914.547 296.875 1914 295 c +1915.693 296.782 1916.375 297.581 1916 300 c +f +*U +0.000 0.000 0.000 0.659 k +*u +1917 300 m +1918 299 l +1917 300 l +f +*U +0.000 0.000 0.000 0.671 k +*u +565 299 m +566 298 l +565 299 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1461 299 m +1462 298 l +1461 299 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1970.333 298.333 m +1970.278 298.278 1970.222 297.222 1970.667 297.667 c +1970.722 297.722 1970.778 298.778 1970.333 298.333 c +f +*U +0.000 0.000 0.000 0.729 k +*u +1989 299 m +1990 298 l +1989 299 l +f +*U +0.000 0.000 0.000 0.243 k +*u +1990 299 m +1991 298 l +1990 299 l +f +*U +0.000 0.000 0.000 0.129 k +*u +565 298 m +565.545 296.365 565.365 296.545 567 296 c +567 298 l +565 298 l +f +*U +0.000 0.000 0.000 0.643 k +*u +592 298 m +593 297 l +592 298 l +f +*U +0.000 0.000 0.000 0.322 k +*u +593 298 m +594 297 l +593 298 l +f +*U +0.000 0.000 0.000 0.831 k +*u +829 298 m +830 297 l +829 298 l +f +*U +0.000 0.000 0.000 0.596 k +*u +1971 298 m +1972 297 l +1971 298 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1990 298 m +1990.545 296.365 1990.365 296.545 1992 296 c +1992 298 l +1990 298 l +f +*U +0.000 0.000 0.000 0.812 k +*u +593 297 m +594 296 l +593 297 l +f +*U +0.000 0.000 0.000 0.090 k +*u +594 297 m +595.223 295.805 595.420 295.684 597 295 c +596 296.783 596 296.594 594 297 c +f +*U +0.000 0.000 0.000 0.173 k +*u +827.333 296.333 m +827.278 296.278 827.222 295.222 827.667 295.667 c +827.722 295.722 827.778 296.778 827.333 296.333 c +f +*U +0.000 0.000 0.000 0.776 k +*u +846 297 m +847 296 l +846 297 l +f +*U +0.000 0.000 0.000 0.690 k +*u +887 297 m +888 296 l +887 297 l +f +*U +0.000 0.000 0.000 0.114 k +*u +907 297 m +907.810 294.778 908.739 293 910 291 c +910.410 293.888 909 295 907 297 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1779 297 m +1780 296 l +1779 297 l +f +*U +0.000 0.000 0.000 0.063 k +*u +1971 297 m +1973 291 l +1973.744 293.735 1972.915 294.968 1971 297 c +f +*U +0.000 0.000 0.000 0.725 k +*u +569 296 m +570 295 l +569 296 l +f +*U +0.000 0.000 0.000 0.129 k +*u +846 296 m +843 290 l +891 290 l +890.190 292.222 889.261 293.990 888 296 c +887.590 293.860 888 293 889 291 c +845 291 l +846 293 846.577 293.769 846 296 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1466 296 m +1467 295 l +1466 296 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1467.667 295.667 m +1467.222 295.222 1468.278 295.278 1468.333 295.333 c +1468.778 295.778 1467.722 295.722 1467.667 295.667 c +f +*U +0.000 0.000 0.000 0.149 k +*u +1779.333 295.333 m +1779.278 295.278 1779.222 294.222 1779.667 294.667 c +1779.722 294.722 1779.778 295.778 1779.333 295.333 c +f +*U +0.000 0.000 0.000 0.773 k +*u +1932 296 m +1933 295 l +1932 296 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1992 296 m +1993 293 1994.415 290.618 1996 288 c +1996.576 291.534 1994.603 293.762 1992 296 c +f +*U +0.000 0.000 0.000 0.235 k +*u +569 295 m +570 294 l +569 295 l +f +*U +0.000 0.000 0.000 0.749 k +*u +596 295 m +597 294 l +596 295 l +f +*U +0.000 0.000 0.000 0.133 k +*u +597 295 m +599.319 292 601.622 290.432 605 289 c +602.701 291.971 600.505 293.641 597 295 c +f +*U +0.000 0.000 0.000 0.102 k +*u +826 295 m +825 293.521 825 293.797 825 292 c +826.289 293.443 826.401 293.234 826 295 c +f +*U +0.000 0.000 0.000 0.765 k +*u +827 295 m +828 294 l +827 295 l +f +*U +0.000 0.278 0.173 0.082 k +*u +1051 295 m +1058.399 291.895 1069.993 294 1078 294 c +1138 294 l +1130.600 297 1119 295 1111 295 c +1051 295 l +f +*U +0.000 0.263 0.196 0.192 k +*u +1138 295 m +1139.248 294.315 1139.548 294.251 1141 294 c +1139.752 294.685 1139.451 294.749 1138 295 c +f +*U +0.000 0.278 0.173 0.082 k +*u +1213 293 m +1221.624 295 1231.174 294 1240 294 c +1287 294 l +1281.784 296.189 1274.619 295 1269 295 c +1231 295 l +1226 295 1216.407 296.899 1213 293 c +f +*U +0.000 0.271 0.243 0.180 k +*u +1296 295 m +1297.248 294.315 1297.548 294.251 1299 294 c +1297.751 294.685 1297.452 294.749 1296 295 c +f +*U +0.000 0.267 0.196 0.063 k +*u +1299 295 m +1302 293.673 1305.586 294 1309 294 c +1305.837 295.327 1302.415 295.000 1299 295 c +f +*U +0.000 0.278 0.227 0.157 k +*u +1313 295 m +1314.248 294.315 1314.548 294.251 1316 294 c +1314.752 294.685 1314.451 294.749 1313 295 c +f +*U +0.000 0.353 0.286 0.043 k +*u +1316 295 m +1317.506 294.317 1318.315 294.174 1320 294 c +1318.494 294.683 1317.685 294.826 1316 295 c +f +*U +0.000 0.278 0.173 0.082 k +*u +1320 295 m +1326.919 292 1337.520 294 1345 294 c +1399 294 l +1392 296.903 1381.480 295 1374 295 c +1320 295 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1468 295 m +1469 294 l +1468 295 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1469 295 m +1470.223 293.805 1470.420 293.684 1472 293 c +1470.777 294.195 1470.580 294.316 1469 295 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1778 295 m +1779 294 l +1778 295 l +f +*U +0.000 0.000 0.000 0.090 k +*u +1913 295 m +1911.952 293 1911.487 292 1911 290 c +1912.693 291.782 1913.375 292.581 1913 295 c +f +*U +0.000 0.000 0.000 0.796 k +*u +1914 295 m +1915 294 l +1914 295 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1973 295 m +1974 294 l +1973 295 l +f +*U +0.000 0.000 0.000 0.843 k +*u +169 294 m +173.720 292 179.920 293 185 293 c +217 293 l +212.280 294.981 206 294 201 294 c +169 294 l +f +*U +0.000 0.000 0.000 0.824 k +*u +889 294 m +890 293 l +889 294 l +f +*U +0.000 0.000 0.000 0.792 k +*u +908 294 m +909 293 l +908 294 l +f +*U +0.000 0.506 0.506 0.494 k +*u +1050.333 293.333 m +1050.278 293.278 1050.222 292.222 1050.667 292.667 c +1050.722 292.722 1050.778 293.778 1050.333 293.333 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1051 294 m +1055 291 l +1062 294.980 1073 293 1081 293 c +1140 293 l +1140 289 l +1140.779 290.769 1140.912 292 1141 294 c +1051 294 l +f +*U +0.000 0.522 0.345 0.471 k +*u +1214.333 293.333 m +1214.278 293.278 1214.222 292.222 1214.667 292.667 c +1214.722 292.722 1214.778 293.778 1214.333 293.333 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1215 294 m +1221.194 291.401 1230.314 293 1237 293 c +1254.524 293 1273.751 295.202 1291 292 c +1285.726 295.996 1275.423 294 1269 294 c +1215 294 l +f +*U +0.149 0.000 0.008 0.133 k +*u +1295.333 293.333 m +1295.278 293.278 1295.222 292.222 1295.667 292.667 c +1295.722 292.723 1295.777 293.778 1295.333 293.333 c +f +*U +0.000 0.702 0.557 0.298 k +*u +1296 294 m +1296 289 l +1296.683 290.506 1296.826 291.315 1297 293 c +1305 293 l +1302 294.213 1299 293.998 1296 294 c +f +*U +0.000 0.882 0.624 0.118 k +*u +1297 293 m +1297 289 l +1284.958 293.668 1273.859 293 1261 293 c +1215 293 l +1216 287 l +1216.685 288.248 1216.749 288.549 1217 290 c +1224 290 l +1221.894 289.356 1220.205 289 1218 289 c +1218 283 l +1250.935 281.586 1284 282 1317 282 c +1315.600 285 1314 287.825 1313 291 c +1310.566 291.651 1309.717 292 1308 294 c +1304.305 293.533 1300.735 293 1297 293 c +f +*U +0.000 0.635 0.463 0.365 k +*u +1308 294 m +1308.899 291.876 1308.876 291.899 1311 291 c +1309.897 292.457 1309.457 292.897 1308 294 c +f +*U +0.000 0.392 0.310 0.580 k +*u +1313 294 m +1314 293 l +1313 294 l +f +*U +0.000 0.745 0.557 0.255 k +*u +1312 291 m +1313 290 l +1314.596 290.959 1315.659 291.726 1317 293 c +1314.333 293 1313.893 292.911 1312 291 c +f +*U +0.000 0.667 0.663 0.298 k +*u +1316 294 m +1319.448 291.598 1323.896 292.966 1328 293 c +1324.302 294.551 1319.983 294 1316 294 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1328 294 m +1334.194 291.401 1343.314 293 1350 293 c +1398 293 l +1391.806 295.599 1382.686 294 1376 294 c +1328 294 l +f +*U +0.000 0.420 0.424 0.176 k +*u +1398 294 m +1398 290 l +1398.710 291.759 1398.710 292.241 1398 294 c +f +*U +0.000 0.000 0.000 0.055 k +*u +1767 286 m +1772.368 286.838 1777.190 289.221 1780 294 c +1775.951 292.207 1769.735 289.435 1767 286 c +f +*U +0.000 0.000 0.000 0.137 k +*u +402 293 m +408.436 290.299 418 292 425 292 c +475 292 l +475 255 l +476.661 258.959 476 263.740 476 268 c +476 293 l +402 293 l +f +*U +0.000 0.000 0.000 0.635 k +*u +476 293 m +476 255 l +477.441 258.435 477 262.298 477 266 c +477 274 479 285.600 476 293 c +f +*U +0.000 0.000 0.000 0.086 k +*u +572 293 m +573.573 290.338 575 289.228 578 288 c +576.170 290.348 574.637 291.617 572 293 c +f +*U +0.000 0.000 0.000 0.816 k +*u +573 293 m +574 292 l +573 293 l +f +*U +0.000 0.859 0.608 0.137 k +*u +1051 293 m +1052 283 l +1079.394 279.538 1108.379 282 1136 282 c +1136 284 l +1056 284 l +1062.584 285.946 1070 285 1077 285 c +1117 285 l +1123.705 285 1132.831 286.880 1138 282 c +1140 282 l +1140.890 285.870 1140.490 289 1140 293 c +1078 293 l +1072.473 293 1059.796 295.344 1056 291 c +1054.175 292.336 1053.247 292.690 1051 293 c +f +*U +0.000 0.522 0.365 0.122 k +*u +1291 293 m +1292 292 l +1291 293 l +f +*U +0.000 0.267 0.212 0.039 k +*u +1312 293 m +1313 292 l +1312 293 l +f +*U +0.000 0.871 0.624 0.129 k +*u +1319 292 m +1320.249 291.315 1320.548 291.251 1322 291 c +1320.722 288 1319.830 285 1319 282 c +1397 282 l +1397 293 l +1346 293 l +1337.393 293 1327.280 294.448 1319 292 c +f +*U +0.000 0.898 0.851 0.047 k +*u +1397 293 m +1397 290 l +1397.696 291.554 1397.696 291.446 1397 293 c +f +*U +0.000 0.000 0.000 0.098 k +*u +1472 293 m +1473.458 291.919 1474.248 291.564 1476 291 c +1474.457 292.267 1473.952 292.489 1472 293 c +f +*U +0.000 0.000 0.000 0.839 k +*u +1818 293 m +1822.720 291 1828.920 292 1834 292 c +1865 292 l +1860.280 293.981 1854 293 1849 293 c +1818 293 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1865 293 m +1866 292 l +1865 293 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1931 293 m +1929 289 l +1976 289 l +1975 293 l +1974.315 291.752 1974.251 291.452 1974 290 c +1960 291.554 1945 290 1931 290 c +1931.400 291.650 1931.479 291.502 1931 293 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1993 293 m +1994 292 l +1993 293 l +f +*U +0.000 0.000 0.000 0.165 k +*u +344 290 m +348 291 l +345.954 291.751 345.404 291.656 344 290 c +f +*U +0.000 0.000 0.000 0.078 k +*u +348 292 m +348 290 l +350 290 l +350 292 l +348 292 l +f +*U +0.000 0.000 0.000 0.722 k +*u +600 292 m +601 291 l +600 292 l +f +*U +0.000 0.000 0.000 0.082 k +*u +784 292 m +784 271 l +786 271 l +786 277.541 786.862 284.699 785 291 c +792 290 798.934 288.303 806 288 c +806 272 l +807.797 272 807.521 272 809 273 c +808 277 809.393 284 806.972 287.486 c +805.447 289.622 802.364 289.842 800 290.245 c +794.702 291 789.378 291.955 784 292 c +f +*U +0.000 0.000 0.000 0.078 k +*u +823 292 m +821.770 289.365 820.766 286.804 820 284 c +822.573 286.383 823.933 288.660 825 292 c +823 292 l +f +*U +0.000 0.000 0.000 0.624 k +*u +825 292 m +826 291 l +825 292 l +f +*U +0.000 0.000 0.000 0.616 k +*u +843 292 m +844 291 l +843 292 l +f +*U +0.000 0.584 0.439 0.329 k +*u +1050 292 m +1050 289 l +1050.696 290.554 1050.696 290.446 1050 292 c +f +*U +0.000 0.259 0.153 0.408 k +*u +1153 292 m +1154 291 l +1153 292 l +f +*U +0.000 0.314 0.184 0.043 k +*u +1154 292 m +1155 291 l +1154 292 l +f +*U +0.000 0.427 0.282 0.098 k +*u +1214 292 m +1215 291 l +1214 292 l +f +*U +0.000 0.447 0.314 0.400 k +*u +1291.667 291.667 m +1291.222 291.222 1292.278 291.278 1292.333 291.333 c +1292.778 291.778 1291.722 291.722 1291.667 291.667 c +f +*U +0.000 0.102 0.059 0.082 k +*u +1295.333 291.333 m +1295.278 291.278 1295.222 290.222 1295.667 290.667 c +1295.722 290.723 1295.777 291.778 1295.333 291.333 c +f +*U +0.000 0.400 0.282 0.098 k +*u +1311 292 m +1312 291 l +1311 292 l +f +*U +0.000 0.318 0.388 0.267 k +*u +1315 292 m +1316.506 291.317 1317.315 291.174 1319 291 c +1317.494 291.683 1316.685 291.826 1315 292 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1446 292 m +1446 264 l +1446 260.293 1445 255.582 1448 253 c +1446.414 261.541 1447 270.342 1447 279 c +1447 283.260 1447.661 288 1446 292 c +f +*U +0.000 0.000 0.000 0.776 k +*u +1473 292 m +1474 291 l +1473 292 l +f +*U +0.000 0.000 0.000 0.161 k +*u +1818 292 m +1822.720 290 1828.920 291 1834 291 c +1866 291 l +1861.280 292.981 1855 292 1850 292 c +1818 292 l +f +*U +0.000 0.000 0.000 0.078 k +*u +169 291 m +169 271 l +171 271 l +171 291 l +169 291 l +f +*U +0.000 0.000 0.000 0.106 k +*u +343 291 m +343 272 l +345 272 l +345 277.819 346.627 286.213 343 291 c +f +*U +0.000 0.000 0.000 0.894 k +*u +345.667 290.667 m +345.222 290.222 346.278 290.278 346.333 290.333 c +346.778 290.778 345.722 290.722 345.667 290.667 c +f +*U +0.000 0.000 0.000 0.600 k +*u +347 291 m +348 290 l +347 291 l +f +*U +0.000 0.000 0.000 0.169 k +*u +350 291 m +351.506 290.317 352.315 290.174 354 290 c +352.494 290.683 351.685 290.826 350 291 c +f +*U +0.000 0.000 0.000 0.082 k +*u +402 291 m +402 254 l +406.630 260.777 403.860 274 404 282 c +404 285.548 405 288.710 402 291 c +f +*U +0.000 0.000 0.000 0.243 k +*u +785 291 m +786 290 l +785 291 l +f +*U +0.000 0.000 0.000 0.541 k +*u +788 291 m +789 290 l +788 291 l +f +*U +0.000 0.000 0.000 0.808 k +*u +891.333 290.333 m +891.278 290.278 891.222 289.222 891.667 289.667 c +891.722 289.722 891.778 290.778 891.333 290.333 c +f +*U +0.000 0.000 0.000 0.710 k +*u +910 291 m +911 290 l +910 291 l +f +*U +0.000 0.000 0.000 0.102 k +*u +911 291 m +912.305 286.905 914.607 283.550 917 280 c +917.717 284.411 914 288.208 911 291 c +f +*U +0.000 0.133 0.122 0.078 k +*u +1141 291 m +1142 290 l +1141 291 l +f +*U +0.000 0.408 0.275 0.004 k +*u +1152.333 290.333 m +1152.278 290.278 1152.222 289.222 1152.667 289.667 c +1152.722 289.722 1152.777 290.778 1152.333 290.333 c +f +*U +0.000 0.698 0.522 0.302 k +*u +1153 288 m +1154.560 288.596 1155.623 289 1157 290 c +1154.303 290.854 1153.614 290.851 1153 288 c +f +*U +0.000 0.263 0.129 0.310 k +*u +1156 291 m +1157 290 l +1156 291 l +f +*U +0.000 0.588 0.451 0.412 k +*u +1293 291 m +1294 290 l +1293 291 l +f +*U +0.000 0.439 0.298 0.086 k +*u +1294 291 m +1295 290 l +1294 291 l +f +*U +0.000 0.204 0.141 0.122 k +*u +1314.333 290.333 m +1314.278 290.278 1314.222 289.222 1314.667 289.667 c +1314.722 289.722 1314.778 290.778 1314.333 290.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1319 284 m +1319.464 286.172 1320 287.958 1321 290 c +1314.568 291.356 1313.905 287.344 1319 284 c +f +*U +0.000 0.318 0.188 0.063 k +*u +1319.667 290.667 m +1319.222 290.222 1320.278 290.278 1320.333 290.333 c +1320.778 290.778 1319.722 290.722 1319.667 290.667 c +f +*U +0.000 0.420 0.263 0.094 k +*u +1321.333 290.333 m +1321.278 290.278 1321.222 289.222 1321.667 289.667 c +1321.722 289.722 1321.777 290.778 1321.333 290.333 c +f +*U +0.000 0.000 0.000 0.110 k +*u +1447 291 m +1447 255 l +1448.552 258.698 1448 263 1448 267 c +1448 289 l +1450.360 287.687 1452.391 286.659 1455 286 c +1452.579 288.268 1450 289.685 1447 291 c +f +*U +0.000 0.000 0.000 0.725 k +*u +1448 291 m +1449 290 l +1448 291 l +f +*U +0.000 0.000 0.000 0.596 k +*u +1475 291 m +1476 290 l +1475 291 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1476 291 m +1478.383 288.549 1480.793 287.178 1484 286 c +1481.654 288.730 1479.449 289.975 1476 291 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1818 291 m +1818 270 l +1820.643 276.299 1818.394 284.254 1820 291 c +1818 291 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1929 291 m +1930 290 l +1929 291 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1994 291 m +1995 290 l +1994 291 l +f +*U +0.000 0.000 0.000 0.827 k +*u +352 290 m +353 289 l +352 290 l +f +*U +0.000 0.000 0.000 0.561 k +*u +353 290 m +354 289 l +353 290 l +f +*U +0.000 0.000 0.000 0.200 k +*u +357.667 289.667 m +357.222 289.222 358.278 289.278 358.333 289.333 c +358.778 289.778 357.722 289.722 357.667 289.667 c +f +*U +0.000 0.000 0.000 0.078 k +*u +359 290 m +361 288.418 362.388 288.174 365 288 c +365 280.237 364.973 272.702 364 265 c +367 269.401 369.457 282.706 365.972 287.436 c +364.435 289.522 361.327 289.677 359 290 c +f +*U +0.000 0.000 0.000 0.753 k +*u +577 290 m +578 289 l +577 290 l +f +*U +0.000 0.000 0.000 0.533 k +*u +794 290 m +795 289 l +794 290 l +f +*U +0.000 0.000 0.000 0.776 k +*u +842 290 m +843 289 l +842 290 l +f +*U +0.000 0.000 0.000 0.616 k +*u +843 290 m +847.720 288 853.920 289 859 289 c +891 289 l +886.280 290.981 880 290 875 290 c +843 290 l +f +*U +0.000 0.404 0.314 0.286 k +*u +1141.333 289.333 m +1141.278 289.278 1141.222 288.222 1141.667 288.667 c +1141.722 288.722 1141.777 289.778 1141.333 289.333 c +f +*U +0.000 0.341 0.392 0.239 k +*u +1157 290 m +1158 289 l +1157 290 l +f +*U +0.000 0.145 0.094 0.192 k +*u +1215 290 m +1216 289 l +1215 290 l +f +*U +0.000 0.780 0.553 0.220 k +*u +1217 290 m +1216.659 283.801 1217.589 282 1224 282 c +1221.948 282.874 1220.253 282.953 1218 283 c +1218 289 l +1224 289 l +1221.669 289.984 1219.543 289.981 1217 290 c +f +*U +0.000 0.604 0.486 0.396 k +*u +1294 290 m +1295 289 l +1294 290 l +f +*U +0.000 0.290 0.290 0.710 k +*u +1313.333 289.333 m +1313.278 289.278 1313.222 288.222 1313.667 288.667 c +1313.722 288.722 1313.777 289.778 1313.333 289.333 c +f +*U +0.000 0.663 0.698 0.267 k +*u +1397 290 m +1397 284 l +1397.951 286.285 1397.951 287.715 1397 290 c +f +*U +0.000 0.322 0.290 0.157 k +*u +1398 290 m +1398 285 l +1398.830 287 1398.830 287.970 1398 290 c +f +*U +0.000 0.000 0.000 0.804 k +*u +1450 290 m +1451 289 l +1450 290 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1819 290 m +1819 283 1819.623 275.818 1818 269 c +1873 269 l +1880.751 269 1891 270.863 1898 267 c +1899.183 269.328 1900.223 271.511 1901 274 c +1893.242 268.414 1884.246 270 1875 270 c +1820 270 l +1820 276.169 1821.398 284.285 1819 290 c +f +*U +0.000 0.000 0.000 0.110 k +*u +1910 290 m +1909 288.522 1909 288.797 1909 287 c +1910.290 288.443 1910.401 288.233 1910 290 c +f +*U +0.000 0.000 0.000 0.820 k +*u +1911 290 m +1912 289 l +1911 290 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1976 290 m +1977 289 l +1976 290 l +f +*U +0.000 0.000 0.000 0.827 k +*u +358 289 m +359 288 l +358 289 l +f +*U +0.000 0.000 0.000 0.659 k +*u +359 289 m +360 288 l +359 289 l +f +*U +0.000 0.000 0.000 0.690 k +*u +578 289 m +579 288 l +578 289 l +f +*U +0.000 0.000 0.000 0.667 k +*u +604 289 m +605 288 l +604 289 l +f +*U +0.000 0.000 0.000 0.125 k +*u +605 289 m +606.624 286.956 607.643 286 610 285 c +608.598 287.274 607.485 287.987 605 289 c +f +*U +0.000 0.000 0.000 0.541 k +*u +800 289 m +801 288 l +800 289 l +f +*U +0.000 0.455 0.322 0.188 k +*u +1050 289 m +1050 284 l +1050.830 286 1050.830 286.970 1050 289 c +f +*U +0.000 0.278 0.231 0.251 k +*u +1152 289 m +1153 288 l +1152 289 l +f +*U +0.000 0.784 0.565 0.188 k +*u +1153 284 m +1157 285 l +1155.752 285.685 1155.451 285.749 1154 286 c +1156.786 286.458 1157.455 286.369 1159 284 c +1159.683 285.506 1159.826 286.315 1160 288 c +1155.836 288.646 1153.747 288.465 1153 284 c +f +*U +0.000 0.639 0.655 0.345 k +*u +1157 289 m +1158 288 l +1157 289 l +f +*U +0.000 0.318 0.486 0.373 k +*u +1158 289 m +1159 288 l +1158 289 l +f +*U +0.000 0.325 0.239 0.294 k +*u +1320 289 m +1321 288 l +1320 289 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1478 289 m +1479 288 l +1478 289 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1770 289 m +1771 288 l +1770 289 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1929 289 m +1933.720 287 1939.920 288 1945 288 c +1977 288 l +1972.280 289.981 1966 289 1961 289 c +1929 289 l +f +*U +0.000 0.588 0.455 0.357 k +*u +1141 288 m +1141 284 l +1141.710 285.759 1141.710 286.241 1141 288 c +f +*U +0.000 0.655 0.545 0.345 k +*u +1152 288 m +1152 282 l +1152.951 284.285 1152.951 285.715 1152 288 c +f +*U +0.000 0.114 0.216 0.318 k +*u +1160 288 m +1161 287 l +1160 288 l +f +*U +0.000 0.404 0.298 0.137 k +*u +1314.333 287.333 m +1314.278 287.278 1314.222 286.222 1314.667 286.667 c +1314.722 286.722 1314.778 287.778 1314.333 287.333 c +f +*U +0.000 0.353 0.243 0.345 k +*u +1319 288 m +1320 287 l +1319 288 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1453 288 m +1454 287 l +1453 288 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1480 288 m +1481 287 l +1480 288 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1766 288 m +1767 287 l +1766 288 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1996 288 m +1997 287 l +1996 288 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1997 288 m +1997.683 286.420 1997.805 286.223 1999 285 c +1998.316 286.580 1998.195 286.777 1997 288 c +f +*U +0.000 0.000 0.000 0.188 k +*u +579.667 286.667 m +579.222 286.222 580.278 286.278 580.333 286.333 c +580.778 286.778 579.722 286.722 579.667 286.667 c +f +*U +0.000 0.741 0.478 0.259 k +*u +1051 287 m +1051 283 l +1051.710 284.759 1051.710 285.241 1051 287 c +f +*U +0.000 0.886 0.667 0.110 k +*u +1154 287 m +1157 285 l +1155 284 1154.222 283.733 1153 282 c +1160 282 l +1159 287 l +1154 287 l +f +*U +0.000 0.267 0.259 0.706 k +*u +1160 287 m +1161 286 l +1160 287 l +f +*U +0.000 0.553 0.388 0.196 k +*u +1216.333 286.333 m +1216.278 286.278 1216.222 285.222 1216.667 285.667 c +1216.722 285.722 1216.777 286.778 1216.333 286.333 c +f +*U +0.122 0.000 0.031 0.161 k +*u +1317 287 m +1318 286 l +1317 287 l +f +*U +0.000 0.451 0.271 0.133 k +*u +1319 287 m +1320 286 l +1319 287 l +f +*U +0.000 0.000 0.000 0.792 k +*u +1455 287 m +1456 286 l +1455 287 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1698 287 m +1698 253 l +1700 253 l +1700 285 l +1709.432 285 1719 286 1728 283 c +1721.767 290 1706.728 287 1698 287 c +f +*U +0.000 0.000 0.000 0.631 k +*u +1724 287 m +1725 286 l +1724 287 l +f +*U +0.000 0.000 0.000 0.043 k +*u +1746 287 m +1747.506 286.317 1748.315 286.174 1750 286 c +1750 283 l +1755 283 l +1754.402 284.196 1754.534 283.977 1753 285 c +1754.314 285.768 1754.232 285.686 1755 287 c +1746 287 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1755 287 m +1757.234 284 1759.750 284.856 1763 286 c +1760.387 287 1757.835 286.993 1755 287 c +f +*U +0.000 0.000 0.000 0.165 k +*u +1763 287 m +1764.506 286.317 1765.315 286.174 1767 286 c +1765.494 286.683 1764.685 286.826 1763 287 c +f +*U +0.000 0.000 0.000 0.078 k +*u +1907 287 m +1906 282 l +1907.656 283.686 1908.251 284.746 1909 287 c +1907 287 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1909 287 m +1910 286 l +1909 287 l +f +*U +0.000 0.000 0.000 0.075 k +*u +581 286 m +583 282.223 585.961 280.341 590 279 c +587.451 282 584.610 284.201 581 286 c +f +*U +0.000 0.000 0.000 0.710 k +*u +582 286 m +583 285 l +582 286 l +f +*U +0.000 0.000 0.000 0.831 k +*u +913 286 m +914 285 l +913 286 l +f +*U +0.000 0.451 0.357 0.506 k +*u +1160 286 m +1160 283 l +1160.696 284.554 1160.696 284.446 1160 286 c +f +*U +0.000 0.459 0.337 0.153 k +*u +1315 286 m +1316 285 l +1315 286 l +f +*U +0.000 0.310 0.216 0.055 k +*u +1316 286 m +1317 285 l +1316 286 l +f +*U +0.016 0.035 0.000 0.188 k +*u +1319.333 285.333 m +1319.278 285.278 1319.222 284.222 1319.667 284.667 c +1319.723 284.723 1319.777 285.777 1319.333 285.333 c +f +*U +0.000 0.000 0.000 0.094 k +*u +1455 286 m +1458.420 281.873 1462.878 279.478 1468 278 c +1464.458 281.653 1459.766 284.255 1455 286 c +f +*U +0.000 0.000 0.000 0.176 k +*u +1484.667 285.667 m +1484.222 285.222 1485.278 285.278 1485.333 285.333 c +1485.778 285.778 1484.722 285.722 1484.667 285.667 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1747 286 m +1748 285 l +1747 286 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1748 286 m +1748.545 284.365 1748.365 284.545 1750 284 c +1750 286 l +1748 286 l +f +*U +0.000 0.000 0.000 0.882 k +*u +615 285 m +615 281 l +615.710 282.760 615.710 283.240 615 285 c +f +*U +0.000 0.937 0.667 0.063 k +*u +1056 285 m +1062.194 282.401 1071.314 284 1078 284 c +1115 284 l +1122.281 284 1129.880 284.695 1137 283 c +1133.298 287.236 1121.373 285 1116 285 c +1056 285 l +f +*U +0.078 0.000 0.020 0.259 k +*u +1151 285 m +1151 282 l +1151.696 283.554 1151.696 283.446 1151 285 c +f +*U +0.000 0.239 0.196 0.141 k +*u +1161 285 m +1162 284 l +1161 285 l +f +*U +0.000 0.937 0.667 0.063 k +*u +1224 285 m +1230.436 282.299 1240 284 1247 284 c +1296 284 l +1289.564 286.701 1279.951 285 1273 285 c +1224 285 l +f +*U +0.000 0.671 0.529 0.329 k +*u +1316 285 m +1316.899 282.876 1316.876 282.899 1319 282 c +1317.897 283.457 1317.457 283.897 1316 285 c +f +*U +0.000 0.369 0.239 0.086 k +*u +1317 285 m +1318 284 l +1317 285 l +f +*U +0.000 0.937 0.667 0.063 k +*u +1328 285 m +1333.707 282.605 1341.846 284 1348 284 c +1392 284 l +1386.293 286.395 1378 285 1372 285 c +1328 285 l +f +*U +0.000 0.204 0.176 0.047 k +*u +1398 285 m +1399 284 l +1398 285 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1458 285 m +1459 284 l +1458 285 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1486.667 284.667 m +1486.222 284.222 1487.278 284.278 1487.333 284.333 c +1487.778 284.778 1486.722 284.722 1486.667 284.667 c +f +*U +0.000 0.000 0.000 0.627 k +*u +1998 285 m +1999 284 l +1998 285 l +f +*U +0.000 0.000 0.000 0.067 k +*u +1999 285 m +2000 281.826 2001.785 279.509 2004 277 c +2003.829 280.924 2002 282.680 1999 285 c +f +*U +0.000 0.000 0.000 0.718 k +*u +820 284 m +821 283 l +820 284 l +f +*U +0.000 0.212 0.141 0.106 k +*u +1050.333 283.333 m +1050.278 283.278 1050.222 282.222 1050.667 282.667 c +1050.722 282.722 1050.778 283.778 1050.333 283.333 c +f +*U +0.000 0.510 0.447 0.404 k +*u +1140 284 m +1141 283 l +1140 284 l +f +*U +0.000 0.290 0.255 0.329 k +*u +1141 284 m +1142 283 l +1141 284 l +f +*U +0.000 0.369 0.329 0.259 k +*u +1161 284 m +1162 283 l +1161 284 l +f +*U +0.000 0.506 0.486 0.494 k +*u +1216.333 283.333 m +1216.278 283.278 1216.222 282.222 1216.667 282.667 c +1216.722 282.722 1216.777 283.778 1216.333 283.333 c +f +*U +0.000 0.243 0.216 0.051 k +*u +1318.667 283.667 m +1318.222 283.222 1319.278 283.278 1319.333 283.333 c +1319.778 283.778 1318.722 283.722 1318.667 283.667 c +f +*U +0.000 0.416 0.416 0.584 k +*u +1397.333 283.333 m +1397.278 283.278 1397.222 282.222 1397.667 282.667 c +1397.722 282.722 1397.778 283.778 1397.333 283.333 c +f +*U +0.000 0.000 0.000 0.584 k +*u +1487 284 m +1488 283 l +1487 284 l +f +*U +0.000 0.000 0.000 0.773 k +*u +586 283 m +587 282 l +586 283 l +f +*U +0.000 0.000 0.000 0.184 k +*u +818.333 282.333 m +818.278 282.278 818.222 281.222 818.667 281.667 c +818.722 281.722 818.778 282.778 818.333 282.333 c +f +*U +0.000 0.000 0.000 0.788 k +*u +915 283 m +916 282 l +915 283 l +f +*U +0.000 0.733 0.624 0.251 k +*u +1051 283 m +1052.769 282.221 1054 282 1056 282 c +1054.231 282.779 1052.964 282.912 1051 283 c +f +*U +0.000 0.698 0.514 0.290 k +*u +1136.667 282.667 m +1136.222 282.222 1137.278 282.278 1137.333 282.333 c +1137.778 282.778 1136.722 282.722 1136.667 282.667 c +f +*U +0.000 0.216 0.216 0.318 k +*u +1140 283 m +1141 282 l +1140 283 l +f +*U +0.000 0.659 0.545 0.341 k +*u +1160 283 m +1161.506 282.317 1162.315 282.174 1164 282 c +1162.494 282.683 1161.685 282.826 1160 283 c +f +*U +0.000 0.200 0.125 0.494 k +*u +1164 283 m +1165 282 l +1164 283 l +f +*U +0.039 0.000 0.012 0.231 k +*u +1215.333 282.333 m +1215.278 282.278 1215.222 281.222 1215.667 281.667 c +1215.723 281.723 1215.777 282.777 1215.333 282.333 c +f +*U +0.000 0.655 0.455 0.173 k +*u +1299.667 282.667 m +1299.222 282.222 1300.278 282.278 1300.333 282.333 c +1300.778 282.778 1299.722 282.722 1299.667 282.667 c +f +*U +0.000 0.561 0.416 0.439 k +*u +1301 283 m +1302.248 282.315 1302.548 282.251 1304 282 c +1302.752 282.685 1302.451 282.749 1301 283 c +f +*U +0.000 0.714 0.533 0.286 k +*u +1304 283 m +1305.248 282.315 1305.548 282.251 1307 282 c +1305.752 282.685 1305.452 282.749 1304 283 c +f +*U +0.000 0.000 0.000 0.118 k +*u +1489 283 m +1493.467 279 1499.361 275.785 1505 274 c +1500.973 278.359 1494.838 281.874 1489 283 c +f +*U +0.000 0.000 0.000 0.200 k +*u +1728 283 m +1729 282 l +1728 283 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1729 283 m +1730 282 l +1729 283 l +f +*U +0.000 0.000 0.000 0.149 k +*u +1752 283 m +1753.223 281.805 1753.420 281.684 1755 281 c +1753.777 282.195 1753.580 282.316 1752 283 c +f +*U +0.000 0.361 0.282 0.275 k +*u +1051.667 281.667 m +1051.222 281.222 1052.278 281.278 1052.333 281.333 c +1052.778 281.778 1051.722 281.722 1051.667 281.667 c +f +*U +0.000 0.247 0.204 0.267 k +*u +1053 282 m +1060 278.996 1071.256 281 1079 281 c +1137 281 l +1129.841 284 1118.744 282 1111 282 c +1053 282 l +f +*U +0.000 0.498 0.380 0.286 k +*u +1137.667 281.667 m +1137.222 281.222 1138.278 281.278 1138.333 281.333 c +1138.778 281.778 1137.722 281.722 1137.667 281.667 c +f +*U +0.000 0.314 0.247 0.173 k +*u +1139 282 m +1140 281 l +1139 282 l +f +*U +0.000 0.451 0.310 0.282 k +*u +1152 282 m +1153.249 281.315 1153.548 281.251 1155 281 c +1153.752 281.685 1153.452 281.749 1152 282 c +f +*U +0.000 0.498 0.380 0.043 k +*u +1155 282 m +1157.332 281 1159.457 281 1162 281 c +1159.669 281.984 1157.543 281.981 1155 282 c +f +*U +0.000 0.443 0.314 0.227 k +*u +1162 282 m +1163.249 281.315 1163.548 281.251 1165 281 c +1163.752 281.685 1163.452 281.749 1162 282 c +f +*U +0.000 0.404 0.286 0.302 k +*u +1216.667 281.667 m +1216.222 281.222 1217.278 281.278 1217.333 281.333 c +1217.778 281.778 1216.722 281.722 1216.667 281.667 c +f +*U +0.000 0.392 0.298 0.208 k +*u +1218 282 m +1219.769 281.221 1221 281 1223 281 c +1221.231 281.779 1219.964 281.912 1218 282 c +f +*U +0.000 0.247 0.204 0.267 k +*u +1223 282 m +1229.678 279.198 1239.784 281 1247 281 c +1299 281 l +1292.322 283.802 1282.216 282 1275 282 c +1223 282 l +f +*U +0.000 0.294 0.239 0.165 k +*u +1304.667 281.667 m +1304.222 281.222 1305.278 281.278 1305.333 281.333 c +1305.778 281.778 1304.722 281.722 1304.667 281.667 c +f +*U +0.000 0.396 0.302 0.337 k +*u +1306.667 281.667 m +1306.222 281.222 1307.278 281.278 1307.333 281.333 c +1307.778 281.778 1306.722 281.722 1306.667 281.667 c +f +*U +0.000 0.380 0.294 0.149 k +*u +1308 282 m +1309.506 281.317 1310.315 281.174 1312 281 c +1310.494 281.683 1309.685 281.826 1308 282 c +f +*U +0.000 0.275 0.200 0.396 k +*u +1312 282 m +1313 281 l +1312 282 l +f +*U +0.000 0.247 0.204 0.267 k +*u +1313 282 m +1320 278.996 1331.256 281 1339 281 c +1398 281 l +1390.841 284 1379.744 282 1372 282 c +1313 282 l +f +*U +0.000 0.000 0.000 0.737 k +*u +1463 282 m +1464 281 l +1463 282 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1730 282 m +1731 281 l +1730 282 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1905 282 m +1904 280.521 1904 280.797 1904 279 c +1905.289 280.443 1905.401 280.234 1905 282 c +f +*U +0.000 0.000 0.000 0.749 k +*u +1906 282 m +1907 281 l +1906 282 l +f +*U +0.000 0.000 0.000 0.561 k +*u +615 281 m +616 280 l +615 281 l +f +*U +0.000 0.000 0.000 0.200 k +*u +817.333 280.333 m +817.278 280.278 817.222 279.222 817.667 279.667 c +817.722 279.722 817.778 280.778 817.333 280.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +818 281 m +819 280 l +818 281 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1492 281 m +1493 280 l +1492 281 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1730 281 m +1731.624 278.956 1732.643 278 1735 277 c +1733.376 279 1732.357 279.896 1730 281 c +f +*U +0.000 0.000 0.000 0.612 k +*u +1754 281 m +1755 280 l +1754 281 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1755 281 m +1756.450 279.392 1757 278.936 1759 278 c +1757.550 279.608 1756.949 280 1755 281 c +f +*U +0.000 0.000 0.000 0.729 k +*u +590 280 m +591 279 l +590 280 l +f +*U +0.000 0.000 0.000 0.000 k +*u +615 280 m +616 279 l +615 280 l +f +*U +0.000 0.000 0.000 0.776 k +*u +917 280 m +918 279 l +917 280 l +f +*U +0.000 0.000 0.000 0.125 k +*u +918 280 m +919 277 920.414 274.618 922 272 c +922.576 275.534 920.603 277.762 918 280 c +f +*U +0.000 0.000 0.000 0.796 k +*u +2001 280 m +2002 279 l +2001 280 l +f +*U +0.000 0.000 0.000 0.137 k +*u +2002.333 279.333 m +2002.278 279.278 2002.222 278.222 2002.667 278.667 c +2002.723 278.723 2002.777 279.777 2002.333 279.333 c +f +*U +0.000 0.000 0.000 0.341 k +*u +590 279 m +591 278 l +590 279 l +f +*U +0.000 0.000 0.000 0.576 k +*u +591 279 m +592 278 l +591 279 l +f +*U +0.000 0.000 0.000 0.133 k +*u +816 279 m +814.602 276.950 813.749 275.354 813 273 c +815 274.908 816.250 276.208 816 279 c +f +*U +0.000 0.000 0.000 0.773 k +*u +1468 279 m +1469 278 l +1468 279 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1904 279 m +1905 278 l +1904 279 l +f +*U +0.000 0.000 0.000 0.063 k +*u +591 278 m +594 273 l +599 272 l +596.681 274.841 594.378 276.568 591 278 c +f +*U +0.000 0.000 0.000 0.694 k +*u +616.333 277.333 m +616.278 277.278 616.222 276.222 616.667 276.667 c +616.722 276.722 616.778 277.778 616.333 277.333 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1468 278 m +1469.543 276.733 1470 276.511 1472 276 c +1470.542 277 1469.752 277.436 1468 278 c +f +*U +0.000 0.000 0.000 0.702 k +*u +1735 278 m +1736 277 l +1735 278 l +f +*U +0.000 0.000 0.000 0.639 k +*u +1758 278 m +1759 277 l +1758 278 l +f +*U +0.000 0.000 0.000 0.671 k +*u +919 277 m +920 276 l +919 277 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1499 277 m +1500 276 l +1499 277 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1760 277 m +1761.223 275.805 1761.420 275.684 1763 275 c +1761.777 276.195 1761.580 276.316 1760 277 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1903 277 m +1904 276 l +1903 277 l +f +*U +0.000 0.000 0.000 0.655 k +*u +2003 277 m +2004 276 l +2003 277 l +f +*U +0.000 0.000 0.000 0.051 k +*u +2004 277 m +2004.547 275 2005 273.745 2006 272 c +2006.710 274.531 2006 275.516 2004 277 c +f +*U +0.000 0.000 0.000 0.753 k +*u +595 276 m +596 275 l +595 276 l +f +*U +0.000 0.000 0.000 0.745 k +*u +815 276 m +816 275 l +815 276 l +f +*U +0.000 0.000 0.000 0.749 k +*u +834 276 m +835 275 l +834 276 l +f +*U +0.000 0.000 0.000 0.129 k +*u +833 272 m +840.188 275 848.323 274 856 274 c +898 274 l +893.280 275.981 887 275 882 275 c +849 275 l +843.679 275 835.945 277.210 833 272 c +f +*U +0.000 0.000 0.000 0.784 k +*u +899 276 m +900 275 l +899 276 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1471.667 275.667 m +1471.222 275.222 1472.278 275.278 1472.333 275.333 c +1472.778 275.778 1471.722 275.722 1471.667 275.667 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1473 276 m +1474 275 l +1473 276 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1736 276 m +1738.719 272.223 1741.644 269.688 1746 268 c +1743.264 271.575 1740 274 1736 276 c +f +*U +0.000 0.000 0.000 0.000 k +*u +259.333 274.333 m +259.278 274.278 259.222 273.222 259.667 273.667 c +259.722 273.722 259.778 274.778 259.333 274.333 c +f +*U +0.000 0.000 0.000 0.114 k +*u +899 275 m +899.684 273.420 899.805 273.223 901 272 c +900.316 273.580 900.195 273.777 899 275 c +f +1473 275 m +1474.717 273 1475.566 272.651 1478 272 c +1476.313 273.656 1475.254 274.251 1473 275 c +f +*U +0.000 0.000 0.000 0.737 k +*u +1762 275 m +1763 274 l +1762 275 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1763 275 m +1768.354 268.424 1778.192 261.301 1786 258 c +1780.827 264.785 1771 272.274 1763 275 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1920 275 m +1921 274 l +1920 275 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1920 272 m +1933.679 275.257 1949.965 273 1964 273 c +1969.259 273 1976.967 274.410 1981.895 272.397 c +1985.436 270.950 1987 266.437 1990 264 c +1989 267 1987.593 271 1984.621 272.972 c +1981 275 1974.935 274 1971 274 c +1939 274 l +1934 274 1923 276.201 1920 272 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1922 275 m +1927.708 272.605 1935.846 274 1942 274 c +1984 274 l +1978.293 276.395 1970 275 1964 275 c +1922 275 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1984 275 m +1985 274 l +1984 275 l +f +*U +0.000 0.000 0.000 0.698 k +*u +1504 274 m +1505 273 l +1504 274 l +f +*U +0.000 0.000 0.000 0.290 k +*u +1505 274 m +1506 273 l +1505 274 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1655.333 273.333 m +1655.278 273.278 1655.222 272.222 1655.667 272.667 c +1655.722 272.722 1655.777 273.778 1655.333 273.333 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1901 274 m +1902 273 l +1901 274 l +f +*U +0.000 0.000 0.000 0.784 k +*u +599 273 m +600 272 l +599 273 l +f +*U +0.000 0.000 0.000 0.063 k +*u +812 273 m +810.652 271.232 809.878 270 809 268 c +811.343 269.347 812.401 270.259 812 273 c +f +*U +0.000 0.000 0.000 0.631 k +*u +813 273 m +814 272 l +813 273 l +f +*U +0.000 0.000 0.000 0.808 k +*u +832 273 m +833 272 l +832 273 l +f +*U +0.000 0.000 0.000 0.604 k +*u +1506 273 m +1507 272 l +1506 273 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1507 273 m +1508.223 271.805 1508.420 271.684 1510 271 c +1508.777 272.195 1508.580 272.316 1507 273 c +f +*U +0.000 0.000 0.000 0.722 k +*u +1741 273 m +1742 272 l +1741 273 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1919 273 m +1920 272 l +1919 273 l +f +*U +0.000 0.000 0.000 0.161 k +*u +806 272 m +806 268 l +806.710 269.760 806.710 270.241 806 272 c +f +*U +0.000 0.000 0.000 0.114 k +*u +832 272 m +831 270.255 830.547 268.875 830 267 c +831.693 268.782 832.375 269.581 832 272 c +f +*U +0.000 0.000 0.000 0.196 k +*u +901.333 271.333 m +901.278 271.278 901.222 270.222 901.667 270.667 c +901.722 270.722 901.778 271.778 901.333 271.333 c +f +*U +0.000 0.000 0.000 0.753 k +*u +1766 272 m +1767 271 l +1766 272 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1919 272 m +1918 270.522 1918 270.797 1918 269 c +1919.290 270.443 1919.401 270.233 1919 272 c +f +*U +0.000 0.000 0.000 0.110 k +*u +2007 272 m +2008.460 268 2010.660 264.537 2013 261 c +2013.886 265.544 2010.329 269.281 2007 272 c +f +*U +0.000 0.000 0.000 0.141 k +*u +169 271 m +175.919 268 186.520 270 194 270 c +249 270 l +242 272.903 231.480 271 224 271 c +169 271 l +f +*U +0.000 0.000 0.000 0.153 k +*u +280 271 m +285.951 268.503 294.580 270 301 270 c +345 270 l +339 272.497 330.420 271 324 271 c +280 271 l +f +*U +0.000 0.000 0.000 0.161 k +*u +600 271 m +601.223 269.805 601.420 269.684 603 269 c +601.777 270.195 601.580 270.316 600 271 c +f +*U +0.000 0.000 0.000 0.710 k +*u +902 271 m +903 270 l +902 271 l +f +*U +0.000 0.000 0.000 0.102 k +*u +924 271 m +924.777 268.511 925.817 266.328 927 264 c +927.728 267 926.256 268.853 924 271 c +f +*U +0.000 0.000 0.000 0.153 k +*u +958 271 m +964.436 268.299 974 270 981 270 c +1032 270 l +1025.564 272.701 1015.951 271 1009 271 c +958 271 l +f +*U +0.000 0.000 0.000 0.325 k +*u +1032 271 m +1033 270 l +1032 271 l +f +*U +0.000 0.306 0.227 0.243 k +*u +1052 271 m +1052 268 l +1053 269 1053.309 269.612 1054 271 c +1052 271 l +f +*U +0.000 0.478 0.349 0.161 k +*u +1054 271 m +1061 267.996 1072.256 270 1080 270 c +1138 270 l +1130.841 273 1119.744 271 1112 271 c +1054 271 l +f +*U +0.000 0.051 0.043 0.286 k +*u +1141 271 m +1142 270 l +1141 271 l +f +*U +0.000 0.318 0.220 0.455 k +*u +1142 271 m +1143 270 l +1142 271 l +f +*U +0.000 0.263 0.184 0.153 k +*u +1143 271 m +1144 270 l +1143 271 l +f +*U +0.000 0.478 0.349 0.161 k +*u +1147 271 m +1154.649 267.790 1166.712 270 1175 270 c +1167.351 273.210 1155.288 271 1147 271 c +f +*U +0.000 0.435 0.314 0.361 k +*u +1175 271 m +1176 270 l +1175 271 l +f +*U +0.000 0.247 0.212 0.227 k +*u +1195 271 m +1196.248 270.315 1196.548 270.251 1198 270 c +1196.752 270.685 1196.451 270.749 1195 271 c +f +*U +0.000 0.478 0.349 0.161 k +*u +1198 271 m +1204.194 268.401 1213.314 270 1220 270 c +1268 270 l +1261.806 272.599 1252.686 271 1246 271 c +1198 271 l +f +*U +0.000 0.416 0.247 0.298 k +*u +1268 271 m +1269.769 270.221 1271 270 1273 270 c +1271.231 270.779 1269.964 270.912 1268 271 c +f +*U +0.000 0.192 0.114 0.188 k +*u +1273.333 270.333 m +1273.278 270.278 1273.222 269.222 1273.667 269.667 c +1273.723 269.723 1273.777 270.777 1273.333 270.333 c +f +*U +0.000 0.298 0.231 0.106 k +*u +1278 271 m +1279 270 l +1278 271 l +f +*U +0.000 0.471 0.341 0.169 k +*u +1279 271 m +1284.715 268.602 1292.831 270 1299 270 c +1293.285 272.398 1285.169 271 1279 271 c +f +*U +0.000 0.278 0.196 0.098 k +*u +1299 271 m +1300 270 l +1299 271 l +f +*U +0.000 0.282 0.192 0.075 k +*u +1307.667 270.667 m +1307.222 270.222 1308.278 270.278 1308.333 270.333 c +1308.778 270.778 1307.722 270.722 1307.667 270.667 c +f +*U +0.000 0.467 0.318 0.275 k +*u +1309 271 m +1310.249 270.315 1310.548 270.251 1312 270 c +1310.752 270.685 1310.452 270.749 1309 271 c +f +*U +0.000 0.153 0.098 0.106 k +*u +1312 271 m +1313 270 l +1312 271 l +f +*U +0.000 0.216 0.165 0.161 k +*u +1316 271 m +1317 270 l +1316 271 l +f +*U +0.000 0.310 0.235 0.286 k +*u +1317 271 m +1318.506 270.317 1319.315 270.174 1321 270 c +1319.494 270.683 1318.685 270.826 1317 271 c +f +*U +0.000 0.478 0.349 0.161 k +*u +1321 271 m +1327.436 268.299 1337 270 1344 270 c +1393 270 l +1386.564 272.701 1376.951 271 1370 271 c +1321 271 l +f +*U +0.000 0.408 0.314 0.129 k +*u +1393 271 m +1396 268 l +1396.951 270.507 1395.348 270.706 1393 271 c +f +*U +0.000 0.000 0.000 0.545 k +*u +1481 271 m +1482 270 l +1481 271 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1509 271 m +1510 270 l +1509 271 l +f +*U +0.000 0.000 0.000 0.141 k +*u +1510.667 270.667 m +1510.222 270.222 1511.278 270.278 1511.333 270.333 c +1511.778 270.778 1510.722 270.722 1510.667 270.667 c +f +*U +0.000 0.000 0.000 0.612 k +*u +169 270 m +175.919 267 186.520 269 194 269 c +249 269 l +242 271.903 231.480 270 224 270 c +169 270 l +f +*U +0.000 0.000 0.000 0.851 k +*u +280 270 m +285.951 267.503 294.580 269 301 269 c +345 269 l +339 271.497 330.420 270 324 270 c +280 270 l +f +721 270 m +726.951 267.503 735.580 269 742 269 c +786 269 l +780 271.497 771.420 270 765 270 c +721 270 l +f +*U +0.000 0.000 0.000 0.239 k +*u +902 270 m +903 269 l +902 270 l +f +*U +0.000 0.000 0.000 0.851 k +*u +958 270 m +964.678 267.198 974.784 269 982 269 c +1033 269 l +1026.564 271.701 1016.951 270 1010 270 c +958 270 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1033 270 m +1033 254 l +1036 258.484 1035 264.749 1035 270 c +1033 270 l +f +*U +0.000 0.859 0.616 0.133 k +*u +1053 270 m +1053.482 267.636 1053.636 267.482 1056 267 c +1055.198 263.829 1055.599 261.232 1056 258 c +1136 258 l +1135 262.609 1135.960 265.571 1137 270 c +1053 270 l +f +*U +0.000 0.459 0.345 0.541 k +*u +1137.333 269.333 m +1137.278 269.278 1137.222 268.222 1137.667 268.667 c +1137.722 268.722 1137.777 269.778 1137.333 269.333 c +f +*U +0.000 0.102 0.086 0.184 k +*u +1138 270 m +1139 269 l +1138 270 l +f +*U +0.000 0.271 0.176 0.196 k +*u +1141.333 269.333 m +1141.278 269.278 1141.222 268.222 1141.667 268.667 c +1141.722 268.722 1141.777 269.778 1141.333 269.333 c +f +*U +0.000 0.612 0.408 0.353 k +*u +1142 270 m +1142 266 l +1143 267.458 1143.436 268.248 1144 270 c +1142 270 l +f +*U +0.000 0.655 0.549 0.345 k +*u +1147 270 m +1147 263 l +1148 265.534 1148 267.466 1147 270 c +f +*U +0.000 0.878 0.620 0.122 k +*u +1148 270 m +1148 267 1147.474 263 1149.742 260.742 c +1151.802 258.683 1155.340 259 1158 258.715 c +1166.621 257.652 1175.319 258 1184 258 c +1180.970 262.517 1177 264.215 1176 270 c +1148 270 l +f +*U +0.000 0.122 0.086 0.188 k +*u +1176 270 m +1177 269 l +1176 270 l +f +*U +0.000 0.404 0.306 0.294 k +*u +1194 270 m +1195 269 l +1194 270 l +f +*U +0.000 0.812 0.655 0.188 k +*u +1194 266 m +1198 269 l +1195.251 269.603 1194.500 268.638 1194 266 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1192 258 m +1264 258 l +1261 263.656 1266.715 265 1270 269 c +1252.776 268 1235.258 269 1218 269 c +1212.485 269 1202 271 1197.228 268.651 c +1193.931 267 1192.774 261.285 1192 258 c +f +*U +0.000 0.839 0.616 0.161 k +*u +1199 270 m +1205.194 267.401 1214.314 269 1221 269 c +1255 269 l +1260.628 269.000 1266.457 268 1272 269 c +1265.564 271.701 1255.951 270 1249 270 c +1199 270 l +f +*U +0.000 0.451 0.294 0.549 k +*u +1272 270 m +1273 269 l +1272 270 l +f +*U +0.000 0.235 0.176 0.114 k +*u +1276 270 m +1277 269 l +1276 270 l +f +*U +0.000 0.718 0.518 0.282 k +*u +1271 260 m +1275.314 262 1276.665 265.876 1280 269 c +1275.894 269.917 1273 263 1271 260 c +f +*U +0.000 0.855 0.604 0.141 k +*u +1271 258 m +1278.564 258 1286.480 257.330 1294 258.174 c +1297.428 258.559 1300.468 260.538 1303.830 260.860 c +1306.956 261 1309.747 259.775 1312.986 260.484 c +1317.567 261.486 1319 267 1323 267.687 c +1329 268.499 1336.776 267 1343 267 c +1392 267 l +1386.293 269.395 1378 268 1372 268 c +1328 268 l +1335 270 1343.573 269 1351 269 c +1395 269 l +1389 271.497 1380.420 270 1374 270 c +1327 270 l +1321.541 270.000 1308.956 271.874 1307 266 c +1304.706 266.303 1303.788 266.579 1302 268 c +1299 267 l +1298 271.221 1293.654 270 1290 270 c +1286.941 270 1282.926 270.656 1280 269.500 c +1276.675 268 1272.924 261 1271 258 c +f +*U +0.000 0.647 0.443 0.333 k +*u +1299 270 m +1299.406 267.907 1299.216 267.980 1301 267 c +1300.309 268.388 1300 268.861 1299 270 c +f +*U +0.000 0.455 0.322 0.353 k +*u +1306.333 269.333 m +1306.278 269.278 1306.222 268.222 1306.667 268.667 c +1306.722 268.722 1306.777 269.778 1306.333 269.333 c +f +*U +0.000 0.361 0.337 0.639 k +*u +1307 270 m +1308 269 l +1307 270 l +f +*U +0.000 0.714 0.553 0.286 k +*u +1312 270 m +1313.769 269.221 1315 269 1317 269 c +1315.231 269.779 1313.964 269.912 1312 270 c +f +*U +0.000 0.702 0.525 0.298 k +*u +1395 270 m +1395 266 l +1395.710 267.759 1395.710 268.241 1395 270 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1511 270 m +1512 269 l +1511 270 l +f +*U +0.000 0.000 0.000 0.157 k +*u +1514.333 269.333 m +1514.278 269.278 1514.222 268.222 1514.667 268.667 c +1514.722 268.722 1514.777 269.778 1514.333 269.333 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1539 270 m +1540 269 l +1539 270 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1917 270 m +1918 269 l +1917 270 l +f +*U +0.000 0.000 0.000 0.698 k +*u +1987 270 m +1988 269 l +1987 270 l +f +*U +0.000 0.000 0.000 0.518 k +*u +364 269 m +365 268 l +364 269 l +f +*U +0.000 0.000 0.000 0.604 k +*u +604 269 m +605 268 l +604 269 l +f +*U +0.000 0.000 0.000 0.549 k +*u +805 269 m +806 268 l +805 269 l +f +*U +0.000 0.000 0.000 0.157 k +*u +903.333 268.333 m +903.278 268.278 903.222 267.222 903.667 267.667 c +903.722 267.722 903.778 268.778 903.333 268.333 c +f +*U +0.000 0.243 0.169 0.553 k +*u +1176 269 m +1177 268 l +1176 269 l +f +*U +0.000 0.361 0.271 0.239 k +*u +1193 269 m +1194 268 l +1193 269 l +f +*U +0.000 0.600 0.576 0.400 k +*u +1271 269 m +1272 268 l +1271 269 l +f +*U +0.000 0.294 0.169 0.071 k +*u +1272 269 m +1273 268 l +1272 269 l +f +*U +0.000 0.255 0.176 0.114 k +*u +1275.333 268.333 m +1275.278 268.278 1275.222 267.222 1275.667 267.667 c +1275.722 267.722 1275.778 268.778 1275.333 268.333 c +f +*U +0.000 0.302 0.224 0.153 k +*u +1300 269 m +1301 268 l +1300 269 l +f +*U +0.000 0.596 0.447 0.345 k +*u +1321 269 m +1322.248 268.315 1322.548 268.251 1324 268 c +1322.752 268.685 1322.451 268.749 1321 269 c +f +*U +0.000 0.859 0.616 0.133 k +*u +1328 269 m +1333.707 266.605 1341.846 268 1348 268 c +1392 268 l +1384.848 265.886 1376.427 267 1369 267 c +1327 267 l +1329 257.518 1336.680 258 1345 258 c +1361 257.994 1377 258.956 1393 259 c +1393.655 261.537 1394.276 263 1396 265 c +1395 269 l +1328 269 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1483 269 m +1484.223 267.805 1484.420 267.684 1486 267 c +1484.777 268.195 1484.580 268.316 1483 269 c +f +*U +0.000 0.000 0.000 0.839 k +*u +1559 269 m +1565.678 266.198 1575.784 268 1583 268 c +1636 268 l +1629.322 270.802 1619.216 269 1612 269 c +1559 269 l +f +*U +0.000 0.000 0.000 0.620 k +*u +1818 269 m +1824.678 266.198 1834.784 268 1842 268 c +1896 268 l +1889.322 270.802 1879.216 269 1872 269 c +1818 269 l +f +*U +0.000 0.000 0.000 0.259 k +*u +1896 269 m +1896 266 l +1896.696 267.554 1896.696 267.446 1896 269 c +f +*U +0.000 0.000 0.000 0.141 k +*u +1917.333 268.333 m +1917.278 268.278 1917.222 267.222 1917.667 267.667 c +1917.722 267.723 1917.777 268.778 1917.333 268.333 c +f +*U +0.000 0.000 0.000 0.702 k +*u +2008 269 m +2009 268 l +2008 269 l +f +*U +0.000 0.000 0.000 0.506 k +*u +260 268 m +261 267 l +260 268 l +f +*U +0.000 0.000 0.000 0.157 k +*u +604.667 267.667 m +604.222 267.222 605.278 267.278 605.333 267.333 c +605.778 267.778 604.722 267.722 604.667 267.667 c +f +*U +0.000 0.000 0.000 0.533 k +*u +701 268 m +702 267 l +701 268 l +f +*U +0.000 0.000 0.000 0.059 k +*u +805 268 m +804.719 264.256 803.789 262.510 801 260 c +801 258 l +802 257 l +804 257 l +806.226 260.710 806.484 263.797 807 268 c +805 268 l +f +*U +0.000 0.000 0.000 0.137 k +*u +809 268 m +808 266.521 808 266.797 808 265 c +809.289 266.443 809.401 266.234 809 268 c +f +*U +0.000 0.000 0.000 0.769 k +*u +810 268 m +811 267 l +810 268 l +f +*U +0.000 0.000 0.000 0.749 k +*u +829 268 m +830 267 l +829 268 l +f +*U +0.000 0.306 0.216 0.000 k +*u +1052 268 m +1053 267 l +1052 268 l +f +*U +0.000 0.275 0.200 0.243 k +*u +1137 268 m +1138 267 l +1137 268 l +f +*U +0.000 0.247 0.165 0.039 k +*u +1141 268 m +1142 267 l +1141 268 l +f +*U +0.000 0.059 0.031 0.592 k +*u +1143 268 m +1142 265 l +1143.766 265.979 1143.956 266.222 1143 268 c +f +*U +0.000 0.553 0.420 0.447 k +*u +1176.333 267.333 m +1176.278 267.278 1176.222 266.222 1176.667 266.667 c +1176.722 266.722 1176.777 267.778 1176.333 267.333 c +f +*U +0.000 0.380 0.314 0.463 k +*u +1268 266 m +1269.580 266.683 1269.777 266.805 1271 268 c +1269.420 267.316 1269.223 267.195 1268 266 c +f +*U +0.000 0.380 0.290 0.020 k +*u +1271 268 m +1272 267 l +1271 268 l +f +*U +0.000 0.302 0.231 0.149 k +*u +1305 268 m +1306 267 l +1305 268 l +f +*U +0.000 0.690 0.529 0.310 k +*u +1306 268 m +1305 266 l +1307 266 l +1307 267.853 1307.300 267.350 1306 268 c +f +*U +0.000 0.463 0.286 0.212 k +*u +1320 268 m +1321 267 l +1320 268 l +f +*U +0.000 0.133 0.141 0.267 k +*u +1321 268 m +1322.248 267.315 1322.548 267.251 1324 267 c +1322.752 267.685 1322.451 267.749 1321 268 c +f +*U +0.000 0.463 0.376 0.298 k +*u +1324 268 m +1325 267 l +1324 268 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1486 268 m +1487 267 l +1486 268 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1515 268 m +1517.487 265.868 1519.809 264.732 1523 264 c +1520.973 266.754 1518.313 267.426 1515 268 c +f +*U +0.000 0.000 0.000 0.714 k +*u +1747 268 m +1748 267 l +1747 268 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1916 268 m +1917 267 l +1916 268 l +f +*U +0.000 0.000 0.000 0.243 k +*u +829 267 m +830 266 l +829 267 l +f +*U +0.000 0.000 0.000 0.149 k +*u +904 267 m +904.547 265 905 263.745 906 262 c +906.375 264.419 905.693 265.218 904 267 c +f +*U +0.000 0.443 0.341 0.557 k +*u +1053 267 m +1053 264 l +1053.696 265.554 1053.696 265.446 1053 267 c +f +*U +0.000 0.671 0.482 0.329 k +*u +1054 267 m +1054 263.831 1054 261 1055 258 c +1056 260.847 1055.515 263.968 1056 267 c +1054 267 l +f +*U +0.000 0.722 0.557 0.278 k +*u +1135 267 m +1135 264 1135.190 261.729 1136 259 c +1136.668 261.787 1136.172 264.387 1135 267 c +f +*U +0.000 0.267 0.173 0.329 k +*u +1136 267 m +1137 266 l +1136 267 l +f +*U +0.000 0.345 0.235 0.055 k +*u +1177 267 m +1178 266 l +1177 267 l +f +*U +0.000 0.518 0.396 0.482 k +*u +1193.333 266.333 m +1193.278 266.278 1193.222 265.222 1193.667 265.667 c +1193.722 265.723 1193.777 266.778 1193.333 266.333 c +f +*U +0.000 0.365 0.267 0.549 k +*u +1302.667 266.667 m +1302.222 266.222 1303.278 266.278 1303.333 266.333 c +1303.778 266.778 1302.722 266.722 1302.667 266.667 c +f +*U +0.000 0.620 0.455 0.125 k +*u +1304 267 m +1305 266 l +1304 267 l +f +*U +0.000 0.329 0.271 0.212 k +*u +1325 267 m +1326 266 l +1325 267 l +f +*U +0.000 0.592 0.424 0.337 k +*u +1326 267 m +1326.406 264.908 1326.217 264.980 1328 264 c +1327.309 265.388 1327 265.861 1326 267 c +f +*U +0.000 0.000 0.000 0.133 k +*u +1486 267 m +1488.856 263.887 1491.878 261.969 1496 261 c +1493 263.952 1489.915 265.760 1486 267 c +f +*U +0.000 0.000 0.000 0.145 k +*u +1539 267 m +1540.965 254.625 1552.471 253 1563 253 c +1639 253 l +1633 255.497 1624.420 254 1618 254 c +1572 254 l +1564.251 254 1555 253 1548 257 c +1543.848 259.472 1541.841 263.404 1539 267 c +f +*U +0.000 0.000 0.000 0.682 k +*u +1654 267 m +1655 266 l +1654 267 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1747 267 m +1748.624 264.956 1749.643 264 1752 263 c +1750.376 265 1749.357 265.896 1747 267 c +f +*U +0.000 0.000 0.000 0.706 k +*u +1773 267 m +1774 266 l +1773 267 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1895 267 m +1896 266 l +1895 267 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1916 267 m +1915 265.521 1915 265.797 1915 264 c +1916.290 265.443 1916.401 265.233 1916 267 c +f +*U +0.000 0.000 0.000 0.996 k +*u +349 266 m +344.829 263.722 338.732 264.490 334 264.200 c +321 263.407 307.943 263.938 295 264 c +288.649 264 282.729 265.499 277 262 c +278.248 261.315 278.548 261.251 280 261 c +281.294 253.546 292.180 256 298 256 c +316.570 256 335.671 254.595 354 258 c +352.376 261.247 350.610 264.439 351 266 c +349 266 l +f +*U +0.000 0.000 0.000 0.741 k +*u +363 266 m +364 265 l +363 266 l +f +*U +0.000 0.000 0.000 0.706 k +*u +608 266 m +609 265 l +608 266 l +f +*U +0.000 0.000 0.000 0.737 k +*u +804 266 m +805 265 l +804 266 l +f +*U +0.000 0.000 0.000 0.675 k +*u +926 266 m +927 265 l +926 266 l +f +*U +0.000 0.455 0.310 0.365 k +*u +1177 266 m +1178 265 l +1177 266 l +f +*U +0.000 0.463 0.302 0.443 k +*u +1266.667 265.667 m +1266.222 265.222 1267.278 265.278 1267.333 265.333 c +1267.778 265.778 1266.722 265.722 1266.667 265.667 c +f +*U +0.000 0.275 0.224 0.247 k +*u +1268 266 m +1269 265 l +1268 266 l +f +*U +0.000 0.369 0.263 0.314 k +*u +1275 266 m +1276 265 l +1275 266 l +f +*U +0.000 0.000 0.000 0.745 k +*u +1518 266 m +1519 265 l +1518 266 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1540 266 m +1541 265 l +1540 266 l +f +*U +0.000 0.000 0.000 0.239 k +*u +1895.333 265.333 m +1895.278 265.278 1895.222 264.222 1895.667 264.667 c +1895.722 264.722 1895.777 265.778 1895.333 265.333 c +f +*U +0.000 0.000 0.000 0.643 k +*u +1896 266 m +1897 265 l +1896 266 l +f +*U +0.000 0.000 0.000 0.745 k +*u +261 265 m +262 264 l +261 265 l +f +*U +0.000 0.000 0.000 0.133 k +*u +608 265 m +609.223 263.805 609.420 263.684 611 263 c +609.777 264.195 609.580 264.316 608 265 c +f +*U +0.000 0.000 0.000 0.678 k +*u +702 265 m +703 264 l +702 265 l +f +*U +0.000 0.000 0.000 0.157 k +*u +804 265 m +803 261 l +804.303 262.668 804.553 262.992 804 265 c +f +*U +0.000 0.000 0.000 0.690 k +*u +808 265 m +809 264 l +808 265 l +f +*U +0.004 0.027 0.000 0.278 k +*u +1143 265 m +1144 264 l +1143 265 l +f +*U +0.000 0.447 0.337 0.553 k +*u +1177 265 m +1178 264 l +1177 265 l +f +*U +0.000 0.125 0.086 0.129 k +*u +1178 265 m +1179 264 l +1178 265 l +f +*U +0.000 0.702 0.494 0.298 k +*u +1193 265 m +1192 261 l +1193.656 262.404 1193.751 262.953 1193 265 c +f +*U +0.000 0.380 0.325 0.620 k +*u +1264.667 264.667 m +1264.222 264.222 1265.278 264.278 1265.333 264.333 c +1265.778 264.778 1264.722 264.722 1264.667 264.667 c +f +*U +0.000 0.282 0.153 0.063 k +*u +1266 265 m +1267 264 l +1266 265 l +f +*U +0.000 0.506 0.431 0.212 k +*u +1319 265 m +1320 264 l +1319 265 l +f +*U +0.000 0.675 0.475 0.325 k +*u +1394 265 m +1393 259 l +1394.654 261.177 1394.994 262.425 1394 265 c +f +*U +0.000 0.408 0.294 0.192 k +*u +1395 265 m +1396 264 l +1395 265 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1491 265 m +1492 264 l +1491 265 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1894 265 m +1895 264 l +1894 265 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1990 265 m +1991 264 l +1990 265 l +f +*U +0.000 0.000 0.000 0.125 k +*u +261.333 263.333 m +261.278 263.278 261.222 262.222 261.667 262.667 c +261.722 262.722 261.778 263.778 261.333 263.333 c +f +702.333 263.333 m +702.278 263.278 702.222 262.222 702.667 262.667 c +702.722 262.722 702.778 263.778 702.333 263.333 c +f +*U +0.000 0.306 0.224 0.055 k +*u +1053.333 263.333 m +1053.278 263.278 1053.222 262.222 1053.667 262.667 c +1053.722 262.722 1053.777 263.778 1053.333 263.333 c +f +*U +0.000 0.694 0.541 0.306 k +*u +1178.333 263.333 m +1178.278 263.278 1178.222 262.222 1178.667 262.667 c +1178.722 262.722 1178.777 263.778 1178.333 263.333 c +f +*U +0.000 0.494 0.341 0.000 k +*u +1192 264 m +1193 263 l +1192 264 l +f +*U +0.000 0.498 0.412 0.369 k +*u +1262 264 m +1262 260 l +1262.911 261.376 1263.404 262.440 1264 264 c +1262 264 l +f +*U +0.000 0.400 0.227 0.098 k +*u +1264 264 m +1265 263 l +1264 264 l +f +*U +0.000 0.451 0.412 0.549 k +*u +1318 264 m +1319 263 l +1318 264 l +f +*U +0.000 0.012 0.051 0.220 k +*u +1319 264 m +1320 263 l +1319 264 l +f +*U +0.000 0.196 0.129 0.094 k +*u +1326 264 m +1327 263 l +1326 264 l +f +*U +0.000 0.471 0.310 0.529 k +*u +1327.333 263.333 m +1327.278 263.278 1327.222 262.222 1327.667 262.667 c +1327.722 262.722 1327.777 263.778 1327.333 263.333 c +f +*U +0.000 0.125 0.078 0.176 k +*u +1395 264 m +1396 263 l +1395 264 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1522 264 m +1524.187 261.968 1526 260.906 1529 260 c +1526.826 262.295 1525 263.273 1522 264 c +f +*U +0.000 0.000 0.000 0.804 k +*u +1653 264 m +1654 263 l +1653 264 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1752 264 m +1753 263 l +1752 264 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1777 264 m +1778 263 l +1777 264 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1894 264 m +1895 263 l +1894 264 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1914.333 263.333 m +1914.278 263.278 1914.222 262.222 1914.667 262.667 c +1914.722 262.722 1914.777 263.778 1914.333 263.333 c +f +*U +0.000 0.000 0.000 0.102 k +*u +1990 264 m +1990.651 261.566 1991 260.717 1993 259 c +1992.251 261.254 1991.656 262.314 1990 264 c +f +*U +0.000 0.000 0.000 0.631 k +*u +262 263 m +263 262 l +262 263 l +f +*U +0.000 0.000 0.000 0.137 k +*u +611 263 m +612.402 260.726 613.515 260 616 259 c +614.394 260.914 613.217 261.837 611 263 c +f +*U +0.000 0.000 0.000 0.710 k +*u +612 263 m +613 262 l +612 263 l +f +*U +0.000 0.000 0.000 0.616 k +*u +703 263 m +704 262 l +703 263 l +f +*U +0.000 0.000 0.000 0.608 k +*u +826 263 m +827 262 l +826 263 l +f +*U +0.000 0.000 0.000 0.831 k +*u +907 263 m +908 262 l +907 263 l +f +*U +0.000 0.000 0.000 0.588 k +*u +928 263 m +929 262 l +928 263 l +f +*U +0.000 0.000 0.000 0.114 k +*u +929 263 m +929 261 l +930.635 261.545 930.455 261.365 931 263 c +929 263 l +f +*U +0.000 0.263 0.165 0.086 k +*u +1147 263 m +1148 262 l +1147 263 l +f +*U +0.000 0.424 0.325 0.463 k +*u +1179 263 m +1180.248 262.315 1180.548 262.251 1182 262 c +1180.752 262.685 1180.451 262.749 1179 263 c +f +*U +0.000 0.478 0.396 0.522 k +*u +1182.333 262.333 m +1182.278 262.278 1182.222 261.222 1182.667 261.667 c +1182.722 261.722 1182.777 262.778 1182.333 262.333 c +f +*U +0.000 0.463 0.329 0.271 k +*u +1192 263 m +1193 262 l +1192 263 l +f +*U +0.000 0.333 0.259 0.431 k +*u +1318 263 m +1319 262 l +1318 263 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1523 263 m +1524 262 l +1523 263 l +f +*U +0.000 0.000 0.000 0.529 k +*u +1541 263 m +1542 262 l +1541 263 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1753 263 m +1754 262 l +1753 263 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1893.333 262.333 m +1893.278 262.278 1893.222 261.222 1893.667 261.667 c +1893.722 261.722 1893.777 262.778 1893.333 262.333 c +f +*U +0.000 0.000 0.000 0.553 k +*u +1894 263 m +1895 262 l +1894 263 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1913 263 m +1914 262 l +1913 263 l +f +*U +0.000 0.000 0.000 0.224 k +*u +262 262 m +263 261 l +262 262 l +f +*U +0.000 0.000 0.000 0.800 k +*u +263 262 m +264 261 l +263 262 l +f +*U +0.000 0.000 0.000 0.671 k +*u +361 262 m +362 261 l +361 262 l +f +*U +0.000 0.000 0.000 0.216 k +*u +703 262 m +704 261 l +703 262 l +f +*U +0.000 0.000 0.000 0.604 k +*u +802 262 m +803 261 l +802 262 l +f +*U +0.000 0.000 0.000 0.204 k +*u +826 262 m +827 261 l +826 262 l +f +*U +0.000 0.000 0.000 0.125 k +*u +907 262 m +907.651 259.566 908 258.717 910 257 c +909.251 259.254 908.656 260.314 907 262 c +f +*U +0.000 0.157 0.106 0.173 k +*u +1136 262 m +1137 261 l +1136 262 l +f +*U +0.000 0.388 0.247 0.353 k +*u +1148 262 m +1149 261 l +1148 262 l +f +*U +0.000 0.310 0.196 0.000 k +*u +1191 262 m +1192 261 l +1191 262 l +f +*U +0.000 0.114 0.184 0.243 k +*u +1271 262 m +1272 261 l +1271 262 l +f +*U +0.000 0.573 0.408 0.392 k +*u +1303 262 m +1304.249 261.315 1304.548 261.251 1306 261 c +1304.751 261.685 1304.452 261.749 1303 262 c +f +*U +0.000 0.333 0.251 0.282 k +*u +1317 262 m +1318 261 l +1317 262 l +f +*U +0.000 0.318 0.204 0.361 k +*u +1327 262 m +1328 261 l +1327 262 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1496 262 m +1497 261 l +1496 262 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1753 262 m +1755.719 258.222 1758.644 255.688 1763 254 c +1760.264 257.575 1757 260 1753 262 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1892 262 m +1893 261 l +1892 262 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1913 262 m +1914 261 l +1913 262 l +f +*U +0.000 0.000 0.000 0.243 k +*u +263 261 m +264 260 l +263 261 l +f +*U +0.000 0.000 0.000 0.090 k +*u +825 261 m +822 255 l +824.640 256.536 825.818 257.939 825 261 c +f +*U +0.000 0.000 0.000 0.118 k +*u +930 261 m +931 258.515 931.726 257.402 934 256 c +932.906 258.357 932 259.599 930 261 c +f +*U +0.000 0.165 0.106 0.141 k +*u +1148 261 m +1149 260 l +1148 261 l +f +*U +0.000 0.545 0.416 0.357 k +*u +1182 261 m +1182.545 259.365 1182.365 259.545 1184 259 c +1184 261 l +1182 261 l +f +*U +0.000 0.125 0.110 0.204 k +*u +1190 261 m +1191 260 l +1190 261 l +f +*U +0.000 0.522 0.341 0.400 k +*u +1191 261 m +1189 260 l +1190.482 259.209 1191.796 259 1191 261 c +f +*U +0.000 0.118 0.184 0.141 k +*u +1263 261 m +1264 260 l +1263 261 l +f +*U +0.000 0.188 0.063 0.204 k +*u +1268 261 m +1269 260 l +1268 261 l +f +*U +0.000 0.549 0.325 0.451 k +*u +1269.667 260.667 m +1269.222 260.222 1270.278 260.278 1270.333 260.333 c +1270.778 260.778 1269.722 260.722 1269.667 260.667 c +f +*U +0.000 0.608 0.518 0.392 k +*u +1300 259 m +1301.580 259.683 1301.777 259.805 1303 261 c +1301.420 260.316 1301.223 260.195 1300 259 c +f +*U +0.000 0.220 0.161 0.133 k +*u +1303.667 260.667 m +1303.222 260.222 1304.278 260.278 1304.333 260.333 c +1304.778 260.778 1303.722 260.722 1303.667 260.667 c +f +*U +0.000 0.404 0.290 0.251 k +*u +1305 261 m +1306 260 l +1305 261 l +f +*U +0.000 0.639 0.451 0.275 k +*u +1313 261 m +1314.506 260.317 1315.315 260.174 1317 260 c +1315.494 260.683 1314.686 260.826 1313 261 c +f +*U +0.000 0.667 0.533 0.333 k +*u +1328 261 m +1329.450 259.392 1330 258.936 1332 258 c +1330.550 259.608 1329.948 260 1328 261 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1781 261 m +1782 260 l +1781 261 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1892 261 m +1893 260 l +1892 261 l +f +*U +0.000 0.000 0.000 0.733 k +*u +1893 261 m +1894 260 l +1893 261 l +f +*U +0.000 0.000 0.000 0.063 k +*u +1912 261 m +1911 257 l +1912.753 258.330 1913.670 259.247 1915 261 c +1912 261 l +f +*U +0.000 0.000 0.000 0.722 k +*u +2013 261 m +2014 260 l +2013 261 l +f +*U +0.000 0.000 0.000 0.098 k +*u +2014 261 m +2014.683 259.420 2014.805 259.222 2016 258 c +2015.316 259.580 2015.195 259.777 2014 261 c +f +*U +0.000 0.000 0.000 0.196 k +*u +264 260 m +265 259 l +264 260 l +f +*U +0.000 0.000 0.000 0.792 k +*u +265 260 m +266 259 l +265 260 l +f +*U +0.000 0.000 0.000 0.812 k +*u +359 260 m +360 259 l +359 260 l +f +*U +0.000 0.000 0.000 0.804 k +*u +616 260 m +617 259 l +616 260 l +f +*U +0.000 0.000 0.000 0.255 k +*u +705 260 m +706 259 l +705 260 l +f +*U +0.000 0.000 0.000 0.824 k +*u +706 260 m +707 259 l +706 260 l +f +800 260 m +801 259 l +800 260 l +f +*U +0.000 0.000 0.000 0.820 k +*u +805 260 m +806 259 l +805 260 l +f +*U +0.000 0.000 0.000 0.804 k +*u +824 260 m +825 259 l +824 260 l +f +*U +0.000 0.439 0.294 0.094 k +*u +1137 260 m +1138 259 l +1137 260 l +f +*U +0.000 0.161 0.153 0.275 k +*u +1149 260 m +1150 259 l +1149 260 l +f +*U +0.000 0.498 0.431 0.502 k +*u +1150 260 m +1151 259 l +1150 260 l +f +*U +0.000 0.494 0.329 0.094 k +*u +1184 260 m +1185 259 l +1184 260 l +f +*U +0.000 0.455 0.298 0.118 k +*u +1188 260 m +1189 259 l +1188 260 l +f +*U +0.000 0.718 0.580 0.282 k +*u +1262 260 m +1263.249 259.315 1263.548 259.251 1265 259 c +1263.752 259.685 1263.452 259.749 1262 260 c +f +*U +0.000 0.392 0.416 0.357 k +*u +1265.667 259.667 m +1265.222 259.222 1266.278 259.278 1266.333 259.333 c +1266.778 259.778 1265.722 259.722 1265.667 259.667 c +f +*U +0.000 0.729 0.671 0.271 k +*u +1266 258 m +1267.580 258.683 1267.777 258.805 1269 260 c +1267.420 259.316 1267.223 259.195 1266 258 c +f +*U +0.000 0.875 0.835 0.098 k +*u +1268 259 m +1269.809 258.426 1270 258.535 1272 259 c +1270.191 259.574 1269.931 259.465 1268 259 c +f +*U +0.000 0.455 0.314 0.196 k +*u +1307 260 m +1308 259 l +1307 260 l +f +*U +0.000 0.690 0.478 0.310 k +*u +1308 260 m +1309.249 259.315 1309.548 259.251 1311 259 c +1309.752 259.685 1309.452 259.749 1308 260 c +f +*U +0.000 0.447 0.325 0.553 k +*u +1311 260 m +1312.248 259.315 1312.548 259.251 1314 259 c +1312.752 259.685 1312.451 259.749 1311 260 c +f +*U +0.000 0.396 0.286 0.208 k +*u +1314 260 m +1315 259 l +1314 260 l +f +*U +0.000 0.329 0.239 0.055 k +*u +1315 260 m +1316 259 l +1315 260 l +f +*U +0.000 0.278 0.239 0.063 k +*u +1394.333 259.333 m +1394.278 259.278 1394.222 258.222 1394.667 258.667 c +1394.723 258.723 1394.777 259.777 1394.333 259.333 c +f +*U +0.000 0.000 0.000 0.106 k +*u +1497 260 m +1499.633 257.340 1502.414 256 1506 255 c +1503.356 257.717 1500.694 259 1497 260 c +f +*U +0.000 0.000 0.000 0.176 k +*u +1529.667 259.667 m +1529.222 259.222 1530.278 259.278 1530.333 259.333 c +1530.778 259.778 1529.722 259.722 1529.667 259.667 c +f +*U +0.000 0.000 0.000 0.310 k +*u +1891.667 259.667 m +1891.222 259.222 1892.278 259.278 1892.333 259.333 c +1892.778 259.778 1891.722 259.722 1891.667 259.667 c +f +*U +0.000 0.000 0.000 0.824 k +*u +1911 260 m +1912 259 l +1911 260 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1993 260 m +1994 259 l +1993 260 l +f +*U +0.000 0.000 0.000 0.263 k +*u +265 259 m +266 258 l +265 259 l +f +*U +0.000 0.000 0.000 0.639 k +*u +266 259 m +267 258 l +266 259 l +f +*U +0.000 0.000 0.000 0.106 k +*u +348 254 m +352.391 254.594 356 255.826 360 258 c +356.543 258.579 350.301 256.677 348 254 c +f +*U +0.000 0.000 0.000 0.110 k +*u +616 259 m +617.624 256.956 618.643 256 621 255 c +619.376 257 618.357 257.896 616 259 c +f +*U +0.000 0.000 0.000 0.094 k +*u +706 259 m +707.465 256.878 708.457 256.526 711 256 c +709.369 257.366 707.962 258 706 259 c +f +*U +0.000 0.000 0.000 0.651 k +*u +707 259 m +708 258 l +707 259 l +f +*U +0.000 0.000 0.000 0.153 k +*u +797 257 m +799.291 257.311 799.320 257.366 801 259 c +799.248 258.436 798.458 258 797 257 c +f +*U +0.000 0.310 0.224 0.247 k +*u +1054 259 m +1055 258 l +1054 259 l +f +*U +0.000 0.400 0.278 0.600 k +*u +1136.667 258.667 m +1136.222 258.222 1137.278 258.278 1137.333 258.333 c +1137.778 258.778 1136.722 258.722 1136.667 258.667 c +f +*U +0.000 0.196 0.125 0.141 k +*u +1138 259 m +1129.439 256.469 1118.901 258 1110 258 c +1055 258 l +1059.609 255.344 1068.602 257 1074 257 c +1119 257 l +1123.999 257 1129 256.941 1134 257 c +1135.998 257 1138.953 256.691 1138 259 c +f +*U +0.000 0.235 0.243 0.282 k +*u +1150 259 m +1151 258 l +1150 259 l +f +*U +0.000 0.714 0.506 0.286 k +*u +1151 259 m +1153.890 257.787 1156.874 258 1160 258 c +1157 259.213 1154 258.998 1151 259 c +f +*U +0.000 0.498 0.498 0.502 k +*u +1184 259 m +1185.506 258.317 1186.315 258.174 1188 258 c +1186.494 258.683 1185.685 258.826 1184 259 c +f +*U +0.000 0.706 0.753 0.196 k +*u +1188 259 m +1189.506 258.317 1190.315 258.174 1192 258 c +1190.494 258.683 1189.685 258.826 1188 259 c +f +*U +0.000 0.804 0.812 0.114 k +*u +1264.667 258.667 m +1264.222 258.222 1265.278 258.278 1265.333 258.333 c +1265.778 258.778 1264.722 258.722 1264.667 258.667 c +f +*U +0.000 0.667 0.451 0.333 k +*u +1296 259 m +1297.506 258.317 1298.315 258.174 1300 258 c +1298.494 258.683 1297.685 258.826 1296 259 c +f +*U +0.000 0.325 0.212 0.251 k +*u +1300 259 m +1301 258 l +1300 259 l +f +*U +0.000 0.271 0.176 0.153 k +*u +1308.667 258.667 m +1308.222 258.222 1309.278 258.278 1309.333 258.333 c +1309.778 258.778 1308.722 258.722 1308.667 258.667 c +f +*U +0.000 0.710 0.486 0.286 k +*u +1333 259 m +1334.249 258.315 1334.548 258.251 1336 258 c +1334.752 258.685 1334.451 258.749 1333 259 c +f +*U +0.000 0.808 0.627 0.192 k +*u +1384 259 m +1386.890 257.787 1389.874 258 1393 258 c +1390 259.213 1387 258.998 1384 259 c +f +*U +0.000 0.349 0.322 0.651 k +*u +1393 259 m +1394 258 l +1393 259 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1501 259 m +1502 258 l +1501 259 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1530 259 m +1531 258 l +1530 259 l +f +*U +0.000 0.000 0.000 0.169 k +*u +1531 259 m +1532.687 257.344 1533.746 256.749 1536 256 c +1534.314 257.656 1533.254 258.251 1531 259 c +f +*U +0.000 0.000 0.000 0.812 k +*u +1758 259 m +1759 258 l +1758 259 l +f +*U +0.000 0.000 0.000 0.090 k +*u +1787 259 m +1786.952 256.670 1786.796 256.994 1789 256 c +1788.308 257.389 1788 257.860 1787 259 c +f +*U +0.000 0.000 0.000 0.078 k +*u +1891 259 m +1892 258 l +1891 259 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1993 259 m +1993.684 257.420 1993.805 257.223 1995 256 c +1994.316 257.580 1994.195 257.777 1993 259 c +f +*U +0.000 0.000 0.000 0.212 k +*u +267 258 m +268 257 l +267 258 l +f +*U +0.000 0.000 0.000 0.608 k +*u +268 258 m +269 257 l +268 258 l +f +*U +0.000 0.000 0.000 0.639 k +*u +709 258 m +710 257 l +709 258 l +f +*U +0.000 0.000 0.000 0.635 k +*u +910 258 m +911 257 l +910 258 l +f +*U +0.000 0.000 0.000 0.824 k +*u +931 258 m +932 257 l +931 258 l +f +*U +0.000 0.196 0.125 0.141 k +*u +1151 258 m +1154.699 256.448 1159 257 1163 257 c +1183 257 l +1179.301 258.552 1174.983 258 1171 258 c +1151 258 l +f +*U +0.000 0.325 0.212 0.063 k +*u +1183 258 m +1185.890 256.787 1188.874 257 1192 257 c +1189 258.213 1186 257.998 1183 258 c +f +*U +0.000 0.196 0.125 0.141 k +*u +1192 258 m +1195.699 256.448 1200 257 1204 257 c +1225 257 l +1299 257 l +1295.301 258.552 1290.983 258 1287 258 c +1266 258 l +1192 258 l +f +1330 258 m +1335.707 255.605 1343.846 257 1350 257 c +1394 257 l +1388.293 259.395 1380 258 1374 258 c +1330 258 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1890.333 257.333 m +1890.278 257.278 1890.222 256.222 1890.667 256.667 c +1890.723 256.723 1890.777 257.777 1890.333 257.333 c +f +*U +0.000 0.000 0.000 0.553 k +*u +1891 258 m +1892 257 l +1891 258 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1910 258 m +1911 257 l +1910 258 l +f +*U +0.000 0.000 0.000 0.647 k +*u +2015 258 m +2016 257 l +2015 258 l +f +*U +0.000 0.000 0.000 0.055 k +*u +268 257 m +270.516 255 272.903 254.465 276 254 c +273.954 256.433 271 256.597 268 257 c +f +*U +0.000 0.000 0.000 0.678 k +*u +271 257 m +272 256 l +271 257 l +f +*U +0.000 0.000 0.000 0.671 k +*u +353 257 m +354 256 l +353 257 l +f +*U +0.000 0.000 0.000 0.639 k +*u +794 257 m +795 256 l +794 257 l +f +*U +0.000 0.000 0.000 0.082 k +*u +795 257 m +792.600 256.197 790.628 255.907 789 254 c +791 254.226 796 254.330 795 257 c +f +*U +0.000 0.000 0.000 0.251 k +*u +796 257 m +797 256 l +796 257 l +f +*U +0.000 0.000 0.000 0.161 k +*u +802 257 m +801 255.522 801 255.797 801 254 c +822 254 l +815.592 256.689 808.348 253.470 802 257 c +f +*U +0.000 0.000 0.000 0.663 k +*u +803 257 m +804 256 l +803 257 l +f +*U +0.000 0.000 0.000 0.078 k +*u +910 257 m +910.406 254.908 910.217 254.980 912 254 c +911.316 255.580 911.195 255.777 910 257 c +f +*U +0.000 0.000 0.000 0.757 k +*u +1646 257 m +1647 256 l +1646 257 l +f +*U +0.000 0.000 0.000 0.569 k +*u +1889 257 m +1890 256 l +1889 257 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1910 257 m +1909 255.521 1909 255.797 1909 254 c +1910.766 254.979 1910.956 255.222 1910 257 c +f +*U +0.000 0.000 0.000 0.565 k +*u +276 256 m +277 255 l +276 256 l +f +*U +0.000 0.000 0.000 0.827 k +*u +277 256 m +278.248 255.315 278.548 255.251 280 255 c +278.752 255.685 278.452 255.749 277 256 c +f +*U +0.000 0.000 0.000 0.847 k +*u +345 256 m +346.248 255.315 346.548 255.251 348 255 c +346.752 255.685 346.452 255.749 345 256 c +f +*U +0.000 0.000 0.000 0.157 k +*u +520 256 m +523.613 251.865 534.751 254 540 254 c +533.987 256.523 526.440 254.467 520 256 c +f +*U +0.000 0.000 0.000 0.659 k +*u +621 256 m +622 255 l +621 256 l +f +*U +0.000 0.000 0.000 0.169 k +*u +712 256 m +713.248 255.315 713.549 255.251 715 255 c +713.751 255.685 713.452 255.749 712 256 c +f +*U +0.000 0.000 0.000 0.553 k +*u +717 256 m +718 255 l +717 256 l +f +*U +0.000 0.000 0.000 0.839 k +*u +718.667 255.667 m +718.222 255.222 719.278 255.278 719.333 255.333 c +719.778 255.778 718.722 255.722 718.667 255.667 c +f +*U +0.000 0.000 0.000 0.890 k +*u +786.667 255.667 m +786.222 255.222 787.278 255.278 787.333 255.333 c +787.778 255.778 786.722 255.722 786.667 255.667 c +f +*U +0.000 0.000 0.000 0.639 k +*u +788 256 m +789 255 l +788 256 l +f +*U +0.000 0.000 0.000 0.345 k +*u +933 256 m +934 255 l +933 256 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1506 256 m +1507 255 l +1506 256 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1536.667 255.667 m +1536.222 255.222 1537.278 255.278 1537.333 255.333 c +1537.778 255.778 1536.722 255.722 1536.667 255.667 c +f +*U +0.000 0.000 0.000 0.776 k +*u +1551 256 m +1552 255 l +1551 256 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1643 256 m +1644 255 l +1643 256 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1788 256 m +1789 255 l +1788 256 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1789 256 m +1790 255 l +1789 256 l +f +1797.333 255.333 m +1797.278 255.278 1797.222 254.222 1797.667 254.667 c +1797.722 254.722 1797.778 255.778 1797.333 255.333 c +f +*U +0.000 0.000 0.000 0.208 k +*u +1889 256 m +1890 255 l +1889 256 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1995.333 255.333 m +1995.278 255.278 1995.222 254.222 1995.667 254.667 c +1995.722 254.722 1995.778 255.778 1995.333 255.333 c +f +*U +0.000 0.000 0.000 0.153 k +*u +2017 256 m +2011.881 252 2002.237 254 1996 254 c +2002.445 251.296 2012 253 2019 253 c +2018.309 254.388 2018 254.861 2017 256 c +f +*U +0.000 0.000 0.000 0.157 k +*u +276 255 m +282.436 252.299 292 254 299 254 c +348 254 l +341.564 256.701 331.951 255 325 255 c +276 255 l +f +621 255 m +624.959 253.339 629.737 254 634 254 c +630 255.661 625.263 255 621 255 c +f +717 255 m +723.436 252.299 733 254 740 254 c +789 254 l +782.564 256.701 772.951 255 766 255 c +717 255 l +f +*U +0.000 0.000 0.000 0.161 k +*u +912 255 m +918.202 252.397 927.298 254 934 254 c +927.798 256.603 918.702 255 912 255 c +f +938 255 m +945.879 251.694 958.466 254 967 254 c +1033 254 l +1025 257.306 1012.534 255 1004 255 c +938 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1506 255 m +1508.435 252.214 1512.484 253 1516 253 c +1540 253 l +1536.753 254.877 1532.729 254 1529 254 c +1521.304 253.988 1513.592 253.591 1506 255 c +f +*U +0.000 0.000 0.000 0.733 k +*u +1537 255 m +1538 254 l +1537 255 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1556 255 m +1557 254 l +1556 255 l +f +*U +0.000 0.000 0.000 0.855 k +*u +1557.667 254.667 m +1557.222 254.222 1558.278 254.278 1558.333 254.333 c +1558.778 254.778 1557.722 254.722 1557.667 254.667 c +f +*U +0.000 0.000 0.000 0.878 k +*u +1635 255 m +1636.248 254.315 1636.549 254.251 1638 254 c +1636.751 254.685 1636.452 254.749 1635 255 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1638 255 m +1639 254 l +1638 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1790 255 m +1781.715 252.551 1771.615 254 1763 254 c +1767.994 251 1778 253 1784 253 c +1786 253 1791 252.226 1790 255 c +f +*U +0.000 0.000 0.000 0.447 k +*u +1888.667 254.667 m +1888.222 254.222 1889.278 254.278 1889.333 254.333 c +1889.778 254.778 1888.722 254.722 1888.667 254.667 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1996 255 m +1997 254 l +1996 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1678 254 m +1683.715 251.602 1691.831 253 1698 253 c +1692.285 255.398 1684.169 254 1678 254 c +f +1798 254 m +1801.699 252.448 1806 253 1810 253 c +1832 253 l +1909 253 l +1905.301 254.552 1900.983 254 1897 254 c +1875 254 l +1798 254 l +f +*U +0.000 0.106 0.086 0.180 k +*u +1057 247 m +1058 246 l +1057 247 l +f +*U +0.000 0.341 0.341 0.659 k +*u +1058.333 246.333 m +1058.278 246.278 1058.222 245.222 1058.667 245.667 c +1058.722 245.722 1058.778 246.778 1058.333 246.333 c +f +*U +0.000 0.498 0.396 0.502 k +*u +1059 247 m +1061.613 245.902 1064 246 1067 246 c +1064.387 247 1061.836 246.993 1059 247 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1067 247 m +1073.678 244.198 1083.784 246 1091 246 c +1144 246 l +1137.322 248.802 1127.216 247 1120 247 c +1067 247 l +f +*U +0.000 0.498 0.380 0.502 k +*u +1144 247 m +1146 246 1147.747 246 1150 246 c +1147.948 246.874 1146.253 246.953 1144 247 c +f +*U +0.000 0.561 0.408 0.267 k +*u +1150.333 246.333 m +1150.278 246.278 1150.222 245.222 1150.667 245.667 c +1150.722 245.722 1150.778 246.778 1150.333 246.333 c +f +*U +0.000 0.263 0.184 0.424 k +*u +1161 247 m +1162 246 l +1161 247 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1162 247 m +1170 243.593 1183.203 246 1192 246 c +1258 246 l +1250 249.306 1237.534 247 1229 247 c +1162 247 l +f +*U +0.000 0.247 0.184 0.753 k +*u +1258.667 246.667 m +1258.222 246.222 1259.278 246.278 1259.333 246.333 c +1259.778 246.778 1258.722 246.722 1258.667 246.667 c +f +*U +0.000 0.035 0.024 0.267 k +*u +1260 247 m +1261 246 l +1260 247 l +f +*U +0.000 0.082 0.047 0.369 k +*u +1268 247 m +1269 246 l +1268 247 l +f +*U +0.000 0.494 0.357 0.506 k +*u +1269 247 m +1270 244 l +1274 246 l +1272.231 246.779 1270.964 246.912 1269 247 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1274 247 m +1277.958 245.339 1282.740 246 1287 246 c +1310 246 l +1306 247.661 1301.260 247 1297 247 c +1274 247 l +f +*U +0.000 0.424 0.322 0.196 k +*u +1310.333 246.333 m +1310.278 246.278 1310.222 245.222 1310.667 245.667 c +1310.722 245.722 1310.778 246.778 1310.333 246.333 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1324 247 m +1329.951 244.503 1338.580 246 1345 246 c +1391 246 l +1385 248.497 1376.420 247 1370 247 c +1324 247 l +f +*U +0.000 0.082 0.114 0.212 k +*u +1391 247 m +1392 246 l +1391 247 l +f +*U +0.000 0.882 0.639 0.118 k +*u +1059 246 m +1059.836 242.935 1060.738 237.971 1063.510 236 c +1066.366 234 1071.701 235 1075 235 c +1105 235 l +1106 240 l +1072 240 l +1079.434 242.197 1088.278 241 1096 241 c +1100.539 241 1105.529 241.903 1110 241.375 c +1116 240.662 1121.966 238.401 1128 238 c +1128 235 l +1152 235 l +1151.825 238.819 1150.848 242.292 1150 246 c +1059 246 l +f +*U +0.000 0.878 0.627 0.122 k +*u +1162 246 m +1164.772 242 1168.415 237.292 1173 235.588 c +1179.519 233.244 1189.201 235 1196 235 c +1252 235 l +1252 239 l +1250.804 238.402 1251 238.534 1250 237 c +1246.447 242 1236.560 240 1231 240 c +1176 240 l +1176 242 l +1248 242 l +1248 244 l +1168 244 l +1170.729 244.810 1173 244.979 1176 245 c +1171.783 246.769 1166.541 246 1162 246 c +f +*U +0.000 0.910 0.627 0.090 k +*u +1168 245 m +1173.951 242.503 1182.580 244 1189 244 c +1227 244 l +1234.810 244 1242.620 244.828 1250 242 c +1242.283 239.719 1233 241 1225 241 c +1176 241 l +1181.217 238.811 1188.381 240 1194 240 c +1230 240 l +1237.251 240 1244.709 241 1251 237 c +1253 243 l +1249 243 l +1249 245 l +1252.419 244.377 1254.691 243.810 1258 245 c +1250.600 248 1239 246 1231 246 c +1209.980 246 1188.944 245.173 1168 245 c +f +*U +0.000 0.525 0.388 0.475 k +*u +1258 246 m +1259 245 l +1258 246 l +f +*U +0.000 0.263 0.176 0.278 k +*u +1259 246 m +1260 245 l +1259 246 l +f +*U +0.000 0.314 0.196 0.322 k +*u +1269 246 m +1270 245 l +1269 246 l +f +*U +0.000 0.878 0.643 0.122 k +*u +1271 246 m +1272.314 241.402 1276.667 239.579 1278 235 c +1362 235 l +1370.177 235 1386.780 231.173 1388 242 c +1385.915 242 1386.276 241.862 1386 244 c +1385.317 242.494 1385.174 241.685 1385 240 c +1344 240 l +1338.621 240 1331.439 238.637 1327 242 c +1325 242 l +1323.777 240.805 1323.580 240.684 1322 240 c +1322 236 l +1318.590 238 1315.720 241 1311.985 242.441 c +1303.438 245.641 1294.926 244.796 1286 245 c +1280.970 245 1276 245.997 1271 246 c +f +*U +0.000 0.922 0.639 0.078 k +*u +1280 246 m +1285.860 243.541 1293.705 245.268 1300 244.960 c +1304.225 244.753 1307.973 243 1312 242 c +1309.645 246.492 1305.605 245.998 1301 246 c +1280 246 l +f +*U +0.000 0.275 0.200 0.027 k +*u +1323 246 m +1324 245 l +1323 246 l +f +*U +0.000 0.910 0.627 0.090 k +*u +1324 246 m +1326.236 238.589 1333.630 240 1340 240 c +1385 240 l +1385 244 l +1385.986 242.521 1386 242.797 1386 241 c +1388.179 242.539 1388.573 243.355 1389 246 c +1324 246 l +f +*U +0.000 0.710 0.510 0.290 k +*u +1389 246 m +1389 242 l +1389.911 243.377 1390.404 244.440 1391 246 c +1389 246 l +f +*U +0.000 0.569 0.396 0.431 k +*u +1058 245 m +1059 244 l +1058 245 l +f +*U +0.000 0.620 0.482 0.380 k +*u +1150 245 m +1151 240 l +1151.791 242.307 1151.475 243 1150 245 c +f +*U +0.000 0.325 0.275 0.078 k +*u +1151 245 m +1152 244 l +1151 245 l +f +*U +0.000 0.710 0.565 0.290 k +*u +1162 245 m +1164 241 l +1164.369 243.223 1163.859 243.735 1162 245 c +f +*U +0.000 0.808 0.596 0.184 k +*u +1249 245 m +1249 243 l +1251.873 242.656 1254.175 242.385 1257 243 c +1254.444 244.190 1251.805 244.702 1249 245 c +f +*U +0.000 0.541 0.416 0.459 k +*u +1257 245 m +1258 244 l +1257 245 l +f +*U +0.000 0.231 0.153 0.329 k +*u +1258 245 m +1259 244 l +1258 245 l +f +*U +0.000 0.592 0.435 0.345 k +*u +1310.667 244.667 m +1310.222 244.222 1311.278 244.278 1311.333 244.333 c +1311.778 244.778 1310.722 244.722 1310.667 244.667 c +f +*U +0.000 0.224 0.173 0.125 k +*u +1312 245 m +1313 244 l +1312 245 l +f +*U +0.000 0.310 0.310 0.690 k +*u +1322 245 m +1322.545 243.365 1322.365 243.545 1324 243 c +1324 245 l +1322 245 l +f +*U +0.000 0.318 0.231 0.333 k +*u +1390 245 m +1391 244 l +1390 245 l +f +*U +0.000 0.443 0.306 0.035 k +*u +1058 244 m +1059 243 l +1058 244 l +f +*U +0.000 0.733 0.541 0.267 k +*u +1059 244 m +1060 239 l +1060.651 241.234 1060.318 242 1059 244 c +f +*U +0.000 0.239 0.188 0.137 k +*u +1162 244 m +1163 243 l +1162 244 l +f +*U +0.000 0.361 0.239 0.318 k +*u +1270 244 m +1271 243 l +1270 244 l +f +*U +0.000 0.431 0.376 0.569 k +*u +1312 244 m +1313 243 l +1312 244 l +f +*U +0.000 0.329 0.263 0.216 k +*u +1313 244 m +1314 243 l +1313 244 l +f +*U +0.000 0.153 0.133 0.259 k +*u +1322 244 m +1323 243 l +1322 244 l +f +*U +0.000 0.878 0.675 0.114 k +*u +1326 244 m +1331.463 241.708 1339 243 1345 243 c +1384 243 l +1378.537 245.292 1370.887 244 1365 244 c +1326 244 l +f +*U +0.000 0.290 0.216 0.031 k +*u +1390 244 m +1391 243 l +1390 244 l +f +*U +0.000 0.251 0.176 0.733 k +*u +1271.333 242.333 m +1271.278 242.278 1271.222 241.222 1271.667 241.667 c +1271.722 241.722 1271.778 242.778 1271.333 242.333 c +f +*U +0.000 0.514 0.439 0.486 k +*u +1313 243 m +1314 242 l +1313 243 l +f +*U +0.000 0.322 0.251 0.180 k +*u +1314 243 m +1315 242 l +1314 243 l +f +*U +0.000 0.561 0.404 0.137 k +*u +1323 243 m +1324 242 l +1323 243 l +f +*U +0.000 0.780 0.541 0.220 k +*u +1324 243 m +1324 240 l +1325 241 1325.309 241.612 1326 243 c +1324 243 l +f +*U +0.000 0.541 0.514 0.459 k +*u +1107 242 m +1108.769 241.221 1110 241 1112 241 c +1110.231 241.779 1108.964 241.912 1107 242 c +f +*U +0.000 0.020 0.004 0.282 k +*u +1152.333 241.333 m +1152.278 241.278 1152.222 240.222 1152.667 240.667 c +1152.722 240.722 1152.778 241.778 1152.333 241.333 c +f +*U +0.000 0.827 0.627 0.157 k +*u +1176 242 m +1182.436 239.299 1192 241 1199 241 c +1250 241 l +1243.564 243.701 1233.951 242 1227 242 c +1176 242 l +f +*U +0.000 0.612 0.482 0.388 k +*u +1253 242 m +1252.278 239.582 1252 237.528 1252 235 c +1240 235 l +1243.958 233.339 1248.737 234 1253 234 c +1253.190 236.971 1253.834 239.260 1255 242 c +1253 242 l +f +*U +0.000 0.663 0.490 0.337 k +*u +1272.667 241.667 m +1272.222 241.222 1273.278 241.278 1273.333 241.333 c +1273.778 241.778 1272.722 241.722 1272.667 241.667 c +f +*U +0.000 0.482 0.459 0.518 k +*u +1314 242 m +1315 241 l +1314 242 l +f +*U +0.000 0.396 0.306 0.122 k +*u +1315 242 m +1316 241 l +1315 242 l +f +*U +0.000 0.612 0.459 0.388 k +*u +1323.333 241.333 m +1323.278 241.278 1323.223 240.222 1323.667 240.667 c +1323.722 240.722 1323.778 241.778 1323.333 241.333 c +f +*U +0.000 0.827 0.627 0.157 k +*u +1328 242 m +1333.216 239.811 1340.381 241 1346 241 c +1384 241 l +1378.783 243.189 1371.619 242 1366 242 c +1328 242 l +f +*U +0.000 0.580 0.451 0.349 k +*u +1388 242 m +1388 239 l +1388.696 240.554 1388.696 240.446 1388 242 c +f +*U +0.000 0.267 0.220 0.318 k +*u +1389 242 m +1390 241 l +1389 242 l +f +*U +0.000 0.251 0.188 0.298 k +*u +1059 241 m +1060 240 l +1059 241 l +f +*U +0.000 0.910 0.627 0.090 k +*u +1072 241 m +1075.959 239.339 1080.740 240 1085 240 c +1108 240 l +1104 241.661 1099.260 241 1095 241 c +1072 241 l +f +*U +0.000 0.310 0.169 0.075 k +*u +1108 241 m +1109 240 l +1108 241 l +f +*U +0.000 0.506 0.380 0.000 k +*u +1112 241 m +1113 240 l +1112 241 l +f +*U +0.000 0.255 0.188 0.149 k +*u +1164 241 m +1165 240 l +1164 241 l +f +*U +0.000 0.549 0.459 0.451 k +*u +1165 241 m +1166 240 l +1165 241 l +f +*U +0.000 0.427 0.322 0.122 k +*u +1273 241 m +1274 240 l +1273 241 l +f +*U +0.000 0.275 0.204 0.376 k +*u +1316 241 m +1317 240 l +1316 241 l +f +*U +0.000 0.153 0.145 0.118 k +*u +1389 241 m +1390 240 l +1389 241 l +f +*U +0.000 0.392 0.325 0.443 k +*u +1106.333 239.333 m +1106.278 239.278 1106.222 238.222 1106.667 238.667 c +1106.722 238.722 1106.778 239.778 1106.333 239.333 c +f +*U +0.000 0.290 0.247 0.102 k +*u +1107 240 m +1108 239 l +1107 240 l +f +*U +0.000 0.227 0.188 0.212 k +*u +1115 240 m +1116 239 l +1115 240 l +f +*U +0.000 0.686 0.486 0.310 k +*u +1116 240 m +1118.432 238.683 1120.248 238.723 1123 239 c +1120.668 239.985 1118.543 239.981 1116 240 c +f +*U +0.000 0.494 0.424 0.478 k +*u +1152 240 m +1152 234 l +1152.951 236.285 1152.951 237.715 1152 240 c +f +*U +0.000 0.180 0.118 0.420 k +*u +1166 240 m +1167 239 l +1166 240 l +f +*U +0.000 0.263 0.165 0.714 k +*u +1167 240 m +1168 239 l +1167 240 l +f +*U +0.000 0.231 0.137 0.035 k +*u +1253 240 m +1254 239 l +1253 240 l +f +*U +0.000 0.576 0.447 0.424 k +*u +1275.667 239.667 m +1275.222 239.222 1276.278 239.278 1276.333 239.333 c +1276.778 239.778 1275.722 239.722 1275.667 239.667 c +f +*U +0.000 0.722 0.553 0.278 k +*u +1317 240 m +1317.684 238.420 1317.804 238.223 1319 237 c +1318.316 238.580 1318.195 238.777 1317 240 c +f +*U +0.000 0.431 0.310 0.322 k +*u +1060 239 m +1061 238 l +1060 239 l +f +*U +0.000 0.561 0.478 0.439 k +*u +1061 239 m +1061 236 l +1061.696 237.554 1061.696 237.446 1061 239 c +f +*U +0.000 0.471 0.349 0.506 k +*u +1105 239 m +1105 234 l +1105.830 236 1105.830 236.970 1105 239 c +f +*U +0.000 0.329 0.282 0.165 k +*u +1118 239 m +1119 238 l +1118 239 l +f +*U +0.000 0.506 0.424 0.494 k +*u +1120 239 m +1121.248 238.315 1121.549 238.251 1123 238 c +1121.752 238.685 1121.452 238.749 1120 239 c +f +*U +0.000 0.216 0.141 0.059 k +*u +1167 239 m +1168 238 l +1167 239 l +f +*U +0.000 0.698 0.537 0.302 k +*u +1168.667 238.667 m +1168.222 238.222 1169.278 238.278 1169.333 238.333 c +1169.778 238.778 1168.722 238.722 1168.667 238.667 c +f +*U +0.000 0.369 0.267 0.212 k +*u +1276 239 m +1277 238 l +1276 239 l +f +*U +0.000 0.384 0.278 0.525 k +*u +1277.333 238.333 m +1277.278 238.278 1277.222 237.222 1277.667 237.667 c +1277.722 237.722 1277.778 238.778 1277.333 238.333 c +f +*U +0.000 0.286 0.192 0.133 k +*u +1321 239 m +1322 238 l +1321 239 l +f +*U +0.000 0.698 0.478 0.302 k +*u +1322 239 m +1321 237.521 1321 237.797 1321 236 c +1322.290 237.443 1322.401 237.234 1322 239 c +f +*U +0.000 0.271 0.204 0.059 k +*u +1388.333 238.333 m +1388.278 238.278 1388.222 237.222 1388.667 237.667 c +1388.722 237.722 1388.778 238.778 1388.333 238.333 c +f +*U +0.000 0.247 0.208 0.059 k +*u +1060 238 m +1061 237 l +1060 238 l +f +*U +0.000 0.200 0.188 0.122 k +*u +1106 238 m +1107 237 l +1106 238 l +f +*U +0.000 0.176 0.137 0.086 k +*u +1125 238 m +1126 237 l +1125 238 l +f +*U +0.000 0.635 0.471 0.365 k +*u +1126 238 m +1126.545 236.365 1126.365 236.545 1128 236 c +1128 238 l +1126 238 l +f +*U +0.000 0.325 0.271 0.318 k +*u +1169 238 m +1170 237 l +1169 238 l +f +*U +0.000 0.243 0.180 0.012 k +*u +1253 238 m +1254 237 l +1253 238 l +f +*U +0.000 0.498 0.388 0.000 k +*u +1319 238 m +1320 237 l +1319 238 l +f +*U +0.000 0.420 0.298 0.404 k +*u +1387.333 237.333 m +1387.278 237.278 1387.222 236.222 1387.667 236.667 c +1387.722 236.722 1387.778 237.778 1387.333 237.333 c +f +*U +0.000 0.373 0.282 0.012 k +*u +1126 237 m +1127 236 l +1126 237 l +f +*U +0.000 0.204 0.176 0.110 k +*u +1153 237 m +1153 234 l +1153.696 235.554 1153.696 235.446 1153 237 c +f +*U +0.000 0.318 0.286 0.227 k +*u +1170 237 m +1171 236 l +1170 237 l +f +*U +0.000 0.263 0.196 0.298 k +*u +1253 237 m +1253 234 l +1253.696 235.554 1253.696 235.446 1253 237 c +f +*U +0.000 0.482 0.478 0.518 k +*u +1277 237 m +1276 234 l +1277.766 234.979 1277.956 235.222 1277 237 c +f +*U +0.000 0.129 0.122 0.337 k +*u +1061.333 235.333 m +1061.278 235.278 1061.222 234.222 1061.667 234.667 c +1061.722 234.722 1061.778 235.778 1061.333 235.333 c +f +*U +0.000 0.420 0.325 0.580 k +*u +1062.333 235.333 m +1062.278 235.278 1062.222 234.222 1062.667 234.667 c +1062.722 234.722 1062.778 235.778 1062.333 235.333 c +f +*U +0.000 0.306 0.239 0.580 k +*u +1127.333 235.333 m +1127.278 235.278 1127.222 234.222 1127.667 234.667 c +1127.722 234.722 1127.778 235.778 1127.333 235.333 c +f +*U +0.000 0.365 0.318 0.102 k +*u +1171 236 m +1172 235 l +1171 236 l +f +*U +0.000 0.420 0.298 0.561 k +*u +1386.333 235.333 m +1386.278 235.278 1386.223 234.222 1386.667 234.667 c +1386.722 234.722 1386.778 235.778 1386.333 235.333 c +f +*U +0.000 0.227 0.173 0.227 k +*u +1387 236 m +1388 235 l +1387 236 l +f +*U +0.000 0.729 0.580 0.271 k +*u +1063 235 m +1067.215 233.231 1072.464 234 1077 234 c +1105 234 l +1100.785 235.769 1095.536 235 1091 235 c +1063 235 l +f +1128 235 m +1134.687 232.194 1144.767 234 1152 234 c +1145.313 236.806 1135.233 235 1128 235 c +f +*U +0.000 0.341 0.282 0.149 k +*u +1172 235 m +1173 234 l +1172 235 l +f +*U +0.000 0.471 0.447 0.529 k +*u +1173.667 234.667 m +1173.222 234.222 1174.278 234.278 1174.333 234.333 c +1174.778 234.778 1173.722 234.722 1173.667 234.667 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1175 235 m +1180.951 232.503 1189.580 234 1196 234 c +1240 234 l +1234 236.497 1225.420 235 1219 235 c +1175 235 l +f +*U +0.000 0.255 0.180 0.157 k +*u +1275 235 m +1276 234 l +1275 235 l +f +*U +0.000 0.729 0.580 0.271 k +*u +1278 235 m +1281.699 233.448 1286 234 1290 234 c +1311 234 l +1386 234 l +1382.301 235.552 1377.983 235 1374 235 c +1353 235 l +1278 235 l +f +*U +0.004 0.000 0.000 0.000 k +*u +1971 228 m +1969.647 227 1969.645 227.177 1968 227 c +1968 190 l +1432 190 l +1436.215 188.231 1441.464 189 1446 189 c +1473 189 l +1567 189 l +1840 189 l +1925 189 l +1939 189 1955.321 191.257 1969 188 c +1969 224 l +1969.810 221.271 1969.979 218.850 1970 216 c +1971.452 219.427 1972.263 224.480 1971 228 c +f +*U +0.000 0.204 0.137 0.133 k +*u +1973 228 m +1974 227 l +1973 228 l +f +*U +0.000 0.333 0.259 0.667 k +*u +1973 227 m +1974 226 l +1973 227 l +f +*U +0.000 0.694 0.478 0.282 k +*u +1974 227 m +1971.938 214.812 1974.578 201.484 1973 189 c +1975.477 192.270 1975.000 195.999 1975 200 c +1975 207.751 1973 218 1977 225 c +1975.814 226.186 1975.416 226.528 1974 227 c +f +*U +0.000 0.306 0.224 0.176 k +*u +1976 226 m +1977 225 l +1976 226 l +f +*U +0.000 0.318 0.227 0.337 k +*u +1977 225 m +1978 224 l +1977 225 l +f +*U +0.000 0.184 0.188 0.102 k +*u +1136 224 m +1137 223 l +1136 224 l +f +*U +0.031 0.000 0.039 0.169 k +*u +1176 224 m +1177 223 l +1176 224 l +f +*U +0.000 0.733 0.588 0.267 k +*u +1973 224 m +1973 192 l +1974.328 195 1974.000 198.581 1974 202 c +1974 208.686 1975.599 217.806 1973 224 c +f +*U +0.000 0.698 0.541 0.302 k +*u +1978.333 223.333 m +1978.278 223.278 1978.222 222.222 1978.667 222.667 c +1978.722 222.722 1978.778 223.778 1978.333 223.333 c +f +*U +0.000 0.373 0.298 0.208 k +*u +1979 224 m +1980 223 l +1979 224 l +f +*U +0.000 0.133 0.090 0.208 k +*u +1066 223 m +1067 222 l +1066 223 l +f +*U +0.000 0.329 0.298 0.671 k +*u +1067 223 m +1068 222 l +1067 223 l +f +*U +0.000 0.525 0.412 0.475 k +*u +1068 223 m +1072.969 220.915 1079.650 222 1085 222 c +1120 222 l +1115 224 1108.350 223 1103 223 c +1068 223 l +f +*U +0.000 0.141 0.078 0.224 k +*u +1120 223 m +1121 222 l +1120 223 l +f +*U +0.000 0.063 0.031 0.686 k +*u +1135 223 m +1136 222 l +1135 223 l +f +*U +0.000 0.588 0.588 0.412 k +*u +1136 223 m +1137.458 221.919 1138.248 221.564 1140 221 c +1138.457 222.267 1137.952 222.489 1136 223 c +f +*U +0.000 0.529 0.400 0.471 k +*u +1139 223 m +1143.724 221 1149.910 222 1155 222 c +1150.276 223.982 1144 223 1139 223 c +f +*U +0.000 0.224 0.192 0.337 k +*u +1155 223 m +1156 222 l +1155 223 l +f +*U +0.000 0.278 0.180 0.094 k +*u +1175.333 222.333 m +1175.278 222.278 1175.222 221.222 1175.667 221.667 c +1175.722 221.722 1175.778 222.778 1175.333 222.333 c +f +*U +0.000 0.525 0.412 0.475 k +*u +1176 223 m +1180.969 220.915 1187.650 222 1193 222 c +1207 222 1223.321 224.257 1237 221 c +1233.803 224.658 1225.577 223 1221 223 c +1176 223 l +f +*U +0.000 0.298 0.259 0.702 k +*u +1237.667 222.667 m +1237.222 222.222 1238.278 222.278 1238.333 222.333 c +1238.778 222.778 1237.722 222.722 1237.667 222.667 c +f +*U +0.000 0.118 0.122 0.196 k +*u +1239 223 m +1240 222 l +1239 223 l +f +*U +0.000 0.341 0.247 0.204 k +*u +1266 223 m +1266 220 l +1266.696 221.554 1266.696 221.446 1266 223 c +f +*U +0.000 0.525 0.412 0.475 k +*u +1267 220 m +1274.573 224.212 1286.527 222 1295 222 c +1355 222 l +1362.993 222 1373.844 223.980 1381 220 c +1382 223 l +1294 223 l +1274 223 l +1270.610 223 1267.797 223.720 1267 220 c +f +*U +0.000 0.239 0.180 0.176 k +*u +1382 223 m +1383 222 l +1382 223 l +f +*U +0.000 0.431 0.431 0.569 k +*u +1979 223 m +1980 222 l +1979 223 l +f +*U +0.000 0.416 0.325 0.329 k +*u +1980 223 m +1981 222 l +1980 223 l +f +*U +0.000 0.875 0.627 0.125 k +*u +1067 222 m +1069.303 218.837 1071.658 213.242 1075.329 211.603 c +1079.551 209.719 1086.451 211 1091 211 c +1126 211 l +1124.811 214.701 1122.757 218.979 1118.816 220.436 c +1114 222.214 1107 221 1102 221 c +1090.306 221 1078.604 220.533 1067 222 c +f +*U +0.000 0.941 0.659 0.059 k +*u +1070 222 m +1074.720 220 1080.920 221 1086 221 c +1120 221 l +1115.280 222.981 1109 222 1104 222 c +1070 222 l +f +*U +0.000 0.647 0.529 0.341 k +*u +1120.333 221.333 m +1120.278 221.278 1120.222 220.222 1120.667 220.667 c +1120.722 220.722 1120.778 221.778 1120.333 221.333 c +f +*U +0.000 0.478 0.365 0.173 k +*u +1136.667 221.667 m +1136.222 221.222 1137.278 221.278 1137.333 221.333 c +1137.778 221.778 1136.722 221.722 1136.667 221.667 c +f +*U +0.000 0.886 0.647 0.114 k +*u +1140 222 m +1141.657 220 1143.887 218.760 1145.326 216.742 c +1146.630 214.912 1146.943 212.610 1149.183 211.603 c +1152.475 210 1157.459 211 1161 211 c +1159.231 211.779 1157.964 211.912 1156 212 c +1161.382 223 1146.695 222 1140 222 c +f +*U +0.000 0.643 0.522 0.357 k +*u +1155.333 221.333 m +1155.278 221.278 1155.222 220.222 1155.667 220.667 c +1155.722 220.722 1155.778 221.778 1155.333 221.333 c +f +*U +0.000 0.875 0.627 0.125 k +*u +1176 222 m +1176 218.577 1176 214.938 1178.920 212.514 c +1181 210.636 1184.292 211 1187 211 c +1193.292 210.987 1199.722 210.628 1206 211 c +1209.773 211.310 1212.695 213.205 1216 211 c +1218.709 211.648 1221.215 211.942 1224 212 c +1224.272 220.344 1229.279 219.399 1236 221 c +1230 223.464 1223 221 1217 221 c +1203.284 220.841 1189.644 221.962 1176 222 c +f +*U +0.000 0.941 0.659 0.059 k +*u +1184 222 m +1188.215 220.231 1193.464 221 1198 221 c +1224 221 l +1219.785 222.769 1214.536 222 1210 222 c +1184 222 l +f +*U +0.000 0.416 0.298 0.361 k +*u +1237 222 m +1238 221 l +1237 222 l +f +*U +0.000 0.941 0.659 0.059 k +*u +1268 222 m +1271 218 l +1276.837 223.572 1289.407 221 1297 221 c +1368 221 l +1359.642 224.507 1346 222 1337 222 c +1268 222 l +f +*U +0.000 0.875 0.620 0.125 k +*u +1272 218 m +1271 220 l +1269.787 217 1270 214 1270 211 c +1288.808 211 1308.257 209.555 1327 211 c +1331.214 211.396 1334.743 213.694 1339 214 c +1339 211 l +1363 211 l +1366.417 211 1370.579 210.351 1373.917 211 c +1376.340 211.663 1381.961 219 1379.472 221.278 c +1378.196 222.430 1375.553 222 1374 222 c +1369.277 222 1364.736 221 1360 221 c +1301 221 l +1280 221 l +1276.470 221 1272.855 221.992 1272 218 c +f +*U +0.000 0.345 0.235 0.325 k +*u +1381 222 m +1382 221 l +1381 222 l +f +*U +0.000 0.388 0.302 0.141 k +*u +1982 222 m +1983 221 l +1982 222 l +f +*U +0.000 0.255 0.180 0.039 k +*u +1067 221 m +1068 220 l +1067 221 l +f +*U +0.000 0.482 0.329 0.416 k +*u +1068.333 220.333 m +1068.278 220.278 1068.222 219.222 1068.667 219.667 c +1068.722 219.722 1068.778 220.778 1068.333 220.333 c +f +*U +0.000 0.282 0.259 0.216 k +*u +1121 221 m +1122 220 l +1121 221 l +f +*U +0.000 0.235 0.208 0.239 k +*u +1139 221 m +1140 220 l +1139 221 l +f +*U +0.000 0.647 0.431 0.353 k +*u +1140.667 220.667 m +1140.222 220.222 1141.278 220.278 1141.333 220.333 c +1141.778 220.778 1140.722 220.722 1140.667 220.667 c +f +*U +0.000 0.365 0.298 0.153 k +*u +1156 221 m +1157 220 l +1156 221 l +f +*U +0.000 0.427 0.282 0.188 k +*u +1175 221 m +1176 220 l +1175 221 l +f +*U +0.000 0.506 0.388 0.494 k +*u +1234.667 220.667 m +1234.222 220.222 1235.278 220.278 1235.333 220.333 c +1235.778 220.778 1234.722 220.722 1234.667 220.667 c +f +*U +0.000 0.298 0.220 0.212 k +*u +1236 221 m +1237 220 l +1236 221 l +f +*U +0.000 0.259 0.180 0.067 k +*u +1381 221 m +1382 220 l +1381 221 l +f +*U +0.000 0.529 0.443 0.471 k +*u +1982.667 220.667 m +1982.222 220.222 1983.278 220.278 1983.333 220.333 c +1983.778 220.778 1982.722 220.722 1982.667 220.667 c +f +*U +0.000 0.584 0.525 0.416 k +*u +1121.333 219.333 m +1121.278 219.278 1121.222 218.222 1121.667 218.667 c +1121.722 218.722 1121.778 219.778 1121.333 219.333 c +f +*U +0.000 0.463 0.353 0.255 k +*u +1141 220 m +1142 219 l +1141 220 l +f +*U +0.000 0.678 0.635 0.267 k +*u +1156 220 m +1156.684 218.420 1156.805 218.223 1158 217 c +1157.316 218.580 1157.195 218.777 1156 220 c +f +*U +0.000 0.184 0.118 0.180 k +*u +1157 220 m +1158 219 l +1157 220 l +f +*U +0.000 0.573 0.388 0.427 k +*u +1175 220 m +1175 216 l +1175.710 217.760 1175.710 218.240 1175 220 c +f +*U +0.000 0.624 0.443 0.376 k +*u +1224 217 m +1227.412 218.446 1230.304 218.959 1234 219 c +1230.302 220.551 1226.279 220.515 1224 217 c +f +*U +0.000 0.216 0.165 0.133 k +*u +1234 220 m +1235 219 l +1234 220 l +f +*U +0.000 0.741 0.537 0.259 k +*u +1267 220 m +1269 216 l +1269.558 218.308 1268.996 218.756 1267 220 c +f +*U +0.000 0.349 0.282 0.278 k +*u +1985 220 m +1986 219 l +1985 220 l +f +*U +0.000 0.306 0.216 0.008 k +*u +1068 219 m +1069 218 l +1068 219 l +f +*U +0.000 0.431 0.302 0.443 k +*u +1069.333 218.333 m +1069.278 218.278 1069.222 217.222 1069.667 217.667 c +1069.722 217.722 1069.778 218.778 1069.333 218.333 c +f +*U +0.000 0.345 0.282 0.145 k +*u +1122 219 m +1123 218 l +1122 219 l +f +*U +0.000 0.333 0.176 0.090 k +*u +1142 219 m +1143 218 l +1142 219 l +f +*U +0.000 0.631 0.482 0.369 k +*u +1143 219 m +1146 214 l +1146.611 216.816 1145.444 217.675 1143 219 c +f +*U +0.000 0.271 0.200 0.071 k +*u +1226 219 m +1227.506 218.317 1228.314 218.174 1230 218 c +1228.494 218.683 1227.685 218.826 1226 219 c +f +*U +0.000 0.337 0.243 0.086 k +*u +1267 219 m +1268 218 l +1267 219 l +f +*U +0.000 0.722 0.592 0.278 k +*u +1986 219 m +1987.229 217 1987.868 216.777 1990 216 c +1988.607 217.434 1987.767 218 1986 219 c +f +*U +0.000 0.341 0.239 0.000 k +*u +1987 219 m +1988 218 l +1987 219 l +f +*U +0.000 0.718 0.514 0.282 k +*u +1070.333 217.333 m +1070.278 217.278 1070.222 216.222 1070.667 216.667 c +1070.722 216.722 1070.778 217.778 1070.333 217.333 c +f +*U +0.000 0.290 0.271 0.106 k +*u +1158 218 m +1159 217 l +1158 218 l +f +*U +0.000 0.239 0.216 0.141 k +*u +1225.333 217.333 m +1225.278 217.278 1225.222 216.222 1225.667 216.667 c +1225.722 216.722 1225.778 217.778 1225.333 217.333 c +f +*U +0.000 0.404 0.286 0.369 k +*u +1268 218 m +1269 217 l +1268 218 l +f +*U +0.000 0.357 0.282 0.384 k +*u +1379 218 m +1380 217 l +1379 218 l +f +*U +0.000 0.357 0.255 0.027 k +*u +1069 217 m +1070 216 l +1069 217 l +f +*U +0.000 0.118 0.165 0.325 k +*u +1123 217 m +1124 216 l +1123 217 l +f +*U +0.000 0.714 0.514 0.243 k +*u +1158 217 m +1156 212 l +1161 212 l +1160 213.962 1159.366 215.369 1158 217 c +f +*U +0.000 0.459 0.333 0.541 k +*u +1224 217 m +1224 214 l +1224.696 215.554 1224.696 215.446 1224 217 c +f +*U +0.000 0.204 0.153 0.161 k +*u +1268 217 m +1269 216 l +1268 217 l +f +*U +0.000 0.251 0.188 0.153 k +*u +1990 217 m +1991 216 l +1990 217 l +f +*U +0.000 0.616 0.475 0.384 k +*u +27 216 m +27 206 l +28.346 209.207 28.346 212.793 27 216 c +f +*U +0.000 0.271 0.176 0.612 k +*u +1070 216 m +1071 215 l +1070 216 l +f +*U +0.000 0.761 0.553 0.239 k +*u +1071 216 m +1071.526 213.457 1071.878 212.465 1074 211 c +1073.199 213 1072.503 214.337 1071 216 c +f +*U +0.000 0.227 0.145 0.133 k +*u +1124 216 m +1125 215 l +1124 216 l +f +*U +0.000 0.373 0.271 0.227 k +*u +1145 216 m +1146 215 l +1145 216 l +f +*U +0.000 0.063 0.035 0.706 k +*u +1175 216 m +1176 215 l +1175 216 l +f +*U +0.000 0.616 0.455 0.384 k +*u +1269 216 m +1269 211 l +1269.830 213 1269.830 213.970 1269 216 c +f +*U +0.000 0.494 0.369 0.506 k +*u +1377.333 215.333 m +1377.278 215.278 1377.222 214.222 1377.667 214.667 c +1377.722 214.722 1377.778 215.778 1377.333 215.333 c +f +*U +0.000 0.208 0.137 0.475 k +*u +1378 216 m +1379 215 l +1378 216 l +f +*U +0.000 0.745 0.545 0.247 k +*u +1990 216 m +1990 214 l +1992 214 l +1992 216 l +1990 216 l +f +*U +0.000 0.263 0.176 0.141 k +*u +1070 215 m +1071 214 l +1070 215 l +f +*U +0.000 0.855 0.541 0.145 k +*u +1080 215 m +1084.215 213.231 1089.465 214 1094 214 c +1120 214 l +1115.785 215.769 1110.536 215 1106 215 c +1080 215 l +f +*U +0.000 0.067 0.047 0.267 k +*u +1175 215 m +1176 214 l +1175 215 l +f +*U +0.000 0.678 0.510 0.322 k +*u +1176.667 214.667 m +1176.222 214.222 1177.278 214.278 1177.333 214.333 c +1177.778 214.778 1176.722 214.722 1176.667 214.667 c +f +*U +0.000 0.855 0.541 0.145 k +*u +1184 215 m +1190.687 212.194 1200.767 214 1208 214 c +1201.313 216.806 1191.233 215 1184 215 c +f +1272 215 m +1276.720 213 1282.920 214 1288 214 c +1320 214 l +1315.280 215.980 1309 215 1304 215 c +1272 215 l +f +*U +0.000 0.388 0.302 0.612 k +*u +1992 215 m +1993 214 l +1992 215 l +f +*U +0.000 0.333 0.263 0.149 k +*u +1993 215 m +1994 214 l +1993 215 l +f +*U +0.000 0.918 0.694 0.082 k +*u +1080 214 m +1084.215 212.231 1089.465 213 1094 213 c +1121 213 l +1116.785 214.769 1111.535 214 1107 214 c +1080 214 l +f +*U +0.000 0.400 0.275 0.231 k +*u +1125 214 m +1126 213 l +1125 214 l +f +*U +0.000 0.263 0.188 0.149 k +*u +1160 214 m +1161 213 l +1160 214 l +f +*U +0.000 0.392 0.294 0.298 k +*u +1177 214 m +1178 213 l +1177 214 l +f +*U +0.000 0.271 0.169 0.282 k +*u +1224.333 213.333 m +1224.278 213.278 1224.222 212.222 1224.667 212.667 c +1224.722 212.722 1224.778 213.778 1224.333 213.333 c +f +*U +0.000 0.678 0.510 0.322 k +*u +1333 214 m +1335 213 1336.747 213 1339 213 c +1336.948 213.874 1335.253 213.953 1333 214 c +f +*U +0.000 0.369 0.247 0.353 k +*u +1377 214 m +1378 213 l +1377 214 l +f +*U +0.000 0.459 0.333 0.384 k +*u +1993.667 213.667 m +1993.222 213.223 1994.277 213.277 1994.333 213.333 c +1994.778 213.778 1993.722 213.722 1993.667 213.667 c +f +*U +0.000 0.275 0.176 0.180 k +*u +1071 213 m +1072 212 l +1071 213 l +f +*U +0.000 0.302 0.220 0.357 k +*u +1126 213 m +1127 212 l +1126 213 l +f +*U +0.000 0.361 0.263 0.000 k +*u +1146 213 m +1147 212 l +1146 213 l +f +*U +0.000 0.306 0.224 0.396 k +*u +1161 213 m +1162 212 l +1161 213 l +f +*U +0.000 0.518 0.388 0.408 k +*u +1178.333 212.333 m +1178.278 212.278 1178.222 211.222 1178.667 211.667 c +1178.722 211.722 1178.778 212.778 1178.333 212.333 c +f +*U +0.000 0.525 0.329 0.380 k +*u +1210 211 m +1211.580 211.684 1211.777 211.805 1213 213 c +1211.420 212.316 1211.223 212.195 1210 211 c +f +*U +0.000 0.545 0.435 0.455 k +*u +1213 213 m +1214.248 212.315 1214.548 212.251 1216 212 c +1214.751 212.685 1214.452 212.749 1213 213 c +f +*U +0.000 0.502 0.357 0.345 k +*u +1332 210 m +1333 211 1333.309 211.612 1334 213 c +1331.797 212 1331.952 212.330 1332 210 c +f +*U +0.000 0.165 0.141 0.129 k +*u +1334 213 m +1335 212 l +1334 213 l +f +*U +0.000 0.439 0.310 0.165 k +*u +1338 213 m +1338 210 l +1338.696 211.554 1338.696 211.446 1338 213 c +f +*U +0.000 0.506 0.337 0.494 k +*u +1376 213 m +1377 212 l +1376 213 l +f +*U +0.000 0.380 0.275 0.306 k +*u +1996 213 m +1997 212 l +1996 213 l +f +*U +0.000 0.592 0.427 0.408 k +*u +1124 211 m +1126 210.249 1126.596 210.344 1128 212 c +1124 211 l +f +*U +0.000 0.349 0.239 0.329 k +*u +1147 212 m +1148 211 l +1147 212 l +f +*U +0.000 0.588 0.467 0.412 k +*u +1159 211 m +1161 210.249 1161.596 210.344 1163 212 c +1159 211 l +f +*U +0.000 0.416 0.298 0.294 k +*u +1163 212 m +1164 211 l +1163 212 l +f +*U +0.000 0.325 0.192 0.098 k +*u +1212 212 m +1213 211 l +1212 212 l +f +*U +0.106 0.000 0.110 0.184 k +*u +1215 212 m +1216 211 l +1215 212 l +f +*U +0.000 0.416 0.341 0.584 k +*u +1217.667 211.667 m +1217.222 211.222 1218.278 211.278 1218.333 211.333 c +1218.778 211.778 1217.722 211.722 1217.667 211.667 c +f +*U +0.000 0.659 0.443 0.341 k +*u +1219 212 m +1220.769 211.221 1222 211 1224 211 c +1222.231 211.779 1220.964 211.912 1219 212 c +f +*U +0.000 0.173 0.106 0.137 k +*u +1224 212 m +1225 211 l +1224 212 l +f +*U +0.000 0.322 0.208 0.341 k +*u +1376 212 m +1377 211 l +1376 212 l +f +*U +0.000 0.706 0.490 0.259 k +*u +1996 212 m +1997.222 210.267 1998 209.849 2000 209 c +1998.771 210.870 1998 211.224 1996 212 c +f +*U +0.000 0.251 0.188 0.153 k +*u +1998 212 m +1999 211 l +1998 212 l +f +*U +0.000 0.459 0.376 0.090 k +*u +1072 211 m +1073 210 l +1072 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1073 211 m +1077.969 208.915 1084.650 210 1090 210 c +1124 210 l +1119 212 1112.350 211 1107 211 c +1073 211 l +f +*U +0.020 0.000 0.008 0.898 k +*u +1128 211 m +1129 210 l +1128 211 l +f +*U +0.000 0.027 0.020 0.627 k +*u +1129 211 m +1130 210 l +1129 211 l +f +*U +0.000 0.020 0.016 0.255 k +*u +1130 211 m +1131 210 l +1130 211 l +f +*U +0.000 0.259 0.180 0.443 k +*u +1148 211 m +1149 210 l +1148 211 l +f +*U +0.000 0.576 0.388 0.416 k +*u +1149 211 m +1150.248 210.315 1150.548 210.251 1152 210 c +1150.752 210.685 1150.452 210.749 1149 211 c +f +*U +0.000 0.345 0.345 0.655 k +*u +1152 211 m +1154.332 210 1156.457 210 1159 210 c +1156.668 210.984 1154.543 210.981 1152 211 c +f +*U +0.000 0.161 0.153 0.839 k +*u +1163.667 210.667 m +1163.222 210.222 1164.278 210.278 1164.333 210.333 c +1164.778 210.778 1163.722 210.722 1163.667 210.667 c +f +*U +0.000 0.047 0.047 0.631 k +*u +1165 211 m +1166 210 l +1165 211 l +f +*U +0.000 0.243 0.184 0.165 k +*u +1178 211 m +1179 210 l +1178 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1179 211 m +1187.367 207.489 1200.924 210 1210 210 c +1201.633 213.511 1188 211 1179 211 c +f +*U +0.000 0.329 0.227 0.275 k +*u +1210 211 m +1211 210 l +1210 211 l +f +*U +0.000 0.145 0.129 0.267 k +*u +1221 211 m +1222.248 210.315 1222.549 210.251 1224 210 c +1222.752 210.685 1222.451 210.749 1221 211 c +f +*U +0.000 0.333 0.243 0.361 k +*u +1269 211 m +1270 210 l +1269 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1270 211 m +1275.707 208.605 1283.846 210 1290 210 c +1332 210 l +1326.293 212.395 1318 211 1312 211 c +1270 211 l +f +*U +0.000 0.533 0.435 0.467 k +*u +1339 211 m +1340.506 210.317 1341.315 210.174 1343 210 c +1341.494 210.683 1340.686 210.826 1339 211 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1343 211 m +1346.699 209.448 1351 210 1355 210 c +1376 210 l +1372.301 211.552 1367.983 211 1364 211 c +1343 211 l +f +*U +0.000 0.431 0.282 0.545 k +*u +2000 210 m +2001 209 l +2000 210 l +f +*U +0.000 0.361 0.239 0.027 k +*u +2001 210 m +2002 209 l +2001 210 l +f +*U +0.000 0.416 0.267 0.310 k +*u +2002 209 m +2003 208 l +2002 209 l +f +*U +0.000 0.455 0.333 0.349 k +*u +0.333 207.333 m +0.278 207.278 0.222 206.222 0.667 206.667 c +0.722 206.722 0.778 207.778 0.333 207.333 c +f +*U +0.000 0.651 0.482 0.349 k +*u +1 208 m +1 200 l +2 202.770 2 205.230 1 208 c +f +*U +0.000 0.537 0.498 0.388 k +*u +2002.667 207.667 m +2002.222 207.223 2003.277 207.277 2003.333 207.333 c +2003.778 207.778 2002.722 207.722 2002.667 207.667 c +f +*U +0.000 0.310 0.345 0.047 k +*u +2004 208 m +2005 207 l +2004 208 l +f +*U +0.000 0.184 0.137 0.047 k +*u +28 207 m +29 206 l +28 207 l +f +*U +0.000 0.357 0.322 0.310 k +*u +2005 207 m +2006 206 l +2005 207 l +f +*U +0.000 0.286 0.220 0.165 k +*u +0.333 205.333 m +0.278 205.278 0.222 204.222 0.667 204.667 c +0.722 204.722 0.778 205.778 0.333 205.333 c +f +*U +0.000 0.271 0.200 0.212 k +*u +28 206 m +29 205 l +28 206 l +f +*U +0.000 0.553 0.420 0.357 k +*u +2005.667 205.667 m +2005.222 205.223 2006.277 205.277 2006.333 205.333 c +2006.778 205.778 2005.722 205.722 2005.667 205.667 c +f +*U +0.000 0.510 0.396 0.180 k +*u +2007 206 m +2008 205 l +2007 206 l +f +*U +0.000 0.192 0.161 0.055 k +*u +0 204 m +1 203 l +0 204 l +f +*U +0.000 0.604 0.471 0.396 k +*u +28.333 203.333 m +28.278 203.278 28.222 202.222 28.667 202.667 c +28.722 202.722 28.778 203.778 28.333 203.333 c +f +*U +0.000 0.325 0.239 0.231 k +*u +2010 204 m +2011 203 l +2010 204 l +f +*U +0.000 0.282 0.196 0.024 k +*u +29 203 m +30 202 l +29 203 l +f +*U +0.000 0.443 0.373 0.557 k +*u +2011 203 m +2012 202 l +2011 203 l +f +*U +0.000 0.400 0.275 0.255 k +*u +29 202 m +30 201 l +29 202 l +f +*U +0.000 0.337 0.239 0.310 k +*u +2013 202 m +2014 201 l +2013 202 l +f +*U +0.000 0.435 0.290 0.439 k +*u +29 201 m +30 200 l +29 201 l +f +*U +0.000 0.376 0.267 0.482 k +*u +2014 201 m +2015 200 l +2014 201 l +f +*U +0.000 0.106 0.086 0.224 k +*u +2015 201 m +2016 200 l +2015 201 l +f +*U +0.000 0.349 0.235 0.165 k +*u +1 200 m +2 199 l +1 200 l +f +*U +0.000 0.408 0.337 0.094 k +*u +30 200 m +31 199 l +30 200 l +f +*U +0.000 0.220 0.125 0.122 k +*u +1080 200 m +1081.506 199.317 1082.315 199.174 1084 199 c +1082.494 199.683 1081.685 199.826 1080 200 c +f +*U +0.000 0.063 0.051 0.216 k +*u +1086 200 m +1087 199 l +1086 200 l +f +*U +0.000 0.208 0.078 0.118 k +*u +1088 200 m +1089.248 199.315 1089.549 199.251 1091 199 c +1089.751 199.685 1089.452 199.749 1088 200 c +f +*U +0.000 0.286 0.169 0.071 k +*u +1095 200 m +1098.699 198.448 1103 199 1107 199 c +1127 199 l +1123.301 200.552 1118.983 200 1115 200 c +1095 200 l +f +*U +0.016 0.000 0.024 0.204 k +*u +1163 200 m +1163 198 l +1164.635 198.545 1164.455 198.365 1165 200 c +1163 200 l +f +*U +0.000 0.286 0.169 0.071 k +*u +1175 200 m +1181.687 197.194 1191.767 199 1199 199 c +1192.313 201.806 1182.233 200 1175 200 c +f +*U +0.000 0.165 0.165 0.204 k +*u +1204 200 m +1205.248 199.315 1205.548 199.251 1207 199 c +1205.751 199.685 1205.452 199.749 1204 200 c +f +*U +0.004 0.000 0.024 0.212 k +*u +1266 200 m +1267 199 l +1266 200 l +f +*U +0.000 0.106 0.314 0.196 k +*u +1267 200 m +1268 199 l +1267 200 l +f +*U +0.000 0.094 0.082 0.153 k +*u +1274 200 m +1275 199 l +1274 200 l +f +*U +0.000 0.306 0.275 0.110 k +*u +1279.667 199.667 m +1279.222 199.222 1280.278 199.278 1280.333 199.333 c +1280.778 199.778 1279.722 199.722 1279.667 199.667 c +f +*U +0.000 0.063 0.016 0.200 k +*u +1298 200 m +1299.248 199.315 1299.549 199.251 1301 199 c +1299.751 199.685 1299.452 199.749 1298 200 c +f +*U +0.000 0.286 0.169 0.071 k +*u +1315 200 m +1319.724 198 1325.910 199 1331 199 c +1326.276 200.982 1320 200 1315 200 c +f +*U +0.000 0.039 0.035 0.169 k +*u +1333 200 m +1334 199 l +1333 200 l +f +*U +0.000 0.286 0.169 0.071 k +*u +1346 200 m +1350.217 198.231 1355.459 199 1360 199 c +1355.783 200.769 1350.541 200 1346 200 c +f +*U +0.000 0.125 0.122 0.157 k +*u +1365 200 m +1366.506 199.317 1367.315 199.174 1369 199 c +1367.494 199.683 1366.685 199.826 1365 200 c +f +*U +0.000 0.333 0.239 0.271 k +*u +2016 200 m +2017 199 l +2016 200 l +f +*U +0.000 0.271 0.188 0.000 k +*u +1 199 m +2 198 l +1 199 l +f +*U +0.000 0.533 0.435 0.467 k +*u +2 199 m +2 196 l +2.696 197.554 2.696 197.446 2 199 c +f +*U +0.000 0.569 0.435 0.412 k +*u +30 199 m +31 195 l +31.393 196.924 31 197.360 30 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1080 199 m +1084.188 196.579 1091 198 1096 198 c +1108.785 198 1122.402 199.339 1135 197 c +1131.914 200.531 1124.411 199 1120 199 c +1080 199 l +f +*U +0.000 0.318 0.255 0.682 k +*u +1164 199 m +1165 198 l +1164 199 l +f +*U +0.000 0.769 0.616 0.212 k +*u +1165 199 m +1166 195 l +1169 197 1171.302 197.882 1175 198 c +1171.837 199.327 1168.415 199.000 1165 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1175 199 m +1184.696 194.931 1197.633 199.468 1208 197 c +1205.565 199.786 1201.516 199.000 1198 199 c +1175 199 l +f +*U +0.000 0.310 0.263 0.180 k +*u +1266 199 m +1266 196 l +1266.696 197.554 1266.696 197.446 1266 199 c +f +*U +0.000 0.639 0.725 0.275 k +*u +1267 199 m +1267 192 l +1268 194.534 1268 196.466 1267 199 c +f +*U +0.000 0.682 0.553 0.318 k +*u +1268 199 m +1271.697 197.449 1276 198 1280 198 c +1276.303 199.551 1271.983 199 1268 199 c +f +*U +0.000 0.639 0.541 0.149 k +*u +1280 199 m +1279 197 l +1281 197 l +1281 198.853 1281.300 198.350 1280 199 c +f +*U +0.000 0.471 0.353 0.035 k +*u +1288 199 m +1289 198 l +1288 199 l +f +*U +0.000 0.514 0.380 0.239 k +*u +1289 199 m +1290 198 l +1289 199 l +f +*U +0.000 0.651 0.533 0.349 k +*u +1290 199 m +1297.409 195.891 1308.975 198 1317 198 c +1309.591 201 1298 199 1290 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1317 199 m +1321.469 197 1327.192 198 1332 198 c +1363 198 l +1358.531 199.875 1352.809 199 1348 199 c +1317 199 l +f +*U +0.000 0.812 0.592 0.188 k +*u +1361 196 m +1362.872 196 1363.612 196 1365 195 c +1366.459 196.312 1367 197.231 1368 199 c +1364.830 198.827 1362.864 198.644 1361 196 c +f +*U +0.000 0.047 0.024 0.686 k +*u +1368 199 m +1369 198 l +1368 199 l +f +*U +0.000 0.424 0.361 0.576 k +*u +2017 199 m +2018 198 l +2017 199 l +f +*U +0.000 0.251 0.184 0.220 k +*u +2018 199 m +2019 198 l +2018 199 l +f +*U +0.000 0.263 0.243 0.125 k +*u +31 198 m +32 197 l +31 198 l +f +*U +0.000 0.353 0.216 0.047 k +*u +1080 198 m +1081 197 l +1080 198 l +f +*U +0.000 0.878 0.631 0.118 k +*u +1082 198 m +1083.523 194.843 1086 189 1089.415 187.600 c +1093.757 185.574 1101.283 187 1106 187 c +1144 187 l +1144 192 l +1138.978 192.912 1135.892 197 1130.981 197.811 c +1115 200 1097.886 197.672 1082 198 c +f +*U +0.000 0.776 0.796 0.125 k +*u +1088 198 m +1090.613 196.902 1093 197 1096 197 c +1093.387 198 1090.836 197.993 1088 198 c +f +*U +0.000 0.494 0.361 0.000 k +*u +1135 198 m +1136 197 l +1135 198 l +f +*U +0.000 0.231 0.192 0.149 k +*u +1164 198 m +1165 197 l +1164 198 l +f +*U +0.000 0.875 0.627 0.125 k +*u +1167 189 m +1169.811 188.837 1172.227 187.623 1175 187.212 c +1181.456 186.259 1188.485 187 1195 187 c +1200.940 187 1207.275 186.308 1213 188 c +1211.205 191 1209.833 195 1206.695 196.972 c +1203.965 198.594 1200 198.000 1197 198 c +1178 198 l +1175.348 198.000 1170.968 198.771 1168.742 196.972 c +1166.565 195.212 1167 191.470 1167 189 c +f +*U +0.000 0.255 0.227 0.357 k +*u +1208 198 m +1209 197 l +1208 198 l +f +*U +0.000 0.867 0.624 0.133 k +*u +1268 198 m +1267.822 193.920 1267.630 190.287 1264 188 c +1267.958 186.339 1272.737 187 1277 187 c +1277.794 188.871 1279.375 191 1279.568 193 c +1280 199 1271.684 198.000 1268 198 c +f +*U +0.000 0.792 0.678 0.208 k +*u +1278 198 m +1278.901 196 1279 196 1281 195 c +1280 196.923 1279.924 196.999 1278 198 c +f +*U +0.000 0.306 0.325 0.196 k +*u +1287 198 m +1288 197 l +1287 198 l +f +*U +0.000 0.624 0.600 0.337 k +*u +1288 198 m +1287.438 196.199 1287.176 194.878 1287 193 c +1290 198 l +1288 198 l +f +*U +0.000 0.882 0.631 0.118 k +*u +1288 193 m +1307 193 l +1306.582 190.311 1306.283 189.446 1304 188 c +1308.720 186 1314.920 187 1320 187 c +1330.816 187 1344.307 184.811 1354.830 187.299 c +1359.709 188.453 1363.982 192.189 1365 197 c +1361.308 196.869 1357.750 197.975 1353.999 197.999 c +1338.334 198 1322.665 198 1307 198 c +1300.721 198 1290.249 200.410 1288 193 c +f +*U +0.000 0.020 0.008 0.278 k +*u +1368 198 m +1369 197 l +1368 198 l +f +*U +0.000 0.533 0.439 0.467 k +*u +2018 198 m +2019 197 l +2018 198 l +f +*U +0.000 0.337 0.247 0.263 k +*u +2019 198 m +2020 197 l +2019 198 l +f +*U +0.000 0.361 0.251 0.243 k +*u +1081 197 m +1082 196 l +1081 197 l +f +*U +0.000 0.502 0.353 0.478 k +*u +1082.333 196.333 m +1082.278 196.278 1082.222 195.222 1082.667 195.667 c +1082.722 195.722 1082.778 196.778 1082.333 196.333 c +f +*U +0.000 0.580 0.475 0.420 k +*u +1208 197 m +1208.684 195.420 1208.805 195.223 1210 194 c +1209.316 195.580 1209.195 195.777 1208 197 c +f +*U +0.000 0.435 0.286 0.427 k +*u +1366.333 196.333 m +1366.278 196.278 1366.222 195.222 1366.667 195.667 c +1366.722 195.722 1366.778 196.778 1366.333 196.333 c +f +*U +0.000 0.404 0.345 0.235 k +*u +1367 197 m +1368 196 l +1367 197 l +f +*U +0.000 0.514 0.388 0.486 k +*u +2020 197 m +2021 196 l +2020 197 l +f +*U +0.000 0.306 0.231 0.231 k +*u +2021 197 m +2022 196 l +2021 197 l +f +*U +0.000 0.224 0.169 0.098 k +*u +2 196 m +3 195 l +2 196 l +f +*U +0.000 0.580 0.459 0.420 k +*u +3 196 m +3 193 l +3.696 194.554 3.696 194.446 3 196 c +f +*U +0.000 0.251 0.157 0.216 k +*u +32 196 m +33 195 l +32 196 l +f +*U +0.000 0.310 0.220 0.588 k +*u +1136 196 m +1137 195 l +1136 196 l +f +*U +0.000 0.337 0.255 0.047 k +*u +1165 196 m +1166 195 l +1165 196 l +f +*U +0.000 0.412 0.329 0.204 k +*u +1266.333 195.333 m +1266.278 195.278 1266.222 194.222 1266.667 194.667 c +1266.722 194.722 1266.778 195.778 1266.333 195.333 c +f +*U +0.000 0.937 0.671 0.063 k +*u +1274 196 m +1275 193.867 1275.882 193.217 1278 192 c +1277 196 l +1274 196 l +f +*U +0.000 0.165 0.137 0.145 k +*u +1286.333 195.333 m +1286.278 195.278 1286.222 194.222 1286.667 194.667 c +1286.722 194.722 1286.777 195.778 1286.333 195.333 c +f +*U +0.000 0.404 0.310 0.514 k +*u +2021.667 195.667 m +2021.222 195.222 2022.278 195.278 2022.333 195.333 c +2022.778 195.778 2021.722 195.722 2021.667 195.667 c +f +*U +0.000 0.671 0.486 0.329 k +*u +30 195 m +31.904 193 33.534 192 36 191 c +34 193.323 32.892 194.194 30 195 c +f +*U +0.000 0.263 0.173 0.094 k +*u +33 195 m +34 194 l +33 195 l +f +*U +0.000 0.220 0.157 0.118 k +*u +1082 195 m +1083 194 l +1082 195 l +f +*U +0.000 0.553 0.427 0.447 k +*u +1083 195 m +1084 194 l +1083 195 l +f +*U +0.000 0.612 0.443 0.388 k +*u +1136.667 194.667 m +1136.222 194.222 1137.278 194.278 1137.333 194.333 c +1137.778 194.778 1136.722 194.722 1136.667 194.667 c +f +*U +0.000 0.400 0.286 0.247 k +*u +1138 195 m +1139 194 l +1138 195 l +f +*U +0.000 0.659 0.478 0.325 k +*u +1166 195 m +1165 190 l +1166.879 191.623 1166.916 192.700 1166 195 c +f +*U +0.000 0.314 0.243 0.306 k +*u +1210 195 m +1211 194 l +1210 195 l +f +*U +0.000 0.522 0.541 0.459 k +*u +1280 195 m +1280 192 l +1280.696 193.554 1280.696 193.446 1280 195 c +f +*U +0.000 0.463 0.325 0.537 k +*u +1365 195 m +1366 194 l +1365 195 l +f +*U +0.000 0.455 0.435 0.545 k +*u +2023 195 m +2024 194 l +2023 195 l +f +*U +0.000 0.212 0.137 0.267 k +*u +2024 195 m +2025 194 l +2024 195 l +f +*U +0.000 0.333 0.216 0.000 k +*u +1083 194 m +1084 193 l +1083 194 l +f +*U +0.000 0.447 0.314 0.451 k +*u +1084.333 193.333 m +1084.278 193.278 1084.222 192.222 1084.667 192.667 c +1084.722 192.722 1084.778 193.778 1084.333 193.333 c +f +*U +0.000 0.471 0.380 0.529 k +*u +1138.667 193.667 m +1138.222 193.222 1139.278 193.278 1139.333 193.333 c +1139.778 193.778 1138.722 193.722 1138.667 193.667 c +f +*U +0.000 0.361 0.259 0.200 k +*u +1140 194 m +1141 193 l +1140 194 l +f +*U +0.000 0.498 0.388 0.502 k +*u +1210 194 m +1211 193 l +1210 194 l +f +*U +0.000 0.616 0.420 0.353 k +*u +1266 194 m +1265.697 191.706 1265.421 190.788 1264 189 c +1267.458 187.697 1267 191.778 1266 194 c +f +*U +0.000 0.412 0.412 0.588 k +*u +1364 194 m +1365 193 l +1364 194 l +f +*U +0.000 0.243 0.176 0.071 k +*u +1365 194 m +1366 193 l +1365 194 l +f +*U +0.000 0.522 0.345 0.333 k +*u +2024.667 193.667 m +2024.222 193.222 2025.278 193.278 2025.333 193.333 c +2025.778 193.778 2024.722 193.722 2024.667 193.667 c +f +*U +0.000 0.349 0.231 0.078 k +*u +2026 194 m +2027 193 l +2026 194 l +f +*U +0.000 0.486 0.345 0.106 k +*u +3 193 m +4 192 l +3 193 l +f +*U +0.000 0.533 0.361 0.392 k +*u +1140 193 m +1141.248 192.315 1141.549 192.251 1143 192 c +1141.752 192.685 1141.452 192.749 1140 193 c +f +*U +0.000 0.282 0.196 0.165 k +*u +1143 193 m +1144 192 l +1143 193 l +f +*U +0.000 0.129 0.102 0.196 k +*u +1211 193 m +1212 192 l +1211 193 l +f +*U +0.000 0.208 0.161 0.227 k +*u +1287 193 m +1288 192 l +1287 193 l +f +*U +0.000 0.714 0.714 0.286 k +*u +1288 193 m +1290.332 192 1292.457 192 1295 192 c +1292.668 192.985 1290.543 192.981 1288 193 c +f +*U +0.000 0.694 0.537 0.306 k +*u +1295 193 m +1296.506 192.317 1297.315 192.174 1299 192 c +1297.494 192.683 1296.685 192.826 1295 193 c +f +*U +0.000 0.537 0.392 0.463 k +*u +1299 193 m +1300.769 192.221 1302 192 1304 192 c +1302.231 192.779 1300.964 192.912 1299 193 c +f +*U +0.000 0.769 0.561 0.231 k +*u +1304 193 m +1304.457 191 1304.581 190.792 1304 189 c +1306.905 187.905 1306.880 190.550 1307 193 c +1304 193 l +f +*U +0.000 0.306 0.345 0.271 k +*u +1364 193 m +1365 192 l +1364 193 l +f +*U +0.000 0.475 0.325 0.525 k +*u +2026 193 m +2027 192 l +2026 193 l +f +*U +0.000 0.224 0.145 0.333 k +*u +2027 193 m +2028 192 l +2027 193 l +f +*U +0.000 0.490 0.337 0.384 k +*u +4.333 191.333 m +4.278 191.278 4.222 190.222 4.667 190.667 c +4.722 190.722 4.778 191.778 4.333 191.333 c +f +*U +0.000 0.290 0.216 0.149 k +*u +36 192 m +37 191 l +36 192 l +f +*U +0.020 0.000 0.020 0.000 k +*u +46 192 m +53 188.996 64.256 191 72 191 c +130 191 l +332 191 l +1032 191 l +1024.841 194 1013.744 192 1006 192 c +948 192 l +746 192 l +46 192 l +f +*U +0.008 0.012 0.000 0.000 k +*u +56 189 m +62.919 186 73.520 188 81 188 c +138 188 l +335 188 l +804 188 l +955 188 l +982.955 188 1012.512 185.346 1040 190 c +1034.725 193 1028 189 1022 189 c +969 189 l +775 189 l +56 189 l +f +*U +0.000 0.369 0.239 0.612 k +*u +1085 192 m +1086 191 l +1085 192 l +f +*U +0.000 0.580 0.396 0.420 k +*u +1086.333 191.333 m +1086.278 191.278 1086.222 190.222 1086.667 190.667 c +1086.722 190.722 1086.778 191.778 1086.333 191.333 c +f +*U +0.000 0.325 0.325 0.675 k +*u +1144.333 191.333 m +1144.278 191.278 1144.222 190.222 1144.667 190.667 c +1144.722 190.722 1144.778 191.778 1144.333 191.333 c +f +*U +0.000 0.365 0.267 0.090 k +*u +1165 192 m +1166 191 l +1165 192 l +f +*U +0.000 0.369 0.337 0.224 k +*u +1211 192 m +1212 191 l +1211 192 l +f +*U +0.000 0.443 0.302 0.239 k +*u +1304 192 m +1305 191 l +1304 192 l +f +*U +0.000 0.384 0.259 0.518 k +*u +1361 190 m +1362.580 190.684 1362.777 190.805 1364 192 c +1362.420 191.316 1362.223 191.195 1361 190 c +f +*U +0.020 0.000 0.020 0.000 k +*u +1432 192 m +1436.720 190 1442.920 191 1448 191 c +1479 191 l +1588 191 l +1968 191 l +1963.280 192.981 1957 192 1952 192 c +1921 192 l +1812 192 l +1432 192 l +f +*U +0.000 0.349 0.255 0.031 k +*u +2029 192 m +2030 191 l +2029 192 l +f +*U +0.000 0.365 0.263 0.286 k +*u +37 191 m +38 190 l +37 191 l +f +*U +0.000 0.020 0.012 0.000 k +*u +48 191 m +55 187.996 66.256 190 74 190 c +132 190 l +333 190 l +1032 190 l +1024.841 193 1013.744 191 1006 191 c +948 191 l +747 191 l +48 191 l +f +*U +0.000 0.251 0.169 0.157 k +*u +1085 191 m +1086 190 l +1085 191 l +f +*U +0.000 0.153 0.118 0.114 k +*u +1145 191 m +1146 190 l +1145 191 l +f +*U +0.000 0.565 0.459 0.435 k +*u +1211.333 190.333 m +1211.278 190.278 1211.222 189.222 1211.667 189.667 c +1211.722 189.722 1211.778 190.778 1211.333 190.333 c +f +*U +0.000 0.388 0.290 0.039 k +*u +1278 191 m +1279 190 l +1278 191 l +f +*U +0.000 0.318 0.235 0.129 k +*u +1305 191 m +1306 190 l +1305 191 l +f +*U +0.000 0.020 0.012 0.000 k +*u +1432 191 m +1436.720 189 1442.920 190 1448 190 c +1479 190 l +1588 190 l +1968 190 l +1963.280 191.981 1957 191 1952 191 c +1921 191 l +1812 191 l +1432 191 l +f +*U +0.000 0.506 0.369 0.490 k +*u +2028.667 190.667 m +2028.222 190.223 2029.277 190.277 2029.333 190.333 c +2029.778 190.778 2028.722 190.722 2028.667 190.667 c +f +*U +0.000 0.322 0.235 0.239 k +*u +2030 191 m +2031 190 l +2030 191 l +f +*U +0.000 0.282 0.200 0.016 k +*u +4 190 m +5 189 l +4 190 l +f +*U +0.000 0.569 0.388 0.431 k +*u +5.333 189.333 m +5.278 189.278 5.222 188.222 5.667 188.667 c +5.722 188.722 5.778 189.778 5.333 189.333 c +f +*U +0.000 0.780 0.537 0.220 k +*u +37 190 m +37.980 188.217 37.908 188.406 40 188 c +38.777 189.195 38.580 189.316 37 190 c +f +*U +0.000 0.322 0.235 0.004 k +*u +39 190 m +40 189 l +39 190 l +f +*U +0.004 0.000 0.000 0.000 k +*u +44 190 m +48.869 186.970 58.251 189 64 189 c +116 189 l +310 189 l +1032 189 l +1024.841 192 1013.744 190 1006 190 c +948 190 l +745 190 l +44 190 l +f +*U +0.000 0.408 0.275 0.173 k +*u +1086 190 m +1087 189 l +1086 190 l +f +*U +0.000 0.329 0.235 0.341 k +*u +1144.333 189.333 m +1144.278 189.278 1144.222 188.222 1144.667 188.667 c +1144.722 188.722 1144.778 189.778 1144.333 189.333 c +f +*U +0.000 0.467 0.333 0.114 k +*u +1165.667 189.667 m +1165.222 189.222 1166.278 189.278 1166.333 189.333 c +1166.778 189.778 1165.722 189.722 1165.667 189.667 c +f +*U +0.000 0.384 0.384 0.616 k +*u +1168 190 m +1169 189 l +1168 190 l +f +*U +0.000 0.278 0.204 0.145 k +*u +1212 190 m +1213 189 l +1212 190 l +f +*U +0.000 0.353 0.255 0.184 k +*u +1265 190 m +1266 189 l +1265 190 l +f +*U +0.000 0.561 0.396 0.416 k +*u +1277 190 m +1275.554 187.717 1274.689 187.418 1272 187 c +1274 186 1275.747 186 1278 186 c +1277.826 187.685 1277.683 188.494 1277 190 c +f +*U +0.000 0.267 0.208 0.082 k +*u +1304 190 m +1305 189 l +1304 190 l +f +*U +0.000 0.443 0.325 0.306 k +*u +1305 190 m +1306 189 l +1305 190 l +f +*U +0.000 0.525 0.412 0.471 k +*u +1358.667 189.667 m +1358.222 189.222 1359.278 189.278 1359.333 189.333 c +1359.778 189.778 1358.722 189.722 1358.667 189.667 c +f +*U +0.000 0.318 0.204 0.294 k +*u +1360 190 m +1361 189 l +1360 190 l +f +*U +0.000 0.263 0.176 0.114 k +*u +1361 190 m +1362 189 l +1361 190 l +f +*U +0.000 0.600 0.455 0.400 k +*u +2030.667 189.667 m +2030.222 189.222 2031.278 189.278 2031.333 189.333 c +2031.778 189.778 2030.722 189.722 2030.667 189.667 c +f +*U +0.000 0.137 0.090 0.180 k +*u +2032 190 m +2033 189 l +2032 190 l +f +*U +0.000 0.439 0.298 0.553 k +*u +40 189 m +41 188 l +40 189 l +f +*U +0.000 0.400 0.275 0.314 k +*u +41 189 m +42 188 l +41 189 l +f +*U +0.000 0.290 0.204 0.027 k +*u +42 189 m +43 188 l +42 189 l +f +*U +0.000 0.376 0.243 0.408 k +*u +1087 189 m +1088 188 l +1087 189 l +f +*U +0.000 0.173 0.200 0.118 k +*u +1169 189 m +1170 188 l +1169 189 l +f +*U +0.000 0.404 0.345 0.243 k +*u +1170 189 m +1171 188 l +1170 189 l +f +*U +0.000 0.224 0.149 0.298 k +*u +1263 189 m +1264 188 l +1263 189 l +f +*U +0.000 0.141 0.145 0.392 k +*u +1303 189 m +1304 188 l +1303 189 l +f +*U +0.000 0.596 0.486 0.404 k +*u +1357.333 188.333 m +1357.278 188.278 1357.222 187.222 1357.667 187.667 c +1357.722 187.722 1357.778 188.778 1357.333 188.333 c +f +*U +0.000 0.482 0.373 0.322 k +*u +1358 189 m +1359 188 l +1358 189 l +f +*U +0.008 0.012 0.000 0.000 k +*u +1430 189 m +1434.720 187 1440.920 188 1446 188 c +1477 188 l +1587 188 l +1968 188 l +1963.280 189.981 1957 189 1952 189 c +1921 189 l +1811 189 l +1430 189 l +f +*U +0.000 0.561 0.388 0.439 k +*u +2032 189 m +2033 188 l +2032 189 l +f +*U +0.000 0.420 0.286 0.235 k +*u +2033 189 m +2034 188 l +2033 189 l +f +*U +0.000 0.365 0.239 0.035 k +*u +5 188 m +6 187 l +5 188 l +f +*U +0.000 0.604 0.467 0.396 k +*u +41 188 m +42.248 187.315 42.549 187.251 44 187 c +42.752 187.685 42.452 187.749 41 188 c +f +*U +0.000 0.392 0.278 0.353 k +*u +44 188 m +45 187 l +44 188 l +f +*U +0.000 0.216 0.161 0.110 k +*u +45 188 m +46.248 187.315 46.549 187.251 48 187 c +46.752 187.685 46.452 187.749 45 188 c +f +*U +0.000 0.192 0.149 0.671 k +*u +1144.333 187.333 m +1144.278 187.278 1144.222 186.222 1144.667 186.667 c +1144.722 186.722 1144.778 187.778 1144.333 187.333 c +f +*U +0.000 0.341 0.278 0.384 k +*u +1172 188 m +1173 187 l +1172 188 l +f +*U +0.000 0.373 0.271 0.557 k +*u +1212 188 m +1212 186 l +1214 186 l +1213.455 187.635 1213.635 187.455 1212 188 c +f +*U +0.000 0.373 0.263 0.318 k +*u +1213 188 m +1214 187 l +1213 188 l +f +*U +0.000 0.490 0.349 0.467 k +*u +1261 188 m +1262.926 185.792 1265 186 1268 186 c +1265.717 187.222 1263.572 187.652 1261 188 c +f +*U +0.000 0.365 0.278 0.047 k +*u +1301 188 m +1302 187 l +1301 188 l +f +*U +0.000 0.498 0.365 0.502 k +*u +1302 188 m +1301 186 l +1303 186 l +1303 187.853 1303.300 187.350 1302 188 c +f +*U +0.000 0.663 0.475 0.275 k +*u +1303.333 187.333 m +1303.278 187.278 1303.222 186.222 1303.667 186.667 c +1303.722 186.722 1303.778 187.778 1303.333 187.333 c +f +*U +0.000 0.341 0.278 0.204 k +*u +1358 188 m +1359 187 l +1358 188 l +f +*U +0.000 0.753 0.514 0.227 k +*u +1973 188 m +1974 184 l +1975 185.458 1975.436 186.248 1976 188 c +1973 188 l +f +*U +0.000 0.573 0.396 0.376 k +*u +2033.667 187.667 m +2033.222 187.222 2034.278 187.278 2034.333 187.333 c +2034.778 187.778 2033.722 187.722 2033.667 187.667 c +f +*U +0.000 0.271 0.200 0.200 k +*u +2035 188 m +2036 187 l +2035 188 l +f +*U +0.000 0.455 0.298 0.247 k +*u +6 187 m +7 186 l +6 187 l +f +*U +0.000 0.506 0.337 0.494 k +*u +7.333 186.333 m +7.278 186.278 7.222 185.222 7.667 185.667 c +7.722 185.722 7.778 186.778 7.333 186.333 c +f +*U +0.000 0.914 0.635 0.086 k +*u +40 186 m +44.917 182.699 54 185 60 185 c +111 185 l +303 185 l +795 185 l +953 185 l +1004 185 l +1014.283 185 1024.836 185.752 1035 184 c +1031.803 187.658 1023.577 186 1019 186 c +975 186 l +796 186 l +279 186 l +116 186 l +64 186 l +56.424 186 47.290 187.580 40 186 c +f +*U +0.000 0.655 0.494 0.345 k +*u +44 187 m +45.506 186.317 46.315 186.174 48 186 c +46.494 186.683 45.685 186.826 44 187 c +f +*U +0.000 0.525 0.424 0.475 k +*u +48 187 m +55 183.996 66.256 186 74 186 c +132 186 l +334 186 l +1035 186 l +1027.841 189 1016.744 187 1009 187 c +951 187 l +749 187 l +48 187 l +f +*U +0.000 0.325 0.239 0.475 k +*u +1035 187 m +1036 186 l +1035 187 l +f +*U +0.000 0.247 0.184 0.118 k +*u +1036 187 m +1037 186 l +1036 187 l +f +*U +0.000 0.459 0.349 0.122 k +*u +1088 187 m +1089 186 l +1088 187 l +f +*U +0.000 0.443 0.329 0.494 k +*u +1089 187 m +1094.216 184.811 1101.381 186 1107 186 c +1144 186 l +1138.783 188.189 1131.619 187 1126 187 c +1089 187 l +f +*U +0.024 0.000 0.027 0.227 k +*u +1145 187 m +1146 186 l +1145 187 l +f +*U +0.000 0.259 0.224 0.278 k +*u +1173 187 m +1174 186 l +1173 187 l +f +*U +0.000 0.443 0.329 0.494 k +*u +1174 187 m +1177.699 185.448 1182 186 1186 186 c +1209 186 l +1205.301 187.552 1200.983 187 1197 187 c +1174 187 l +f +*U +0.000 0.478 0.314 0.373 k +*u +1209 187 m +1210.248 186.315 1210.549 186.251 1212 186 c +1210.752 186.685 1210.452 186.749 1209 187 c +f +*U +0.000 0.380 0.275 0.306 k +*u +1268 187 m +1269.506 186.317 1270.315 186.174 1272 186 c +1270.494 186.683 1269.685 186.826 1268 187 c +f +*U +0.000 0.443 0.329 0.494 k +*u +1304 187 m +1308.969 184.915 1315.650 186 1321 186 c +1357 186 l +1352 188 1345.350 187 1340 187 c +1304 187 l +f +*U +0.000 0.271 0.212 0.275 k +*u +1357 187 m +1358 186 l +1357 187 l +f +*U +0.000 0.216 0.192 0.039 k +*u +1425 187 m +1426 186 l +1425 187 l +f +*U +0.000 0.306 0.243 0.271 k +*u +1426 187 m +1427 186 l +1426 187 l +f +*U +0.000 0.416 0.345 0.584 k +*u +1427 187 m +1428.506 186.317 1429.314 186.174 1431 186 c +1429.494 186.683 1428.685 186.826 1427 187 c +f +*U +0.000 0.525 0.424 0.475 k +*u +1431 187 m +1435.720 185 1441.920 186 1447 186 c +1478 186 l +1589 186 l +1973 186 l +1968.280 187.980 1962 187 1957 187 c +1926 187 l +1815 187 l +1431 187 l +f +*U +0.000 0.384 0.278 0.412 k +*u +2035.667 186.667 m +2035.222 186.222 2036.278 186.278 2036.333 186.333 c +2036.778 186.778 2035.722 186.722 2035.667 186.667 c +f +*U +0.000 0.694 0.514 0.306 k +*u +1035 186 m +1036.693 184.938 1038 184.480 1040 184 c +1038.211 185.422 1037.294 185.697 1035 186 c +f +*U +0.000 0.314 0.200 0.145 k +*u +1423 186 m +1424 185 l +1423 186 l +f +*U +0.000 0.643 0.510 0.337 k +*u +1424.667 185.667 m +1424.222 185.222 1425.278 185.278 1425.333 185.333 c +1425.778 185.778 1424.722 185.722 1424.667 185.667 c +f +*U +0.000 0.914 0.635 0.086 k +*u +1429 184 m +1436.724 185.839 1445 185 1453 185 c +1493 185 l +1623 185 l +1853 185 l +1927 185 l +1941.930 185 1957.180 185.947 1972 184 c +1969.897 186.407 1967 185.994 1964 186 c +1945 186 l +1866 186 l +1547 186 l +1459 186 l +1438 186 l +1434.683 185.999 1431.276 186.604 1429 184 c +f +*U +0.000 0.459 0.392 0.541 k +*u +2037 186 m +2038 185 l +2037 186 l +f +*U +0.000 0.349 0.263 0.082 k +*u +2038 186 m +2039 185 l +2038 186 l +f +*U +0.000 0.478 0.314 0.251 k +*u +7 185 m +8 184 l +7 185 l +f +*U +0.000 0.878 0.616 0.122 k +*u +48 185 m +55 181.996 66.256 184 74 184 c +132 184 l +333 184 l +1032 184 l +1024.841 187 1013.744 185 1006 185 c +948 185 l +747 185 l +48 185 l +f +*U +0.000 0.094 0.047 0.463 k +*u +1040 185 m +1041 184 l +1040 185 l +f +*U +0.000 0.482 0.306 0.510 k +*u +1422.667 184.667 m +1422.222 184.222 1423.278 184.278 1423.333 184.333 c +1423.778 184.778 1422.722 184.722 1422.667 184.667 c +f +*U +0.000 0.878 0.616 0.122 k +*u +1431 185 m +1435.720 183 1441.920 184 1447 184 c +1478 184 l +1587 184 l +1968 184 l +1963.280 185.981 1957 185 1952 185 c +1921 185 l +1812 185 l +1431 185 l +f +*U +0.000 0.545 0.388 0.431 k +*u +2038.667 184.667 m +2038.222 184.223 2039.277 184.277 2039.333 184.333 c +2039.778 184.778 2038.722 184.722 2038.667 184.667 c +f +*U +0.000 0.686 0.435 0.302 k +*u +8 184 m +9 181.783 10 180.606 12 179 c +11 184 l +8 184 l +f +*U +0.000 0.800 0.686 0.161 k +*u +1040 184 m +1040.684 181.791 1041 181.297 1043 180 c +1042 181.769 1041.459 182.688 1040 184 c +f +*U +0.000 0.561 0.482 0.388 k +*u +1041 184 m +1041 182 l +1043 182 l +1042.455 183.635 1042.635 183.455 1041 184 c +f +*U +0.000 0.365 0.333 0.012 k +*u +1420 184 m +1421 183 l +1420 184 l +f +*U +0.000 0.463 0.463 0.537 k +*u +1421 184 m +1422 183 l +1421 184 l +f +*U +0.000 0.502 0.498 0.475 k +*u +2040 184 m +2041 183 l +2040 184 l +f +*U +0.000 0.365 0.380 0.239 k +*u +2041 184 m +2042 183 l +2041 184 l +f +*U +0.000 0.349 0.212 0.086 k +*u +8 183 m +9 182 l +8 183 l +f +*U +0.000 0.259 0.247 0.188 k +*u +1419 183 m +1420 182 l +1419 183 l +f +*U +0.000 0.435 0.412 0.565 k +*u +1420 183 m +1421 182 l +1420 183 l +f +*U +0.000 0.439 0.365 0.459 k +*u +2041.667 182.667 m +2041.222 182.222 2042.278 182.278 2042.333 182.333 c +2042.778 182.778 2041.722 182.722 2041.667 182.667 c +f +*U +0.000 0.180 0.157 0.169 k +*u +2043 183 m +2044 182 l +2043 183 l +f +*U +0.000 0.651 0.537 0.349 k +*u +1043.333 181.333 m +1043.278 181.278 1043.222 180.222 1043.667 180.667 c +1043.722 180.722 1043.778 181.778 1043.333 181.333 c +f +*U +0.000 0.282 0.220 0.098 k +*u +1418 182 m +1419 181 l +1418 182 l +f +*U +0.000 0.686 0.529 0.314 k +*u +1419 182 m +1417.738 179.990 1416.810 178.222 1416 176 c +1418.583 177.570 1419.675 179.282 1421 182 c +1419 182 l +f +*U +0.000 0.537 0.420 0.416 k +*u +2043 182 m +2044 181 l +2043 182 l +f +*U +0.000 0.259 0.216 0.251 k +*u +2044 182 m +2045 181 l +2044 182 l +f +*U +0.000 0.235 0.212 0.176 k +*u +1044 181 m +1045 180 l +1044 181 l +f +*U +0.000 0.212 0.137 0.169 k +*u +2046 181 m +2047 180 l +2046 181 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1044 180 m +1045 179 l +1044 180 l +f +*U +0.000 0.235 0.173 0.129 k +*u +1417 180 m +1418 179 l +1417 180 l +f +*U +0.000 0.471 0.388 0.529 k +*u +2046 180 m +2047 179 l +2046 180 l +f +*U +0.000 0.376 0.231 0.318 k +*u +2047 180 m +2048 179 l +2047 180 l +f +*U +0.000 0.635 0.498 0.365 k +*u +1045.333 178.333 m +1045.278 178.278 1045.222 177.222 1045.667 177.667 c +1045.722 177.722 1045.778 178.778 1045.333 178.333 c +f +*U +0.000 0.988 0.671 0.012 k +*u +1419 179 m +1418 177.521 1418 177.797 1418 176 c +1419.290 177.443 1419.401 177.233 1419 179 c +f +*U +0.000 0.376 0.290 0.600 k +*u +2048 179 m +2049 178 l +2048 179 l +f +*U +0.000 0.322 0.259 0.075 k +*u +2049 179 m +2050 178 l +2049 179 l +f +*U +0.000 0.106 0.059 0.118 k +*u +12 178 m +13 177 l +12 178 l +f +*U +0.000 0.227 0.173 0.341 k +*u +1046 178 m +1047 177 l +1046 178 l +f +*U +0.000 0.627 0.502 0.373 k +*u +2049 178 m +2050 177 l +2049 178 l +f +*U +0.000 0.455 0.341 0.290 k +*u +2050 178 m +2051 177 l +2050 178 l +f +*U +0.000 0.290 0.188 0.078 k +*u +13 177 m +14 176 l +13 177 l +f +*U +0.000 0.447 0.329 0.553 k +*u +2050.667 176.667 m +2050.223 176.223 2051.278 176.278 2051.333 176.333 c +2051.778 176.778 2050.722 176.722 2050.667 176.667 c +f +*U +0.000 0.212 0.157 0.251 k +*u +2052 177 m +2053 176 l +2052 177 l +f +*U +0.000 0.247 0.157 0.145 k +*u +14 176 m +15 175 l +14 176 l +f +*U +0.000 0.349 0.224 0.510 k +*u +15 176 m +16 175 l +15 176 l +f +*U +0.000 0.078 0.051 0.169 k +*u +1098.333 175.333 m +1098.278 175.278 1098.222 174.222 1098.667 174.667 c +1098.722 174.722 1098.778 175.778 1098.333 175.333 c +f +*U +0.000 0.384 0.412 0.133 k +*u +1099 176 m +1103.720 174 1109.920 175 1115 175 c +1149 175 l +1144.280 176.980 1138 176 1133 176 c +1099 176 l +f +*U +0.000 0.361 0.333 0.306 k +*u +1149 176 m +1150 175 l +1149 176 l +f +*U +0.000 0.102 0.133 0.204 k +*u +1150 176 m +1151 175 l +1150 176 l +f +*U +0.000 0.384 0.412 0.133 k +*u +1185 176 m +1189.215 174.231 1194.465 175 1199 175 c +1227 175 l +1222.785 176.769 1217.536 176 1213 176 c +1185 176 l +f +*U +0.000 0.235 0.282 0.039 k +*u +1227 176 m +1228 175 l +1227 176 l +f +*U +0.000 0.318 0.251 0.141 k +*u +1256 176 m +1257.506 175.317 1258.315 175.174 1260 175 c +1258.494 175.683 1257.685 175.826 1256 176 c +f +*U +0.000 0.392 0.373 0.129 k +*u +1260 176 m +1264.217 174.231 1269.459 175 1274 175 c +1269.783 176.769 1264.541 176 1260 176 c +f +*U +0.000 0.008 0.004 0.243 k +*u +1296 176 m +1297 175 l +1296 176 l +f +*U +0.000 0.055 0.098 0.490 k +*u +1297 176 m +1298 174 l +1299.635 174.545 1299.455 174.365 1300 176 c +1297 176 l +f +*U +0.000 0.231 0.224 0.098 k +*u +1300.667 175.667 m +1300.222 175.222 1301.278 175.278 1301.333 175.333 c +1301.778 175.778 1300.722 175.722 1300.667 175.667 c +f +*U +0.000 0.384 0.412 0.133 k +*u +1302 176 m +1306.469 174 1312.191 175 1317 175 c +1348 175 l +1343.531 176.875 1337.809 176 1333 176 c +1302 176 l +f +*U +0.000 0.039 0.165 0.431 k +*u +1348.667 175.667 m +1348.222 175.222 1349.278 175.278 1349.333 175.333 c +1349.778 175.778 1348.722 175.722 1348.667 175.667 c +f +*U +0.000 0.161 0.141 0.176 k +*u +1350 176 m +1351 175 l +1350 176 l +f +*U +0.000 0.694 0.545 0.306 k +*u +1415 176 m +1413.545 173.344 1412 170.832 1411 168 c +1413.665 170.231 1415.825 172.419 1415 176 c +f +*U +0.000 0.690 0.494 0.310 k +*u +2053 176 m +2053 174 l +2055 174 l +2054.455 175.635 2054.635 175.455 2053 176 c +f +*U +0.000 0.286 0.176 0.047 k +*u +2054 176 m +2055 175 l +2054 176 l +f +*U +0.000 0.263 0.173 0.063 k +*u +15 175 m +16 174 l +15 175 l +f +*U +0.000 0.271 0.176 0.400 k +*u +1048 175 m +1049 174 l +1048 175 l +f +*U +0.000 0.510 0.384 0.490 k +*u +1099 175 m +1099.545 173.365 1099.365 173.545 1101 173 c +1101 175 l +1099 175 l +f +*U +0.000 0.910 0.663 0.082 k +*u +1101 175 m +1102 173 1103 172.260 1105 171 c +1105 175 l +1101 175 l +f +*U +0.000 0.867 0.753 0.075 k +*u +1105 175 m +1105 170 l +1107 170 l +1107 175 l +1105 175 l +f +*U +0.000 0.871 0.616 0.125 k +*u +1107 175 m +1106 169 l +1108 167 1109.547 165.421 1111 163 c +1124.682 166.257 1140.961 164 1155 164 c +1154 167.322 1153 169.275 1150 171 c +1149.461 175.291 1143.577 174 1140 174 c +1128.929 174 1118 174.657 1107 175 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1112 175 m +1115.699 173.448 1120 174 1124 174 c +1145 174 l +1141.301 175.552 1136.983 175 1133 175 c +1112 175 l +f +*U +0.000 0.678 0.525 0.286 k +*u +1145 175 m +1146.940 174 1148.898 173.561 1151 173 c +1149.266 175 1147.645 174.923 1145 175 c +f +*U +0.000 0.522 0.365 0.298 k +*u +1185.333 174.333 m +1185.278 174.278 1185.222 173.222 1185.667 173.667 c +1185.722 173.722 1185.778 174.778 1185.333 174.333 c +f +*U +0.000 0.690 0.541 0.306 k +*u +1186 173 m +1192 174 l +1189.471 175 1187.824 175 1186 173 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1192 175 m +1195.699 173.448 1200 174 1204 174 c +1225 174 l +1221.301 175.552 1216.983 175 1213 175 c +1192 175 l +f +*U +0.000 0.831 0.600 0.149 k +*u +1225 175 m +1221.309 172.204 1216.485 173 1212 173 c +1202.898 173 1194 172.648 1185 172 c +1181 165 l +1191.522 168.283 1203 167 1214 167 c +1272 167 l +1267 169 1260.362 168 1255 168 c +1258 168.900 1260.831 168.992 1264 169 c +1260.881 170.312 1257.782 169.891 1255 172 c +1252.280 170.967 1249.813 170.278 1248 168 c +1244.336 170.567 1239.395 170.445 1235 171 c +1235.980 169.217 1235.907 169.406 1238 169 c +1234.414 168.319 1230.664 168.259 1227 168 c +1228.479 168.986 1228.203 169 1230 169 c +1226 170.661 1221.260 170 1217 170 c +1192 170 l +1192 172 l +1216 172 l +1220.296 172 1224.302 171.260 1227 175 c +1225 175 l +f +*U +0.000 0.392 0.392 0.608 k +*u +1227 175 m +1228 174 l +1227 175 l +f +*U +0.000 0.655 0.518 0.322 k +*u +1228 175 m +1228.980 173.217 1228.907 173.406 1231 173 c +1229.860 174 1229.389 174.309 1228 175 c +f +*U +0.000 0.259 0.192 0.106 k +*u +1237 175 m +1238 174 l +1237 175 l +f +*U +0.000 0.757 0.588 0.243 k +*u +1238.333 174.333 m +1238.278 174.278 1238.222 173.222 1238.667 173.667 c +1238.722 173.722 1238.778 174.778 1238.333 174.333 c +f +*U +0.000 0.573 0.447 0.427 k +*u +1239 175 m +1241.836 173.693 1244.998 172.939 1248 172 c +1245.271 174.787 1242.827 174.956 1239 175 c +f +*U +0.000 0.251 0.188 0.157 k +*u +1246 175 m +1247 174 l +1246 175 l +f +*U +0.000 0.251 0.196 0.133 k +*u +1253 175 m +1254 174 l +1253 175 l +f +*U +0.000 0.486 0.380 0.365 k +*u +1254.667 174.667 m +1254.222 174.222 1255.278 174.278 1255.333 174.333 c +1255.778 174.778 1254.722 174.722 1254.667 174.667 c +f +*U +0.000 0.690 0.749 0.251 k +*u +1256 175 m +1258.613 173.902 1261 174 1264 174 c +1261.387 175 1258.835 174.993 1256 175 c +f +*U +0.000 0.749 0.847 0.145 k +*u +1264 175 m +1266.613 173.902 1269 174 1272 174 c +1269.387 175 1266.836 174.993 1264 175 c +f +*U +0.000 0.882 0.627 0.118 k +*u +1254 173 m +1256.529 169.493 1259.940 170 1264 170 c +1260.959 169 1258.169 169 1255 169 c +1259.974 166.913 1266.638 168 1272 168 c +1264.848 165.886 1256.427 167 1249 167 c +1206 167 l +1199.931 167 1186.617 169.579 1183 164 c +1250 164 l +1267 164 l +1269.301 164 1272.496 163.564 1274.471 165 c +1277.520 167.286 1276.363 172.889 1272.856 173.972 c +1267.975 175.480 1258.816 174.424 1254 173 c +f +*U +0.000 0.384 0.384 0.616 k +*u +1273 175 m +1274 174 l +1273 175 l +f +*U +0.000 0.263 0.224 0.322 k +*u +1274 175 m +1275 174 l +1274 175 l +f +*U +0.075 0.216 0.000 0.192 k +*u +1297 175 m +1298 174 l +1297 175 l +f +*U +0.000 0.631 0.639 0.361 k +*u +1299 175 m +1300.223 173.805 1300.420 173.684 1302 173 c +1300.777 174.195 1300.580 174.316 1299 175 c +f +*U +0.000 0.773 0.631 0.212 k +*u +1301.667 174.667 m +1301.222 174.222 1302.278 174.278 1302.333 174.333 c +1302.778 174.778 1301.722 174.722 1301.667 174.667 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1302 174 m +1305.985 173 1310.830 174.000 1315 174 c +1344 174 l +1340 175.661 1335.260 175 1331 175 c +1321.805 175 1310.842 176.614 1302 174 c +f +*U +0.000 0.918 0.659 0.082 k +*u +1312 174 m +1318.965 171 1329.475 173 1337 172.996 c +1340.593 172.961 1343.614 172 1346 175 c +1334.957 172.950 1323.203 174 1312 174 c +f +*U +0.000 0.788 0.616 0.212 k +*u +1346 175 m +1345 172.896 1344.954 172.248 1345 170 c +1346.840 171.717 1347.349 172.566 1348 175 c +1346 175 l +f +*U +0.000 0.580 0.522 0.306 k +*u +1348 175 m +1348 173 l +1349.635 173.545 1349.455 173.365 1350 175 c +1348 175 l +f +*U +0.000 0.408 0.325 0.224 k +*u +1414 175 m +1415 174 l +1414 175 l +f +*U +0.000 0.475 0.349 0.098 k +*u +2055 175 m +2056 174 l +2055 175 l +f +*U +0.000 0.204 0.145 0.102 k +*u +1049 174 m +1050 173 l +1049 174 l +f +*U +0.000 0.533 0.475 0.035 k +*u +1151 174 m +1152 173 l +1151 174 l +f +*U +0.000 0.918 0.659 0.082 k +*u +1186 171 m +1197.524 175.489 1212.781 173 1225 173 c +1217 176.305 1204.531 174 1196 174 c +1191.995 173.998 1188.334 174.600 1186 171 c +f +*U +0.000 0.894 0.643 0.106 k +*u +1226 174 m +1222.730 171.523 1219 172 1215 172 c +1192 172 l +1192 170 l +1230 170 l +1228.521 169 1228.797 169 1227 169 c +1230.382 167.640 1234.352 168 1238 168 c +1235 171 l +1239 170.240 1243.650 170.538 1247 168 c +1248 171 1246.257 173 1242.981 173.682 c +1237.459 174.621 1231.755 172.932 1226 174 c +f +*U +0.000 0.357 0.298 0.020 k +*u +1231 174 m +1232.769 173.221 1234 173 1236 173 c +1234.231 173.779 1232.964 173.912 1231 174 c +f +*U +0.000 0.608 0.490 0.392 k +*u +1236.667 173.667 m +1236.222 173.222 1237.278 173.278 1237.333 173.333 c +1237.778 173.778 1236.722 173.722 1236.667 173.667 c +f +*U +0.000 0.329 0.275 0.137 k +*u +1247 174 m +1248 173 l +1247 174 l +f +*U +0.000 0.388 0.314 0.125 k +*u +1252.333 173.333 m +1252.278 173.278 1252.222 172.222 1252.667 172.667 c +1252.722 172.722 1252.778 173.778 1252.333 173.333 c +f +*U +0.000 0.714 0.588 0.286 k +*u +1252 171 m +1253.923 171.902 1253.999 172 1255 174 c +1253 173 1253 172.924 1252 171 c +f +*U +0.000 0.318 0.294 0.216 k +*u +1275 174 m +1276 173 l +1275 174 l +f +*U +0.000 0.859 0.604 0.137 k +*u +1301 173 m +1302 170.237 1307.468 166.678 1304 165 c +1308 162.843 1312.478 163.944 1317 163.996 c +1327.786 164 1335.368 163.682 1345 169 c +1343 173.893 1338.660 173.000 1334 173 c +1323.230 173 1311.529 174.955 1301 173 c +f +*U +0.000 0.710 0.537 0.290 k +*u +2055 174 m +2053.964 172.813 2053.662 172.397 2053 171 c +2054.849 171.967 2055.722 172 2055 174 c +f +*U +0.016 0.008 0.000 0.741 k +*u +2056 174 m +2057 173 l +2056 174 l +f +*U +0.000 0.408 0.286 0.329 k +*u +18 173 m +19 172 l +18 173 l +f +*U +0.000 0.627 0.471 0.373 k +*u +19 173 m +20 171.543 20.543 171 22 170 c +21 172 21 172 19 173 c +f +*U +0.000 0.365 0.306 0.635 k +*u +1049 173 m +1050 172 l +1049 173 l +f +*U +0.000 0.267 0.196 0.082 k +*u +1100 173 m +1101 172 l +1100 173 l +f +*U +0.000 0.698 0.553 0.302 k +*u +1101 173 m +1103.732 169 1106.678 166 1111 164 c +1108.464 168 1105.345 171 1101 173 c +f +*U +0.000 0.651 0.471 0.349 k +*u +1150 172 m +1151.551 170 1152.855 168.218 1154 166 c +1154.785 168.916 1153.644 170.511 1152 173 c +1150 172 l +f +*U +0.000 0.208 0.188 0.302 k +*u +1182 173 m +1183 172 l +1182 173 l +f +*U +0.000 0.714 0.514 0.286 k +*u +1183 171 m +1184.580 171.684 1184.777 171.805 1186 173 c +1183.907 172.594 1183.980 172.783 1183 171 c +f +*U +0.000 0.357 0.337 0.392 k +*u +1276 173 m +1277 172 l +1276 173 l +f +*U +0.000 0.141 0.114 0.145 k +*u +1289 173 m +1290 172 l +1289 173 l +f +*U +0.000 0.384 0.310 0.106 k +*u +1300 173 m +1301 172 l +1300 173 l +f +*U +0.000 0.004 0.000 0.298 k +*u +2056 173 m +2057 172 l +2056 173 l +f +*U +0.000 0.094 0.071 0.184 k +*u +19 172 m +20 171 l +19 172 l +f +*U +0.000 0.761 0.522 0.239 k +*u +22 172 m +23.382 169.580 24.363 168.939 27 168 c +25.410 169.752 24 170.794 22 172 c +f +*U +0.000 0.655 0.525 0.345 k +*u +1050.333 171.333 m +1050.278 171.278 1050.222 170.222 1050.667 170.667 c +1050.722 170.722 1050.778 171.778 1050.333 171.333 c +f +*U +0.000 0.106 0.110 0.278 k +*u +1181 172 m +1182 171 l +1181 172 l +f +*U +0.000 0.333 0.333 0.667 k +*u +1182 172 m +1183 171 l +1182 172 l +f +*U +0.000 0.294 0.184 0.165 k +*u +1248 172 m +1249 171 l +1248 172 l +f +*U +0.000 0.271 0.243 0.188 k +*u +1251 172 m +1252 171 l +1251 172 l +f +*U +0.000 0.514 0.408 0.478 k +*u +1276 172 m +1276 169 l +1276.696 170.554 1276.696 170.446 1276 172 c +f +*U +0.000 0.322 0.271 0.424 k +*u +1287 172 m +1288 171 l +1287 172 l +f +*U +0.000 0.631 0.475 0.369 k +*u +1288 172 m +1289.248 171.315 1289.548 171.251 1291 171 c +1289.751 171.685 1289.452 171.749 1288 172 c +f +*U +0.000 0.361 0.267 0.220 k +*u +1291 172 m +1292 171 l +1291 172 l +f +*U +0.000 0.118 0.176 0.267 k +*u +1299 172 m +1300 171 l +1299 172 l +f +*U +0.000 0.275 0.275 0.725 k +*u +1300 172 m +1301 171 l +1300 172 l +f +*U +0.000 0.392 0.298 0.239 k +*u +1412 172 m +1413 171 l +1412 172 l +f +*U +0.000 0.341 0.231 0.314 k +*u +2054 172 m +2055 171 l +2054 172 l +f +*U +0.000 0.412 0.306 0.235 k +*u +1051 171 m +1052 170 l +1051 171 l +f +*U +0.000 0.800 0.784 0.122 k +*u +1182 171 m +1183 168 l +1183.685 169.249 1183.749 169.548 1184 171 c +1182 171 l +f +*U +0.000 0.557 0.435 0.443 k +*u +1248 171 m +1249.506 170.317 1250.315 170.174 1252 170 c +1250.494 170.683 1249.685 170.826 1248 171 c +f +*U +0.000 0.212 0.196 0.137 k +*u +1286 171 m +1287 170 l +1286 171 l +f +*U +0.000 0.478 0.408 0.498 k +*u +1287 171 m +1288 170 l +1287 171 l +f +*U +0.000 0.937 0.678 0.063 k +*u +1288 171 m +1287 164 l +1291 164 l +1291.262 166.428 1291.262 168.572 1291 171 c +1288 171 l +f +*U +0.000 0.627 0.475 0.373 k +*u +1291 171 m +1291 168 l +1291.696 169.554 1291.696 169.446 1291 171 c +f +*U +0.000 0.294 0.220 0.271 k +*u +1292 171 m +1293 170 l +1292 171 l +f +*U +0.000 0.294 0.208 0.314 k +*u +1300 171 m +1301 170 l +1300 171 l +f +*U +0.000 0.478 0.427 0.522 k +*u +1301 171 m +1302 170 l +1301 171 l +f +*U +0.000 0.475 0.349 0.412 k +*u +2051.667 170.667 m +2051.223 170.223 2052.278 170.278 2052.333 170.333 c +2052.778 170.778 2051.722 170.722 2051.667 170.667 c +f +*U +0.000 0.275 0.176 0.102 k +*u +2053 171 m +2054 170 l +2053 171 l +f +*U +0.000 0.114 0.090 0.173 k +*u +22 170 m +23 169 l +22 170 l +f +*U +0.000 0.337 0.247 0.027 k +*u +1052 170 m +1053 169 l +1052 170 l +f +*U +0.000 0.184 0.157 0.078 k +*u +1103 170 m +1104 169 l +1103 170 l +f +*U +0.000 0.353 0.255 0.204 k +*u +1154 170 m +1155 169 l +1154 170 l +f +*U +0.000 0.396 0.412 0.075 k +*u +1182.333 169.333 m +1182.278 169.278 1182.222 168.222 1182.667 168.667 c +1182.722 168.722 1182.778 169.778 1182.333 169.333 c +f +*U +0.000 0.322 0.208 0.059 k +*u +1277 170 m +1277 167 l +1277.696 168.554 1277.696 168.446 1277 170 c +f +*U +0.000 0.314 0.275 0.290 k +*u +1286 170 m +1287 169 l +1286 170 l +f +*U +0.000 0.722 0.596 0.278 k +*u +1287.333 169.333 m +1287.278 169.278 1287.222 168.222 1287.667 168.667 c +1287.722 168.722 1287.778 169.778 1287.333 169.333 c +f +*U +0.000 0.522 0.376 0.400 k +*u +1292 170 m +1292 165 l +1292.830 167 1292.830 167.969 1292 170 c +f +*U +0.000 0.667 0.592 0.333 k +*u +1302.667 169.667 m +1302.222 169.222 1303.278 169.278 1303.333 169.333 c +1303.778 169.778 1302.722 169.722 1302.667 169.667 c +f +*U +0.000 0.584 0.427 0.349 k +*u +2049 170 m +2048 168 l +2050 168 l +2050 169.853 2050.300 169.350 2049 170 c +f +*U +0.000 0.396 0.380 0.604 k +*u +2050 170 m +2051 169 l +2050 170 l +f +*U +0.000 0.310 0.255 0.290 k +*u +2051 170 m +2052 169 l +2051 170 l +f +*U +0.000 0.686 0.506 0.031 k +*u +24 169 m +25 168 l +24 169 l +f +*U +0.000 0.882 0.635 0.118 k +*u +54 169 m +60.919 166 71.520 168 79 168 c +136 168 l +333 168 l +1016 168 l +1009 170.903 998.480 169 991 169 c +934 169 l +737 169 l +54 169 l +f +*U +0.000 0.655 0.455 0.314 k +*u +1052 169 m +1053.523 164.519 1056.174 161.720 1060 159 c +1058 163 1055.451 166.215 1052 169 c +f +*U +0.000 0.584 0.337 0.000 k +*u +1104 169 m +1105 168 l +1104 169 l +f +*U +0.000 0.478 0.380 0.522 k +*u +1286 169 m +1286 163 l +1286.951 165.285 1286.951 166.715 1286 169 c +f +*U +0.000 0.361 0.282 0.243 k +*u +1303 169 m +1304 168 l +1303 169 l +f +*U +0.431 0.000 0.184 0.000 k +*u +1344 169 m +1345 168 l +1344 169 l +f +*U +0.000 0.263 0.212 0.220 k +*u +1410 169 m +1411 168 l +1410 169 l +f +*U +0.000 0.882 0.635 0.118 k +*u +1449 169 m +1453.469 167 1459.191 168 1464 168 c +1494 168 l +1600 168 l +1967 168 l +1962.531 169.875 1956.809 169 1952 169 c +1922 169 l +1816 169 l +1449 169 l +f +*U +0.000 0.282 0.220 0.082 k +*u +2050 169 m +2051 168 l +2050 169 l +f +*U +0.000 0.204 0.133 0.118 k +*u +26 168 m +27 167 l +26 168 l +f +*U +0.000 0.510 0.431 0.490 k +*u +27.667 167.667 m +27.222 167.222 28.278 167.278 28.333 167.333 c +28.778 167.778 27.722 167.722 27.667 167.667 c +f +*U +0.000 0.882 0.627 0.118 k +*u +48 168 m +55.782 163.635 65.383 165 74 165 c +125 165 l +317 165 l +1020 165 l +1012.841 168 1001.744 166 994 166 c +937 166 l +737 166 l +512.682 166 288.312 164.556 64 166 c +58.486 166 53.541 167.981 48 168 c +f +*U +0.000 0.831 0.600 0.149 k +*u +56 168 m +63 164.996 74.256 167 82 167 c +139 167 l +337 167 l +1026 167 l +1018.841 170 1007.744 168 1000 168 c +943 168 l +744 168 l +56 168 l +f +*U +0.000 0.478 0.373 0.502 k +*u +1276 168 m +1276 165 l +1276.696 166.554 1276.696 166.446 1276 168 c +f +*U +0.000 0.078 0.047 0.184 k +*u +1285 168 m +1286 167 l +1285 168 l +f +*U +0.000 0.388 0.243 0.188 k +*u +1304 168 m +1305 167 l +1304 168 l +f +*U +0.000 0.467 0.467 0.533 k +*u +1341 168 m +1342 167 l +1341 168 l +f +*U +0.000 0.251 0.259 0.435 k +*u +1342 168 m +1343 167 l +1342 168 l +f +*U +0.000 0.310 0.267 0.129 k +*u +1409 168 m +1410 167 l +1409 168 l +f +*U +0.000 0.561 0.427 0.357 k +*u +1410 168 m +1409 166.521 1409 166.797 1409 165 c +1410.289 166.443 1410.401 166.234 1410 168 c +f +*U +0.000 0.831 0.600 0.149 k +*u +1448 168 m +1452.469 166 1458.191 167 1463 167 c +1494 167 l +1600 167 l +1968 167 l +1963.531 168.875 1957.809 168 1953 168 c +1922 168 l +1816 168 l +1448 168 l +f +*U +0.000 0.737 0.561 0.263 k +*u +2042 164 m +2044.222 164.810 2045.990 165.739 2048 167 c +2045 167.698 2043.578 166.511 2042 164 c +f +*U +0.063 0.000 0.012 0.278 k +*u +2048 168 m +2049 167 l +2048 168 l +f +*U +0.000 0.259 0.196 0.106 k +*u +28 167 m +29 166 l +28 167 l +f +*U +0.000 0.502 0.420 0.498 k +*u +29.667 166.667 m +29.222 166.222 30.278 166.278 30.333 166.333 c +30.778 166.778 29.722 166.722 29.667 166.667 c +f +*U +0.000 0.906 0.655 0.094 k +*u +56 167 m +63 163.996 74.256 166 82 166 c +139 166 l +337 166 l +1024 166 l +1016.841 169 1005.744 167 998 167 c +941 167 l +743 167 l +56 167 l +f +*U +0.000 0.208 0.247 0.267 k +*u +1155 167 m +1156 166 l +1155 167 l +f +*U +0.000 0.345 0.263 0.212 k +*u +1180.667 166.667 m +1180.222 166.222 1181.278 166.278 1181.333 166.333 c +1181.778 166.778 1180.722 166.722 1180.667 166.667 c +f +*U +0.000 0.667 0.494 0.333 k +*u +1291 167 m +1289.774 164.965 1289.298 164.674 1287 164 c +1288.769 163.221 1290 163 1292 163 c +1291.826 164.685 1291.683 165.494 1291 167 c +f +*U +0.000 0.482 0.447 0.118 k +*u +1306 167 m +1307 166 l +1306 167 l +f +*U +0.000 0.412 0.345 0.412 k +*u +1340.667 166.667 m +1340.222 166.222 1341.278 166.278 1341.333 166.333 c +1341.778 166.778 1340.722 166.722 1340.667 166.667 c +f +*U +0.000 0.906 0.655 0.094 k +*u +1448 167 m +1452.469 165 1458.191 166 1463 166 c +1494 166 l +1600 166 l +1968 166 l +1963.531 167.875 1957.809 167 1953 167 c +1922 167 l +1816 167 l +1448 167 l +f +*U +0.000 0.220 0.176 0.102 k +*u +31 166 m +32 165 l +31 166 l +f +*U +0.000 0.584 0.424 0.400 k +*u +32 166 m +33.248 165.315 33.548 165.251 35 165 c +33.752 165.685 33.452 165.749 32 166 c +f +*U +0.000 0.400 0.286 0.212 k +*u +1055 166 m +1056 165 l +1055 166 l +f +*U +0.000 0.580 0.459 0.349 k +*u +1155.333 165.333 m +1155.278 165.278 1155.222 164.222 1155.667 164.667 c +1155.722 164.722 1155.778 165.778 1155.333 165.333 c +f +*U +0.000 0.553 0.467 0.447 k +*u +1178 163 m +1181 165 l +1178.860 166 1178.473 165.251 1178 163 c +f +*U +0.000 0.290 0.345 0.243 k +*u +1304 166 m +1305 165 l +1304 166 l +f +*U +0.000 0.592 0.490 0.333 k +*u +1305.667 165.667 m +1305.222 165.222 1306.278 165.278 1306.333 165.333 c +1306.778 165.778 1305.722 165.722 1305.667 165.667 c +f +*U +0.000 0.573 0.482 0.427 k +*u +1339 166 m +1340 165 l +1339 166 l +f +*U +0.000 0.318 0.271 0.259 k +*u +1340 166 m +1341 165 l +1340 166 l +f +*U +0.000 0.408 0.329 0.247 k +*u +1408 166 m +1409 165 l +1408 166 l +f +*U +0.000 0.882 0.627 0.118 k +*u +1448 166 m +1452.469 164 1458.191 165 1463 165 c +1493 165 l +1597 165 l +1851 165 l +1933 165 l +1945.430 165 1959.861 162.946 1972 165 c +1967.531 166.875 1961.809 166 1957 166 c +1926 166 l +1819 166 l +1448 166 l +f +*U +0.000 0.357 0.278 0.125 k +*u +2045 166 m +2046 165 l +2045 166 l +f +*U +0.000 0.216 0.161 0.176 k +*u +34 165 m +35 164 l +34 165 l +f +*U +0.000 0.667 0.525 0.333 k +*u +35 165 m +36.769 164.221 38 164 40 164 c +38.231 164.779 36.964 164.912 35 165 c +f +*U +0.000 0.871 0.616 0.125 k +*u +56 165 m +61.707 162.605 69.846 164 76 164 c +120 164 l +273 164 l +803 164 l +974 164 l +988.325 164 1002.677 164.265 1016.999 163.995 c +1022.983 163.883 1026.670 158.761 1032 163 c +1024.402 166.657 1014.282 165 1006 165 c +951 165 l +755 165 l +56 165 l +f +*U +0.000 0.094 0.086 0.192 k +*u +1056 165 m +1057 164 l +1056 165 l +f +*U +0.000 0.255 0.176 0.118 k +*u +1177.333 164.333 m +1177.278 164.278 1177.222 163.222 1177.667 163.667 c +1177.722 163.722 1177.778 164.778 1177.333 164.333 c +f +*U +0.000 0.992 0.753 0.000 k +*u +1179 165 m +1180.506 164.317 1181.315 164.174 1183 164 c +1181.494 164.683 1180.685 164.826 1179 165 c +f +*U +0.000 0.490 0.345 0.490 k +*u +1275.333 164.333 m +1275.278 164.278 1275.222 163.222 1275.667 163.667 c +1275.722 163.722 1275.778 164.778 1275.333 164.333 c +f +*U +0.000 0.369 0.267 0.231 k +*u +1276 165 m +1277 164 l +1276 165 l +f +*U +0.000 0.302 0.231 0.267 k +*u +1292.333 164.333 m +1292.278 164.278 1292.222 163.222 1292.667 163.667 c +1292.722 163.722 1292.778 164.778 1292.333 164.333 c +f +*U +0.000 0.329 0.267 0.196 k +*u +1301 165 m +1302 164 l +1301 165 l +f +*U +0.000 0.706 0.678 0.251 k +*u +1299 164 m +1301 163 1302.747 163 1305 163 c +1302.817 164.430 1301.625 164.328 1299 164 c +f +*U +0.000 0.729 0.549 0.271 k +*u +1310 164 m +1316.988 161 1331.781 161.866 1339 164 c +1330.505 166 1318.899 164 1310 164 c +f +*U +0.000 0.325 0.278 0.384 k +*u +1339 165 m +1340 164 l +1339 165 l +f +*U +0.000 0.192 0.125 0.129 k +*u +1407 165 m +1408 164 l +1407 165 l +f +*U +0.000 0.871 0.616 0.125 k +*u +1448 165 m +1452.469 163 1458.191 164 1463 164 c +1494 164 l +1600 164 l +1969 164 l +1964.531 165.875 1958.809 165 1954 165 c +1923 165 l +1817 165 l +1448 165 l +f +*U +0.000 0.259 0.188 0.224 k +*u +38.667 163.667 m +38.222 163.222 39.278 163.278 39.333 163.333 c +39.778 163.778 38.722 163.722 38.667 163.667 c +f +*U +0.000 0.608 0.478 0.392 k +*u +40 164 m +41.769 163.221 43 163 45 163 c +43.231 163.779 41.964 163.912 40 164 c +f +*U +0.000 0.729 0.549 0.271 k +*u +45 164 m +52 160.996 63.256 163 71 163 c +129 163 l +329 163 l +1024 163 l +1016.841 166 1005.744 164 998 164 c +940 164 l +740 164 l +45 164 l +f +*U +0.000 0.408 0.294 0.306 k +*u +1110 164 m +1111 163 l +1110 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1112 164 m +1116.215 162.231 1121.464 163 1126 163 c +1155 163 l +1150.785 164.769 1145.536 164 1141 164 c +1112 164 l +f +*U +0.000 0.408 0.408 0.592 k +*u +1155 164 m +1156 163 l +1155 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1179 164 m +1186.879 160.694 1199.466 163 1208 163 c +1275 163 l +1267 166.306 1254.534 164 1246 164 c +1179 164 l +f +*U +0.000 0.161 0.180 0.192 k +*u +1298.333 163.333 m +1298.278 163.278 1298.222 162.222 1298.667 162.667 c +1298.722 162.722 1298.778 163.778 1298.333 163.333 c +f +*U +0.000 0.749 0.804 0.118 k +*u +1305 164 m +1306.248 163.315 1306.548 163.251 1308 163 c +1306.752 163.685 1306.452 163.749 1305 164 c +f +*U +0.000 0.275 0.235 0.216 k +*u +1338 164 m +1339 163 l +1338 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1438 162 m +1445 163.695 1452.719 163 1460 163 c +1495 163 l +1609 163 l +1973 163 l +1973 120 l +1974.875 124.469 1974 130.191 1974 135 c +1974 164 l +1571 164 l +1472 164 l +1448 164 l +1444.483 164.000 1440.435 164.786 1438 162 c +f +*U +0.000 0.596 0.471 0.404 k +*u +2040 164 m +2040 162 l +2041.635 162.545 2041.455 162.365 2042 164 c +2040 164 l +f +*U +0.000 0.318 0.227 0.051 k +*u +2042 164 m +2043 163 l +2042 164 l +f +*U +0.000 0.176 0.125 0.157 k +*u +45.667 162.667 m +45.222 162.222 46.278 162.278 46.333 162.333 c +46.778 162.778 45.722 162.722 45.667 162.667 c +f +*U +0.000 0.384 0.290 0.129 k +*u +47 163 m +54 159.996 65.256 162 73 162 c +130 162 l +329 162 l +1020 162 l +1012.841 165 1001.744 163 994 163 c +937 163 l +738 163 l +47 163 l +f +*U +0.000 0.361 0.271 0.227 k +*u +1020 163 m +1021.506 162.317 1022.315 162.174 1024 162 c +1022.494 162.683 1021.685 162.826 1020 163 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1111 163 m +1115.469 161 1121.192 162 1126 162 c +1155 162 l +1150.531 163.875 1144.809 163 1140 163 c +1111 163 l +f +*U +0.000 0.263 0.204 0.361 k +*u +1155 163 m +1156 162 l +1155 163 l +f +*U +0.000 0.384 0.290 0.129 k +*u +1178 163 m +1186 159.593 1199.203 162 1208 162 c +1276 162 l +1267.882 165.407 1254.797 163 1246 163 c +1178 163 l +f +*U +0.000 0.271 0.231 0.255 k +*u +1286 163 m +1288 162 1289.747 162 1292 162 c +1289.948 162.874 1288.253 162.953 1286 163 c +f +*U +0.000 0.106 0.090 0.208 k +*u +1292 163 m +1293 162 l +1292 163 l +f +*U +0.000 0.412 0.455 0.141 k +*u +1299 163 m +1300.506 162.317 1301.315 162.174 1303 162 c +1301.494 162.683 1300.685 162.826 1299 163 c +f +*U +0.000 0.290 0.325 0.184 k +*u +1303 163 m +1305.890 161.787 1308.874 162 1312 162 c +1309 163.213 1306 162.998 1303 163 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1312 163 m +1319.169 159.992 1330.239 162 1338 162 c +1330.831 165 1319.761 163 1312 163 c +f +*U +0.000 0.522 0.380 0.431 k +*u +1437.333 162.333 m +1437.278 162.278 1437.222 161.222 1437.667 161.667 c +1437.722 161.722 1437.778 162.778 1437.333 162.333 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1439 163 m +1443.720 161 1449.920 162 1455 162 c +1486 162 l +1595 162 l +1973 162 l +1968.280 163.980 1962 163 1957 163 c +1926 163 l +1817 163 l +1439 163 l +f +*U +0.000 0.286 0.212 0.118 k +*u +1024 162 m +1025 161 l +1024 162 l +f +*U +0.000 0.424 0.282 0.251 k +*u +1405 162 m +1406 161 l +1405 162 l +f +*U +0.000 0.725 0.518 0.275 k +*u +1436.333 161.333 m +1436.278 161.278 1436.223 160.222 1436.667 160.667 c +1436.722 160.722 1436.778 161.778 1436.333 161.333 c +f +*U +0.000 0.275 0.200 0.102 k +*u +1438 162 m +1439 161 l +1438 162 l +f +*U +0.000 0.435 0.329 0.380 k +*u +2037 162 m +2037 160 l +2038.635 160.545 2038.455 160.365 2039 162 c +2037 162 l +f +*U +0.000 0.353 0.282 0.043 k +*u +2039 162 m +2040 161 l +2039 162 l +f +*U +0.020 0.000 0.027 0.000 k +*u +56 161 m +63 157.996 74.256 160 82 160 c +139 160 l +337 160 l +1023 160 l +1015.841 163 1004.744 161 997 161 c +940 161 l +742 161 l +56 161 l +f +*U +0.000 0.333 0.243 0.376 k +*u +1025 161 m +1026 160 l +1025 161 l +f +*U +0.000 0.243 0.157 0.122 k +*u +1404 161 m +1405 160 l +1404 161 l +f +*U +0.000 0.408 0.294 0.247 k +*u +1437 161 m +1438 160 l +1437 161 l +f +*U +0.020 0.000 0.027 0.000 k +*u +1440 161 m +1444.469 159 1450.191 160 1455 160 c +1486 160 l +1595 160 l +1971 160 l +1971 128 l +1972.552 131.699 1972 136 1972 140 c +1972 161 l +1440 161 l +f +*U +0.000 0.514 0.463 0.486 k +*u +2036 161 m +2037 160 l +2036 161 l +f +*U +0.000 0.290 0.235 0.439 k +*u +1026 160 m +1027 159 l +1026 160 l +f +*U +0.000 0.498 0.373 0.408 k +*u +1027.333 159.333 m +1027.278 159.278 1027.222 158.222 1027.667 158.667 c +1027.722 158.722 1027.778 159.778 1027.333 159.333 c +f +*U +0.000 0.400 0.333 0.220 k +*u +1060 160 m +1061 159 l +1060 160 l +f +*U +0.000 0.600 0.486 0.400 k +*u +1404 160 m +1403 158.521 1403 158.797 1403 157 c +1404.289 158.443 1404.401 158.234 1404 160 c +f +*U +0.000 0.400 0.325 0.447 k +*u +1435.667 159.667 m +1435.222 159.222 1436.278 159.278 1436.333 159.333 c +1436.778 159.778 1435.722 159.722 1435.667 159.667 c +f +*U +0.000 0.694 0.478 0.282 k +*u +1974 160 m +1974 122 l +1977 129.399 1975 140.993 1975 149 c +1975 152.702 1975.441 156.566 1974 160 c +f +*U +0.000 0.259 0.165 0.565 k +*u +2034.667 159.667 m +2034.222 159.222 2035.278 159.278 2035.333 159.333 c +2035.778 159.778 2034.722 159.722 2034.667 159.667 c +f +*U +0.000 0.051 0.031 0.192 k +*u +2036 160 m +2037 159 l +2036 160 l +f +*U +0.000 0.749 0.553 0.251 k +*u +1060 159 m +1061 155 l +1061.553 157 1061.303 157.332 1060 159 c +f +*U +0.000 0.314 0.243 0.271 k +*u +1061 159 m +1062 158 l +1061 159 l +f +*U +0.000 0.420 0.416 0.580 k +*u +1435 159 m +1436 158 l +1435 159 l +f +*U +0.000 0.510 0.373 0.490 k +*u +2032 159 m +2032 157 l +2033.635 157.545 2033.455 157.365 2034 159 c +2032 159 l +f +*U +0.000 0.376 0.255 0.267 k +*u +2034 159 m +2035 158 l +2034 159 l +f +*U +0.000 0.157 0.133 0.188 k +*u +1027 158 m +1028 157 l +1027 158 l +f +*U +0.000 0.420 0.384 0.580 k +*u +1028 158 m +1029 157 l +1028 158 l +f +*U +0.000 0.251 0.184 0.133 k +*u +1062 158 m +1063 157 l +1062 158 l +f +*U +0.000 0.392 0.302 0.357 k +*u +1402 158 m +1403 157 l +1402 158 l +f +*U +0.000 0.533 0.396 0.384 k +*u +1434.333 157.333 m +1434.278 157.278 1434.222 156.222 1434.667 156.667 c +1434.722 156.722 1434.778 157.778 1434.333 157.333 c +f +*U +0.000 0.325 0.267 0.263 k +*u +1435 158 m +1436 157 l +1435 158 l +f +*U +0.000 0.227 0.180 0.357 k +*u +1028 157 m +1029 156 l +1028 157 l +f +*U +0.000 0.624 0.490 0.376 k +*u +1062 157 m +1063.324 154.313 1064.313 153.324 1067 152 c +1065.451 154 1064 155.451 1062 157 c +f +*U +0.000 0.267 0.200 0.165 k +*u +1063 157 m +1064 156 l +1063 157 l +f +*U +0.000 0.290 0.235 0.227 k +*u +1401 157 m +1402 156 l +1401 157 l +f +*U +0.000 0.569 0.467 0.431 k +*u +1402 157 m +1403 156 l +1402 157 l +f +*U +0.000 0.471 0.420 0.529 k +*u +2030 157 m +2031 156 l +2030 157 l +f +*U +0.000 0.388 0.329 0.110 k +*u +2031 157 m +2032 156 l +2031 157 l +f +*U +0.000 0.427 0.345 0.114 k +*u +1400 156 m +1401 155 l +1400 156 l +f +*U +0.000 0.537 0.420 0.463 k +*u +1433 156 m +1434 155 l +1433 156 l +f +*U +0.000 0.200 0.165 0.129 k +*u +1434 156 m +1435 155 l +1434 156 l +f +*U +0.000 0.361 0.294 0.357 k +*u +2029 156 m +2030 155 l +2029 156 l +f +*U +0.000 0.216 0.141 0.173 k +*u +1399 155 m +1400 154 l +1399 155 l +f +*U +0.000 0.298 0.251 0.243 k +*u +1433 155 m +1434 154 l +1433 155 l +f +*U +0.000 0.494 0.376 0.498 k +*u +2027 155 m +2028 154 l +2027 155 l +f +*U +0.000 0.192 0.169 0.157 k +*u +2028 155 m +2029 154 l +2028 155 l +f +*U +0.000 0.267 0.196 0.110 k +*u +1030 154 m +1031 153 l +1030 154 l +f +*U +0.000 0.620 0.431 0.380 k +*u +1399.333 153.333 m +1399.278 153.278 1399.222 152.222 1399.667 152.667 c +1399.722 152.722 1399.778 153.778 1399.333 153.333 c +f +*U +0.000 0.612 0.561 0.388 k +*u +1431.333 153.333 m +1431.278 153.278 1431.222 152.222 1431.667 152.667 c +1431.722 152.722 1431.778 153.778 1431.333 153.333 c +f +*U +0.000 0.306 0.267 0.435 k +*u +1432 154 m +1433 153 l +1432 154 l +f +*U +0.000 0.396 0.306 0.365 k +*u +2026 154 m +2027 153 l +2026 154 l +f +*U +0.000 0.259 0.196 0.231 k +*u +1031 153 m +1032 152 l +1031 153 l +f +*U +0.000 0.427 0.271 0.349 k +*u +1398 153 m +1399 152 l +1398 153 l +f +*U +0.000 0.467 0.420 0.533 k +*u +2024 153 m +2025 152 l +2024 153 l +f +*U +0.000 0.392 0.294 0.012 k +*u +2025 153 m +2026 152 l +2025 153 l +f +*U +0.000 0.322 0.224 0.255 k +*u +1032 152 m +1033 151 l +1032 152 l +f +*U +0.000 0.384 0.365 0.616 k +*u +1033 152 m +1034 151 l +1033 152 l +f +*U +0.000 0.710 0.498 0.282 k +*u +1067 152 m +1067.684 149.791 1068 149.297 1070 148 c +1069 149.948 1068.607 150.550 1067 152 c +f +*U +0.000 0.180 0.129 0.188 k +*u +1125 152 m +1126 151 l +1125 152 l +f +*U +0.000 0.616 0.455 0.373 k +*u +1126 152 m +1130.564 149.361 1138.689 151 1144 151 c +1138.777 153.191 1131.632 152 1126 152 c +f +*U +0.000 0.522 0.400 0.447 k +*u +1144 152 m +1147.959 150.339 1152.740 151 1157 151 c +1180 151 l +1176 152.661 1171.260 152 1167 152 c +1144 152 l +f +*U +0.000 0.718 0.545 0.282 k +*u +1180 152 m +1181.458 150.919 1182.248 150.564 1184 150 c +1182.686 151.618 1182 151.693 1180 152 c +f +*U +0.000 0.000 0.000 0.298 k +*u +1214.667 151.667 m +1214.222 151.222 1215.278 151.278 1215.333 151.333 c +1215.778 151.778 1214.722 151.722 1214.667 151.667 c +f +*U +0.000 0.145 0.114 0.180 k +*u +1233 152 m +1234 151 l +1233 152 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1234 152 m +1235 151 l +1234 152 l +f +*U +0.000 0.529 0.384 0.467 k +*u +1235.333 151.333 m +1235.278 151.278 1235.222 150.222 1235.667 150.667 c +1235.722 150.722 1235.778 151.778 1235.333 151.333 c +f +*U +0.000 0.741 0.529 0.251 k +*u +1236 152 m +1236.307 149.877 1236.382 149.314 1238 148 c +1237.404 149.560 1236.911 150.623 1236 152 c +f +*U +0.000 0.616 0.463 0.376 k +*u +1237 152 m +1242.469 149.705 1250 151 1256 151 c +1250.531 153.295 1242.901 152 1237 152 c +f +*U +0.000 0.522 0.400 0.447 k +*u +1256 152 m +1261.707 149.605 1269.846 151 1276 151 c +1290.998 151 1307.230 152.742 1322 150 c +1318.696 153.781 1309.740 152 1305 152 c +1256 152 l +f +*U +0.000 0.278 0.251 0.722 k +*u +1322 152 m +1323 151 l +1322 152 l +f +*U +0.000 0.145 0.094 0.333 k +*u +1323 152 m +1324 151 l +1323 152 l +f +*U +0.000 0.804 0.600 0.196 k +*u +1397 152 m +1395.998 149.386 1395.678 147.773 1396 145 c +1399 146 l +1397 149 l +1398.924 150 1399 150 1400 152 c +1397 152 l +f +*U +0.000 0.455 0.463 0.490 k +*u +1430 152 m +1431 151 l +1430 152 l +f +*U +0.110 0.000 0.071 0.133 k +*u +1431 152 m +1432 151 l +1431 152 l +f +*U +0.000 0.514 0.337 0.486 k +*u +2022 152 m +2023 151 l +2022 152 l +f +*U +0.000 0.349 0.204 0.290 k +*u +2023 152 m +2024 151 l +2023 152 l +f +*U +0.000 0.263 0.184 0.325 k +*u +1126 151 m +1127 150 l +1126 151 l +f +*U +0.000 0.894 0.651 0.106 k +*u +1128 151 m +1131.547 146.985 1139.689 140.968 1145 139.938 c +1151 138.752 1158.724 140 1165 140 c +1205 140 l +1205 142 l +1202.214 142.355 1199.684 143.535 1196.911 143.871 c +1193.952 144.229 1190.807 143.588 1188 145 c +1184.936 146.650 1183.611 150 1179.946 150.772 c +1174.300 151.876 1167.742 151 1162 151 c +1128 151 l +f +*U +0.000 0.243 0.176 0.090 k +*u +1234 151 m +1235 150 l +1234 151 l +f +*U +0.000 0.882 0.635 0.118 k +*u +1237 151 m +1238.959 144.618 1244.912 145.185 1248 140 c +1265.500 140 1284.675 137.762 1302 140 c +1307.844 140.959 1317 145.842 1320 151 c +1237 151 l +f +*U +0.000 0.263 0.176 0.133 k +*u +1322 151 m +1323 150 l +1322 151 l +f +*U +0.000 0.341 0.282 0.286 k +*u +1396 151 m +1397 150 l +1396 151 l +f +*U +0.000 0.306 0.345 0.365 k +*u +1430 151 m +1431 150 l +1430 151 l +f +*U +0.000 0.545 0.451 0.455 k +*u +1034 150 m +1035 149 l +1034 150 l +f +*U +0.000 0.698 0.510 0.278 k +*u +1128.667 149.667 m +1128.222 149.222 1129.278 149.278 1129.333 149.333 c +1129.778 149.778 1128.722 149.722 1128.667 149.667 c +f +*U +0.000 0.282 0.208 0.224 k +*u +1235 150 m +1236 149 l +1235 150 l +f +*U +0.000 0.275 0.180 0.329 k +*u +1320 150 m +1321 149 l +1320 150 l +f +*U +0.000 0.286 0.208 0.369 k +*u +1395 150 m +1396 149 l +1395 150 l +f +*U +0.000 0.310 0.231 0.396 k +*u +1429 150 m +1430 149 l +1429 150 l +f +*U +0.000 0.384 0.267 0.259 k +*u +2020 150 m +2021 149 l +2020 150 l +f +*U +0.000 0.294 0.212 0.176 k +*u +1034 149 m +1035 148 l +1034 149 l +f +*U +0.000 0.349 0.271 0.243 k +*u +1070 149 m +1071 148 l +1070 149 l +f +*U +0.000 0.282 0.220 0.204 k +*u +1129 149 m +1130 148 l +1129 149 l +f +*U +0.000 0.224 0.169 0.443 k +*u +1184 149 m +1185 148 l +1184 149 l +f +*U +0.000 0.459 0.302 0.525 k +*u +1317.667 148.667 m +1317.222 148.222 1318.278 148.278 1318.333 148.333 c +1318.778 148.778 1317.722 148.722 1317.667 148.667 c +f +*U +0.000 0.278 0.141 0.086 k +*u +1319 149 m +1320 148 l +1319 149 l +f +*U +0.000 0.271 0.180 0.204 k +*u +1394 149 m +1395 148 l +1394 149 l +f +*U +0.000 0.651 0.494 0.349 k +*u +1427 149 m +1427 147 l +1428.635 147.545 1428.455 147.365 1429 149 c +1427 149 l +f +*U +0.000 0.553 0.384 0.380 k +*u +2017.667 148.667 m +2017.222 148.222 2018.278 148.278 2018.333 148.333 c +2018.778 148.778 2017.722 148.722 2017.667 148.667 c +f +*U +0.000 0.247 0.169 0.110 k +*u +2019 149 m +2020 148 l +2019 149 l +f +*U +0.000 0.306 0.224 0.259 k +*u +1035 148 m +1036 147 l +1035 148 l +f +*U +0.000 0.486 0.365 0.125 k +*u +1071 148 m +1072 147 l +1071 148 l +f +*U +0.000 0.420 0.314 0.275 k +*u +1131 148 m +1132 147 l +1131 148 l +f +*U +0.000 0.553 0.361 0.412 k +*u +1184 148 m +1188 143.180 1193.174 144 1199 144 c +1194.338 145.956 1188.933 146 1184 148 c +f +*U +0.000 0.200 0.165 0.165 k +*u +1236 148 m +1237 147 l +1236 148 l +f +*U +0.000 0.431 0.325 0.424 k +*u +1237 148 m +1237.684 146.420 1237.805 146.223 1239 145 c +1238.316 146.580 1238.195 146.777 1237 148 c +f +*U +0.000 0.318 0.251 0.431 k +*u +1317 148 m +1318 147 l +1317 148 l +f +*U +0.000 0.306 0.204 0.188 k +*u +1393 148 m +1394 147 l +1393 148 l +f +*U +0.000 0.522 0.404 0.478 k +*u +1394 148 m +1395 147 l +1394 148 l +f +*U +0.000 0.278 0.231 0.102 k +*u +1428 148 m +1429 147 l +1428 148 l +f +*U +0.000 0.380 0.259 0.290 k +*u +2017 148 m +2018 147 l +2017 148 l +f +*U +0.000 0.208 0.161 0.306 k +*u +1036 147 m +1037 146 l +1036 147 l +f +*U +0.000 0.243 0.212 0.416 k +*u +1072 147 m +1073 146 l +1072 147 l +f +*U +0.000 0.255 0.204 0.133 k +*u +1132 147 m +1133 146 l +1132 147 l +f +*U +0.000 0.714 0.537 0.286 k +*u +1133.667 146.667 m +1133.222 146.222 1134.278 146.278 1134.333 146.333 c +1134.778 146.778 1133.722 146.722 1133.667 146.667 c +f +*U +0.000 0.196 0.184 0.153 k +*u +1316 147 m +1317 146 l +1316 147 l +f +*U +0.000 0.400 0.290 0.035 k +*u +1392 147 m +1393 146 l +1392 147 l +f +*U +0.000 0.718 0.545 0.282 k +*u +1393 147 m +1392 145 l +1394 145 l +1394 146.853 1394.300 146.350 1393 147 c +f +*U +0.000 0.667 0.424 0.333 k +*u +1425 147 m +1425 144 l +1426.195 145.223 1426.316 145.420 1427 147 c +1425 147 l +f +*U +0.000 0.361 0.275 0.184 k +*u +1427 147 m +1428 146 l +1427 147 l +f +*U +0.000 0.204 0.133 0.122 k +*u +2016 147 m +2017 146 l +2016 147 l +f +*U +0.000 0.412 0.306 0.282 k +*u +1037 146 m +1038 145 l +1037 146 l +f +*U +0.000 0.565 0.467 0.435 k +*u +1072 146 m +1073 145 l +1072 146 l +f +*U +0.000 0.412 0.341 0.141 k +*u +1073 146 m +1074 145 l +1073 146 l +f +*U +0.000 0.306 0.243 0.216 k +*u +1134 146 m +1135 145 l +1134 146 l +f +*U +0.000 0.475 0.392 0.525 k +*u +1135 146 m +1136 145 l +1135 146 l +f +*U +0.000 0.102 0.067 0.227 k +*u +1195 146 m +1196.248 145.315 1196.549 145.251 1198 145 c +1196.751 145.685 1196.452 145.749 1195 146 c +f +*U +0.000 0.200 0.173 0.329 k +*u +1237 146 m +1238 145 l +1237 146 l +f +*U +0.000 0.592 0.498 0.408 k +*u +1313 146 m +1314 145 l +1313 146 l +f +*U +0.000 0.471 0.353 0.208 k +*u +1314 146 m +1315 145 l +1314 146 l +f +*U +0.000 0.506 0.396 0.451 k +*u +2012.667 145.667 m +2012.222 145.222 2013.278 145.278 2013.333 145.333 c +2013.778 145.778 2012.722 145.722 2012.667 145.667 c +f +*U +0.000 0.345 0.259 0.220 k +*u +2014 146 m +2015 145 l +2014 146 l +f +*U +0.000 0.569 0.467 0.431 k +*u +1073 145 m +1074 144 l +1073 145 l +f +*U +0.000 0.247 0.212 0.341 k +*u +1074 145 m +1075 144 l +1074 145 l +f +*U +0.000 0.114 0.129 0.125 k +*u +1135 145 m +1136 144 l +1135 145 l +f +*U +0.000 0.647 0.420 0.133 k +*u +1199 145 m +1200 144 l +1199 145 l +f +*U +0.000 0.180 0.169 0.153 k +*u +1238 145 m +1239 144 l +1238 145 l +f +*U +0.000 0.459 0.361 0.125 k +*u +1239 145 m +1240 144 l +1239 145 l +f +*U +0.000 0.580 0.486 0.420 k +*u +1240 145 m +1241.506 144.317 1242.315 144.174 1244 144 c +1242.494 144.683 1241.686 144.826 1240 145 c +f +*U +0.000 0.329 0.282 0.580 k +*u +1312 145 m +1313 144 l +1312 145 l +f +*U +0.000 0.224 0.141 0.584 k +*u +1391 145 m +1392 144 l +1391 145 l +f +*U +0.000 0.482 0.427 0.231 k +*u +2012 145 m +2013 144 l +2012 145 l +f +*U +0.000 0.188 0.118 0.671 k +*u +1039 144 m +1040 143 l +1039 144 l +f +*U +0.000 0.741 0.463 0.259 k +*u +1040 144 m +1040.684 142.420 1040.805 142.223 1042 141 c +1042 144 l +1040 144 l +f +*U +0.000 0.463 0.443 0.173 k +*u +1075 144 m +1076 143 l +1075 144 l +f +*U +0.000 0.192 0.137 0.294 k +*u +1137 144 m +1138 143 l +1137 144 l +f +*U +0.000 0.698 0.533 0.302 k +*u +1138.667 143.667 m +1138.222 143.222 1139.278 143.278 1139.333 143.333 c +1139.778 143.778 1138.722 143.722 1138.667 143.667 c +f +*U +0.000 0.067 0.114 0.302 k +*u +1200 144 m +1201 143 l +1200 144 l +f +*U +0.000 0.086 0.012 0.192 k +*u +1243 144 m +1244 143 l +1243 144 l +f +*U +0.000 0.290 0.161 0.376 k +*u +1244 144 m +1245 143 l +1244 144 l +f +*U +0.000 0.416 0.259 0.573 k +*u +1309.667 143.667 m +1309.222 143.222 1310.278 143.278 1310.333 143.333 c +1310.778 143.778 1309.722 143.722 1309.667 143.667 c +f +*U +0.000 0.337 0.180 0.039 k +*u +1311 144 m +1312 143 l +1311 144 l +f +*U +0.000 0.682 0.498 0.282 k +*u +1390 144 m +1387.794 141.748 1385.807 139.576 1384 137 c +1387 138.489 1390 140.283 1390 144 c +f +*U +0.000 0.243 0.149 0.686 k +*u +1424 144 m +1425 143 l +1424 144 l +f +*U +0.000 0.180 0.114 0.125 k +*u +1425 144 m +1426 143 l +1425 144 l +f +*U +0.000 0.443 0.286 0.463 k +*u +2009.667 143.667 m +2009.222 143.223 2010.277 143.277 2010.333 143.333 c +2010.778 143.778 2009.722 143.722 2009.667 143.667 c +f +*U +0.000 0.169 0.102 0.173 k +*u +2011 144 m +2012 143 l +2011 144 l +f +*U +0.000 0.180 0.118 0.176 k +*u +1039 143 m +1040 142 l +1039 143 l +f +*U +0.000 0.502 0.400 0.341 k +*u +1075 143 m +1076.223 141.805 1076.420 141.684 1078 141 c +1076.777 142.195 1076.580 142.316 1075 143 c +f +*U +0.000 0.365 0.263 0.247 k +*u +1139 143 m +1140 142 l +1139 143 l +f +*U +0.000 0.471 0.365 0.486 k +*u +1200 143 m +1201 142 l +1200 143 l +f +*U +0.000 0.420 0.329 0.259 k +*u +1201 143 m +1202 142 l +1201 143 l +f +*U +0.000 0.275 0.235 0.067 k +*u +1202 143 m +1203 142 l +1202 143 l +f +*U +0.000 0.137 0.110 0.122 k +*u +1210 143 m +1211 142 l +1210 143 l +f +*U +0.000 0.290 0.216 0.306 k +*u +1211 143 m +1212 142 l +1211 143 l +f +*U +0.000 0.537 0.467 0.431 k +*u +1212 143 m +1214 142 1215.747 142 1218 142 c +1215.948 142.874 1214.253 142.953 1212 143 c +f +*U +0.000 0.267 0.216 0.259 k +*u +1218 143 m +1219 142 l +1218 143 l +f +*U +0.000 0.349 0.224 0.000 k +*u +1245 143 m +1246 142 l +1245 143 l +f +*U +0.000 0.471 0.345 0.306 k +*u +1246 143 m +1246 140 l +1246.696 141.554 1246.696 141.446 1246 143 c +f +*U +0.000 0.576 0.435 0.353 k +*u +1247 143 m +1246 139 l +1247.656 140.404 1247.751 140.954 1247 143 c +f +*U +0.000 0.357 0.259 0.310 k +*u +1309 143 m +1310 142 l +1309 143 l +f +*U +0.000 0.161 0.098 0.263 k +*u +1424 143 m +1425 142 l +1424 143 l +f +*U +0.000 0.557 0.361 0.427 k +*u +2008 143 m +2009 142 l +2008 143 l +f +*U +0.000 0.478 0.322 0.098 k +*u +2009 143 m +2010 142 l +2009 143 l +f +*U +0.000 0.282 0.212 0.075 k +*u +1040 142 m +1041 141 l +1040 142 l +f +*U +0.000 0.329 0.239 0.055 k +*u +1140 142 m +1141 141 l +1140 142 l +f +*U +0.000 0.580 0.455 0.420 k +*u +1205 142 m +1206.769 141.221 1208 141 1210 141 c +1208.231 141.779 1206.964 141.912 1205 142 c +f +*U +0.000 0.945 0.667 0.055 k +*u +1205 141 m +1208.959 139.339 1213.737 140 1218 140 c +1218 142 l +1205 141 l +f +*U +0.000 0.667 0.522 0.333 k +*u +1218 142 m +1212.887 138 1203.218 140 1197 140 c +1146 140 l +1152.436 137.299 1162 139 1169 139 c +1220 139 l +1219.316 140.580 1219.195 140.777 1218 142 c +f +*U +0.000 0.329 0.251 0.075 k +*u +1219 142 m +1220 141 l +1219 142 l +f +*U +0.000 0.604 0.459 0.396 k +*u +1306 142 m +1307 141 l +1306 142 l +f +*U +0.000 0.361 0.298 0.396 k +*u +1307 142 m +1308 141 l +1307 142 l +f +*U +0.000 0.369 0.306 0.353 k +*u +1423 142 m +1424 141 l +1423 142 l +f +*U +0.000 0.659 0.471 0.341 k +*u +2006.667 141.667 m +2006.222 141.222 2007.278 141.278 2007.333 141.333 c +2007.778 141.778 2006.722 141.722 2006.667 141.667 c +f +*U +0.000 0.184 0.125 0.133 k +*u +2008 142 m +2009 141 l +2008 142 l +f +*U +0.000 0.361 0.337 0.086 k +*u +1041 141 m +1042 140 l +1041 141 l +f +*U +0.000 0.620 0.475 0.380 k +*u +1042 141 m +1043 140 l +1042 141 l +f +*U +0.000 0.706 0.490 0.294 k +*u +1077 141 m +1078.573 138.338 1080 137.228 1083 136 c +1081 138.447 1079.763 139.700 1077 141 c +f +*U +0.000 0.325 0.235 0.082 k +*u +1142 141 m +1143 140 l +1142 141 l +f +*U +0.000 0.443 0.337 0.188 k +*u +1220 141 m +1221 140 l +1220 141 l +f +*U +0.000 0.412 0.388 0.588 k +*u +1304 141 m +1305 140 l +1304 141 l +f +*U +0.000 0.420 0.318 0.380 k +*u +1305 141 m +1306 140 l +1305 141 l +f +*U +0.000 0.427 0.325 0.341 k +*u +1422 141 m +1423 140 l +1422 141 l +f +*U +0.000 0.439 0.431 0.561 k +*u +2005 141 m +2006 140 l +2005 141 l +f +*U +0.000 0.329 0.227 0.325 k +*u +2006 141 m +2007 140 l +2006 141 l +f +*U +0.000 0.267 0.220 0.235 k +*u +1042 140 m +1043 139 l +1042 140 l +f +*U +0.000 0.604 0.412 0.000 k +*u +1144 140 m +1145 139 l +1144 140 l +f +*U +0.000 0.400 0.388 0.600 k +*u +1220.667 139.667 m +1220.222 139.222 1221.278 139.278 1221.333 139.333 c +1221.778 139.778 1220.722 139.722 1220.667 139.667 c +f +*U +0.000 0.416 0.267 0.325 k +*u +1222 140 m +1223 139 l +1222 140 l +f +*U +0.000 0.145 0.075 0.220 k +*u +1222 138 m +1223.580 138.684 1223.777 138.805 1225 140 c +1223.420 139.316 1223.223 139.195 1222 138 c +f +*U +0.000 0.204 0.137 0.169 k +*u +1227 139 m +1230.607 137.487 1234.260 138 1238 139 c +1234.672 140 1230.479 139.411 1227 139 c +f +*U +0.000 0.259 0.165 0.396 k +*u +1229 140 m +1230.248 139.315 1230.548 139.251 1232 139 c +1230.751 139.685 1230.452 139.749 1229 140 c +f +*U +0.000 0.227 0.153 0.286 k +*u +1232 140 m +1233.248 139.315 1233.548 139.251 1235 139 c +1233.751 139.685 1233.452 139.749 1232 140 c +f +*U +0.000 0.067 0.078 0.518 k +*u +1239.667 139.667 m +1239.222 139.222 1240.278 139.278 1240.333 139.333 c +1240.778 139.778 1239.722 139.722 1239.667 139.667 c +f +*U +0.000 0.667 0.522 0.333 k +*u +1248 140 m +1253.216 137.811 1260.381 139 1266 139 c +1304 139 l +1298.783 141.189 1291.619 140 1286 140 c +1248 140 l +f +*U +0.000 0.404 0.314 0.596 k +*u +1421 140 m +1422 139 l +1421 140 l +f +*U +0.000 0.498 0.384 0.427 k +*u +2003.667 139.667 m +2003.222 139.222 2004.278 139.278 2004.333 139.333 c +2004.778 139.778 2003.722 139.722 2003.667 139.667 c +f +*U +0.000 0.373 0.298 0.259 k +*u +1043 139 m +1044 138 l +1043 139 l +f +*U +0.000 0.675 0.533 0.294 k +*u +1044 139 m +1045 136.643 1045.956 135.624 1048 134 c +1046.987 136.485 1046.274 137.598 1044 139 c +f +*U +0.012 0.000 0.024 0.145 k +*u +1145.667 138.667 m +1145.222 138.222 1146.278 138.278 1146.333 138.333 c +1146.778 138.778 1145.722 138.722 1145.667 138.667 c +f +*U +0.000 0.035 0.024 0.251 k +*u +1238 139 m +1239 138 l +1238 139 l +f +*U +0.000 0.310 0.251 0.071 k +*u +1247 139 m +1248 138 l +1247 139 l +f +*U +0.000 0.039 0.035 0.220 k +*u +1299.667 138.667 m +1299.222 138.222 1300.278 138.278 1300.333 138.333 c +1300.778 138.778 1299.722 138.722 1299.667 138.667 c +f +*U +0.000 0.424 0.365 0.576 k +*u +1420 139 m +1421 138 l +1420 139 l +f +*U +0.000 0.455 0.357 0.102 k +*u +2003 139 m +2004 138 l +2003 139 l +f +*U +0.000 0.420 0.388 0.580 k +*u +1419 138 m +1420 137 l +1419 138 l +f +*U +0.000 0.235 0.173 0.110 k +*u +1420 138 m +1421 137 l +1420 138 l +f +*U +0.000 0.561 0.424 0.192 k +*u +2001 138 m +2002 137 l +2001 138 l +f +*U +0.000 0.337 0.255 0.071 k +*u +2002 138 m +2003 137 l +2002 138 l +f +*U +0.000 0.145 0.086 0.169 k +*u +1083 137 m +1084 136 l +1083 137 l +f +*U +0.000 0.110 0.047 0.729 k +*u +1383 137 m +1384 136 l +1383 137 l +f +*U +0.000 0.318 0.251 0.110 k +*u +1419 137 m +1420 136 l +1419 137 l +f +*U +0.000 0.333 0.302 0.153 k +*u +2000 137 m +2001 136 l +2000 137 l +f +*U +0.000 0.796 0.576 0.204 k +*u +1083 136 m +1084 132.767 1085.455 130.310 1088 128 c +1089.198 129.245 1089 129 1091 129 c +1088.615 131.749 1086 133.943 1083 136 c +f +*U +0.000 0.271 0.290 0.102 k +*u +1084 136 m +1085 135 l +1084 136 l +f +*U +0.000 0.490 0.365 0.510 k +*u +1417 136 m +1418 135 l +1417 136 l +f +*U +0.000 0.231 0.149 0.318 k +*u +1418 136 m +1419 135 l +1418 136 l +f +*U +0.000 0.463 0.345 0.431 k +*u +1995 134 m +1996.580 134.684 1996.777 134.805 1998 136 c +1996.420 135.316 1996.223 135.195 1995 134 c +f +*U +0.000 0.129 0.102 0.475 k +*u +1998 136 m +1999 135 l +1998 136 l +f +*U +0.000 0.267 0.196 0.251 k +*u +1085 135 m +1086 134 l +1085 135 l +f +*U +0.000 0.545 0.361 0.455 k +*u +1416 135 m +1417 134 l +1416 135 l +f +*U +0.000 0.384 0.255 0.157 k +*u +1417 135 m +1418 134 l +1417 135 l +f +*U +0.000 0.275 0.216 0.082 k +*u +1997 135 m +1998 134 l +1997 135 l +f +*U +0.000 0.341 0.239 0.271 k +*u +1086 134 m +1087 133 l +1086 134 l +f +*U +0.000 0.514 0.380 0.486 k +*u +1380 134 m +1381 133 l +1380 134 l +f +*U +0.000 0.616 0.431 0.380 k +*u +1415 134 m +1413.242 131.988 1412 130.419 1411 128 c +1413.348 129.773 1415 131 1415 134 c +f +*U +0.000 0.224 0.137 0.314 k +*u +1416 134 m +1417 133 l +1416 134 l +f +*U +0.000 0.525 0.408 0.475 k +*u +1994 134 m +1995 133 l +1994 134 l +f +*U +0.000 0.337 0.243 0.306 k +*u +1995 134 m +1996 133 l +1995 134 l +f +*U +0.000 0.204 0.157 0.125 k +*u +1048 133 m +1049 132 l +1048 133 l +f +*U +0.000 0.494 0.420 0.227 k +*u +1087 133 m +1088 132 l +1087 133 l +f +*U +0.000 0.510 0.510 0.459 k +*u +1379 133 m +1380 132 l +1379 133 l +f +*U +0.000 0.796 0.600 0.196 k +*u +1380 133 m +1378.390 131.672 1377.299 130.617 1376 129 c +1380 128 l +1379.402 129.196 1379.534 128.977 1378 130 c +1379.994 130.847 1380.699 131 1380 133 c +f +*U +0.000 0.533 0.400 0.455 k +*u +1992.667 132.667 m +1992.222 132.222 1993.278 132.278 1993.333 132.333 c +1993.778 132.778 1992.722 132.722 1992.667 132.667 c +f +*U +0.000 0.318 0.220 0.051 k +*u +1994 133 m +1995 132 l +1994 133 l +f +*U +0.000 0.341 0.235 0.439 k +*u +1088 132 m +1089 131 l +1088 132 l +f +*U +0.000 0.251 0.271 0.157 k +*u +1377 132 m +1378 131 l +1377 132 l +f +*U +0.000 0.212 0.188 0.373 k +*u +1992 132 m +1993 131 l +1992 132 l +f +*U +0.000 0.525 0.424 0.475 k +*u +1051 131 m +1052 130 l +1051 131 l +f +*U +0.000 0.286 0.263 0.180 k +*u +1376 131 m +1377 130 l +1376 131 l +f +*U +0.000 0.439 0.341 0.349 k +*u +1989 131 m +1989 129 l +1990.635 129.545 1990.455 129.365 1991 131 c +1989 131 l +f +*U +0.000 0.337 0.275 0.059 k +*u +1991 131 m +1992 130 l +1991 131 l +f +*U +0.000 0.486 0.431 0.514 k +*u +1052 130 m +1053 129 l +1052 130 l +f +*U +0.000 0.275 0.200 0.286 k +*u +1091 130 m +1092 129 l +1091 130 l +f +*U +0.000 0.325 0.204 0.204 k +*u +1375 130 m +1376 129 l +1375 130 l +f +*U +0.000 0.953 0.620 0.047 k +*u +1380 128 m +1381.580 128.684 1381.777 128.805 1383 130 c +1381.420 129.317 1381.223 129.195 1380 128 c +f +*U +0.000 0.525 0.396 0.475 k +*u +1988 130 m +1989 129 l +1988 130 l +f +*U +0.000 0.251 0.180 0.349 k +*u +1092 129 m +1093 128 l +1092 129 l +f +*U +0.000 0.306 0.200 0.302 k +*u +1374 129 m +1375 128 l +1374 129 l +f +*U +0.000 0.486 0.310 0.514 k +*u +1375 129 m +1376 128 l +1375 129 l +f +*U +0.000 0.180 0.141 0.059 k +*u +1412 129 m +1413 128 l +1412 129 l +f +*U +0.000 0.408 0.333 0.424 k +*u +1986.667 128.667 m +1986.222 128.223 1987.277 128.277 1987.333 128.333 c +1987.778 128.778 1986.722 128.722 1986.667 128.667 c +f +*U +0.000 0.192 0.173 0.149 k +*u +1988 129 m +1989 128 l +1988 129 l +f +*U +0.000 0.506 0.561 0.427 k +*u +1054 128 m +1054.545 126.365 1054.365 126.545 1056 126 c +1056 128 l +1054 128 l +f +*U +0.000 0.588 0.443 0.329 k +*u +1092 128 m +1093.624 125.956 1094.643 125 1097 124 c +1095.376 126 1094.357 126.896 1092 128 c +f +*U +0.000 0.192 0.129 0.506 k +*u +1173 128 m +1174 127 l +1173 128 l +f +*U +0.000 0.220 0.220 0.780 k +*u +1174.667 127.667 m +1174.222 127.223 1175.278 127.278 1175.333 127.333 c +1175.778 127.778 1174.722 127.722 1174.667 127.667 c +f +*U +0.000 0.580 0.420 0.420 k +*u +1176 128 m +1180.271 125 1188.772 127 1194 127 c +1240 127 l +1234.293 129.395 1226 128 1220 128 c +1176 128 l +f +*U +0.000 0.529 0.412 0.471 k +*u +1240 128 m +1247.409 124.891 1258.975 127 1267 127 c +1259.591 130 1248 128 1240 128 c +f +*U +0.000 0.620 0.467 0.380 k +*u +1264 126 m +1266.698 125 1269 125.647 1272 126 c +1269 128 1267.224 127 1264 126 c +f +*U +0.000 0.247 0.247 0.753 k +*u +1271 128 m +1272.506 127.317 1273.315 127.174 1275 127 c +1273.494 127.683 1272.685 127.826 1271 128 c +f +*U +0.000 0.192 0.192 0.478 k +*u +1275 128 m +1276 127 l +1275 128 l +f +*U +0.000 0.098 0.102 0.200 k +*u +1276 128 m +1277 127 l +1276 128 l +f +*U +0.000 0.675 0.482 0.325 k +*u +1373 125 m +1374 126 1374.309 126.612 1375 128 c +1372.797 127 1372.952 127.330 1373 125 c +f +*U +0.000 0.545 0.435 0.384 k +*u +1409 128 m +1408 126.522 1408 126.797 1408 125 c +1409.289 126.443 1409.401 126.234 1409 128 c +f +*U +0.000 0.322 0.298 0.678 k +*u +1410 128 m +1411 127 l +1410 128 l +f +*U +0.000 0.443 0.282 0.475 k +*u +1984 128 m +1984 126 l +1985.635 126.545 1985.455 126.365 1986 128 c +1984 128 l +f +*U +0.000 0.212 0.133 0.169 k +*u +1986 128 m +1987 127 l +1986 128 l +f +*U +0.000 0.792 0.620 0.208 k +*u +1057 127 m +1057.514 124 1058.289 123.366 1061 122 c +1059.774 123.922 1058.627 125.412 1057 127 c +f +*U +0.000 0.478 0.365 0.161 k +*u +1176 127 m +1177 126 l +1176 127 l +f +*U +0.000 0.878 0.620 0.122 k +*u +1180 127 m +1184 124 l +1192.981 124.818 1202.873 121.439 1212 121 c +1230.863 120.213 1248.573 122.424 1267 126 c +1259.601 129 1248 127 1240 127 c +1180 127 l +f +*U +0.000 0.259 0.224 0.122 k +*u +1410 127 m +1411 126 l +1410 127 l +f +*U +0.000 0.192 0.145 0.125 k +*u +1096 126 m +1097 125 l +1096 126 l +f +*U +0.000 0.220 0.188 0.318 k +*u +1180 126 m +1181 125 l +1180 126 l +f +*U +0.000 0.604 0.451 0.392 k +*u +1181 126 m +1182.249 125.315 1182.548 125.251 1184 125 c +1182.752 125.685 1182.451 125.749 1181 126 c +f +*U +0.000 0.263 0.263 0.220 k +*u +1268 126 m +1269 125 l +1268 126 l +f +*U +0.000 0.224 0.173 0.051 k +*u +1370 126 m +1371 125 l +1370 126 l +f +*U +0.000 0.353 0.290 0.173 k +*u +1409 126 m +1410 125 l +1409 126 l +f +*U +0.000 0.443 0.357 0.373 k +*u +1981 126 m +1981 124 l +1982.635 124.545 1982.455 124.365 1983 126 c +1981 126 l +f +*U +0.000 0.243 0.243 0.278 k +*u +1983 126 m +1984 125 l +1983 126 l +f +*U +0.000 0.325 0.231 0.275 k +*u +1097 125 m +1098 124 l +1097 125 l +f +*U +0.000 0.294 0.239 0.027 k +*u +1183 125 m +1184 124 l +1183 125 l +f +*U +0.000 0.620 0.463 0.361 k +*u +1185 125 m +1186.249 124.315 1186.548 124.251 1188 124 c +1186.752 124.685 1186.451 124.749 1185 125 c +f +*U +0.000 0.600 0.459 0.400 k +*u +1256 124 m +1258.698 123 1261 123.647 1264 124 c +1261.244 125 1258.893 124.532 1256 124 c +f +*U +0.000 0.173 0.141 0.380 k +*u +1264 125 m +1265 124 l +1264 125 l +f +*U +0.000 0.149 0.129 0.110 k +*u +1265 125 m +1266 124 l +1265 125 l +f +*U +0.000 0.216 0.165 0.263 k +*u +1369 125 m +1370 124 l +1369 125 l +f +*U +0.000 0.643 0.475 0.341 k +*u +1404 121 m +1405.753 122.330 1406.670 123.247 1408 125 c +1405.751 123.847 1405 123.249 1404 121 c +f +*U +0.000 0.298 0.255 0.176 k +*u +1408 125 m +1409 124 l +1408 125 l +f +*U +0.000 0.247 0.220 0.094 k +*u +1187 124 m +1188 123 l +1187 124 l +f +*U +0.000 0.412 0.325 0.231 k +*u +1188 124 m +1189 123 l +1188 124 l +f +*U +0.000 0.600 0.506 0.400 k +*u +1189.667 123.667 m +1189.223 123.223 1190.278 123.278 1190.333 123.333 c +1190.778 123.778 1189.722 123.722 1189.667 123.667 c +f +*U +0.000 0.306 0.208 0.204 k +*u +1260 124 m +1261 123 l +1260 124 l +f +*U +0.000 0.290 0.204 0.341 k +*u +1368 124 m +1369 123 l +1368 124 l +f +*U +0.000 0.376 0.298 0.118 k +*u +1407 124 m +1408 123 l +1407 124 l +f +*U +0.000 0.220 0.153 0.118 k +*u +1980 124 m +1981 123 l +1980 124 l +f +*U +0.000 0.302 0.220 0.071 k +*u +1100 123 m +1101 122 l +1100 123 l +f +*U +0.000 0.310 0.224 0.059 k +*u +1192 123 m +1193 122 l +1192 123 l +f +*U +0.000 0.333 0.243 0.212 k +*u +1193 123 m +1194 122 l +1193 123 l +f +*U +0.000 0.510 0.357 0.475 k +*u +1194 123 m +1195.249 122.315 1195.548 122.251 1197 122 c +1195.752 122.685 1195.451 122.749 1194 123 c +f +*U +0.000 0.753 0.569 0.247 k +*u +1248 123 m +1249.249 122.315 1249.548 122.251 1251 122 c +1249.752 122.685 1249.452 122.749 1248 123 c +f +*U +0.000 0.549 0.455 0.451 k +*u +1251 123 m +1252.249 122.315 1252.548 122.251 1254 122 c +1252.752 122.685 1252.451 122.749 1251 123 c +f +*U +0.000 0.498 0.369 0.200 k +*u +1254 123 m +1255 122 l +1254 123 l +f +*U +0.000 0.502 0.376 0.031 k +*u +1255 123 m +1256 122 l +1255 123 l +f +*U +0.000 0.086 0.027 0.153 k +*u +1256 123 m +1257 122 l +1256 123 l +f +*U +0.000 0.271 0.275 0.388 k +*u +1367 123 m +1368 122 l +1367 123 l +f +*U +0.000 0.459 0.416 0.541 k +*u +1368 123 m +1369 122 l +1368 123 l +f +*U +0.000 0.380 0.298 0.094 k +*u +1406 123 m +1407 122 l +1406 123 l +f +*U +0.000 0.553 0.478 0.447 k +*u +1977 123 m +1978 122 l +1977 123 l +f +*U +0.000 0.325 0.224 0.310 k +*u +1978 123 m +1979 122 l +1978 123 l +f +*U +0.000 0.365 0.263 0.224 k +*u +1101 122 m +1102 121 l +1101 122 l +f +*U +0.000 0.176 0.137 0.125 k +*u +1198 122 m +1199 121 l +1198 122 l +f +*U +0.000 0.176 0.137 0.298 k +*u +1199 122 m +1200 121 l +1199 122 l +f +*U +0.000 0.643 0.498 0.357 k +*u +1200 122 m +1202.613 120.902 1205 121 1208 121 c +1205.387 122 1202.835 121.993 1200 122 c +f +*U +0.000 0.706 0.518 0.294 k +*u +1240 122 m +1241.769 121.221 1243 121 1245 121 c +1243.231 121.779 1241.964 121.912 1240 122 c +f +*U +0.000 0.545 0.424 0.455 k +*u +1245 122 m +1246.249 121.315 1246.548 121.251 1248 121 c +1246.752 121.685 1246.451 121.749 1245 122 c +f +*U +0.000 0.235 0.176 0.278 k +*u +1248.667 121.667 m +1248.222 121.222 1249.278 121.278 1249.333 121.333 c +1249.778 121.778 1248.722 121.722 1248.667 121.667 c +f +*U +0.000 0.200 0.149 0.071 k +*u +1250 122 m +1251 121 l +1250 122 l +f +*U +0.000 0.294 0.243 0.204 k +*u +1405 122 m +1406 121 l +1405 122 l +f +*U +0.000 0.471 0.380 0.529 k +*u +1974.333 121.333 m +1974.278 121.278 1974.222 120.222 1974.667 120.667 c +1974.722 120.722 1974.778 121.778 1974.333 121.333 c +f +*U +0.000 0.408 0.294 0.424 k +*u +1102 121 m +1103 120 l +1102 121 l +f +*U +0.000 0.173 0.161 0.247 k +*u +1205 121 m +1206.249 120.315 1206.548 120.251 1208 120 c +1206.752 120.685 1206.451 120.749 1205 121 c +f +*U +0.000 0.502 0.357 0.192 k +*u +1208 121 m +1209 120 l +1208 121 l +f +*U +0.000 0.604 0.514 0.396 k +*u +1209 121 m +1211.331 120 1213.457 120 1216 120 c +1213.668 120.985 1211.543 120.981 1209 121 c +f +*U +0.000 0.843 0.851 0.149 k +*u +1216 121 m +1221.469 118.705 1229 120 1235 120 c +1229.531 122.295 1221.901 121 1216 121 c +f +*U +0.000 0.553 0.541 0.447 k +*u +1235 121 m +1236.249 120.315 1236.548 120.251 1238 120 c +1236.752 120.685 1236.452 120.749 1235 121 c +f +*U +0.000 0.675 0.400 0.243 k +*u +1238.667 120.667 m +1238.222 120.223 1239.278 120.278 1239.333 120.333 c +1239.778 120.778 1238.722 120.722 1238.667 120.667 c +f +*U +0.000 0.337 0.255 0.204 k +*u +1240 121 m +1241.249 120.315 1241.548 120.251 1243 120 c +1241.752 120.685 1241.451 120.749 1240 121 c +f +*U +0.000 0.169 0.137 0.082 k +*u +1243 121 m +1244 120 l +1243 121 l +f +*U +0.000 0.122 0.055 0.204 k +*u +1364 121 m +1365 120 l +1364 121 l +f +*U +0.000 0.400 0.298 0.600 k +*u +1365 121 m +1366 120 l +1365 121 l +f +*U +0.000 0.510 0.392 0.059 k +*u +1404 121 m +1405 120 l +1404 121 l +f +*U +0.000 0.671 0.463 0.094 k +*u +1975 121 m +1976 120 l +1975 121 l +f +*U +0.000 0.322 0.204 0.298 k +*u +1062 120 m +1063 119 l +1062 120 l +f +*U +0.000 0.427 0.286 0.573 k +*u +1063 120 m +1064 119 l +1063 120 l +f +*U +0.000 0.133 0.114 0.161 k +*u +1104 120 m +1105 119 l +1104 120 l +f +*U +0.000 0.090 0.020 0.224 k +*u +1218 120 m +1220.890 118.787 1223.874 119 1227 119 c +1224 120.213 1221 119.998 1218 120 c +f +*U +0.000 0.384 0.416 0.263 k +*u +1363 120 m +1364 119 l +1363 120 l +f +*U +0.000 0.506 0.329 0.443 k +*u +1402 120 m +1403 119 l +1402 120 l +f +*U +0.000 0.200 0.125 0.176 k +*u +1403 120 m +1404 119 l +1403 120 l +f +*U +0.031 0.000 0.012 0.588 k +*u +1973 120 m +1974 119 l +1973 120 l +f +*U +0.000 0.290 0.184 0.235 k +*u +1063 119 m +1064 118 l +1063 119 l +f +*U +0.000 0.494 0.357 0.455 k +*u +1104 119 m +1105 118 l +1104 119 l +f +*U +0.000 0.424 0.302 0.290 k +*u +1105 119 m +1106 118 l +1105 119 l +f +*U +0.000 0.627 0.506 0.373 k +*u +1362.667 118.667 m +1362.222 118.223 1363.278 118.278 1363.333 118.333 c +1363.778 118.778 1362.722 118.722 1362.667 118.667 c +f +*U +0.000 0.537 0.408 0.463 k +*u +1401 119 m +1402 118 l +1401 119 l +f +*U +0.000 0.329 0.220 0.075 k +*u +1402 119 m +1403 118 l +1402 119 l +f +*U +0.000 0.376 0.294 0.188 k +*u +1064 118 m +1065 117 l +1064 118 l +f +*U +0.000 0.522 0.424 0.478 k +*u +1065 118 m +1066 117 l +1065 118 l +f +*U +0.000 0.235 0.180 0.090 k +*u +1107 118 m +1108 117 l +1107 118 l +f +*U +0.000 0.318 0.388 0.086 k +*u +1360 118 m +1361 117 l +1360 118 l +f +*U +0.000 0.459 0.451 0.541 k +*u +1361 118 m +1362 117 l +1361 118 l +f +*U +0.000 0.522 0.341 0.431 k +*u +1400 118 m +1401 117 l +1400 118 l +f +*U +0.000 0.329 0.224 0.067 k +*u +1401 118 m +1402 117 l +1401 118 l +f +*U +0.000 0.404 0.325 0.561 k +*u +1066 117 m +1067 116 l +1066 117 l +f +*U +0.000 0.541 0.424 0.459 k +*u +1107 117 m +1108 116 l +1107 117 l +f +*U +0.000 0.322 0.247 0.310 k +*u +1108 117 m +1109 116 l +1108 117 l +f +*U +0.000 0.278 0.192 0.322 k +*u +1359 117 m +1360 116 l +1359 117 l +f +*U +0.000 0.553 0.404 0.447 k +*u +1399 117 m +1400 116 l +1399 117 l +f +*U +0.000 0.224 0.145 0.180 k +*u +1400 117 m +1401 116 l +1400 117 l +f +*U +0.055 0.000 0.059 0.157 k +*u +1066 116 m +1067 115 l +1066 116 l +f +*U +0.000 0.329 0.329 0.671 k +*u +1067 116 m +1068 115 l +1067 116 l +f +*U +0.000 0.486 0.353 0.404 k +*u +1108.667 115.667 m +1108.222 115.222 1109.278 115.278 1109.333 115.333 c +1109.778 115.778 1108.722 115.722 1108.667 115.667 c +f +*U +0.000 0.235 0.196 0.114 k +*u +1357 116 m +1358 115 l +1357 116 l +f +*U +0.000 0.490 0.388 0.510 k +*u +1358 116 m +1359 115 l +1358 116 l +f +*U +0.000 0.706 0.525 0.239 k +*u +1396 116 m +1396 113 l +1397.196 114.223 1397.316 114.420 1398 116 c +1396 116 l +f +*U +0.000 0.365 0.310 0.635 k +*u +1398 116 m +1399 115 l +1398 116 l +f +*U +0.000 0.212 0.157 0.075 k +*u +1399 116 m +1400 115 l +1399 116 l +f +*U +0.000 0.455 0.380 0.545 k +*u +1068 115 m +1069 114 l +1068 115 l +f +*U +0.000 0.443 0.341 0.196 k +*u +1111 115 m +1112 114 l +1111 115 l +f +*U +0.000 0.373 0.302 0.231 k +*u +1356 115 m +1357 114 l +1356 115 l +f +*U +0.000 0.451 0.451 0.549 k +*u +1357 115 m +1358 114 l +1357 115 l +f +*U +0.000 0.659 0.451 0.341 k +*u +1112 114 m +1112 112 l +1114 112 l +1113.455 113.635 1113.635 113.455 1112 114 c +f +*U +0.000 0.380 0.255 0.063 k +*u +1113 114 m +1114 113 l +1113 114 l +f +*U +0.000 0.490 0.408 0.263 k +*u +1070 113 m +1071 112 l +1070 113 l +f +*U +0.000 0.310 0.192 0.196 k +*u +1114 113 m +1115 112 l +1114 113 l +f +*U +0.000 0.106 0.102 0.404 k +*u +1353 113 m +1354 112 l +1353 113 l +f +*U +0.000 0.514 0.431 0.239 k +*u +1395 113 m +1396 112 l +1395 113 l +f +*U +0.000 0.094 0.055 0.329 k +*u +1071 112 m +1072 111 l +1071 112 l +f +*U +0.000 0.643 0.431 0.357 k +*u +1072 112 m +1072.545 110.365 1072.365 110.545 1074 110 c +1074 112 l +1072 112 l +f +*U +0.000 0.467 0.467 0.533 k +*u +1115 112 m +1116 111 l +1115 112 l +f +*U +0.000 0.302 0.318 0.110 k +*u +1116 112 m +1117 111 l +1116 112 l +f +*U +0.000 0.549 0.384 0.451 k +*u +1393 112 m +1394 111 l +1393 112 l +f +*U +0.000 0.220 0.137 0.333 k +*u +1394 112 m +1395 111 l +1394 112 l +f +*U +0.000 0.267 0.165 0.082 k +*u +1072 111 m +1073 110 l +1072 111 l +f +*U +0.000 0.384 0.318 0.251 k +*u +1117 111 m +1118 110 l +1117 111 l +f +*U +0.000 0.310 0.263 0.196 k +*u +1350 111 m +1351 110 l +1350 111 l +f +*U +0.000 0.471 0.369 0.478 k +*u +1351 111 m +1352 110 l +1351 111 l +f +*U +0.000 0.412 0.275 0.141 k +*u +1393 111 m +1394 110 l +1393 111 l +f +*U +0.000 0.361 0.243 0.016 k +*u +1119 110 m +1120 109 l +1119 110 l +f +*U +0.000 0.278 0.216 0.075 k +*u +1348 110 m +1349 109 l +1348 110 l +f +*U +0.000 0.475 0.333 0.463 k +*u +1388 107 m +1389.949 107.936 1390.550 108.392 1392 110 c +1390 109 1389.450 108.608 1388 107 c +f +*U +0.000 0.235 0.153 0.098 k +*u +1392 110 m +1393 109 l +1392 110 l +f +*U +0.000 0.663 0.537 0.337 k +*u +1075.667 108.667 m +1075.222 108.222 1076.278 108.278 1076.333 108.333 c +1076.778 108.778 1075.722 108.722 1075.667 108.667 c +f +*U +0.000 0.627 0.506 0.373 k +*u +1120 109 m +1120 107 l +1122 107 l +1121.455 108.635 1121.635 108.455 1120 109 c +f +*U +0.000 0.216 0.192 0.125 k +*u +1121 109 m +1122 108 l +1121 109 l +f +*U +0.000 0.369 0.263 0.341 k +*u +1347 109 m +1348 108 l +1347 109 l +f +*U +0.000 0.310 0.235 0.071 k +*u +1391 109 m +1392 108 l +1391 109 l +f +*U +0.000 0.227 0.220 0.212 k +*u +1076 108 m +1077 107 l +1076 108 l +f +*U +0.000 0.584 0.471 0.416 k +*u +1077 108 m +1078 107 l +1077 108 l +f +*U +0.000 0.341 0.275 0.290 k +*u +1122 108 m +1123 107 l +1122 108 l +f +*U +0.000 0.282 0.204 0.133 k +*u +1345 108 m +1346 107 l +1345 108 l +f +*U +0.000 0.184 0.169 0.176 k +*u +1077 107 m +1078 106 l +1077 107 l +f +*U +0.000 0.486 0.408 0.514 k +*u +1078 107 m +1079 106 l +1078 107 l +f +*U +0.000 0.592 0.431 0.392 k +*u +1122.667 106.667 m +1122.222 106.222 1123.278 106.278 1123.333 106.333 c +1123.778 106.778 1122.722 106.722 1122.667 106.667 c +f +*U +0.000 0.380 0.282 0.082 k +*u +1124 107 m +1125 106 l +1124 107 l +f +*U +0.000 0.620 0.447 0.353 k +*u +1344.667 106.667 m +1344.223 106.223 1345.278 106.278 1345.333 106.333 c +1345.778 106.778 1344.722 106.722 1344.667 106.667 c +f +*U +0.000 0.561 0.455 0.439 k +*u +1387 107 m +1388 106 l +1387 107 l +f +*U +0.000 0.322 0.243 0.267 k +*u +1388 107 m +1389 106 l +1388 107 l +f +*U +0.000 0.663 0.518 0.271 k +*u +1079 106 m +1080.543 104.733 1081 104.511 1083 104 c +1081.457 105.267 1080.952 105.489 1079 106 c +f +*U +0.000 0.761 0.576 0.239 k +*u +1125 106 m +1125.980 104.217 1125.908 104.406 1128 104 c +1126.861 105 1126.388 105.309 1125 106 c +f +*U +0.000 0.275 0.235 0.161 k +*u +1126 106 m +1127 105 l +1126 106 l +f +*U +0.000 0.373 0.255 0.208 k +*u +1342 106 m +1343 105 l +1342 106 l +f +*U +0.000 0.365 0.290 0.635 k +*u +1343 106 m +1344 105 l +1343 106 l +f +*U +0.000 0.455 0.404 0.545 k +*u +1386 106 m +1387 105 l +1386 106 l +f +*U +0.000 0.298 0.239 0.278 k +*u +1387 106 m +1388 105 l +1387 106 l +f +*U +0.102 0.000 0.027 0.137 k +*u +1128 105 m +1129 104 l +1128 105 l +f +*U +0.000 0.251 0.161 0.129 k +*u +1340 105 m +1341 104 l +1340 105 l +f +*U +0.000 0.655 0.506 0.345 k +*u +1341.667 104.667 m +1341.222 104.223 1342.278 104.278 1342.333 104.333 c +1342.778 104.778 1341.722 104.722 1341.667 104.667 c +f +*U +0.000 0.490 0.471 0.510 k +*u +1385 105 m +1386 104 l +1385 105 l +f +*U +0.000 0.286 0.251 0.141 k +*u +1386 105 m +1387 104 l +1386 105 l +f +*U +0.000 0.098 0.067 0.231 k +*u +1081 104 m +1082 103 l +1081 104 l +f +*U +0.000 0.455 0.322 0.545 k +*u +1082 104 m +1083 103 l +1082 104 l +f +*U +0.000 0.510 0.384 0.490 k +*u +1128 104 m +1129 103 l +1128 104 l +f +*U +0.000 0.439 0.310 0.278 k +*u +1129 104 m +1130 103 l +1129 104 l +f +*U +0.000 0.580 0.490 0.420 k +*u +1338 102 m +1339.581 102.684 1339.777 102.804 1341 104 c +1339.420 103.317 1339.223 103.195 1338 102 c +f +*U +0.000 0.753 0.686 0.192 k +*u +1380 104 m +1380 100 l +1384 102 l +1382.542 103 1381.752 103.436 1380 104 c +f +*U +0.000 0.075 0.039 0.651 k +*u +1384 104 m +1385 103 l +1384 104 l +f +*U +0.000 0.678 0.486 0.322 k +*u +1083.667 102.667 m +1083.222 102.222 1084.278 102.278 1084.333 102.333 c +1084.778 102.778 1083.722 102.722 1083.667 102.667 c +f +*U +0.000 0.463 0.361 0.537 k +*u +1130 103 m +1131 102 l +1130 103 l +f +*U +0.000 0.325 0.235 0.329 k +*u +1131 103 m +1132 102 l +1131 103 l +f +*U +0.000 0.322 0.267 0.361 k +*u +1337 103 m +1338 102 l +1337 103 l +f +*U +0.000 0.365 0.259 0.322 k +*u +1084 102 m +1085 101 l +1084 102 l +f +*U +0.000 0.561 0.451 0.439 k +*u +1085 102 m +1086 101 l +1085 102 l +f +*U +0.000 0.522 0.388 0.478 k +*u +1132 102 m +1133 101 l +1132 102 l +f +*U +0.000 0.325 0.224 0.337 k +*u +1133 102 m +1134 101 l +1133 102 l +f +*U +0.000 0.294 0.247 0.306 k +*u +1335 102 m +1336 101 l +1335 102 l +f +*U +0.000 0.620 0.514 0.380 k +*u +1336.667 101.667 m +1336.222 101.223 1337.278 101.278 1337.333 101.333 c +1337.778 101.778 1336.722 101.722 1336.667 101.667 c +f +*U +0.000 0.306 0.337 0.243 k +*u +1382 102 m +1383 101 l +1382 102 l +f +*U +0.000 0.255 0.188 0.098 k +*u +1085 101 m +1086 100 l +1085 101 l +f +*U +0.000 0.651 0.514 0.349 k +*u +1133 101 m +1134.543 99.733 1135 99.511 1137 99 c +1135.542 100 1134.752 100.436 1133 101 c +f +*U +0.000 0.388 0.282 0.212 k +*u +1135 101 m +1136 100 l +1135 101 l +f +*U +0.000 0.286 0.267 0.306 k +*u +1333 101 m +1334 100 l +1333 101 l +f +*U +0.000 0.494 0.471 0.506 k +*u +1334 101 m +1335 100 l +1334 101 l +f +*U +0.000 0.224 0.216 0.235 k +*u +1381 101 m +1382 100 l +1381 101 l +f +*U +0.000 0.329 0.235 0.525 k +*u +1087 100 m +1088 99 l +1087 100 l +f +*U +0.000 0.392 0.247 0.267 k +*u +1137 100 m +1138 99 l +1137 100 l +f +*U +0.000 0.278 0.231 0.239 k +*u +1331 100 m +1332 99 l +1331 100 l +f +*U +0.000 0.631 0.502 0.369 k +*u +1332.667 99.667 m +1332.222 99.222 1333.278 99.278 1333.333 99.333 c +1333.778 99.778 1332.722 99.722 1332.667 99.667 c +f +*U +0.000 0.722 0.600 0.204 k +*u +1373 96 m +1375.403 96.628 1376.958 97.562 1379 99 c +1376 99.483 1374.593 98.410 1373 96 c +f +*U +0.000 0.392 0.235 0.275 k +*u +1379 100 m +1380 99 l +1379 100 l +f +*U +0.000 0.533 0.361 0.165 k +*u +1088 99 m +1089 98 l +1088 99 l +f +*U +0.000 0.584 0.471 0.416 k +*u +1089 99 m +1090.223 97.805 1090.420 97.684 1092 97 c +1090.777 98.195 1090.580 98.316 1089 99 c +f +*U +0.000 0.478 0.392 0.522 k +*u +1138 99 m +1139 98 l +1138 99 l +f +*U +0.000 0.294 0.239 0.318 k +*u +1139 99 m +1140 98 l +1139 99 l +f +*U +0.000 0.251 0.208 0.165 k +*u +1329 99 m +1330 98 l +1329 99 l +f +*U +0.000 0.647 0.533 0.353 k +*u +1330.667 98.667 m +1330.222 98.223 1331.278 98.278 1331.333 98.333 c +1331.778 98.778 1330.722 98.722 1330.667 98.667 c +f +*U +0.000 0.243 0.235 0.357 k +*u +1378 99 m +1379 98 l +1378 99 l +f +*U +0.000 0.396 0.318 0.220 k +*u +1141 98 m +1142 97 l +1141 98 l +f +*U +0.000 0.278 0.235 0.239 k +*u +1327 98 m +1328 97 l +1327 98 l +f +*U +0.000 0.635 0.475 0.329 k +*u +1328.667 97.667 m +1328.222 97.222 1329.278 97.278 1329.333 97.333 c +1329.778 97.778 1328.722 97.722 1328.667 97.667 c +f +*U +0.000 0.349 0.271 0.506 k +*u +1376 98 m +1377 97 l +1376 98 l +f +*U +0.000 0.247 0.161 0.118 k +*u +1377 98 m +1378 97 l +1377 98 l +f +*U +0.000 0.482 0.420 0.114 k +*u +1091 97 m +1092 96 l +1091 97 l +f +*U +0.000 0.541 0.541 0.459 k +*u +1092 97 m +1093 96 l +1092 97 l +f +*U +0.000 0.588 0.459 0.412 k +*u +1141.667 96.667 m +1141.222 96.222 1142.278 96.278 1142.333 96.333 c +1142.778 96.778 1141.722 96.722 1141.667 96.667 c +f +*U +0.000 0.263 0.204 0.145 k +*u +1325 97 m +1326 96 l +1325 97 l +f +*U +0.000 0.522 0.396 0.392 k +*u +1326.667 96.667 m +1326.222 96.223 1327.278 96.278 1327.333 96.333 c +1327.778 96.778 1326.722 96.722 1326.667 96.667 c +f +*U +0.000 0.725 0.518 0.275 k +*u +1333.667 96.667 m +1333.222 96.222 1334.278 96.278 1334.333 96.333 c +1334.778 96.778 1333.722 96.722 1333.667 96.667 c +f +*U +0.000 0.514 0.337 0.435 k +*u +1093 96 m +1094 94.985 1094.611 94.691 1096 94 c +1095 95.783 1095 95.594 1093 96 c +f +*U +0.000 0.365 0.267 0.031 k +*u +1146 96 m +1147 95 l +1146 96 l +f +*U +0.000 0.416 0.322 0.243 k +*u +1323 96 m +1324 95 l +1323 96 l +f +*U +0.000 0.482 0.376 0.518 k +*u +1373 96 m +1374 95 l +1373 96 l +f +*U +0.000 0.224 0.169 0.196 k +*u +1374 96 m +1375 95 l +1374 96 l +f +*U +0.000 0.427 0.286 0.114 k +*u +1094 95 m +1095 94 l +1094 95 l +f +*U +0.000 0.522 0.369 0.475 k +*u +1146.667 94.667 m +1146.222 94.222 1147.278 94.278 1147.333 94.333 c +1147.778 94.778 1146.722 94.722 1146.667 94.667 c +f +*U +0.000 0.349 0.251 0.094 k +*u +1148 95 m +1149 94 l +1148 95 l +f +*U +0.000 0.353 0.267 0.082 k +*u +1320 95 m +1321 94 l +1320 95 l +f +*U +0.000 0.627 0.455 0.310 k +*u +1321.667 94.667 m +1321.222 94.222 1322.278 94.278 1322.333 94.333 c +1322.778 94.778 1321.722 94.722 1321.667 94.667 c +f +*U +0.000 0.690 0.506 0.294 k +*u +1326 95 m +1326.545 93.365 1326.365 93.545 1328 93 c +1328 95 l +1326 95 l +f +*U +0.000 0.412 0.318 0.451 k +*u +1372 95 m +1373 94 l +1372 95 l +f +*U +0.000 0.204 0.133 0.133 k +*u +1095 94 m +1096 93 l +1095 94 l +f +*U +0.000 0.471 0.392 0.529 k +*u +1096 94 m +1097 93 l +1096 94 l +f +*U +0.000 0.471 0.349 0.529 k +*u +1149 94 m +1150 93 l +1149 94 l +f +*U +0.000 0.278 0.204 0.329 k +*u +1150 94 m +1151 93 l +1150 94 l +f +*U +0.000 0.357 0.255 0.016 k +*u +1318 94 m +1319 93 l +1318 94 l +f +*U +0.000 0.565 0.475 0.435 k +*u +1370 94 m +1371 93 l +1370 94 l +f +*U +0.000 0.353 0.275 0.047 k +*u +1371 94 m +1372 93 l +1371 94 l +f +*U +0.000 0.349 0.251 0.322 k +*u +1097 93 m +1098 92 l +1097 93 l +f +*U +0.000 0.427 0.302 0.478 k +*u +1151.667 92.667 m +1151.222 92.222 1152.278 92.278 1152.333 92.333 c +1152.778 92.778 1151.722 92.722 1151.667 92.667 c +f +*U +0.000 0.212 0.161 0.153 k +*u +1153 93 m +1154 92 l +1153 93 l +f +*U +0.000 0.282 0.227 0.263 k +*u +1316 93 m +1317 92 l +1316 93 l +f +*U +0.000 0.431 0.431 0.569 k +*u +1368 93 m +1369 92 l +1368 93 l +f +*U +0.000 0.431 0.325 0.361 k +*u +1369 93 m +1370 92 l +1369 93 l +f +*U +0.000 0.125 0.102 0.129 k +*u +1098 92 m +1099 91 l +1098 92 l +f +*U +0.000 0.682 0.545 0.318 k +*u +1099.667 91.667 m +1099.222 91.222 1100.278 91.278 1100.333 91.333 c +1100.778 91.778 1099.722 91.722 1099.667 91.667 c +f +*U +0.000 0.737 0.545 0.263 k +*u +1152 92 m +1153.458 90.919 1154.248 90.564 1156 90 c +1154.457 91.267 1153.952 91.489 1152 92 c +f +*U +0.000 0.431 0.306 0.275 k +*u +1155 92 m +1156 91 l +1155 92 l +f +*U +0.000 0.051 0.055 0.149 k +*u +1156 92 m +1157 91 l +1156 92 l +f +*U +0.000 0.243 0.184 0.149 k +*u +1313 92 m +1314 91 l +1313 92 l +f +*U +0.000 0.624 0.478 0.333 k +*u +1314.667 91.667 m +1314.222 91.223 1315.278 91.278 1315.333 91.333 c +1315.778 91.778 1314.722 91.722 1314.667 91.667 c +f +*U +0.000 0.639 0.475 0.361 k +*u +1366.667 91.667 m +1366.223 91.223 1367.278 91.278 1367.333 91.333 c +1367.778 91.778 1366.722 91.722 1366.667 91.667 c +f +*U +0.000 0.184 0.153 0.263 k +*u +1368 92 m +1369 91 l +1368 92 l +f +*U +0.000 0.341 0.247 0.271 k +*u +1100 91 m +1101 90 l +1100 91 l +f +*U +0.000 0.737 0.573 0.263 k +*u +1101.667 90.667 m +1101.222 90.222 1102.278 90.278 1102.333 90.333 c +1102.778 90.778 1101.722 90.722 1101.667 90.667 c +f +*U +0.000 0.443 0.333 0.486 k +*u +1156.667 90.667 m +1156.222 90.222 1157.278 90.278 1157.333 90.333 c +1157.778 90.778 1156.722 90.722 1156.667 90.667 c +f +*U +0.000 0.227 0.196 0.204 k +*u +1158 91 m +1159 90 l +1158 91 l +f +*U +0.000 0.259 0.231 0.192 k +*u +1311 91 m +1312 90 l +1311 91 l +f +*U +0.000 0.392 0.282 0.435 k +*u +1365.667 90.667 m +1365.222 90.222 1366.278 90.278 1366.333 90.333 c +1366.778 90.778 1365.722 90.722 1365.667 90.667 c +f +*U +0.000 0.435 0.365 0.565 k +*u +1102.667 89.667 m +1102.222 89.222 1103.278 89.278 1103.333 89.333 c +1103.778 89.778 1102.722 89.722 1102.667 89.667 c +f +*U +0.000 0.451 0.451 0.549 k +*u +1159 90 m +1160 89 l +1159 90 l +f +*U +0.000 0.286 0.184 0.475 k +*u +1160 90 m +1161 89 l +1160 90 l +f +*U +0.000 0.263 0.173 0.118 k +*u +1161 90 m +1162 89 l +1161 90 l +f +*U +0.000 0.298 0.243 0.204 k +*u +1308 90 m +1309 89 l +1308 90 l +f +*U +0.000 0.580 0.447 0.408 k +*u +1309 90 m +1310.249 89.315 1310.548 89.251 1312 89 c +1310.752 89.685 1310.452 89.749 1309 90 c +f +*U +0.000 0.541 0.408 0.459 k +*u +1363 90 m +1363 88 l +1364.635 88.545 1364.455 88.365 1365 90 c +1363 90 l +f +*U +0.000 0.322 0.235 0.035 k +*u +1365 90 m +1366 89 l +1365 90 l +f +*U +0.067 0.000 0.067 0.176 k +*u +1103 89 m +1104 88 l +1103 89 l +f +*U +0.000 0.475 0.329 0.525 k +*u +1161.667 88.667 m +1161.222 88.222 1162.278 88.278 1162.333 88.333 c +1162.778 88.778 1161.722 88.722 1161.667 88.667 c +f +*U +0.000 0.278 0.176 0.412 k +*u +1163 89 m +1164 88 l +1163 89 l +f +*U +0.000 0.094 0.059 0.137 k +*u +1164 89 m +1165 88 l +1164 89 l +f +*U +0.000 0.094 0.055 0.208 k +*u +1305 89 m +1306 88 l +1305 89 l +f +*U +0.000 0.580 0.447 0.420 k +*u +1306.667 88.667 m +1306.222 88.222 1307.278 88.278 1307.333 88.333 c +1307.778 88.778 1306.722 88.722 1306.667 88.667 c +f +*U +0.000 0.271 0.200 0.349 k +*u +1105 88 m +1106 87 l +1105 88 l +f +*U +0.000 0.690 0.557 0.310 k +*u +1106.667 87.667 m +1106.222 87.222 1107.278 87.278 1107.333 87.333 c +1107.778 87.778 1106.722 87.722 1106.667 87.667 c +f +*U +0.000 0.588 0.447 0.412 k +*u +1164.667 87.667 m +1164.222 87.222 1165.278 87.278 1165.333 87.333 c +1165.778 87.778 1164.722 87.722 1164.667 87.667 c +f +*U +0.000 0.710 0.522 0.255 k +*u +1165 87 m +1166.506 86.317 1167.315 86.174 1169 86 c +1167.265 87 1167 87 1165 87 c +f +*U +0.000 0.486 0.365 0.000 k +*u +1167 88 m +1168 87 l +1167 88 l +f +*U +0.000 0.235 0.263 0.090 k +*u +1302 88 m +1303 87 l +1302 88 l +f +*U +0.000 0.298 0.314 0.455 k +*u +1303 88 m +1304 87 l +1303 88 l +f +*U +0.000 0.400 0.255 0.498 k +*u +1360.667 87.667 m +1360.222 87.222 1361.278 87.278 1361.333 87.333 c +1361.778 87.778 1360.722 87.722 1360.667 87.667 c +f +*U +0.000 0.220 0.141 0.165 k +*u +1362 88 m +1363 87 l +1362 88 l +f +*U +0.000 0.329 0.251 0.416 k +*u +1107 87 m +1108 86 l +1107 87 l +f +*U +0.000 0.494 0.345 0.235 k +*u +1169 87 m +1170 86 l +1169 87 l +f +*U +0.000 0.263 0.192 0.000 k +*u +1170 87 m +1171 86 l +1170 87 l +f +*U +0.000 0.271 0.227 0.118 k +*u +1299 87 m +1300 86 l +1299 87 l +f +*U +0.000 0.431 0.349 0.404 k +*u +1300 87 m +1301 86 l +1300 87 l +f +*U +0.000 0.612 0.545 0.388 k +*u +1301.667 86.667 m +1301.222 86.222 1302.278 86.278 1302.333 86.333 c +1302.778 86.778 1301.722 86.722 1301.667 86.667 c +f +*U +0.000 0.329 0.216 0.224 k +*u +1360 87 m +1361 86 l +1360 87 l +f +*U +0.000 0.263 0.192 0.078 k +*u +1108 86 m +1109 85 l +1108 86 l +f +*U +0.000 0.612 0.498 0.388 k +*u +1109.667 85.667 m +1109.222 85.222 1110.278 85.278 1110.333 85.333 c +1110.778 85.778 1109.722 85.722 1109.667 85.667 c +f +*U +0.000 0.616 0.486 0.384 k +*u +1170.667 85.667 m +1170.222 85.222 1171.278 85.278 1171.333 85.333 c +1171.778 85.778 1170.722 85.722 1170.667 85.667 c +f +*U +0.000 0.322 0.220 0.106 k +*u +1173 86 m +1174 85 l +1173 86 l +f +*U +0.000 0.369 0.314 0.224 k +*u +1296 86 m +1297 85 l +1296 86 l +f +*U +0.000 0.565 0.447 0.435 k +*u +1297.667 85.667 m +1297.223 85.223 1298.278 85.278 1298.333 85.333 c +1298.778 85.778 1297.722 85.722 1297.667 85.667 c +f +*U +0.000 0.416 0.294 0.502 k +*u +1358 86 m +1359 85 l +1358 86 l +f +*U +0.000 0.294 0.220 0.016 k +*u +1110 85 m +1111 84 l +1110 85 l +f +*U +0.000 0.737 0.561 0.263 k +*u +1111.667 84.667 m +1111.222 84.222 1112.278 84.278 1112.333 84.333 c +1112.778 84.778 1111.722 84.722 1111.667 84.667 c +f +*U +0.000 0.439 0.349 0.561 k +*u +1174.667 84.667 m +1174.222 84.223 1175.278 84.278 1175.333 84.333 c +1175.778 84.778 1174.722 84.722 1174.667 84.667 c +f +*U +0.000 0.259 0.192 0.306 k +*u +1176 85 m +1177 84 l +1176 85 l +f +*U +0.000 0.208 0.169 0.098 k +*u +1177 85 m +1178 84 l +1177 85 l +f +*U +0.000 0.110 0.090 0.192 k +*u +1292 85 m +1293 84 l +1292 85 l +f +*U +0.000 0.753 0.588 0.247 k +*u +1288 83 m +1291 82 1293.942 82.554 1296 85 c +1293.225 84.590 1290.673 83.851 1288 83 c +f +*U +0.000 0.545 0.388 0.455 k +*u +1356 85 m +1357 84 l +1356 85 l +f +*U +0.000 0.243 0.180 0.141 k +*u +1357 85 m +1358 84 l +1357 85 l +f +*U +0.000 0.447 0.322 0.239 k +*u +1112 84 m +1113 83 l +1112 84 l +f +*U +0.000 0.533 0.380 0.467 k +*u +1113 84 m +1114 83 l +1113 84 l +f +*U +0.000 0.663 0.565 0.271 k +*u +1176 84 m +1177.377 83 1178.440 82.596 1180 82 c +1178.686 83.618 1178 83.693 1176 84 c +f +*U +0.000 0.373 0.357 0.239 k +*u +1180 84 m +1181 83 l +1180 84 l +f +*U +0.000 0.208 0.227 0.055 k +*u +1181 84 m +1182 83 l +1181 84 l +f +*U +0.000 0.173 0.137 0.153 k +*u +1288 84 m +1289 83 l +1288 84 l +f +*U +0.000 0.310 0.224 0.290 k +*u +1289 84 m +1290 83 l +1289 84 l +f +*U +0.000 0.557 0.427 0.443 k +*u +1354 84 m +1355 83 l +1354 84 l +f +*U +0.000 0.294 0.216 0.349 k +*u +1355 84 m +1356 83 l +1355 84 l +f +*U +0.000 0.549 0.420 0.451 k +*u +1114.667 82.667 m +1114.222 82.222 1115.278 82.278 1115.333 82.333 c +1115.778 82.778 1114.722 82.722 1114.667 82.667 c +f +*U +0.000 0.612 0.514 0.388 k +*u +1180 83 m +1181.506 82.317 1182.315 82.174 1184 82 c +1182.494 82.683 1181.685 82.826 1180 83 c +f +*U +0.000 0.196 0.141 0.314 k +*u +1184 83 m +1185 82 l +1184 83 l +f +*U +0.000 0.188 0.141 0.137 k +*u +1185 83 m +1186 82 l +1185 83 l +f +*U +0.000 0.255 0.188 0.051 k +*u +1284 83 m +1285 82 l +1284 83 l +f +*U +0.000 0.333 0.239 0.255 k +*u +1285 83 m +1286 82 l +1285 83 l +f +*U +0.000 0.424 0.302 0.569 k +*u +1287 83 m +1288 82 l +1287 83 l +f +*U +0.000 0.565 0.431 0.373 k +*u +1348 81 m +1350.274 80.591 1351.781 81.212 1354 82 c +1351.538 82.697 1350.335 82 1348 81 c +f +*U +0.000 0.184 0.141 0.086 k +*u +1115 82 m +1116 81 l +1115 82 l +f +*U +0.000 0.584 0.408 0.365 k +*u +1116 82 m +1117.458 80.919 1118.248 80.564 1120 80 c +1118.457 81.267 1117.952 81.489 1116 82 c +f +*U +0.000 0.678 0.498 0.322 k +*u +1185 82 m +1186.249 81.315 1186.548 81.251 1188 81 c +1186.752 81.685 1186.451 81.749 1185 82 c +f +*U +0.000 0.388 0.275 0.322 k +*u +1188 82 m +1189 81 l +1188 82 l +f +*U +0.000 0.212 0.161 0.212 k +*u +1189 82 m +1190 81 l +1189 82 l +f +*U +0.000 0.416 0.286 0.078 k +*u +1280 82 m +1281 81 l +1280 82 l +f +*U +0.000 0.600 0.451 0.400 k +*u +1281 82 m +1282.769 81.221 1284 81 1286 81 c +1284.231 81.779 1282.964 81.912 1281 82 c +f +*U +0.000 0.059 0.043 0.149 k +*u +1352 82 m +1353 81 l +1352 82 l +f +*U +0.000 0.278 0.212 0.090 k +*u +1117 81 m +1118 80 l +1117 81 l +f +*U +0.000 0.667 0.537 0.333 k +*u +1190.667 80.667 m +1190.222 80.222 1191.278 80.278 1191.333 80.333 c +1191.778 80.778 1190.722 80.722 1190.667 80.667 c +f +*U +0.000 0.361 0.243 0.639 k +*u +1192 81 m +1193 80 l +1192 81 l +f +*U +0.000 0.345 0.224 0.439 k +*u +1193 81 m +1194 80 l +1193 81 l +f +*U +0.000 0.263 0.173 0.255 k +*u +1194 81 m +1195 80 l +1194 81 l +f +*U +0.000 0.153 0.098 0.129 k +*u +1195 81 m +1196 80 l +1195 81 l +f +*U +0.000 0.157 0.098 0.255 k +*u +1275 81 m +1276 80 l +1275 81 l +f +*U +0.000 0.349 0.227 0.322 k +*u +1276 81 m +1277 80 l +1276 81 l +f +*U +0.000 0.612 0.435 0.388 k +*u +1277 81 m +1278.249 80.315 1278.548 80.251 1280 80 c +1278.752 80.685 1278.452 80.749 1277 81 c +f +*U +0.000 0.310 0.267 0.129 k +*u +1350 81 m +1351 80 l +1350 81 l +f +*U +0.000 0.416 0.345 0.584 k +*u +1120.667 79.667 m +1120.222 79.222 1121.278 79.278 1121.333 79.333 c +1121.778 79.778 1120.722 79.722 1120.667 79.667 c +f +*U +0.000 0.278 0.227 0.098 k +*u +1268 80 m +1269.249 79.315 1269.548 79.251 1271 79 c +1269.752 79.685 1269.452 79.749 1268 80 c +f +*U +0.000 0.737 0.541 0.263 k +*u +1268 79 m +1270.698 78 1273 78.647 1276 79 c +1273.244 80 1270.893 79.532 1268 79 c +f +*U +0.000 0.302 0.196 0.569 k +*u +1346.667 79.667 m +1346.223 79.223 1347.278 79.278 1347.333 79.333 c +1347.778 79.778 1346.722 79.722 1346.667 79.667 c +f +*U +0.000 0.102 0.063 0.220 k +*u +1348 80 m +1349 79 l +1348 80 l +f +*U +0.000 0.176 0.141 0.110 k +*u +1121 79 m +1122 78 l +1121 79 l +f +*U +0.000 0.616 0.478 0.384 k +*u +1122.667 78.667 m +1122.222 78.222 1123.278 78.278 1123.333 78.333 c +1123.778 78.778 1122.722 78.722 1122.667 78.667 c +f +*U +0.000 0.514 0.392 0.486 k +*u +1202 79 m +1203.249 78.315 1203.548 78.251 1205 78 c +1203.752 78.685 1203.452 78.749 1202 79 c +f +*U +0.000 0.259 0.180 0.251 k +*u +1205.667 78.667 m +1205.222 78.222 1206.278 78.278 1206.333 78.333 c +1206.778 78.778 1205.722 78.722 1205.667 78.667 c +f +*U +0.000 0.063 0.039 0.149 k +*u +1207.667 78.667 m +1207.222 78.222 1208.278 78.278 1208.333 78.333 c +1208.778 78.778 1207.722 78.722 1207.667 78.667 c +f +*U +0.000 0.188 0.133 0.184 k +*u +1260.667 78.667 m +1260.222 78.223 1261.278 78.278 1261.333 78.333 c +1261.778 78.778 1260.722 78.722 1260.667 78.667 c +f +*U +0.000 0.239 0.161 0.322 k +*u +1262.667 78.667 m +1262.222 78.222 1263.278 78.278 1263.333 78.333 c +1263.778 78.778 1262.722 78.722 1262.667 78.667 c +f +*U +0.000 0.569 0.392 0.384 k +*u +1264 79 m +1265.506 78.317 1266.315 78.174 1268 78 c +1266.494 78.683 1265.685 78.826 1264 79 c +f +*U +0.000 0.561 0.369 0.439 k +*u +1344.667 78.667 m +1344.223 78.223 1345.278 78.278 1345.333 78.333 c +1345.778 78.778 1344.722 78.722 1344.667 78.667 c +f +*U +0.000 0.373 0.247 0.118 k +*u +1346 79 m +1347 78 l +1346 79 l +f +*U +0.000 0.627 0.463 0.373 k +*u +1124.667 77.667 m +1124.222 77.222 1125.278 77.278 1125.333 77.333 c +1125.778 77.778 1124.722 77.722 1124.667 77.667 c +f +*U +0.000 0.627 0.439 0.373 k +*u +1208 78 m +1209.249 77.315 1209.548 77.251 1211 77 c +1209.752 77.685 1209.452 77.749 1208 78 c +f +*U +0.000 0.482 0.416 0.518 k +*u +1211 78 m +1212.249 77.315 1212.548 77.251 1214 77 c +1212.752 77.685 1212.452 77.749 1211 78 c +f +*U +0.000 0.278 0.231 0.224 k +*u +1215.667 77.667 m +1215.222 77.222 1216.278 77.278 1216.333 77.333 c +1216.778 77.778 1215.722 77.722 1215.667 77.667 c +f +*U +0.000 0.231 0.192 0.137 k +*u +1217 78 m +1218.506 77.317 1219.315 77.174 1221 77 c +1219.494 77.683 1218.685 77.826 1217 78 c +f +*U +0.000 0.212 0.082 0.129 k +*u +1249 78 m +1250.506 77.317 1251.315 77.174 1253 77 c +1251.494 77.683 1250.685 77.826 1249 78 c +f +*U +0.000 0.349 0.251 0.216 k +*u +1253 78 m +1254.249 77.315 1254.548 77.251 1256 77 c +1254.752 77.685 1254.451 77.749 1253 78 c +f +*U +0.000 0.506 0.416 0.494 k +*u +1256 78 m +1257.249 77.315 1257.548 77.251 1259 77 c +1257.752 77.685 1257.451 77.749 1256 78 c +f +*U +0.000 0.702 0.537 0.298 k +*u +1259 78 m +1260.249 77.315 1260.548 77.251 1262 77 c +1260.752 77.685 1260.452 77.749 1259 78 c +f +*U +0.000 0.631 0.471 0.325 k +*u +1341 78 m +1342.249 77.315 1342.548 77.251 1344 77 c +1342.752 77.685 1342.451 77.749 1341 78 c +f +*U +0.000 0.204 0.129 0.286 k +*u +1344 78 m +1345 77 l +1344 78 l +f +*U +0.000 0.255 0.188 0.047 k +*u +1125 77 m +1126 76 l +1125 77 l +f +*U +0.000 0.659 0.455 0.314 k +*u +1126 77 m +1127.750 75.745 1128.857 75.386 1131 75 c +1129.249 76.255 1128 76.614 1126 77 c +f +*U +0.000 0.729 0.596 0.271 k +*u +1219 77 m +1220.769 76.221 1222 76 1224 76 c +1222.231 76.779 1220.964 76.912 1219 77 c +f +*U +0.000 0.447 0.353 0.553 k +*u +1224 77 m +1226.613 75.902 1229 76 1232 76 c +1229.387 77 1226.836 76.993 1224 77 c +f +*U +0.000 0.541 0.380 0.447 k +*u +1232 77 m +1234.613 75.902 1237 76 1240 76 c +1237.387 77 1234.835 76.993 1232 77 c +f +*U +0.000 0.478 0.373 0.522 k +*u +1240 77 m +1242.613 75.902 1245 76 1248 76 c +1245.387 77 1242.836 76.993 1240 77 c +f +*U +0.000 0.753 0.690 0.247 k +*u +1248 77 m +1249.249 76.315 1249.548 76.251 1251 76 c +1249.752 76.685 1249.452 76.749 1248 77 c +f +*U +0.000 0.894 0.922 0.078 k +*u +1251 77 m +1252.506 76.317 1253.315 76.174 1255 76 c +1253.494 76.683 1252.685 76.826 1251 77 c +f +*U +0.000 0.427 0.400 0.573 k +*u +1340.667 76.667 m +1340.222 76.222 1341.278 76.278 1341.333 76.333 c +1341.778 76.778 1340.722 76.722 1340.667 76.667 c +f +*U +0.000 0.294 0.247 0.184 k +*u +1342 77 m +1343 76 l +1342 77 l +f +*U +0.000 0.043 0.047 0.216 k +*u +1127 76 m +1128 75 l +1127 76 l +f +*U +0.000 0.533 0.443 0.467 k +*u +1338.667 75.667 m +1338.222 75.222 1339.278 75.278 1339.333 75.333 c +1339.778 75.778 1338.722 75.722 1338.667 75.667 c +f +*U +0.000 0.404 0.322 0.141 k +*u +1340 76 m +1341 75 l +1340 76 l +f +*U +0.000 0.365 0.263 0.231 k +*u +1130 75 m +1131 74 l +1130 75 l +f +*U +0.000 0.733 0.529 0.267 k +*u +1131.667 74.667 m +1131.222 74.222 1132.278 74.278 1132.333 74.333 c +1132.778 74.778 1131.722 74.722 1131.667 74.667 c +f +*U +0.000 0.510 0.400 0.447 k +*u +1336.667 74.667 m +1336.222 74.223 1337.278 74.278 1337.333 74.333 c +1337.778 74.778 1336.722 74.722 1336.667 74.667 c +f +*U +0.000 0.325 0.271 0.063 k +*u +1338 75 m +1339 74 l +1338 75 l +f +*U +0.000 0.349 0.243 0.271 k +*u +1132 74 m +1133 73 l +1132 74 l +f +*U +0.000 0.722 0.486 0.278 k +*u +1133 74 m +1134 72.985 1134.611 72.691 1136 72 c +1135 73.783 1135 73.594 1133 74 c +f +*U +0.000 0.565 0.549 0.357 k +*u +1331 73 m +1332.846 72.533 1334 72.699 1336 73 c +1333.955 73.775 1333 73.592 1331 73 c +f +*U +0.000 0.208 0.196 0.208 k +*u +1336 74 m +1337 73 l +1336 74 l +f +*U +0.000 0.427 0.278 0.000 k +*u +1134 73 m +1135 72 l +1134 73 l +f +*U +0.000 0.341 0.369 0.298 k +*u +1333 73 m +1334 72 l +1333 73 l +f +*U +0.000 0.137 0.173 0.098 k +*u +1334 73 m +1335 72 l +1334 73 l +f +*U +0.000 0.239 0.110 0.118 k +*u +1136 72 m +1137 71 l +1136 72 l +f +*U +0.000 0.345 0.200 0.396 k +*u +1137 72 m +1138 71 l +1137 72 l +f +*U +0.000 0.757 0.545 0.243 k +*u +1138 72 m +1139.750 70.745 1140.857 70.386 1143 70 c +1141.212 71.421 1140.294 71.697 1138 72 c +f +*U +0.000 0.788 0.620 0.212 k +*u +1326 70 m +1329 70 l +1328 72 l +1326.365 71.455 1326.545 71.635 1326 70 c +f +*U +0.000 0.486 0.314 0.514 k +*u +1329.667 71.667 m +1329.222 71.222 1330.278 71.278 1330.333 71.333 c +1330.778 71.778 1329.722 71.722 1329.667 71.667 c +f +*U +0.000 0.239 0.141 0.333 k +*u +1331 72 m +1332 71 l +1331 72 l +f +*U +0.000 0.271 0.169 0.290 k +*u +1139 71 m +1140 70 l +1139 71 l +f +*U +0.000 0.376 0.255 0.000 k +*u +1329 71 m +1330 70 l +1329 71 l +f +*U +0.000 0.463 0.325 0.271 k +*u +1142 70 m +1143 69 l +1142 70 l +f +*U +0.000 0.714 0.573 0.286 k +*u +1143.667 69.667 m +1143.222 69.222 1144.278 69.278 1144.333 69.333 c +1144.778 69.778 1143.722 69.722 1143.667 69.667 c +f +*U +0.000 0.333 0.255 0.282 k +*u +1326 70 m +1327 69 l +1326 70 l +f +*U +0.000 0.431 0.322 0.180 k +*u +1144 69 m +1145 68 l +1144 69 l +f +*U +0.000 0.545 0.420 0.455 k +*u +1145.667 68.667 m +1145.222 68.223 1146.278 68.278 1146.333 68.333 c +1146.778 68.778 1145.722 68.722 1145.667 68.667 c +f +*U +0.000 0.263 0.192 0.102 k +*u +1324 69 m +1325 68 l +1324 69 l +f +*U +0.000 0.267 0.200 0.275 k +*u +1147 68 m +1148 67 l +1147 68 l +f +*U +0.000 0.616 0.490 0.384 k +*u +1148.667 67.667 m +1148.222 67.222 1149.278 67.278 1149.333 67.333 c +1149.778 67.778 1148.722 67.722 1148.667 67.667 c +f +*U +0.000 0.796 0.620 0.204 k +*u +1152 68 m +1152.980 66.217 1152.908 66.406 1155 66 c +1153.860 67 1153.388 67.309 1152 68 c +f +*U +0.000 0.710 0.522 0.271 k +*u +1317 68 m +1318.506 67.317 1319.315 67.174 1321 67 c +1319.494 67.683 1318.685 67.826 1317 68 c +f +*U +0.000 0.388 0.278 0.322 k +*u +1321 68 m +1322 67 l +1321 68 l +f +*U +0.000 0.161 0.129 0.145 k +*u +1322 68 m +1323 67 l +1322 68 l +f +*U +0.000 0.286 0.208 0.067 k +*u +1149 67 m +1150 66 l +1149 67 l +f +*U +0.000 0.525 0.365 0.416 k +*u +1150.667 66.667 m +1150.222 66.222 1151.278 66.278 1151.333 66.333 c +1151.778 66.778 1150.722 66.722 1150.667 66.667 c +f +*U +0.000 0.518 0.384 0.447 k +*u +1316.667 66.667 m +1316.222 66.222 1317.278 66.278 1317.333 66.333 c +1317.778 66.778 1316.722 66.722 1316.667 66.667 c +f +*U +0.000 0.263 0.216 0.361 k +*u +1318 67 m +1319 66 l +1318 67 l +f +*U +0.000 0.118 0.122 0.180 k +*u +1319 67 m +1320 66 l +1319 67 l +f +*U +0.000 0.518 0.361 0.129 k +*u +1152 66 m +1153 65 l +1152 66 l +f +*U +0.000 0.576 0.471 0.416 k +*u +1153.667 65.667 m +1153.222 65.222 1154.278 65.278 1154.333 65.333 c +1154.778 65.778 1153.722 65.722 1153.667 65.667 c +f +*U +0.000 0.745 0.659 0.239 k +*u +1155 66 m +1156.789 64.578 1157.706 64.303 1160 64 c +1158.307 65 1156.960 65.520 1155 66 c +f +*U +0.000 0.502 0.341 0.396 k +*u +1312.333 65.333 m +1312.278 65.278 1312.223 64.222 1312.667 64.667 c +1312.722 64.722 1312.778 65.778 1312.333 65.333 c +f +*U +0.000 0.490 0.412 0.510 k +*u +1313 66 m +1314.249 65.315 1314.549 65.251 1316 65 c +1314.752 65.685 1314.451 65.749 1313 66 c +f +*U +0.000 0.333 0.243 0.137 k +*u +1316 66 m +1317 65 l +1316 66 l +f +*U +0.000 0.314 0.373 0.047 k +*u +1155 65 m +1156 64 l +1155 65 l +f +*U +0.000 0.749 0.710 0.251 k +*u +1310.667 64.667 m +1310.222 64.223 1311.278 64.278 1311.333 64.333 c +1311.778 64.778 1310.722 64.722 1310.667 64.667 c +f +*U +0.000 0.388 0.278 0.027 k +*u +1313 65 m +1314 64 l +1313 65 l +f +*U +0.008 0.024 0.000 0.220 k +*u +1158 64 m +1159 63 l +1158 64 l +f +*U +0.004 0.012 0.000 0.549 k +*u +1159 64 m +1160 63 l +1159 64 l +f +*U +0.000 0.631 0.455 0.369 k +*u +1160.667 63.667 m +1160.222 63.222 1161.278 63.278 1161.333 63.333 c +1161.778 63.778 1160.722 63.722 1160.667 63.667 c +f +*U +0.000 0.412 0.337 0.588 k +*u +1307 64 m +1308.249 63.315 1308.548 63.251 1310 63 c +1308.752 63.685 1308.452 63.749 1307 64 c +f +*U +0.000 0.239 0.192 0.153 k +*u +1310 64 m +1311 63 l +1310 64 l +f +*U +0.000 0.204 0.129 0.071 k +*u +1161 63 m +1162 62 l +1161 63 l +f +*U +0.000 0.325 0.216 0.302 k +*u +1162 63 m +1163 62 l +1162 63 l +f +*U +0.000 0.608 0.451 0.392 k +*u +1163 63 m +1164.249 62.315 1164.548 62.251 1166 62 c +1164.752 62.685 1164.451 62.749 1163 63 c +f +*U +0.000 0.576 0.455 0.424 k +*u +1304.667 62.667 m +1304.222 62.222 1305.278 62.278 1305.333 62.333 c +1305.778 62.778 1304.722 62.722 1304.667 62.667 c +f +*U +0.000 0.341 0.259 0.118 k +*u +1307 63 m +1308 62 l +1307 63 l +f +*U +0.000 0.318 0.231 0.129 k +*u +1165 62 m +1166 61 l +1165 62 l +f +*U +0.000 0.392 0.290 0.408 k +*u +1166 62 m +1167 61 l +1166 62 l +f +*U +0.000 0.565 0.420 0.435 k +*u +1167 62 m +1168.249 61.315 1168.548 61.251 1170 61 c +1168.752 61.685 1168.452 61.749 1167 62 c +f +*U +0.000 0.514 0.384 0.486 k +*u +1300 62 m +1301.249 61.315 1301.548 61.251 1303 61 c +1301.752 61.685 1301.451 61.749 1300 62 c +f +*U +0.000 0.322 0.212 0.145 k +*u +1303 62 m +1304 61 l +1303 62 l +f +*U +0.000 0.122 0.055 0.129 k +*u +1168 61 m +1169 60 l +1168 61 l +f +*U +0.000 0.220 0.161 0.318 k +*u +1169 61 m +1170 60 l +1169 61 l +f +*U +0.000 0.580 0.478 0.420 k +*u +1170.667 60.667 m +1170.222 60.222 1171.278 60.278 1171.333 60.333 c +1171.778 60.778 1170.722 60.722 1170.667 60.667 c +f +*U +0.000 0.600 0.431 0.373 k +*u +1293 60 m +1295 59.324 1296.732 59.613 1299 60 c +1296.761 60.811 1295.353 60.529 1293 60 c +f +*U +0.000 0.475 0.369 0.165 k +*u +1299 61 m +1300 60 l +1299 61 l +f +*U +0.000 0.314 0.263 0.047 k +*u +1300 61 m +1301 60 l +1300 61 l +f +*U +0.000 0.141 0.173 0.071 k +*u +1172 60 m +1173 59 l +1172 60 l +f +*U +0.000 0.325 0.255 0.306 k +*u +1173 60 m +1174 59 l +1173 60 l +f +*U +0.000 0.541 0.376 0.459 k +*u +1174 60 m +1175.506 59.317 1176.315 59.174 1178 59 c +1176.494 59.683 1175.685 59.826 1174 60 c +f +*U +0.000 0.161 0.098 0.282 k +*u +1296 60 m +1297 59 l +1296 60 l +f +*U +0.000 0.082 0.078 0.157 k +*u +1176 59 m +1177 58 l +1176 59 l +f +*U +0.000 0.247 0.184 0.239 k +*u +1177 59 m +1178 58 l +1177 59 l +f +*U +0.000 0.561 0.424 0.439 k +*u +1178 59 m +1179.506 58.317 1180.315 58.174 1182 58 c +1180.494 58.683 1179.685 58.826 1178 59 c +f +*U +0.000 0.663 0.486 0.337 k +*u +1288 59 m +1289.249 58.315 1289.548 58.251 1291 58 c +1289.752 58.685 1289.451 58.749 1288 59 c +f +*U +0.000 0.459 0.318 0.227 k +*u +1291 59 m +1292 58 l +1291 59 l +f +*U +0.000 0.129 0.086 0.071 k +*u +1292.667 58.667 m +1292.222 58.222 1293.278 58.278 1293.333 58.333 c +1293.778 58.778 1292.722 58.722 1292.667 58.667 c +f +*U +0.000 0.176 0.125 0.110 k +*u +1181 58 m +1182 57 l +1181 58 l +f +*U +0.000 0.478 0.325 0.267 k +*u +1182 58 m +1183 57 l +1182 58 l +f +*U +0.000 0.490 0.369 0.510 k +*u +1183 58 m +1184.249 57.315 1184.548 57.251 1186 57 c +1184.752 57.685 1184.452 57.749 1183 58 c +f +*U +0.000 0.631 0.498 0.369 k +*u +1282 58 m +1283.769 57.221 1285 57 1287 57 c +1285.231 57.779 1283.964 57.912 1282 58 c +f +*U +0.000 0.541 0.392 0.114 k +*u +1287 58 m +1288 57 l +1287 58 l +f +*U +0.000 0.239 0.157 0.082 k +*u +1186 57 m +1187 56 l +1186 57 l +f +*U +0.000 0.384 0.275 0.290 k +*u +1187 57 m +1188 56 l +1187 57 l +f +*U +0.000 0.573 0.525 0.427 k +*u +1188 57 m +1189.249 56.315 1189.548 56.251 1191 56 c +1189.752 56.685 1189.452 56.749 1188 57 c +f +*U +0.000 0.420 0.361 0.580 k +*u +1280 57 m +1281 56 l +1280 57 l +f +*U +0.000 0.482 0.353 0.216 k +*u +1281 57 m +1282 56 l +1281 57 l +f +*U +0.000 0.282 0.224 0.047 k +*u +1282.667 56.667 m +1282.222 56.222 1283.278 56.278 1283.333 56.333 c +1283.778 56.778 1282.722 56.722 1282.667 56.667 c +f +*U +0.000 0.384 0.259 0.306 k +*u +1192.667 55.667 m +1192.222 55.222 1193.278 55.278 1193.333 55.333 c +1193.778 55.778 1192.722 55.722 1192.667 55.667 c +f +*U +0.000 0.498 0.373 0.502 k +*u +1194.667 55.667 m +1194.222 55.222 1195.278 55.278 1195.333 55.333 c +1195.778 55.778 1194.722 55.722 1194.667 55.667 c +f +*U +0.000 0.749 0.545 0.251 k +*u +1196 56 m +1197.506 55.317 1198.315 55.174 1200 55 c +1198.494 55.683 1197.685 55.826 1196 56 c +f +*U +0.000 0.580 0.431 0.420 k +*u +1272 56 m +1273.506 55.317 1274.315 55.174 1276 55 c +1274.494 55.683 1273.685 55.826 1272 56 c +f +*U +0.000 0.333 0.208 0.333 k +*u +1276 56 m +1277 55 l +1276 56 l +f +*U +0.000 0.137 0.078 0.102 k +*u +1277.667 55.667 m +1277.222 55.222 1278.278 55.278 1278.333 55.333 c +1278.778 55.777 1277.723 55.723 1277.667 55.667 c +f +*U +0.000 0.176 0.125 0.235 k +*u +1198.667 54.667 m +1198.222 54.222 1199.278 54.278 1199.333 54.333 c +1199.778 54.777 1198.723 54.723 1198.667 54.667 c +f +*U +0.000 0.545 0.451 0.455 k +*u +1200 55 m +1201.769 54.221 1203 54 1205 54 c +1203.231 54.779 1201.964 54.912 1200 55 c +f +*U +0.000 0.741 0.620 0.259 k +*u +1216 55 m +1217.314 53.382 1217.877 53.307 1220 53 c +1218.624 53.911 1217.560 54.404 1216 55 c +f +*U +0.000 0.588 0.612 0.388 k +*u +1264.667 54.667 m +1264.222 54.222 1265.278 54.278 1265.333 54.333 c +1265.778 54.777 1264.723 54.723 1264.667 54.667 c +f +*U +0.000 0.420 0.447 0.553 k +*u +1266 55 m +1267.249 54.315 1267.548 54.251 1269 54 c +1267.752 54.685 1267.452 54.749 1266 55 c +f +*U +0.000 0.200 0.333 0.329 k +*u +1269 55 m +1270 54 l +1269 55 l +f +*U +0.000 0.078 0.251 0.157 k +*u +1270.667 54.667 m +1270.222 54.222 1271.278 54.278 1271.333 54.333 c +1271.778 54.777 1270.723 54.723 1270.667 54.667 c +f +*U +0.000 0.122 0.118 0.302 k +*u +1206.667 53.667 m +1206.222 53.222 1207.278 53.278 1207.333 53.333 c +1207.778 53.778 1206.722 53.722 1206.667 53.667 c +f +*U +0.000 0.612 0.510 0.035 k +*u +1208 54 m +1209 53 l +1208 54 l +f +*U +0.000 0.529 0.420 0.471 k +*u +1210 54 m +1212 53 1213.747 53 1216 53 c +1213.948 53.874 1212.253 53.953 1210 54 c +f +*U +0.000 0.557 0.447 0.443 k +*u +1253 54 m +1255.332 53 1257.457 53 1260 53 c +1257.668 53.985 1255.543 53.981 1253 54 c +f +*U +0.000 0.329 0.239 0.192 k +*u +1260 54 m +1261.506 53.317 1262.315 53.174 1264 53 c +1262.494 53.683 1261.685 53.826 1260 54 c +f +*U +0.000 0.345 0.282 0.173 k +*u +1217 53 m +1219.332 52 1221.457 52 1224 52 c +1221.668 52.985 1219.544 52.981 1217 53 c +f +*U +0.000 0.608 0.424 0.227 k +*u +1224.667 52.667 m +1224.222 52.222 1225.278 52.278 1225.333 52.333 c +1225.778 52.778 1224.722 52.722 1224.667 52.667 c +f +*U +0.000 0.525 0.424 0.475 k +*u +1226 53 m +1228 52 1229.747 52 1232 52 c +1229.948 52.874 1228.253 52.953 1226 53 c +f +*U +0.000 0.392 0.392 0.608 k +*u +1232 53 m +1234.613 51.902 1237 52 1240 52 c +1237.387 53 1234.835 52.993 1232 53 c +f +*U +0.000 0.478 0.337 0.506 k +*u +1240 53 m +1241.506 52.317 1242.315 52.174 1244 52 c +1242.494 52.683 1241.685 52.826 1240 53 c +f +*U +0.000 0.467 0.329 0.275 k +*u +1244.667 52.667 m +1244.222 52.222 1245.278 52.278 1245.333 52.333 c +1245.778 52.778 1244.722 52.722 1244.667 52.667 c +f +*U +0.000 0.404 0.286 0.110 k +*u +1246 53 m +1248 52 1249.747 52 1252 52 c +1249.948 52.874 1248.253 52.953 1246 53 c +f +*U +0.000 0.106 0.090 0.067 k +*u +1252.667 52.667 m +1252.222 52.222 1253.278 52.278 1253.333 52.333 c +1253.778 52.777 1252.723 52.723 1252.667 52.667 c +f +*U +%%Trailer +%%EOF diff --git a/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.eps b/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.eps new file mode 100644 index 0000000..fe74ae3 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.eps @@ -0,0 +1,28071 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: Adobe Illustrator by AutoTrace version 0.31.1 +%%Title: /var/www/autotracer.org/temp_dir_m/25f86a2855585e93e61da0f2839bb576/technicalkorea_Logo.eps +%%CreationDate: Tue Jul 1 04:59:13 2025 +%%BoundingBox: 0 0 2094 600 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +/bd { bind def } bind def +/incompound false def +/m { moveto } bd +/l { lineto } bd +/c { curveto } bd +/F { incompound not {fill} if } bd +/f { closepath F } bd +/S { stroke } bd +/*u { /incompound true def } bd +/*U { /incompound false def f} bd +/k { setcmykcolor } bd +/K { k } bd +%%EndProlog +%%BeginSetup +%%EndSetup +0.000 0.000 0.000 0.000 k +*u +0 600 m +0 395 l +2.656 400.517 3 406.612 6.468 412 c +15.646 426.865 33.640 436.640 51 437 c +50 438.783 50 438.594 48 439 c +57.403 441.779 69.218 440 79 440 c +142 440 l +348 440 l +1023 440 l +1013.597 437.221 1001.782 439 992 439 c +929 439 l +724 439 l +53 439 l +59.678 436.198 69.784 438 77 438 c +130 438 l +313 438 l +802 438 l +953 438 l +1000 438 l +1006.746 438 1015.382 436.560 1021.910 438.318 c +1028.865 440.190 1035.484 451.822 1040.170 457 c +1051.647 469.684 1064.752 480.969 1078 491.739 c +1115.698 522.386 1162.655 542.211 1211 546.830 c +1270.668 552.532 1330.755 531 1377 493.540 c +1391.785 481.543 1405.287 468.291 1417.845 454 c +1422.293 448.938 1428.382 437 1435 435.318 c +1440.178 433.942 1446.752 435 1452 435 c +1488 435 l +1603 435 l +1975 435 l +1975 410 l +1598 410 l +1480 410 l +1443 410 l +1436.570 410 1429.295 409 1423 410.529 c +1414.316 412.540 1409.882 421.408 1404.870 428 c +1395.994 439.674 1385.879 450.987 1375 460.830 c +1339.790 492.687 1295.380 518.597 1247 521.911 c +1189.677 525.836 1137.711 505.369 1093 470.338 c +1078.487 458.967 1065.337 445.924 1053.289 432 c +1045.483 422.979 1040.211 412.343 1027 412 c +951.439 410 875.588 412 800 412 c +346 412 l +143 412 l +79 412 l +68.784 412 56.989 413.612 47 411.319 c +25.723 406.435 28 384.934 28 368 c +28 236 l +28 219.459 23.618 191.367 46 188 c +45.350 189.300 45.853 189 44 189 c +48 190 l +47.350 191.300 47.853 191 46 191 c +55.963 193.945 68.631 192 79 192 c +147 192 l +367 192 l +812 192 l +958 192 l +985 192 1013 193.925 1040 191 c +1029 186.711 1017.488 188 1006 188 c +949 188 l +746 188 l +513.345 188 280.567 188.358 48 189 c +48 187 l +708 187 l +925 187 l +997 187 l +1008.831 187 1021.229 188 1033 186.895 c +1043.211 185.875 1048.521 174.214 1054.211 167 c +1066 151.956 1079.889 138.204 1095 126.424 c +1137.864 93 1187.948 76.740 1242 77 c +1293.516 77.249 1341.887 99.730 1380 133.285 c +1392 143.903 1402.337 156.917 1411.576 170 c +1416 176.377 1419.345 185.301 1428 186.775 c +1434.378 187.862 1441.539 187 1448 187 c +1486 187 l +1605 187 l +1973 187 l +1973 228 l +1991.816 213.537 2013.250 202 2033 189 c +2040.776 183.821 2051.203 179.405 2057 172 c +2046.379 167.980 2036.523 159.845 2027 153.691 c +2009 142 1990.829 130.798 1973 119 c +1973 162 l +1607 162 l +1493 162 l +1458 162 l +1452.692 162 1446.176 163 1441 161.682 c +1434.719 160 1430 149.848 1426.338 145 c +1415.872 131.643 1403.990 119.341 1391 108.438 c +1351.307 75 1298.445 52.254 1246 52 c +1186.955 51.716 1132 66.518 1084 101.884 c +1068 113.547 1053.250 127.194 1040.286 142 c +1035.508 147.457 1029.281 159.806 1021.985 161.682 c +1016.820 163 1010.312 162 1005 162 c +970 162 l +859 162 l +502 162 l +118 162 l +94 162 l +63.275 162 22.657 155.452 5.493 188 c +3 192.609 1.452 197.822 1 203 c +-1.292 197.538 0 189.887 0 184 c +0 143 l +0 0 l +2094 0 l +2094 600 l +0 600 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1220.667 547.667 m +1220.222 547.222 1221.278 547.278 1221.333 547.333 c +1221.778 547.778 1220.722 547.722 1220.667 547.667 c +f +*U +0.000 0.000 0.000 0.408 k +*u +1222 548 m +1223.506 547.317 1224.315 547.174 1226 547 c +1224.494 547.683 1223.685 547.826 1222 548 c +f +*U +0.000 0.000 0.000 0.498 k +*u +1226 548 m +1228.890 546.787 1231.874 547 1235 547 c +1232 548.213 1229 547.998 1226 548 c +f +*U +0.000 0.000 0.000 0.259 k +*u +1235 548 m +1236.769 547.221 1238 547 1240 547 c +1238.231 547.779 1236.964 547.912 1235 548 c +f +*U +0.000 0.000 0.000 0.435 k +*u +1208 547 m +1209.249 546.315 1209.548 546.251 1211 546 c +1209.752 546.685 1209.451 546.749 1208 547 c +f +*U +0.000 0.000 0.000 0.706 k +*u +1211 547 m +1212 546 l +1211 547 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1097 505 m +1102.506 505.267 1106.507 504.498 1112 504 c +1111.402 505.195 1111.534 504.978 1110 506 c +1111.798 508.376 1112 511 1113 514 c +1117.498 511.951 1123 512.486 1128 512 c +1127 520 l +1133.353 520.383 1138 520.728 1144 523 c +1143.417 525.914 1144.588 524.930 1142 527 c +1144 527.529 1145.875 527.948 1148 528 c +1148.986 529.479 1149 529.203 1149 531 c +1152 529.921 1154.825 528.604 1158 528 c +1156 532 l +1164.214 535.235 1170 536.679 1179 536 c +1177.777 537.195 1177.580 537.317 1176 538 c +1192 536 l +1190.211 537.422 1189.294 537.697 1187 538 c +1189.974 539.754 1192.648 542 1196 543 c +1202.709 544.728 1209.612 543.318 1216 546 c +1218.673 542.941 1223.233 544.168 1227 544.305 c +1235.305 544.606 1243.588 544.364 1251.884 544.219 c +1256.600 544 1263.284 544.889 1264 539 c +1267 540 l +1265.564 538.550 1264.885 537.778 1264 536 c +1269 536 l +1270.582 538 1271 537.733 1273 536 c +1277 536 l +1278 540 l +1280 540 l +1281 536 l +1285 539 l +1285 537.203 1285 537.479 1286 536 c +1289.458 536.692 1293.276 537.234 1297 535 c +1296 534 l +1302 534 l +1299.979 533 1298 532.504 1296 532 c +1297.684 530.717 1299.572 529.475 1300 532 c +1305 529 l +1304 528 l +1307.472 528.329 1310.633 529 1314 530 c +1309.697 533.253 1304 534.641 1299 536.333 c +1286.644 540.449 1273.894 543.338 1261 545 c +1218.743 551 1176 544 1137 527.421 c +1123.816 521.779 1107.527 514.888 1097 505 c +f +*U +0.000 0.000 0.000 0.714 k +*u +1248.667 546.667 m +1248.223 546.223 1249.277 546.277 1249.333 546.333 c +1249.778 546.778 1248.722 546.722 1248.667 546.667 c +f +*U +0.000 0.000 0.000 0.471 k +*u +1250.667 546.667 m +1250.222 546.222 1251.278 546.278 1251.333 546.333 c +1251.778 546.778 1250.722 546.722 1250.667 546.667 c +f +*U +0.000 0.000 0.000 0.212 k +*u +1252.667 546.667 m +1252.222 546.222 1253.278 546.278 1253.333 546.333 c +1253.778 546.778 1252.722 546.722 1252.667 546.667 c +f +*U +0.000 0.000 0.000 0.333 k +*u +1199 546 m +1200 545 l +1199 546 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1200.667 545.667 m +1200.222 545.222 1201.278 545.278 1201.333 545.333 c +1201.778 545.778 1200.722 545.722 1200.667 545.667 c +f +*U +0.000 0.000 0.000 0.996 k +*u +1187 539 m +1188.648 538 1190.175 537.551 1192 537 c +1186.275 536.347 1181.495 537.749 1176 539 c +1177 537.985 1177.612 537.691 1179 537 c +1170.375 535.591 1164 536.497 1156 532 c +1156.406 529.907 1156.217 529.980 1158 529 c +1154.812 529 1152 530.303 1149 531 c +1148 528 l +1145.646 528 1144.232 527.791 1142 527 c +1144 523 l +1138.183 521.579 1132.916 520.993 1127 520 c +1128 512 l +1122.997 512.954 1117.879 512.549 1113 514 c +1111.862 511.207 1110 507.540 1112 505 c +1108 504.450 1104.859 506.945 1101 506 c +1094 504.285 1088.645 500 1083 495.846 c +1072.743 488.290 1063 479.954 1054 471 c +1048.283 465.376 1038.172 458.932 1040 450 c +1038.271 449 1037.406 448.392 1036 447 c +1036 449 l +1031.474 445.298 1030.846 441.527 1032 436 c +1030 437 l +1030.768 435.686 1030.686 435.768 1032 435 c +1030.723 433 1030.723 433.915 1032 432 c +1029 434 l +1026.227 431.732 1022.444 432.412 1019 432 c +1020 434 l +1008.634 430.453 995.831 432 984 432 c +921 432 l +710 432 l +271 432 l +127 432 l +101.328 432 74.463 429.782 49 433 c +53 434 l +51.542 435 50.752 435.436 49 436 c +48 432 l +43 434 l +44 432 l +39.342 432.898 35.518 432.375 31 431 c +30.695 424 23.491 425.482 20 421 c +24 421 l +22.469 419 20.951 417.532 19 416 c +19 420 l +16.912 418.828 15.321 411.481 13 414 c +11.275 412.723 10.221 412.314 12 411 c +10.316 410.776 9.687 410.782 8 411 c +8.980 409.217 8.908 409.406 11 409 c +8.299 407.261 7 406 6 403 c +7.267 401.457 7.489 400.952 8 399 c +4 400 l +6.466 394.711 7 390.778 8 385 c +6.814 386 6.396 386.339 5 387 c +6 384 l +4.373 385.717 4 385.899 5 388 c +4 393 l +-1.639 383.933 0 373.290 0 363 c +0 305 l +24 305 l +24 391 l +25 389 l +25.751 391 25.656 391.596 24 393 c +24.727 395.753 24.607 398.517 26 401 c +24 404 l +25.915 402.723 25 402.723 27 404 c +28 399 l +29.187 401.180 29.234 402.514 29 405 c +34.487 405.255 32.224 409 34.895 412.489 c +36.307 414.307 38.989 415 41 416 c +40.489 414 40.267 413.543 39 412 c +40 414 l +38.217 413 38.406 413 38 411 c +39.878 411.176 41.199 411.438 43 412 c +42 415 l +44.592 415 45.707 414.737 48 414 c +47 416 l +86.624 411 127.988 414 168 414 c +378 414 l +1024 414 l +1016.841 417 1005.744 415 998 415 c +941 415 l +743 415 l +56 415 l +64.280 417.448 74.393 416 83 416 c +137 416 l +312 416 l +886 416 l +995 416 l +1004.996 416 1015 416 1025 415.995 c +1030.506 415.905 1034.575 414.502 1039.826 417 c +1043.661 418.902 1046 422.759 1048.600 426 c +1052.525 430.910 1056.589 435.507 1060.985 439.999 c +1076.853 456.214 1093.284 471.210 1112 484 c +1126.948 494.423 1143 502.860 1160 509.550 c +1165.691 511.808 1175.917 512.565 1178 519 c +1179 517.466 1178.805 517.598 1180 517 c +1183.857 518.867 1189.271 518.625 1192 522 c +1195 521.472 1197 522 1200 523 c +1197.812 524.885 1195.713 526 1193 527 c +1196.767 526.871 1200.391 524.566 1203 528 c +1205.934 527.360 1208 527.360 1211 528 c +1209.952 526 1209.487 525 1209 523 c +1217 525 l +1214.761 525.811 1213.353 525.529 1211 525 c +1213 527 1214.000 528.429 1217 528 c +1219 527 l +1222.348 527.279 1226.657 528.965 1231 528 c +1232 527.747 1233.863 526.284 1235 526 c +1237.340 525.415 1239.191 526.397 1241 527 c +1242 526 l +1242 528 l +1243 526 l +1244.300 526.650 1244 526 1244 528 c +1244.986 526.521 1245 526.797 1245 525 c +1245.685 526.248 1245.749 526.549 1246 528 c +1248.855 527.294 1251 527.513 1254 528 c +1253 524 l +1255.378 524.181 1257.628 524.233 1260 524 c +1260 528 l +1261 525.538 1261.334 524.568 1264 524 c +1263 521 l +1271.274 520.324 1277.667 518.358 1286 520 c +1284.843 518.183 1284.855 518 1285 516 c +1286.528 517.474 1286.840 517.918 1287 520 c +1289.409 519.728 1291.581 519.799 1294 520 c +1294.307 517.877 1294.382 517.314 1296 516 c +1295 513 l +1298.604 512 1301.263 511.594 1304 509 c +1310.537 511.439 1311.791 507.453 1316 503 c +1318.992 503 1321.189 502.883 1324 504 c +1323 500 l +1325.420 501.382 1326 502.363 1327 505 c +1327.506 503 1327.686 502.268 1329 501 c +1327.744 499.263 1327.345 498 1327 496 c +1349.291 482.355 1368.859 466.798 1387 447.996 c +1396.451 438.263 1406.258 427.833 1413 416 c +1415.741 415.723 1417.586 414.291 1420 413 c +1420 414.797 1419.986 414.522 1419 416 c +1968 416 l +1968 432 l +1586 432 l +1480 432 l +1463.783 432 1443.713 428.891 1429 436 c +1427.990 434.831 1427.516 434.685 1426 434 c +1424 440 l +1418.649 440.829 1416.401 443.682 1416 449 c +1417 445 l +1418.739 448.573 1415.598 458.891 1411 455 c +1409.287 456.647 1408.306 456.631 1408 459 c +1409.478 458 1409.203 458 1411 458 c +1409.465 467.785 1397 476.545 1389.999 482.834 c +1374.955 496.309 1358.416 507.820 1341 517.988 c +1333.655 522.277 1323.626 528.946 1315 529.748 c +1311.380 530 1307.517 528.743 1304 528 c +1303.441 530.579 1302.466 530.972 1300 532 c +1300.000 529.312 1298.323 530.572 1296 531 c +1298 531.881 1299.854 532.496 1302 533 c +1299.948 533.874 1298.253 533.953 1296 534 c +1295.404 537.935 1289 536.731 1286 536 c +1285 539 l +1283 537.999 1282.901 537.923 1282 536 c +1280 540 l +1278 540 l +1277 536 l +1275.313 536.218 1274.684 536.224 1273 536 c +1271.722 538.898 1269.750 539.483 1269 536 c +1266.968 536.323 1266 536.340 1264 536 c +1267 539 l +1265.502 539.479 1265.650 539.400 1264 539 c +1263.720 545 1256.869 544.287 1252 544.487 c +1244 544.813 1235.971 544.989 1228 544.634 c +1223.594 544.438 1219.714 543.187 1216 546 c +1209.178 543.964 1201.981 544.830 1195 543 c +1192 542.248 1189.747 540.246 1187 539 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1258 546 m +1259 545 l +1258 546 l +f +*U +0.000 0.000 0.000 0.557 k +*u +1259 546 m +1260 545 l +1259 546 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1260 546 m +1261 545 l +1260 546 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1192 545 m +1193 544 l +1192 545 l +f +*U +0.000 0.000 0.000 0.424 k +*u +1193 545 m +1194 544 l +1193 545 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1194 545 m +1195 544 l +1194 545 l +f +*U +0.012 0.012 0.000 0.678 k +*u +1265 545 m +1266 544 l +1265 545 l +f +*U +0.008 0.008 0.000 0.435 k +*u +1266 545 m +1267 544 l +1266 545 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1267 545 m +1268 544 l +1267 545 l +f +*U +0.000 0.000 0.000 0.267 k +*u +1187 544 m +1188 543 l +1187 544 l +f +*U +0.000 0.000 0.000 0.553 k +*u +1188 544 m +1189 543 l +1188 544 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1189 544 m +1190 543 l +1189 544 l +f +*U +0.000 0.000 0.000 0.686 k +*u +1271 544 m +1272 543 l +1271 544 l +f +*U +0.000 0.000 0.000 0.314 k +*u +1272 544 m +1273 543 l +1272 544 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1182 543 m +1183 542 l +1182 543 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1183 543 m +1184 542 l +1183 543 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1276 543 m +1277 542 l +1276 543 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1277 543 m +1278 542 l +1277 543 l +f +*U +0.000 0.000 0.000 0.286 k +*u +1178 542 m +1179 541 l +1178 542 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1179 542 m +1180 541 l +1179 542 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1280 542 m +1281 541 l +1280 542 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1281 542 m +1282 541 l +1281 542 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1174 541 m +1175 540 l +1174 541 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1175 541 m +1176 540 l +1175 541 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1284 541 m +1285 540 l +1284 541 l +f +*U +0.000 0.000 0.000 0.424 k +*u +1285 541 m +1286 540 l +1285 541 l +f +*U +0.000 0.000 0.000 0.294 k +*u +1170 540 m +1171 539 l +1170 540 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1171 540 m +1172 539 l +1171 540 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1288 540 m +1289 539 l +1288 540 l +f +*U +0.000 0.000 0.000 0.302 k +*u +1289 540 m +1290 539 l +1289 540 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1166 539 m +1167 538 l +1166 539 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1167 539 m +1168 538 l +1167 539 l +f +*U +0.000 0.000 0.000 0.416 k +*u +1292 539 m +1293 538 l +1292 539 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1163 538 m +1164 537 l +1163 538 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1164 538 m +1165 537 l +1164 538 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1295 538 m +1296 537 l +1295 538 l +f +*U +0.000 0.000 0.000 0.376 k +*u +1160 537 m +1161 536 l +1160 537 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1161 537 m +1162 536 l +1161 537 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1298 537 m +1299 536 l +1298 537 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1299 537 m +1300 536 l +1299 537 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1157 536 m +1158 535 l +1157 536 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1158 536 m +1159 535 l +1158 536 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1301 536 m +1302 535 l +1301 536 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1302 536 m +1303 535 l +1302 536 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1154 535 m +1155 534 l +1154 535 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1304 535 m +1305 534 l +1304 535 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1151 534 m +1152 533 l +1151 534 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1152 534 m +1153 533 l +1152 534 l +f +*U +0.000 0.000 0.000 0.557 k +*u +1307 534 m +1308 533 l +1307 534 l +f +*U +0.000 0.000 0.000 0.576 k +*u +1149 533 m +1150 532 l +1149 533 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1309 533 m +1310 532 l +1309 533 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1310 533 m +1311 532 l +1310 533 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1146 532 m +1147 531 l +1146 532 l +f +*U +0.000 0.000 0.000 0.576 k +*u +1312 532 m +1313 531 l +1312 532 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1144 531 m +1145 530 l +1144 531 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1314 531 m +1315 530 l +1314 531 l +f +*U +0.000 0.000 0.000 0.278 k +*u +1141 530 m +1142 529 l +1141 530 l +f +*U +0.000 0.000 0.000 0.357 k +*u +1317 530 m +1318 529 l +1317 530 l +f +*U +0.000 0.000 0.000 0.392 k +*u +1139 529 m +1140 528 l +1139 529 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1319 529 m +1320 528 l +1319 529 l +f +*U +0.000 0.000 0.000 0.267 k +*u +1136 528 m +1137 527 l +1136 528 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1137 528 m +1138 527 l +1137 528 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1193 528 m +1195.187 525.968 1197 524.906 1200 524 c +1197.184 522.642 1195 521.920 1192 522 c +1189.177 519.689 1182.345 517 1179 519 c +1177.407 514.799 1183.789 517 1186 517.630 c +1194.832 519.818 1203.937 521.406 1213 522 c +1239.991 524 1266.293 521.434 1292 512.319 c +1303.849 508 1315 500.221 1327 497 c +1327.689 498.688 1327.676 499 1329 500 c +1327.825 501.879 1327.870 502.716 1328 505 c +1323 500 l +1324 504 l +1321.301 503.264 1318.766 503.253 1316 503 c +1312.638 508.242 1310.278 512.630 1304 509 c +1301.737 512 1298.686 512.301 1295 513 c +1295.986 514.479 1296 514.203 1296 516 c +1294.733 517.543 1294.511 518 1294 520 c +1287 520 l +1287 517.898 1286.455 517.629 1285 516 c +1284.930 517.952 1284.646 517.940 1286 519 c +1283 520 1280 518.908 1277 518.998 c +1272.265 519 1267.750 520.793 1263 521 c +1263.986 522.479 1264 522.203 1264 524 c +1261.965 525.226 1261.674 525.702 1261 528 c +1260.317 526.494 1260.174 525.685 1260 524 c +1257.353 524.578 1255.636 524.607 1253 524 c +1254 528 l +1250.641 527.802 1246.615 528.853 1246 525 c +1245 526.479 1245 526.203 1245 528 c +1243.804 527.402 1244 527.534 1243 526 c +1243 528 l +1241.700 527.350 1242 527.853 1242 526 c +1233.779 527 1217.519 531.663 1211 525 c +1217 526 l +1209 523 l +1211 528 l +1208.194 527.598 1205.806 527.598 1203 528 c +1199.774 525 1196.868 527.178 1193 528 c +f +*U +0.000 0.000 0.000 0.212 k +*u +1322 528 m +1323 527 l +1322 528 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1134 527 m +1135 526 l +1134 527 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1324 527 m +1325 526 l +1324 527 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1132 526 m +1133 525 l +1132 526 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1326 526 m +1327 525 l +1326 526 l +f +*U +0.000 0.000 0.000 0.341 k +*u +1130 525 m +1131 524 l +1130 525 l +f +*U +0.000 0.000 0.000 0.306 k +*u +1328 525 m +1329 524 l +1328 525 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1128 524 m +1129 523 l +1128 524 l +f +*U +0.000 0.000 0.000 0.427 k +*u +1330 524 m +1331 523 l +1330 524 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1126 523 m +1127 522 l +1126 523 l +f +*U +0.000 0.000 0.000 0.612 k +*u +1216.667 522.667 m +1216.223 522.223 1217.277 522.277 1217.333 522.333 c +1217.778 522.778 1216.722 522.722 1216.667 522.667 c +f +*U +0.000 0.000 0.000 0.478 k +*u +1218 523 m +1219.249 522.315 1219.548 522.251 1221 522 c +1219.752 522.685 1219.451 522.749 1218 523 c +f +*U +0.000 0.000 0.000 0.290 k +*u +1221 523 m +1222.248 522.315 1222.548 522.251 1224 522 c +1222.752 522.685 1222.451 522.749 1221 523 c +f +*U +0.024 0.000 0.020 0.125 k +*u +1224 523 m +1227.698 521.448 1232 522 1236 522 c +1232.303 523.552 1227.983 523 1224 523 c +f +*U +0.000 0.000 0.000 0.314 k +*u +1236 523 m +1237.769 522.221 1239 522 1241 522 c +1239.231 522.779 1237.964 522.912 1236 523 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1241.667 522.667 m +1241.222 522.222 1242.278 522.278 1242.333 522.333 c +1242.778 522.778 1241.722 522.722 1241.667 522.667 c +f +*U +0.000 0.000 0.000 0.867 k +*u +1243.667 522.667 m +1243.223 522.223 1244.277 522.277 1244.333 522.333 c +1244.778 522.778 1243.722 522.722 1243.667 522.667 c +f +*U +0.000 0.000 0.000 0.404 k +*u +1332 523 m +1333 522 l +1332 523 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1124 522 m +1125 521 l +1124 522 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1206 522 m +1207 521 l +1206 522 l +f +*U +0.000 0.000 0.000 0.427 k +*u +1207.667 521.667 m +1207.223 521.223 1208.277 521.277 1208.333 521.333 c +1208.778 521.778 1207.722 521.722 1207.667 521.667 c +f +*U +0.000 0.000 0.000 0.235 k +*u +1209 522 m +1210 521 l +1209 522 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1250 522 m +1251.248 521.315 1251.548 521.251 1253 521 c +1251.752 521.685 1251.451 521.749 1250 522 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1253 522 m +1254 521 l +1253 522 l +f +*U +0.000 0.000 0.000 0.459 k +*u +1334 522 m +1335 521 l +1334 522 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1122 521 m +1123 520 l +1122 521 l +f +*U +0.000 0.000 0.000 0.608 k +*u +1200 521 m +1201 520 l +1200 521 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1201 521 m +1202 520 l +1201 521 l +f +*U +0.000 0.000 0.000 0.310 k +*u +1258 521 m +1259 520 l +1258 521 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1259 521 m +1260 520 l +1259 521 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1260 521 m +1261 520 l +1260 521 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1336 521 m +1337 520 l +1336 521 l +f +*U +0.000 0.000 0.000 0.443 k +*u +1120 520 m +1121 519 l +1120 520 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1194 520 m +1195 519 l +1194 520 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1195 520 m +1196 519 l +1195 520 l +f +*U +0.012 0.012 0.000 0.341 k +*u +1264 520 m +1265 519 l +1264 520 l +f +*U +0.008 0.008 0.000 0.608 k +*u +1265 520 m +1266 519 l +1265 520 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1338 520 m +1339 519 l +1338 520 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1118 519 m +1119 518 l +1118 519 l +f +*U +0.000 0.000 0.008 0.733 k +*u +1189 519 m +1190 518 l +1189 519 l +f +*U +0.000 0.000 0.008 0.396 k +*u +1190 519 m +1191 518 l +1190 519 l +f +*U +0.000 0.000 0.008 0.310 k +*u +1269 519 m +1270 518 l +1269 519 l +f +*U +0.000 0.000 0.008 0.741 k +*u +1270 519 m +1271 518 l +1270 519 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1116 518 m +1117 517 l +1116 518 l +f +*U +0.008 0.008 0.000 0.627 k +*u +1185 518 m +1186 517 l +1185 518 l +f +*U +0.008 0.008 0.000 0.282 k +*u +1186 518 m +1187 517 l +1186 518 l +f +*U +0.008 0.008 0.000 0.224 k +*u +1273 518 m +1274 517 l +1273 518 l +f +*U +0.008 0.008 0.000 0.655 k +*u +1274 518 m +1275 517 l +1274 518 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1341 518 m +1342 517 l +1341 518 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1115 517 m +1116 516 l +1115 517 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1181 517 m +1182 516 l +1181 517 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1182 517 m +1183 516 l +1182 517 l +f +*U +0.012 0.012 0.000 0.184 k +*u +1277 517 m +1278 516 l +1277 517 l +f +*U +0.008 0.008 0.000 0.690 k +*u +1278 517 m +1279 516 l +1278 517 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1343 517 m +1344 516 l +1343 517 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1113 516 m +1114 515 l +1113 516 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1177 516 m +1178 515 l +1177 516 l +f +*U +0.000 0.000 0.000 0.384 k +*u +1178 516 m +1179 515 l +1178 516 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1281 516 m +1282 515 l +1281 516 l +f +*U +0.000 0.000 0.000 0.463 k +*u +1111 515 m +1112 514 l +1111 515 l +f +*U +0.000 0.000 0.000 0.510 k +*u +1174 515 m +1175 514 l +1174 515 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1284 515 m +1285 514 l +1284 515 l +f +*U +0.000 0.000 0.000 0.643 k +*u +1285 515 m +1286 514 l +1285 515 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1346 515 m +1347 514 l +1346 515 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1109 514 m +1110 513 l +1109 514 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1171 514 m +1172 513 l +1171 514 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1288 514 m +1289 513 l +1288 514 l +f +*U +0.000 0.000 0.000 0.412 k +*u +1348 514 m +1349 513 l +1348 514 l +f +*U +0.000 0.000 0.000 0.290 k +*u +1168 513 m +1169 512 l +1168 513 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1290 513 m +1291 512 l +1290 513 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1291 513 m +1292 512 l +1291 513 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1350 513 m +1351 512 l +1350 513 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1106 512 m +1107 511 l +1106 512 l +f +*U +0.000 0.000 0.000 0.502 k +*u +1165 512 m +1166 511 l +1165 512 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1294 512 m +1295 511 l +1294 512 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1351 512 m +1352 511 l +1351 512 l +f +*U +0.000 0.000 0.000 0.259 k +*u +1104 511 m +1105 510 l +1104 511 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1162 511 m +1163 510 l +1162 511 l +f +*U +0.000 0.000 0.000 0.380 k +*u +1296 511 m +1297 510 l +1296 511 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1353 511 m +1354 510 l +1353 511 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1103 510 m +1104 509 l +1103 510 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1159 510 m +1160 509 l +1159 510 l +f +*U +0.000 0.000 0.000 0.600 k +*u +1299 510 m +1300 509 l +1299 510 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1101 509 m +1102 508 l +1101 509 l +f +*U +0.000 0.000 0.000 0.455 k +*u +1157 509 m +1158 508 l +1157 509 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1301 509 m +1302 508 l +1301 509 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1302 509 m +1303 508 l +1302 509 l +f +*U +0.000 0.000 0.000 0.471 k +*u +1356 509 m +1357 508 l +1356 509 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1155 508 m +1156 507 l +1155 508 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1098 507 m +1099 506 l +1098 507 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1152 507 m +1153 506 l +1152 507 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1306 507 m +1307 506 l +1306 507 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1359 507 m +1360 506 l +1359 507 l +f +*U +0.000 0.000 0.000 0.420 k +*u +1150 506 m +1151 505 l +1150 506 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1308 506 m +1309 505 l +1308 506 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1360 506 m +1361 505 l +1360 506 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1095 505 m +1096 504 l +1095 505 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1148 505 m +1149 504 l +1148 505 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1310 505 m +1311 504 l +1310 505 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1362 505 m +1363 504 l +1362 505 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1145 504 m +1146 503 l +1145 504 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1146 504 m +1147 503 l +1146 504 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1313 504 m +1314 503 l +1313 504 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1363 504 m +1364 503 l +1363 504 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1092 503 m +1093 502 l +1092 503 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1143 503 m +1144 502 l +1143 503 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1314 503 m +1315 502 l +1314 503 l +f +*U +0.000 0.000 0.000 0.624 k +*u +1141 502 m +1142 501 l +1141 502 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1317 502 m +1318 501 l +1317 502 l +f +*U +0.000 0.000 0.000 0.310 k +*u +1366 502 m +1367 501 l +1366 502 l +f +*U +0.000 0.000 0.000 0.408 k +*u +1089 501 m +1090 500 l +1089 501 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1139 501 m +1140 500 l +1139 501 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1318 501 m +1319 500 l +1318 501 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1088 500 m +1089 499 l +1088 500 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1137 500 m +1138 499 l +1137 500 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1320 500 m +1321 499 l +1320 500 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1369 500 m +1370 499 l +1369 500 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1086 499 m +1087 498 l +1086 499 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1135 499 m +1136 498 l +1135 499 l +f +*U +0.000 0.000 0.000 0.235 k +*u +1322 499 m +1323 498 l +1322 499 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1370 499 m +1371 498 l +1370 499 l +f +*U +0.000 0.000 0.000 0.467 k +*u +1085 498 m +1086 497 l +1085 498 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1134 498 m +1135 497 l +1134 498 l +f +*U +0.000 0.000 0.000 0.353 k +*u +1324 498 m +1325 497 l +1324 498 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1326 497 m +1327 496 l +1326 497 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1373 497 m +1374 496 l +1373 497 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1082 496 m +1083 495 l +1082 496 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1130 496 m +1131 495 l +1130 496 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1374 496 m +1375 495 l +1374 496 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1081 495 m +1082 494 l +1081 495 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1128 495 m +1129 494 l +1128 495 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1126 494 m +1127 493 l +1126 494 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1331 494 m +1332 493 l +1331 494 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1377 494 m +1378 493 l +1377 494 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1078 493 m +1079 492 l +1078 493 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1125 493 m +1126 492 l +1125 493 l +f +*U +0.000 0.000 0.000 0.314 k +*u +1378 493 m +1379 492 l +1378 493 l +f +1077 492 m +1078 491 l +1077 492 l +f +*U +0.000 0.000 0.000 0.404 k +*u +1123 492 m +1124 491 l +1123 492 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1334 492 m +1335 491 l +1334 492 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1379 492 m +1380 491 l +1379 492 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1076 491 m +1077 490 l +1076 491 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1121 491 m +1122 490 l +1121 491 l +f +*U +0.000 0.000 0.000 0.627 k +*u +1336 491 m +1337 490 l +1336 491 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1380 491 m +1381 490 l +1380 491 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1120 490 m +1121 489 l +1120 490 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1337 490 m +1338 489 l +1337 490 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1118 489 m +1119 488 l +1118 489 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1339 489 m +1340 488 l +1339 489 l +f +*U +0.000 0.000 0.000 0.439 k +*u +1072 488 m +1073 487 l +1072 488 l +f +*U +0.000 0.000 0.000 0.525 k +*u +1384 488 m +1385 487 l +1384 488 l +f +*U +0.000 0.000 0.000 0.537 k +*u +1115 487 m +1116 486 l +1115 487 l +f +*U +0.000 0.000 0.000 0.490 k +*u +1342 487 m +1343 486 l +1342 487 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1385 487 m +1386 486 l +1385 487 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1113 486 m +1114 485 l +1113 486 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1386 486 m +1387 485 l +1386 486 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1112 485 m +1113 484 l +1112 485 l +f +*U +0.000 0.000 0.000 0.439 k +*u +1345 485 m +1346 484 l +1345 485 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1067 484 m +1068 483 l +1067 484 l +f +1346 484 m +1347 483 l +1346 484 l +f +*U +0.000 0.000 0.000 0.506 k +*u +1066 483 m +1067 482 l +1066 483 l +f +1109 483 m +1110 482 l +1109 483 l +f +*U +0.000 0.000 0.000 0.816 k +*u +1348 483 m +1349 482 l +1348 483 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1065 482 m +1066 481 l +1065 482 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1349 482 m +1350 481 l +1349 482 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1391 482 m +1392 481 l +1391 482 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1064 481 m +1065 480 l +1064 481 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1106 481 m +1107 480 l +1106 481 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1392 481 m +1393 480 l +1392 481 l +f +*U +0.000 0.000 0.000 0.816 k +*u +1063 480 m +1064 479 l +1063 480 l +f +*U +0.000 0.333 0.275 0.169 k +*u +1209 480 m +1210.769 479.221 1212 479 1214 479 c +1212.231 479.779 1210.964 479.912 1209 480 c +f +*U +0.000 0.310 0.216 0.306 k +*u +1214.667 479.667 m +1214.222 479.222 1215.278 479.278 1215.333 479.333 c +1215.778 479.778 1214.722 479.722 1214.667 479.667 c +f +*U +0.000 0.682 0.471 0.220 k +*u +1216.667 479.667 m +1216.222 479.222 1217.278 479.278 1217.333 479.333 c +1217.778 479.778 1216.722 479.722 1216.667 479.667 c +f +*U +0.000 0.584 0.416 0.416 k +*u +1218 480 m +1220.890 478.787 1223.874 479 1227 479 c +1224 480.213 1221 479.998 1218 480 c +f +*U +0.000 0.482 0.482 0.518 k +*u +1227 480 m +1228.769 479.221 1230 479 1232 479 c +1230.231 479.779 1228.964 479.912 1227 480 c +f +*U +0.000 0.549 0.522 0.380 k +*u +1232.667 479.667 m +1232.222 479.222 1233.278 479.278 1233.333 479.333 c +1233.778 479.778 1232.722 479.722 1232.667 479.667 c +f +*U +0.000 0.384 0.416 0.165 k +*u +1234 480 m +1235.249 479.315 1235.548 479.251 1237 479 c +1235.752 479.685 1235.452 479.749 1234 480 c +f +*U +0.000 0.145 0.255 0.161 k +*u +1237.667 479.667 m +1237.222 479.222 1238.278 479.278 1238.333 479.333 c +1238.778 479.777 1237.722 479.722 1237.667 479.667 c +f +*U +0.000 0.000 0.000 0.494 k +*u +1393 480 m +1394 479 l +1393 480 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1103 479 m +1104 478 l +1103 479 l +f +*U +0.000 0.239 0.208 0.008 k +*u +1201 479 m +1202 478 l +1201 479 l +f +*U +0.000 0.302 0.251 0.149 k +*u +1202 479 m +1203 478 l +1202 479 l +f +*U +0.000 0.392 0.310 0.290 k +*u +1203 479 m +1204 478 l +1203 479 l +f +*U +0.000 0.514 0.416 0.486 k +*u +1204 479 m +1205.506 478.317 1206.315 478.174 1208 478 c +1206.494 478.683 1205.685 478.826 1204 479 c +f +*U +0.000 0.851 0.698 0.149 k +*u +1208 477 m +1212 477.749 1215.899 477.997 1220 478 c +1216.479 479.478 1210.661 480 1208 477 c +f +*U +0.000 0.863 0.616 0.129 k +*u +1186 475 m +1187 472 l +1211.465 475.213 1236.492 471.285 1261 473 c +1258 477.519 1245.341 477.930 1240 478 c +1227.931 478.172 1216 478.866 1204 477.802 c +1197.857 477.262 1192.257 475 1186 475 c +f +*U +0.000 0.694 0.424 0.306 k +*u +1233 479 m +1235.332 478 1237.457 478 1240 478 c +1237.669 478.984 1235.543 478.981 1233 479 c +f +*U +0.000 0.451 0.435 0.549 k +*u +1240 479 m +1241.769 478.221 1243 478 1245 478 c +1243.231 478.779 1241.964 478.912 1240 479 c +f +*U +0.000 0.475 0.373 0.259 k +*u +1245 479 m +1246 478 l +1245 479 l +f +*U +0.000 0.435 0.325 0.000 k +*u +1246.667 478.667 m +1246.222 478.222 1247.278 478.278 1247.333 478.333 c +1247.778 478.778 1246.722 478.722 1246.667 478.667 c +f +*U +0.000 0.000 0.000 0.392 k +*u +1353 479 m +1354 478 l +1353 479 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1394 479 m +1395 478 l +1394 479 l +f +*U +0.000 0.000 0.000 0.494 k +*u +1102 478 m +1103 477 l +1102 478 l +f +*U +0.000 0.259 0.118 0.129 k +*u +1195 478 m +1196 477 l +1195 478 l +f +*U +0.000 0.388 0.204 0.286 k +*u +1196 478 m +1197 477 l +1196 478 l +f +*U +0.000 0.624 0.494 0.376 k +*u +1197 478 m +1198.769 477.221 1200 477 1202 477 c +1200.231 477.779 1198.964 477.912 1197 478 c +f +*U +0.000 0.518 0.349 0.482 k +*u +1248 478 m +1249.506 477.317 1250.315 477.174 1252 477 c +1250.494 477.683 1249.685 477.826 1248 478 c +f +*U +0.000 0.298 0.224 0.204 k +*u +1252.667 477.667 m +1252.222 477.222 1253.278 477.278 1253.333 477.333 c +1253.778 477.778 1252.722 477.722 1252.667 477.667 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1395 478 m +1396 477 l +1395 478 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1101 477 m +1102 476 l +1101 477 l +f +*U +0.000 0.341 0.263 0.141 k +*u +1190 477 m +1191 476 l +1190 477 l +f +*U +0.000 0.451 0.263 0.290 k +*u +1191 477 m +1192 476 l +1191 477 l +f +*U +0.000 0.741 0.659 0.259 k +*u +1192 477 m +1194 476 1195.747 476 1198 476 c +1195.948 476.874 1194.253 476.953 1192 477 c +f +*U +0.000 0.910 0.918 0.063 k +*u +1248 477 m +1249.769 476.221 1251 476 1253 476 c +1251.231 476.779 1249.964 476.912 1248 477 c +f +*U +0.000 0.718 0.667 0.282 k +*u +1253 477 m +1254.248 476.315 1254.548 476.251 1256 476 c +1254.752 476.685 1254.451 476.749 1253 477 c +f +*U +0.000 0.416 0.200 0.584 k +*u +1256 477 m +1257 476 l +1256 477 l +f +*U +0.000 0.373 0.267 0.337 k +*u +1257 477 m +1258 476 l +1257 477 l +f +*U +0.000 0.149 0.043 0.129 k +*u +1258.667 476.667 m +1258.222 476.222 1259.278 476.278 1259.333 476.333 c +1259.778 476.777 1258.722 476.722 1258.667 476.667 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1356 477 m +1357 476 l +1356 477 l +f +*U +0.000 0.043 0.204 0.290 k +*u +1184.667 475.667 m +1184.222 475.222 1185.278 475.278 1185.333 475.333 c +1185.778 475.778 1184.722 475.722 1184.667 475.667 c +f +*U +0.000 0.341 0.153 0.357 k +*u +1186 476 m +1187 475 l +1186 476 l +f +*U +0.000 0.675 0.412 0.325 k +*u +1187 476 m +1189.332 475 1191.457 475 1194 475 c +1191.668 475.984 1189.544 475.981 1187 476 c +f +*U +0.000 0.514 0.322 0.486 k +*u +1260 476 m +1261.249 475.315 1261.548 475.251 1263 475 c +1261.752 475.685 1261.451 475.749 1260 476 c +f +*U +0.000 0.412 0.137 0.078 k +*u +1263 476 m +1264 475 l +1263 476 l +f +*U +0.000 0.000 0.000 0.518 k +*u +1357 476 m +1358 475 l +1357 476 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1397 476 m +1398 475 l +1397 476 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1057 475 m +1058 474 l +1057 475 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1098 475 m +1099 474 l +1098 475 l +f +*U +0.000 0.275 0.231 0.059 k +*u +1181 475 m +1182 474 l +1181 475 l +f +*U +0.000 0.435 0.314 0.322 k +*u +1182 475 m +1183 474 l +1182 475 l +f +*U +0.000 0.635 0.655 0.345 k +*u +1183 475 m +1184.249 474.315 1184.548 474.251 1186 474 c +1184.752 474.685 1184.452 474.749 1183 475 c +f +*U +0.000 0.796 0.592 0.204 k +*u +1261 475 m +1262 473 l +1263.635 473.545 1263.455 473.365 1264 475 c +1261 475 l +f +*U +0.000 0.522 0.373 0.443 k +*u +1264.667 474.667 m +1264.222 474.222 1265.278 474.278 1265.333 474.333 c +1265.778 474.778 1264.722 474.722 1264.667 474.667 c +f +*U +0.000 0.435 0.278 0.227 k +*u +1266 475 m +1267 474 l +1266 475 l +f +*U +0.000 0.314 0.200 0.039 k +*u +1267 475 m +1268 474 l +1267 475 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1398 475 m +1399 474 l +1398 475 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1056 474 m +1057 473 l +1056 474 l +f +*U +0.000 0.000 0.000 0.231 k +*u +1097 474 m +1098 473 l +1097 474 l +f +*U +0.000 0.216 0.192 0.043 k +*u +1177 474 m +1178 473 l +1177 474 l +f +*U +0.000 0.333 0.239 0.337 k +*u +1178 474 m +1179 473 l +1178 474 l +f +*U +0.000 0.573 0.518 0.427 k +*u +1179.667 473.667 m +1179.222 473.222 1180.278 473.278 1180.333 473.333 c +1180.778 473.778 1179.722 473.722 1179.667 473.667 c +f +*U +0.000 0.859 0.694 0.141 k +*u +1181 474 m +1182.750 472.745 1183.857 472.386 1186 472 c +1184.460 473.803 1183.403 473.832 1181 474 c +f +*U +0.000 0.843 0.910 0.090 k +*u +1186.333 473.333 m +1186.278 473.278 1186.222 472.222 1186.667 472.667 c +1186.723 472.723 1186.777 473.778 1186.333 473.333 c +f +*U +0.000 0.910 0.788 0.090 k +*u +1258 473 m +1262.216 471.231 1267.459 472 1272 472 c +1267.693 474 1262.585 474.272 1258 473 c +f +*U +0.000 0.518 0.471 0.455 k +*u +1267 474 m +1268.248 473.315 1268.548 473.251 1270 473 c +1268.752 473.685 1268.452 473.749 1267 474 c +f +*U +0.000 0.263 0.263 0.341 k +*u +1270 474 m +1271 473 l +1270 474 l +f +*U +0.000 0.239 0.196 0.176 k +*u +1271 474 m +1272 473 l +1271 474 l +f +*U +0.000 0.000 0.000 0.745 k +*u +1399 474 m +1400 473 l +1399 474 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1055 473 m +1056 472 l +1055 473 l +f +*U +0.000 0.027 0.020 0.322 k +*u +1173 471 m +1176 471 l +1175 473 l +1173.365 472.455 1173.545 472.635 1173 471 c +f +*U +0.000 0.502 0.502 0.498 k +*u +1175 473 m +1176.248 472.315 1176.548 472.251 1178 472 c +1176.752 472.685 1176.451 472.749 1175 473 c +f +*U +0.000 0.973 0.914 0.027 k +*u +1178 473 m +1179.769 472.221 1181 472 1183 472 c +1181.231 472.779 1179.964 472.912 1178 473 c +f +*U +0.000 0.918 0.918 0.082 k +*u +1188.667 472.667 m +1188.222 472.222 1189.278 472.278 1189.333 472.333 c +1189.778 472.778 1188.722 472.722 1188.667 472.667 c +f +*U +0.000 1.000 1.000 0.000 k +*u +1191 473 m +1192.769 472.221 1194 472 1196 472 c +1194.231 472.779 1192.964 472.912 1191 473 c +f +*U +0.000 0.776 0.847 0.153 k +*u +1196 473 m +1198 472 1199.747 472 1202 472 c +1199.948 472.874 1198.253 472.953 1196 473 c +f +*U +0.000 1.000 1.000 0.000 k +*u +1202 473 m +1206.720 471 1212.920 472 1218 472 c +1251 472 l +1246.280 473.981 1240 473 1235 473 c +1202 473 l +f +*U +0.000 0.820 0.875 0.125 k +*u +1251 473 m +1252.769 472.221 1254 472 1256 472 c +1254.231 472.779 1252.964 472.912 1251 473 c +f +*U +0.000 0.467 0.333 0.506 k +*u +1272.667 472.667 m +1272.222 472.222 1273.278 472.278 1273.333 472.333 c +1273.778 472.778 1272.722 472.722 1272.667 472.667 c +f +*U +0.000 0.122 0.035 0.180 k +*u +1176 472 m +1184.358 468.493 1197.940 471 1207 471 c +1276 471 l +1273 472.638 1270.260 472 1267 472 c +1260.668 471.941 1254.332 472 1248 472 c +1176 472 l +f +*U +0.000 0.000 0.000 0.753 k +*u +1361 473 m +1362 472 l +1361 473 l +f +*U +0.000 0.000 0.004 0.827 k +*u +1400 473 m +1401 472 l +1400 473 l +f +*U +0.000 0.000 0.000 0.494 k +*u +1054 472 m +1055 471 l +1054 472 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1094 472 m +1095 471 l +1094 472 l +f +*U +0.000 0.000 0.000 0.471 k +*u +1362 472 m +1363 471 l +1362 472 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1053 471 m +1054 470 l +1053 471 l +f +*U +0.000 0.000 0.000 0.341 k +*u +1093 471 m +1094 470 l +1093 471 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1363 471 m +1364 470 l +1363 471 l +f +*U +0.008 0.008 0.000 0.745 k +*u +1402 471 m +1403 470 l +1402 471 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1052 470 m +1053 469 l +1052 470 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1051 469 m +1052 468 l +1051 469 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1050 468 m +1051 467 l +1050 468 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1089 468 m +1090 467 l +1089 468 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1049 467 m +1050 466 l +1049 467 l +f +*U +0.000 0.000 0.000 0.510 k +*u +1088 467 m +1089 466 l +1088 467 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1368 467 m +1369 466 l +1368 467 l +f +*U +0.000 0.000 0.008 0.765 k +*u +1406 467 m +1407 466 l +1406 467 l +f +*U +0.000 0.000 0.000 0.294 k +*u +1087 466 m +1088 465 l +1087 466 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1369 466 m +1370 465 l +1369 466 l +f +*U +0.000 0.000 0.008 0.639 k +*u +1407 466 m +1408 465 l +1407 466 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1047 465 m +1048 464 l +1047 465 l +f +*U +0.000 0.000 0.000 0.443 k +*u +1370 465 m +1371 464 l +1370 465 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1408 465 m +1409 464 l +1408 465 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1046 464 m +1047 463 l +1046 464 l +f +*U +0.000 0.000 0.000 0.251 k +*u +1371 464 m +1372 463 l +1371 464 l +f +*U +0.000 0.000 0.008 0.651 k +*u +1409 464 m +1410 463 l +1409 464 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1045 463 m +1046 462 l +1045 463 l +f +*U +0.000 0.000 0.008 0.663 k +*u +1410 463 m +1411 462 l +1410 463 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1044 462 m +1045 461 l +1044 462 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1082 462 m +1083 461 l +1082 462 l +f +*U +0.000 0.000 0.008 0.251 k +*u +1411 462 m +1412 461 l +1411 462 l +f +*U +0.000 0.000 0.000 0.729 k +*u +1043 461 m +1044 460 l +1043 461 l +f +*U +0.000 0.000 0.000 0.463 k +*u +1081 461 m +1082 460 l +1081 461 l +f +*U +0.000 0.271 0.192 0.224 k +*u +1145 461 m +1146 460 l +1145 461 l +f +*U +0.000 0.400 0.282 0.600 k +*u +1146 461 m +1152.202 458.397 1161.298 460 1168 460 c +1161.797 462.603 1152.702 461 1146 461 c +f +*U +0.000 0.569 0.451 0.431 k +*u +1168 461 m +1169.969 459.937 1171.798 459.468 1174 459 c +1171.943 460.582 1170.613 460.826 1168 461 c +f +*U +0.000 0.278 0.259 0.722 k +*u +1173 461 m +1174.249 460.315 1174.548 460.251 1176 460 c +1174.752 460.685 1174.452 460.749 1173 461 c +f +*U +0.004 0.000 0.000 0.741 k +*u +1176 461 m +1177 460 l +1176 461 l +f +*U +0.000 0.424 0.345 0.576 k +*u +1283 461 m +1288.469 458.705 1296 460 1302 460 c +1296.531 462.295 1288.901 461 1283 461 c +f +*U +0.000 0.286 0.200 0.333 k +*u +1302.667 460.667 m +1302.222 460.222 1303.278 460.278 1303.333 460.333 c +1303.778 460.778 1302.722 460.722 1302.667 460.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1411 461 m +1409.723 459 1409.723 459.915 1411 458 c +1408 459 l +1408.275 456.730 1409.181 456.721 1410 455 c +1415.614 458.509 1418 449.335 1418 445 c +1417 449 l +1414.756 443.432 1418.748 440.397 1424 440 c +1426 434 l +1428.670 434.534 1428.443 433.215 1429 436 c +1439.506 428.578 1458.445 432 1471 432 c +1574 432 l +1968 432 l +1968 415 l +1619 415 l +1552.427 415 1485.454 413 1419 416 c +1420 413 l +1418 414.486 1416 415.836 1414 417 c +1419 407 1438.511 411 1448 411 c +1549 411 l +1974 411 l +1974 435 l +1592 435 l +1481 435 l +1449 435 l +1444.596 435 1438.312 433.875 1434.184 435.603 c +1430.813 437 1428.585 441.253 1426.399 444 c +1421.695 449.910 1417 456.566 1411 461 c +f +*U +0.000 0.000 0.008 0.200 k +*u +1412 461 m +1413 460 l +1412 461 l +f +*U +0.000 0.000 0.000 0.682 k +*u +1042 460 m +1043 459 l +1042 460 l +f +*U +0.000 0.000 0.000 0.400 k +*u +1080 460 m +1081 459 l +1080 460 l +f +*U +0.000 0.153 0.137 0.180 k +*u +1143 460 m +1144 459 l +1143 460 l +f +*U +0.000 0.686 0.506 0.314 k +*u +1144 460 m +1145.248 459.315 1145.548 459.251 1147 459 c +1145.752 459.685 1145.451 459.749 1144 460 c +f +*U +0.000 0.875 0.620 0.125 k +*u +1133 452 m +1133 450 l +1143.965 447.389 1159.403 448.480 1166 459 c +1168 458.754 1169.874 458.769 1172 459 c +1168.565 460.441 1164.703 460 1161 460 c +1156 460 1150.724 460.623 1146 459.200 c +1141.257 457.771 1137.281 454.383 1133 452 c +f +*U +0.000 0.141 0.094 0.271 k +*u +1174 460 m +1175 459 l +1174 460 l +f +*U +0.000 0.671 0.498 0.329 k +*u +1283 460 m +1283.545 458.365 1283.365 458.545 1285 458 c +1285 460 l +1283 460 l +f +*U +0.000 0.863 0.624 0.133 k +*u +1284 457 m +1286 455 1287.676 452.259 1290.224 450.862 c +1297 447 1307.481 449 1315 449 c +1313.378 451.388 1312.428 453 1312 456 c +1309.291 455.352 1306.784 455 1304 455 c +1305.800 455.562 1307 455.824 1309 456 c +1304 460.863 1288.450 463.171 1284 457 c +f +*U +0.000 0.286 0.204 0.082 k +*u +1305 460 m +1306 459 l +1305 460 l +f +*U +0.000 0.000 0.000 0.612 k +*u +1041 459 m +1042 458 l +1041 459 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1079 459 m +1080 458 l +1079 459 l +f +*U +0.000 0.314 0.251 0.086 k +*u +1141 459 m +1142 458 l +1141 459 l +f +*U +0.000 0.663 0.506 0.337 k +*u +1142.667 458.667 m +1142.222 458.222 1143.278 458.278 1143.333 458.333 c +1143.778 458.778 1142.722 458.722 1142.667 458.667 c +f +*U +0.000 0.757 0.596 0.243 k +*u +1166 459 m +1165 458 l +1165 456 l +1167.364 456.482 1167.518 456.636 1168 459 c +1166 459 l +f +*U +0.000 0.545 0.431 0.455 k +*u +1169.667 458.667 m +1169.222 458.222 1170.278 458.278 1170.333 458.333 c +1170.778 458.778 1169.722 458.722 1169.667 458.667 c +f +*U +0.000 0.447 0.298 0.337 k +*u +1171 459 m +1172 458 l +1171 459 l +f +*U +0.000 0.243 0.161 0.082 k +*u +1172 459 m +1173 458 l +1172 459 l +f +*U +0.000 0.325 0.220 0.039 k +*u +1283 459 m +1284 458 l +1283 459 l +f +*U +0.000 0.549 0.380 0.329 k +*u +1305.667 458.667 m +1305.222 458.222 1306.278 458.278 1306.333 458.333 c +1306.778 458.778 1305.722 458.722 1305.667 458.667 c +f +*U +0.000 0.298 0.212 0.000 k +*u +1307 459 m +1308 458 l +1307 459 l +f +*U +0.000 0.000 0.000 0.361 k +*u +1040 458 m +1041 457 l +1040 458 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1078 458 m +1079 457 l +1078 458 l +f +*U +0.000 0.235 0.180 0.090 k +*u +1139 458 m +1140 457 l +1139 458 l +f +*U +0.000 0.749 0.565 0.251 k +*u +1139 456 m +1140.580 456.683 1140.777 456.805 1142 458 c +1140.420 457.316 1140.223 457.195 1139 456 c +f +*U +0.000 0.443 0.337 0.557 k +*u +1168 458 m +1169 457 l +1168 458 l +f +*U +0.000 0.404 0.267 0.192 k +*u +1169 458 m +1170 457 l +1169 458 l +f +*U +0.000 0.392 0.282 0.361 k +*u +1308 458 m +1309 457 l +1308 458 l +f +*U +0.000 0.000 0.000 0.722 k +*u +1378 458 m +1379 457 l +1378 458 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1039 457 m +1040 456 l +1039 457 l +f +*U +0.000 0.302 0.212 0.278 k +*u +1138 457 m +1139 456 l +1138 457 l +f +*U +0.000 0.278 0.271 0.122 k +*u +1284 457 m +1285 456 l +1284 457 l +f +*U +0.000 0.769 0.482 0.224 k +*u +1304 456 m +1306.332 455 1308.457 455 1311 455 c +1308.644 456.371 1306.743 456 1304 456 c +f +*U +0.000 0.298 0.208 0.306 k +*u +1310 457 m +1311 456 l +1310 457 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1038 456 m +1039 455 l +1038 456 l +f +*U +0.000 0.569 0.459 0.165 k +*u +1136 456 m +1137 455 l +1136 456 l +f +*U +0.000 0.741 0.506 0.259 k +*u +1136 454 m +1137.580 454.683 1137.778 454.805 1139 456 c +1137.420 455.316 1137.223 455.195 1136 454 c +f +*U +0.000 0.557 0.396 0.443 k +*u +1163.667 455.667 m +1163.222 455.222 1164.278 455.278 1164.333 455.333 c +1164.778 455.778 1163.722 455.722 1163.667 455.667 c +f +*U +0.000 0.278 0.212 0.212 k +*u +1165 456 m +1166 455 l +1165 456 l +f +*U +0.000 0.314 0.200 0.459 k +*u +1285 456 m +1286 455 l +1285 456 l +f +*U +0.000 0.596 0.396 0.404 k +*u +1286 456 m +1286 453 l +1286.696 454.554 1286.696 454.446 1286 456 c +f +*U +0.000 0.243 0.224 0.055 k +*u +1312 456 m +1313 455 l +1312 456 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1038 455 m +1033.585 449.946 1028.679 441.305 1022.826 438 c +1018.671 435.701 1011.614 437 1007 437 c +969 437 l +833 437 l +243 437 l +109 437 l +68 437 l +58.250 437 48.548 437.463 39 435 c +24.783 431.584 11 422.596 4.901 409 c +1.701 402 0.947 394.492 0 387 c +2 388.988 2.579 390 3 393 c +5 388 l +3 386.181 3.920 385.305 6 384 c +6 385.797 5.986 385.522 5 387 c +6.635 386.455 6.455 386.635 7 385 c +9 390.551 7 395.360 4 400 c +8 399 l +7.693 401 7.618 401.686 6 403 c +7.409 405.564 8.403 406.670 11 408 c +8 411 l +12 410 l +11.402 411.195 11.534 410.977 10 412 c +11.416 412.472 11.814 412.814 13 414 c +15.367 410.507 17.329 418.372 19 420 c +18.782 418.313 18.776 417.684 19 416 c +21.437 417.306 22.694 418.563 24 421 c +22.316 421.224 21.687 421.218 20 421 c +24 424.478 32 424.227 31 431 c +35.444 431.946 39.463 432.483 44 432 c +43 434 l +44.723 433 46 432.465 48 432 c +49 436 l +53 435 l +49 434 l +54.619 430.634 62.653 432 69 432 c +114 432 l +282 432 l +804 432 l +954 432 l +997 432 l +1004.677 432 1012.812 430.954 1020 434 c +1019 432 l +1022.312 432.552 1024 431.678 1028 433 c +1029 432 l +1029 434 l +1030.186 432.964 1030.604 432.661 1032 432 c +1031.548 433.863 1030.908 435.308 1030 437 c +1032 436 l +1031.454 441.569 1032.295 444.690 1036 449 c +1036 447 l +1040 450 l +1039.676 452.204 1039.433 453.328 1038 455 c +f +*U +0.000 0.192 0.114 0.153 k +*u +1134 455 m +1135 454 l +1134 455 l +f +*U +0.000 0.322 0.196 0.529 k +*u +1135 455 m +1136 454 l +1135 455 l +f +*U +0.000 0.482 0.388 0.518 k +*u +1161.667 454.667 m +1161.222 454.222 1162.278 454.278 1162.333 454.333 c +1162.778 454.777 1161.722 454.722 1161.667 454.667 c +f +*U +0.000 0.361 0.267 0.153 k +*u +1163 455 m +1164 454 l +1163 455 l +f +*U +0.000 0.369 0.357 0.475 k +*u +1312.667 454.667 m +1312.222 454.222 1313.278 454.278 1313.333 454.333 c +1313.778 454.778 1312.722 454.722 1312.667 454.667 c +f +*U +0.000 0.000 0.000 0.749 k +*u +1417 455 m +1418 454 l +1417 455 l +f +*U +0.000 0.349 0.220 0.263 k +*u +1133 454 m +1134 453 l +1133 454 l +f +*U +0.000 0.714 0.557 0.286 k +*u +1131 452 m +1133 451.590 1133.963 452 1136 453 c +1133.859 453.410 1133 452.968 1131 452 c +f +*U +0.000 0.369 0.318 0.631 k +*u +1160 454 m +1161 453 l +1160 454 l +f +*U +0.000 0.353 0.259 0.122 k +*u +1161 454 m +1162 453 l +1161 454 l +f +*U +0.000 0.812 0.600 0.188 k +*u +1312 454 m +1313.446 449.667 1316.885 449 1321 448 c +1318.952 451.731 1316 453.201 1312 454 c +f +*U +0.000 0.427 0.341 0.169 k +*u +1315 454 m +1316 453 l +1315 454 l +f +*U +0.020 0.024 0.000 0.753 k +*u +1382 454 m +1383 453 l +1382 454 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1418 454 m +1419 453 l +1418 454 l +f +*U +0.000 0.341 0.227 0.129 k +*u +1131 453 m +1132 452 l +1131 453 l +f +*U +0.000 0.533 0.388 0.345 k +*u +1157 453 m +1158.248 452.315 1158.548 452.251 1160 452 c +1158.752 452.685 1158.452 452.749 1157 453 c +f +*U +0.000 0.275 0.188 0.059 k +*u +1286 453 m +1287 452 l +1286 453 l +f +*U +0.000 0.529 0.357 0.471 k +*u +1287.333 452.333 m +1287.278 452.278 1287.222 451.222 1287.667 451.667 c +1287.723 451.723 1287.777 452.778 1287.333 452.333 c +f +*U +0.000 0.298 0.145 0.102 k +*u +1317 453 m +1318 452 l +1317 453 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1419 453 m +1420 452 l +1419 453 l +f +*U +0.000 0.282 0.188 0.310 k +*u +1130 452 m +1131 451 l +1130 452 l +f +*U +0.000 0.604 0.482 0.396 k +*u +1156 452 m +1157 451 l +1156 452 l +f +*U +0.000 0.396 0.286 0.220 k +*u +1157 452 m +1158 451 l +1157 452 l +f +*U +0.000 0.282 0.208 0.357 k +*u +1318 452 m +1319 451 l +1318 452 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1034 451 m +1035 450 l +1034 451 l +f +*U +0.000 0.435 0.239 0.094 k +*u +1128 451 m +1129 450 l +1128 451 l +f +*U +0.000 0.639 0.459 0.361 k +*u +1129.667 450.667 m +1129.222 450.222 1130.278 450.278 1130.333 450.333 c +1130.778 450.778 1129.722 450.722 1129.667 450.667 c +f +*U +0.000 0.867 0.675 0.133 k +*u +1129 450 m +1131 449 1132.747 449 1135 449 c +1132.787 450.393 1131.609 450.374 1129 450 c +f +*U +0.000 0.451 0.329 0.388 k +*u +1154.667 450.667 m +1154.222 450.222 1155.278 450.278 1155.333 450.333 c +1155.778 450.778 1154.722 450.722 1154.667 450.667 c +f +*U +0.000 0.251 0.188 0.122 k +*u +1156 451 m +1157 450 l +1156 451 l +f +*U +0.000 0.298 0.196 0.239 k +*u +1287 451 m +1288 450 l +1287 451 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1288 451 m +1289 450 l +1288 451 l +f +*U +0.000 0.608 0.443 0.341 k +*u +1289 451 m +1290.458 449.919 1291.248 449.564 1293 449 c +1291.457 450.267 1290.952 450.489 1289 451 c +f +*U +0.000 0.000 0.000 0.655 k +*u +1033 450 m +1034 449 l +1033 450 l +f +*U +0.000 0.275 0.196 0.396 k +*u +1127 450 m +1128 449 l +1127 450 l +f +*U +0.000 0.741 0.741 0.259 k +*u +1128 450 m +1131.989 445.435 1146 448 1152 448 c +1144.846 451 1135.658 448.177 1128 450 c +f +*U +0.000 0.510 0.416 0.490 k +*u +1153 450 m +1154 449 l +1153 450 l +f +*U +0.000 0.298 0.239 0.192 k +*u +1154 450 m +1155 449 l +1154 450 l +f +*U +0.000 0.208 0.169 0.141 k +*u +1290 450 m +1291 449 l +1290 450 l +f +*U +0.000 0.337 0.267 0.004 k +*u +1321 450 m +1322 449 l +1321 450 l +f +*U +0.000 0.000 0.000 0.361 k +*u +1032 449 m +1033 448 l +1032 449 l +f +*U +0.000 0.141 0.114 0.259 k +*u +1125 449 m +1126 448 l +1125 449 l +f +*U +0.000 0.271 0.271 0.729 k +*u +1126.667 448.667 m +1126.222 448.222 1127.278 448.278 1127.333 448.333 c +1127.778 448.778 1126.722 448.722 1126.667 448.667 c +f +*U +0.000 0.192 0.188 0.263 k +*u +1152 449 m +1153 448 l +1152 449 l +f +*U +0.000 0.573 0.514 0.427 k +*u +1292.667 448.667 m +1292.222 448.222 1293.278 448.278 1293.333 448.333 c +1293.778 448.778 1292.722 448.722 1292.667 448.667 c +f +*U +0.000 0.753 0.753 0.247 k +*u +1294 449 m +1301.169 445.992 1312.239 448 1320 448 c +1312.831 451 1301.761 449 1294 449 c +f +*U +0.000 0.373 0.282 0.549 k +*u +1321.667 448.667 m +1321.222 448.222 1322.278 448.278 1322.333 448.333 c +1322.778 448.778 1321.722 448.722 1321.667 448.667 c +f +*U +0.000 0.000 0.000 0.780 k +*u +1422 449 m +1423 448 l +1422 449 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1031 448 m +1032 447 l +1031 448 l +f +*U +0.094 0.000 0.027 0.216 k +*u +1294 448 m +1295.248 447.315 1295.548 447.251 1297 447 c +1295.752 447.685 1295.451 447.749 1294 448 c +f +*U +0.000 0.000 0.000 0.796 k +*u +1423 448 m +1424 447 l +1423 448 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1030 447 m +1031 446 l +1030 447 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1066 447 m +1067 446 l +1066 447 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1424 447 m +1425 446 l +1424 447 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1389 446 m +1390 445 l +1389 446 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1426 444 m +1427 443 l +1426 444 l +f +*U +0.000 0.000 0.000 0.541 k +*u +1027 443 m +1028 442 l +1027 443 l +f +*U +0.000 0.000 0.000 0.298 k +*u +1392 443 m +1393 442 l +1392 443 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1427 443 m +1428 442 l +1427 443 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1026 442 m +1027 441 l +1026 442 l +f +*U +0.000 0.000 0.000 0.545 k +*u +1393 442 m +1394 441 l +1393 442 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1428 442 m +1429 441 l +1428 442 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1025 441 m +1026 440 l +1025 441 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1394 441 m +1395 440 l +1394 441 l +f +*U +0.012 0.000 0.016 0.000 k +*u +48 440 m +52 437 l +58.834 440.647 68.400 439 76 439 c +129 439 l +322 439 l +1023 439 l +1015.841 442 1004.744 440 997 440 c +940 440 l +740 440 l +48 440 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1395 440 m +1396 439 l +1395 440 l +f +*U +0.000 0.000 0.000 0.729 k +*u +1024 439 m +1025 438 l +1024 439 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1059 439 m +1060 438 l +1059 439 l +f +*U +0.000 0.000 0.000 0.408 k +*u +1430 439 m +1431 438 l +1430 439 l +f +*U +0.000 0.000 0.000 0.004 k +*u +1439 436 m +1445.817 437.623 1453 437 1460 437 c +1495 437 l +1608 437 l +1969 437 l +1965.730 439.477 1962 439.000 1958 439 c +1939 439 l +1861 439 l +1558 439 l +1469 439 l +1448 439 l +1444.213 438.992 1441.171 439.349 1439 436 c +f +*U +0.024 0.000 0.027 0.102 k +*u +52 438 m +59 434.996 70.256 437 78 437 c +135 437 l +333 437 l +1022 437 l +1014.841 440 1003.744 438 996 438 c +939 438 l +740 438 l +52 438 l +f +*U +0.024 0.000 0.031 0.325 k +*u +1022.667 437.667 m +1022.222 437.222 1023.278 437.278 1023.333 437.333 c +1023.778 437.778 1022.722 437.722 1022.667 437.667 c +f +*U +0.000 0.000 0.000 0.200 k +*u +1058 438 m +1059 437 l +1058 438 l +f +*U +0.000 0.000 0.000 0.325 k +*u +1431 438 m +1432 437 l +1431 438 l +f +*U +0.000 0.000 0.000 0.420 k +*u +44 437 m +45 436 l +44 437 l +f +*U +0.000 0.000 0.000 0.588 k +*u +45 437 m +46 436 l +45 437 l +f +*U +0.000 0.000 0.000 0.824 k +*u +46 437 m +47 436 l +46 437 l +f +*U +0.000 0.000 0.000 0.263 k +*u +1057 437 m +1058 436 l +1057 437 l +f +*U +0.000 0.224 0.169 0.035 k +*u +1110 437 m +1111 436 l +1110 437 l +f +*U +0.000 0.529 0.408 0.471 k +*u +1111 437 m +1117.584 434.237 1125.949 436.679 1133 435 c +1129.196 439.354 1116.561 437 1111 437 c +f +*U +0.000 0.373 0.271 0.592 k +*u +1133.667 436.667 m +1133.222 436.222 1134.278 436.278 1134.333 436.333 c +1134.778 436.778 1133.722 436.722 1133.667 436.667 c +f +*U +0.000 0.514 0.420 0.486 k +*u +1298 435 m +1307.524 437.267 1318.247 436 1328 436 c +1321.814 438.596 1312.678 437 1306 437 c +1302.895 436.994 1300 437.407 1298 435 c +f +*U +0.000 0.604 0.486 0.396 k +*u +1328 437 m +1331.366 435.584 1335.373 435.673 1339 435 c +1335.734 437.474 1331.990 437.000 1328 437 c +f +*U +0.000 0.000 0.000 0.537 k +*u +40 436 m +41 435 l +40 436 l +f +*U +0.004 0.000 0.004 0.996 k +*u +57 436 m +63.919 433 74.520 435 82 435 c +139 435 l +335 435 l +1015 435 l +1008 437.903 997.480 436 990 436 c +933 436 l +737 436 l +57 436 l +f +*U +0.000 0.000 0.000 0.475 k +*u +1056 436 m +1057 435 l +1056 436 l +f +*U +0.000 0.263 0.204 0.357 k +*u +1109 436 m +1110 435 l +1109 436 l +f +*U +0.000 0.545 0.447 0.455 k +*u +1110 436 m +1111 435 l +1110 436 l +f +*U +0.000 0.863 0.604 0.137 k +*u +1106 427 m +1101 427 l +1101 425 l +1121 425 l +1123.329 429.352 1128.185 431.948 1132 435 c +1124.775 438 1104.947 438.189 1106 427 c +f +*U +0.000 0.353 0.259 0.176 k +*u +1133 436 m +1134 435 l +1133 436 l +f +*U +0.000 0.875 0.624 0.125 k +*u +1299 436 m +1298.808 431.871 1297.540 428.769 1296 425 c +1348 425 l +1338.944 441.346 1314.725 436 1299 436 c +f +*U +0.000 0.173 0.157 0.192 k +*u +1339 436 m +1340 435 l +1339 436 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1398 436 m +1399 435 l +1398 436 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1432 436 m +1433 435 l +1432 436 l +f +*U +0.000 0.000 0.000 0.451 k +*u +36 435 m +37 434 l +36 435 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1055 435 m +1056 434 l +1055 435 l +f +*U +0.000 0.282 0.239 0.176 k +*u +1108 435 m +1109 434 l +1108 435 l +f +*U +0.000 0.506 0.431 0.494 k +*u +1131 435 m +1132 434 l +1131 435 l +f +*U +0.000 0.227 0.176 0.122 k +*u +1132 435 m +1133 434 l +1132 435 l +f +*U +0.000 0.518 0.475 0.090 k +*u +1298.333 434.333 m +1298.278 434.278 1298.222 433.222 1298.667 433.667 c +1298.723 433.723 1298.777 434.777 1298.333 434.333 c +f +*U +0.000 0.725 0.549 0.275 k +*u +1339 435 m +1340.324 432.313 1341.313 431.324 1344 430 c +1342.451 432 1341 433.451 1339 435 c +f +*U +0.000 0.294 0.224 0.098 k +*u +1340 435 m +1341 434 l +1340 435 l +f +*U +0.000 0.000 0.000 0.475 k +*u +1399 435 m +1400 434 l +1399 435 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1974 435 m +1974 410 l +1976.413 415.750 1976.413 429.250 1974 435 c +f +*U +0.000 0.000 0.000 0.400 k +*u +33 434 m +34 433 l +33 434 l +f +*U +0.000 0.000 0.000 0.988 k +*u +55 434 m +61.919 431 72.520 433 80 433 c +137 433 l +334 433 l +1016 433 l +1009 435.903 998.480 434 991 434 c +934 434 l +737 434 l +55 434 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1054 434 m +1055 433 l +1054 434 l +f +*U +0.000 0.416 0.325 0.133 k +*u +1107 434 m +1108 433 l +1107 434 l +f +*U +0.000 0.529 0.392 0.318 k +*u +1129 434 m +1129 432 l +1130.635 432.545 1130.455 432.365 1131 434 c +1129 434 l +f +*U +0.000 0.294 0.235 0.220 k +*u +1341 434 m +1342 433 l +1341 434 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1400 434 m +1401 433 l +1400 434 l +f +*U +0.000 0.000 0.000 0.220 k +*u +30 433 m +31 432 l +30 433 l +f +*U +0.000 0.000 0.000 0.592 k +*u +31 433 m +32 432 l +31 433 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1053 433 m +1054 432 l +1053 433 l +f +*U +0.000 0.349 0.282 0.247 k +*u +1106 433 m +1107 432 l +1106 433 l +f +*U +0.000 0.514 0.369 0.427 k +*u +1298 433 m +1298 430 l +1298.696 431.554 1298.696 431.446 1298 433 c +f +*U +0.000 0.227 0.200 0.263 k +*u +1342 433 m +1343 432 l +1342 433 l +f +*U +0.000 0.000 0.000 0.384 k +*u +28 432 m +29 431 l +28 432 l +f +*U +0.000 0.412 0.314 0.208 k +*u +1105 432 m +1106 431 l +1105 432 l +f +*U +0.063 0.000 0.012 0.275 k +*u +1128 432 m +1129 431 l +1128 432 l +f +*U +0.000 0.624 0.522 0.067 k +*u +1343 432 m +1344 431 l +1343 432 l +f +*U +0.000 0.000 0.000 0.349 k +*u +26 431 m +27 430 l +26 431 l +f +*U +0.000 0.753 0.576 0.235 k +*u +1104 431 m +1102 427 l +1106 427 l +1106 431 l +1104 431 l +f +*U +0.000 0.478 0.349 0.416 k +*u +1124 428 m +1125.457 429 1125.897 429.543 1127 431 c +1124.876 430 1124.899 430 1124 428 c +f +*U +0.000 0.188 0.149 0.082 k +*u +1127 431 m +1128 430 l +1127 431 l +f +*U +0.000 0.137 0.145 0.412 k +*u +1344 431 m +1345 430 l +1344 431 l +f +*U +0.000 0.000 0.000 0.239 k +*u +24 430 m +25 429 l +24 430 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1051 430 m +1052 429 l +1051 430 l +f +*U +0.000 0.400 0.227 0.310 k +*u +1103 430 m +1104 429 l +1103 430 l +f +*U +0.000 0.263 0.216 0.090 k +*u +1297 430 m +1298 429 l +1297 430 l +f +*U +0.000 0.369 0.306 0.271 k +*u +1345 430 m +1346 429 l +1345 430 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1403 430 m +1404 429 l +1403 430 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1050 429 m +1051 428 l +1050 429 l +f +*U +0.000 0.553 0.455 0.447 k +*u +1297.333 428.333 m +1297.278 428.278 1297.222 427.222 1297.667 427.667 c +1297.722 427.722 1297.778 428.778 1297.333 428.333 c +f +*U +0.000 0.314 0.369 0.192 k +*u +1346 429 m +1347 428 l +1346 429 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1404 429 m +1405 428 l +1404 429 l +f +*U +0.000 0.000 0.000 0.451 k +*u +21 428 m +22 427 l +21 428 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1049 428 m +1050 427 l +1049 428 l +f +*U +0.000 0.325 0.267 0.298 k +*u +1101 428 m +1102 427 l +1101 428 l +f +*U +0.000 0.686 0.518 0.306 k +*u +1121 428 m +1121 426 l +1122.635 426.545 1122.455 426.365 1123 428 c +1121 428 l +f +*U +0.000 0.365 0.294 0.259 k +*u +1123 428 m +1124 427 l +1123 428 l +f +*U +0.000 0.227 0.192 0.086 k +*u +1296 428 m +1297 427 l +1296 428 l +f +*U +0.000 0.325 0.212 0.282 k +*u +1347 428 m +1348 427 l +1347 428 l +f +*U +0.000 0.412 0.325 0.341 k +*u +1100 427 m +1101 426 l +1100 427 l +f +*U +0.000 0.310 0.263 0.204 k +*u +1122 427 m +1123 426 l +1122 427 l +f +*U +0.000 0.420 0.392 0.580 k +*u +1347 427 m +1348 426 l +1347 427 l +f +*U +0.000 0.220 0.235 0.239 k +*u +1348 427 m +1349 426 l +1348 427 l +f +*U +0.000 0.000 0.000 0.188 k +*u +18 426 m +19 425 l +18 426 l +f +*U +0.000 0.349 0.263 0.290 k +*u +1099 426 m +1100 425 l +1099 426 l +f +*U +0.000 0.533 0.482 0.467 k +*u +1099 425 m +1100.769 424.221 1102 424 1104 424 c +1102 425 1101.229 425 1099 425 c +f +*U +0.000 0.357 0.255 0.192 k +*u +1121 426 m +1122 425 l +1121 426 l +f +*U +0.000 0.173 0.125 0.329 k +*u +1295 426 m +1296 425 l +1295 426 l +f +*U +0.000 0.592 0.471 0.408 k +*u +1303 425 m +1307.720 423 1313.920 424 1319 424 c +1350 424 l +1346.182 426.207 1340.402 425 1336 425 c +1303 425 l +f +*U +0.000 0.278 0.247 0.239 k +*u +1349 426 m +1350 425 l +1349 426 l +f +*U +0.000 0.000 0.000 0.275 k +*u +1406 426 m +1407 425 l +1406 426 l +f +*U +0.000 0.000 0.000 0.773 k +*u +17 425 m +18 424 l +17 425 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1047 425 m +1048 424 l +1047 425 l +f +*U +0.000 0.192 0.161 0.447 k +*u +1098 425 m +1099 424 l +1098 425 l +f +*U +0.000 0.616 0.518 0.384 k +*u +1104 425 m +1108.724 423 1114.910 424 1120 424 c +1115.276 425.982 1109 425 1104 425 c +f +*U +0.000 0.082 0.051 0.380 k +*u +1120 425 m +1121 424 l +1120 425 l +f +*U +0.000 0.239 0.180 0.576 k +*u +1294 425 m +1295 424 l +1294 425 l +f +*U +0.000 0.400 0.400 0.600 k +*u +1295 425 m +1297.613 423.902 1300 424 1303 424 c +1300.387 425 1297.836 424.993 1295 425 c +f +*U +0.000 0.239 0.129 0.278 k +*u +1350 425 m +1351 424 l +1350 425 l +f +*U +0.000 0.000 0.004 0.361 k +*u +1407 425 m +1408 424 l +1407 425 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1046 424 m +1047 423 l +1046 424 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1045 423 m +1046 422 l +1045 423 l +f +*U +0.008 0.008 0.000 0.200 k +*u +1409 422 m +1410 421 l +1409 422 l +f +*U +0.008 0.008 0.000 0.643 k +*u +1410 421 m +1411 420 l +1410 421 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1043 420 m +1044 419 l +1043 420 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1042 419 m +1043 418 l +1042 419 l +f +*U +0.000 0.000 0.000 0.792 k +*u +10 418 m +11 417 l +10 418 l +f +*U +0.008 0.008 0.000 0.494 k +*u +1412 418 m +1413 417 l +1412 418 l +f +*U +0.000 0.000 0.000 0.533 k +*u +9 417 m +10 416 l +9 417 l +f +*U +0.000 0.000 0.000 1.000 k +*u +56 416 m +63 412.996 74.256 415 82 415 c +139 415 l +337 415 l +1024 415 l +1014.317 412 1002 414 992 414 c +927 414 l +713 414 l +287 414 l +150 414 l +120.557 414 90.368 412 61 414 c +56.305 414.375 51.748 415.650 47 416 c +48 414 l +46.365 414.545 46.545 414.365 46 416 c +42 415 l +42 413.203 42 413.479 43 412 c +40.734 411.657 38.346 411.382 40 414 c +39 412 l +40.618 413.314 40.693 413.877 41 416 c +38.711 415.239 35.767 414.630 34.328 412.490 c +32 409.247 33.743 405.592 29 405 c +29 399 l +27 404 l +24 404 l +24.768 402.686 24.686 402.768 26 402 c +24 399 24.308 396.349 24 393 c +25.267 391.457 25.489 390.952 26 389 c +25 391 l +21.895 383.601 24 372 24 364 c +24 305 l +15.957 305 7.998 305.609 0 305 c +7.409 301.891 18.975 304 27 304 c +27 371 l +27 381.888 25.902 394 33.380 402.960 c +41.502 412.660 53.403 413 65 413 c +101 413 l +286 413 l +823 413 l +974 413 l +1015 413 l +1024 413 1032.654 412 1041 416 c +1038.167 416.926 1036.303 415.540 1033.424 415.394 c +1027 415 1020.376 416 1014 416 c +952 416 l +745 416 l +56 416 l +f +*U +0.000 0.000 0.000 0.212 k +*u +8 416 m +9 415 l +8 416 l +f +*U +0.024 0.024 0.000 0.976 k +*u +1424 416 m +1428.720 414 1434.920 415 1440 415 c +1472 415 l +1583 415 l +1968 415 l +1963.280 416.981 1957 416 1952 416 c +1921 416 l +1810 416 l +1424 416 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1037 415 m +1038 414 l +1037 415 l +f +*U +0.000 0.000 0.000 0.298 k +*u +1038 415 m +1039 414 l +1038 415 l +f +*U +0.008 0.000 0.012 0.988 k +*u +1422 415 m +1425.691 412.204 1430.515 413 1435 413 c +1461 413 l +1566 413 l +1969 413 l +1964.785 414.769 1959.536 414 1955 414 c +1926 414 l +1825 414 l +1555 414 l +1469 414 l +1453.686 414 1437 412.200 1422 415 c +f +*U +0.000 0.000 0.000 0.647 k +*u +7 414 m +8 413 l +7 414 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1035 414 m +1036 413 l +1035 414 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1036 414 m +1037 413 l +1036 414 l +f +*U +0.000 0.255 0.075 0.110 k +*u +1089 414 m +1093.471 412 1099.183 413 1104 413 c +1099.529 414.876 1093.817 414 1089 414 c +f +*U +0.000 0.361 0.220 0.047 k +*u +1104 414 m +1105.769 413.221 1107 413 1109 413 c +1107.231 413.779 1105.964 413.912 1104 414 c +f +*U +0.000 0.251 0.063 0.114 k +*u +1298 414 m +1303.217 411.811 1310.381 413 1316 413 c +1352 413 l +1346.784 415.189 1339.619 414 1334 414 c +1298 414 l +f +*U +0.000 0.231 0.161 0.118 k +*u +1352 414 m +1354.613 412.902 1357 413 1360 413 c +1357.387 414 1354.836 413.993 1352 414 c +f +*U +0.000 0.000 0.000 0.173 k +*u +1415 414 m +1416 413 l +1415 414 l +f +*U +0.000 0.000 0.000 0.239 k +*u +6 413 m +7 412 l +6 413 l +f +*U +0.000 0.000 0.000 0.812 k +*u +50 413 m +51 412 l +50 413 l +f +*U +0.000 0.000 0.000 0.490 k +*u +51 413 m +58 409.996 69.256 412 77 412 c +135 412 l +336 412 l +1033 412 l +1025.841 415 1014.744 413 1007 413 c +949 413 l +748 413 l +51 413 l +f +*U +0.000 0.690 0.486 0.310 k +*u +1088 413 m +1088 411 l +1090 411 l +1089.455 412.635 1089.635 412.455 1088 413 c +f +*U +0.000 0.733 0.722 0.267 k +*u +1089.667 412.667 m +1089.222 412.222 1090.278 412.278 1090.333 412.333 c +1090.778 412.778 1089.722 412.722 1089.667 412.667 c +f +*U +0.000 0.800 0.875 0.125 k +*u +1091 413 m +1095.724 411 1101.910 412 1107 412 c +1102.276 413.982 1096 413 1091 413 c +f +*U +0.000 0.475 0.525 0.475 k +*u +1107 413 m +1108 412 l +1107 413 l +f +*U +0.000 0.227 0.302 0.259 k +*u +1108 413 m +1109 412 l +1108 413 l +f +*U +0.000 0.565 0.420 0.396 k +*u +1298 413 m +1298 408 l +1298.830 410 1298.830 410.970 1298 413 c +f +*U +0.000 0.773 0.855 0.145 k +*u +1299 413 m +1303.969 410.915 1310.650 412 1316 412 c +1352 412 l +1347 414 1340.350 413 1335 413 c +1299 413 l +f +*U +0.000 0.859 0.612 0.137 k +*u +1352 413 m +1354 412 1355.747 412 1358 412 c +1358 410 l +1315 410 l +1306 410 1296.397 408.986 1291 401 c +1294.474 401.231 1297.560 402.704 1301 402.946 c +1314.869 403.916 1329 403 1343 403 c +1346.604 403 1358.640 401 1360.824 404.545 c +1363.322 408.491 1353.592 407.999 1352 408 c +1355.590 409 1358.703 408.815 1361 412 c +1357.959 412.900 1355.169 412.992 1352 413 c +f +*U +0.000 0.278 0.180 0.345 k +*u +1360 413 m +1361 412 l +1360 413 l +f +*U +0.000 0.000 0.000 0.525 k +*u +1417 413 m +1418 412 l +1417 413 l +f +*U +0.000 0.000 0.000 0.686 k +*u +46 412 m +47 411 l +46 412 l +f +*U +0.000 0.000 0.000 0.192 k +*u +47 412 m +48 411 l +47 412 l +f +*U +0.000 0.235 0.149 0.337 k +*u +1087 412 m +1088 411 l +1087 412 l +f +*U +0.000 0.851 0.596 0.141 k +*u +1082 401 m +1086.620 401 1093.403 399.742 1097.696 401.603 c +1100.704 402.908 1102.175 406.339 1105 408 c +1103.272 413.208 1093.657 413.509 1089.299 410.825 c +1086.243 408.943 1083.492 404 1082 401 c +f +*U +0.000 0.808 0.718 0.173 k +*u +1104 412 m +1105 410 l +1106.635 410.545 1106.455 410.365 1107 412 c +1104 412 l +f +*U +0.000 0.286 0.275 0.235 k +*u +1107 412 m +1108 411 l +1107 412 l +f +*U +0.000 0.925 0.663 0.075 k +*u +1299 412 m +1299 408 l +1318.474 410.576 1338.184 410 1358 410 c +1358 412 l +1338.254 411.592 1318.764 410.440 1299 412 c +f +*U +0.000 0.843 0.580 0.157 k +*u +1303 412 m +1307.720 410 1313.920 411 1319 411 c +1352 411 l +1347.280 412.981 1341 412 1336 412 c +1303 412 l +f +*U +0.000 0.263 0.173 0.157 k +*u +1361 412 m +1362 411 l +1361 412 l +f +*U +0.000 0.000 0.000 0.541 k +*u +1419 412 m +1420 411 l +1419 412 l +f +*U +0.000 0.000 0.000 0.341 k +*u +5 411 m +6 410 l +5 411 l +f +*U +0.000 0.000 0.000 0.624 k +*u +43 411 m +44 410 l +43 411 l +f +*U +0.000 0.365 0.243 0.173 k +*u +1086 411 m +1087 410 l +1086 411 l +f +*U +0.000 0.471 0.337 0.529 k +*u +1087 411 m +1088 410 l +1087 411 l +f +*U +0.000 0.333 0.310 0.275 k +*u +1106 411 m +1107 410 l +1106 411 l +f +*U +0.000 0.910 0.663 0.090 k +*u +1360 411 m +1357.440 409 1355.192 409 1352 409 c +1356.775 406.991 1359.915 407.950 1363 403 c +1296 403 l +1296 401 l +1367 401 l +1365 404.706 1362.922 408 1360 411 c +f +*U +0.000 0.702 0.498 0.298 k +*u +1361 411 m +1361.683 409.420 1361.805 409.223 1363 408 c +1362.316 409.580 1362.195 409.777 1361 411 c +f +*U +0.000 0.000 0.000 0.188 k +*u +1422 411 m +1423 410 l +1422 411 l +f +*U +0.055 0.063 0.000 0.580 k +*u +1423 411 m +1427.720 409 1433.920 410 1439 410 c +1471 410 l +1583 410 l +1974 410 l +1969.280 411.981 1963 411 1958 411 c +1926 411 l +1813 411 l +1423 411 l +f +*U +0.000 0.000 0.000 0.365 k +*u +41 410 m +42 409 l +41 410 l +f +*U +0.000 0.000 0.000 0.004 k +*u +56 410 m +56 408 l +1032 408 l +1023.793 411.476 1012.764 410 1004 410 c +947 410 l +748 410 l +56 410 l +f +*U +0.000 0.631 0.427 0.369 k +*u +1086 410 m +1085 408.521 1085 408.797 1085 407 c +1086.289 408.443 1086.401 408.234 1086 410 c +f +*U +0.000 0.506 0.247 0.275 k +*u +1105 410 m +1106 409 l +1105 410 l +f +*U +0.000 0.000 0.000 0.200 k +*u +4 409 m +5 408 l +4 409 l +f +*U +0.000 0.000 0.000 0.592 k +*u +39 409 m +40 408 l +39 409 l +f +*U +0.000 0.278 0.165 0.071 k +*u +1297 409 m +1298 408 l +1297 409 l +f +*U +0.000 0.325 0.208 0.306 k +*u +1363 409 m +1364 408 l +1363 409 l +f +*U +0.008 0.008 0.000 0.827 k +*u +35 408 m +36 407 l +35 408 l +f +*U +0.000 0.259 0.302 0.329 k +*u +1084 408 m +1085 407 l +1084 408 l +f +*U +0.000 0.776 0.627 0.071 k +*u +1086 408 m +1085 406 l +1087 406 l +1087 407.853 1087.300 407.350 1086 408 c +f +*U +0.000 0.565 0.439 0.435 k +*u +1102 408 m +1102 406 l +1103.635 406.545 1103.455 406.365 1104 408 c +1102 408 l +f +*U +0.000 0.635 0.486 0.051 k +*u +1296 408 m +1297 407 l +1296 408 l +f +*U +0.000 0.741 0.549 0.239 k +*u +1295 407 m +1297 406.249 1297.596 406.344 1299 408 c +1295 407 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1363.333 407.333 m +1363.278 407.278 1363.222 406.222 1363.667 406.667 c +1363.722 406.723 1363.777 407.778 1363.333 407.333 c +f +*U +0.000 0.204 0.180 0.145 k +*u +1364 408 m +1365 407 l +1364 408 l +f +*U +0.000 0.000 0.000 0.216 k +*u +3 407 m +4 406 l +3 407 l +f +*U +0.008 0.008 0.000 0.737 k +*u +36 407 m +37 406 l +36 407 l +f +*U +0.000 0.447 0.404 0.475 k +*u +1084 407 m +1085 406 l +1084 407 l +f +*U +0.000 0.341 0.224 0.145 k +*u +1294 407 m +1295 406 l +1294 407 l +f +*U +0.000 0.427 0.325 0.573 k +*u +1364 407 m +1365 406 l +1364 407 l +f +*U +0.000 0.000 0.000 0.678 k +*u +3 406 m +4 405 l +3 406 l +f +*U +0.008 0.008 0.000 0.192 k +*u +35 406 m +36 405 l +35 406 l +f +*U +0.000 0.733 0.557 0.267 k +*u +1083 406 m +1083 404 l +1084.635 404.545 1084.455 404.365 1085 406 c +1083 406 l +f +*U +0.000 0.278 0.204 0.063 k +*u +1102 406 m +1103 405 l +1102 406 l +f +*U +0.000 0.337 0.243 0.286 k +*u +1293 406 m +1294 405 l +1293 406 l +f +*U +0.000 0.584 0.451 0.416 k +*u +1365 406 m +1365.406 403.908 1365.217 403.980 1367 403 c +1366.309 404.388 1366 404.861 1365 406 c +f +*U +0.000 0.000 0.000 0.345 k +*u +34 405 m +35 404 l +34 405 l +f +*U +0.000 0.361 0.290 0.278 k +*u +1082 405 m +1083 404 l +1082 405 l +f +*U +0.000 0.325 0.235 0.184 k +*u +1101 405 m +1102 404 l +1101 405 l +f +*U +0.000 0.694 0.561 0.306 k +*u +1292 405 m +1292 403 l +1293.635 403.545 1293.455 403.365 1294 405 c +1292 405 l +f +*U +0.000 0.263 0.208 0.259 k +*u +1366 405 m +1367 404 l +1366 405 l +f +*U +0.000 0.000 0.000 0.173 k +*u +2 404 m +3 403 l +2 404 l +f +*U +0.000 0.000 0.000 0.314 k +*u +33 404 m +34 403 l +33 404 l +f +*U +0.000 0.255 0.220 0.094 k +*u +1081 404 m +1082 403 l +1081 404 l +f +*U +0.000 0.545 0.467 0.455 k +*u +1082 404 m +1083 403 l +1082 404 l +f +*U +0.000 0.353 0.255 0.227 k +*u +1100 404 m +1101 403 l +1100 404 l +f +*U +0.000 0.365 0.302 0.635 k +*u +1291 404 m +1292 403 l +1291 404 l +f +*U +0.000 0.733 0.573 0.267 k +*u +1361.667 403.667 m +1361.222 403.222 1362.278 403.278 1362.333 403.333 c +1362.778 403.778 1361.722 403.722 1361.667 403.667 c +f +*U +0.000 0.000 0.000 0.671 k +*u +2 403 m +3 402 l +2 403 l +f +*U +0.000 0.000 0.008 0.792 k +*u +32 403 m +33 402 l +32 403 l +f +*U +0.000 0.400 0.271 0.545 k +*u +1081 403 m +1080 400 l +1083 400 l +1082.309 401.388 1082 401.861 1081 403 c +f +*U +0.000 0.376 0.302 0.424 k +*u +1099 403 m +1100 402 l +1099 403 l +f +*U +0.000 0.612 0.490 0.388 k +*u +1289 400 m +1303 400 l +1300.722 402.278 1294.392 399.965 1291 402 c +1292 403 l +1289.876 402 1289.899 402 1289 400 c +f +*U +0.000 0.686 0.498 0.294 k +*u +1366 403 m +1366.000 400.649 1365.347 401 1363 401 c +1365.388 399.631 1369.689 400.928 1366 403 c +f +*U +0.000 0.412 0.247 0.239 k +*u +1080 402 m +1081 401 l +1080 402 l +f +*U +0.000 0.380 0.286 0.149 k +*u +1288 402 m +1289 401 l +1288 402 l +f +*U +0.000 0.137 0.086 0.369 k +*u +1368 402 m +1369 401 l +1368 402 l +f +*U +0.000 0.000 0.000 0.267 k +*u +31 401 m +32 400 l +31 401 l +f +*U +0.031 0.000 0.016 0.078 k +*u +1078.667 400.667 m +1078.222 400.222 1079.278 400.278 1079.333 400.333 c +1079.778 400.778 1078.722 400.722 1078.667 400.667 c +f +*U +0.000 0.596 0.439 0.400 k +*u +1083 401 m +1087.471 399 1093.183 400 1098 400 c +1093.529 401.876 1087.817 401 1083 401 c +f +*U +0.031 0.000 0.008 0.455 k +*u +1287 401 m +1288 400 l +1287 401 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1288 401 m +1289 400 l +1288 401 l +f +*U +0.000 0.522 0.400 0.447 k +*u +1303 401 m +1308.463 398.708 1316 400 1322 400 c +1363 400 l +1357.537 402.292 1349.887 401 1344 401 c +1303 401 l +f +*U +0.000 0.243 0.161 0.733 k +*u +1368 401 m +1369 400 l +1368 401 l +f +*U +0.000 0.000 0.000 0.545 k +*u +1 400 m +2 399 l +1 400 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1 399 m +2 398 l +1 399 l +f +*U +0.000 0.000 0.000 0.196 k +*u +30 399 m +31 398 l +30 399 l +f +*U +0.000 0.000 0.000 0.831 k +*u +29 398 m +30 397 l +29 398 l +f +*U +0.000 0.000 0.000 0.322 k +*u +29 397 m +30 396 l +29 397 l +f +*U +0.000 0.000 0.000 0.467 k +*u +0 395 m +0 392 l +0.696 393.554 0.696 393.446 0 395 c +f +*U +0.000 0.000 0.000 0.812 k +*u +28 395 m +29 394 l +28 395 l +f +*U +0.000 0.000 0.000 0.306 k +*u +28 394 m +29 393 l +28 394 l +f +*U +0.000 0.000 0.000 0.859 k +*u +0.333 391.333 m +0.278 391.278 0.222 390.222 0.667 390.667 c +0.722 390.722 0.778 391.778 0.333 391.333 c +f +*U +0.000 0.357 0.333 0.149 k +*u +1073 390 m +1077.974 387.913 1084.638 389 1090 389 c +1085 391 1078.362 390 1073 390 c +f +*U +0.000 0.329 0.247 0.192 k +*u +1285 390 m +1287.613 388.902 1290 389 1293 389 c +1290.387 390 1287.835 389.993 1285 390 c +f +*U +0.000 0.192 0.102 0.114 k +*u +1293.333 389.333 m +1293.278 389.278 1293.222 388.222 1293.667 388.667 c +1293.722 388.722 1293.778 389.778 1293.333 389.333 c +f +*U +0.000 0.369 0.329 0.137 k +*u +1295 388 m +1304.222 390.196 1314.559 389 1324 389 c +1376 389 l +1370.293 391.395 1362 390 1356 390 c +1314 390 l +1308.940 390 1298.508 392 1295 388 c +f +*U +0.000 0.000 0.000 0.812 k +*u +27 389 m +27 304 l +29.395 309.707 28 317.846 28 324 c +28 367 l +28 373.686 29.599 382.806 27 389 c +f +*U +0.000 0.875 0.612 0.125 k +*u +1072 389 m +1070 378 l +1083 378 l +1084 382 1086.260 385.235 1088 389 c +1072 389 l +f +*U +0.000 0.325 0.286 0.475 k +*u +1088 389 m +1088 387 l +1089.635 387.545 1089.455 387.365 1090 389 c +1088 389 l +f +*U +0.000 0.224 0.165 0.286 k +*u +1284 389 m +1285 388 l +1284 389 l +f +*U +0.000 0.635 0.514 0.365 k +*u +1285 389 m +1285 384 l +1285.830 386 1285.830 386.970 1285 389 c +f +*U +0.000 0.824 0.627 0.176 k +*u +1286 389 m +1287.506 388.317 1288.315 388.174 1290 388 c +1289.776 386.316 1289.782 385.687 1290 384 c +1291.255 385.751 1291.614 386.857 1292 389 c +1286 389 l +f +*U +0.000 0.490 0.478 0.510 k +*u +1292 389 m +1293 388 l +1292 389 l +f +*U +0.000 0.678 0.475 0.322 k +*u +1296 389 m +1296.477 385.223 1296 379.552 1299 377 c +1298 381 1298.405 385.480 1296 389 c +f +*U +0.000 0.831 0.643 0.169 k +*u +1297 387 m +1305.923 389 1315.866 388 1325 388 c +1376 388 l +1370.537 390.292 1362.887 389 1357 389 c +1316 389 l +1310.940 389 1300.508 391 1297 387 c +f +*U +0.000 0.165 0.114 0.204 k +*u +1376 389 m +1377 388 l +1376 389 l +f +*U +0.000 0.259 0.192 0.082 k +*u +1284 388 m +1285 387 l +1284 388 l +f +*U +0.000 0.882 0.620 0.118 k +*u +1286 388 m +1285 379 l +1283.814 380 1283.396 380.339 1282 381 c +1282.576 378.313 1284.968 376.798 1287.361 379.333 c +1289.461 381.558 1289.624 385 1290 388 c +1286 388 l +f +*U +0.000 0.341 0.302 0.243 k +*u +1292 388 m +1293 387 l +1292 388 l +f +*U +0.000 0.859 0.620 0.141 k +*u +1298 388 m +1299 382 l +1303 384 l +1303.640 378.907 1315.759 381 1320 381 c +1376 381 l +1369.564 383.701 1359.951 382 1353 382 c +1304 382 l +1311.717 384.281 1320.982 383 1329 383 c +1378 383 l +1374.413 390.540 1364.181 388 1357 388 c +1298 388 l +f +*U +0.000 0.565 0.427 0.435 k +*u +1376.333 387.333 m +1376.278 387.278 1376.222 386.222 1376.667 386.667 c +1376.722 386.722 1376.777 387.778 1376.333 387.333 c +f +*U +0.000 0.337 0.216 0.373 k +*u +1071 387 m +1072 386 l +1071 387 l +f +*U +0.000 0.588 0.451 0.412 k +*u +1086 387 m +1086 385 l +1087.635 385.545 1087.455 385.365 1088 387 c +1086 387 l +f +*U +0.000 0.388 0.290 0.122 k +*u +1377 387 m +1378 386 l +1377 387 l +f +*U +0.000 0.290 0.196 0.043 k +*u +1070 386 m +1071 385 l +1070 386 l +f +*U +0.000 0.667 0.447 0.333 k +*u +1071.333 385.333 m +1071.278 385.278 1071.222 384.222 1071.667 384.667 c +1071.722 384.723 1071.777 385.778 1071.333 385.333 c +f +*U +0.000 0.408 0.306 0.263 k +*u +1087 386 m +1088 385 l +1087 386 l +f +*U +0.000 0.278 0.188 0.106 k +*u +1291 386 m +1292 385 l +1291 386 l +f +*U +0.000 0.498 0.400 0.133 k +*u +1296 386 m +1297 385 l +1296 386 l +f +*U +0.000 0.620 0.459 0.380 k +*u +1377.333 385.333 m +1377.278 385.278 1377.222 384.222 1377.667 384.667 c +1377.722 384.723 1377.777 385.778 1377.333 385.333 c +f +*U +0.000 0.333 0.224 0.341 k +*u +1070 385 m +1071 384 l +1070 385 l +f +*U +0.000 0.435 0.333 0.420 k +*u +1085.667 384.667 m +1085.222 384.222 1086.278 384.278 1086.333 384.333 c +1086.778 384.778 1085.722 384.722 1085.667 384.667 c +f +*U +0.000 0.114 0.090 0.271 k +*u +1284 385 m +1285 384 l +1284 385 l +f +*U +0.000 0.404 0.369 0.004 k +*u +1296 385 m +1297 384 l +1296 385 l +f +*U +0.000 0.196 0.157 0.290 k +*u +1378 385 m +1379 384 l +1378 385 l +f +*U +0.000 0.396 0.263 0.000 k +*u +1069 384 m +1070 383 l +1069 384 l +f +*U +0.000 0.800 0.596 0.200 k +*u +1070 384 m +1069 381 1068.635 379 1071 377 c +1070 384 l +f +*U +0.000 0.698 0.522 0.302 k +*u +1084 384 m +1084 381 l +1084.696 382.554 1084.696 382.446 1084 384 c +f +*U +0.000 0.349 0.298 0.651 k +*u +1085 384 m +1086 383 l +1085 384 l +f +*U +0.000 0.086 0.075 0.169 k +*u +1086 384 m +1087 383 l +1086 384 l +f +*U +0.000 0.773 0.600 0.227 k +*u +1283 384 m +1281.511 381.696 1280 379.503 1279 377 c +1282.306 377 1285.727 376.399 1288 379 c +1284.966 378.476 1283.720 378.400 1282 381 c +1285 379 l +1285.481 381.201 1285.481 381.799 1285 384 c +1283 384 l +f +*U +0.000 0.620 0.522 0.345 k +*u +1289 384 m +1288 380 l +1289.303 381.668 1289.553 381.992 1289 384 c +f +*U +0.000 0.412 0.318 0.318 k +*u +1290 384 m +1291 383 l +1290 384 l +f +*U +0.000 0.890 0.627 0.106 k +*u +1298 384 m +1298 378 l +1378 378 l +1378 383 l +1304 383 l +1310.436 380.299 1320 382 1327 382 c +1376 382 l +1370.309 379.919 1363 381 1357 381 c +1320 381 l +1315.950 381 1303.743 378.929 1303 384 c +1300.987 383.499 1299.961 383.363 1298 384 c +f +*U +0.000 0.612 0.580 0.337 k +*u +1378.333 383.333 m +1378.278 383.278 1378.222 382.222 1378.667 382.667 c +1378.722 382.722 1378.778 383.778 1378.333 383.333 c +f +*U +0.000 0.353 0.255 0.247 k +*u +1085 383 m +1086 382 l +1085 383 l +f +*U +0.000 0.388 0.310 0.612 k +*u +1282 383 m +1283 382 l +1282 383 l +f +*U +0.000 0.329 0.271 0.051 k +*u +1290 383 m +1291 382 l +1290 383 l +f +*U +0.000 0.184 0.141 0.337 k +*u +1379 383 m +1380 382 l +1379 383 l +f +*U +0.000 0.286 0.216 0.051 k +*u +1068 382 m +1069 381 l +1068 382 l +f +*U +0.000 0.863 0.671 0.137 k +*u +1378 382 m +1378 378 l +1299 378 l +1305.436 375.299 1315 377 1322 377 c +1359 377 l +1365.834 377 1373.416 376 1380 378 c +1379.436 379.752 1379 380.542 1378 382 c +f +*U +0.000 0.678 0.518 0.322 k +*u +1379.333 381.333 m +1379.278 381.278 1379.222 380.222 1379.667 380.667 c +1379.722 380.722 1379.778 381.778 1379.333 381.333 c +f +*U +0.000 0.698 0.561 0.302 k +*u +1068 381 m +1068 377 l +1068.710 378.759 1068.710 379.241 1068 381 c +f +*U +0.000 0.443 0.318 0.431 k +*u +1083.333 380.333 m +1083.278 380.278 1083.222 379.222 1083.667 379.667 c +1083.722 379.723 1083.777 380.778 1083.333 380.333 c +f +*U +0.000 0.302 0.220 0.224 k +*u +1084 381 m +1085 380 l +1084 381 l +f +*U +0.000 0.396 0.263 0.192 k +*u +1280 381 m +1281 380 l +1280 381 l +f +*U +0.000 0.325 0.298 0.188 k +*u +1289 381 m +1290 380 l +1289 381 l +f +*U +0.000 0.239 0.145 0.051 k +*u +1296 381 m +1297 380 l +1296 381 l +f +*U +0.000 0.439 0.275 0.145 k +*u +1380 381 m +1381 380 l +1380 381 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1288 380 m +1289 379 l +1288 380 l +f +*U +0.000 0.294 0.192 0.290 k +*u +1296 380 m +1297 379 l +1296 380 l +f +*U +0.000 0.667 0.459 0.333 k +*u +1380 380 m +1379 377 l +1380.766 377.979 1380.956 378.222 1380 380 c +f +*U +0.000 0.361 0.278 0.373 k +*u +1067 379 m +1068 378 l +1067 379 l +f +*U +0.000 0.275 0.200 0.122 k +*u +1083 379 m +1084 378 l +1083 379 l +f +*U +0.000 0.227 0.243 0.400 k +*u +1279 379 m +1280 378 l +1279 379 l +f +*U +0.000 0.204 0.192 0.573 k +*u +1288 379 m +1289 378 l +1288 379 l +f +*U +0.000 0.365 0.325 0.635 k +*u +1296.333 378.333 m +1296.278 378.278 1296.222 377.222 1296.667 377.667 c +1296.723 377.723 1296.777 378.778 1296.333 378.333 c +f +*U +0.000 0.231 0.282 0.224 k +*u +1381 379 m +1382 378 l +1381 379 l +f +*U +0.000 0.396 0.369 0.604 k +*u +1067 378 m +1068 377 l +1067 378 l +f +*U +0.000 0.729 0.584 0.271 k +*u +1071 378 m +1074.698 376.448 1079 377 1083 377 c +1079.302 378.552 1074.983 378 1071 378 c +f +*U +0.000 0.227 0.231 0.173 k +*u +1278 378 m +1279 377 l +1278 378 l +f +*U +0.000 0.341 0.369 0.518 k +*u +1381.333 377.333 m +1381.278 377.278 1381.222 376.222 1381.667 376.667 c +1381.722 376.722 1381.777 377.778 1381.333 377.333 c +f +*U +0.008 0.000 0.039 0.235 k +*u +1066 377 m +1067 376 l +1066 377 l +f +*U +0.000 0.345 0.290 0.271 k +*u +1067 377 m +1068 376 l +1067 377 l +f +*U +0.000 0.345 0.337 0.141 k +*u +1068 377 m +1072.217 375.231 1077.459 376 1082 376 c +1077.783 377.769 1072.541 377 1068 377 c +f +*U +0.000 0.075 0.075 0.141 k +*u +1082 377 m +1083 376 l +1082 377 l +f +*U +0.000 0.078 0.098 0.200 k +*u +1277 377 m +1278 376 l +1277 377 l +f +*U +0.000 0.514 0.420 0.059 k +*u +1278 377 m +1280 376 1281.747 376 1284 376 c +1281.948 376.874 1280.253 376.953 1278 377 c +f +*U +0.000 0.224 0.251 0.192 k +*u +1284 377 m +1285.506 376.317 1286.315 376.174 1288 376 c +1286.494 376.683 1285.685 376.826 1284 377 c +f +*U +0.000 0.408 0.376 0.114 k +*u +1296 377 m +1303 373.996 1314.256 376 1322 376 c +1381 376 l +1373.841 379 1362.744 377 1355 377 c +1296 377 l +f +*U +0.000 0.051 0.055 0.212 k +*u +1061 366 m +1062 365 l +1061 366 l +f +*U +0.000 0.314 0.231 0.306 k +*u +1062 366 m +1063 365 l +1062 366 l +f +*U +0.000 0.388 0.278 0.451 k +*u +1063 366 m +1064 365 l +1063 366 l +f +*U +0.000 0.420 0.306 0.251 k +*u +1064 366 m +1067.432 364.560 1071.300 365 1075 365 c +1071.568 366.440 1067.700 366 1064 366 c +f +*U +0.000 0.204 0.157 0.592 k +*u +1075 366 m +1076 365 l +1075 366 l +f +*U +0.000 0.373 0.251 0.278 k +*u +1262 366 m +1269 362.998 1278.342 365.823 1286 364 c +1282 368.565 1267.868 366 1262 366 c +f +*U +0.000 0.169 0.122 0.188 k +*u +1292 366 m +1293 365 l +1292 366 l +f +*U +0.000 0.373 0.251 0.278 k +*u +1293 366 m +1300.879 362.694 1313.466 365 1322 365 c +1387 365 l +1379 368.306 1366.534 366 1358 366 c +1293 366 l +f +*U +0.000 0.333 0.239 0.298 k +*u +1061 365 m +1062 364 l +1061 365 l +f +*U +0.000 0.886 0.639 0.114 k +*u +1062 365 m +1060.848 361.339 1059.742 357.774 1059 354 c +1067.597 354 1073 355.555 1075 365 c +1062 365 l +f +*U +0.000 0.400 0.365 0.600 k +*u +1075 365 m +1076 364 l +1075 365 l +f +*U +0.000 0.267 0.208 0.145 k +*u +1261.333 364.333 m +1261.278 364.278 1261.222 363.222 1261.667 363.667 c +1261.723 363.723 1261.777 364.778 1261.333 364.333 c +f +*U +0.000 0.871 0.604 0.125 k +*u +1262 365 m +1259.401 357.925 1251.946 358.723 1246 361 c +1241 354 l +1256.413 352.714 1272.503 354 1288 354 c +1384 354 l +1379.785 355.769 1374.536 355 1370 355 c +1343 355 l +1248 355 l +1253.436 356.607 1259.360 356 1265 356 c +1292 356 l +1384 356 l +1379.785 357.769 1374.536 357 1370 357 c +1344 357 l +1252 357 l +1266.222 361.322 1283.269 359 1298 359 c +1384 359 l +1378.697 362.618 1369.285 360 1363 360 c +1310 360 l +1302.427 360 1289.233 357.173 1285 365 c +1262 365 l +f +*U +0.000 0.251 0.188 0.090 k +*u +1291 365 m +1292 364 l +1291 365 l +f +*U +0.000 0.714 0.510 0.286 k +*u +1291 363 m +1292.580 363.683 1292.777 363.805 1294 365 c +1292.420 364.316 1292.223 364.195 1291 363 c +f +*U +0.000 0.839 0.584 0.161 k +*u +1294 363 m +1308.271 366.398 1325.354 364 1340 364 c +1354.951 364 1372.432 366.468 1387 363 c +1383.394 367 1372.217 365 1367 365 c +1313 365 l +1307.940 365 1297.508 367 1294 363 c +f +*U +0.000 0.243 0.184 0.122 k +*u +1387 365 m +1388 364 l +1387 365 l +f +*U +0.000 0.498 0.396 0.502 k +*u +1061.333 363.333 m +1061.278 363.278 1061.222 362.222 1061.667 362.667 c +1061.722 362.722 1061.777 363.778 1061.333 363.333 c +f +*U +0.000 0.341 0.271 0.243 k +*u +1075 364 m +1076 363 l +1075 364 l +f +*U +0.000 0.067 0.067 0.176 k +*u +1088 364 m +1089 363 l +1088 364 l +f +*U +0.000 0.196 0.153 0.208 k +*u +1245 364 m +1246 363 l +1245 364 l +f +*U +0.000 0.694 0.561 0.306 k +*u +1285 364 m +1285.980 362.217 1285.908 362.406 1288 362 c +1286.861 363 1286.388 363.309 1285 364 c +f +*U +0.000 0.290 0.278 0.333 k +*u +1286 364 m +1287 363 l +1286 364 l +f +*U +0.000 0.318 0.227 0.149 k +*u +1290 364 m +1291 363 l +1290 364 l +f +*U +0.000 0.875 0.631 0.114 k +*u +1288 361 m +1295 357.996 1306.256 360 1314 360 c +1361 360 l +1368.555 360 1376.591 361.314 1384 360 c +1371.804 356.395 1355.711 359 1343 359 c +1259 359 l +1262.959 357.339 1267.740 358 1272 358 c +1297 358 l +1384 358 l +1384 354 l +1388 354 l +1386 357 l +1387.479 356 1387.203 356 1389 356 c +1386.575 367 1375 364 1366 364 c +1316 364 l +1306.514 364 1296.677 365.344 1288 361 c +f +*U +0.000 0.537 0.392 0.463 k +*u +1387.333 363.333 m +1387.278 363.278 1387.222 362.222 1387.667 362.667 c +1387.722 362.722 1387.777 363.778 1387.333 363.333 c +f +*U +0.000 0.200 0.141 0.067 k +*u +1060 363 m +1061 362 l +1060 363 l +f +*U +0.000 0.282 0.220 0.424 k +*u +1088 363 m +1089 362 l +1088 363 l +f +*U +0.000 0.204 0.169 0.133 k +*u +1089 363 m +1090 362 l +1089 363 l +f +*U +0.000 0.325 0.318 0.675 k +*u +1245 363 m +1246 362 l +1245 363 l +f +*U +0.000 0.706 0.533 0.294 k +*u +1246 363 m +1244.602 360.950 1243.749 359.354 1243 357 c +1244.867 358.548 1246.438 360 1248 362 c +1246 363 l +f +*U +0.000 0.349 0.271 0.322 k +*u +1261 363 m +1262 362 l +1261 363 l +f +*U +0.000 0.392 0.278 0.361 k +*u +1288 363 m +1289 362 l +1288 363 l +f +*U +0.000 0.753 0.569 0.247 k +*u +1288 361 m +1289.580 361.683 1289.777 361.805 1291 363 c +1289.420 362.316 1289.223 362.195 1288 361 c +f +*U +0.000 0.400 0.275 0.184 k +*u +1060 362 m +1061 361 l +1060 362 l +f +*U +0.000 0.420 0.286 0.251 k +*u +1074 362 m +1075 361 l +1074 362 l +f +*U +0.000 0.424 0.329 0.506 k +*u +1088 362 m +1088 360 l +1090 360 l +1090 362 l +1088 362 l +f +*U +0.000 0.255 0.192 0.149 k +*u +1244 362 m +1245 361 l +1244 362 l +f +*U +0.000 0.341 0.267 0.200 k +*u +1260 362 m +1261 361 l +1260 362 l +f +*U +0.000 0.306 0.224 0.047 k +*u +1388 362 m +1389 361 l +1388 362 l +f +*U +0.000 0.251 0.196 0.227 k +*u +1090 361 m +1091 360 l +1090 361 l +f +*U +0.000 0.365 0.235 0.604 k +*u +1248 361 m +1249 360 l +1248 361 l +f +*U +0.000 0.306 0.200 0.286 k +*u +1249 361 m +1250 360 l +1249 361 l +f +*U +0.000 0.169 0.110 0.098 k +*u +1250 361 m +1251 360 l +1250 361 l +f +*U +0.000 0.255 0.176 0.322 k +*u +1258 361 m +1259 360 l +1258 361 l +f +*U +0.000 0.714 0.580 0.286 k +*u +1259.667 360.667 m +1259.222 360.222 1260.278 360.278 1260.333 360.333 c +1260.778 360.778 1259.722 360.722 1259.667 360.667 c +f +*U +0.000 0.467 0.325 0.306 k +*u +1388 361 m +1389 360 l +1388 361 l +f +*U +0.000 0.290 0.216 0.055 k +*u +1059 360 m +1060 359 l +1059 360 l +f +*U +0.000 0.655 0.510 0.345 k +*u +1072 360 m +1069.176 353.787 1065.243 354 1059 354 c +1063.989 351.907 1074 352.287 1072 360 c +f +*U +0.000 0.247 0.176 0.310 k +*u +1073 360 m +1074 359 l +1073 360 l +f +*U +0.153 0.004 0.000 0.196 k +*u +1087 360 m +1088 359 l +1087 360 l +f +*U +0.000 0.843 0.647 0.157 k +*u +1088 360 m +1088 356 l +1092 356 l +1091 360 l +1088 360 l +f +*U +0.000 0.318 0.204 0.118 k +*u +1243 360 m +1244 359 l +1243 360 l +f +*U +0.000 0.671 0.537 0.329 k +*u +1248 360 m +1250.613 358.902 1253 359 1256 359 c +1253.387 360 1250.836 359.993 1248 360 c +f +*U +0.000 0.502 0.463 0.498 k +*u +1388.333 359.333 m +1388.278 359.278 1388.222 358.222 1388.667 358.667 c +1388.722 358.722 1388.778 359.778 1388.333 359.333 c +f +*U +0.000 0.420 0.294 0.278 k +*u +1059 359 m +1060 358 l +1059 359 l +f +*U +0.000 0.337 0.235 0.055 k +*u +1073 359 m +1074 358 l +1073 359 l +f +*U +0.000 0.220 0.259 0.239 k +*u +1087 359 m +1088 358 l +1087 359 l +f +*U +0.000 0.592 0.471 0.408 k +*u +1091.333 358.333 m +1091.278 358.278 1091.222 357.222 1091.667 357.667 c +1091.722 357.723 1091.777 358.778 1091.333 358.333 c +f +*U +0.000 0.192 0.188 0.278 k +*u +1389 359 m +1390 358 l +1389 359 l +f +*U +0.000 0.639 0.498 0.361 k +*u +1059.333 357.333 m +1059.278 357.278 1059.222 356.222 1059.667 356.667 c +1059.722 356.722 1059.777 357.778 1059.333 357.333 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1087.333 357.333 m +1087.278 357.278 1087.222 356.222 1087.667 356.667 c +1087.722 356.722 1087.777 357.778 1087.333 357.333 c +f +*U +0.000 0.443 0.294 0.004 k +*u +1092 358 m +1093 357 l +1092 358 l +f +*U +0.000 0.349 0.247 0.180 k +*u +1242 358 m +1243 357 l +1242 358 l +f +*U +0.000 0.824 0.620 0.153 k +*u +1252 358 m +1256.215 356.231 1261.465 357 1266 357 c +1292 357 l +1384 357 l +1379.785 358.769 1374.536 358 1370 358 c +1344 358 l +1252 358 l +f +*U +0.000 0.427 0.380 0.329 k +*u +1389 358 m +1390 357 l +1389 358 l +f +*U +0.000 0.337 0.204 0.000 k +*u +1058 357 m +1059 356 l +1058 357 l +f +*U +0.000 0.102 0.067 0.180 k +*u +1072 357 m +1073 356 l +1072 357 l +f +*U +0.000 0.478 0.384 0.224 k +*u +1086 357 m +1087 356 l +1086 357 l +f +*U +0.000 0.455 0.294 0.275 k +*u +1092 357 m +1093 356 l +1092 357 l +f +*U +0.000 0.035 0.067 0.153 k +*u +1210 357 m +1211 356 l +1210 357 l +f +*U +0.000 0.424 0.306 0.278 k +*u +1211.667 356.667 m +1211.222 356.222 1212.278 356.278 1212.333 356.333 c +1212.778 356.778 1211.722 356.722 1211.667 356.667 c +f +*U +0.000 0.592 0.592 0.408 k +*u +1213 357 m +1215 353 l +1215.683 354.506 1215.826 355.315 1216 357 c +1213 357 l +f +*U +0.012 0.149 0.000 0.208 k +*u +1239 357 m +1240 356 l +1239 357 l +f +*U +0.000 0.588 0.373 0.412 k +*u +1240 357 m +1241.249 356.315 1241.548 356.251 1243 356 c +1241.752 356.685 1241.452 356.749 1240 357 c +f +*U +0.000 0.898 0.537 0.102 k +*u +1386 357 m +1386.901 355 1387 355 1389 354 c +1388 355.923 1387.924 355.999 1386 357 c +f +*U +0.000 0.655 0.384 0.345 k +*u +1389 357 m +1389.406 354.908 1389.217 354.980 1391 354 c +1390.309 355.388 1390 355.861 1389 357 c +f +*U +0.000 0.255 0.094 0.118 k +*u +1390.333 356.333 m +1390.278 356.278 1390.222 355.222 1390.667 355.667 c +1390.722 355.722 1390.777 356.778 1390.333 356.333 c +f +*U +0.000 0.416 0.282 0.286 k +*u +1058 356 m +1059 355 l +1058 356 l +f +*U +0.000 0.122 0.176 0.220 k +*u +1082.667 355.667 m +1082.222 355.222 1083.278 355.278 1083.333 355.333 c +1083.778 355.778 1082.722 355.722 1082.667 355.667 c +f +*U +0.000 0.345 0.247 0.290 k +*u +1084 356 m +1085 355 l +1084 356 l +f +*U +0.000 0.686 0.514 0.314 k +*u +1085.667 355.667 m +1085.222 355.222 1086.278 355.278 1086.333 355.333 c +1086.778 355.778 1085.722 355.722 1085.667 355.667 c +f +*U +0.000 0.910 0.651 0.090 k +*u +1085 355 m +1086.506 354.317 1087.315 354.174 1089 354 c +1087.276 355 1087 355 1085 355 c +f +*U +0.000 0.678 0.482 0.216 k +*u +1088 356 m +1089.223 354.805 1089.420 354.684 1091 354 c +1090 355.783 1090 355.594 1088 356 c +f +*U +0.000 0.478 0.329 0.522 k +*u +1091 356 m +1091 353 l +1091.696 354.554 1091.696 354.446 1091 356 c +f +*U +0.000 0.263 0.153 0.067 k +*u +1092 356 m +1093 355 l +1092 356 l +f +*U +0.000 0.125 0.051 0.110 k +*u +1207 356 m +1208 355 l +1207 356 l +f +*U +0.000 0.898 0.643 0.102 k +*u +1208 356 m +1209.926 353.792 1212 354 1215 354 c +1215 356 l +1208 356 l +f +*U +0.000 0.620 0.518 0.380 k +*u +1209.667 355.667 m +1209.222 355.222 1210.278 355.278 1210.333 355.333 c +1210.778 355.778 1209.722 355.722 1209.667 355.667 c +f +*U +0.000 0.161 0.235 0.263 k +*u +1231 356 m +1232 355 l +1231 356 l +f +*U +0.000 0.475 0.380 0.478 k +*u +1232 356 m +1233 355 l +1232 356 l +f +*U +0.000 0.365 0.443 0.149 k +*u +1233 356 m +1234.248 355.315 1234.548 355.251 1236 355 c +1234.751 355.685 1234.452 355.749 1233 356 c +f +*U +0.000 0.467 0.302 0.059 k +*u +1236.667 355.667 m +1236.222 355.222 1237.278 355.278 1237.333 355.333 c +1237.778 355.778 1236.722 355.722 1236.667 355.667 c +f +*U +0.000 0.537 0.482 0.447 k +*u +1238.667 355.667 m +1238.222 355.222 1239.278 355.278 1239.333 355.333 c +1239.778 355.778 1238.722 355.722 1238.667 355.667 c +f +*U +0.000 0.714 0.502 0.286 k +*u +1240 356 m +1240.654 352.946 1242 353 1245 353 c +1241 355 l +1242 356 l +1240 356 l +f +*U +0.000 0.878 0.671 0.122 k +*u +1248 356 m +1252.215 354.231 1257.465 355 1262 355 c +1289 355 l +1384 355 l +1379.785 356.769 1374.536 356 1370 356 c +1343 356 l +1248 356 l +f +*U +0.000 0.361 0.361 0.639 k +*u +1058.333 354.333 m +1058.278 354.278 1058.222 353.222 1058.667 353.667 c +1058.722 353.722 1058.777 354.778 1058.333 354.333 c +f +*U +0.000 0.518 0.341 0.176 k +*u +1071 355 m +1072 354 l +1071 355 l +f +*U +0.000 0.208 0.165 0.027 k +*u +1079 355 m +1080 354 l +1079 355 l +f +*U +0.000 0.698 0.620 0.302 k +*u +1080 353 m +1091 353 l +1087.676 354.492 1082.641 355.976 1080 353 c +f +*U +0.000 0.208 0.137 0.067 k +*u +1204 355 m +1205 354 l +1204 355 l +f +*U +0.000 0.467 0.325 0.200 k +*u +1205 355 m +1206 354 l +1205 355 l +f +*U +0.000 0.780 0.635 0.220 k +*u +1206.667 354.667 m +1206.222 354.222 1207.278 354.278 1207.333 354.333 c +1207.778 354.778 1206.722 354.722 1206.667 354.667 c +f +*U +0.000 0.800 0.686 0.200 k +*u +1229 355 m +1230.223 353.805 1230.420 353.684 1232 353 c +1231 354.783 1231 354.594 1229 355 c +f +*U +0.000 0.741 0.784 0.196 k +*u +1232 353 m +1236 354 l +1233.954 354.751 1233.404 354.656 1232 353 c +f +*U +0.000 0.706 0.686 0.294 k +*u +1233 354 m +1235.332 353 1237.457 353 1240 353 c +1237.557 354.530 1235.855 354.392 1233 354 c +f +*U +0.000 0.831 0.776 0.149 k +*u +1238.667 354.667 m +1238.222 354.222 1239.278 354.278 1239.333 354.333 c +1239.778 354.778 1238.722 354.722 1238.667 354.667 c +f +*U +0.000 0.251 0.192 0.110 k +*u +1057 354 m +1058 353 l +1057 354 l +f +*U +0.000 0.357 0.216 0.102 k +*u +1071 354 m +1072 353 l +1071 354 l +f +*U +0.000 0.192 0.161 0.243 k +*u +1077 354 m +1078 353 l +1077 354 l +f +*U +0.000 0.400 0.361 0.600 k +*u +1078.667 353.667 m +1078.222 353.222 1079.278 353.278 1079.333 353.333 c +1079.778 353.778 1078.722 353.722 1078.667 353.667 c +f +*U +0.000 0.800 0.580 0.200 k +*u +1081.667 353.667 m +1081.222 353.222 1082.278 353.278 1082.333 353.333 c +1082.778 353.778 1081.722 353.722 1081.667 353.667 c +f +*U +0.000 0.047 0.031 0.192 k +*u +1092 354 m +1093 353 l +1092 354 l +f +*U +0.000 0.110 0.231 0.114 k +*u +1202 354 m +1203 353 l +1202 354 l +f +*U +0.000 0.365 0.365 0.635 k +*u +1203.667 353.667 m +1203.222 353.222 1204.278 353.278 1204.333 353.333 c +1204.778 353.778 1203.722 353.722 1203.667 353.667 c +f +*U +0.000 0.659 0.514 0.341 k +*u +1205 354 m +1208 352.673 1211.586 353 1215 353 c +1211.837 354.327 1208.415 354.000 1205 354 c +f +*U +0.000 0.145 0.114 0.263 k +*u +1227 354 m +1228 353 l +1227 354 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1228.667 353.667 m +1228.222 353.222 1229.278 353.278 1229.333 353.333 c +1229.778 353.778 1228.722 353.722 1228.667 353.667 c +f +*U +0.000 0.671 0.702 0.298 k +*u +1246 354 m +1250.215 352.231 1255.464 353 1260 353 c +1289 353 l +1390 353 l +1385.785 354.769 1380.536 354 1376 354 c +1347 354 l +1246 354 l +f +*U +0.000 0.345 0.345 0.655 k +*u +1390 354 m +1391 353 l +1390 354 l +f +*U +0.020 0.000 0.000 0.282 k +*u +1069.667 352.667 m +1069.222 352.222 1070.278 352.278 1070.333 352.333 c +1070.778 352.778 1069.722 352.722 1069.667 352.667 c +f +*U +0.082 0.000 0.082 0.129 k +*u +1081 353 m +1082 352 l +1081 353 l +f +*U +0.000 0.196 0.145 0.125 k +*u +1203.667 352.667 m +1203.222 352.222 1204.278 352.278 1204.333 352.333 c +1204.778 352.778 1203.722 352.722 1203.667 352.667 c +f +*U +0.000 0.271 0.153 0.094 k +*u +1213 353 m +1214.249 352.315 1214.548 352.251 1216 352 c +1214.752 352.685 1214.452 352.749 1213 353 c +f +*U +0.000 0.114 0.106 0.192 k +*u +1229.667 352.667 m +1229.222 352.222 1230.278 352.278 1230.333 352.333 c +1230.778 352.778 1229.722 352.722 1229.667 352.667 c +f +*U +0.000 0.302 0.125 0.067 k +*u +1388 353 m +1389.248 352.315 1389.548 352.251 1391 352 c +1389.752 352.685 1389.451 352.749 1388 353 c +f +*U +0.000 0.000 0.000 0.075 k +*u +38 344 m +38 342 l +248 342 l +248 328 l +169 328 l +169 308 l +171 308 l +171 326 l +221 326 l +228.998 326 238 324.805 245.941 326 c +251 327 252 340 248.397 342.972 c +245 345.544 236.929 344 233 344 c +193 344 l +38 344 l +f +*U +0.000 0.000 0.000 0.067 k +*u +283 344 m +283 342 l +303 342 324 340.473 344 343 c +338.293 345.395 330 344 324 344 c +283 344 l +f +*U +0.000 0.000 0.000 0.075 k +*u +381 344 m +381 342 l +402 342 l +402 317 l +402 313.346 400.779 308.904 405 308 c +403.315 310.695 404 313.738 404 317 c +404 334 l +404 336.397 405 341.905 402.833 343.500 c +401.413 344.522 398.639 344 397 344 c +381 344 l +f +*U +0.000 0.000 0.000 0.067 k +*u +476 344 m +476 342 l +498 342 l +498 344 l +476 344 l +f +*U +0.000 0.000 0.000 0.055 k +*u +523 344 m +525.431 341.218 529.491 342 533 342 c +533 344 l +523 344 l +f +*U +0.000 0.000 0.000 0.075 k +*u +613 343 m +619.202 340.397 628.298 342 635 342 c +635 344 l +627.863 344 619.871 345 613 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +658 256 m +661 263.399 659 274.993 659 283 c +659 342 l +663.930 342 673.587 340 677 344 c +672.386 343.703 661.217 346.237 658 342.258 c +656.459 340.299 657.287 337.229 657.576 335 c +658.219 330 658 324.999 658 320 c +658 256 l +f +*U +0.000 0.000 0.000 0.075 k +*u +723 344 m +728.261 340.406 736.835 342 743 342 c +791 342 l +783.828 345 774.666 344 767 344 c +723 344 l +f +855 339 m +861.361 343.592 871.617 342.758 879 341 c +878.203 344.720 875.390 344 872 344 c +866.888 344 855 346 855 339 c +f +*U +0.000 0.000 0.000 0.067 k +*u +937 344 m +937 342 l +958 342 l +958 271 l +960 271 l +960 325 l +960 329 961.939 340.167 958.397 342.972 c +956.719 344.301 953.992 343.986 952 343.999 c +937 344 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1424 343 m +1429.281 338.999 1439.557 341 1446 341 c +1446 305 l +1450 307 l +1445 318.691 1451.483 332.607 1446 344 c +1438.638 343 1431.415 343 1424 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1503 342 m +1509.638 339.215 1523 339.975 1530 342 c +1523.242 344.909 1509.979 344 1503 342 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1943 343 m +1948.750 338.644 1958 341.897 1965 339 c +1963 344 l +1956.487 342.449 1949.659 343 1943 343 c +f +*U +0.000 0.000 0.000 0.161 k +*u +268 341 m +272.467 339.644 278.216 341.960 283 342 c +278 344 272.854 342.539 268 341 c +f +*U +0.000 0.000 0.000 0.133 k +*u +340 343 m +343 341.673 346.586 342 350 342 c +346.837 343.327 343.414 343.000 340 343 c +f +*U +0.000 0.000 0.000 0.141 k +*u +380 343 m +380 254 l +402 254 l +396.639 256.249 386.863 252.344 382.603 256.603 c +378.748 260.459 381 272.899 381 278 c +381 324 l +381 329.509 382.740 338.261 380 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +519 343 m +520.934 332.581 520 321.567 520 311 c +520 256 l +522.802 262.678 521 272.785 521 280 c +521 320 l +521 327.591 520.233 335.578 522 343 c +519 343 l +f +*U +0.000 0.000 0.000 0.157 k +*u +533.667 342.667 m +533.222 342.222 534.278 342.278 534.333 342.333 c +534.778 342.778 533.722 342.722 533.667 342.667 c +f +*U +0.000 0.000 0.000 0.075 k +*u +678 343 m +680.338 333.181 679 322 679 312 c +679 256 l +681 256 l +681 321 l +681 327 683.405 339.182 678 343 c +f +*U +0.000 0.000 0.000 0.137 k +*u +716 343 m +718.890 341.787 721.874 342 725 342 c +722 343.213 719 342.998 716 343 c +f +*U +0.000 0.000 0.000 0.129 k +*u +936 343 m +936 277 l +936 271.319 933.549 257.889 938 254 c +936.473 262.226 937 270.661 937 279 c +937 318 l +937 322.989 936.823 328 937 333 c +937.204 336.798 938.331 339.800 936 343 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1541 333 m +1552.458 342.259 1563.919 341 1578 341 c +1632 341 l +1632 343 l +1609 343 1585.778 344.470 1563 342.910 c +1555.191 342.376 1543.470 341.855 1541 333 c +f +1678 342 m +1684.678 339.198 1694.784 341 1702 341 c +1740 341 l +1746.834 341 1754.416 340 1761 342 c +1754.322 344.802 1744.216 343 1737 343 c +1700 343 l +1692.719 343 1685 343.695 1678 342 c +f +1798 342 m +1805.639 338.794 1817.729 341 1826 341 c +1873 341 l +1880.722 341 1889.565 339.802 1897 342 c +1889 345.306 1876.534 343 1868 343 c +1823 343 l +1814.790 343 1806 343.910 1798 342 c +f +*U +0.000 0.000 0.000 0.149 k +*u +37 342 m +37 328 l +38.667 331.972 38.667 338 37 342 c +f +*U +0.000 0.000 0.000 0.843 k +*u +38 342 m +38 328 l +39.667 331.972 39.667 338 38 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +39 342 m +39 328 l +84 328 l +84 255 l +104 255 l +104 328 l +147 328 l +147 342 l +39 342 l +f +*U +0.000 0.000 0.000 0.502 k +*u +147 342 m +147 328 l +148.796 332.279 147.909 337.419 149 342 c +147 342 l +f +*U +0.000 0.000 0.000 1.000 k +*u +149 342 m +149 255 l +249 255 l +249 269 l +169 269 l +169 296 l +166.727 292.523 167.889 288.994 167.985 285 c +168 277.977 167.882 270.994 168 264 c +194.536 265.978 221.374 265 248 265 c +247.971 262.575 248.282 259.481 246.397 257.603 c +242.527 253.750 230 256 225 256 c +152 256 l +152 305 l +152 309.955 153.774 319.380 150 323 c +152.697 326.851 152 331.439 152 336 c +247 336 l +247 329 l +168 329 l +168 323.686 168.242 318.306 167.911 313 c +167.774 310.792 166.850 307.834 168.357 305.898 c +170.552 303 176.906 305 180 305 c +191.999 304.932 204 305 216 305 c +216 296 l +170 296 l +170 294 l +217 294 l +217 307 l +169 307 l +169 328 l +248 328 l +248 342 l +149 342 l +f +*U +0.000 0.000 0.000 0.565 k +*u +275 342 m +276 341 l +275 342 l +f +*U +0.000 0.000 0.000 0.835 k +*u +276.667 341.667 m +276.222 341.222 277.278 341.278 277.333 341.333 c +277.778 341.778 276.722 341.722 276.667 341.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +365 288 m +358.261 288 351.753 289.944 345 290 c +345 269 l +298 269 l +293.583 269 283.993 267.214 280.603 270.603 c +277.463 273.744 279 281.938 279 286 c +279 328 l +345 328 l +345 309 l +348.433 309.434 352.677 309.327 355 312 c +351 311 l +351 328 l +349.902 325.387 350 322.835 350 320 c +349.190 322.729 349 325 349 328 c +346.699 322.517 349.734 315.928 346 311 c +347.722 316.825 347 323 346 329 c +278 329 l +278 325 l +276.285 326.551 275.177 327.244 273 328 c +271.600 322 272.998 316 273 310 c +273 270 l +277 271 l +278 267 l +275 269 l +274.438 267.199 274.176 265.878 274 264 c +273.438 265.801 273.176 267 273 269 c +272 267 271.561 265 271 263 c +268.234 263.676 267.348 263.604 265 262 c +264 265.534 263.510 268.354 264 272 c +262 271 l +262.934 272.723 263.535 274 264 276 c +261 275 l +262 279 l +263 277 l +264.769 281.215 264 286.464 264 291 c +264 301.834 266.730 317 262 327 c +264 326 l +263.339 327.396 263 327.814 262 329 c +263.367 330.731 263.984 333 265.564 334.658 c +268.309 337.354 273.537 336.315 277 336 c +277.228 338 277 337.890 279 339 c +278 337.521 278 337.797 278 336 c +297.472 337.254 317.471 335.999 337 336 c +342.945 336 352.661 338.707 357.870 335 c +359.627 333.792 360.672 331.638 362 330 c +359 324.658 360 317.970 360 312 c +356 312 l +364.876 308.285 365 316.411 364.985 323 c +364.776 331.411 361.647 338.267 352.999 340.485 c +344.854 342.575 336.325 342 328 342 c +291 342 l +283 342 272.886 342.842 266 338 c +260.527 334 260 327.249 260 321 c +260 279 l +260 272 259.582 264.689 265.329 259.800 c +271.276 254.742 281.613 255 289 255 c +305.663 254.994 322.339 254.806 339 255 c +345.793 255 355.403 255.340 360.442 260.532 c +367 267.310 365 279.432 365 288 c +f +*U +0.000 0.000 0.000 0.784 k +*u +347.667 341.667 m +347.222 341.222 348.278 341.278 348.333 341.333 c +348.778 341.778 347.722 341.722 347.667 341.667 c +f +*U +0.000 0.000 0.000 0.514 k +*u +349 342 m +350 341 l +349 342 l +f +*U +0.000 0.000 0.000 0.196 k +*u +352.667 341.667 m +352.222 341.222 353.278 341.278 353.333 341.333 c +353.778 341.778 352.722 341.722 352.667 341.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +382 342 m +382 255 l +402 255 l +402 293 l +477 293 l +477 255 l +496 255 l +496 342 l +477 342 l +477 307 l +402 307 l +402 342 l +382 342 l +f +*U +0.000 0.000 0.000 0.145 k +*u +475 342 m +475 309 l +405 309 l +411.194 306.401 420.314 308 427 308 c +476 308 l +476 330 l +476 333.983 476.552 338.301 475 342 c +f +*U +0.000 0.000 0.000 0.635 k +*u +476 342 m +476 308 l +477.328 311 477.000 314.581 477 318 c +477 325.215 478.802 335.323 476 342 c +f +*U +0.000 0.000 0.000 0.855 k +*u +496 342 m +496 255 l +498.395 260.707 497 268.846 497 275 c +497 319 l +497 325.951 498.701 335.564 496 342 c +f +*U +0.000 0.000 0.000 0.161 k +*u +497 342 m +497 255 l +476 255 l +482.202 252.397 491.298 254 498 254 c +498 315 l +498 323 500 334.600 497 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +521 342 m +521 255 l +539 255 l +539 320 l +536.960 317.763 536.388 316.617 538 314 c +534.952 308.288 536 301.340 536 295 c +536 256 l +527 256 l +527 317 l +527 325 529.264 334.805 522 340 c +526 339.907 528.433 337.780 532 336 c +531 338 l +532.635 337.455 532.455 337.635 533 336 c +534.797 336 534.521 336 536 337 c +537 336 l +536.438 334.199 536.176 332.878 536 331 c +536.685 332.248 536.749 332.548 537 334 c +537.225 331.765 537 331 536 329 c +536.873 326.519 537 324.638 537 322 c +540.167 321.588 540.838 318.289 543 316 c +547 311.801 552.312 308.388 557 304.861 c +571 294.254 585 283.464 599 272.611 c +605.712 267.375 613.978 258.378 622 255.500 c +625.547 254.227 630.278 255 634 255 c +634 342 l +615 342 l +615 320.949 615 299.981 616 279 c +599.355 295.299 578.505 308 560 322.235 c +552 328.219 543.366 337.927 534 341.272 c +530 342.687 525 342 521 342 c +f +*U +0.000 0.000 0.000 0.725 k +*u +534 342 m +535 341 l +534 342 l +f +*U +0.000 0.000 0.000 0.145 k +*u +614 342 m +614 283 l +612.483 283.957 611.661 284.387 610 285 c +611.549 282.864 612.864 281.549 615 280 c +615 322 l +615 328 616.395 336.293 614 342 c +f +*U +0.000 0.000 0.000 0.153 k +*u +634 342 m +634 255 l +636.395 260.707 635 268.846 635 275 c +635 319 l +635 325.951 636.701 335.564 634 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +659 342 m +659 255 l +679 255 l +679 342 l +659 342 l +f +*U +0.000 0.000 0.000 0.200 k +*u +707 340 m +709.533 339.463 711.512 340.220 714 341 c +711.328 341.799 709.568 341 707 340 c +f +*U +0.000 0.000 0.000 0.569 k +*u +716 342 m +717 341 l +716 342 l +f +*U +0.000 0.000 0.000 0.882 k +*u +717.667 341.667 m +717.222 341.222 718.278 341.278 718.333 341.333 c +718.778 341.778 717.722 341.722 717.667 341.667 c +f +*U +0.000 0.000 0.000 0.996 k +*u +806 288 m +800.959 288.216 795.988 289.841 791 289 c +792.981 280.677 790.819 272.352 792 264 c +739 264 l +735 264 723.533 262.871 723 267 c +720 265 l +720.462 270 719 275.691 719 281 c +719 329 l +771 329 l +777 329 786.400 330.884 790 325 c +790.685 326.248 790.749 326.548 791 328 c +792.254 322.426 791.350 316.569 793 311 c +800 312 l +800 320.200 800.248 328.211 803 336 c +792 342.480 781.309 342 769 342 c +730 342 l +721.969 342 710.324 342.670 704.649 335.787 c +700.958 331.311 701 325.467 701 320 c +701 295 l +701 285.335 697.933 269.255 704.649 261.329 c +709.588 255.499 718.907 255 726 255 c +742.994 254.802 760 254.993 777 255 c +784.338 255 794.781 254.715 800.660 259.800 c +808 266.288 806 279.211 806 288 c +f +*U +0.000 0.000 0.000 0.788 k +*u +788.667 341.667 m +788.223 341.223 789.277 341.278 789.333 341.333 c +789.778 341.778 788.722 341.722 788.667 341.667 c +f +*U +0.000 0.000 0.000 0.525 k +*u +790 342 m +791 341 l +790 342 l +f +*U +0.000 0.000 0.000 0.098 k +*u +791 342 m +793.283 340.779 795.428 340.348 798 340 c +795.686 341.591 793.810 341.858 791 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +818 278 m +823 280 l +822 283 l +823.796 283.969 823.681 285.432 825.194 286.889 c +826.774 288.409 829 287.791 830.611 289.306 c +832.810 291.495 833 298.935 834 302 c +835.714 300.450 836.823 299.756 839 299 c +838 296 l +841 295 l +840.458 292.326 840.493 291.269 842 289 c +850 301.314 860.923 315 866 329 c +868 329 l +873.587 314.239 886.418 302.728 892 288 c +896 290 l +895 296 l +893.805 295.402 894 295.534 893 294 c +892 295.207 889.170 296.995 888 299 c +887.230 300.321 887.249 303.259 887 305 c +886.895 305.737 889 305.375 886 306 c +887.479 306.986 887.203 307 889 307 c +887.752 307.685 887.452 307.749 886 308 c +887 312 l +885.263 311.938 885.360 311.980 884 313 c +883 310 l +881.483 310.957 880.661 311.387 879 312 c +879.764 314.746 879.764 316.254 879 319 c +888 321 l +888.197 318.624 888.247 316.372 888 314 c +890.580 313 892.253 312.747 895 313 c +895.628 310 896.659 307.856 896 305 c +896.810 303.230 896.497 301.947 898 301 c +896.964 299.814 896.661 299.396 896 298 c +898.377 297.689 898.983 297.747 901 299 c +901 297.203 901 297.479 902 296 c +905 297 l +904 292.337 904.911 289.835 910 290 c +910.560 284.738 913.861 280.204 918 277 c +916.703 275.406 916.465 274.982 916 273 c +917.797 273 917.522 273 919 274 c +919.902 272 920 272 922 271 c +921.954 268.752 922 268 923 266 c +920.717 264.554 920.418 263.689 920 261 c +921 262.458 921.436 263.248 922 265 c +923.938 261.993 925.532 260 929 259 c +922.952 255.612 912.227 253.236 912 263 c +909.433 264.246 908.914 265 909 268 c +910 266.466 909.805 266.598 911 266 c +912 271.764 907.541 271.650 903 272 c +903.986 273.479 904 273.203 904 275 c +902.521 275.986 902.797 276 901 276 c +902 277.186 902.339 277.604 903 279 c +900.777 279.184 900.810 279.240 899 278 c +892.386 281.530 883.352 280 876 280 c +851 280 l +844.697 280 838.703 280.351 833.274 276.532 c +830.404 274.513 828.884 270.872 827 268 c +826 271 l +823 270 l +824.341 268.726 825.403 267.959 827 267 c +825.952 265 825.487 264 825 262 c +823 262 822.734 261.830 821 261 c +822 263 l +816 261 l +817 256 l +807 256 l +808.283 260.441 810.639 264 813 268 c +814 265 l +815.554 267.485 815.542 269 815 272 c +818 273 l +818 277 l +811.345 272.962 806.249 261.951 803 255 c +808.192 255 818.207 253 822.391 256.603 c +827.945 261.295 829.256 272.479 836.185 275.397 c +841 277.438 848.806 276 854 276 c +866.992 276 880 276.241 892.999 275.995 c +904 275.786 904.250 262.539 911.529 256.603 c +916 252.850 927.332 255 933 255 c +921.231 277 906 298 892.344 319 c +888.903 324.272 885.735 329.719 882.308 334.999 c +880.831 337.274 879.276 340.246 876.674 341.397 c +872.829 343 860.974 343.216 857.379 340.972 c +852.377 337.851 848.859 328.923 845.808 324 c +840 314.649 834.265 305.249 828.308 296 c +824.582 290.215 820 284.615 818 278 c +f +938 342 m +938 255 l +1033 255 l +1033 269 l +958 269 l +958 342 l +938 342 l +f +*U +0.000 0.427 0.302 0.239 k +*u +1054.333 341.333 m +1054.278 341.278 1054.222 340.222 1054.667 340.667 c +1054.723 340.723 1054.777 341.778 1054.333 341.333 c +f +*U +0.000 0.525 0.416 0.475 k +*u +1055 340 m +1066.604 342.763 1080 341 1092 341 c +1096.941 341 1102.923 342 1107 339 c +1108.703 343.519 1098.748 342 1096 342 c +1066 342 l +1062.385 342 1057.271 343 1055 340 c +f +*U +0.000 0.341 0.243 0.047 k +*u +1108.333 341.333 m +1108.278 341.278 1108.222 340.222 1108.667 340.667 c +1108.723 340.723 1108.777 341.778 1108.333 341.333 c +f +*U +0.000 0.420 0.369 0.282 k +*u +1191 342 m +1192 341 l +1191 342 l +f +*U +0.000 0.525 0.416 0.475 k +*u +1192 342 m +1197.462 339.708 1205 341 1211 341 c +1252 341 l +1394 341 l +1388.537 343.292 1380.887 342 1375 342 c +1334 342 l +1192 342 l +f +*U +0.000 0.388 0.267 0.031 k +*u +1394.333 341.333 m +1394.278 341.278 1394.222 340.222 1394.667 340.667 c +1394.723 340.723 1394.777 341.777 1394.333 341.333 c +f +*U +0.000 0.000 0.000 0.161 k +*u +1529 342 m +1530 340 l +1531.635 340.545 1531.455 340.365 1532 342 c +1529 342 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1632 342 m +1634.890 340.787 1637.874 341 1641 341 c +1638 342.213 1635 341.998 1632 342 c +f +*U +0.000 0.000 0.000 0.071 k +*u +1640 341 m +1641.769 340.221 1643 340 1645 340 c +1643 341.301 1642.372 341.330 1640 341 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1760 342 m +1762.332 341 1764.457 341 1767 341 c +1764.669 341.984 1762.543 341.981 1760 342 c +f +*U +0.000 0.000 0.000 0.133 k +*u +1896 342 m +1896 326 l +1897.812 330.319 1897.812 337.681 1896 342 c +f +*U +0.000 0.000 0.000 0.149 k +*u +1942 342 m +1940.286 339.376 1938.944 336.987 1938 334 c +1940.574 336.358 1942.298 338.952 1944 342 c +1942 342 l +f +*U +0.000 0.000 0.000 0.325 k +*u +148 341 m +148 328 l +149.591 331.791 149.591 337.209 148 341 c +f +*U +0.000 0.000 0.000 0.745 k +*u +353 341 m +354 340 l +353 341 l +f +*U +0.000 0.000 0.000 0.169 k +*u +355.667 340.667 m +355.222 340.222 356.278 340.278 356.333 340.333 c +356.778 340.778 355.722 340.722 355.667 340.667 c +f +*U +0.000 0.000 0.000 0.067 k +*u +381 341 m +381 256 l +383.395 261.707 382 269.846 382 276 c +382 319 l +382 325.686 383.599 334.806 381 341 c +f +*U +0.000 0.000 0.000 0.125 k +*u +519 341 m +519 256 l +521.395 261.707 520 269.846 520 276 c +520 319 l +520 325.686 521.599 334.806 519 341 c +f +*U +0.000 0.000 0.000 0.996 k +*u +522 340 m +528.915 333.235 527 324 527 315 c +527 256 l +536 256 l +536 294 l +536 300.340 534.952 307.288 538 313 c +537 316.780 538.349 318.645 540 322 c +538 323.277 538.915 323.277 537 322 c +537.284 324.853 537.557 326.603 536 329 c +537.336 330.826 537.690 331.753 538 334 c +537.315 332.752 537.251 332.452 537 331 c +536.660 333 536.677 333.968 537 336 c +536 337 l +531 338 l +532 336 l +528.566 338.505 526.390 340.606 522 340 c +f +*U +0.000 0.000 0.000 0.157 k +*u +536 341 m +537.223 339.805 537.420 339.684 539 339 c +537.777 340.195 537.580 340.316 536 341 c +f +*U +0.000 0.000 0.000 0.769 k +*u +794 341 m +795 340 l +794 341 l +f +*U +0.000 0.000 0.000 0.608 k +*u +878 341 m +879 340 l +878 341 l +f +*U +0.000 0.000 0.000 0.094 k +*u +879 341 m +879.564 339.248 879.919 338.458 881 337 c +880.689 339.291 880.634 339.320 879 341 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1053 336 m +1053.363 333.768 1053.363 332.232 1053 330 c +1112 330 l +1109.601 333.899 1107.435 336.220 1107 341 c +1072 341 l +1063.987 341 1058.563 342 1053 336 c +f +*U +0.000 0.341 0.318 0.008 k +*u +1190 341 m +1191 340 l +1190 341 l +f +*U +0.000 0.875 0.608 0.125 k +*u +1191 341 m +1191 339 l +1286 339 l +1276.597 336.221 1264.782 338 1255 338 c +1192 338 l +1199.639 334.794 1211.729 337 1220 337 c +1283 337 l +1283 333 l +1255.927 329.579 1227.296 332 1200 332 c +1207.400 328.895 1218.993 331 1227 331 c +1287 331 l +1288 338 l +1291.694 337 1295.214 337 1299 337 c +1297.752 337.685 1297.452 337.749 1296 338 c +1305.683 340.862 1317.924 339 1328 339 c +1392 339 l +1386.293 341.395 1378 340 1372 340 c +1331 340 l +1284.362 340 1237.700 341 1191 341 c +f +*U +0.000 0.882 0.635 0.118 k +*u +1296 341 m +1303.879 337.694 1316.466 340 1325 340 c +1392 340 l +1382.317 337 1370 339 1360 339 c +1296 339 l +1299.619 336.322 1300.850 334.591 1301 330 c +1395 330 l +1394.694 333.752 1393.759 337.320 1393 341 c +1296 341 l +f +*U +0.000 0.733 0.533 0.267 k +*u +1393 341 m +1393 338 l +1395 339 l +1394.455 340.635 1394.635 340.455 1393 341 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1425 341 m +1425 253 l +1446 253 l +1440.286 255.398 1432.169 254 1426 254 c +1426 314 l +1426 322 1428 333.601 1425 341 c +f +*U +0.000 0.000 0.000 0.855 k +*u +1426 341 m +1426 254 l +1428.701 260.436 1427 270 1427 277 c +1427 321 l +1427 327 1428.395 335.293 1426 341 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1427 341 m +1427 254 l +1446 254 l +1446 292 l +1459.982 283.441 1473.942 274.834 1488 266.400 c +1494.470 262.518 1501.682 256.505 1509 254.499 c +1517.380 252.203 1528.330 254 1537 254 c +1529.973 261 1518.663 265.461 1510 270.427 c +1493.561 279.852 1477.411 291.497 1460 299 c +1482.270 313.736 1506.223 326 1529 340 c +1525.565 341.441 1521.703 341 1518 341 c +1513.502 341 1508.356 341.663 1504 340.351 c +1496.680 338 1489.450 332 1483 328 c +1470.699 320.335 1458 313 1446 305 c +1446 341 l +1427 341 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1491 335 m +1495.302 333.994 1499.507 337.689 1503 340 c +1498.778 340.616 1494.663 336.949 1491 335 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1503 341 m +1504 340 l +1503 341 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1529 341 m +1530 340 l +1529 341 l +f +*U +0.000 0.000 0.000 0.506 k +*u +1554 341 m +1555 340 l +1554 341 l +f +*U +0.000 0.000 0.000 0.855 k +*u +1555.667 340.667 m +1555.222 340.222 1556.278 340.278 1556.333 340.333 c +1556.778 340.777 1555.722 340.722 1555.667 340.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1636 255 m +1630.194 257.303 1622.186 256 1616 256 c +1574 256 l +1563.575 256 1553.913 253.776 1548 264 c +1545 262 l +1543.393 267.482 1544.298 272.443 1543.826 278 c +1542.614 292.285 1543 306.647 1543 321 c +1541.231 316.785 1542 311.536 1542 307 c +1542 280 l +1540.304 284.639 1541 290 1541 295 c +1541 302.647 1539.780 311.446 1541 318.972 c +1541.455 320.915 1542.816 322.241 1543.361 324 c +1544 326.697 1542.720 330.297 1544 332.694 c +1547.265 338.455 1556.648 333.660 1558 340 c +1566.631 335.508 1576.540 336 1586 336 c +1628 336 l +1635.905 336 1643.682 337.177 1651 334 c +1650 330 l +1649 332 l +1647.833 328.992 1647.521 325.261 1650 323 c +1649 325 l +1653 324 l +1644.764 313.519 1650 295.666 1648.830 283 c +1648 275.920 1646.705 268 1651 262 c +1650 261 l +1648.483 261.957 1647.662 262.387 1646 263 c +1643.373 259.674 1641 257.375 1637 256 c +1644.933 252.766 1652.822 259.407 1654.481 267 c +1655.735 272.734 1655 279 1655 285 c +1655 319 l +1654.997 325.661 1654.998 333 1648.956 337.297 c +1642.231 342 1631.781 341 1624 341 c +1569 341 l +1561 341 1550.307 341.777 1544.214 335.775 c +1539.258 330.894 1539 322.545 1539 316 c +1538.933 302 1538.407 287.932 1539 274 c +1539.305 268 1540.919 261.234 1546 257.728 c +1549.735 255.202 1554.704 255 1559 254.425 c +1571.338 252.746 1584.555 254 1597 254 c +1609 254 1624.361 251.560 1636 255 c +f +*U +0.000 0.000 0.000 0.808 k +*u +1638.667 340.667 m +1638.222 340.222 1639.278 340.278 1639.333 340.333 c +1639.778 340.778 1638.722 340.722 1638.667 340.667 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1677 341 m +1677 254 l +1679.395 259.707 1678 267.846 1678 274 c +1678 318 l +1678 324.951 1679.701 334.564 1677 341 c +f +*U +0.000 0.000 0.000 0.851 k +*u +1678 341 m +1678 254 l +1680.395 259.707 1679 267.846 1679 274 c +1679 318 l +1679 324.951 1680.701 334.564 1678 341 c +f +*U +0.000 0.000 0.000 0.996 k +*u +1679 341 m +1679 338 l +1760 338 l +1760 336 l +1680 336 l +1680 256 l +1696 256 l +1696 266 1698 278.211 1696 288 c +1703.463 288.834 1711.460 288 1719 287.999 c +1723.253 287.979 1728.340 288.223 1732 286 c +1733.662 286.613 1734.483 287 1736 288 c +1735.522 286 1735.295 284.504 1734 283 c +1735.636 280.382 1735.730 278.558 1739 279 c +1739.777 277.298 1740.588 275.810 1741 274 c +1742.767 273 1743.608 272.434 1745 271 c +1747.502 271.402 1749.489 271.359 1752 271 c +1751 266.465 1753.520 264.181 1758 264 c +1759 262 1759 261.902 1761 261 c +1761.642 263.842 1763.253 265.681 1765 268 c +1762.460 269.693 1761.684 272.422 1761 269 c +1757 274 l +1752 272 l +1752 273.410 1752.851 279 1752 280 c +1750.303 281.980 1749.186 278.744 1750 282 c +1747.944 281.513 1746.856 281 1745 280 c +1744 281 l +1745.517 281.958 1746.338 282.387 1748 283 c +1746.494 283.683 1745.685 283.826 1744 284 c +1753.243 290.648 1766.731 283.345 1775.786 291.419 c +1778.777 294 1780 298 1780.699 302 c +1782.276 312.675 1783.853 333.465 1771.996 338.521 c +1762.259 342.672 1750.334 341 1740 341 c +1679 341 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1765 341 m +1766 340 l +1765 341 l +f +*U +0.000 0.000 0.000 0.502 k +*u +1766 341 m +1767 340 l +1766 341 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1767 341 m +1769 339.775 1770.658 339.355 1773 339 c +1770.958 340.416 1769.489 340.745 1767 341 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1797 341 m +1797 256 l +1799.395 261.707 1798 269.846 1798 276 c +1798 319 l +1798 325.686 1799.599 334.806 1797 341 c +f +*U +0.000 0.000 0.000 0.851 k +*u +1798 341 m +1798 254 l +1800.395 259.707 1799 267.846 1799 274 c +1799 318 l +1799 324.951 1800.701 334.564 1798 341 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1799 341 m +1799 254 l +1860 254 l +1878 254 l +1880.762 254 1884.206 253.505 1886.815 254.603 c +1891.372 256.523 1894.169 263.750 1896 268 c +1818 268 l +1818 276.954 1816.760 286.543 1820 295 c +1816 296 l +1816 285.911 1813.562 272.892 1819 264 c +1823 264 l +1827.782 267.623 1836.197 266 1842 266 c +1888 266 l +1881 263.970 1873 265 1866 265 c +1824 265 l +1828.720 263 1834.920 264 1840 264 c +1871 264 l +1877.237 264 1885 265.537 1890 261 c +1888 262 l +1887.835 253.173 1874 256 1868 256 c +1800 256 l +1800 336 l +1888 336 l +1888 328 l +1839 328 l +1831.722 328 1823 329.518 1816 328 c +1816.654 320 1816.359 311.882 1816 304 c +1831.677 305.519 1848.224 304 1864 304 c +1864 296 l +1832 296 l +1828 296 1822.666 297.177 1821 293 c +1865 293 l +1865 306 l +1818 306 l +1818 327 l +1896 327 l +1894.855 331.810 1894.855 336.190 1896 341 c +1799 341 l +f +1890 254 m +1894.853 254 1904.246 252.186 1908.366 255 c +1914.572 259.309 1914.958 269.959 1921.379 273.972 c +1925.246 276.389 1932.606 275 1937 275 c +1971 275 l +1977.708 275 1982.871 276 1987 270 c +1992 273 l +1991 278 l +1989.805 276.777 1989.684 276.580 1989 275 c +1987.328 275.338 1987.690 275.537 1987 274 c +1985.868 276.328 1985.484 276.978 1987 279 c +1975.641 282.358 1960.833 280 1949 280 c +1941.869 280 1933.868 281 1927 279 c +1928 277 l +1927 276 l +1923 278 l +1921.517 276 1916.355 277.250 1916 280 c +1911 276 l +1910.961 278.627 1910.839 280.664 1912 283 c +1912.532 287.842 1915.597 288.210 1920 288 c +1919.277 294 1920.394 299 1922 305 c +1923.672 304.662 1923.310 304.463 1924 306 c +1928 304 l +1927.805 306.424 1927.590 308.648 1927 311 c +1928.397 311.662 1928.813 311.964 1930 313 c +1930 311 l +1931.300 311.650 1931 311 1931 313 c +1932.944 312.598 1933 312.598 1935 313 c +1936 311 1936 310.902 1938 310 c +1935.182 306 1934.649 302.227 1929 302 c +1927 287 l +1944.985 287 1963 286.267 1981 288 c +1981 292 l +1982 288 l +1983.195 289.223 1983.316 289.420 1984 291 c +1986.877 288.691 1988.808 287.950 1992 290 c +1992.338 285.727 1993.331 283.397 1996 280 c +1997.797 280 1997.521 280 1999 281 c +1999.648 278.606 2000 277.464 2002 276 c +2000 269 l +2001.801 268.438 2003 268.176 2005 268 c +2003.521 267 2003.797 267 2002 267 c +2004.401 264.987 2005.890 264.657 2009 265 c +2010 262.229 2010.945 259.969 2011 257 c +2009 261 l +2006.749 256 2004.263 255.764 1999 257 c +1999.986 258.479 2000 258.203 2000 260 c +1998.584 259.528 1998.186 259.186 1997 258 c +1995 261.930 1992.625 266.562 1989 269 c +1990 264.302 1993.289 256.564 1998 254.603 c +2003.297 252.489 2011.444 254 2017 254 c +2014.701 260 2010.612 265.493 2007.192 271 c +2000.539 281.715 1993.696 292.313 1987 303 c +1984.198 300.326 1983 296.294 1981 293 c +1979.977 294.534 1980.196 294.402 1979 295 c +1977.701 294.350 1978 294.853 1978 293 c +1976 293 l +1976.175 296.585 1974.198 299.859 1976 303 c +1973.992 303.553 1973.667 303.303 1972 302 c +1970.343 303.664 1969 304.875 1967 306 c +1969.363 299.545 1973.778 294 1977 288 c +1929 288 l +1934 301.975 1945.877 313 1951 327 c +1944 328 l +1944.892 326 1945.402 325.481 1947 324 c +1944 324 l +1945 319 l +1942.622 318.617 1942.644 316.363 1942 314 c +1940.507 314.999 1940.734 314.968 1939 315 c +1937.741 317.498 1936.440 318.632 1934 320 c +1935 322.243 1935.182 322.577 1935 325 c +1936.822 325.990 1936.716 326.867 1937 329 c +1938.479 328 1938.203 328 1940 328 c +1939 330 l +1943 328 l +1943.494 331 1943 332.000 1940 333 c +1947 336.523 1953.786 334.868 1961 337 c +1960.636 335.505 1960.198 327.855 1962 332 c +1964.939 329 1969.397 327.339 1970 323 c +1978 314 l +1977 312.261 1976.308 310.445 1975 309 c +1977.799 307 1980.760 305.927 1984 305 c +1982.851 310.943 1978.871 315.940 1975.681 321 c +1972.297 326.370 1967.910 337.839 1961.816 340.397 c +1958.944 341.602 1955 341 1952 341 c +1949.243 340.999 1945.798 341.467 1943.329 339.972 c +1940.557 338.294 1939 334.672 1937.399 332 c +1927.600 316 l +1919.747 302.917 1911.642 289.953 1903.575 277 c +1898.951 269.576 1893 262.205 1890 254 c +f +*U +0.000 0.000 0.000 0.184 k +*u +266.667 339.667 m +266.222 339.222 267.278 339.278 267.333 339.333 c +267.778 339.778 266.722 339.722 266.667 339.667 c +f +*U +0.000 0.000 0.000 0.773 k +*u +268 340 m +269 339 l +268 340 l +f +*U +0.000 0.000 0.000 0.702 k +*u +356 340 m +357 339 l +356 340 l +f +*U +0.000 0.000 0.000 0.153 k +*u +357.667 339.667 m +357.222 339.222 358.278 339.278 358.333 339.333 c +358.778 339.778 357.722 339.722 357.667 339.667 c +f +*U +0.000 0.000 0.000 0.753 k +*u +709 340 m +710 339 l +709 340 l +f +*U +0.000 0.000 0.000 0.765 k +*u +797 340 m +798 339 l +797 340 l +f +*U +0.000 0.576 0.431 0.424 k +*u +1054 340 m +1054 336 l +1054.710 337.759 1054.710 338.241 1054 340 c +f +*U +0.000 0.408 0.357 0.114 k +*u +1108.333 339.333 m +1108.278 339.278 1108.222 338.222 1108.667 338.667 c +1108.722 338.722 1108.777 339.778 1108.333 339.333 c +f +*U +0.000 0.486 0.412 0.290 k +*u +1190 340 m +1191 339 l +1190 340 l +f +*U +0.000 0.000 0.000 0.075 k +*u +1525 338 m +1527.457 337.484 1528.502 338 1530 340 c +1528 339.453 1526.745 338.890 1525 338 c +f +*U +0.000 0.000 0.000 0.769 k +*u +1550 340 m +1551 339 l +1550 340 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1558 340 m +1554.752 334.808 1547.456 338.432 1544.169 333 c +1542.619 330.512 1543.697 327.184 1542.945 324.421 c +1539 310.450 1541 294.552 1541 280 c +1542.769 284.215 1542 289.465 1542 294 c +1542 321 l +1543.692 315.275 1543 308.940 1543 303 c +1543 294.265 1543.334 285.691 1543.791 277 c +1544 271.522 1542.600 267.230 1545 262 c +1546.396 262.661 1546.814 262.964 1548 264 c +1551.815 254.311 1560 256 1569 256 c +1624 256 l +1632.962 255.986 1640.944 253.814 1646 263 c +1650 261 l +1651 262 l +1647.318 269.250 1648.621 276.236 1648.961 284 c +1649.552 297.500 1646.300 311.964 1653 324 c +1649 325 l +1650 323 l +1648.348 325.719 1648.347 328.823 1648 332 c +1649 330.466 1648.805 330.598 1650 330 c +1651 334 l +1643.507 338.510 1632.561 336 1624 336 c +1602.813 336 1578 332.322 1558 340 c +f +*U +0.000 0.000 0.000 0.671 k +*u +1644 340 m +1645 339 l +1644 340 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1645 340 m +1646.458 338.919 1647.248 338.564 1649 338 c +1647.457 339.267 1646.952 339.489 1645 340 c +f +*U +0.000 0.000 0.000 0.827 k +*u +1769 340 m +1770 339 l +1769 340 l +f +*U +0.000 0.000 0.000 0.863 k +*u +1895 340 m +1895 328 l +1896.512 331.604 1896.512 336.396 1895 340 c +f +*U +0.000 0.000 0.000 0.114 k +*u +261 333 m +262.968 334.868 264.488 336.744 266 339 c +262.718 337.748 261.728 336.425 261 333 c +f +*U +0.000 0.000 0.000 0.725 k +*u +266 339 m +267 338 l +266 339 l +f +*U +0.000 0.000 0.000 0.996 k +*u +277 339 m +275.723 337 275.723 337.915 277 336 c +268.909 337.450 265.627 336.462 262 329 c +264 326 l +262 327 l +266.932 311.864 264 292.764 264 277 c +263 279 l +262 277.623 261.596 276.560 261 275 c +262.797 275 262.522 275 264 276 c +262 271 l +264 272 l +263.185 268.202 263.688 265.626 265 262 c +267.266 263 268.477 263.306 271 263 c +271.644 265 271.906 266.795 272 269 c +272.562 267.199 272.824 265.878 273 264 c +273.924 265.648 274.449 267.175 275 269 c +276.186 267.964 276.604 267.661 278 267 c +277 271 l +273 270 l +273 309 l +273 315.348 271.891 321.745 273 328 c +274.767 327 275.607 326.434 277 325 c +277.683 326.506 277.826 327.315 278 329 c +346 329 l +346.780 322.831 347.460 317 346 311 c +349.786 314.308 348 323.233 348 328 c +348.810 325.271 348.979 322.850 349 320 c +350 322.613 349.993 325 350 328 c +351.607 322.563 351 316.642 351 311 c +353.669 311.430 354.626 310.763 357 310 c +357 312.351 357.652 311.935 360 312 c +360 317.602 359.373 324 362 329 c +357.914 339.779 349.335 336 340 336 c +319.688 335.787 298 338.213 278 336 c +279 339 l +277 339 l +f +*U +0.000 0.000 0.000 0.675 k +*u +358 339 m +359 338 l +358 339 l +f +*U +0.000 0.000 0.000 0.212 k +*u +359 339 m +360 338 l +359 339 l +f +*U +0.000 0.000 0.000 0.682 k +*u +538 339 m +539 338 l +538 339 l +f +*U +0.000 0.000 0.000 0.118 k +*u +539 339 m +540.450 337.392 541 336.936 543 336 c +541.771 337.870 541 338.224 539 339 c +f +*U +0.000 0.000 0.000 0.133 k +*u +704 336 m +705.457 337 705.897 337.543 707 339 c +704.876 338 704.899 338 704 336 c +f +*U +0.000 0.000 0.000 0.733 k +*u +707 339 m +708 338 l +707 339 l +f +*U +0.000 0.000 0.000 0.765 k +*u +799 339 m +800 338 l +799 339 l +f +*U +0.000 0.000 0.000 0.267 k +*u +800 339 m +800.545 337.365 800.365 337.545 802 337 c +801.455 338.635 801.635 338.455 800 339 c +f +*U +0.000 0.000 0.000 0.235 k +*u +854 339 m +855 338 l +854 339 l +f +*U +0.000 0.690 0.631 0.251 k +*u +1107 339 m +1107 336 l +1107.696 337.554 1107.696 337.446 1107 339 c +f +*U +0.000 0.651 0.486 0.349 k +*u +1190 339 m +1190 336 1189.792 333.925 1192 332 c +1191.405 334.396 1191 336.767 1190 339 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1191 339 m +1191 335.922 1191.438 333 1192 330 c +1287 330 l +1279.600 333 1268 331 1260 331 c +1200 331 l +1207 333 1215.573 332 1223 332 c +1242.417 332 1263.893 329.453 1283 333 c +1283 337 l +1192 337 l +1201.403 339.779 1213.218 338 1223 338 c +1286 338 l +1278 341.306 1265.534 339 1257 339 c +1191 339 l +f +*U +0.000 0.580 0.392 0.416 k +*u +1394 339 m +1394 335.389 1395.207 332.211 1392 330 c +1393.506 329.317 1394.315 329.174 1396 329 c +1395.926 332.575 1395.692 335.818 1394 339 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1547 339 m +1548 338 l +1547 339 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1772 339 m +1773 338 l +1772 339 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1773.667 338.667 m +1773.222 338.222 1774.278 338.278 1774.333 338.333 c +1774.778 338.778 1773.722 338.722 1773.667 338.667 c +f +*U +0.000 0.000 0.000 0.651 k +*u +1964 339 m +1965 338 l +1964 339 l +f +*U +0.000 0.000 0.000 0.141 k +*u +1965 339 m +1965.547 337 1966 335.745 1967 334 c +1967.375 336.419 1966.693 337.218 1965 339 c +f +*U +0.000 0.000 0.000 0.220 k +*u +360 338 m +361 337 l +360 338 l +f +*U +0.000 0.000 0.000 0.831 k +*u +800 338 m +801 337 l +800 338 l +f +*U +0.000 0.000 0.000 0.075 k +*u +853 338 m +852 336.521 852 336.797 852 335 c +853.289 336.443 853.401 336.234 853 338 c +f +*U +0.000 0.000 0.000 0.655 k +*u +854 338 m +855 337 l +854 338 l +f +*U +0.000 0.000 0.000 0.071 k +*u +937 338 m +937 256 l +939.292 261.462 938 269 938 275 c +938 317 l +938 323.420 939.497 332 937 338 c +f +*U +0.000 0.259 0.192 0.090 k +*u +1053 338 m +1054 337 l +1053 338 l +f +*U +0.000 0.392 0.220 0.341 k +*u +1108.333 337.333 m +1108.278 337.278 1108.222 336.222 1108.667 336.667 c +1108.723 336.723 1108.777 337.778 1108.333 337.333 c +f +*U +0.000 0.388 0.306 0.286 k +*u +1288 338 m +1289 337 l +1288 338 l +f +*U +0.000 0.427 0.333 0.004 k +*u +1289 338 m +1290 337 l +1289 338 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1431 338 m +1427 330.610 1429 320 1429 312 c +1429 256 l +1440 256 l +1440 267 1441.209 279.000 1440 290 c +1442.979 290.596 1441.733 291.567 1444 291 c +1445 292 l +1444.466 294.670 1445.785 294.443 1443 295 c +1446.375 295.457 1448.391 295.223 1451 293 c +1455 294 l +1453.466 292.978 1453.598 293.195 1453 292 c +1456 291 l +1455 289 l +1458.629 286.899 1463 289 1466 287 c +1468 292 l +1464 290 l +1466 294 l +1463.851 295.236 1456.647 297 1458 300 c +1456.526 302.358 1455.440 306.306 1452 306.500 c +1448.447 306.700 1446.841 301 1443.333 304.167 c +1439.311 307.751 1441.765 309.947 1442 314 c +1442.422 321.278 1442 328.708 1442 336 c +1439.194 329.313 1441 319.233 1441 312 c +1438.801 319.438 1440 328.271 1440 336 c +1436.580 336 1434 336.325 1431 338 c +f +*U +0.000 0.000 0.000 0.584 k +*u +1524 338 m +1525 337 l +1524 338 l +f +*U +0.000 0.000 0.000 0.169 k +*u +1649 338 m +1650.330 336.248 1651.247 335.330 1653 334 c +1651.847 336.249 1651.249 336.847 1649 338 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1679 338 m +1679 254 l +1698 254 l +1698 287 l +1705.526 287 1717 289.170 1724 286 c +1727.728 284.311 1730.884 281 1734 278.414 c +1753 262.750 l +1756.344 259.987 1759.841 256 1764 254.600 c +1771.303 251.994 1782.278 254 1790 254 c +1781 263 1769 269.783 1759 277.373 c +1754.494 280.753 1749.901 285.603 1744 285 c +1745.506 284.317 1746.315 284.174 1748 284 c +1746.400 283 1745.337 282.280 1744 281 c +1745 280 l +1750 282 l +1749.613 279.910 1749.616 280.289 1752 280 c +1752 272 l +1757 274 l +1760 269 l +1761.195 269.598 1760.978 269.466 1762 271 c +1762.901 269 1763 269 1765 268 c +1762.665 265.716 1761.409 264.229 1761 261 c +1758 264 l +1753.965 264.429 1751.657 266.859 1752 271 c +1749.312 271.592 1747.659 271.675 1745 271 c +1743.771 272.870 1743 273.224 1741 274 c +1740.752 276 1740.213 277 1739 279 c +1737 278.622 1736.240 278 1735 281 c +1734.839 281.375 1737 281.377 1734 282 c +1735.333 284 1735.679 285.552 1736 288 c +1732 286 l +1729.777 288.437 1726.208 287.912 1723 287.975 c +1714.614 288 1704 289.749 1696 288 c +1696.876 277.482 1696 266.572 1696 256 c +1680 256 l +1680 336 l +1760 336 l +1760 338 l +1679 338 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1774 338 m +1775 337 l +1774 338 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1775 338 m +1776.755 335.287 1777.833 333.611 1781 333 c +1779.210 335.445 1777.895 337 1775 338 c +f +*U +0.000 0.000 0.000 0.812 k +*u +360 337 m +361 336 l +360 337 l +f +*U +0.000 0.000 0.000 0.224 k +*u +361 337 m +362 336 l +361 337 l +f +*U +0.000 0.000 0.000 0.996 k +*u +479 337 m +479 330 478.884 323 479 316 c +479 313 479.940 309.399 478 307 c +478.598 305.805 478.466 306 480 305 c +461.492 303 442.591 304 424 304 c +418.504 304 408.270 302 404 306 c +401 304 l +400 336 l +384 336 l +384 256 l +400 256 l +400 264.332 399.915 272.669 400 281 c +400 285.375 401.167 289.738 400 294 c +415.345 295 430.608 295 446 295 c +455.295 295 464.832 295.702 474 294 c +473 296 l +474.850 295.798 476 295.798 478 296 c +477.952 293.670 477.797 293.994 480 293 c +479.776 291.316 479.782 290.687 480 289 c +478 290 l +480 278.957 479 267.203 479 256 c +495 256 l +495 336 l +489.600 336 484.282 335.742 479 337 c +f +*U +0.000 0.000 0.000 0.827 k +*u +801 337 m +802 336 l +801 337 l +f +*U +0.000 0.000 0.000 0.227 k +*u +802 337 m +803 336 l +802 337 l +f +*U +0.000 0.000 0.000 0.216 k +*u +881 337 m +882 336 l +881 337 l +f +*U +0.000 0.271 0.196 0.255 k +*u +1053 337 m +1054 336 l +1053 337 l +f +*U +0.043 0.000 0.071 0.396 k +*u +1288 337 m +1289 336 l +1288 337 l +f +*U +0.000 0.451 0.353 0.180 k +*u +1292 337 m +1293 336 l +1292 337 l +f +*U +0.000 0.702 0.553 0.298 k +*u +1293 337 m +1294.248 336.315 1294.548 336.251 1296 336 c +1294.752 336.685 1294.451 336.749 1293 337 c +f +*U +0.000 0.584 0.584 0.416 k +*u +1296 337 m +1297.248 336.315 1297.548 336.251 1299 336 c +1297.752 336.685 1297.452 336.749 1296 337 c +f +*U +0.000 0.635 0.443 0.357 k +*u +1299 337 m +1300 333 l +1300.751 335 1300.656 335.596 1299 337 c +f +*U +0.000 0.106 0.067 0.122 k +*u +1395 337 m +1396 336 l +1395 337 l +f +*U +0.000 0.000 0.000 0.098 k +*u +1521 336 m +1522.809 335.426 1523 335.535 1525 336 c +1523.341 336.406 1522.758 336.309 1521 336 c +f +*U +0.000 0.000 0.000 0.788 k +*u +1544 337 m +1545 336 l +1544 337 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1960 337 m +1953.445 335 1946.674 336 1940 334 c +1942 331.998 1942.903 330.929 1943 328 c +1939 330 l +1940 328 l +1937 329 l +1936.501 327.201 1936.267 326.281 1935 325 c +1934.834 323 1934.555 321.804 1934 320 c +1942 314 l +1944 320 l +1945 319 l +1944 324 l +1945.915 322.723 1945 322.723 1947 324 c +1944 328 l +1946.590 327.435 1950.248 327.898 1952.572 326.601 c +1956 324.606 1958 319.366 1960 316 c +1963.171 310.633 1966.869 306.574 1971 302 c +1976 304 l +1973.470 300.177 1975.978 297.212 1976 293 c +1978 293.501 1979 293.637 1981 293 c +1984.465 297.246 1986.168 301.549 1985 307 c +1981.505 305.871 1978.520 307.387 1975 308 c +1978 313 l +1976 316.927 1973.812 320.679 1970 323 c +1969.776 327.728 1965.586 329.413 1962 332 c +1961.274 329.821 1961.561 330.220 1960 331 c +1960.452 333.241 1960.838 334.884 1960 337 c +f +40 336 m +40 329 l +55 329 74 332.196 88 326 c +87 318.526 88 310.551 88 303 c +88 256 l +103 256 l +103 329 l +144 329 l +144 336 l +40 336 l +f +152 336 m +152 331.354 152.313 327 150 323 c +153.524 318.323 152 309.597 152 304 c +152 256 l +225 256 l +230.330 256 235.670 255.904 240.999 256 c +242.984 256 245.590 255.865 246.972 257.603 c +248.468 259.484 247.992 262.768 248 265 c +199 265 l +188.695 265 178.210 265.561 168 264 c +169.301 274.446 166.876 285.466 168 296 c +169 294.466 168.805 294.598 170 294 c +173.701 296.622 179.518 295.979 184 295.999 c +194.666 296 205.334 296 216 296 c +216 305 l +204.357 305 192.635 304.604 181 305 c +178 305 171 303.824 168.983 305.948 c +167.236 307.701 167.906 310.802 167.965 313 c +168 318.328 168 323.671 168 329 c +247 329 l +247 336 l +152 336 l +f +*U +0.000 0.000 0.000 0.090 k +*u +362 336 m +364.278 327.651 365 320.686 365 312 c +367 312 l +367 319.634 367.930 330.355 362 336 c +f +*U +0.000 0.000 0.000 0.682 k +*u +542 336 m +543 335 l +542 336 l +f +*U +0.000 0.000 0.000 0.996 k +*u +616 336 m +616 299 l +616 291.661 615.447 283.624 619 277 c +623 280 l +622.976 276.554 622 274.713 620 272 c +619 275 l +616 274.700 614.652 274.995 614 272 c +610 282 l +609.315 280.752 609.251 280.452 609 279 c +606.715 280.588 604.754 280.700 602 281 c +603.186 282.186 603.584 282.528 605 283 c +602 285.478 599.167 287.871 596 290 c +594 288 l +593.658 290.602 593.459 291.946 595 294 c +590 296.451 586.648 300.786 582 303.667 c +580.295 304.723 578.583 304.813 577 306 c +576 303 l +574.814 304.186 574.416 304.528 573 305 c +573 301 l +576 301 l +576 296 l +580.731 295.471 583.468 293.995 582 289 c +584 289 583.724 289 584 287 c +591 288 l +591.195 283.869 591.189 280.197 596 280 c +597.222 278.267 598 277.849 600 277 c +600.796 272.450 604 271.911 607 269 c +612 271 l +612 267 l +612.683 268.506 612.826 269.315 613 271 c +616 263 l +619.199 263 620.875 262.386 620 259 c +624.291 257.179 627.247 256 632 256 c +632 336 l +616 336 l +f +*U +0.000 0.000 0.000 0.137 k +*u +657 336 m +657 254 l +662.715 254 676 251.540 680 256 c +675.303 254.882 663.409 252.798 659.603 256.603 c +655.862 260.345 658 272 658 277 c +658 317 l +658 322.887 659.292 330.538 657 336 c +f +*U +0.000 0.000 0.000 0.996 k +*u +664 336 m +664 256 l +673 256 l +673 336 l +664 336 l +f +*U +0.000 0.000 0.000 0.196 k +*u +703 336 m +704 335 l +703 336 l +f +*U +0.000 0.000 0.000 0.114 k +*u +803 336 m +804 332 l +804.751 334 804.656 334.596 803 336 c +f +*U +0.000 0.000 0.000 0.996 k +*u +944 336 m +944 256 l +1011 256 l +1015.400 256 1027.971 253.850 1030.972 257.602 c +1032.312 259.276 1031.976 262 1032 264 c +978 264 l +971 264 961 262.350 955 266 c +952 265 l +953.343 272.365 952 280.485 952 288 c +952 336 l +944 336 l +f +*U +0.000 0.561 0.463 0.318 k +*u +1108 336 m +1108 333 l +1108.696 334.554 1108.696 334.446 1108 336 c +f +*U +0.000 0.302 0.224 0.157 k +*u +1189 336 m +1189 333 l +1189.696 334.554 1189.696 334.446 1189 336 c +f +*U +0.000 0.698 0.537 0.302 k +*u +1287 336 m +1287 330 l +1287.951 332.285 1287.951 333.715 1287 336 c +f +*U +0.000 0.118 0.063 0.176 k +*u +1288 336 m +1288 329 l +1289 331.534 1289 333.466 1288 336 c +f +*U +0.000 0.431 0.310 0.090 k +*u +1395 336 m +1396 335 l +1395 336 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1495 336 m +1496 335 l +1495 336 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1543 336 m +1544 335 l +1543 336 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1800 336 m +1800 256 l +1868 256 l +1874.243 256 1888.339 252.975 1888 262 c +1890 261 l +1886.645 265.749 1878.243 264 1873 264 c +1824 264 l +1830.868 266 1838.869 265 1846 265 c +1888 265 l +1883.280 266.981 1877 266 1872 266 c +1839 266 l +1834.423 266 1826.197 267.658 1823 264 c +1821 264.402 1820.943 264.402 1819 264 c +1814.610 274.280 1816.439 285 1816 296 c +1821 293 l +1822 296 l +1835.586 294.506 1850.274 296 1864 296 c +1864 304 l +1853 304 1842.000 303.951 1831 304 c +1825.937 304 1820.979 305 1816 304 c +1816.761 311.353 1817.516 320.795 1816 328 c +1823.794 328.871 1832 328 1840 328 c +1888 328 l +1888 336 l +1800 336 l +f +*U +0.000 0.000 0.000 0.710 k +*u +262 335 m +263 334 l +262 335 l +f +*U +0.000 0.000 0.000 0.149 k +*u +544 335 m +545.223 333.805 545.420 333.684 547 333 c +545.777 334.195 545.580 334.316 544 335 c +f +*U +0.000 0.000 0.000 0.200 k +*u +702.333 334.333 m +702.278 334.278 702.222 333.222 702.667 333.667 c +702.722 333.722 702.778 334.778 702.333 334.333 c +f +*U +0.000 0.000 0.000 0.733 k +*u +703 335 m +704 334 l +703 335 l +f +*U +0.000 0.000 0.000 1.000 k +*u +802 335 m +799.654 327.528 800 319.764 800 312 c +797.558 311.891 795.377 311.572 793 311 c +791.660 316.627 791.872 322.254 792 328 c +791.315 326.752 791.251 326.451 791 325 c +786.553 330.882 777.644 329 771 329 c +719 329 l +719 307.660 718.430 286.235 720 265 c +721.314 265.768 721.232 265.686 722 267 c +724 264 l +731.213 265.221 739.599 264 747 264 c +761.998 264 777 264.185 792 264 c +791.510 272.494 791.417 281.523 792 290 c +786 291 l +786 269 l +740 269 l +735.281 269 726.390 267.311 722.318 270 c +718.716 272.431 720 279.309 720 283 c +720 315 l +720 318.565 719 324.610 722.434 326.972 c +726.403 329.704 735.362 328 740 328 c +786 328 l +786 309 l +790.704 309.371 800.650 308.986 804.397 312 c +806.351 313.608 805.985 316.769 805.999 319 c +806 324.758 806 330.621 802 335 c +f +*U +0.000 0.635 0.451 0.365 k +*u +1053 335 m +1053 331 l +1053.710 332.759 1053.710 333.241 1053 335 c +f +*U +0.000 0.000 0.000 0.675 k +*u +1519 335 m +1520 334 l +1519 335 l +f +*U +0.000 0.000 0.000 0.255 k +*u +1520 335 m +1521 334 l +1520 335 l +f +*U +0.000 0.000 0.000 0.133 k +*u +849 334 m +849 330 l +850.434 331.393 851 332.233 852 334 c +849 334 l +f +*U +0.000 0.424 0.325 0.098 k +*u +1109 334 m +1110 333 l +1109 334 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1517 334 m +1518 333 l +1517 334 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1653 334 m +1656.654 318 1656 302.349 1656 286 c +1656 278.680 1656.716 269.601 1652.911 263 c +1649.440 256.988 1642.787 257.507 1639 253 c +1644.525 253.748 1649.893 255.313 1653.347 260 c +1657 265 1656.998 272 1657 278 c +1657 309 l +1657 317 1658.856 327.485 1653 334 c +f +*U +0.000 0.000 0.000 0.180 k +*u +1937.333 333.333 m +1937.278 333.278 1937.222 332.222 1937.667 332.667 c +1937.722 332.722 1937.778 333.778 1937.333 333.333 c +f +*U +0.000 0.000 0.000 0.686 k +*u +1938 334 m +1939 333 l +1938 334 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1968 334 m +1968.899 331.876 1968.876 331.899 1971 331 c +1969.896 332.457 1969.457 332.897 1968 334 c +f +*U +0.000 0.000 0.000 0.129 k +*u +260 333 m +257.599 323.720 258 314.513 258 305 c +258 292.256 257.999 279.680 259 267 c +260.908 271.636 259 277 259 282 c +258.781 292.964 258.746 304 259 315 c +259 320.683 261.674 327.556 260 333 c +f +*U +0.000 0.000 0.000 0.710 k +*u +261 333 m +262 332 l +261 333 l +f +*U +0.000 0.000 0.000 0.600 k +*u +546 333 m +547 332 l +546 333 l +f +*U +0.000 0.000 0.000 0.110 k +*u +547 333 m +550.358 328.622 554.915 325 560 323 c +556.600 327.482 552.218 330.882 547 333 c +f +*U +0.000 0.000 0.000 0.118 k +*u +701 333 m +698 319 699 305 699 291 c +699 282 698 272.632 701 264 c +702.590 269.170 700.275 275.621 700 281 c +699.560 291.942 699.887 303 700 314 c +700 319.906 702.716 327.418 701 333 c +f +*U +0.000 0.000 0.000 0.671 k +*u +702 333 m +703 332 l +702 333 l +f +*U +0.000 0.000 0.000 0.114 k +*u +884 333 m +884.684 331.420 884.805 331.223 886 330 c +885.316 331.580 885.195 331.777 884 333 c +f +*U +0.000 0.243 0.180 0.259 k +*u +1052 333 m +1052 330 l +1052.696 331.554 1052.696 331.446 1052 333 c +f +*U +0.000 0.157 0.165 0.176 k +*u +1111 333 m +1112 332 l +1111 333 l +f +*U +0.000 0.506 0.392 0.494 k +*u +1300 333 m +1300 329 l +1304 329 l +1300 333 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1487 331 m +1488.580 331.683 1488.777 331.805 1490 333 c +1488.419 332.316 1488.223 332.196 1487 331 c +f +*U +0.000 0.000 0.000 0.718 k +*u +1490 333 m +1491 332 l +1490 333 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1513 331 m +1515.509 330.434 1516.220 331 1518 333 c +1516 332.453 1514.745 331.890 1513 331 c +f +1540 333 m +1538 326 l +1540.353 327.901 1540.877 330 1540 333 c +f +*U +0.000 0.000 0.000 0.765 k +*u +1541 333 m +1542 332 l +1541 333 l +f +*U +0.000 0.000 0.000 0.141 k +*u +805 332 m +806 324 l +807.232 327 806.825 329.328 805 332 c +f +*U +0.000 0.435 0.435 0.565 k +*u +1111 332 m +1112 331 l +1111 332 l +f +*U +0.000 0.184 0.137 0.361 k +*u +1112 332 m +1113 331 l +1112 332 l +f +*U +0.000 0.263 0.329 0.384 k +*u +1191 332 m +1192 331 l +1191 332 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1779 332 m +1780 331 l +1779 332 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1780.333 331.333 m +1780.278 331.278 1780.222 330.222 1780.667 330.667 c +1780.722 330.723 1780.777 331.778 1780.333 331.333 c +f +*U +0.000 0.549 0.490 0.451 k +*u +1105 330 m +1107.890 328.787 1110.874 329 1114 329 c +1111.184 330.629 1108.238 330 1105 330 c +f +*U +0.000 0.392 0.294 0.184 k +*u +1113 331 m +1114 330 l +1113 331 l +f +*U +0.000 0.220 0.153 0.102 k +*u +1396 331 m +1397 330 l +1396 331 l +f +*U +0.000 0.000 0.000 0.157 k +*u +1483 330 m +1484.809 329.426 1485 329.535 1487 330 c +1485.341 330.406 1484.758 330.309 1483 330 c +f +*U +0.000 0.000 0.000 0.753 k +*u +1512 331 m +1513 330 l +1512 331 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1969 331 m +1970 330 l +1969 331 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1970.333 330.333 m +1970.278 330.278 1970.222 329.222 1970.667 329.667 c +1970.722 329.722 1970.778 330.778 1970.333 330.333 c +f +*U +0.000 0.000 0.000 0.596 k +*u +260 330 m +261 329 l +260 330 l +f +*U +0.000 0.000 0.000 0.616 k +*u +701 330 m +702 329 l +701 330 l +f +*U +0.000 0.000 0.000 0.714 k +*u +849 330 m +850 329 l +849 330 l +f +*U +0.000 0.000 0.000 0.761 k +*u +885 330 m +886 329 l +885 330 l +f +*U +0.000 0.000 0.000 0.102 k +*u +886 330 m +886.944 327 888.286 324.624 890 322 c +890.962 325.672 888.789 327.790 886 330 c +f +*U +0.000 0.584 0.482 0.416 k +*u +1052 330 m +1053.506 329.317 1054.315 329.174 1056 329 c +1054.494 329.683 1053.685 329.826 1052 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1056 330 m +1060.720 328 1066.920 329 1072 329 c +1105 329 l +1100.280 330.981 1094 330 1089 330 c +1056 330 l +f +*U +0.000 0.169 0.149 0.224 k +*u +1114 330 m +1115 329 l +1114 330 l +f +*U +0.000 0.404 0.278 0.247 k +*u +1193 330 m +1194 329 l +1193 330 l +f +*U +0.000 0.541 0.431 0.459 k +*u +1194 330 m +1195.769 329.221 1197 329 1199 329 c +1197.231 329.779 1195.964 329.912 1194 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1199 330 m +1205.919 327 1216.520 329 1224 329 c +1280 329 l +1273 331.903 1262.480 330 1255 330 c +1199 330 l +f +*U +0.000 0.522 0.400 0.478 k +*u +1280 330 m +1282.613 328.902 1285 329 1288 329 c +1285.387 330 1282.835 329.993 1280 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1304 330 m +1311.399 326.895 1322.993 329 1331 329 c +1392 329 l +1384.600 332 1373 330 1365 330 c +1304 330 l +f +*U +0.000 0.216 0.141 0.404 k +*u +1396 330 m +1397 329 l +1396 330 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1508 328 m +1510 327.590 1510.963 328 1513 329 c +1510.860 329.410 1510 328.968 1508 328 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1780 330 m +1780 328 l +1782 328 l +1782 330 l +1780 330 l +f +*U +0.000 0.000 0.000 0.231 k +*u +1935 330 m +1936 329 l +1935 330 l +f +*U +0.000 0.000 0.000 0.655 k +*u +364 329 m +365 328 l +364 329 l +f +*U +0.000 0.000 0.000 0.808 k +*u +551 329 m +552 328 l +551 329 l +f +*U +0.000 0.000 0.000 0.612 k +*u +805 329 m +806 328 l +805 329 l +f +*U +0.000 0.000 0.000 0.000 k +*u +866.667 328.667 m +866.222 328.222 867.278 328.278 867.333 328.333 c +867.778 328.778 866.722 328.722 866.667 328.667 c +f +*U +0.000 0.169 0.114 0.063 k +*u +1195 329 m +1196 328 l +1195 329 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1558 327 m +1555.663 327.519 1554.360 327.480 1552 327 c +1558.248 321 1557 315 1557 307 c +1557 272 l +1555.308 277.725 1556 284 1556 290 c +1556 320 l +1554 315.531 1555 309.809 1555 305 c +1555 294 1552.890 280.522 1556 270 c +1552.911 274 1554 280 1554 285 c +1554 321 l +1552.231 316.785 1553 311.536 1553 307 c +1553 280 l +1552.994 276 1550.995 269.732 1554 267 c +1552.964 265.814 1552.661 265.396 1552 264 c +1555 264.614 1554.395 263.395 1557 266 c +1557 264 l +1562 268.917 1571.341 267 1578 267 c +1633 267 l +1631.723 265 1631.723 265.915 1633 264 c +1634 265 1634.308 265.611 1635 267 c +1636.757 265.267 1637.642 264.659 1640 264 c +1639.402 265.195 1639.534 264.978 1638 266 c +1641.511 269.368 1640 277.401 1640 282 c +1640 311 l +1640.000 315 1638.806 320.206 1640 324 c +1639 328 l +1619 327.290 1597.519 328 1577 328 c +1572.735 328 1568.242 327.588 1564 328 c +1561 328.277 1559.227 330 1558 327 c +f +*U +0.000 0.000 0.000 0.820 k +*u +1654 329 m +1655 328 l +1654 329 l +f +*U +0.000 0.000 0.000 0.243 k +*u +1934 329 m +1935 328 l +1934 329 l +f +*U +0.000 0.000 0.000 0.737 k +*u +1935 329 m +1936 328 l +1935 329 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1971 329 m +1972 328 l +1971 329 l +f +*U +0.000 0.000 0.000 0.000 k +*u +104 328 m +108.215 326.231 113.464 327 118 327 c +147 327 l +142.785 328.769 137.536 328 133 328 c +104 328 l +f +*U +0.000 0.000 0.000 0.133 k +*u +104 327 m +104 255 l +99.198 255 88.240 252.966 84.603 256.603 c +81 260 83 270.410 83 275 c +83 327 l +40 327 l +44.215 325.231 49.464 326 54 326 c +82 326 l +82 254 l +105 254 l +105 326 l +147 326 l +147 254 l +250 254 l +250 270 l +248 265.529 249 259.817 249 255 c +175 255 l +169 255 162.999 254.959 157 255 c +154.582 255 151.474 254.732 149.603 256.603 c +146 260 148 270.410 148 275 c +148 292.208 145.855 311 149 328 c +134.538 325.315 118.684 327 104 327 c +f +*U +0.000 0.000 0.000 0.867 k +*u +279 328 m +279 270 l +280.981 274.720 280 280.920 280 286 c +280 314 l +280 318.536 280.769 323.785 279 328 c +f +*U +0.000 0.000 0.000 0.000 k +*u +280 328 m +285.951 325.503 294.580 327 301 327 c +345 327 l +339 329.497 330.420 328 324 328 c +280 328 l +f +721 328 m +726.951 325.503 735.580 327 742 327 c +786 327 l +780 329.497 771.420 328 765 328 c +721 328 l +f +*U +0.000 0.000 0.000 0.082 k +*u +846 328 m +844.296 325 842.939 322.260 842 319 c +844.821 321.605 846.482 324.483 848 328 c +846 328 l +f +*U +0.000 0.000 0.000 0.102 k +*u +865 325 m +866.457 326 866.897 326.543 868 328 c +865.876 327 865.899 327 865 325 c +f +*U +0.000 0.000 0.000 0.125 k +*u +1472 321 m +1482 327 l +1477.705 327.702 1473.987 324.621 1472 321 c +f +*U +0.000 0.000 0.000 0.702 k +*u +1482 328 m +1483 327 l +1482 328 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1507 328 m +1508 327 l +1507 328 l +f +*U +0.000 0.000 0.000 0.890 k +*u +1780.333 327.333 m +1780.278 327.278 1780.222 326.222 1780.667 326.667 c +1780.722 326.723 1780.777 327.778 1780.333 327.333 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1781 328 m +1781 300 l +1783.604 306.207 1783.604 321.793 1781 328 c +f +*U +0.000 0.000 0.000 0.098 k +*u +1952 328 m +1952.684 326.420 1952.805 326.223 1954 325 c +1953.316 326.580 1953.195 326.777 1952 328 c +f +*U +0.000 0.000 0.000 0.686 k +*u +1971 328 m +1972 327 l +1971 328 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1972 328 m +1973.508 323.269 1976.410 319.216 1979 315 c +1980.187 319.889 1975.422 324.898 1972 328 c +f +*U +0.000 0.000 0.000 0.141 k +*u +280 327 m +280 272 l +282.189 277.217 281 284.381 281 290 c +281 326 l +344 326 l +338.293 328.395 330 327 324 327 c +280 327 l +f +*U +0.000 0.000 0.000 0.106 k +*u +344 327 m +342.423 321.665 341 310.732 346 307 c +344.820 313.355 346.459 321 344 327 c +f +*U +0.000 0.000 0.000 0.153 k +*u +721 327 m +721 270 l +786 270 l +780.293 272.395 772 271 766 271 c +722 271 l +722 326 l +784 326 l +784 319.757 783.222 313 785 307 c +787.709 307.648 790.216 307.942 793 308 c +791 308.871 788.187 308.991 786.603 310.603 c +783.338 313.925 785 322.689 785 327 c +721 327 l +f +*U +0.000 0.000 0.000 0.075 k +*u +785 327 m +785 310 l +786.883 314.486 786.883 322.514 785 327 c +f +*U +0.000 0.000 0.000 0.592 k +*u +847 327 m +848 326 l +847 327 l +f +*U +0.000 0.000 0.000 0.000 k +*u +867 327 m +863.441 323.609 861.755 319.216 858 316 c +857.516 312.696 856.536 311 854 309 c +852.926 302.808 847.781 296.667 845 291 c +889 291 l +886.655 296.373 883 300.984 880 305.996 c +875.946 312.991 872.250 320.731 867 327 c +f +*U +0.000 0.000 0.000 0.161 k +*u +868.333 326.333 m +868.278 326.278 868.222 325.222 868.667 325.667 c +868.722 325.722 868.778 326.778 868.333 326.333 c +f +*U +0.000 0.000 0.000 0.129 k +*u +1506.667 326.667 m +1506.222 326.222 1507.278 326.278 1507.333 326.333 c +1507.778 326.778 1506.722 326.722 1506.667 326.667 c +f +*U +0.000 0.000 0.000 0.012 k +*u +1559 325 m +1567.923 327 1577.866 326 1587 326 c +1636 326 l +1630.537 328.292 1622.887 327 1617 327 c +1577 327 l +1572 327 1562.407 328.899 1559 325 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1698 327 m +1703.217 324.811 1710.381 326 1716 326 c +1755 326 l +1749.783 328.189 1742.619 327 1737 327 c +1698 327 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1755 327 m +1756.717 325 1757.566 324.651 1760 324 c +1758.314 325.656 1757.254 326.251 1755 327 c +f +*U +0.000 0.000 0.000 0.761 k +*u +1757 327 m +1758 326 l +1757 327 l +f +*U +0.000 0.000 0.000 0.075 k +*u +1818 327 m +1818 320.654 1817.522 314.208 1819 308 c +1821 312.974 1820 319.638 1820 325 c +1897 325 l +1891.726 328.996 1881.423 327 1875 327 c +1818 327 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1951 327 m +1952 326 l +1951 327 l +f +*U +0.000 0.000 0.000 0.071 k +*u +148 326 m +148 256 l +150 260.969 149 267.650 149 273 c +149 307 l +149 312.887 150.292 320.538 148 326 c +f +*U +0.000 0.000 0.000 0.820 k +*u +555 326 m +556 325 l +555 326 l +f +*U +0.000 0.000 0.000 0.859 k +*u +720 326 m +720 270 l +721.769 274.215 721 279.465 721 284 c +721 311 l +721 315.809 721.875 321.531 720 326 c +f +*U +0.000 0.000 0.000 0.671 k +*u +864 326 m +865 325 l +864 326 l +f +*U +0.000 0.000 0.000 0.639 k +*u +869 326 m +870 325 l +869 326 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1503 324 m +1504.580 324.683 1504.777 324.805 1506 326 c +1504.420 325.316 1504.223 325.195 1503 324 c +f +*U +0.000 0.000 0.000 0.161 k +*u +1538 326 m +1538 268 l +1539.981 272.720 1539 278.920 1539 284 c +1539 312 l +1539 316.536 1539.769 321.785 1538 326 c +f +*U +0.000 0.000 0.000 0.600 k +*u +1539 326 m +1540 325 l +1539 326 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1559 269 m +1636 269 l +1636 326 l +1579 326 l +1574.766 326 1562.918 328 1560 324.397 c +1557.456 321 1559 312.929 1559 309 c +1559 269 l +f +*U +0.000 0.000 0.000 0.067 k +*u +1698 326 m +1698 302 l +1700.633 308.274 1699.858 319 1700 326 c +1698 326 l +f +*U +0.000 0.000 0.000 0.000 k +*u +1700 326 m +1700 302 l +1719 302 1740.201 299.510 1759 303 c +1759 308 1761.253 320.332 1757.397 324 c +1754 327.425 1746.315 326 1742 326 c +1700 326 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1932 326 m +1929 321.997 1926.230 317.784 1925 313 c +1928.309 316 1932.684 321.314 1932 326 c +f +*U +0.000 0.000 0.000 0.576 k +*u +1933 326 m +1934 325 l +1933 326 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1951 326 m +1949.286 323.376 1947.944 320.987 1947 318 c +1949.464 320.284 1951.502 322.551 1951 326 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1952 326 m +1950.218 322.226 1947.742 319.243 1948 315 c +1940 310.991 1935 297.600 1931 290 c +1945.210 290 1959.845 291 1974 290 c +1970.750 297.805 1965.749 304.792 1961.370 312 c +1958.365 316.945 1956.264 321.945 1952 326 c +f +*U +0.000 0.000 0.000 0.627 k +*u +1954 326 m +1955 325 l +1954 326 l +f +*U +0.000 0.000 0.000 0.141 k +*u +869 325 m +869.944 322 871.286 319.624 873 317 c +873.502 320.449 871.464 322.716 869 325 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1477 325 m +1478 324 l +1477 325 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1502 325 m +1503 324 l +1502 325 l +f +*U +0.000 0.000 0.000 0.882 k +*u +1539.333 324.333 m +1539.278 324.278 1539.222 323.222 1539.667 323.667 c +1539.723 323.723 1539.777 324.778 1539.333 324.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1560 325 m +1560 270 l +1635 270 l +1635 309 l +1635 312.731 1636.423 320.302 1633.972 323.397 c +1631 327 1619.234 325 1615 325 c +1560 325 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1954 325 m +1954.547 323 1955 321.744 1956 320 c +1956.375 322.419 1955.693 323.218 1954 325 c +f +*U +0.000 0.000 0.000 0.000 k +*u +700.333 323.333 m +700.277 323.278 700.222 322.222 700.667 322.667 c +700.722 322.722 700.778 323.778 700.333 323.333 c +f +*U +0.000 0.000 0.000 0.090 k +*u +806 324 m +806 311 l +808.794 314.688 808 319.519 808 324 c +806 324 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1496 321 m +1498.837 320.325 1500.522 321.495 1503 323 c +1500.311 323.405 1498.444 322.225 1496 321 c +f +*U +0.000 0.000 0.000 0.651 k +*u +1655.333 323.333 m +1655.278 323.278 1655.222 322.222 1655.667 322.667 c +1655.722 322.722 1655.777 323.778 1655.333 323.333 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1759 324 m +1759 303 l +1761.351 307.369 1761.449 319.711 1759 324 c +f +*U +0.000 0.000 0.000 0.780 k +*u +1949 324 m +1950 323 l +1949 324 l +f +*U +0.000 0.000 0.000 0.757 k +*u +559 323 m +560 322 l +559 323 l +f +*U +0.000 0.000 0.000 0.090 k +*u +560 323 m +562.319 320 564.622 318.432 568 317 c +565.709 320 563.641 321.761 560 323 c +f +*U +0.000 0.000 0.000 0.831 k +*u +871 323 m +872 322 l +871 323 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1474 323 m +1475 322 l +1474 323 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1760 323 m +1761 322 l +1760 323 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1956 323 m +1957 322 l +1956 323 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1974 323 m +1975 322 l +1974 323 l +f +*U +0.000 0.000 0.000 0.824 k +*u +560 322 m +561 321 l +560 322 l +f +*U +0.000 0.000 0.000 0.749 k +*u +844 322 m +845 321 l +844 322 l +f +*U +0.000 0.000 0.000 0.122 k +*u +862 322 m +861 320.255 860.547 318.875 860 317 c +861.693 318.782 862.375 319.581 862 322 c +f +*U +0.000 0.000 0.000 0.827 k +*u +890 322 m +891 321 l +890 322 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1471 322 m +1472 321 l +1471 322 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1497 322 m +1498 321 l +1497 322 l +f +*U +0.000 0.000 0.000 0.871 k +*u +1655 322 m +1655 274 l +1656.552 277.699 1656 282 1656 286 c +1656 309 l +1656 313.260 1656.661 318 1655 322 c +f +*U +0.000 0.000 0.000 0.616 k +*u +259 321 m +259 276 l +260.661 279.959 260 284.740 260 289 c +260 310 l +260 313.702 260.441 317.565 259 321 c +f +*U +0.000 0.000 0.000 0.635 k +*u +700 321 m +700 276 l +701.661 279.959 701 284.740 701 289 c +701 310 l +701 313.702 701.441 317.565 700 321 c +f +*U +0.000 0.000 0.000 0.996 k +*u +879 319 m +879.508 316.408 879.508 314.593 879 312 c +883 310 l +883.986 311.479 884 311.203 884 313 c +885.493 312 885.266 312 887 312 c +886.423 309.289 886.232 308.605 889 308 c +887.522 307 887.797 307 886 307 c +887.791 304 888.463 290.190 895 296 c +896 290 l +890.818 288.394 885.381 289 880 289 c +853 289 l +847.537 289 840.729 287.777 841 295 c +839.521 295.986 839.797 296 838 296 c +838.986 297.479 839 297.203 839 299 c +834 302 l +832.781 298.586 832.532 293.624 830.647 290.607 c +827.879 286.179 821.909 286.980 823 280 c +817 279 l +817.194 276.894 817.417 275 818 273 c +816.203 273 816.479 272.986 815 272 c +815.224 269.625 815.214 267.376 815 265 c +813 268 l +809.974 264.391 807.832 260.662 807 256 c +817 256 l +816 261 l +818.172 261.464 819.958 262 822 263 c +821 261 l +823.979 261.596 822.733 262.567 825 262 c +825.613 263.661 826 264.483 827 266 c +825.550 267.608 824.949 268 823 269 c +826 271 l +826 269.203 826 269.479 827 268 c +830.854 272 832.458 276 838 278.532 c +842.983 280.687 848.690 280 854 280 c +882 280 l +887.552 280 893 280.668 898 278 c +899.804 278.555 901 278.834 903 279 c +901 276 l +904 275 l +903 272 l +907.215 271.394 911.430 271.215 911 266 c +910 268 l +908.235 265.304 908.957 263.863 912 263 c +910.624 253 923 255.829 929 258 c +926.540 260.196 924.463 262 923 265 c +921.919 263.542 921.564 262.752 921 261 c +920.862 263.667 921 264 923 266 c +922.434 267.773 922 269 922 271 c +919 274 l +916 273 l +918 277 l +914.586 280.751 911 284.951 910 290 c +905.168 290 904.463 292.500 905 297 c +903.203 297 903.479 296.986 902 296 c +901 299 l +899.177 298.255 897.977 298 896 298 c +898 301 l +895.658 301.781 895.980 301.654 898 303 c +897.455 304.635 897.635 304.455 896 305 c +897.550 308 896.183 309.916 895 313 c +892.440 312.887 890.456 313.265 888 314 c +888.496 316.556 888.442 318.429 888 321 c +884.864 320.580 881.976 320 879 319 c +f +*U +0.000 0.000 0.000 0.157 k +*u +892.333 320.333 m +892.278 320.278 892.222 319.222 892.667 319.667 c +892.722 319.722 892.778 320.778 892.333 320.333 c +f +1464 318 m +1466.690 317.595 1468.556 318.775 1471 320 c +1468 320.675 1466.478 319.505 1464 318 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1760 321 m +1760 307 l +1761.667 310.972 1761.667 317 1760 321 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1930 321 m +1931 320 l +1930 321 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1957 321 m +1958 320 l +1957 321 l +f +*U +0.000 0.000 0.000 0.027 k +*u +539 320 m +539 317 l +539.696 318.554 539.696 318.446 539 320 c +f +*U +0.000 0.000 0.000 0.765 k +*u +563 320 m +564 319 l +563 320 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1469 320 m +1470 319 l +1469 320 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1699 320 m +1699 313.654 1699.478 307.208 1698 301 c +1701 301 l +1699.540 307 1701.403 314.274 1699 320 c +f +*U +0.000 0.000 0.000 0.647 k +*u +1976 320 m +1977 319 l +1976 320 l +f +*U +0.000 0.000 0.000 0.761 k +*u +540 319 m +541 318 l +540 319 l +f +*U +0.000 0.000 0.000 0.125 k +*u +841 319 m +840 317.255 839.547 315.875 839 314 c +840.693 315.782 841.375 316.581 841 319 c +f +*U +0.000 0.000 0.000 0.745 k +*u +842 319 m +843 318 l +842 319 l +f +*U +0.000 0.000 0.000 0.725 k +*u +892 319 m +893 318 l +892 319 l +f +*U +0.000 0.000 0.000 0.094 k +*u +893 319 m +893.684 317.420 893.805 317.223 895 316 c +894.316 317.580 894.195 317.777 893 319 c +f +*U +0.000 0.118 0.239 0.184 k +*u +1051 319 m +1052 318 l +1051 319 l +f +*U +0.000 0.216 0.047 0.082 k +*u +1052 319 m +1053 318 l +1052 319 l +f +*U +0.000 0.129 0.059 0.169 k +*u +1109 319 m +1110.506 318.317 1111.315 318.174 1113 318 c +1111.494 318.683 1110.685 318.826 1109 319 c +f +*U +0.000 0.169 0.122 0.137 k +*u +1126 319 m +1127.769 318.221 1129 318 1131 318 c +1129.231 318.779 1127.964 318.912 1126 319 c +f +*U +0.000 0.176 0.106 0.153 k +*u +1202 319 m +1203.249 318.315 1203.548 318.251 1205 318 c +1203.752 318.685 1203.451 318.749 1202 319 c +f +*U +0.000 0.251 0.184 0.110 k +*u +1281.667 318.667 m +1281.222 318.222 1282.278 318.278 1282.333 318.333 c +1282.778 318.778 1281.722 318.722 1281.667 318.667 c +f +*U +0.000 0.075 0.059 0.153 k +*u +1297.667 318.667 m +1297.222 318.222 1298.278 318.278 1298.333 318.333 c +1298.778 318.778 1297.722 318.722 1297.667 318.667 c +f +*U +0.000 0.098 0.078 0.227 k +*u +1396.667 318.667 m +1396.222 318.222 1397.278 318.278 1397.333 318.333 c +1397.778 318.778 1396.722 318.722 1396.667 318.667 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1492 319 m +1493 318 l +1492 319 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1946 319 m +1947 318 l +1946 319 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1958.333 318.333 m +1958.278 318.278 1958.222 317.222 1958.667 317.667 c +1958.723 317.723 1958.777 318.777 1958.333 318.333 c +f +540 318 m +540 255 l +542.395 260.707 541 268.846 541 275 c +541 316 l +543 314.242 544.581 313 547 312 c +544.951 314.832 543 316.520 540 318 c +f +*U +0.000 0.000 0.000 0.765 k +*u +859 318 m +860 317 l +859 318 l +f +*U +0.000 0.000 0.000 0.675 k +*u +874 318 m +875 317 l +874 318 l +f +*U +0.000 0.388 0.294 0.078 k +*u +1050 318 m +1050 315 l +1050.696 316.554 1050.696 316.446 1050 318 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1051 318 m +1056.707 315.605 1064.846 317 1071 317 c +1112 317 l +1106.293 319.395 1098 318 1092 318 c +1051 318 l +f +*U +0.000 0.235 0.204 0.765 k +*u +1112 318 m +1113 317 l +1112 318 l +f +*U +0.000 0.643 0.482 0.357 k +*u +1120 314 m +1124.336 312.848 1128 316.766 1133 316 c +1128.217 319.622 1124.585 316.330 1120 314 c +f +*U +0.000 0.263 0.180 0.149 k +*u +1132 318 m +1133 317 l +1132 318 l +f +*U +0.000 0.314 0.196 0.310 k +*u +1202 318 m +1203 317 l +1202 318 l +f +*U +0.000 0.580 0.467 0.420 k +*u +1203.667 317.667 m +1203.222 317.222 1204.278 317.278 1204.333 317.333 c +1204.778 317.778 1203.722 317.722 1203.667 317.667 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1204 317 m +1205.623 314.565 1208.716 314.819 1206 316 c +1213.999 318.364 1223.688 317 1232 317 c +1282 317 l +1281 312 l +1282.580 311.317 1282.777 311.195 1284 310 c +1284.985 312.806 1283.633 315 1283 318 c +1231 318 l +1222.393 318 1212.280 319.447 1204 317 c +f +*U +0.000 0.208 0.153 0.102 k +*u +1283 318 m +1283 315 l +1283.696 316.554 1283.696 316.446 1283 318 c +f +*U +0.000 0.878 0.627 0.122 k +*u +1296 318 m +1295.570 312.551 1295.260 311.437 1299 307.500 c +1298 307 l +1306 303.593 1319.203 306 1328 306 c +1397 306 l +1397 317 l +1331 317 l +1319.718 317 1307 315.379 1296 318 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1297 318 m +1305 314.593 1318.203 317 1327 317 c +1396 317 l +1387.882 320.407 1374.797 318 1366 318 c +1297 318 l +f +*U +0.000 0.600 0.616 0.376 k +*u +1396 318 m +1397 315 l +1397.685 316.248 1397.749 316.549 1398 318 c +1396 318 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1466 318 m +1467 317 l +1466 318 l +f +*U +0.000 0.000 0.000 0.792 k +*u +1490 318 m +1491 317 l +1490 318 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1946 318 m +1945 316.255 1944.547 314.875 1944 313 c +1948 315 l +1947.309 316.388 1947 316.861 1946 318 c +f +*U +0.000 0.000 0.000 0.576 k +*u +539.333 316.333 m +539.278 316.278 539.222 315.222 539.667 315.667 c +539.722 315.722 539.778 316.778 539.333 316.333 c +f +*U +0.000 0.000 0.000 0.659 k +*u +567 317 m +568 316 l +567 317 l +f +*U +0.000 0.000 0.000 0.051 k +*u +568 317 m +570 314.542 571.790 313.641 575 313 c +572.841 315 570.801 316 568 317 c +f +*U +0.000 0.000 0.000 0.114 k +*u +874 317 m +874.547 315 875 313.745 876 312 c +876.375 314.419 875.693 315.218 874 317 c +f +*U +0.000 0.682 0.776 0.188 k +*u +1051 317 m +1051 312 l +1051.830 314 1051.830 314.970 1051 317 c +f +*U +0.000 0.906 0.667 0.094 k +*u +1052 317 m +1051 306 l +1135 306 l +1133.239 309.561 1132.478 312 1133 316 c +1126.471 317.490 1123 311.750 1117 312.502 c +1113.762 312.910 1112.182 316.296 1108.896 316.852 c +1102.898 317.867 1096 317 1090 317 c +1052 317 l +f +*U +0.000 0.451 0.329 0.314 k +*u +1112.333 316.333 m +1112.278 316.278 1112.222 315.222 1112.667 315.667 c +1112.722 315.723 1112.777 316.778 1112.333 316.333 c +f +*U +0.000 0.235 0.176 0.110 k +*u +1124 317 m +1125 316 l +1124 317 l +f +*U +0.000 0.259 0.176 0.353 k +*u +1133 317 m +1134 316 l +1133 317 l +f +*U +0.000 0.380 0.247 0.129 k +*u +1203 317 m +1204 316 l +1203 317 l +f +*U +0.000 0.882 0.647 0.118 k +*u +1206 317 m +1207.364 315.181 1207.492 315.969 1207 314 c +1212 313 l +1210.952 311 1210.488 310 1210 308 c +1217.426 305 1226 307.997 1234 308 c +1252.180 308 1270 308.419 1288 306 c +1285.880 308.630 1284.237 310.917 1281 312 c +1281.562 313.801 1281.824 315 1282 317 c +1206 317 l +f +*U +0.000 0.310 0.224 0.200 k +*u +1295 317 m +1296 316 l +1295 317 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1457 314 m +1459.837 313.325 1461.522 314.495 1464 316 c +1461.311 316.405 1459.444 315.225 1457 314 c +f +*U +0.000 0.000 0.000 0.616 k +*u +1464 317 m +1465 316 l +1464 317 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1489.667 316.667 m +1489.222 316.222 1490.278 316.278 1490.333 316.333 c +1490.778 316.778 1489.722 316.722 1489.667 316.667 c +f +*U +0.000 0.000 0.000 0.118 k +*u +1959 317 m +1959.899 313.173 1961.819 310.249 1964 307 c +1964.572 310.923 1961.728 314.354 1959 317 c +f +*U +0.000 0.000 0.000 0.608 k +*u +894 316 m +895 315 l +894 316 l +f +*U +0.000 0.000 0.000 0.075 k +*u +895 316 m +895.547 314 896 312.745 897 311 c +897.710 313.531 897 314.516 895 316 c +f +*U +0.000 0.278 0.204 0.031 k +*u +1123 316 m +1124 315 l +1123 316 l +f +*U +0.000 0.569 0.404 0.431 k +*u +1133.333 315.333 m +1133.278 315.278 1133.222 314.222 1133.667 314.667 c +1133.722 314.722 1133.777 315.778 1133.333 315.333 c +f +*U +0.000 0.165 0.125 0.169 k +*u +1134 316 m +1135 315 l +1134 316 l +f +*U +0.000 0.275 0.200 0.145 k +*u +1294 316 m +1295 315 l +1294 316 l +f +*U +0.000 0.675 0.494 0.325 k +*u +1295 316 m +1294 314 l +1296 314 l +1296 315.853 1296.300 315.350 1295 316 c +f +*U +0.000 0.306 0.353 0.027 k +*u +1398.333 315.333 m +1398.278 315.278 1398.222 314.222 1398.667 314.667 c +1398.722 314.722 1398.777 315.778 1398.333 315.333 c +f +*U +0.000 0.000 0.000 0.106 k +*u +1481 312 m +1484.534 311.424 1486.762 313.397 1489 316 c +1486 314.955 1483.618 313.586 1481 312 c +f +*U +0.000 0.000 0.000 0.788 k +*u +1927 316 m +1928 315 l +1927 316 l +f +*U +0.000 0.000 0.000 0.859 k +*u +539 315 m +539 255 l +540.875 259.469 540 265.191 540 270 c +540 299 l +540 304 540.981 310.280 539 315 c +f +*U +0.000 0.000 0.000 0.125 k +*u +858 315 m +857 313.521 857 313.797 857 312 c +858.289 313.443 858.401 313.234 858 315 c +f +*U +0.000 0.459 0.424 0.192 k +*u +1050 315 m +1050 310 l +1050.830 312 1050.830 312.970 1050 315 c +f +*U +0.000 0.412 0.314 0.125 k +*u +1113 315 m +1114 314 l +1113 315 l +f +*U +0.000 0.286 0.208 0.231 k +*u +1121 315 m +1122 314 l +1121 315 l +f +*U +0.000 0.290 0.212 0.141 k +*u +1205 315 m +1206 314 l +1205 315 l +f +*U +0.000 0.396 0.286 0.176 k +*u +1283 315 m +1284 314 l +1283 315 l +f +*U +0.000 0.796 0.769 0.141 k +*u +1397 315 m +1397 306 l +1398.256 308.994 1398.256 312 1397 315 c +f +*U +0.000 0.000 0.000 0.816 k +*u +1461 315 m +1462 314 l +1461 315 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1485 315 m +1486 314 l +1485 315 l +f +1979 315 m +1980 314 l +1979 315 l +f +*U +0.000 0.000 0.000 0.710 k +*u +571 314 m +572 313 l +571 314 l +f +*U +0.000 0.000 0.000 0.094 k +*u +837 314 m +837 311 l +838.195 312.223 838.316 312.420 839 314 c +837 314 l +f +*U +0.000 0.000 0.000 0.816 k +*u +839 314 m +840 313 l +839 314 l +f +*U +0.000 0.533 0.424 0.467 k +*u +1113 314 m +1114.543 312.733 1115 312.511 1117 312 c +1115.542 313 1114.752 313.436 1113 314 c +f +*U +0.000 0.196 0.169 0.216 k +*u +1119 314 m +1120 313 l +1119 314 l +f +*U +0.000 0.427 0.376 0.573 k +*u +1132 314 m +1132 310 l +1132.710 311.759 1132.710 312.241 1132 314 c +f +*U +0.000 0.376 0.282 0.247 k +*u +1133 314 m +1134 313 l +1133 314 l +f +*U +0.000 0.188 0.165 0.110 k +*u +1206 314 m +1207 313 l +1206 314 l +f +*U +0.000 0.290 0.278 0.710 k +*u +1207 314 m +1208 313 l +1207 314 l +f +*U +0.000 0.710 0.490 0.290 k +*u +1208 314 m +1209 309 l +1210.274 310.341 1211 311.403 1212 313 c +1208 314 l +f +*U +0.000 0.467 0.373 0.533 k +*u +1294 314 m +1294 311 l +1294.696 312.554 1294.696 312.446 1294 314 c +f +*U +0.000 0.420 0.451 0.094 k +*u +1398 314 m +1398 309 l +1398.830 311 1398.830 311.970 1398 314 c +f +*U +0.000 0.000 0.000 0.733 k +*u +1943 314 m +1944 313 l +1943 314 l +f +*U +0.000 0.000 0.000 0.149 k +*u +1981 314 m +1982 310 l +1982.553 312 1982.303 312.332 1981 314 c +f +*U +0.000 0.000 0.000 0.792 k +*u +547 313 m +548 312 l +547 313 l +f +*U +0.000 0.000 0.000 0.137 k +*u +573 313 m +574.223 311.805 574.420 311.684 576 311 c +574.777 312.195 574.580 312.316 573 313 c +f +*U +0.000 0.000 0.000 0.663 k +*u +856 313 m +857 312 l +856 313 l +f +*U +0.000 0.000 0.000 0.620 k +*u +877 313 m +878 312 l +877 313 l +f +*U +0.000 0.341 0.271 0.118 k +*u +1117 313 m +1118 312 l +1117 313 l +f +*U +0.000 0.710 0.553 0.290 k +*u +1118.667 312.667 m +1118.222 312.222 1119.278 312.278 1119.333 312.333 c +1119.778 312.778 1118.722 312.722 1118.667 312.667 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1924 313 m +1923 311.255 1922.547 309.875 1922 308 c +1923.693 309.782 1924.375 310.581 1924 313 c +f +*U +0.000 0.000 0.000 0.631 k +*u +1925 313 m +1926 312 l +1925 313 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1929 313 m +1928.455 311.365 1928.635 311.545 1927 311 c +1928 304 l +1924 306 l +1923.274 303.821 1923.561 304.220 1922 305 c +1919.825 299.325 1918.419 294 1920 288 c +1915.576 288.690 1911.467 288.267 1912 283 c +1910 281 1910.814 278.697 1911 276 c +1916 280 l +1916.251 278.548 1916.315 278.248 1917 277 c +1919.259 277 1921.290 276.624 1923 278 c +1924.517 277 1925.339 276.613 1927 276 c +1928.276 277.915 1928.277 277 1927 279 c +1936.521 281.267 1947.251 280 1957 280 c +1966.749 280 1977.479 281.267 1987 279 c +1985.907 277 1985.838 276.265 1986 274 c +1987.819 275.365 1987 275.492 1989 275 c +1990 278 l +1992 273 l +1989.567 271.538 1988.823 270.712 1988 268 c +1992.365 267.405 1994.627 261.447 1997 258 c +1998.417 258.472 1998.814 258.814 2000 260 c +1999 257 l +2003.462 255.684 2008.227 255.219 2008 261 c +2008.957 259.483 2009.387 258.662 2010 257 c +2011.533 260 2010.509 262 2009 265 c +2006.539 265 2004.400 265.434 2002 266 c +2003.478 266.986 2003.204 267 2005 267 c +2003.352 267.924 2001.825 268.449 2000 269 c +2002 276 l +2000.488 277.653 1999.819 278.894 1999 281 c +1996 280 l +1994 283.445 1992.720 286 1992 290 c +1988.786 288.587 1986.946 289.231 1984 291 c +1983 288 l +1982 292 l +1981.317 290.494 1981.174 289.685 1981 288 c +1927 287 l +1927.931 292.260 1928.728 296.660 1929 302 c +1934.463 301.221 1935.407 305 1938 309 c +1935 313 l +1933 312.590 1932.298 312.465 1931 311 c +1929.977 312.534 1930.195 312.402 1929 313 c +f +*U +0.000 0.000 0.000 0.125 k +*u +1943 313 m +1942 311.255 1941.547 309.875 1941 308 c +1942.693 309.782 1943.375 310.581 1943 313 c +f +*U +0.000 0.000 0.000 0.627 k +*u +364 312 m +365 311 l +364 312 l +f +*U +0.000 0.000 0.000 0.259 k +*u +365 312 m +366 311 l +365 312 l +f +*U +0.000 0.000 0.000 0.106 k +*u +547 312 m +548.402 309.726 549.515 309 552 308 c +550.394 309.914 549.217 310.837 547 312 c +f +*U +0.000 0.000 0.000 0.600 k +*u +548 312 m +549 311 l +548 312 l +f +*U +0.000 0.000 0.000 0.624 k +*u +805 312 m +806 311 l +805 312 l +f +*U +0.000 0.000 0.000 0.137 k +*u +856 312 m +855 310.521 855 310.797 855 309 c +856.289 310.443 856.401 310.234 856 312 c +f +*U +0.000 0.522 0.341 0.000 k +*u +1208 312 m +1209 311 l +1208 312 l +f +*U +0.000 0.333 0.310 0.231 k +*u +1285 312 m +1286 311 l +1285 312 l +f +*U +0.000 0.612 0.420 0.373 k +*u +1295 312 m +1295 309 l +1295.696 310.554 1295.696 310.446 1295 312 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1453 312 m +1454 310 l +1455.635 310.545 1455.455 310.365 1456 312 c +1453 312 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1456 312 m +1457 311 l +1456 312 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1480 312 m +1481 311 l +1480 312 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1981 312 m +1982 311 l +1981 312 l +f +*U +0.000 0.000 0.000 0.537 k +*u +357 311 m +358 310 l +357 311 l +f +*U +0.000 0.000 0.000 0.129 k +*u +347 309 m +352.305 306.836 359.395 309.558 365 310 c +359.672 312.215 352.581 309.706 347 309 c +f +*U +0.000 0.000 0.000 0.671 k +*u +575 311 m +576 310 l +575 311 l +f +*U +0.000 0.000 0.000 0.098 k +*u +576 311 m +579.358 306.622 583.915 303 589 301 c +585.678 305.500 581 308.833 576 311 c +f +*U +0.000 0.000 0.000 0.545 k +*u +798 311 m +799 310 l +798 311 l +f +*U +0.000 0.000 0.000 0.141 k +*u +799 311 m +801.332 310 803.457 310 806 310 c +803.668 310.985 801.543 310.981 799 311 c +f +*U +0.000 0.000 0.000 0.110 k +*u +835 311 m +833 305 l +835.181 306.896 836 308.259 837 311 c +835 311 l +f +*U +0.000 0.000 0.000 0.620 k +*u +837 311 m +838 310 l +837 311 l +f +*U +0.000 0.000 0.000 0.078 k +*u +878 311 m +878.833 306.696 880.634 303.791 884 301 c +882.616 304.781 880.761 308 878 311 c +f +*U +0.000 0.000 0.000 0.224 k +*u +898 311 m +899 310 l +898 311 l +f +*U +0.000 0.251 0.208 0.102 k +*u +1133 311 m +1134 310 l +1133 311 l +f +*U +0.000 0.533 0.408 0.463 k +*u +1285 311 m +1285 308 l +1285.696 309.554 1285.696 309.446 1285 311 c +f +*U +0.000 0.329 0.239 0.224 k +*u +1294 311 m +1295 310 l +1294 311 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1449 309 m +1451.509 308.434 1452.220 309 1454 311 c +1449 309 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1476 309 m +1478 308.590 1478.962 309 1481 310 c +1478.860 310.410 1478 309.968 1476 309 c +f +*U +0.000 0.000 0.000 0.812 k +*u +1924 311 m +1925 310 l +1924 311 l +f +*U +0.000 0.000 0.000 0.878 k +*u +348.667 309.667 m +348.222 309.222 349.278 309.278 349.333 309.333 c +349.778 309.778 348.722 309.722 348.667 309.667 c +f +*U +0.000 0.000 0.000 0.569 k +*u +350 310 m +351 309 l +350 310 l +f +*U +0.000 0.000 0.000 0.643 k +*u +790.667 309.667 m +790.223 309.223 791.278 309.278 791.333 309.333 c +791.778 309.778 790.722 309.722 790.667 309.667 c +f +*U +0.000 0.000 0.000 0.188 k +*u +794 310 m +795.769 309.221 797 309 799 309 c +797.231 309.779 795.964 309.912 794 310 c +f +*U +0.000 0.000 0.000 0.749 k +*u +879 310 m +880 309 l +879 310 l +f +*U +0.000 0.000 0.000 0.129 k +*u +898 310 m +898.545 308.365 898.365 308.545 900 308 c +900 310 l +898 310 l +f +*U +0.000 0.471 0.400 0.412 k +*u +1050 310 m +1050 305 l +1050.830 307 1050.830 307.970 1050 310 c +f +*U +0.000 0.639 0.463 0.341 k +*u +1133 310 m +1133.684 308.420 1133.805 308.223 1135 307 c +1134.316 308.580 1134.195 308.777 1133 310 c +f +*U +0.000 0.294 0.243 0.118 k +*u +1134 310 m +1135 309 l +1134 310 l +f +*U +0.000 0.306 0.239 0.694 k +*u +1208 310 m +1209 309 l +1208 310 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1453 310 m +1454 309 l +1453 310 l +f +*U +0.000 0.000 0.000 0.000 k +*u +1818 310 m +1818 306 l +1865 306 l +1861.301 307.552 1856.983 307 1853 307 c +1832 307 l +1826.819 307 1821.973 306.207 1818 310 c +f +*U +0.000 0.000 0.000 0.090 k +*u +1983 310 m +1985 305 l +1985.710 307.530 1985 308.516 1983 310 c +f +*U +0.000 0.000 0.000 0.169 k +*u +171 309 m +174.699 307.448 179 308 183 308 c +203 308 l +206.567 308 211.649 308.869 214.852 306.972 c +219.877 303.997 219 294 212.956 293 c +199 290.846 183 293 169 293 c +172.699 291.448 177 292 181 292 c +204 292 l +207.652 292 213.326 290.952 216.682 292.603 c +220 294.282 220 304.700 217.972 307.397 c +215.739 310.216 209 309 206 309 c +171 309 l +f +*U +0.000 0.000 0.000 0.678 k +*u +552 309 m +553 308 l +552 309 l +f +*U +0.000 0.133 0.149 0.169 k +*u +1135 309 m +1136 308 l +1135 309 l +f +*U +0.000 0.294 0.239 0.051 k +*u +1286 309 m +1287 308 l +1286 309 l +f +*U +0.000 0.290 0.196 0.357 k +*u +1295 309 m +1296 308 l +1295 309 l +f +*U +0.000 0.478 0.478 0.522 k +*u +1296 309 m +1297 308 l +1296 309 l +f +*U +0.000 1.000 0.725 0.000 k +*u +1297 309 m +1298.223 307.805 1298.420 307.684 1300 307 c +1298.777 308.195 1298.580 308.316 1297 309 c +f +*U +0.000 0.463 0.361 0.443 k +*u +1398 309 m +1398 306 l +1398.696 307.554 1398.696 307.446 1398 309 c +f +*U +0.000 0.000 0.000 0.710 k +*u +1475 309 m +1476 308 l +1475 309 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1940 309 m +1941 308 l +1940 309 l +f +*U +0.000 0.000 0.000 0.000 k +*u +169 308 m +173.720 306 179.920 307 185 307 c +216 307 l +211.280 308.981 205 308 200 308 c +169 308 l +f +*U +0.000 0.000 0.000 0.859 k +*u +402 308 m +408.436 305.299 418 307 425 307 c +477 307 l +470.564 309.701 460.951 308 454 308 c +402 308 l +f +*U +0.000 0.000 0.000 0.149 k +*u +853 308 m +853 306 l +854.635 306.545 854.455 306.365 855 308 c +853 308 l +f +*U +0.000 0.000 0.000 0.765 k +*u +899 308 m +900 307 l +899 308 l +f +*U +0.000 0.000 0.000 0.122 k +*u +900 308 m +900.810 305.778 901.739 304 903 302 c +903.410 304.888 902 306 900 308 c +f +*U +0.000 0.537 0.416 0.463 k +*u +1135 308 m +1132.692 306.241 1130.908 306 1128 306 c +1130.278 304.900 1136.531 303.938 1135 308 c +f +*U +0.000 0.376 0.282 0.624 k +*u +1211 308 m +1212 307 l +1211 308 l +f +*U +0.000 0.882 0.592 0.118 k +*u +1216 307 m +1222.194 304.401 1231.314 306 1238 306 c +1285 306 l +1278.650 309.376 1269.998 308 1263 308 c +1247.304 308 1231.625 307 1216 307 c +f +*U +0.000 0.471 0.345 0.212 k +*u +1286 308 m +1287 307 l +1286 308 l +f +*U +0.000 0.392 0.322 0.267 k +*u +1296 308 m +1297 307 l +1296 308 l +f +*U +0.000 0.361 0.271 0.482 k +*u +1297.333 307.333 m +1297.278 307.278 1297.222 306.222 1297.667 306.667 c +1297.722 306.722 1297.778 307.778 1297.333 307.333 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1466 303 m +1470 302.321 1473.438 305 1476 308 c +1472.360 306.848 1469.252 304.988 1466 303 c +f +*U +0.000 0.000 0.000 0.173 k +*u +1819 308 m +1823.720 306 1829.920 307 1835 307 c +1845.467 307 1856.647 305.862 1867 307 c +1862.280 308.981 1856 308 1851 308 c +1819 308 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1922 308 m +1923 307 l +1922 308 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1940 308 m +1939 306.255 1938.547 304.875 1938 303 c +1939.693 304.782 1940.375 305.581 1940 308 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1965 308 m +1966 307 l +1965 308 l +f +*U +0.000 0.000 0.000 0.098 k +*u +553 307 m +554.223 305.805 554.420 305.684 556 305 c +554.777 306.195 554.580 306.316 553 307 c +f +*U +0.000 0.000 0.000 0.812 k +*u +881 307 m +882 306 l +881 307 l +f +*U +0.000 0.027 0.016 0.541 k +*u +1136 307 m +1137 306 l +1136 307 l +f +*U +0.000 0.302 0.208 0.086 k +*u +1211 307 m +1212 306 l +1211 307 l +f +*U +0.000 0.475 0.380 0.525 k +*u +1212 307 m +1214.718 303.890 1220 305 1224 305 c +1220.304 306.551 1215.951 306 1212 307 c +f +*U +0.000 0.518 0.404 0.482 k +*u +1280 306 m +1283.698 304.448 1288 305 1292 305 c +1288.552 307.402 1284 306 1280 306 c +f +*U +0.000 0.349 0.224 0.188 k +*u +1291 307 m +1292 306 l +1291 307 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1448 307 m +1449 306 l +1448 307 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1920.333 306.333 m +1920.278 306.278 1920.222 305.222 1920.667 305.667 c +1920.722 305.722 1920.778 306.778 1920.333 306.333 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1965 307 m +1965.526 304.457 1965.878 303.465 1968 302 c +1967.251 304.254 1966.656 305.313 1965 307 c +f +*U +0.000 0.000 0.000 0.000 k +*u +217 306 m +217 295 l +218.431 298.410 218.431 302.590 217 306 c +f +*U +0.000 0.000 0.000 0.765 k +*u +556 306 m +557 305 l +556 306 l +f +*U +0.000 0.000 0.000 0.816 k +*u +834 306 m +835 305 l +834 306 l +f +*U +0.000 0.000 0.000 0.145 k +*u +852.333 305.333 m +852.278 305.278 852.222 304.222 852.667 304.667 c +852.722 304.722 852.778 305.778 852.333 305.333 c +f +*U +0.000 0.392 0.298 0.608 k +*u +1051 306 m +1057.678 303.198 1067.784 305 1075 305 c +1128 305 l +1121.322 307.802 1111.216 306 1104 306 c +1051 306 l +f +*U +0.000 0.047 0.035 0.816 k +*u +1136 306 m +1137 305 l +1136 306 l +f +*U +0.000 0.392 0.298 0.608 k +*u +1224 306 m +1229.217 303.811 1236.381 305 1242 305 c +1280 305 l +1274.784 307.189 1267.619 306 1262 306 c +1224 306 l +f +*U +0.000 0.235 0.149 0.357 k +*u +1292 306 m +1293 305 l +1292 306 l +f +*U +0.000 0.333 0.227 0.435 k +*u +1298 306 m +1299 305 l +1298 306 l +f +*U +0.000 0.392 0.298 0.608 k +*u +1299 306 m +1307 302.593 1320.203 305 1329 305 c +1398 305 l +1389.882 308.407 1376.797 306 1368 306 c +1299 306 l +f +*U +0.000 0.247 0.216 0.349 k +*u +1398 306 m +1399 305 l +1398 306 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1470 306 m +1471 305 l +1470 306 l +f +*U +0.000 0.000 0.000 0.627 k +*u +1760 306 m +1761 305 l +1760 306 l +f +*U +0.000 0.000 0.000 0.851 k +*u +1865 306 m +1865 293 l +1866.591 296.791 1866.591 302.209 1865 306 c +f +*U +0.000 0.000 0.000 0.129 k +*u +1866 306 m +1866 292 l +1867.667 295.972 1867.667 302 1866 306 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1918 304 m +1921 304 l +1920 306 l +1918.365 305.455 1918.545 305.635 1918 304 c +f +*U +0.000 0.000 0.000 0.800 k +*u +1938 306 m +1939 305 l +1938 306 l +f +*U +0.000 0.000 0.000 0.718 k +*u +851 305 m +852 304 l +851 305 l +f +*U +0.000 0.000 0.000 0.690 k +*u +882 305 m +883 304 l +882 305 l +f +*U +0.000 0.000 0.000 0.682 k +*u +901 305 m +902 304 l +901 305 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1468 305 m +1469 304 l +1468 305 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1986 305 m +1987 304 l +1986 305 l +f +*U +0.000 0.875 0.624 0.125 k +*u +0 304 m +3.415 275.239 0.989 244.987 1 216 c +1 207 1.178 189 10 184 c +9 187 l +16 187 l +16 192 l +13.603 192 10.582 191.716 8.742 193.603 c +4.524 197.931 8 211.340 8 217 c +8 296 l +25 296 l +25 303 l +16.661 303 8.226 302.473 0 304 c +f +*U +0.000 0.745 0.553 0.137 k +*u +2 304 m +8.928 301 19.503 303 27 303 c +20 305.907 9.497 304 2 304 c +f +*U +0.000 0.529 0.424 0.471 k +*u +27 304 m +27 216 l +29.497 221.951 28 230.580 28 237 c +28 281 l +28 287.951 29.701 297.564 27 304 c +f +*U +0.000 0.000 0.000 0.827 k +*u +584 304 m +585 303 l +584 304 l +f +*U +0.000 0.000 0.000 0.212 k +*u +832 304 m +833 303 l +832 304 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1918 304 m +1917 300 l +1918.434 301.393 1919 302.233 1920 304 c +1918 304 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1937 304 m +1938 303 l +1937 304 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1986 304 m +1987 303 l +1986 304 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1987 304 m +1987.547 302 1988 300.745 1989 299 c +1989.566 301.509 1988.847 302.220 1987 304 c +f +*U +0.000 0.878 0.631 0.122 k +*u +25 303 m +25 296 l +8 296 l +8 217 l +8 211.280 7 205.681 7 200 c +6.995 197.774 6.812 194.596 8.742 193 c +10.581 191.534 13.806 192 16 192 c +16 187 l +9 187 l +14.729 166.871 38 164 56 164 c +53.463 166 51.218 166.670 48 167 c +58.732 170.394 70.870 169 82 169 c +143 169 l +347 169 l +573.316 169 799.773 168 1026 168 c +1023.904 166.957 1022.301 166.397 1020 166 c +1023.746 164.425 1028 164.434 1032 163 c +1026.917 159.292 1028.860 154.570 1034 152 c +1034.482 147.602 1037.710 144.720 1042 144 c +1043.302 137.874 1051.372 127.403 1058 127 c +1060 121 l +1065.645 117.731 1070.265 112.945 1075.455 108.999 c +1084.809 101.890 1094.383 95 1104.385 88.790 c +1134.840 69.853 1172.407 57.574 1208 53.835 c +1230.812 51.439 1255.294 52.482 1278 56.194 c +1287.576 57.760 1297.239 62.310 1307 62 c +1312.651 67 1322.939 65.752 1327 72 c +1332.257 72 1337.333 75 1342 77.400 c +1351.411 82 1360 86.993 1368.950 92.731 c +1372.926 95.325 1375.304 98.590 1380 100 c +1380 104 l +1387 103.403 1392.546 110.925 1397.458 115.326 c +1406 123 1415.699 131.761 1422.624 141 c +1426 145.676 1429.982 150.383 1433 155.286 c +1434.874 157.982 1436 161.339 1439 162.972 c +1441.710 164.417 1445 163.998 1448 164 c +1449.545 169 1453.191 168.990 1458 169 c +1478 169 l +1571 169 l +1827 169 l +1918 169 l +1932.570 169 1948.564 170.879 1962.985 168.856 c +1966.189 168.407 1968.792 166.496 1972 166 c +1971.613 163.910 1971.616 164.289 1974 164 c +1975 149.673 1975 135.396 1975 121 c +1982.528 124.210 1989 130.403 1996 134.640 c +2016 146.761 2035.364 160.180 2055 173 c +2051.417 177.778 2043.203 182.381 2037 186 c +2034 187.663 2030.666 188.867 2028 191 c +2029 192 l +2022.569 194 2017.566 198.699 2012 202.371 c +2005 206.960 1997.472 210.666 1990.434 215 c +1985.255 218.421 1981 222.529 1975 224 c +1975 212.795 1977.422 198.436 1973 188 c +1974.801 186.685 1974.833 186.277 1975 184 c +1973.814 185 1973.396 185.339 1972 186 c +1968.765 183.562 1963.922 184 1960 184 c +1933 184 l +1828 184 l +1560 184 l +1472 184 l +1457.950 184 1442.908 185.529 1429 184 c +1424.554 188.593 1420.781 180.451 1418.570 177.454 c +1414.841 172.400 1410.443 167.829 1406.669 162.831 c +1403.309 158.382 1400.831 152.978 1397 149 c +1397.661 147.603 1397.964 147.187 1399 146 c +1397 145.930 1397 145.646 1396 147 c +1388.668 143.421 1383.819 135.383 1378 130 c +1379.943 129.378 1380.949 129.564 1383 130 c +1379.505 128.242 1376 128.553 1374 125 c +1369.507 125 1366.900 121.701 1363.485 119 c +1359.730 116 1355.532 113.778 1351.579 111 c +1336.876 101.279 1321.828 93.423 1304.999 87.715 c +1298.627 85.554 1292.888 81.909 1286 83 c +1279.646 78 1268.692 78.522 1261 77.421 c +1240.338 74.461 1219.358 75.788 1199 79.625 c +1192.383 80.872 1185.525 80.815 1179 82.795 c +1170.709 85.311 1162 87.656 1154 91 c +1149.521 92.958 1146 96.249 1141 96 c +1137.817 100.206 1130 102.419 1125.428 105 c +1116.708 109.812 1108.985 116 1100.910 121.890 c +1098 123.857 1090.870 130.413 1088 128 c +1077.695 141 1064.620 151.726 1054.411 164.985 c +1049.525 171.332 1045.859 180.996 1037.780 184.219 c +1032.550 186.306 1022.720 184 1017 184 c +967 184 l +792 184 l +289 184 l +126 184 l +74 184 l +62.741 184 51 183.376 40 185 c +40.986 186.479 41 186.203 41 188 c +37 188 l +35.781 191.439 33.303 192.655 30 194 c +30.636 201.291 27 208.512 27 216 c +27 303 l +25 303 l +f +*U +0.000 0.000 0.000 0.220 k +*u +559 303 m +560 302 l +559 303 l +f +*U +0.000 0.000 0.000 0.800 k +*u +560 303 m +561 302 l +560 303 l +f +*U +0.000 0.000 0.000 0.090 k +*u +831 303 m +830 301.521 830 301.797 830 300 c +831.289 301.443 831.401 301.234 831 303 c +f +*U +0.000 0.000 0.000 0.733 k +*u +832 303 m +833 302 l +832 303 l +f +*U +0.000 0.000 0.000 0.133 k +*u +850 303 m +848.817 300.672 847.777 298.489 847 296 c +849.256 298 850.728 299.867 850 303 c +f +*U +0.000 0.000 0.000 0.624 k +*u +1465 303 m +1466 302 l +1465 303 l +f +*U +0.000 0.000 0.000 0.153 k +*u +1701 302 m +1706.217 299.811 1713.381 301 1719 301 c +1731.812 301 1746.506 299 1759 302 c +1753.902 303.568 1746.469 302 1741 302 c +1701 302 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1919 303 m +1920 302 l +1919 303 l +f +*U +0.000 0.000 0.000 0.275 k +*u +1937 303 m +1938 302 l +1937 303 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1968 303 m +1969 302 l +1968 303 l +f +*U +0.000 0.000 0.000 0.820 k +*u +849 302 m +850 301 l +849 302 l +f +*U +0.000 0.000 0.000 0.804 k +*u +884 302 m +885 301 l +884 302 l +f +*U +0.000 0.000 0.000 0.608 k +*u +903 302 m +904 301 l +903 302 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1463 302 m +1464 301 l +1463 302 l +f +*U +0.000 0.000 0.000 0.118 k +*u +1460 300 m +1462.187 297.968 1464 296.906 1467 296 c +1465.771 297.870 1465 298.224 1463 299 c +1466 301 l +1463.726 301.409 1462.219 300.788 1460 300 c +f +*U +0.000 0.000 0.000 0.596 k +*u +1757 302 m +1758 301 l +1757 302 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1936 302 m +1934.216 298.641 1932.268 295.810 1932 292 c +1934.509 294.996 1936.347 298.460 1938 302 c +1936 302 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1968 302 m +1968.683 300.420 1968.805 300.222 1970 299 c +1969.316 300.580 1969.195 300.777 1968 302 c +f +*U +0.000 0.631 0.420 0.365 k +*u +0 301 m +0 208 l +2.802 214.678 1 224.784 1 232 c +1 279 l +1 285.686 2.599 294.806 0 301 c +f +*U +0.000 0.000 0.000 0.106 k +*u +561 301 m +562.450 299.392 563 298.936 565 298 c +563.550 299.608 562.949 300 561 301 c +f +*U +0.000 0.000 0.000 0.796 k +*u +588 301 m +589 300 l +588 301 l +f +*U +0.000 0.000 0.000 0.133 k +*u +589 301 m +590.450 299.392 591 298.936 593 298 c +591.550 299.608 590.949 300 589 301 c +f +*U +0.000 0.000 0.000 0.106 k +*u +884 301 m +884.651 298.566 885 297.717 887 296 c +886.251 298.254 885.656 299.314 884 301 c +f +*U +0.000 0.000 0.000 0.137 k +*u +905 301 m +906 297 l +906.393 298.924 906 299.360 905 301 c +f +*U +0.000 0.000 0.000 0.843 k +*u +1698 301 m +1703.217 298.811 1710.381 300 1716 300 c +1753 300 l +1747.783 302.189 1740.619 301 1735 301 c +1698 301 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1780 301 m +1781 300 l +1780 301 l +f +*U +0.000 0.000 0.000 0.596 k +*u +830 300 m +831 299 l +830 300 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1916 300 m +1915 298.255 1914.547 296.875 1914 295 c +1915.693 296.782 1916.375 297.581 1916 300 c +f +*U +0.000 0.000 0.000 0.659 k +*u +1917 300 m +1918 299 l +1917 300 l +f +*U +0.000 0.000 0.000 0.671 k +*u +565 299 m +566 298 l +565 299 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1461 299 m +1462 298 l +1461 299 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1970.333 298.333 m +1970.278 298.278 1970.222 297.222 1970.667 297.667 c +1970.722 297.722 1970.778 298.778 1970.333 298.333 c +f +*U +0.000 0.000 0.000 0.729 k +*u +1989 299 m +1990 298 l +1989 299 l +f +*U +0.000 0.000 0.000 0.243 k +*u +1990 299 m +1991 298 l +1990 299 l +f +*U +0.000 0.000 0.000 0.129 k +*u +565 298 m +565.545 296.365 565.365 296.545 567 296 c +567 298 l +565 298 l +f +*U +0.000 0.000 0.000 0.643 k +*u +592 298 m +593 297 l +592 298 l +f +*U +0.000 0.000 0.000 0.322 k +*u +593 298 m +594 297 l +593 298 l +f +*U +0.000 0.000 0.000 0.831 k +*u +829 298 m +830 297 l +829 298 l +f +*U +0.000 0.000 0.000 0.596 k +*u +1971 298 m +1972 297 l +1971 298 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1990 298 m +1990.545 296.365 1990.365 296.545 1992 296 c +1992 298 l +1990 298 l +f +*U +0.000 0.000 0.000 0.812 k +*u +593 297 m +594 296 l +593 297 l +f +*U +0.000 0.000 0.000 0.090 k +*u +594 297 m +595.223 295.805 595.420 295.684 597 295 c +596 296.783 596 296.594 594 297 c +f +*U +0.000 0.000 0.000 0.173 k +*u +827.333 296.333 m +827.278 296.278 827.222 295.222 827.667 295.667 c +827.722 295.722 827.778 296.778 827.333 296.333 c +f +*U +0.000 0.000 0.000 0.776 k +*u +846 297 m +847 296 l +846 297 l +f +*U +0.000 0.000 0.000 0.690 k +*u +887 297 m +888 296 l +887 297 l +f +*U +0.000 0.000 0.000 0.114 k +*u +907 297 m +907.810 294.778 908.739 293 910 291 c +910.410 293.888 909 295 907 297 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1779 297 m +1780 296 l +1779 297 l +f +*U +0.000 0.000 0.000 0.063 k +*u +1971 297 m +1973 291 l +1973.744 293.735 1972.915 294.968 1971 297 c +f +*U +0.000 0.000 0.000 0.725 k +*u +569 296 m +570 295 l +569 296 l +f +*U +0.000 0.000 0.000 0.129 k +*u +846 296 m +843 290 l +891 290 l +890.190 292.222 889.261 293.990 888 296 c +887.590 293.860 888 293 889 291 c +845 291 l +846 293 846.577 293.769 846 296 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1466 296 m +1467 295 l +1466 296 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1467.667 295.667 m +1467.222 295.222 1468.278 295.278 1468.333 295.333 c +1468.778 295.778 1467.722 295.722 1467.667 295.667 c +f +*U +0.000 0.000 0.000 0.149 k +*u +1779.333 295.333 m +1779.278 295.278 1779.222 294.222 1779.667 294.667 c +1779.722 294.722 1779.778 295.778 1779.333 295.333 c +f +*U +0.000 0.000 0.000 0.773 k +*u +1932 296 m +1933 295 l +1932 296 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1992 296 m +1993 293 1994.415 290.618 1996 288 c +1996.576 291.534 1994.603 293.762 1992 296 c +f +*U +0.000 0.000 0.000 0.235 k +*u +569 295 m +570 294 l +569 295 l +f +*U +0.000 0.000 0.000 0.749 k +*u +596 295 m +597 294 l +596 295 l +f +*U +0.000 0.000 0.000 0.133 k +*u +597 295 m +599.319 292 601.622 290.432 605 289 c +602.701 291.971 600.505 293.641 597 295 c +f +*U +0.000 0.000 0.000 0.102 k +*u +826 295 m +825 293.521 825 293.797 825 292 c +826.289 293.443 826.401 293.234 826 295 c +f +*U +0.000 0.000 0.000 0.765 k +*u +827 295 m +828 294 l +827 295 l +f +*U +0.000 0.278 0.173 0.082 k +*u +1051 295 m +1058.399 291.895 1069.993 294 1078 294 c +1138 294 l +1130.600 297 1119 295 1111 295 c +1051 295 l +f +*U +0.000 0.263 0.196 0.192 k +*u +1138 295 m +1139.248 294.315 1139.548 294.251 1141 294 c +1139.752 294.685 1139.451 294.749 1138 295 c +f +*U +0.000 0.278 0.173 0.082 k +*u +1213 293 m +1221.624 295 1231.174 294 1240 294 c +1287 294 l +1281.784 296.189 1274.619 295 1269 295 c +1231 295 l +1226 295 1216.407 296.899 1213 293 c +f +*U +0.000 0.271 0.243 0.180 k +*u +1296 295 m +1297.248 294.315 1297.548 294.251 1299 294 c +1297.751 294.685 1297.452 294.749 1296 295 c +f +*U +0.000 0.267 0.196 0.063 k +*u +1299 295 m +1302 293.673 1305.586 294 1309 294 c +1305.837 295.327 1302.415 295.000 1299 295 c +f +*U +0.000 0.278 0.227 0.157 k +*u +1313 295 m +1314.248 294.315 1314.548 294.251 1316 294 c +1314.752 294.685 1314.451 294.749 1313 295 c +f +*U +0.000 0.353 0.286 0.043 k +*u +1316 295 m +1317.506 294.317 1318.315 294.174 1320 294 c +1318.494 294.683 1317.685 294.826 1316 295 c +f +*U +0.000 0.278 0.173 0.082 k +*u +1320 295 m +1326.919 292 1337.520 294 1345 294 c +1399 294 l +1392 296.903 1381.480 295 1374 295 c +1320 295 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1468 295 m +1469 294 l +1468 295 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1469 295 m +1470.223 293.805 1470.420 293.684 1472 293 c +1470.777 294.195 1470.580 294.316 1469 295 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1778 295 m +1779 294 l +1778 295 l +f +*U +0.000 0.000 0.000 0.090 k +*u +1913 295 m +1911.952 293 1911.487 292 1911 290 c +1912.693 291.782 1913.375 292.581 1913 295 c +f +*U +0.000 0.000 0.000 0.796 k +*u +1914 295 m +1915 294 l +1914 295 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1973 295 m +1974 294 l +1973 295 l +f +*U +0.000 0.000 0.000 0.843 k +*u +169 294 m +173.720 292 179.920 293 185 293 c +217 293 l +212.280 294.981 206 294 201 294 c +169 294 l +f +*U +0.000 0.000 0.000 0.824 k +*u +889 294 m +890 293 l +889 294 l +f +*U +0.000 0.000 0.000 0.792 k +*u +908 294 m +909 293 l +908 294 l +f +*U +0.000 0.506 0.506 0.494 k +*u +1050.333 293.333 m +1050.278 293.278 1050.222 292.222 1050.667 292.667 c +1050.722 292.722 1050.778 293.778 1050.333 293.333 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1051 294 m +1055 291 l +1062 294.980 1073 293 1081 293 c +1140 293 l +1140 289 l +1140.779 290.769 1140.912 292 1141 294 c +1051 294 l +f +*U +0.000 0.522 0.345 0.471 k +*u +1214.333 293.333 m +1214.278 293.278 1214.222 292.222 1214.667 292.667 c +1214.722 292.722 1214.778 293.778 1214.333 293.333 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1215 294 m +1221.194 291.401 1230.314 293 1237 293 c +1254.524 293 1273.751 295.202 1291 292 c +1285.726 295.996 1275.423 294 1269 294 c +1215 294 l +f +*U +0.149 0.000 0.008 0.133 k +*u +1295.333 293.333 m +1295.278 293.278 1295.222 292.222 1295.667 292.667 c +1295.722 292.723 1295.777 293.778 1295.333 293.333 c +f +*U +0.000 0.702 0.557 0.298 k +*u +1296 294 m +1296 289 l +1296.683 290.506 1296.826 291.315 1297 293 c +1305 293 l +1302 294.213 1299 293.998 1296 294 c +f +*U +0.000 0.882 0.624 0.118 k +*u +1297 293 m +1297 289 l +1284.958 293.668 1273.859 293 1261 293 c +1215 293 l +1216 287 l +1216.685 288.248 1216.749 288.549 1217 290 c +1224 290 l +1221.894 289.356 1220.205 289 1218 289 c +1218 283 l +1250.935 281.586 1284 282 1317 282 c +1315.600 285 1314 287.825 1313 291 c +1310.566 291.651 1309.717 292 1308 294 c +1304.305 293.533 1300.735 293 1297 293 c +f +*U +0.000 0.635 0.463 0.365 k +*u +1308 294 m +1308.899 291.876 1308.876 291.899 1311 291 c +1309.897 292.457 1309.457 292.897 1308 294 c +f +*U +0.000 0.392 0.310 0.580 k +*u +1313 294 m +1314 293 l +1313 294 l +f +*U +0.000 0.745 0.557 0.255 k +*u +1312 291 m +1313 290 l +1314.596 290.959 1315.659 291.726 1317 293 c +1314.333 293 1313.893 292.911 1312 291 c +f +*U +0.000 0.667 0.663 0.298 k +*u +1316 294 m +1319.448 291.598 1323.896 292.966 1328 293 c +1324.302 294.551 1319.983 294 1316 294 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1328 294 m +1334.194 291.401 1343.314 293 1350 293 c +1398 293 l +1391.806 295.599 1382.686 294 1376 294 c +1328 294 l +f +*U +0.000 0.420 0.424 0.176 k +*u +1398 294 m +1398 290 l +1398.710 291.759 1398.710 292.241 1398 294 c +f +*U +0.000 0.000 0.000 0.055 k +*u +1767 286 m +1772.368 286.838 1777.190 289.221 1780 294 c +1775.951 292.207 1769.735 289.435 1767 286 c +f +*U +0.000 0.000 0.000 0.137 k +*u +402 293 m +408.436 290.299 418 292 425 292 c +475 292 l +475 255 l +476.661 258.959 476 263.740 476 268 c +476 293 l +402 293 l +f +*U +0.000 0.000 0.000 0.635 k +*u +476 293 m +476 255 l +477.441 258.435 477 262.298 477 266 c +477 274 479 285.600 476 293 c +f +*U +0.000 0.000 0.000 0.086 k +*u +572 293 m +573.573 290.338 575 289.228 578 288 c +576.170 290.348 574.637 291.617 572 293 c +f +*U +0.000 0.000 0.000 0.816 k +*u +573 293 m +574 292 l +573 293 l +f +*U +0.000 0.859 0.608 0.137 k +*u +1051 293 m +1052 283 l +1079.394 279.538 1108.379 282 1136 282 c +1136 284 l +1056 284 l +1062.584 285.946 1070 285 1077 285 c +1117 285 l +1123.705 285 1132.831 286.880 1138 282 c +1140 282 l +1140.890 285.870 1140.490 289 1140 293 c +1078 293 l +1072.473 293 1059.796 295.344 1056 291 c +1054.175 292.336 1053.247 292.690 1051 293 c +f +*U +0.000 0.522 0.365 0.122 k +*u +1291 293 m +1292 292 l +1291 293 l +f +*U +0.000 0.267 0.212 0.039 k +*u +1312 293 m +1313 292 l +1312 293 l +f +*U +0.000 0.871 0.624 0.129 k +*u +1319 292 m +1320.249 291.315 1320.548 291.251 1322 291 c +1320.722 288 1319.830 285 1319 282 c +1397 282 l +1397 293 l +1346 293 l +1337.393 293 1327.280 294.448 1319 292 c +f +*U +0.000 0.898 0.851 0.047 k +*u +1397 293 m +1397 290 l +1397.696 291.554 1397.696 291.446 1397 293 c +f +*U +0.000 0.000 0.000 0.098 k +*u +1472 293 m +1473.458 291.919 1474.248 291.564 1476 291 c +1474.457 292.267 1473.952 292.489 1472 293 c +f +*U +0.000 0.000 0.000 0.839 k +*u +1818 293 m +1822.720 291 1828.920 292 1834 292 c +1865 292 l +1860.280 293.981 1854 293 1849 293 c +1818 293 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1865 293 m +1866 292 l +1865 293 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1931 293 m +1929 289 l +1976 289 l +1975 293 l +1974.315 291.752 1974.251 291.452 1974 290 c +1960 291.554 1945 290 1931 290 c +1931.400 291.650 1931.479 291.502 1931 293 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1993 293 m +1994 292 l +1993 293 l +f +*U +0.000 0.000 0.000 0.165 k +*u +344 290 m +348 291 l +345.954 291.751 345.404 291.656 344 290 c +f +*U +0.000 0.000 0.000 0.078 k +*u +348 292 m +348 290 l +350 290 l +350 292 l +348 292 l +f +*U +0.000 0.000 0.000 0.722 k +*u +600 292 m +601 291 l +600 292 l +f +*U +0.000 0.000 0.000 0.082 k +*u +784 292 m +784 271 l +786 271 l +786 277.541 786.862 284.699 785 291 c +792 290 798.934 288.303 806 288 c +806 272 l +807.797 272 807.521 272 809 273 c +808 277 809.393 284 806.972 287.486 c +805.447 289.622 802.364 289.842 800 290.245 c +794.702 291 789.378 291.955 784 292 c +f +*U +0.000 0.000 0.000 0.078 k +*u +823 292 m +821.770 289.365 820.766 286.804 820 284 c +822.573 286.383 823.933 288.660 825 292 c +823 292 l +f +*U +0.000 0.000 0.000 0.624 k +*u +825 292 m +826 291 l +825 292 l +f +*U +0.000 0.000 0.000 0.616 k +*u +843 292 m +844 291 l +843 292 l +f +*U +0.000 0.584 0.439 0.329 k +*u +1050 292 m +1050 289 l +1050.696 290.554 1050.696 290.446 1050 292 c +f +*U +0.000 0.259 0.153 0.408 k +*u +1153 292 m +1154 291 l +1153 292 l +f +*U +0.000 0.314 0.184 0.043 k +*u +1154 292 m +1155 291 l +1154 292 l +f +*U +0.000 0.427 0.282 0.098 k +*u +1214 292 m +1215 291 l +1214 292 l +f +*U +0.000 0.447 0.314 0.400 k +*u +1291.667 291.667 m +1291.222 291.222 1292.278 291.278 1292.333 291.333 c +1292.778 291.778 1291.722 291.722 1291.667 291.667 c +f +*U +0.000 0.102 0.059 0.082 k +*u +1295.333 291.333 m +1295.278 291.278 1295.222 290.222 1295.667 290.667 c +1295.722 290.723 1295.777 291.778 1295.333 291.333 c +f +*U +0.000 0.400 0.282 0.098 k +*u +1311 292 m +1312 291 l +1311 292 l +f +*U +0.000 0.318 0.388 0.267 k +*u +1315 292 m +1316.506 291.317 1317.315 291.174 1319 291 c +1317.494 291.683 1316.685 291.826 1315 292 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1446 292 m +1446 264 l +1446 260.293 1445 255.582 1448 253 c +1446.414 261.541 1447 270.342 1447 279 c +1447 283.260 1447.661 288 1446 292 c +f +*U +0.000 0.000 0.000 0.776 k +*u +1473 292 m +1474 291 l +1473 292 l +f +*U +0.000 0.000 0.000 0.161 k +*u +1818 292 m +1822.720 290 1828.920 291 1834 291 c +1866 291 l +1861.280 292.981 1855 292 1850 292 c +1818 292 l +f +*U +0.000 0.000 0.000 0.078 k +*u +169 291 m +169 271 l +171 271 l +171 291 l +169 291 l +f +*U +0.000 0.000 0.000 0.106 k +*u +343 291 m +343 272 l +345 272 l +345 277.819 346.627 286.213 343 291 c +f +*U +0.000 0.000 0.000 0.894 k +*u +345.667 290.667 m +345.222 290.222 346.278 290.278 346.333 290.333 c +346.778 290.778 345.722 290.722 345.667 290.667 c +f +*U +0.000 0.000 0.000 0.600 k +*u +347 291 m +348 290 l +347 291 l +f +*U +0.000 0.000 0.000 0.169 k +*u +350 291 m +351.506 290.317 352.315 290.174 354 290 c +352.494 290.683 351.685 290.826 350 291 c +f +*U +0.000 0.000 0.000 0.082 k +*u +402 291 m +402 254 l +406.630 260.777 403.860 274 404 282 c +404 285.548 405 288.710 402 291 c +f +*U +0.000 0.000 0.000 0.243 k +*u +785 291 m +786 290 l +785 291 l +f +*U +0.000 0.000 0.000 0.541 k +*u +788 291 m +789 290 l +788 291 l +f +*U +0.000 0.000 0.000 0.808 k +*u +891.333 290.333 m +891.278 290.278 891.222 289.222 891.667 289.667 c +891.722 289.722 891.778 290.778 891.333 290.333 c +f +*U +0.000 0.000 0.000 0.710 k +*u +910 291 m +911 290 l +910 291 l +f +*U +0.000 0.000 0.000 0.102 k +*u +911 291 m +912.305 286.905 914.607 283.550 917 280 c +917.717 284.411 914 288.208 911 291 c +f +*U +0.000 0.133 0.122 0.078 k +*u +1141 291 m +1142 290 l +1141 291 l +f +*U +0.000 0.408 0.275 0.004 k +*u +1152.333 290.333 m +1152.278 290.278 1152.222 289.222 1152.667 289.667 c +1152.722 289.722 1152.777 290.778 1152.333 290.333 c +f +*U +0.000 0.698 0.522 0.302 k +*u +1153 288 m +1154.560 288.596 1155.623 289 1157 290 c +1154.303 290.854 1153.614 290.851 1153 288 c +f +*U +0.000 0.263 0.129 0.310 k +*u +1156 291 m +1157 290 l +1156 291 l +f +*U +0.000 0.588 0.451 0.412 k +*u +1293 291 m +1294 290 l +1293 291 l +f +*U +0.000 0.439 0.298 0.086 k +*u +1294 291 m +1295 290 l +1294 291 l +f +*U +0.000 0.204 0.141 0.122 k +*u +1314.333 290.333 m +1314.278 290.278 1314.222 289.222 1314.667 289.667 c +1314.722 289.722 1314.778 290.778 1314.333 290.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1319 284 m +1319.464 286.172 1320 287.958 1321 290 c +1314.568 291.356 1313.905 287.344 1319 284 c +f +*U +0.000 0.318 0.188 0.063 k +*u +1319.667 290.667 m +1319.222 290.222 1320.278 290.278 1320.333 290.333 c +1320.778 290.778 1319.722 290.722 1319.667 290.667 c +f +*U +0.000 0.420 0.263 0.094 k +*u +1321.333 290.333 m +1321.278 290.278 1321.222 289.222 1321.667 289.667 c +1321.722 289.722 1321.777 290.778 1321.333 290.333 c +f +*U +0.000 0.000 0.000 0.110 k +*u +1447 291 m +1447 255 l +1448.552 258.698 1448 263 1448 267 c +1448 289 l +1450.360 287.687 1452.391 286.659 1455 286 c +1452.579 288.268 1450 289.685 1447 291 c +f +*U +0.000 0.000 0.000 0.725 k +*u +1448 291 m +1449 290 l +1448 291 l +f +*U +0.000 0.000 0.000 0.596 k +*u +1475 291 m +1476 290 l +1475 291 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1476 291 m +1478.383 288.549 1480.793 287.178 1484 286 c +1481.654 288.730 1479.449 289.975 1476 291 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1818 291 m +1818 270 l +1820.643 276.299 1818.394 284.254 1820 291 c +1818 291 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1929 291 m +1930 290 l +1929 291 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1994 291 m +1995 290 l +1994 291 l +f +*U +0.000 0.000 0.000 0.827 k +*u +352 290 m +353 289 l +352 290 l +f +*U +0.000 0.000 0.000 0.561 k +*u +353 290 m +354 289 l +353 290 l +f +*U +0.000 0.000 0.000 0.200 k +*u +357.667 289.667 m +357.222 289.222 358.278 289.278 358.333 289.333 c +358.778 289.778 357.722 289.722 357.667 289.667 c +f +*U +0.000 0.000 0.000 0.078 k +*u +359 290 m +361 288.418 362.388 288.174 365 288 c +365 280.237 364.973 272.702 364 265 c +367 269.401 369.457 282.706 365.972 287.436 c +364.435 289.522 361.327 289.677 359 290 c +f +*U +0.000 0.000 0.000 0.753 k +*u +577 290 m +578 289 l +577 290 l +f +*U +0.000 0.000 0.000 0.533 k +*u +794 290 m +795 289 l +794 290 l +f +*U +0.000 0.000 0.000 0.776 k +*u +842 290 m +843 289 l +842 290 l +f +*U +0.000 0.000 0.000 0.616 k +*u +843 290 m +847.720 288 853.920 289 859 289 c +891 289 l +886.280 290.981 880 290 875 290 c +843 290 l +f +*U +0.000 0.404 0.314 0.286 k +*u +1141.333 289.333 m +1141.278 289.278 1141.222 288.222 1141.667 288.667 c +1141.722 288.722 1141.777 289.778 1141.333 289.333 c +f +*U +0.000 0.341 0.392 0.239 k +*u +1157 290 m +1158 289 l +1157 290 l +f +*U +0.000 0.145 0.094 0.192 k +*u +1215 290 m +1216 289 l +1215 290 l +f +*U +0.000 0.780 0.553 0.220 k +*u +1217 290 m +1216.659 283.801 1217.589 282 1224 282 c +1221.948 282.874 1220.253 282.953 1218 283 c +1218 289 l +1224 289 l +1221.669 289.984 1219.543 289.981 1217 290 c +f +*U +0.000 0.604 0.486 0.396 k +*u +1294 290 m +1295 289 l +1294 290 l +f +*U +0.000 0.290 0.290 0.710 k +*u +1313.333 289.333 m +1313.278 289.278 1313.222 288.222 1313.667 288.667 c +1313.722 288.722 1313.777 289.778 1313.333 289.333 c +f +*U +0.000 0.663 0.698 0.267 k +*u +1397 290 m +1397 284 l +1397.951 286.285 1397.951 287.715 1397 290 c +f +*U +0.000 0.322 0.290 0.157 k +*u +1398 290 m +1398 285 l +1398.830 287 1398.830 287.970 1398 290 c +f +*U +0.000 0.000 0.000 0.804 k +*u +1450 290 m +1451 289 l +1450 290 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1819 290 m +1819 283 1819.623 275.818 1818 269 c +1873 269 l +1880.751 269 1891 270.863 1898 267 c +1899.183 269.328 1900.223 271.511 1901 274 c +1893.242 268.414 1884.246 270 1875 270 c +1820 270 l +1820 276.169 1821.398 284.285 1819 290 c +f +*U +0.000 0.000 0.000 0.110 k +*u +1910 290 m +1909 288.522 1909 288.797 1909 287 c +1910.290 288.443 1910.401 288.233 1910 290 c +f +*U +0.000 0.000 0.000 0.820 k +*u +1911 290 m +1912 289 l +1911 290 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1976 290 m +1977 289 l +1976 290 l +f +*U +0.000 0.000 0.000 0.827 k +*u +358 289 m +359 288 l +358 289 l +f +*U +0.000 0.000 0.000 0.659 k +*u +359 289 m +360 288 l +359 289 l +f +*U +0.000 0.000 0.000 0.690 k +*u +578 289 m +579 288 l +578 289 l +f +*U +0.000 0.000 0.000 0.667 k +*u +604 289 m +605 288 l +604 289 l +f +*U +0.000 0.000 0.000 0.125 k +*u +605 289 m +606.624 286.956 607.643 286 610 285 c +608.598 287.274 607.485 287.987 605 289 c +f +*U +0.000 0.000 0.000 0.541 k +*u +800 289 m +801 288 l +800 289 l +f +*U +0.000 0.455 0.322 0.188 k +*u +1050 289 m +1050 284 l +1050.830 286 1050.830 286.970 1050 289 c +f +*U +0.000 0.278 0.231 0.251 k +*u +1152 289 m +1153 288 l +1152 289 l +f +*U +0.000 0.784 0.565 0.188 k +*u +1153 284 m +1157 285 l +1155.752 285.685 1155.451 285.749 1154 286 c +1156.786 286.458 1157.455 286.369 1159 284 c +1159.683 285.506 1159.826 286.315 1160 288 c +1155.836 288.646 1153.747 288.465 1153 284 c +f +*U +0.000 0.639 0.655 0.345 k +*u +1157 289 m +1158 288 l +1157 289 l +f +*U +0.000 0.318 0.486 0.373 k +*u +1158 289 m +1159 288 l +1158 289 l +f +*U +0.000 0.325 0.239 0.294 k +*u +1320 289 m +1321 288 l +1320 289 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1478 289 m +1479 288 l +1478 289 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1770 289 m +1771 288 l +1770 289 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1929 289 m +1933.720 287 1939.920 288 1945 288 c +1977 288 l +1972.280 289.981 1966 289 1961 289 c +1929 289 l +f +*U +0.000 0.588 0.455 0.357 k +*u +1141 288 m +1141 284 l +1141.710 285.759 1141.710 286.241 1141 288 c +f +*U +0.000 0.655 0.545 0.345 k +*u +1152 288 m +1152 282 l +1152.951 284.285 1152.951 285.715 1152 288 c +f +*U +0.000 0.114 0.216 0.318 k +*u +1160 288 m +1161 287 l +1160 288 l +f +*U +0.000 0.404 0.298 0.137 k +*u +1314.333 287.333 m +1314.278 287.278 1314.222 286.222 1314.667 286.667 c +1314.722 286.722 1314.778 287.778 1314.333 287.333 c +f +*U +0.000 0.353 0.243 0.345 k +*u +1319 288 m +1320 287 l +1319 288 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1453 288 m +1454 287 l +1453 288 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1480 288 m +1481 287 l +1480 288 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1766 288 m +1767 287 l +1766 288 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1996 288 m +1997 287 l +1996 288 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1997 288 m +1997.683 286.420 1997.805 286.223 1999 285 c +1998.316 286.580 1998.195 286.777 1997 288 c +f +*U +0.000 0.000 0.000 0.188 k +*u +579.667 286.667 m +579.222 286.222 580.278 286.278 580.333 286.333 c +580.778 286.778 579.722 286.722 579.667 286.667 c +f +*U +0.000 0.741 0.478 0.259 k +*u +1051 287 m +1051 283 l +1051.710 284.759 1051.710 285.241 1051 287 c +f +*U +0.000 0.886 0.667 0.110 k +*u +1154 287 m +1157 285 l +1155 284 1154.222 283.733 1153 282 c +1160 282 l +1159 287 l +1154 287 l +f +*U +0.000 0.267 0.259 0.706 k +*u +1160 287 m +1161 286 l +1160 287 l +f +*U +0.000 0.553 0.388 0.196 k +*u +1216.333 286.333 m +1216.278 286.278 1216.222 285.222 1216.667 285.667 c +1216.722 285.722 1216.777 286.778 1216.333 286.333 c +f +*U +0.122 0.000 0.031 0.161 k +*u +1317 287 m +1318 286 l +1317 287 l +f +*U +0.000 0.451 0.271 0.133 k +*u +1319 287 m +1320 286 l +1319 287 l +f +*U +0.000 0.000 0.000 0.792 k +*u +1455 287 m +1456 286 l +1455 287 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1698 287 m +1698 253 l +1700 253 l +1700 285 l +1709.432 285 1719 286 1728 283 c +1721.767 290 1706.728 287 1698 287 c +f +*U +0.000 0.000 0.000 0.631 k +*u +1724 287 m +1725 286 l +1724 287 l +f +*U +0.000 0.000 0.000 0.043 k +*u +1746 287 m +1747.506 286.317 1748.315 286.174 1750 286 c +1750 283 l +1755 283 l +1754.402 284.196 1754.534 283.977 1753 285 c +1754.314 285.768 1754.232 285.686 1755 287 c +1746 287 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1755 287 m +1757.234 284 1759.750 284.856 1763 286 c +1760.387 287 1757.835 286.993 1755 287 c +f +*U +0.000 0.000 0.000 0.165 k +*u +1763 287 m +1764.506 286.317 1765.315 286.174 1767 286 c +1765.494 286.683 1764.685 286.826 1763 287 c +f +*U +0.000 0.000 0.000 0.078 k +*u +1907 287 m +1906 282 l +1907.656 283.686 1908.251 284.746 1909 287 c +1907 287 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1909 287 m +1910 286 l +1909 287 l +f +*U +0.000 0.000 0.000 0.075 k +*u +581 286 m +583 282.223 585.961 280.341 590 279 c +587.451 282 584.610 284.201 581 286 c +f +*U +0.000 0.000 0.000 0.710 k +*u +582 286 m +583 285 l +582 286 l +f +*U +0.000 0.000 0.000 0.831 k +*u +913 286 m +914 285 l +913 286 l +f +*U +0.000 0.451 0.357 0.506 k +*u +1160 286 m +1160 283 l +1160.696 284.554 1160.696 284.446 1160 286 c +f +*U +0.000 0.459 0.337 0.153 k +*u +1315 286 m +1316 285 l +1315 286 l +f +*U +0.000 0.310 0.216 0.055 k +*u +1316 286 m +1317 285 l +1316 286 l +f +*U +0.016 0.035 0.000 0.188 k +*u +1319.333 285.333 m +1319.278 285.278 1319.222 284.222 1319.667 284.667 c +1319.723 284.723 1319.777 285.777 1319.333 285.333 c +f +*U +0.000 0.000 0.000 0.094 k +*u +1455 286 m +1458.420 281.873 1462.878 279.478 1468 278 c +1464.458 281.653 1459.766 284.255 1455 286 c +f +*U +0.000 0.000 0.000 0.176 k +*u +1484.667 285.667 m +1484.222 285.222 1485.278 285.278 1485.333 285.333 c +1485.778 285.778 1484.722 285.722 1484.667 285.667 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1747 286 m +1748 285 l +1747 286 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1748 286 m +1748.545 284.365 1748.365 284.545 1750 284 c +1750 286 l +1748 286 l +f +*U +0.000 0.000 0.000 0.882 k +*u +615 285 m +615 281 l +615.710 282.760 615.710 283.240 615 285 c +f +*U +0.000 0.937 0.667 0.063 k +*u +1056 285 m +1062.194 282.401 1071.314 284 1078 284 c +1115 284 l +1122.281 284 1129.880 284.695 1137 283 c +1133.298 287.236 1121.373 285 1116 285 c +1056 285 l +f +*U +0.078 0.000 0.020 0.259 k +*u +1151 285 m +1151 282 l +1151.696 283.554 1151.696 283.446 1151 285 c +f +*U +0.000 0.239 0.196 0.141 k +*u +1161 285 m +1162 284 l +1161 285 l +f +*U +0.000 0.937 0.667 0.063 k +*u +1224 285 m +1230.436 282.299 1240 284 1247 284 c +1296 284 l +1289.564 286.701 1279.951 285 1273 285 c +1224 285 l +f +*U +0.000 0.671 0.529 0.329 k +*u +1316 285 m +1316.899 282.876 1316.876 282.899 1319 282 c +1317.897 283.457 1317.457 283.897 1316 285 c +f +*U +0.000 0.369 0.239 0.086 k +*u +1317 285 m +1318 284 l +1317 285 l +f +*U +0.000 0.937 0.667 0.063 k +*u +1328 285 m +1333.707 282.605 1341.846 284 1348 284 c +1392 284 l +1386.293 286.395 1378 285 1372 285 c +1328 285 l +f +*U +0.000 0.204 0.176 0.047 k +*u +1398 285 m +1399 284 l +1398 285 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1458 285 m +1459 284 l +1458 285 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1486.667 284.667 m +1486.222 284.222 1487.278 284.278 1487.333 284.333 c +1487.778 284.778 1486.722 284.722 1486.667 284.667 c +f +*U +0.000 0.000 0.000 0.627 k +*u +1998 285 m +1999 284 l +1998 285 l +f +*U +0.000 0.000 0.000 0.067 k +*u +1999 285 m +2000 281.826 2001.785 279.509 2004 277 c +2003.829 280.924 2002 282.680 1999 285 c +f +*U +0.000 0.000 0.000 0.718 k +*u +820 284 m +821 283 l +820 284 l +f +*U +0.000 0.212 0.141 0.106 k +*u +1050.333 283.333 m +1050.278 283.278 1050.222 282.222 1050.667 282.667 c +1050.722 282.722 1050.778 283.778 1050.333 283.333 c +f +*U +0.000 0.510 0.447 0.404 k +*u +1140 284 m +1141 283 l +1140 284 l +f +*U +0.000 0.290 0.255 0.329 k +*u +1141 284 m +1142 283 l +1141 284 l +f +*U +0.000 0.369 0.329 0.259 k +*u +1161 284 m +1162 283 l +1161 284 l +f +*U +0.000 0.506 0.486 0.494 k +*u +1216.333 283.333 m +1216.278 283.278 1216.222 282.222 1216.667 282.667 c +1216.722 282.722 1216.777 283.778 1216.333 283.333 c +f +*U +0.000 0.243 0.216 0.051 k +*u +1318.667 283.667 m +1318.222 283.222 1319.278 283.278 1319.333 283.333 c +1319.778 283.778 1318.722 283.722 1318.667 283.667 c +f +*U +0.000 0.416 0.416 0.584 k +*u +1397.333 283.333 m +1397.278 283.278 1397.222 282.222 1397.667 282.667 c +1397.722 282.722 1397.778 283.778 1397.333 283.333 c +f +*U +0.000 0.000 0.000 0.584 k +*u +1487 284 m +1488 283 l +1487 284 l +f +*U +0.000 0.000 0.000 0.773 k +*u +586 283 m +587 282 l +586 283 l +f +*U +0.000 0.000 0.000 0.184 k +*u +818.333 282.333 m +818.278 282.278 818.222 281.222 818.667 281.667 c +818.722 281.722 818.778 282.778 818.333 282.333 c +f +*U +0.000 0.000 0.000 0.788 k +*u +915 283 m +916 282 l +915 283 l +f +*U +0.000 0.733 0.624 0.251 k +*u +1051 283 m +1052.769 282.221 1054 282 1056 282 c +1054.231 282.779 1052.964 282.912 1051 283 c +f +*U +0.000 0.698 0.514 0.290 k +*u +1136.667 282.667 m +1136.222 282.222 1137.278 282.278 1137.333 282.333 c +1137.778 282.778 1136.722 282.722 1136.667 282.667 c +f +*U +0.000 0.216 0.216 0.318 k +*u +1140 283 m +1141 282 l +1140 283 l +f +*U +0.000 0.659 0.545 0.341 k +*u +1160 283 m +1161.506 282.317 1162.315 282.174 1164 282 c +1162.494 282.683 1161.685 282.826 1160 283 c +f +*U +0.000 0.200 0.125 0.494 k +*u +1164 283 m +1165 282 l +1164 283 l +f +*U +0.039 0.000 0.012 0.231 k +*u +1215.333 282.333 m +1215.278 282.278 1215.222 281.222 1215.667 281.667 c +1215.723 281.723 1215.777 282.777 1215.333 282.333 c +f +*U +0.000 0.655 0.455 0.173 k +*u +1299.667 282.667 m +1299.222 282.222 1300.278 282.278 1300.333 282.333 c +1300.778 282.778 1299.722 282.722 1299.667 282.667 c +f +*U +0.000 0.561 0.416 0.439 k +*u +1301 283 m +1302.248 282.315 1302.548 282.251 1304 282 c +1302.752 282.685 1302.451 282.749 1301 283 c +f +*U +0.000 0.714 0.533 0.286 k +*u +1304 283 m +1305.248 282.315 1305.548 282.251 1307 282 c +1305.752 282.685 1305.452 282.749 1304 283 c +f +*U +0.000 0.000 0.000 0.118 k +*u +1489 283 m +1493.467 279 1499.361 275.785 1505 274 c +1500.973 278.359 1494.838 281.874 1489 283 c +f +*U +0.000 0.000 0.000 0.200 k +*u +1728 283 m +1729 282 l +1728 283 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1729 283 m +1730 282 l +1729 283 l +f +*U +0.000 0.000 0.000 0.149 k +*u +1752 283 m +1753.223 281.805 1753.420 281.684 1755 281 c +1753.777 282.195 1753.580 282.316 1752 283 c +f +*U +0.000 0.361 0.282 0.275 k +*u +1051.667 281.667 m +1051.222 281.222 1052.278 281.278 1052.333 281.333 c +1052.778 281.778 1051.722 281.722 1051.667 281.667 c +f +*U +0.000 0.247 0.204 0.267 k +*u +1053 282 m +1060 278.996 1071.256 281 1079 281 c +1137 281 l +1129.841 284 1118.744 282 1111 282 c +1053 282 l +f +*U +0.000 0.498 0.380 0.286 k +*u +1137.667 281.667 m +1137.222 281.222 1138.278 281.278 1138.333 281.333 c +1138.778 281.778 1137.722 281.722 1137.667 281.667 c +f +*U +0.000 0.314 0.247 0.173 k +*u +1139 282 m +1140 281 l +1139 282 l +f +*U +0.000 0.451 0.310 0.282 k +*u +1152 282 m +1153.249 281.315 1153.548 281.251 1155 281 c +1153.752 281.685 1153.452 281.749 1152 282 c +f +*U +0.000 0.498 0.380 0.043 k +*u +1155 282 m +1157.332 281 1159.457 281 1162 281 c +1159.669 281.984 1157.543 281.981 1155 282 c +f +*U +0.000 0.443 0.314 0.227 k +*u +1162 282 m +1163.249 281.315 1163.548 281.251 1165 281 c +1163.752 281.685 1163.452 281.749 1162 282 c +f +*U +0.000 0.404 0.286 0.302 k +*u +1216.667 281.667 m +1216.222 281.222 1217.278 281.278 1217.333 281.333 c +1217.778 281.778 1216.722 281.722 1216.667 281.667 c +f +*U +0.000 0.392 0.298 0.208 k +*u +1218 282 m +1219.769 281.221 1221 281 1223 281 c +1221.231 281.779 1219.964 281.912 1218 282 c +f +*U +0.000 0.247 0.204 0.267 k +*u +1223 282 m +1229.678 279.198 1239.784 281 1247 281 c +1299 281 l +1292.322 283.802 1282.216 282 1275 282 c +1223 282 l +f +*U +0.000 0.294 0.239 0.165 k +*u +1304.667 281.667 m +1304.222 281.222 1305.278 281.278 1305.333 281.333 c +1305.778 281.778 1304.722 281.722 1304.667 281.667 c +f +*U +0.000 0.396 0.302 0.337 k +*u +1306.667 281.667 m +1306.222 281.222 1307.278 281.278 1307.333 281.333 c +1307.778 281.778 1306.722 281.722 1306.667 281.667 c +f +*U +0.000 0.380 0.294 0.149 k +*u +1308 282 m +1309.506 281.317 1310.315 281.174 1312 281 c +1310.494 281.683 1309.685 281.826 1308 282 c +f +*U +0.000 0.275 0.200 0.396 k +*u +1312 282 m +1313 281 l +1312 282 l +f +*U +0.000 0.247 0.204 0.267 k +*u +1313 282 m +1320 278.996 1331.256 281 1339 281 c +1398 281 l +1390.841 284 1379.744 282 1372 282 c +1313 282 l +f +*U +0.000 0.000 0.000 0.737 k +*u +1463 282 m +1464 281 l +1463 282 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1730 282 m +1731 281 l +1730 282 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1905 282 m +1904 280.521 1904 280.797 1904 279 c +1905.289 280.443 1905.401 280.234 1905 282 c +f +*U +0.000 0.000 0.000 0.749 k +*u +1906 282 m +1907 281 l +1906 282 l +f +*U +0.000 0.000 0.000 0.561 k +*u +615 281 m +616 280 l +615 281 l +f +*U +0.000 0.000 0.000 0.200 k +*u +817.333 280.333 m +817.278 280.278 817.222 279.222 817.667 279.667 c +817.722 279.722 817.778 280.778 817.333 280.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +818 281 m +819 280 l +818 281 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1492 281 m +1493 280 l +1492 281 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1730 281 m +1731.624 278.956 1732.643 278 1735 277 c +1733.376 279 1732.357 279.896 1730 281 c +f +*U +0.000 0.000 0.000 0.612 k +*u +1754 281 m +1755 280 l +1754 281 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1755 281 m +1756.450 279.392 1757 278.936 1759 278 c +1757.550 279.608 1756.949 280 1755 281 c +f +*U +0.000 0.000 0.000 0.729 k +*u +590 280 m +591 279 l +590 280 l +f +*U +0.000 0.000 0.000 0.000 k +*u +615 280 m +616 279 l +615 280 l +f +*U +0.000 0.000 0.000 0.776 k +*u +917 280 m +918 279 l +917 280 l +f +*U +0.000 0.000 0.000 0.125 k +*u +918 280 m +919 277 920.414 274.618 922 272 c +922.576 275.534 920.603 277.762 918 280 c +f +*U +0.000 0.000 0.000 0.796 k +*u +2001 280 m +2002 279 l +2001 280 l +f +*U +0.000 0.000 0.000 0.137 k +*u +2002.333 279.333 m +2002.278 279.278 2002.222 278.222 2002.667 278.667 c +2002.723 278.723 2002.777 279.777 2002.333 279.333 c +f +*U +0.000 0.000 0.000 0.341 k +*u +590 279 m +591 278 l +590 279 l +f +*U +0.000 0.000 0.000 0.576 k +*u +591 279 m +592 278 l +591 279 l +f +*U +0.000 0.000 0.000 0.133 k +*u +816 279 m +814.602 276.950 813.749 275.354 813 273 c +815 274.908 816.250 276.208 816 279 c +f +*U +0.000 0.000 0.000 0.773 k +*u +1468 279 m +1469 278 l +1468 279 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1904 279 m +1905 278 l +1904 279 l +f +*U +0.000 0.000 0.000 0.063 k +*u +591 278 m +594 273 l +599 272 l +596.681 274.841 594.378 276.568 591 278 c +f +*U +0.000 0.000 0.000 0.694 k +*u +616.333 277.333 m +616.278 277.278 616.222 276.222 616.667 276.667 c +616.722 276.722 616.778 277.778 616.333 277.333 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1468 278 m +1469.543 276.733 1470 276.511 1472 276 c +1470.542 277 1469.752 277.436 1468 278 c +f +*U +0.000 0.000 0.000 0.702 k +*u +1735 278 m +1736 277 l +1735 278 l +f +*U +0.000 0.000 0.000 0.639 k +*u +1758 278 m +1759 277 l +1758 278 l +f +*U +0.000 0.000 0.000 0.671 k +*u +919 277 m +920 276 l +919 277 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1499 277 m +1500 276 l +1499 277 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1760 277 m +1761.223 275.805 1761.420 275.684 1763 275 c +1761.777 276.195 1761.580 276.316 1760 277 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1903 277 m +1904 276 l +1903 277 l +f +*U +0.000 0.000 0.000 0.655 k +*u +2003 277 m +2004 276 l +2003 277 l +f +*U +0.000 0.000 0.000 0.051 k +*u +2004 277 m +2004.547 275 2005 273.745 2006 272 c +2006.710 274.531 2006 275.516 2004 277 c +f +*U +0.000 0.000 0.000 0.753 k +*u +595 276 m +596 275 l +595 276 l +f +*U +0.000 0.000 0.000 0.745 k +*u +815 276 m +816 275 l +815 276 l +f +*U +0.000 0.000 0.000 0.749 k +*u +834 276 m +835 275 l +834 276 l +f +*U +0.000 0.000 0.000 0.129 k +*u +833 272 m +840.188 275 848.323 274 856 274 c +898 274 l +893.280 275.981 887 275 882 275 c +849 275 l +843.679 275 835.945 277.210 833 272 c +f +*U +0.000 0.000 0.000 0.784 k +*u +899 276 m +900 275 l +899 276 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1471.667 275.667 m +1471.222 275.222 1472.278 275.278 1472.333 275.333 c +1472.778 275.778 1471.722 275.722 1471.667 275.667 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1473 276 m +1474 275 l +1473 276 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1736 276 m +1738.719 272.223 1741.644 269.688 1746 268 c +1743.264 271.575 1740 274 1736 276 c +f +*U +0.000 0.000 0.000 0.000 k +*u +259.333 274.333 m +259.278 274.278 259.222 273.222 259.667 273.667 c +259.722 273.722 259.778 274.778 259.333 274.333 c +f +*U +0.000 0.000 0.000 0.114 k +*u +899 275 m +899.684 273.420 899.805 273.223 901 272 c +900.316 273.580 900.195 273.777 899 275 c +f +1473 275 m +1474.717 273 1475.566 272.651 1478 272 c +1476.313 273.656 1475.254 274.251 1473 275 c +f +*U +0.000 0.000 0.000 0.737 k +*u +1762 275 m +1763 274 l +1762 275 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1763 275 m +1768.354 268.424 1778.192 261.301 1786 258 c +1780.827 264.785 1771 272.274 1763 275 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1920 275 m +1921 274 l +1920 275 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1920 272 m +1933.679 275.257 1949.965 273 1964 273 c +1969.259 273 1976.967 274.410 1981.895 272.397 c +1985.436 270.950 1987 266.437 1990 264 c +1989 267 1987.593 271 1984.621 272.972 c +1981 275 1974.935 274 1971 274 c +1939 274 l +1934 274 1923 276.201 1920 272 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1922 275 m +1927.708 272.605 1935.846 274 1942 274 c +1984 274 l +1978.293 276.395 1970 275 1964 275 c +1922 275 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1984 275 m +1985 274 l +1984 275 l +f +*U +0.000 0.000 0.000 0.698 k +*u +1504 274 m +1505 273 l +1504 274 l +f +*U +0.000 0.000 0.000 0.290 k +*u +1505 274 m +1506 273 l +1505 274 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1655.333 273.333 m +1655.278 273.278 1655.222 272.222 1655.667 272.667 c +1655.722 272.722 1655.777 273.778 1655.333 273.333 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1901 274 m +1902 273 l +1901 274 l +f +*U +0.000 0.000 0.000 0.784 k +*u +599 273 m +600 272 l +599 273 l +f +*U +0.000 0.000 0.000 0.063 k +*u +812 273 m +810.652 271.232 809.878 270 809 268 c +811.343 269.347 812.401 270.259 812 273 c +f +*U +0.000 0.000 0.000 0.631 k +*u +813 273 m +814 272 l +813 273 l +f +*U +0.000 0.000 0.000 0.808 k +*u +832 273 m +833 272 l +832 273 l +f +*U +0.000 0.000 0.000 0.604 k +*u +1506 273 m +1507 272 l +1506 273 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1507 273 m +1508.223 271.805 1508.420 271.684 1510 271 c +1508.777 272.195 1508.580 272.316 1507 273 c +f +*U +0.000 0.000 0.000 0.722 k +*u +1741 273 m +1742 272 l +1741 273 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1919 273 m +1920 272 l +1919 273 l +f +*U +0.000 0.000 0.000 0.161 k +*u +806 272 m +806 268 l +806.710 269.760 806.710 270.241 806 272 c +f +*U +0.000 0.000 0.000 0.114 k +*u +832 272 m +831 270.255 830.547 268.875 830 267 c +831.693 268.782 832.375 269.581 832 272 c +f +*U +0.000 0.000 0.000 0.196 k +*u +901.333 271.333 m +901.278 271.278 901.222 270.222 901.667 270.667 c +901.722 270.722 901.778 271.778 901.333 271.333 c +f +*U +0.000 0.000 0.000 0.753 k +*u +1766 272 m +1767 271 l +1766 272 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1919 272 m +1918 270.522 1918 270.797 1918 269 c +1919.290 270.443 1919.401 270.233 1919 272 c +f +*U +0.000 0.000 0.000 0.110 k +*u +2007 272 m +2008.460 268 2010.660 264.537 2013 261 c +2013.886 265.544 2010.329 269.281 2007 272 c +f +*U +0.000 0.000 0.000 0.141 k +*u +169 271 m +175.919 268 186.520 270 194 270 c +249 270 l +242 272.903 231.480 271 224 271 c +169 271 l +f +*U +0.000 0.000 0.000 0.153 k +*u +280 271 m +285.951 268.503 294.580 270 301 270 c +345 270 l +339 272.497 330.420 271 324 271 c +280 271 l +f +*U +0.000 0.000 0.000 0.161 k +*u +600 271 m +601.223 269.805 601.420 269.684 603 269 c +601.777 270.195 601.580 270.316 600 271 c +f +*U +0.000 0.000 0.000 0.710 k +*u +902 271 m +903 270 l +902 271 l +f +*U +0.000 0.000 0.000 0.102 k +*u +924 271 m +924.777 268.511 925.817 266.328 927 264 c +927.728 267 926.256 268.853 924 271 c +f +*U +0.000 0.000 0.000 0.153 k +*u +958 271 m +964.436 268.299 974 270 981 270 c +1032 270 l +1025.564 272.701 1015.951 271 1009 271 c +958 271 l +f +*U +0.000 0.000 0.000 0.325 k +*u +1032 271 m +1033 270 l +1032 271 l +f +*U +0.000 0.306 0.227 0.243 k +*u +1052 271 m +1052 268 l +1053 269 1053.309 269.612 1054 271 c +1052 271 l +f +*U +0.000 0.478 0.349 0.161 k +*u +1054 271 m +1061 267.996 1072.256 270 1080 270 c +1138 270 l +1130.841 273 1119.744 271 1112 271 c +1054 271 l +f +*U +0.000 0.051 0.043 0.286 k +*u +1141 271 m +1142 270 l +1141 271 l +f +*U +0.000 0.318 0.220 0.455 k +*u +1142 271 m +1143 270 l +1142 271 l +f +*U +0.000 0.263 0.184 0.153 k +*u +1143 271 m +1144 270 l +1143 271 l +f +*U +0.000 0.478 0.349 0.161 k +*u +1147 271 m +1154.649 267.790 1166.712 270 1175 270 c +1167.351 273.210 1155.288 271 1147 271 c +f +*U +0.000 0.435 0.314 0.361 k +*u +1175 271 m +1176 270 l +1175 271 l +f +*U +0.000 0.247 0.212 0.227 k +*u +1195 271 m +1196.248 270.315 1196.548 270.251 1198 270 c +1196.752 270.685 1196.451 270.749 1195 271 c +f +*U +0.000 0.478 0.349 0.161 k +*u +1198 271 m +1204.194 268.401 1213.314 270 1220 270 c +1268 270 l +1261.806 272.599 1252.686 271 1246 271 c +1198 271 l +f +*U +0.000 0.416 0.247 0.298 k +*u +1268 271 m +1269.769 270.221 1271 270 1273 270 c +1271.231 270.779 1269.964 270.912 1268 271 c +f +*U +0.000 0.192 0.114 0.188 k +*u +1273.333 270.333 m +1273.278 270.278 1273.222 269.222 1273.667 269.667 c +1273.723 269.723 1273.777 270.777 1273.333 270.333 c +f +*U +0.000 0.298 0.231 0.106 k +*u +1278 271 m +1279 270 l +1278 271 l +f +*U +0.000 0.471 0.341 0.169 k +*u +1279 271 m +1284.715 268.602 1292.831 270 1299 270 c +1293.285 272.398 1285.169 271 1279 271 c +f +*U +0.000 0.278 0.196 0.098 k +*u +1299 271 m +1300 270 l +1299 271 l +f +*U +0.000 0.282 0.192 0.075 k +*u +1307.667 270.667 m +1307.222 270.222 1308.278 270.278 1308.333 270.333 c +1308.778 270.778 1307.722 270.722 1307.667 270.667 c +f +*U +0.000 0.467 0.318 0.275 k +*u +1309 271 m +1310.249 270.315 1310.548 270.251 1312 270 c +1310.752 270.685 1310.452 270.749 1309 271 c +f +*U +0.000 0.153 0.098 0.106 k +*u +1312 271 m +1313 270 l +1312 271 l +f +*U +0.000 0.216 0.165 0.161 k +*u +1316 271 m +1317 270 l +1316 271 l +f +*U +0.000 0.310 0.235 0.286 k +*u +1317 271 m +1318.506 270.317 1319.315 270.174 1321 270 c +1319.494 270.683 1318.685 270.826 1317 271 c +f +*U +0.000 0.478 0.349 0.161 k +*u +1321 271 m +1327.436 268.299 1337 270 1344 270 c +1393 270 l +1386.564 272.701 1376.951 271 1370 271 c +1321 271 l +f +*U +0.000 0.408 0.314 0.129 k +*u +1393 271 m +1396 268 l +1396.951 270.507 1395.348 270.706 1393 271 c +f +*U +0.000 0.000 0.000 0.545 k +*u +1481 271 m +1482 270 l +1481 271 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1509 271 m +1510 270 l +1509 271 l +f +*U +0.000 0.000 0.000 0.141 k +*u +1510.667 270.667 m +1510.222 270.222 1511.278 270.278 1511.333 270.333 c +1511.778 270.778 1510.722 270.722 1510.667 270.667 c +f +*U +0.000 0.000 0.000 0.612 k +*u +169 270 m +175.919 267 186.520 269 194 269 c +249 269 l +242 271.903 231.480 270 224 270 c +169 270 l +f +*U +0.000 0.000 0.000 0.851 k +*u +280 270 m +285.951 267.503 294.580 269 301 269 c +345 269 l +339 271.497 330.420 270 324 270 c +280 270 l +f +721 270 m +726.951 267.503 735.580 269 742 269 c +786 269 l +780 271.497 771.420 270 765 270 c +721 270 l +f +*U +0.000 0.000 0.000 0.239 k +*u +902 270 m +903 269 l +902 270 l +f +*U +0.000 0.000 0.000 0.851 k +*u +958 270 m +964.678 267.198 974.784 269 982 269 c +1033 269 l +1026.564 271.701 1016.951 270 1010 270 c +958 270 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1033 270 m +1033 254 l +1036 258.484 1035 264.749 1035 270 c +1033 270 l +f +*U +0.000 0.859 0.616 0.133 k +*u +1053 270 m +1053.482 267.636 1053.636 267.482 1056 267 c +1055.198 263.829 1055.599 261.232 1056 258 c +1136 258 l +1135 262.609 1135.960 265.571 1137 270 c +1053 270 l +f +*U +0.000 0.459 0.345 0.541 k +*u +1137.333 269.333 m +1137.278 269.278 1137.222 268.222 1137.667 268.667 c +1137.722 268.722 1137.777 269.778 1137.333 269.333 c +f +*U +0.000 0.102 0.086 0.184 k +*u +1138 270 m +1139 269 l +1138 270 l +f +*U +0.000 0.271 0.176 0.196 k +*u +1141.333 269.333 m +1141.278 269.278 1141.222 268.222 1141.667 268.667 c +1141.722 268.722 1141.777 269.778 1141.333 269.333 c +f +*U +0.000 0.612 0.408 0.353 k +*u +1142 270 m +1142 266 l +1143 267.458 1143.436 268.248 1144 270 c +1142 270 l +f +*U +0.000 0.655 0.549 0.345 k +*u +1147 270 m +1147 263 l +1148 265.534 1148 267.466 1147 270 c +f +*U +0.000 0.878 0.620 0.122 k +*u +1148 270 m +1148 267 1147.474 263 1149.742 260.742 c +1151.802 258.683 1155.340 259 1158 258.715 c +1166.621 257.652 1175.319 258 1184 258 c +1180.970 262.517 1177 264.215 1176 270 c +1148 270 l +f +*U +0.000 0.122 0.086 0.188 k +*u +1176 270 m +1177 269 l +1176 270 l +f +*U +0.000 0.404 0.306 0.294 k +*u +1194 270 m +1195 269 l +1194 270 l +f +*U +0.000 0.812 0.655 0.188 k +*u +1194 266 m +1198 269 l +1195.251 269.603 1194.500 268.638 1194 266 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1192 258 m +1264 258 l +1261 263.656 1266.715 265 1270 269 c +1252.776 268 1235.258 269 1218 269 c +1212.485 269 1202 271 1197.228 268.651 c +1193.931 267 1192.774 261.285 1192 258 c +f +*U +0.000 0.839 0.616 0.161 k +*u +1199 270 m +1205.194 267.401 1214.314 269 1221 269 c +1255 269 l +1260.628 269.000 1266.457 268 1272 269 c +1265.564 271.701 1255.951 270 1249 270 c +1199 270 l +f +*U +0.000 0.451 0.294 0.549 k +*u +1272 270 m +1273 269 l +1272 270 l +f +*U +0.000 0.235 0.176 0.114 k +*u +1276 270 m +1277 269 l +1276 270 l +f +*U +0.000 0.718 0.518 0.282 k +*u +1271 260 m +1275.314 262 1276.665 265.876 1280 269 c +1275.894 269.917 1273 263 1271 260 c +f +*U +0.000 0.855 0.604 0.141 k +*u +1271 258 m +1278.564 258 1286.480 257.330 1294 258.174 c +1297.428 258.559 1300.468 260.538 1303.830 260.860 c +1306.956 261 1309.747 259.775 1312.986 260.484 c +1317.567 261.486 1319 267 1323 267.687 c +1329 268.499 1336.776 267 1343 267 c +1392 267 l +1386.293 269.395 1378 268 1372 268 c +1328 268 l +1335 270 1343.573 269 1351 269 c +1395 269 l +1389 271.497 1380.420 270 1374 270 c +1327 270 l +1321.541 270.000 1308.956 271.874 1307 266 c +1304.706 266.303 1303.788 266.579 1302 268 c +1299 267 l +1298 271.221 1293.654 270 1290 270 c +1286.941 270 1282.926 270.656 1280 269.500 c +1276.675 268 1272.924 261 1271 258 c +f +*U +0.000 0.647 0.443 0.333 k +*u +1299 270 m +1299.406 267.907 1299.216 267.980 1301 267 c +1300.309 268.388 1300 268.861 1299 270 c +f +*U +0.000 0.455 0.322 0.353 k +*u +1306.333 269.333 m +1306.278 269.278 1306.222 268.222 1306.667 268.667 c +1306.722 268.722 1306.777 269.778 1306.333 269.333 c +f +*U +0.000 0.361 0.337 0.639 k +*u +1307 270 m +1308 269 l +1307 270 l +f +*U +0.000 0.714 0.553 0.286 k +*u +1312 270 m +1313.769 269.221 1315 269 1317 269 c +1315.231 269.779 1313.964 269.912 1312 270 c +f +*U +0.000 0.702 0.525 0.298 k +*u +1395 270 m +1395 266 l +1395.710 267.759 1395.710 268.241 1395 270 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1511 270 m +1512 269 l +1511 270 l +f +*U +0.000 0.000 0.000 0.157 k +*u +1514.333 269.333 m +1514.278 269.278 1514.222 268.222 1514.667 268.667 c +1514.722 268.722 1514.777 269.778 1514.333 269.333 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1539 270 m +1540 269 l +1539 270 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1917 270 m +1918 269 l +1917 270 l +f +*U +0.000 0.000 0.000 0.698 k +*u +1987 270 m +1988 269 l +1987 270 l +f +*U +0.000 0.000 0.000 0.518 k +*u +364 269 m +365 268 l +364 269 l +f +*U +0.000 0.000 0.000 0.604 k +*u +604 269 m +605 268 l +604 269 l +f +*U +0.000 0.000 0.000 0.549 k +*u +805 269 m +806 268 l +805 269 l +f +*U +0.000 0.000 0.000 0.157 k +*u +903.333 268.333 m +903.278 268.278 903.222 267.222 903.667 267.667 c +903.722 267.722 903.778 268.778 903.333 268.333 c +f +*U +0.000 0.243 0.169 0.553 k +*u +1176 269 m +1177 268 l +1176 269 l +f +*U +0.000 0.361 0.271 0.239 k +*u +1193 269 m +1194 268 l +1193 269 l +f +*U +0.000 0.600 0.576 0.400 k +*u +1271 269 m +1272 268 l +1271 269 l +f +*U +0.000 0.294 0.169 0.071 k +*u +1272 269 m +1273 268 l +1272 269 l +f +*U +0.000 0.255 0.176 0.114 k +*u +1275.333 268.333 m +1275.278 268.278 1275.222 267.222 1275.667 267.667 c +1275.722 267.722 1275.778 268.778 1275.333 268.333 c +f +*U +0.000 0.302 0.224 0.153 k +*u +1300 269 m +1301 268 l +1300 269 l +f +*U +0.000 0.596 0.447 0.345 k +*u +1321 269 m +1322.248 268.315 1322.548 268.251 1324 268 c +1322.752 268.685 1322.451 268.749 1321 269 c +f +*U +0.000 0.859 0.616 0.133 k +*u +1328 269 m +1333.707 266.605 1341.846 268 1348 268 c +1392 268 l +1384.848 265.886 1376.427 267 1369 267 c +1327 267 l +1329 257.518 1336.680 258 1345 258 c +1361 257.994 1377 258.956 1393 259 c +1393.655 261.537 1394.276 263 1396 265 c +1395 269 l +1328 269 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1483 269 m +1484.223 267.805 1484.420 267.684 1486 267 c +1484.777 268.195 1484.580 268.316 1483 269 c +f +*U +0.000 0.000 0.000 0.839 k +*u +1559 269 m +1565.678 266.198 1575.784 268 1583 268 c +1636 268 l +1629.322 270.802 1619.216 269 1612 269 c +1559 269 l +f +*U +0.000 0.000 0.000 0.620 k +*u +1818 269 m +1824.678 266.198 1834.784 268 1842 268 c +1896 268 l +1889.322 270.802 1879.216 269 1872 269 c +1818 269 l +f +*U +0.000 0.000 0.000 0.259 k +*u +1896 269 m +1896 266 l +1896.696 267.554 1896.696 267.446 1896 269 c +f +*U +0.000 0.000 0.000 0.141 k +*u +1917.333 268.333 m +1917.278 268.278 1917.222 267.222 1917.667 267.667 c +1917.722 267.723 1917.777 268.778 1917.333 268.333 c +f +*U +0.000 0.000 0.000 0.702 k +*u +2008 269 m +2009 268 l +2008 269 l +f +*U +0.000 0.000 0.000 0.506 k +*u +260 268 m +261 267 l +260 268 l +f +*U +0.000 0.000 0.000 0.157 k +*u +604.667 267.667 m +604.222 267.222 605.278 267.278 605.333 267.333 c +605.778 267.778 604.722 267.722 604.667 267.667 c +f +*U +0.000 0.000 0.000 0.533 k +*u +701 268 m +702 267 l +701 268 l +f +*U +0.000 0.000 0.000 0.059 k +*u +805 268 m +804.719 264.256 803.789 262.510 801 260 c +801 258 l +802 257 l +804 257 l +806.226 260.710 806.484 263.797 807 268 c +805 268 l +f +*U +0.000 0.000 0.000 0.137 k +*u +809 268 m +808 266.521 808 266.797 808 265 c +809.289 266.443 809.401 266.234 809 268 c +f +*U +0.000 0.000 0.000 0.769 k +*u +810 268 m +811 267 l +810 268 l +f +*U +0.000 0.000 0.000 0.749 k +*u +829 268 m +830 267 l +829 268 l +f +*U +0.000 0.306 0.216 0.000 k +*u +1052 268 m +1053 267 l +1052 268 l +f +*U +0.000 0.275 0.200 0.243 k +*u +1137 268 m +1138 267 l +1137 268 l +f +*U +0.000 0.247 0.165 0.039 k +*u +1141 268 m +1142 267 l +1141 268 l +f +*U +0.000 0.059 0.031 0.592 k +*u +1143 268 m +1142 265 l +1143.766 265.979 1143.956 266.222 1143 268 c +f +*U +0.000 0.553 0.420 0.447 k +*u +1176.333 267.333 m +1176.278 267.278 1176.222 266.222 1176.667 266.667 c +1176.722 266.722 1176.777 267.778 1176.333 267.333 c +f +*U +0.000 0.380 0.314 0.463 k +*u +1268 266 m +1269.580 266.683 1269.777 266.805 1271 268 c +1269.420 267.316 1269.223 267.195 1268 266 c +f +*U +0.000 0.380 0.290 0.020 k +*u +1271 268 m +1272 267 l +1271 268 l +f +*U +0.000 0.302 0.231 0.149 k +*u +1305 268 m +1306 267 l +1305 268 l +f +*U +0.000 0.690 0.529 0.310 k +*u +1306 268 m +1305 266 l +1307 266 l +1307 267.853 1307.300 267.350 1306 268 c +f +*U +0.000 0.463 0.286 0.212 k +*u +1320 268 m +1321 267 l +1320 268 l +f +*U +0.000 0.133 0.141 0.267 k +*u +1321 268 m +1322.248 267.315 1322.548 267.251 1324 267 c +1322.752 267.685 1322.451 267.749 1321 268 c +f +*U +0.000 0.463 0.376 0.298 k +*u +1324 268 m +1325 267 l +1324 268 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1486 268 m +1487 267 l +1486 268 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1515 268 m +1517.487 265.868 1519.809 264.732 1523 264 c +1520.973 266.754 1518.313 267.426 1515 268 c +f +*U +0.000 0.000 0.000 0.714 k +*u +1747 268 m +1748 267 l +1747 268 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1916 268 m +1917 267 l +1916 268 l +f +*U +0.000 0.000 0.000 0.243 k +*u +829 267 m +830 266 l +829 267 l +f +*U +0.000 0.000 0.000 0.149 k +*u +904 267 m +904.547 265 905 263.745 906 262 c +906.375 264.419 905.693 265.218 904 267 c +f +*U +0.000 0.443 0.341 0.557 k +*u +1053 267 m +1053 264 l +1053.696 265.554 1053.696 265.446 1053 267 c +f +*U +0.000 0.671 0.482 0.329 k +*u +1054 267 m +1054 263.831 1054 261 1055 258 c +1056 260.847 1055.515 263.968 1056 267 c +1054 267 l +f +*U +0.000 0.722 0.557 0.278 k +*u +1135 267 m +1135 264 1135.190 261.729 1136 259 c +1136.668 261.787 1136.172 264.387 1135 267 c +f +*U +0.000 0.267 0.173 0.329 k +*u +1136 267 m +1137 266 l +1136 267 l +f +*U +0.000 0.345 0.235 0.055 k +*u +1177 267 m +1178 266 l +1177 267 l +f +*U +0.000 0.518 0.396 0.482 k +*u +1193.333 266.333 m +1193.278 266.278 1193.222 265.222 1193.667 265.667 c +1193.722 265.723 1193.777 266.778 1193.333 266.333 c +f +*U +0.000 0.365 0.267 0.549 k +*u +1302.667 266.667 m +1302.222 266.222 1303.278 266.278 1303.333 266.333 c +1303.778 266.778 1302.722 266.722 1302.667 266.667 c +f +*U +0.000 0.620 0.455 0.125 k +*u +1304 267 m +1305 266 l +1304 267 l +f +*U +0.000 0.329 0.271 0.212 k +*u +1325 267 m +1326 266 l +1325 267 l +f +*U +0.000 0.592 0.424 0.337 k +*u +1326 267 m +1326.406 264.908 1326.217 264.980 1328 264 c +1327.309 265.388 1327 265.861 1326 267 c +f +*U +0.000 0.000 0.000 0.133 k +*u +1486 267 m +1488.856 263.887 1491.878 261.969 1496 261 c +1493 263.952 1489.915 265.760 1486 267 c +f +*U +0.000 0.000 0.000 0.145 k +*u +1539 267 m +1540.965 254.625 1552.471 253 1563 253 c +1639 253 l +1633 255.497 1624.420 254 1618 254 c +1572 254 l +1564.251 254 1555 253 1548 257 c +1543.848 259.472 1541.841 263.404 1539 267 c +f +*U +0.000 0.000 0.000 0.682 k +*u +1654 267 m +1655 266 l +1654 267 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1747 267 m +1748.624 264.956 1749.643 264 1752 263 c +1750.376 265 1749.357 265.896 1747 267 c +f +*U +0.000 0.000 0.000 0.706 k +*u +1773 267 m +1774 266 l +1773 267 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1895 267 m +1896 266 l +1895 267 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1916 267 m +1915 265.521 1915 265.797 1915 264 c +1916.290 265.443 1916.401 265.233 1916 267 c +f +*U +0.000 0.000 0.000 0.996 k +*u +349 266 m +344.829 263.722 338.732 264.490 334 264.200 c +321 263.407 307.943 263.938 295 264 c +288.649 264 282.729 265.499 277 262 c +278.248 261.315 278.548 261.251 280 261 c +281.294 253.546 292.180 256 298 256 c +316.570 256 335.671 254.595 354 258 c +352.376 261.247 350.610 264.439 351 266 c +349 266 l +f +*U +0.000 0.000 0.000 0.741 k +*u +363 266 m +364 265 l +363 266 l +f +*U +0.000 0.000 0.000 0.706 k +*u +608 266 m +609 265 l +608 266 l +f +*U +0.000 0.000 0.000 0.737 k +*u +804 266 m +805 265 l +804 266 l +f +*U +0.000 0.000 0.000 0.675 k +*u +926 266 m +927 265 l +926 266 l +f +*U +0.000 0.455 0.310 0.365 k +*u +1177 266 m +1178 265 l +1177 266 l +f +*U +0.000 0.463 0.302 0.443 k +*u +1266.667 265.667 m +1266.222 265.222 1267.278 265.278 1267.333 265.333 c +1267.778 265.778 1266.722 265.722 1266.667 265.667 c +f +*U +0.000 0.275 0.224 0.247 k +*u +1268 266 m +1269 265 l +1268 266 l +f +*U +0.000 0.369 0.263 0.314 k +*u +1275 266 m +1276 265 l +1275 266 l +f +*U +0.000 0.000 0.000 0.745 k +*u +1518 266 m +1519 265 l +1518 266 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1540 266 m +1541 265 l +1540 266 l +f +*U +0.000 0.000 0.000 0.239 k +*u +1895.333 265.333 m +1895.278 265.278 1895.222 264.222 1895.667 264.667 c +1895.722 264.722 1895.777 265.778 1895.333 265.333 c +f +*U +0.000 0.000 0.000 0.643 k +*u +1896 266 m +1897 265 l +1896 266 l +f +*U +0.000 0.000 0.000 0.745 k +*u +261 265 m +262 264 l +261 265 l +f +*U +0.000 0.000 0.000 0.133 k +*u +608 265 m +609.223 263.805 609.420 263.684 611 263 c +609.777 264.195 609.580 264.316 608 265 c +f +*U +0.000 0.000 0.000 0.678 k +*u +702 265 m +703 264 l +702 265 l +f +*U +0.000 0.000 0.000 0.157 k +*u +804 265 m +803 261 l +804.303 262.668 804.553 262.992 804 265 c +f +*U +0.000 0.000 0.000 0.690 k +*u +808 265 m +809 264 l +808 265 l +f +*U +0.004 0.027 0.000 0.278 k +*u +1143 265 m +1144 264 l +1143 265 l +f +*U +0.000 0.447 0.337 0.553 k +*u +1177 265 m +1178 264 l +1177 265 l +f +*U +0.000 0.125 0.086 0.129 k +*u +1178 265 m +1179 264 l +1178 265 l +f +*U +0.000 0.702 0.494 0.298 k +*u +1193 265 m +1192 261 l +1193.656 262.404 1193.751 262.953 1193 265 c +f +*U +0.000 0.380 0.325 0.620 k +*u +1264.667 264.667 m +1264.222 264.222 1265.278 264.278 1265.333 264.333 c +1265.778 264.778 1264.722 264.722 1264.667 264.667 c +f +*U +0.000 0.282 0.153 0.063 k +*u +1266 265 m +1267 264 l +1266 265 l +f +*U +0.000 0.506 0.431 0.212 k +*u +1319 265 m +1320 264 l +1319 265 l +f +*U +0.000 0.675 0.475 0.325 k +*u +1394 265 m +1393 259 l +1394.654 261.177 1394.994 262.425 1394 265 c +f +*U +0.000 0.408 0.294 0.192 k +*u +1395 265 m +1396 264 l +1395 265 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1491 265 m +1492 264 l +1491 265 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1894 265 m +1895 264 l +1894 265 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1990 265 m +1991 264 l +1990 265 l +f +*U +0.000 0.000 0.000 0.125 k +*u +261.333 263.333 m +261.278 263.278 261.222 262.222 261.667 262.667 c +261.722 262.722 261.778 263.778 261.333 263.333 c +f +702.333 263.333 m +702.278 263.278 702.222 262.222 702.667 262.667 c +702.722 262.722 702.778 263.778 702.333 263.333 c +f +*U +0.000 0.306 0.224 0.055 k +*u +1053.333 263.333 m +1053.278 263.278 1053.222 262.222 1053.667 262.667 c +1053.722 262.722 1053.777 263.778 1053.333 263.333 c +f +*U +0.000 0.694 0.541 0.306 k +*u +1178.333 263.333 m +1178.278 263.278 1178.222 262.222 1178.667 262.667 c +1178.722 262.722 1178.777 263.778 1178.333 263.333 c +f +*U +0.000 0.494 0.341 0.000 k +*u +1192 264 m +1193 263 l +1192 264 l +f +*U +0.000 0.498 0.412 0.369 k +*u +1262 264 m +1262 260 l +1262.911 261.376 1263.404 262.440 1264 264 c +1262 264 l +f +*U +0.000 0.400 0.227 0.098 k +*u +1264 264 m +1265 263 l +1264 264 l +f +*U +0.000 0.451 0.412 0.549 k +*u +1318 264 m +1319 263 l +1318 264 l +f +*U +0.000 0.012 0.051 0.220 k +*u +1319 264 m +1320 263 l +1319 264 l +f +*U +0.000 0.196 0.129 0.094 k +*u +1326 264 m +1327 263 l +1326 264 l +f +*U +0.000 0.471 0.310 0.529 k +*u +1327.333 263.333 m +1327.278 263.278 1327.222 262.222 1327.667 262.667 c +1327.722 262.722 1327.777 263.778 1327.333 263.333 c +f +*U +0.000 0.125 0.078 0.176 k +*u +1395 264 m +1396 263 l +1395 264 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1522 264 m +1524.187 261.968 1526 260.906 1529 260 c +1526.826 262.295 1525 263.273 1522 264 c +f +*U +0.000 0.000 0.000 0.804 k +*u +1653 264 m +1654 263 l +1653 264 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1752 264 m +1753 263 l +1752 264 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1777 264 m +1778 263 l +1777 264 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1894 264 m +1895 263 l +1894 264 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1914.333 263.333 m +1914.278 263.278 1914.222 262.222 1914.667 262.667 c +1914.722 262.722 1914.777 263.778 1914.333 263.333 c +f +*U +0.000 0.000 0.000 0.102 k +*u +1990 264 m +1990.651 261.566 1991 260.717 1993 259 c +1992.251 261.254 1991.656 262.314 1990 264 c +f +*U +0.000 0.000 0.000 0.631 k +*u +262 263 m +263 262 l +262 263 l +f +*U +0.000 0.000 0.000 0.137 k +*u +611 263 m +612.402 260.726 613.515 260 616 259 c +614.394 260.914 613.217 261.837 611 263 c +f +*U +0.000 0.000 0.000 0.710 k +*u +612 263 m +613 262 l +612 263 l +f +*U +0.000 0.000 0.000 0.616 k +*u +703 263 m +704 262 l +703 263 l +f +*U +0.000 0.000 0.000 0.608 k +*u +826 263 m +827 262 l +826 263 l +f +*U +0.000 0.000 0.000 0.831 k +*u +907 263 m +908 262 l +907 263 l +f +*U +0.000 0.000 0.000 0.588 k +*u +928 263 m +929 262 l +928 263 l +f +*U +0.000 0.000 0.000 0.114 k +*u +929 263 m +929 261 l +930.635 261.545 930.455 261.365 931 263 c +929 263 l +f +*U +0.000 0.263 0.165 0.086 k +*u +1147 263 m +1148 262 l +1147 263 l +f +*U +0.000 0.424 0.325 0.463 k +*u +1179 263 m +1180.248 262.315 1180.548 262.251 1182 262 c +1180.752 262.685 1180.451 262.749 1179 263 c +f +*U +0.000 0.478 0.396 0.522 k +*u +1182.333 262.333 m +1182.278 262.278 1182.222 261.222 1182.667 261.667 c +1182.722 261.722 1182.777 262.778 1182.333 262.333 c +f +*U +0.000 0.463 0.329 0.271 k +*u +1192 263 m +1193 262 l +1192 263 l +f +*U +0.000 0.333 0.259 0.431 k +*u +1318 263 m +1319 262 l +1318 263 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1523 263 m +1524 262 l +1523 263 l +f +*U +0.000 0.000 0.000 0.529 k +*u +1541 263 m +1542 262 l +1541 263 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1753 263 m +1754 262 l +1753 263 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1893.333 262.333 m +1893.278 262.278 1893.222 261.222 1893.667 261.667 c +1893.722 261.722 1893.777 262.778 1893.333 262.333 c +f +*U +0.000 0.000 0.000 0.553 k +*u +1894 263 m +1895 262 l +1894 263 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1913 263 m +1914 262 l +1913 263 l +f +*U +0.000 0.000 0.000 0.224 k +*u +262 262 m +263 261 l +262 262 l +f +*U +0.000 0.000 0.000 0.800 k +*u +263 262 m +264 261 l +263 262 l +f +*U +0.000 0.000 0.000 0.671 k +*u +361 262 m +362 261 l +361 262 l +f +*U +0.000 0.000 0.000 0.216 k +*u +703 262 m +704 261 l +703 262 l +f +*U +0.000 0.000 0.000 0.604 k +*u +802 262 m +803 261 l +802 262 l +f +*U +0.000 0.000 0.000 0.204 k +*u +826 262 m +827 261 l +826 262 l +f +*U +0.000 0.000 0.000 0.125 k +*u +907 262 m +907.651 259.566 908 258.717 910 257 c +909.251 259.254 908.656 260.314 907 262 c +f +*U +0.000 0.157 0.106 0.173 k +*u +1136 262 m +1137 261 l +1136 262 l +f +*U +0.000 0.388 0.247 0.353 k +*u +1148 262 m +1149 261 l +1148 262 l +f +*U +0.000 0.310 0.196 0.000 k +*u +1191 262 m +1192 261 l +1191 262 l +f +*U +0.000 0.114 0.184 0.243 k +*u +1271 262 m +1272 261 l +1271 262 l +f +*U +0.000 0.573 0.408 0.392 k +*u +1303 262 m +1304.249 261.315 1304.548 261.251 1306 261 c +1304.751 261.685 1304.452 261.749 1303 262 c +f +*U +0.000 0.333 0.251 0.282 k +*u +1317 262 m +1318 261 l +1317 262 l +f +*U +0.000 0.318 0.204 0.361 k +*u +1327 262 m +1328 261 l +1327 262 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1496 262 m +1497 261 l +1496 262 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1753 262 m +1755.719 258.222 1758.644 255.688 1763 254 c +1760.264 257.575 1757 260 1753 262 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1892 262 m +1893 261 l +1892 262 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1913 262 m +1914 261 l +1913 262 l +f +*U +0.000 0.000 0.000 0.243 k +*u +263 261 m +264 260 l +263 261 l +f +*U +0.000 0.000 0.000 0.090 k +*u +825 261 m +822 255 l +824.640 256.536 825.818 257.939 825 261 c +f +*U +0.000 0.000 0.000 0.118 k +*u +930 261 m +931 258.515 931.726 257.402 934 256 c +932.906 258.357 932 259.599 930 261 c +f +*U +0.000 0.165 0.106 0.141 k +*u +1148 261 m +1149 260 l +1148 261 l +f +*U +0.000 0.545 0.416 0.357 k +*u +1182 261 m +1182.545 259.365 1182.365 259.545 1184 259 c +1184 261 l +1182 261 l +f +*U +0.000 0.125 0.110 0.204 k +*u +1190 261 m +1191 260 l +1190 261 l +f +*U +0.000 0.522 0.341 0.400 k +*u +1191 261 m +1189 260 l +1190.482 259.209 1191.796 259 1191 261 c +f +*U +0.000 0.118 0.184 0.141 k +*u +1263 261 m +1264 260 l +1263 261 l +f +*U +0.000 0.188 0.063 0.204 k +*u +1268 261 m +1269 260 l +1268 261 l +f +*U +0.000 0.549 0.325 0.451 k +*u +1269.667 260.667 m +1269.222 260.222 1270.278 260.278 1270.333 260.333 c +1270.778 260.778 1269.722 260.722 1269.667 260.667 c +f +*U +0.000 0.608 0.518 0.392 k +*u +1300 259 m +1301.580 259.683 1301.777 259.805 1303 261 c +1301.420 260.316 1301.223 260.195 1300 259 c +f +*U +0.000 0.220 0.161 0.133 k +*u +1303.667 260.667 m +1303.222 260.222 1304.278 260.278 1304.333 260.333 c +1304.778 260.778 1303.722 260.722 1303.667 260.667 c +f +*U +0.000 0.404 0.290 0.251 k +*u +1305 261 m +1306 260 l +1305 261 l +f +*U +0.000 0.639 0.451 0.275 k +*u +1313 261 m +1314.506 260.317 1315.315 260.174 1317 260 c +1315.494 260.683 1314.686 260.826 1313 261 c +f +*U +0.000 0.667 0.533 0.333 k +*u +1328 261 m +1329.450 259.392 1330 258.936 1332 258 c +1330.550 259.608 1329.948 260 1328 261 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1781 261 m +1782 260 l +1781 261 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1892 261 m +1893 260 l +1892 261 l +f +*U +0.000 0.000 0.000 0.733 k +*u +1893 261 m +1894 260 l +1893 261 l +f +*U +0.000 0.000 0.000 0.063 k +*u +1912 261 m +1911 257 l +1912.753 258.330 1913.670 259.247 1915 261 c +1912 261 l +f +*U +0.000 0.000 0.000 0.722 k +*u +2013 261 m +2014 260 l +2013 261 l +f +*U +0.000 0.000 0.000 0.098 k +*u +2014 261 m +2014.683 259.420 2014.805 259.222 2016 258 c +2015.316 259.580 2015.195 259.777 2014 261 c +f +*U +0.000 0.000 0.000 0.196 k +*u +264 260 m +265 259 l +264 260 l +f +*U +0.000 0.000 0.000 0.792 k +*u +265 260 m +266 259 l +265 260 l +f +*U +0.000 0.000 0.000 0.812 k +*u +359 260 m +360 259 l +359 260 l +f +*U +0.000 0.000 0.000 0.804 k +*u +616 260 m +617 259 l +616 260 l +f +*U +0.000 0.000 0.000 0.255 k +*u +705 260 m +706 259 l +705 260 l +f +*U +0.000 0.000 0.000 0.824 k +*u +706 260 m +707 259 l +706 260 l +f +800 260 m +801 259 l +800 260 l +f +*U +0.000 0.000 0.000 0.820 k +*u +805 260 m +806 259 l +805 260 l +f +*U +0.000 0.000 0.000 0.804 k +*u +824 260 m +825 259 l +824 260 l +f +*U +0.000 0.439 0.294 0.094 k +*u +1137 260 m +1138 259 l +1137 260 l +f +*U +0.000 0.161 0.153 0.275 k +*u +1149 260 m +1150 259 l +1149 260 l +f +*U +0.000 0.498 0.431 0.502 k +*u +1150 260 m +1151 259 l +1150 260 l +f +*U +0.000 0.494 0.329 0.094 k +*u +1184 260 m +1185 259 l +1184 260 l +f +*U +0.000 0.455 0.298 0.118 k +*u +1188 260 m +1189 259 l +1188 260 l +f +*U +0.000 0.718 0.580 0.282 k +*u +1262 260 m +1263.249 259.315 1263.548 259.251 1265 259 c +1263.752 259.685 1263.452 259.749 1262 260 c +f +*U +0.000 0.392 0.416 0.357 k +*u +1265.667 259.667 m +1265.222 259.222 1266.278 259.278 1266.333 259.333 c +1266.778 259.778 1265.722 259.722 1265.667 259.667 c +f +*U +0.000 0.729 0.671 0.271 k +*u +1266 258 m +1267.580 258.683 1267.777 258.805 1269 260 c +1267.420 259.316 1267.223 259.195 1266 258 c +f +*U +0.000 0.875 0.835 0.098 k +*u +1268 259 m +1269.809 258.426 1270 258.535 1272 259 c +1270.191 259.574 1269.931 259.465 1268 259 c +f +*U +0.000 0.455 0.314 0.196 k +*u +1307 260 m +1308 259 l +1307 260 l +f +*U +0.000 0.690 0.478 0.310 k +*u +1308 260 m +1309.249 259.315 1309.548 259.251 1311 259 c +1309.752 259.685 1309.452 259.749 1308 260 c +f +*U +0.000 0.447 0.325 0.553 k +*u +1311 260 m +1312.248 259.315 1312.548 259.251 1314 259 c +1312.752 259.685 1312.451 259.749 1311 260 c +f +*U +0.000 0.396 0.286 0.208 k +*u +1314 260 m +1315 259 l +1314 260 l +f +*U +0.000 0.329 0.239 0.055 k +*u +1315 260 m +1316 259 l +1315 260 l +f +*U +0.000 0.278 0.239 0.063 k +*u +1394.333 259.333 m +1394.278 259.278 1394.222 258.222 1394.667 258.667 c +1394.723 258.723 1394.777 259.777 1394.333 259.333 c +f +*U +0.000 0.000 0.000 0.106 k +*u +1497 260 m +1499.633 257.340 1502.414 256 1506 255 c +1503.356 257.717 1500.694 259 1497 260 c +f +*U +0.000 0.000 0.000 0.176 k +*u +1529.667 259.667 m +1529.222 259.222 1530.278 259.278 1530.333 259.333 c +1530.778 259.778 1529.722 259.722 1529.667 259.667 c +f +*U +0.000 0.000 0.000 0.310 k +*u +1891.667 259.667 m +1891.222 259.222 1892.278 259.278 1892.333 259.333 c +1892.778 259.778 1891.722 259.722 1891.667 259.667 c +f +*U +0.000 0.000 0.000 0.824 k +*u +1911 260 m +1912 259 l +1911 260 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1993 260 m +1994 259 l +1993 260 l +f +*U +0.000 0.000 0.000 0.263 k +*u +265 259 m +266 258 l +265 259 l +f +*U +0.000 0.000 0.000 0.639 k +*u +266 259 m +267 258 l +266 259 l +f +*U +0.000 0.000 0.000 0.106 k +*u +348 254 m +352.391 254.594 356 255.826 360 258 c +356.543 258.579 350.301 256.677 348 254 c +f +*U +0.000 0.000 0.000 0.110 k +*u +616 259 m +617.624 256.956 618.643 256 621 255 c +619.376 257 618.357 257.896 616 259 c +f +*U +0.000 0.000 0.000 0.094 k +*u +706 259 m +707.465 256.878 708.457 256.526 711 256 c +709.369 257.366 707.962 258 706 259 c +f +*U +0.000 0.000 0.000 0.651 k +*u +707 259 m +708 258 l +707 259 l +f +*U +0.000 0.000 0.000 0.153 k +*u +797 257 m +799.291 257.311 799.320 257.366 801 259 c +799.248 258.436 798.458 258 797 257 c +f +*U +0.000 0.310 0.224 0.247 k +*u +1054 259 m +1055 258 l +1054 259 l +f +*U +0.000 0.400 0.278 0.600 k +*u +1136.667 258.667 m +1136.222 258.222 1137.278 258.278 1137.333 258.333 c +1137.778 258.778 1136.722 258.722 1136.667 258.667 c +f +*U +0.000 0.196 0.125 0.141 k +*u +1138 259 m +1129.439 256.469 1118.901 258 1110 258 c +1055 258 l +1059.609 255.344 1068.602 257 1074 257 c +1119 257 l +1123.999 257 1129 256.941 1134 257 c +1135.998 257 1138.953 256.691 1138 259 c +f +*U +0.000 0.235 0.243 0.282 k +*u +1150 259 m +1151 258 l +1150 259 l +f +*U +0.000 0.714 0.506 0.286 k +*u +1151 259 m +1153.890 257.787 1156.874 258 1160 258 c +1157 259.213 1154 258.998 1151 259 c +f +*U +0.000 0.498 0.498 0.502 k +*u +1184 259 m +1185.506 258.317 1186.315 258.174 1188 258 c +1186.494 258.683 1185.685 258.826 1184 259 c +f +*U +0.000 0.706 0.753 0.196 k +*u +1188 259 m +1189.506 258.317 1190.315 258.174 1192 258 c +1190.494 258.683 1189.685 258.826 1188 259 c +f +*U +0.000 0.804 0.812 0.114 k +*u +1264.667 258.667 m +1264.222 258.222 1265.278 258.278 1265.333 258.333 c +1265.778 258.778 1264.722 258.722 1264.667 258.667 c +f +*U +0.000 0.667 0.451 0.333 k +*u +1296 259 m +1297.506 258.317 1298.315 258.174 1300 258 c +1298.494 258.683 1297.685 258.826 1296 259 c +f +*U +0.000 0.325 0.212 0.251 k +*u +1300 259 m +1301 258 l +1300 259 l +f +*U +0.000 0.271 0.176 0.153 k +*u +1308.667 258.667 m +1308.222 258.222 1309.278 258.278 1309.333 258.333 c +1309.778 258.778 1308.722 258.722 1308.667 258.667 c +f +*U +0.000 0.710 0.486 0.286 k +*u +1333 259 m +1334.249 258.315 1334.548 258.251 1336 258 c +1334.752 258.685 1334.451 258.749 1333 259 c +f +*U +0.000 0.808 0.627 0.192 k +*u +1384 259 m +1386.890 257.787 1389.874 258 1393 258 c +1390 259.213 1387 258.998 1384 259 c +f +*U +0.000 0.349 0.322 0.651 k +*u +1393 259 m +1394 258 l +1393 259 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1501 259 m +1502 258 l +1501 259 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1530 259 m +1531 258 l +1530 259 l +f +*U +0.000 0.000 0.000 0.169 k +*u +1531 259 m +1532.687 257.344 1533.746 256.749 1536 256 c +1534.314 257.656 1533.254 258.251 1531 259 c +f +*U +0.000 0.000 0.000 0.812 k +*u +1758 259 m +1759 258 l +1758 259 l +f +*U +0.000 0.000 0.000 0.090 k +*u +1787 259 m +1786.952 256.670 1786.796 256.994 1789 256 c +1788.308 257.389 1788 257.860 1787 259 c +f +*U +0.000 0.000 0.000 0.078 k +*u +1891 259 m +1892 258 l +1891 259 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1993 259 m +1993.684 257.420 1993.805 257.223 1995 256 c +1994.316 257.580 1994.195 257.777 1993 259 c +f +*U +0.000 0.000 0.000 0.212 k +*u +267 258 m +268 257 l +267 258 l +f +*U +0.000 0.000 0.000 0.608 k +*u +268 258 m +269 257 l +268 258 l +f +*U +0.000 0.000 0.000 0.639 k +*u +709 258 m +710 257 l +709 258 l +f +*U +0.000 0.000 0.000 0.635 k +*u +910 258 m +911 257 l +910 258 l +f +*U +0.000 0.000 0.000 0.824 k +*u +931 258 m +932 257 l +931 258 l +f +*U +0.000 0.196 0.125 0.141 k +*u +1151 258 m +1154.699 256.448 1159 257 1163 257 c +1183 257 l +1179.301 258.552 1174.983 258 1171 258 c +1151 258 l +f +*U +0.000 0.325 0.212 0.063 k +*u +1183 258 m +1185.890 256.787 1188.874 257 1192 257 c +1189 258.213 1186 257.998 1183 258 c +f +*U +0.000 0.196 0.125 0.141 k +*u +1192 258 m +1195.699 256.448 1200 257 1204 257 c +1225 257 l +1299 257 l +1295.301 258.552 1290.983 258 1287 258 c +1266 258 l +1192 258 l +f +1330 258 m +1335.707 255.605 1343.846 257 1350 257 c +1394 257 l +1388.293 259.395 1380 258 1374 258 c +1330 258 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1890.333 257.333 m +1890.278 257.278 1890.222 256.222 1890.667 256.667 c +1890.723 256.723 1890.777 257.777 1890.333 257.333 c +f +*U +0.000 0.000 0.000 0.553 k +*u +1891 258 m +1892 257 l +1891 258 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1910 258 m +1911 257 l +1910 258 l +f +*U +0.000 0.000 0.000 0.647 k +*u +2015 258 m +2016 257 l +2015 258 l +f +*U +0.000 0.000 0.000 0.055 k +*u +268 257 m +270.516 255 272.903 254.465 276 254 c +273.954 256.433 271 256.597 268 257 c +f +*U +0.000 0.000 0.000 0.678 k +*u +271 257 m +272 256 l +271 257 l +f +*U +0.000 0.000 0.000 0.671 k +*u +353 257 m +354 256 l +353 257 l +f +*U +0.000 0.000 0.000 0.639 k +*u +794 257 m +795 256 l +794 257 l +f +*U +0.000 0.000 0.000 0.082 k +*u +795 257 m +792.600 256.197 790.628 255.907 789 254 c +791 254.226 796 254.330 795 257 c +f +*U +0.000 0.000 0.000 0.251 k +*u +796 257 m +797 256 l +796 257 l +f +*U +0.000 0.000 0.000 0.161 k +*u +802 257 m +801 255.522 801 255.797 801 254 c +822 254 l +815.592 256.689 808.348 253.470 802 257 c +f +*U +0.000 0.000 0.000 0.663 k +*u +803 257 m +804 256 l +803 257 l +f +*U +0.000 0.000 0.000 0.078 k +*u +910 257 m +910.406 254.908 910.217 254.980 912 254 c +911.316 255.580 911.195 255.777 910 257 c +f +*U +0.000 0.000 0.000 0.757 k +*u +1646 257 m +1647 256 l +1646 257 l +f +*U +0.000 0.000 0.000 0.569 k +*u +1889 257 m +1890 256 l +1889 257 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1910 257 m +1909 255.521 1909 255.797 1909 254 c +1910.766 254.979 1910.956 255.222 1910 257 c +f +*U +0.000 0.000 0.000 0.565 k +*u +276 256 m +277 255 l +276 256 l +f +*U +0.000 0.000 0.000 0.827 k +*u +277 256 m +278.248 255.315 278.548 255.251 280 255 c +278.752 255.685 278.452 255.749 277 256 c +f +*U +0.000 0.000 0.000 0.847 k +*u +345 256 m +346.248 255.315 346.548 255.251 348 255 c +346.752 255.685 346.452 255.749 345 256 c +f +*U +0.000 0.000 0.000 0.157 k +*u +520 256 m +523.613 251.865 534.751 254 540 254 c +533.987 256.523 526.440 254.467 520 256 c +f +*U +0.000 0.000 0.000 0.659 k +*u +621 256 m +622 255 l +621 256 l +f +*U +0.000 0.000 0.000 0.169 k +*u +712 256 m +713.248 255.315 713.549 255.251 715 255 c +713.751 255.685 713.452 255.749 712 256 c +f +*U +0.000 0.000 0.000 0.553 k +*u +717 256 m +718 255 l +717 256 l +f +*U +0.000 0.000 0.000 0.839 k +*u +718.667 255.667 m +718.222 255.222 719.278 255.278 719.333 255.333 c +719.778 255.778 718.722 255.722 718.667 255.667 c +f +*U +0.000 0.000 0.000 0.890 k +*u +786.667 255.667 m +786.222 255.222 787.278 255.278 787.333 255.333 c +787.778 255.778 786.722 255.722 786.667 255.667 c +f +*U +0.000 0.000 0.000 0.639 k +*u +788 256 m +789 255 l +788 256 l +f +*U +0.000 0.000 0.000 0.345 k +*u +933 256 m +934 255 l +933 256 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1506 256 m +1507 255 l +1506 256 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1536.667 255.667 m +1536.222 255.222 1537.278 255.278 1537.333 255.333 c +1537.778 255.778 1536.722 255.722 1536.667 255.667 c +f +*U +0.000 0.000 0.000 0.776 k +*u +1551 256 m +1552 255 l +1551 256 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1643 256 m +1644 255 l +1643 256 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1788 256 m +1789 255 l +1788 256 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1789 256 m +1790 255 l +1789 256 l +f +1797.333 255.333 m +1797.278 255.278 1797.222 254.222 1797.667 254.667 c +1797.722 254.722 1797.778 255.778 1797.333 255.333 c +f +*U +0.000 0.000 0.000 0.208 k +*u +1889 256 m +1890 255 l +1889 256 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1995.333 255.333 m +1995.278 255.278 1995.222 254.222 1995.667 254.667 c +1995.722 254.722 1995.778 255.778 1995.333 255.333 c +f +*U +0.000 0.000 0.000 0.153 k +*u +2017 256 m +2011.881 252 2002.237 254 1996 254 c +2002.445 251.296 2012 253 2019 253 c +2018.309 254.388 2018 254.861 2017 256 c +f +*U +0.000 0.000 0.000 0.157 k +*u +276 255 m +282.436 252.299 292 254 299 254 c +348 254 l +341.564 256.701 331.951 255 325 255 c +276 255 l +f +621 255 m +624.959 253.339 629.737 254 634 254 c +630 255.661 625.263 255 621 255 c +f +717 255 m +723.436 252.299 733 254 740 254 c +789 254 l +782.564 256.701 772.951 255 766 255 c +717 255 l +f +*U +0.000 0.000 0.000 0.161 k +*u +912 255 m +918.202 252.397 927.298 254 934 254 c +927.798 256.603 918.702 255 912 255 c +f +938 255 m +945.879 251.694 958.466 254 967 254 c +1033 254 l +1025 257.306 1012.534 255 1004 255 c +938 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1506 255 m +1508.435 252.214 1512.484 253 1516 253 c +1540 253 l +1536.753 254.877 1532.729 254 1529 254 c +1521.304 253.988 1513.592 253.591 1506 255 c +f +*U +0.000 0.000 0.000 0.733 k +*u +1537 255 m +1538 254 l +1537 255 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1556 255 m +1557 254 l +1556 255 l +f +*U +0.000 0.000 0.000 0.855 k +*u +1557.667 254.667 m +1557.222 254.222 1558.278 254.278 1558.333 254.333 c +1558.778 254.778 1557.722 254.722 1557.667 254.667 c +f +*U +0.000 0.000 0.000 0.878 k +*u +1635 255 m +1636.248 254.315 1636.549 254.251 1638 254 c +1636.751 254.685 1636.452 254.749 1635 255 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1638 255 m +1639 254 l +1638 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1790 255 m +1781.715 252.551 1771.615 254 1763 254 c +1767.994 251 1778 253 1784 253 c +1786 253 1791 252.226 1790 255 c +f +*U +0.000 0.000 0.000 0.447 k +*u +1888.667 254.667 m +1888.222 254.222 1889.278 254.278 1889.333 254.333 c +1889.778 254.778 1888.722 254.722 1888.667 254.667 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1996 255 m +1997 254 l +1996 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1678 254 m +1683.715 251.602 1691.831 253 1698 253 c +1692.285 255.398 1684.169 254 1678 254 c +f +1798 254 m +1801.699 252.448 1806 253 1810 253 c +1832 253 l +1909 253 l +1905.301 254.552 1900.983 254 1897 254 c +1875 254 l +1798 254 l +f +*U +0.000 0.106 0.086 0.180 k +*u +1057 247 m +1058 246 l +1057 247 l +f +*U +0.000 0.341 0.341 0.659 k +*u +1058.333 246.333 m +1058.278 246.278 1058.222 245.222 1058.667 245.667 c +1058.722 245.722 1058.778 246.778 1058.333 246.333 c +f +*U +0.000 0.498 0.396 0.502 k +*u +1059 247 m +1061.613 245.902 1064 246 1067 246 c +1064.387 247 1061.836 246.993 1059 247 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1067 247 m +1073.678 244.198 1083.784 246 1091 246 c +1144 246 l +1137.322 248.802 1127.216 247 1120 247 c +1067 247 l +f +*U +0.000 0.498 0.380 0.502 k +*u +1144 247 m +1146 246 1147.747 246 1150 246 c +1147.948 246.874 1146.253 246.953 1144 247 c +f +*U +0.000 0.561 0.408 0.267 k +*u +1150.333 246.333 m +1150.278 246.278 1150.222 245.222 1150.667 245.667 c +1150.722 245.722 1150.778 246.778 1150.333 246.333 c +f +*U +0.000 0.263 0.184 0.424 k +*u +1161 247 m +1162 246 l +1161 247 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1162 247 m +1170 243.593 1183.203 246 1192 246 c +1258 246 l +1250 249.306 1237.534 247 1229 247 c +1162 247 l +f +*U +0.000 0.247 0.184 0.753 k +*u +1258.667 246.667 m +1258.222 246.222 1259.278 246.278 1259.333 246.333 c +1259.778 246.778 1258.722 246.722 1258.667 246.667 c +f +*U +0.000 0.035 0.024 0.267 k +*u +1260 247 m +1261 246 l +1260 247 l +f +*U +0.000 0.082 0.047 0.369 k +*u +1268 247 m +1269 246 l +1268 247 l +f +*U +0.000 0.494 0.357 0.506 k +*u +1269 247 m +1270 244 l +1274 246 l +1272.231 246.779 1270.964 246.912 1269 247 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1274 247 m +1277.958 245.339 1282.740 246 1287 246 c +1310 246 l +1306 247.661 1301.260 247 1297 247 c +1274 247 l +f +*U +0.000 0.424 0.322 0.196 k +*u +1310.333 246.333 m +1310.278 246.278 1310.222 245.222 1310.667 245.667 c +1310.722 245.722 1310.778 246.778 1310.333 246.333 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1324 247 m +1329.951 244.503 1338.580 246 1345 246 c +1391 246 l +1385 248.497 1376.420 247 1370 247 c +1324 247 l +f +*U +0.000 0.082 0.114 0.212 k +*u +1391 247 m +1392 246 l +1391 247 l +f +*U +0.000 0.882 0.639 0.118 k +*u +1059 246 m +1059.836 242.935 1060.738 237.971 1063.510 236 c +1066.366 234 1071.701 235 1075 235 c +1105 235 l +1106 240 l +1072 240 l +1079.434 242.197 1088.278 241 1096 241 c +1100.539 241 1105.529 241.903 1110 241.375 c +1116 240.662 1121.966 238.401 1128 238 c +1128 235 l +1152 235 l +1151.825 238.819 1150.848 242.292 1150 246 c +1059 246 l +f +*U +0.000 0.878 0.627 0.122 k +*u +1162 246 m +1164.772 242 1168.415 237.292 1173 235.588 c +1179.519 233.244 1189.201 235 1196 235 c +1252 235 l +1252 239 l +1250.804 238.402 1251 238.534 1250 237 c +1246.447 242 1236.560 240 1231 240 c +1176 240 l +1176 242 l +1248 242 l +1248 244 l +1168 244 l +1170.729 244.810 1173 244.979 1176 245 c +1171.783 246.769 1166.541 246 1162 246 c +f +*U +0.000 0.910 0.627 0.090 k +*u +1168 245 m +1173.951 242.503 1182.580 244 1189 244 c +1227 244 l +1234.810 244 1242.620 244.828 1250 242 c +1242.283 239.719 1233 241 1225 241 c +1176 241 l +1181.217 238.811 1188.381 240 1194 240 c +1230 240 l +1237.251 240 1244.709 241 1251 237 c +1253 243 l +1249 243 l +1249 245 l +1252.419 244.377 1254.691 243.810 1258 245 c +1250.600 248 1239 246 1231 246 c +1209.980 246 1188.944 245.173 1168 245 c +f +*U +0.000 0.525 0.388 0.475 k +*u +1258 246 m +1259 245 l +1258 246 l +f +*U +0.000 0.263 0.176 0.278 k +*u +1259 246 m +1260 245 l +1259 246 l +f +*U +0.000 0.314 0.196 0.322 k +*u +1269 246 m +1270 245 l +1269 246 l +f +*U +0.000 0.878 0.643 0.122 k +*u +1271 246 m +1272.314 241.402 1276.667 239.579 1278 235 c +1362 235 l +1370.177 235 1386.780 231.173 1388 242 c +1385.915 242 1386.276 241.862 1386 244 c +1385.317 242.494 1385.174 241.685 1385 240 c +1344 240 l +1338.621 240 1331.439 238.637 1327 242 c +1325 242 l +1323.777 240.805 1323.580 240.684 1322 240 c +1322 236 l +1318.590 238 1315.720 241 1311.985 242.441 c +1303.438 245.641 1294.926 244.796 1286 245 c +1280.970 245 1276 245.997 1271 246 c +f +*U +0.000 0.922 0.639 0.078 k +*u +1280 246 m +1285.860 243.541 1293.705 245.268 1300 244.960 c +1304.225 244.753 1307.973 243 1312 242 c +1309.645 246.492 1305.605 245.998 1301 246 c +1280 246 l +f +*U +0.000 0.275 0.200 0.027 k +*u +1323 246 m +1324 245 l +1323 246 l +f +*U +0.000 0.910 0.627 0.090 k +*u +1324 246 m +1326.236 238.589 1333.630 240 1340 240 c +1385 240 l +1385 244 l +1385.986 242.521 1386 242.797 1386 241 c +1388.179 242.539 1388.573 243.355 1389 246 c +1324 246 l +f +*U +0.000 0.710 0.510 0.290 k +*u +1389 246 m +1389 242 l +1389.911 243.377 1390.404 244.440 1391 246 c +1389 246 l +f +*U +0.000 0.569 0.396 0.431 k +*u +1058 245 m +1059 244 l +1058 245 l +f +*U +0.000 0.620 0.482 0.380 k +*u +1150 245 m +1151 240 l +1151.791 242.307 1151.475 243 1150 245 c +f +*U +0.000 0.325 0.275 0.078 k +*u +1151 245 m +1152 244 l +1151 245 l +f +*U +0.000 0.710 0.565 0.290 k +*u +1162 245 m +1164 241 l +1164.369 243.223 1163.859 243.735 1162 245 c +f +*U +0.000 0.808 0.596 0.184 k +*u +1249 245 m +1249 243 l +1251.873 242.656 1254.175 242.385 1257 243 c +1254.444 244.190 1251.805 244.702 1249 245 c +f +*U +0.000 0.541 0.416 0.459 k +*u +1257 245 m +1258 244 l +1257 245 l +f +*U +0.000 0.231 0.153 0.329 k +*u +1258 245 m +1259 244 l +1258 245 l +f +*U +0.000 0.592 0.435 0.345 k +*u +1310.667 244.667 m +1310.222 244.222 1311.278 244.278 1311.333 244.333 c +1311.778 244.778 1310.722 244.722 1310.667 244.667 c +f +*U +0.000 0.224 0.173 0.125 k +*u +1312 245 m +1313 244 l +1312 245 l +f +*U +0.000 0.310 0.310 0.690 k +*u +1322 245 m +1322.545 243.365 1322.365 243.545 1324 243 c +1324 245 l +1322 245 l +f +*U +0.000 0.318 0.231 0.333 k +*u +1390 245 m +1391 244 l +1390 245 l +f +*U +0.000 0.443 0.306 0.035 k +*u +1058 244 m +1059 243 l +1058 244 l +f +*U +0.000 0.733 0.541 0.267 k +*u +1059 244 m +1060 239 l +1060.651 241.234 1060.318 242 1059 244 c +f +*U +0.000 0.239 0.188 0.137 k +*u +1162 244 m +1163 243 l +1162 244 l +f +*U +0.000 0.361 0.239 0.318 k +*u +1270 244 m +1271 243 l +1270 244 l +f +*U +0.000 0.431 0.376 0.569 k +*u +1312 244 m +1313 243 l +1312 244 l +f +*U +0.000 0.329 0.263 0.216 k +*u +1313 244 m +1314 243 l +1313 244 l +f +*U +0.000 0.153 0.133 0.259 k +*u +1322 244 m +1323 243 l +1322 244 l +f +*U +0.000 0.878 0.675 0.114 k +*u +1326 244 m +1331.463 241.708 1339 243 1345 243 c +1384 243 l +1378.537 245.292 1370.887 244 1365 244 c +1326 244 l +f +*U +0.000 0.290 0.216 0.031 k +*u +1390 244 m +1391 243 l +1390 244 l +f +*U +0.000 0.251 0.176 0.733 k +*u +1271.333 242.333 m +1271.278 242.278 1271.222 241.222 1271.667 241.667 c +1271.722 241.722 1271.778 242.778 1271.333 242.333 c +f +*U +0.000 0.514 0.439 0.486 k +*u +1313 243 m +1314 242 l +1313 243 l +f +*U +0.000 0.322 0.251 0.180 k +*u +1314 243 m +1315 242 l +1314 243 l +f +*U +0.000 0.561 0.404 0.137 k +*u +1323 243 m +1324 242 l +1323 243 l +f +*U +0.000 0.780 0.541 0.220 k +*u +1324 243 m +1324 240 l +1325 241 1325.309 241.612 1326 243 c +1324 243 l +f +*U +0.000 0.541 0.514 0.459 k +*u +1107 242 m +1108.769 241.221 1110 241 1112 241 c +1110.231 241.779 1108.964 241.912 1107 242 c +f +*U +0.000 0.020 0.004 0.282 k +*u +1152.333 241.333 m +1152.278 241.278 1152.222 240.222 1152.667 240.667 c +1152.722 240.722 1152.778 241.778 1152.333 241.333 c +f +*U +0.000 0.827 0.627 0.157 k +*u +1176 242 m +1182.436 239.299 1192 241 1199 241 c +1250 241 l +1243.564 243.701 1233.951 242 1227 242 c +1176 242 l +f +*U +0.000 0.612 0.482 0.388 k +*u +1253 242 m +1252.278 239.582 1252 237.528 1252 235 c +1240 235 l +1243.958 233.339 1248.737 234 1253 234 c +1253.190 236.971 1253.834 239.260 1255 242 c +1253 242 l +f +*U +0.000 0.663 0.490 0.337 k +*u +1272.667 241.667 m +1272.222 241.222 1273.278 241.278 1273.333 241.333 c +1273.778 241.778 1272.722 241.722 1272.667 241.667 c +f +*U +0.000 0.482 0.459 0.518 k +*u +1314 242 m +1315 241 l +1314 242 l +f +*U +0.000 0.396 0.306 0.122 k +*u +1315 242 m +1316 241 l +1315 242 l +f +*U +0.000 0.612 0.459 0.388 k +*u +1323.333 241.333 m +1323.278 241.278 1323.223 240.222 1323.667 240.667 c +1323.722 240.722 1323.778 241.778 1323.333 241.333 c +f +*U +0.000 0.827 0.627 0.157 k +*u +1328 242 m +1333.216 239.811 1340.381 241 1346 241 c +1384 241 l +1378.783 243.189 1371.619 242 1366 242 c +1328 242 l +f +*U +0.000 0.580 0.451 0.349 k +*u +1388 242 m +1388 239 l +1388.696 240.554 1388.696 240.446 1388 242 c +f +*U +0.000 0.267 0.220 0.318 k +*u +1389 242 m +1390 241 l +1389 242 l +f +*U +0.000 0.251 0.188 0.298 k +*u +1059 241 m +1060 240 l +1059 241 l +f +*U +0.000 0.910 0.627 0.090 k +*u +1072 241 m +1075.959 239.339 1080.740 240 1085 240 c +1108 240 l +1104 241.661 1099.260 241 1095 241 c +1072 241 l +f +*U +0.000 0.310 0.169 0.075 k +*u +1108 241 m +1109 240 l +1108 241 l +f +*U +0.000 0.506 0.380 0.000 k +*u +1112 241 m +1113 240 l +1112 241 l +f +*U +0.000 0.255 0.188 0.149 k +*u +1164 241 m +1165 240 l +1164 241 l +f +*U +0.000 0.549 0.459 0.451 k +*u +1165 241 m +1166 240 l +1165 241 l +f +*U +0.000 0.427 0.322 0.122 k +*u +1273 241 m +1274 240 l +1273 241 l +f +*U +0.000 0.275 0.204 0.376 k +*u +1316 241 m +1317 240 l +1316 241 l +f +*U +0.000 0.153 0.145 0.118 k +*u +1389 241 m +1390 240 l +1389 241 l +f +*U +0.000 0.392 0.325 0.443 k +*u +1106.333 239.333 m +1106.278 239.278 1106.222 238.222 1106.667 238.667 c +1106.722 238.722 1106.778 239.778 1106.333 239.333 c +f +*U +0.000 0.290 0.247 0.102 k +*u +1107 240 m +1108 239 l +1107 240 l +f +*U +0.000 0.227 0.188 0.212 k +*u +1115 240 m +1116 239 l +1115 240 l +f +*U +0.000 0.686 0.486 0.310 k +*u +1116 240 m +1118.432 238.683 1120.248 238.723 1123 239 c +1120.668 239.985 1118.543 239.981 1116 240 c +f +*U +0.000 0.494 0.424 0.478 k +*u +1152 240 m +1152 234 l +1152.951 236.285 1152.951 237.715 1152 240 c +f +*U +0.000 0.180 0.118 0.420 k +*u +1166 240 m +1167 239 l +1166 240 l +f +*U +0.000 0.263 0.165 0.714 k +*u +1167 240 m +1168 239 l +1167 240 l +f +*U +0.000 0.231 0.137 0.035 k +*u +1253 240 m +1254 239 l +1253 240 l +f +*U +0.000 0.576 0.447 0.424 k +*u +1275.667 239.667 m +1275.222 239.222 1276.278 239.278 1276.333 239.333 c +1276.778 239.778 1275.722 239.722 1275.667 239.667 c +f +*U +0.000 0.722 0.553 0.278 k +*u +1317 240 m +1317.684 238.420 1317.804 238.223 1319 237 c +1318.316 238.580 1318.195 238.777 1317 240 c +f +*U +0.000 0.431 0.310 0.322 k +*u +1060 239 m +1061 238 l +1060 239 l +f +*U +0.000 0.561 0.478 0.439 k +*u +1061 239 m +1061 236 l +1061.696 237.554 1061.696 237.446 1061 239 c +f +*U +0.000 0.471 0.349 0.506 k +*u +1105 239 m +1105 234 l +1105.830 236 1105.830 236.970 1105 239 c +f +*U +0.000 0.329 0.282 0.165 k +*u +1118 239 m +1119 238 l +1118 239 l +f +*U +0.000 0.506 0.424 0.494 k +*u +1120 239 m +1121.248 238.315 1121.549 238.251 1123 238 c +1121.752 238.685 1121.452 238.749 1120 239 c +f +*U +0.000 0.216 0.141 0.059 k +*u +1167 239 m +1168 238 l +1167 239 l +f +*U +0.000 0.698 0.537 0.302 k +*u +1168.667 238.667 m +1168.222 238.222 1169.278 238.278 1169.333 238.333 c +1169.778 238.778 1168.722 238.722 1168.667 238.667 c +f +*U +0.000 0.369 0.267 0.212 k +*u +1276 239 m +1277 238 l +1276 239 l +f +*U +0.000 0.384 0.278 0.525 k +*u +1277.333 238.333 m +1277.278 238.278 1277.222 237.222 1277.667 237.667 c +1277.722 237.722 1277.778 238.778 1277.333 238.333 c +f +*U +0.000 0.286 0.192 0.133 k +*u +1321 239 m +1322 238 l +1321 239 l +f +*U +0.000 0.698 0.478 0.302 k +*u +1322 239 m +1321 237.521 1321 237.797 1321 236 c +1322.290 237.443 1322.401 237.234 1322 239 c +f +*U +0.000 0.271 0.204 0.059 k +*u +1388.333 238.333 m +1388.278 238.278 1388.222 237.222 1388.667 237.667 c +1388.722 237.722 1388.778 238.778 1388.333 238.333 c +f +*U +0.000 0.247 0.208 0.059 k +*u +1060 238 m +1061 237 l +1060 238 l +f +*U +0.000 0.200 0.188 0.122 k +*u +1106 238 m +1107 237 l +1106 238 l +f +*U +0.000 0.176 0.137 0.086 k +*u +1125 238 m +1126 237 l +1125 238 l +f +*U +0.000 0.635 0.471 0.365 k +*u +1126 238 m +1126.545 236.365 1126.365 236.545 1128 236 c +1128 238 l +1126 238 l +f +*U +0.000 0.325 0.271 0.318 k +*u +1169 238 m +1170 237 l +1169 238 l +f +*U +0.000 0.243 0.180 0.012 k +*u +1253 238 m +1254 237 l +1253 238 l +f +*U +0.000 0.498 0.388 0.000 k +*u +1319 238 m +1320 237 l +1319 238 l +f +*U +0.000 0.420 0.298 0.404 k +*u +1387.333 237.333 m +1387.278 237.278 1387.222 236.222 1387.667 236.667 c +1387.722 236.722 1387.778 237.778 1387.333 237.333 c +f +*U +0.000 0.373 0.282 0.012 k +*u +1126 237 m +1127 236 l +1126 237 l +f +*U +0.000 0.204 0.176 0.110 k +*u +1153 237 m +1153 234 l +1153.696 235.554 1153.696 235.446 1153 237 c +f +*U +0.000 0.318 0.286 0.227 k +*u +1170 237 m +1171 236 l +1170 237 l +f +*U +0.000 0.263 0.196 0.298 k +*u +1253 237 m +1253 234 l +1253.696 235.554 1253.696 235.446 1253 237 c +f +*U +0.000 0.482 0.478 0.518 k +*u +1277 237 m +1276 234 l +1277.766 234.979 1277.956 235.222 1277 237 c +f +*U +0.000 0.129 0.122 0.337 k +*u +1061.333 235.333 m +1061.278 235.278 1061.222 234.222 1061.667 234.667 c +1061.722 234.722 1061.778 235.778 1061.333 235.333 c +f +*U +0.000 0.420 0.325 0.580 k +*u +1062.333 235.333 m +1062.278 235.278 1062.222 234.222 1062.667 234.667 c +1062.722 234.722 1062.778 235.778 1062.333 235.333 c +f +*U +0.000 0.306 0.239 0.580 k +*u +1127.333 235.333 m +1127.278 235.278 1127.222 234.222 1127.667 234.667 c +1127.722 234.722 1127.778 235.778 1127.333 235.333 c +f +*U +0.000 0.365 0.318 0.102 k +*u +1171 236 m +1172 235 l +1171 236 l +f +*U +0.000 0.420 0.298 0.561 k +*u +1386.333 235.333 m +1386.278 235.278 1386.223 234.222 1386.667 234.667 c +1386.722 234.722 1386.778 235.778 1386.333 235.333 c +f +*U +0.000 0.227 0.173 0.227 k +*u +1387 236 m +1388 235 l +1387 236 l +f +*U +0.000 0.729 0.580 0.271 k +*u +1063 235 m +1067.215 233.231 1072.464 234 1077 234 c +1105 234 l +1100.785 235.769 1095.536 235 1091 235 c +1063 235 l +f +1128 235 m +1134.687 232.194 1144.767 234 1152 234 c +1145.313 236.806 1135.233 235 1128 235 c +f +*U +0.000 0.341 0.282 0.149 k +*u +1172 235 m +1173 234 l +1172 235 l +f +*U +0.000 0.471 0.447 0.529 k +*u +1173.667 234.667 m +1173.222 234.222 1174.278 234.278 1174.333 234.333 c +1174.778 234.778 1173.722 234.722 1173.667 234.667 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1175 235 m +1180.951 232.503 1189.580 234 1196 234 c +1240 234 l +1234 236.497 1225.420 235 1219 235 c +1175 235 l +f +*U +0.000 0.255 0.180 0.157 k +*u +1275 235 m +1276 234 l +1275 235 l +f +*U +0.000 0.729 0.580 0.271 k +*u +1278 235 m +1281.699 233.448 1286 234 1290 234 c +1311 234 l +1386 234 l +1382.301 235.552 1377.983 235 1374 235 c +1353 235 l +1278 235 l +f +*U +0.004 0.000 0.000 0.000 k +*u +1971 228 m +1969.647 227 1969.645 227.177 1968 227 c +1968 190 l +1432 190 l +1436.215 188.231 1441.464 189 1446 189 c +1473 189 l +1567 189 l +1840 189 l +1925 189 l +1939 189 1955.321 191.257 1969 188 c +1969 224 l +1969.810 221.271 1969.979 218.850 1970 216 c +1971.452 219.427 1972.263 224.480 1971 228 c +f +*U +0.000 0.204 0.137 0.133 k +*u +1973 228 m +1974 227 l +1973 228 l +f +*U +0.000 0.333 0.259 0.667 k +*u +1973 227 m +1974 226 l +1973 227 l +f +*U +0.000 0.694 0.478 0.282 k +*u +1974 227 m +1971.938 214.812 1974.578 201.484 1973 189 c +1975.477 192.270 1975.000 195.999 1975 200 c +1975 207.751 1973 218 1977 225 c +1975.814 226.186 1975.416 226.528 1974 227 c +f +*U +0.000 0.306 0.224 0.176 k +*u +1976 226 m +1977 225 l +1976 226 l +f +*U +0.000 0.318 0.227 0.337 k +*u +1977 225 m +1978 224 l +1977 225 l +f +*U +0.000 0.184 0.188 0.102 k +*u +1136 224 m +1137 223 l +1136 224 l +f +*U +0.031 0.000 0.039 0.169 k +*u +1176 224 m +1177 223 l +1176 224 l +f +*U +0.000 0.733 0.588 0.267 k +*u +1973 224 m +1973 192 l +1974.328 195 1974.000 198.581 1974 202 c +1974 208.686 1975.599 217.806 1973 224 c +f +*U +0.000 0.698 0.541 0.302 k +*u +1978.333 223.333 m +1978.278 223.278 1978.222 222.222 1978.667 222.667 c +1978.722 222.722 1978.778 223.778 1978.333 223.333 c +f +*U +0.000 0.373 0.298 0.208 k +*u +1979 224 m +1980 223 l +1979 224 l +f +*U +0.000 0.133 0.090 0.208 k +*u +1066 223 m +1067 222 l +1066 223 l +f +*U +0.000 0.329 0.298 0.671 k +*u +1067 223 m +1068 222 l +1067 223 l +f +*U +0.000 0.525 0.412 0.475 k +*u +1068 223 m +1072.969 220.915 1079.650 222 1085 222 c +1120 222 l +1115 224 1108.350 223 1103 223 c +1068 223 l +f +*U +0.000 0.141 0.078 0.224 k +*u +1120 223 m +1121 222 l +1120 223 l +f +*U +0.000 0.063 0.031 0.686 k +*u +1135 223 m +1136 222 l +1135 223 l +f +*U +0.000 0.588 0.588 0.412 k +*u +1136 223 m +1137.458 221.919 1138.248 221.564 1140 221 c +1138.457 222.267 1137.952 222.489 1136 223 c +f +*U +0.000 0.529 0.400 0.471 k +*u +1139 223 m +1143.724 221 1149.910 222 1155 222 c +1150.276 223.982 1144 223 1139 223 c +f +*U +0.000 0.224 0.192 0.337 k +*u +1155 223 m +1156 222 l +1155 223 l +f +*U +0.000 0.278 0.180 0.094 k +*u +1175.333 222.333 m +1175.278 222.278 1175.222 221.222 1175.667 221.667 c +1175.722 221.722 1175.778 222.778 1175.333 222.333 c +f +*U +0.000 0.525 0.412 0.475 k +*u +1176 223 m +1180.969 220.915 1187.650 222 1193 222 c +1207 222 1223.321 224.257 1237 221 c +1233.803 224.658 1225.577 223 1221 223 c +1176 223 l +f +*U +0.000 0.298 0.259 0.702 k +*u +1237.667 222.667 m +1237.222 222.222 1238.278 222.278 1238.333 222.333 c +1238.778 222.778 1237.722 222.722 1237.667 222.667 c +f +*U +0.000 0.118 0.122 0.196 k +*u +1239 223 m +1240 222 l +1239 223 l +f +*U +0.000 0.341 0.247 0.204 k +*u +1266 223 m +1266 220 l +1266.696 221.554 1266.696 221.446 1266 223 c +f +*U +0.000 0.525 0.412 0.475 k +*u +1267 220 m +1274.573 224.212 1286.527 222 1295 222 c +1355 222 l +1362.993 222 1373.844 223.980 1381 220 c +1382 223 l +1294 223 l +1274 223 l +1270.610 223 1267.797 223.720 1267 220 c +f +*U +0.000 0.239 0.180 0.176 k +*u +1382 223 m +1383 222 l +1382 223 l +f +*U +0.000 0.431 0.431 0.569 k +*u +1979 223 m +1980 222 l +1979 223 l +f +*U +0.000 0.416 0.325 0.329 k +*u +1980 223 m +1981 222 l +1980 223 l +f +*U +0.000 0.875 0.627 0.125 k +*u +1067 222 m +1069.303 218.837 1071.658 213.242 1075.329 211.603 c +1079.551 209.719 1086.451 211 1091 211 c +1126 211 l +1124.811 214.701 1122.757 218.979 1118.816 220.436 c +1114 222.214 1107 221 1102 221 c +1090.306 221 1078.604 220.533 1067 222 c +f +*U +0.000 0.941 0.659 0.059 k +*u +1070 222 m +1074.720 220 1080.920 221 1086 221 c +1120 221 l +1115.280 222.981 1109 222 1104 222 c +1070 222 l +f +*U +0.000 0.647 0.529 0.341 k +*u +1120.333 221.333 m +1120.278 221.278 1120.222 220.222 1120.667 220.667 c +1120.722 220.722 1120.778 221.778 1120.333 221.333 c +f +*U +0.000 0.478 0.365 0.173 k +*u +1136.667 221.667 m +1136.222 221.222 1137.278 221.278 1137.333 221.333 c +1137.778 221.778 1136.722 221.722 1136.667 221.667 c +f +*U +0.000 0.886 0.647 0.114 k +*u +1140 222 m +1141.657 220 1143.887 218.760 1145.326 216.742 c +1146.630 214.912 1146.943 212.610 1149.183 211.603 c +1152.475 210 1157.459 211 1161 211 c +1159.231 211.779 1157.964 211.912 1156 212 c +1161.382 223 1146.695 222 1140 222 c +f +*U +0.000 0.643 0.522 0.357 k +*u +1155.333 221.333 m +1155.278 221.278 1155.222 220.222 1155.667 220.667 c +1155.722 220.722 1155.778 221.778 1155.333 221.333 c +f +*U +0.000 0.875 0.627 0.125 k +*u +1176 222 m +1176 218.577 1176 214.938 1178.920 212.514 c +1181 210.636 1184.292 211 1187 211 c +1193.292 210.987 1199.722 210.628 1206 211 c +1209.773 211.310 1212.695 213.205 1216 211 c +1218.709 211.648 1221.215 211.942 1224 212 c +1224.272 220.344 1229.279 219.399 1236 221 c +1230 223.464 1223 221 1217 221 c +1203.284 220.841 1189.644 221.962 1176 222 c +f +*U +0.000 0.941 0.659 0.059 k +*u +1184 222 m +1188.215 220.231 1193.464 221 1198 221 c +1224 221 l +1219.785 222.769 1214.536 222 1210 222 c +1184 222 l +f +*U +0.000 0.416 0.298 0.361 k +*u +1237 222 m +1238 221 l +1237 222 l +f +*U +0.000 0.941 0.659 0.059 k +*u +1268 222 m +1271 218 l +1276.837 223.572 1289.407 221 1297 221 c +1368 221 l +1359.642 224.507 1346 222 1337 222 c +1268 222 l +f +*U +0.000 0.875 0.620 0.125 k +*u +1272 218 m +1271 220 l +1269.787 217 1270 214 1270 211 c +1288.808 211 1308.257 209.555 1327 211 c +1331.214 211.396 1334.743 213.694 1339 214 c +1339 211 l +1363 211 l +1366.417 211 1370.579 210.351 1373.917 211 c +1376.340 211.663 1381.961 219 1379.472 221.278 c +1378.196 222.430 1375.553 222 1374 222 c +1369.277 222 1364.736 221 1360 221 c +1301 221 l +1280 221 l +1276.470 221 1272.855 221.992 1272 218 c +f +*U +0.000 0.345 0.235 0.325 k +*u +1381 222 m +1382 221 l +1381 222 l +f +*U +0.000 0.388 0.302 0.141 k +*u +1982 222 m +1983 221 l +1982 222 l +f +*U +0.000 0.255 0.180 0.039 k +*u +1067 221 m +1068 220 l +1067 221 l +f +*U +0.000 0.482 0.329 0.416 k +*u +1068.333 220.333 m +1068.278 220.278 1068.222 219.222 1068.667 219.667 c +1068.722 219.722 1068.778 220.778 1068.333 220.333 c +f +*U +0.000 0.282 0.259 0.216 k +*u +1121 221 m +1122 220 l +1121 221 l +f +*U +0.000 0.235 0.208 0.239 k +*u +1139 221 m +1140 220 l +1139 221 l +f +*U +0.000 0.647 0.431 0.353 k +*u +1140.667 220.667 m +1140.222 220.222 1141.278 220.278 1141.333 220.333 c +1141.778 220.778 1140.722 220.722 1140.667 220.667 c +f +*U +0.000 0.365 0.298 0.153 k +*u +1156 221 m +1157 220 l +1156 221 l +f +*U +0.000 0.427 0.282 0.188 k +*u +1175 221 m +1176 220 l +1175 221 l +f +*U +0.000 0.506 0.388 0.494 k +*u +1234.667 220.667 m +1234.222 220.222 1235.278 220.278 1235.333 220.333 c +1235.778 220.778 1234.722 220.722 1234.667 220.667 c +f +*U +0.000 0.298 0.220 0.212 k +*u +1236 221 m +1237 220 l +1236 221 l +f +*U +0.000 0.259 0.180 0.067 k +*u +1381 221 m +1382 220 l +1381 221 l +f +*U +0.000 0.529 0.443 0.471 k +*u +1982.667 220.667 m +1982.222 220.222 1983.278 220.278 1983.333 220.333 c +1983.778 220.778 1982.722 220.722 1982.667 220.667 c +f +*U +0.000 0.584 0.525 0.416 k +*u +1121.333 219.333 m +1121.278 219.278 1121.222 218.222 1121.667 218.667 c +1121.722 218.722 1121.778 219.778 1121.333 219.333 c +f +*U +0.000 0.463 0.353 0.255 k +*u +1141 220 m +1142 219 l +1141 220 l +f +*U +0.000 0.678 0.635 0.267 k +*u +1156 220 m +1156.684 218.420 1156.805 218.223 1158 217 c +1157.316 218.580 1157.195 218.777 1156 220 c +f +*U +0.000 0.184 0.118 0.180 k +*u +1157 220 m +1158 219 l +1157 220 l +f +*U +0.000 0.573 0.388 0.427 k +*u +1175 220 m +1175 216 l +1175.710 217.760 1175.710 218.240 1175 220 c +f +*U +0.000 0.624 0.443 0.376 k +*u +1224 217 m +1227.412 218.446 1230.304 218.959 1234 219 c +1230.302 220.551 1226.279 220.515 1224 217 c +f +*U +0.000 0.216 0.165 0.133 k +*u +1234 220 m +1235 219 l +1234 220 l +f +*U +0.000 0.741 0.537 0.259 k +*u +1267 220 m +1269 216 l +1269.558 218.308 1268.996 218.756 1267 220 c +f +*U +0.000 0.349 0.282 0.278 k +*u +1985 220 m +1986 219 l +1985 220 l +f +*U +0.000 0.306 0.216 0.008 k +*u +1068 219 m +1069 218 l +1068 219 l +f +*U +0.000 0.431 0.302 0.443 k +*u +1069.333 218.333 m +1069.278 218.278 1069.222 217.222 1069.667 217.667 c +1069.722 217.722 1069.778 218.778 1069.333 218.333 c +f +*U +0.000 0.345 0.282 0.145 k +*u +1122 219 m +1123 218 l +1122 219 l +f +*U +0.000 0.333 0.176 0.090 k +*u +1142 219 m +1143 218 l +1142 219 l +f +*U +0.000 0.631 0.482 0.369 k +*u +1143 219 m +1146 214 l +1146.611 216.816 1145.444 217.675 1143 219 c +f +*U +0.000 0.271 0.200 0.071 k +*u +1226 219 m +1227.506 218.317 1228.314 218.174 1230 218 c +1228.494 218.683 1227.685 218.826 1226 219 c +f +*U +0.000 0.337 0.243 0.086 k +*u +1267 219 m +1268 218 l +1267 219 l +f +*U +0.000 0.722 0.592 0.278 k +*u +1986 219 m +1987.229 217 1987.868 216.777 1990 216 c +1988.607 217.434 1987.767 218 1986 219 c +f +*U +0.000 0.341 0.239 0.000 k +*u +1987 219 m +1988 218 l +1987 219 l +f +*U +0.000 0.718 0.514 0.282 k +*u +1070.333 217.333 m +1070.278 217.278 1070.222 216.222 1070.667 216.667 c +1070.722 216.722 1070.778 217.778 1070.333 217.333 c +f +*U +0.000 0.290 0.271 0.106 k +*u +1158 218 m +1159 217 l +1158 218 l +f +*U +0.000 0.239 0.216 0.141 k +*u +1225.333 217.333 m +1225.278 217.278 1225.222 216.222 1225.667 216.667 c +1225.722 216.722 1225.778 217.778 1225.333 217.333 c +f +*U +0.000 0.404 0.286 0.369 k +*u +1268 218 m +1269 217 l +1268 218 l +f +*U +0.000 0.357 0.282 0.384 k +*u +1379 218 m +1380 217 l +1379 218 l +f +*U +0.000 0.357 0.255 0.027 k +*u +1069 217 m +1070 216 l +1069 217 l +f +*U +0.000 0.118 0.165 0.325 k +*u +1123 217 m +1124 216 l +1123 217 l +f +*U +0.000 0.714 0.514 0.243 k +*u +1158 217 m +1156 212 l +1161 212 l +1160 213.962 1159.366 215.369 1158 217 c +f +*U +0.000 0.459 0.333 0.541 k +*u +1224 217 m +1224 214 l +1224.696 215.554 1224.696 215.446 1224 217 c +f +*U +0.000 0.204 0.153 0.161 k +*u +1268 217 m +1269 216 l +1268 217 l +f +*U +0.000 0.251 0.188 0.153 k +*u +1990 217 m +1991 216 l +1990 217 l +f +*U +0.000 0.616 0.475 0.384 k +*u +27 216 m +27 206 l +28.346 209.207 28.346 212.793 27 216 c +f +*U +0.000 0.271 0.176 0.612 k +*u +1070 216 m +1071 215 l +1070 216 l +f +*U +0.000 0.761 0.553 0.239 k +*u +1071 216 m +1071.526 213.457 1071.878 212.465 1074 211 c +1073.199 213 1072.503 214.337 1071 216 c +f +*U +0.000 0.227 0.145 0.133 k +*u +1124 216 m +1125 215 l +1124 216 l +f +*U +0.000 0.373 0.271 0.227 k +*u +1145 216 m +1146 215 l +1145 216 l +f +*U +0.000 0.063 0.035 0.706 k +*u +1175 216 m +1176 215 l +1175 216 l +f +*U +0.000 0.616 0.455 0.384 k +*u +1269 216 m +1269 211 l +1269.830 213 1269.830 213.970 1269 216 c +f +*U +0.000 0.494 0.369 0.506 k +*u +1377.333 215.333 m +1377.278 215.278 1377.222 214.222 1377.667 214.667 c +1377.722 214.722 1377.778 215.778 1377.333 215.333 c +f +*U +0.000 0.208 0.137 0.475 k +*u +1378 216 m +1379 215 l +1378 216 l +f +*U +0.000 0.745 0.545 0.247 k +*u +1990 216 m +1990 214 l +1992 214 l +1992 216 l +1990 216 l +f +*U +0.000 0.263 0.176 0.141 k +*u +1070 215 m +1071 214 l +1070 215 l +f +*U +0.000 0.855 0.541 0.145 k +*u +1080 215 m +1084.215 213.231 1089.465 214 1094 214 c +1120 214 l +1115.785 215.769 1110.536 215 1106 215 c +1080 215 l +f +*U +0.000 0.067 0.047 0.267 k +*u +1175 215 m +1176 214 l +1175 215 l +f +*U +0.000 0.678 0.510 0.322 k +*u +1176.667 214.667 m +1176.222 214.222 1177.278 214.278 1177.333 214.333 c +1177.778 214.778 1176.722 214.722 1176.667 214.667 c +f +*U +0.000 0.855 0.541 0.145 k +*u +1184 215 m +1190.687 212.194 1200.767 214 1208 214 c +1201.313 216.806 1191.233 215 1184 215 c +f +1272 215 m +1276.720 213 1282.920 214 1288 214 c +1320 214 l +1315.280 215.980 1309 215 1304 215 c +1272 215 l +f +*U +0.000 0.388 0.302 0.612 k +*u +1992 215 m +1993 214 l +1992 215 l +f +*U +0.000 0.333 0.263 0.149 k +*u +1993 215 m +1994 214 l +1993 215 l +f +*U +0.000 0.918 0.694 0.082 k +*u +1080 214 m +1084.215 212.231 1089.465 213 1094 213 c +1121 213 l +1116.785 214.769 1111.535 214 1107 214 c +1080 214 l +f +*U +0.000 0.400 0.275 0.231 k +*u +1125 214 m +1126 213 l +1125 214 l +f +*U +0.000 0.263 0.188 0.149 k +*u +1160 214 m +1161 213 l +1160 214 l +f +*U +0.000 0.392 0.294 0.298 k +*u +1177 214 m +1178 213 l +1177 214 l +f +*U +0.000 0.271 0.169 0.282 k +*u +1224.333 213.333 m +1224.278 213.278 1224.222 212.222 1224.667 212.667 c +1224.722 212.722 1224.778 213.778 1224.333 213.333 c +f +*U +0.000 0.678 0.510 0.322 k +*u +1333 214 m +1335 213 1336.747 213 1339 213 c +1336.948 213.874 1335.253 213.953 1333 214 c +f +*U +0.000 0.369 0.247 0.353 k +*u +1377 214 m +1378 213 l +1377 214 l +f +*U +0.000 0.459 0.333 0.384 k +*u +1993.667 213.667 m +1993.222 213.223 1994.277 213.277 1994.333 213.333 c +1994.778 213.778 1993.722 213.722 1993.667 213.667 c +f +*U +0.000 0.275 0.176 0.180 k +*u +1071 213 m +1072 212 l +1071 213 l +f +*U +0.000 0.302 0.220 0.357 k +*u +1126 213 m +1127 212 l +1126 213 l +f +*U +0.000 0.361 0.263 0.000 k +*u +1146 213 m +1147 212 l +1146 213 l +f +*U +0.000 0.306 0.224 0.396 k +*u +1161 213 m +1162 212 l +1161 213 l +f +*U +0.000 0.518 0.388 0.408 k +*u +1178.333 212.333 m +1178.278 212.278 1178.222 211.222 1178.667 211.667 c +1178.722 211.722 1178.778 212.778 1178.333 212.333 c +f +*U +0.000 0.525 0.329 0.380 k +*u +1210 211 m +1211.580 211.684 1211.777 211.805 1213 213 c +1211.420 212.316 1211.223 212.195 1210 211 c +f +*U +0.000 0.545 0.435 0.455 k +*u +1213 213 m +1214.248 212.315 1214.548 212.251 1216 212 c +1214.751 212.685 1214.452 212.749 1213 213 c +f +*U +0.000 0.502 0.357 0.345 k +*u +1332 210 m +1333 211 1333.309 211.612 1334 213 c +1331.797 212 1331.952 212.330 1332 210 c +f +*U +0.000 0.165 0.141 0.129 k +*u +1334 213 m +1335 212 l +1334 213 l +f +*U +0.000 0.439 0.310 0.165 k +*u +1338 213 m +1338 210 l +1338.696 211.554 1338.696 211.446 1338 213 c +f +*U +0.000 0.506 0.337 0.494 k +*u +1376 213 m +1377 212 l +1376 213 l +f +*U +0.000 0.380 0.275 0.306 k +*u +1996 213 m +1997 212 l +1996 213 l +f +*U +0.000 0.592 0.427 0.408 k +*u +1124 211 m +1126 210.249 1126.596 210.344 1128 212 c +1124 211 l +f +*U +0.000 0.349 0.239 0.329 k +*u +1147 212 m +1148 211 l +1147 212 l +f +*U +0.000 0.588 0.467 0.412 k +*u +1159 211 m +1161 210.249 1161.596 210.344 1163 212 c +1159 211 l +f +*U +0.000 0.416 0.298 0.294 k +*u +1163 212 m +1164 211 l +1163 212 l +f +*U +0.000 0.325 0.192 0.098 k +*u +1212 212 m +1213 211 l +1212 212 l +f +*U +0.106 0.000 0.110 0.184 k +*u +1215 212 m +1216 211 l +1215 212 l +f +*U +0.000 0.416 0.341 0.584 k +*u +1217.667 211.667 m +1217.222 211.222 1218.278 211.278 1218.333 211.333 c +1218.778 211.778 1217.722 211.722 1217.667 211.667 c +f +*U +0.000 0.659 0.443 0.341 k +*u +1219 212 m +1220.769 211.221 1222 211 1224 211 c +1222.231 211.779 1220.964 211.912 1219 212 c +f +*U +0.000 0.173 0.106 0.137 k +*u +1224 212 m +1225 211 l +1224 212 l +f +*U +0.000 0.322 0.208 0.341 k +*u +1376 212 m +1377 211 l +1376 212 l +f +*U +0.000 0.706 0.490 0.259 k +*u +1996 212 m +1997.222 210.267 1998 209.849 2000 209 c +1998.771 210.870 1998 211.224 1996 212 c +f +*U +0.000 0.251 0.188 0.153 k +*u +1998 212 m +1999 211 l +1998 212 l +f +*U +0.000 0.459 0.376 0.090 k +*u +1072 211 m +1073 210 l +1072 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1073 211 m +1077.969 208.915 1084.650 210 1090 210 c +1124 210 l +1119 212 1112.350 211 1107 211 c +1073 211 l +f +*U +0.020 0.000 0.008 0.898 k +*u +1128 211 m +1129 210 l +1128 211 l +f +*U +0.000 0.027 0.020 0.627 k +*u +1129 211 m +1130 210 l +1129 211 l +f +*U +0.000 0.020 0.016 0.255 k +*u +1130 211 m +1131 210 l +1130 211 l +f +*U +0.000 0.259 0.180 0.443 k +*u +1148 211 m +1149 210 l +1148 211 l +f +*U +0.000 0.576 0.388 0.416 k +*u +1149 211 m +1150.248 210.315 1150.548 210.251 1152 210 c +1150.752 210.685 1150.452 210.749 1149 211 c +f +*U +0.000 0.345 0.345 0.655 k +*u +1152 211 m +1154.332 210 1156.457 210 1159 210 c +1156.668 210.984 1154.543 210.981 1152 211 c +f +*U +0.000 0.161 0.153 0.839 k +*u +1163.667 210.667 m +1163.222 210.222 1164.278 210.278 1164.333 210.333 c +1164.778 210.778 1163.722 210.722 1163.667 210.667 c +f +*U +0.000 0.047 0.047 0.631 k +*u +1165 211 m +1166 210 l +1165 211 l +f +*U +0.000 0.243 0.184 0.165 k +*u +1178 211 m +1179 210 l +1178 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1179 211 m +1187.367 207.489 1200.924 210 1210 210 c +1201.633 213.511 1188 211 1179 211 c +f +*U +0.000 0.329 0.227 0.275 k +*u +1210 211 m +1211 210 l +1210 211 l +f +*U +0.000 0.145 0.129 0.267 k +*u +1221 211 m +1222.248 210.315 1222.549 210.251 1224 210 c +1222.752 210.685 1222.451 210.749 1221 211 c +f +*U +0.000 0.333 0.243 0.361 k +*u +1269 211 m +1270 210 l +1269 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1270 211 m +1275.707 208.605 1283.846 210 1290 210 c +1332 210 l +1326.293 212.395 1318 211 1312 211 c +1270 211 l +f +*U +0.000 0.533 0.435 0.467 k +*u +1339 211 m +1340.506 210.317 1341.315 210.174 1343 210 c +1341.494 210.683 1340.686 210.826 1339 211 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1343 211 m +1346.699 209.448 1351 210 1355 210 c +1376 210 l +1372.301 211.552 1367.983 211 1364 211 c +1343 211 l +f +*U +0.000 0.431 0.282 0.545 k +*u +2000 210 m +2001 209 l +2000 210 l +f +*U +0.000 0.361 0.239 0.027 k +*u +2001 210 m +2002 209 l +2001 210 l +f +*U +0.000 0.416 0.267 0.310 k +*u +2002 209 m +2003 208 l +2002 209 l +f +*U +0.000 0.455 0.333 0.349 k +*u +0.333 207.333 m +0.278 207.278 0.222 206.222 0.667 206.667 c +0.722 206.722 0.778 207.778 0.333 207.333 c +f +*U +0.000 0.651 0.482 0.349 k +*u +1 208 m +1 200 l +2 202.770 2 205.230 1 208 c +f +*U +0.000 0.537 0.498 0.388 k +*u +2002.667 207.667 m +2002.222 207.223 2003.277 207.277 2003.333 207.333 c +2003.778 207.778 2002.722 207.722 2002.667 207.667 c +f +*U +0.000 0.310 0.345 0.047 k +*u +2004 208 m +2005 207 l +2004 208 l +f +*U +0.000 0.184 0.137 0.047 k +*u +28 207 m +29 206 l +28 207 l +f +*U +0.000 0.357 0.322 0.310 k +*u +2005 207 m +2006 206 l +2005 207 l +f +*U +0.000 0.286 0.220 0.165 k +*u +0.333 205.333 m +0.278 205.278 0.222 204.222 0.667 204.667 c +0.722 204.722 0.778 205.778 0.333 205.333 c +f +*U +0.000 0.271 0.200 0.212 k +*u +28 206 m +29 205 l +28 206 l +f +*U +0.000 0.553 0.420 0.357 k +*u +2005.667 205.667 m +2005.222 205.223 2006.277 205.277 2006.333 205.333 c +2006.778 205.778 2005.722 205.722 2005.667 205.667 c +f +*U +0.000 0.510 0.396 0.180 k +*u +2007 206 m +2008 205 l +2007 206 l +f +*U +0.000 0.192 0.161 0.055 k +*u +0 204 m +1 203 l +0 204 l +f +*U +0.000 0.604 0.471 0.396 k +*u +28.333 203.333 m +28.278 203.278 28.222 202.222 28.667 202.667 c +28.722 202.722 28.778 203.778 28.333 203.333 c +f +*U +0.000 0.325 0.239 0.231 k +*u +2010 204 m +2011 203 l +2010 204 l +f +*U +0.000 0.282 0.196 0.024 k +*u +29 203 m +30 202 l +29 203 l +f +*U +0.000 0.443 0.373 0.557 k +*u +2011 203 m +2012 202 l +2011 203 l +f +*U +0.000 0.400 0.275 0.255 k +*u +29 202 m +30 201 l +29 202 l +f +*U +0.000 0.337 0.239 0.310 k +*u +2013 202 m +2014 201 l +2013 202 l +f +*U +0.000 0.435 0.290 0.439 k +*u +29 201 m +30 200 l +29 201 l +f +*U +0.000 0.376 0.267 0.482 k +*u +2014 201 m +2015 200 l +2014 201 l +f +*U +0.000 0.106 0.086 0.224 k +*u +2015 201 m +2016 200 l +2015 201 l +f +*U +0.000 0.349 0.235 0.165 k +*u +1 200 m +2 199 l +1 200 l +f +*U +0.000 0.408 0.337 0.094 k +*u +30 200 m +31 199 l +30 200 l +f +*U +0.000 0.220 0.125 0.122 k +*u +1080 200 m +1081.506 199.317 1082.315 199.174 1084 199 c +1082.494 199.683 1081.685 199.826 1080 200 c +f +*U +0.000 0.063 0.051 0.216 k +*u +1086 200 m +1087 199 l +1086 200 l +f +*U +0.000 0.208 0.078 0.118 k +*u +1088 200 m +1089.248 199.315 1089.549 199.251 1091 199 c +1089.751 199.685 1089.452 199.749 1088 200 c +f +*U +0.000 0.286 0.169 0.071 k +*u +1095 200 m +1098.699 198.448 1103 199 1107 199 c +1127 199 l +1123.301 200.552 1118.983 200 1115 200 c +1095 200 l +f +*U +0.016 0.000 0.024 0.204 k +*u +1163 200 m +1163 198 l +1164.635 198.545 1164.455 198.365 1165 200 c +1163 200 l +f +*U +0.000 0.286 0.169 0.071 k +*u +1175 200 m +1181.687 197.194 1191.767 199 1199 199 c +1192.313 201.806 1182.233 200 1175 200 c +f +*U +0.000 0.165 0.165 0.204 k +*u +1204 200 m +1205.248 199.315 1205.548 199.251 1207 199 c +1205.751 199.685 1205.452 199.749 1204 200 c +f +*U +0.004 0.000 0.024 0.212 k +*u +1266 200 m +1267 199 l +1266 200 l +f +*U +0.000 0.106 0.314 0.196 k +*u +1267 200 m +1268 199 l +1267 200 l +f +*U +0.000 0.094 0.082 0.153 k +*u +1274 200 m +1275 199 l +1274 200 l +f +*U +0.000 0.306 0.275 0.110 k +*u +1279.667 199.667 m +1279.222 199.222 1280.278 199.278 1280.333 199.333 c +1280.778 199.778 1279.722 199.722 1279.667 199.667 c +f +*U +0.000 0.063 0.016 0.200 k +*u +1298 200 m +1299.248 199.315 1299.549 199.251 1301 199 c +1299.751 199.685 1299.452 199.749 1298 200 c +f +*U +0.000 0.286 0.169 0.071 k +*u +1315 200 m +1319.724 198 1325.910 199 1331 199 c +1326.276 200.982 1320 200 1315 200 c +f +*U +0.000 0.039 0.035 0.169 k +*u +1333 200 m +1334 199 l +1333 200 l +f +*U +0.000 0.286 0.169 0.071 k +*u +1346 200 m +1350.217 198.231 1355.459 199 1360 199 c +1355.783 200.769 1350.541 200 1346 200 c +f +*U +0.000 0.125 0.122 0.157 k +*u +1365 200 m +1366.506 199.317 1367.315 199.174 1369 199 c +1367.494 199.683 1366.685 199.826 1365 200 c +f +*U +0.000 0.333 0.239 0.271 k +*u +2016 200 m +2017 199 l +2016 200 l +f +*U +0.000 0.271 0.188 0.000 k +*u +1 199 m +2 198 l +1 199 l +f +*U +0.000 0.533 0.435 0.467 k +*u +2 199 m +2 196 l +2.696 197.554 2.696 197.446 2 199 c +f +*U +0.000 0.569 0.435 0.412 k +*u +30 199 m +31 195 l +31.393 196.924 31 197.360 30 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1080 199 m +1084.188 196.579 1091 198 1096 198 c +1108.785 198 1122.402 199.339 1135 197 c +1131.914 200.531 1124.411 199 1120 199 c +1080 199 l +f +*U +0.000 0.318 0.255 0.682 k +*u +1164 199 m +1165 198 l +1164 199 l +f +*U +0.000 0.769 0.616 0.212 k +*u +1165 199 m +1166 195 l +1169 197 1171.302 197.882 1175 198 c +1171.837 199.327 1168.415 199.000 1165 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1175 199 m +1184.696 194.931 1197.633 199.468 1208 197 c +1205.565 199.786 1201.516 199.000 1198 199 c +1175 199 l +f +*U +0.000 0.310 0.263 0.180 k +*u +1266 199 m +1266 196 l +1266.696 197.554 1266.696 197.446 1266 199 c +f +*U +0.000 0.639 0.725 0.275 k +*u +1267 199 m +1267 192 l +1268 194.534 1268 196.466 1267 199 c +f +*U +0.000 0.682 0.553 0.318 k +*u +1268 199 m +1271.697 197.449 1276 198 1280 198 c +1276.303 199.551 1271.983 199 1268 199 c +f +*U +0.000 0.639 0.541 0.149 k +*u +1280 199 m +1279 197 l +1281 197 l +1281 198.853 1281.300 198.350 1280 199 c +f +*U +0.000 0.471 0.353 0.035 k +*u +1288 199 m +1289 198 l +1288 199 l +f +*U +0.000 0.514 0.380 0.239 k +*u +1289 199 m +1290 198 l +1289 199 l +f +*U +0.000 0.651 0.533 0.349 k +*u +1290 199 m +1297.409 195.891 1308.975 198 1317 198 c +1309.591 201 1298 199 1290 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1317 199 m +1321.469 197 1327.192 198 1332 198 c +1363 198 l +1358.531 199.875 1352.809 199 1348 199 c +1317 199 l +f +*U +0.000 0.812 0.592 0.188 k +*u +1361 196 m +1362.872 196 1363.612 196 1365 195 c +1366.459 196.312 1367 197.231 1368 199 c +1364.830 198.827 1362.864 198.644 1361 196 c +f +*U +0.000 0.047 0.024 0.686 k +*u +1368 199 m +1369 198 l +1368 199 l +f +*U +0.000 0.424 0.361 0.576 k +*u +2017 199 m +2018 198 l +2017 199 l +f +*U +0.000 0.251 0.184 0.220 k +*u +2018 199 m +2019 198 l +2018 199 l +f +*U +0.000 0.263 0.243 0.125 k +*u +31 198 m +32 197 l +31 198 l +f +*U +0.000 0.353 0.216 0.047 k +*u +1080 198 m +1081 197 l +1080 198 l +f +*U +0.000 0.878 0.631 0.118 k +*u +1082 198 m +1083.523 194.843 1086 189 1089.415 187.600 c +1093.757 185.574 1101.283 187 1106 187 c +1144 187 l +1144 192 l +1138.978 192.912 1135.892 197 1130.981 197.811 c +1115 200 1097.886 197.672 1082 198 c +f +*U +0.000 0.776 0.796 0.125 k +*u +1088 198 m +1090.613 196.902 1093 197 1096 197 c +1093.387 198 1090.836 197.993 1088 198 c +f +*U +0.000 0.494 0.361 0.000 k +*u +1135 198 m +1136 197 l +1135 198 l +f +*U +0.000 0.231 0.192 0.149 k +*u +1164 198 m +1165 197 l +1164 198 l +f +*U +0.000 0.875 0.627 0.125 k +*u +1167 189 m +1169.811 188.837 1172.227 187.623 1175 187.212 c +1181.456 186.259 1188.485 187 1195 187 c +1200.940 187 1207.275 186.308 1213 188 c +1211.205 191 1209.833 195 1206.695 196.972 c +1203.965 198.594 1200 198.000 1197 198 c +1178 198 l +1175.348 198.000 1170.968 198.771 1168.742 196.972 c +1166.565 195.212 1167 191.470 1167 189 c +f +*U +0.000 0.255 0.227 0.357 k +*u +1208 198 m +1209 197 l +1208 198 l +f +*U +0.000 0.867 0.624 0.133 k +*u +1268 198 m +1267.822 193.920 1267.630 190.287 1264 188 c +1267.958 186.339 1272.737 187 1277 187 c +1277.794 188.871 1279.375 191 1279.568 193 c +1280 199 1271.684 198.000 1268 198 c +f +*U +0.000 0.792 0.678 0.208 k +*u +1278 198 m +1278.901 196 1279 196 1281 195 c +1280 196.923 1279.924 196.999 1278 198 c +f +*U +0.000 0.306 0.325 0.196 k +*u +1287 198 m +1288 197 l +1287 198 l +f +*U +0.000 0.624 0.600 0.337 k +*u +1288 198 m +1287.438 196.199 1287.176 194.878 1287 193 c +1290 198 l +1288 198 l +f +*U +0.000 0.882 0.631 0.118 k +*u +1288 193 m +1307 193 l +1306.582 190.311 1306.283 189.446 1304 188 c +1308.720 186 1314.920 187 1320 187 c +1330.816 187 1344.307 184.811 1354.830 187.299 c +1359.709 188.453 1363.982 192.189 1365 197 c +1361.308 196.869 1357.750 197.975 1353.999 197.999 c +1338.334 198 1322.665 198 1307 198 c +1300.721 198 1290.249 200.410 1288 193 c +f +*U +0.000 0.020 0.008 0.278 k +*u +1368 198 m +1369 197 l +1368 198 l +f +*U +0.000 0.533 0.439 0.467 k +*u +2018 198 m +2019 197 l +2018 198 l +f +*U +0.000 0.337 0.247 0.263 k +*u +2019 198 m +2020 197 l +2019 198 l +f +*U +0.000 0.361 0.251 0.243 k +*u +1081 197 m +1082 196 l +1081 197 l +f +*U +0.000 0.502 0.353 0.478 k +*u +1082.333 196.333 m +1082.278 196.278 1082.222 195.222 1082.667 195.667 c +1082.722 195.722 1082.778 196.778 1082.333 196.333 c +f +*U +0.000 0.580 0.475 0.420 k +*u +1208 197 m +1208.684 195.420 1208.805 195.223 1210 194 c +1209.316 195.580 1209.195 195.777 1208 197 c +f +*U +0.000 0.435 0.286 0.427 k +*u +1366.333 196.333 m +1366.278 196.278 1366.222 195.222 1366.667 195.667 c +1366.722 195.722 1366.778 196.778 1366.333 196.333 c +f +*U +0.000 0.404 0.345 0.235 k +*u +1367 197 m +1368 196 l +1367 197 l +f +*U +0.000 0.514 0.388 0.486 k +*u +2020 197 m +2021 196 l +2020 197 l +f +*U +0.000 0.306 0.231 0.231 k +*u +2021 197 m +2022 196 l +2021 197 l +f +*U +0.000 0.224 0.169 0.098 k +*u +2 196 m +3 195 l +2 196 l +f +*U +0.000 0.580 0.459 0.420 k +*u +3 196 m +3 193 l +3.696 194.554 3.696 194.446 3 196 c +f +*U +0.000 0.251 0.157 0.216 k +*u +32 196 m +33 195 l +32 196 l +f +*U +0.000 0.310 0.220 0.588 k +*u +1136 196 m +1137 195 l +1136 196 l +f +*U +0.000 0.337 0.255 0.047 k +*u +1165 196 m +1166 195 l +1165 196 l +f +*U +0.000 0.412 0.329 0.204 k +*u +1266.333 195.333 m +1266.278 195.278 1266.222 194.222 1266.667 194.667 c +1266.722 194.722 1266.778 195.778 1266.333 195.333 c +f +*U +0.000 0.937 0.671 0.063 k +*u +1274 196 m +1275 193.867 1275.882 193.217 1278 192 c +1277 196 l +1274 196 l +f +*U +0.000 0.165 0.137 0.145 k +*u +1286.333 195.333 m +1286.278 195.278 1286.222 194.222 1286.667 194.667 c +1286.722 194.722 1286.777 195.778 1286.333 195.333 c +f +*U +0.000 0.404 0.310 0.514 k +*u +2021.667 195.667 m +2021.222 195.222 2022.278 195.278 2022.333 195.333 c +2022.778 195.778 2021.722 195.722 2021.667 195.667 c +f +*U +0.000 0.671 0.486 0.329 k +*u +30 195 m +31.904 193 33.534 192 36 191 c +34 193.323 32.892 194.194 30 195 c +f +*U +0.000 0.263 0.173 0.094 k +*u +33 195 m +34 194 l +33 195 l +f +*U +0.000 0.220 0.157 0.118 k +*u +1082 195 m +1083 194 l +1082 195 l +f +*U +0.000 0.553 0.427 0.447 k +*u +1083 195 m +1084 194 l +1083 195 l +f +*U +0.000 0.612 0.443 0.388 k +*u +1136.667 194.667 m +1136.222 194.222 1137.278 194.278 1137.333 194.333 c +1137.778 194.778 1136.722 194.722 1136.667 194.667 c +f +*U +0.000 0.400 0.286 0.247 k +*u +1138 195 m +1139 194 l +1138 195 l +f +*U +0.000 0.659 0.478 0.325 k +*u +1166 195 m +1165 190 l +1166.879 191.623 1166.916 192.700 1166 195 c +f +*U +0.000 0.314 0.243 0.306 k +*u +1210 195 m +1211 194 l +1210 195 l +f +*U +0.000 0.522 0.541 0.459 k +*u +1280 195 m +1280 192 l +1280.696 193.554 1280.696 193.446 1280 195 c +f +*U +0.000 0.463 0.325 0.537 k +*u +1365 195 m +1366 194 l +1365 195 l +f +*U +0.000 0.455 0.435 0.545 k +*u +2023 195 m +2024 194 l +2023 195 l +f +*U +0.000 0.212 0.137 0.267 k +*u +2024 195 m +2025 194 l +2024 195 l +f +*U +0.000 0.333 0.216 0.000 k +*u +1083 194 m +1084 193 l +1083 194 l +f +*U +0.000 0.447 0.314 0.451 k +*u +1084.333 193.333 m +1084.278 193.278 1084.222 192.222 1084.667 192.667 c +1084.722 192.722 1084.778 193.778 1084.333 193.333 c +f +*U +0.000 0.471 0.380 0.529 k +*u +1138.667 193.667 m +1138.222 193.222 1139.278 193.278 1139.333 193.333 c +1139.778 193.778 1138.722 193.722 1138.667 193.667 c +f +*U +0.000 0.361 0.259 0.200 k +*u +1140 194 m +1141 193 l +1140 194 l +f +*U +0.000 0.498 0.388 0.502 k +*u +1210 194 m +1211 193 l +1210 194 l +f +*U +0.000 0.616 0.420 0.353 k +*u +1266 194 m +1265.697 191.706 1265.421 190.788 1264 189 c +1267.458 187.697 1267 191.778 1266 194 c +f +*U +0.000 0.412 0.412 0.588 k +*u +1364 194 m +1365 193 l +1364 194 l +f +*U +0.000 0.243 0.176 0.071 k +*u +1365 194 m +1366 193 l +1365 194 l +f +*U +0.000 0.522 0.345 0.333 k +*u +2024.667 193.667 m +2024.222 193.222 2025.278 193.278 2025.333 193.333 c +2025.778 193.778 2024.722 193.722 2024.667 193.667 c +f +*U +0.000 0.349 0.231 0.078 k +*u +2026 194 m +2027 193 l +2026 194 l +f +*U +0.000 0.486 0.345 0.106 k +*u +3 193 m +4 192 l +3 193 l +f +*U +0.000 0.533 0.361 0.392 k +*u +1140 193 m +1141.248 192.315 1141.549 192.251 1143 192 c +1141.752 192.685 1141.452 192.749 1140 193 c +f +*U +0.000 0.282 0.196 0.165 k +*u +1143 193 m +1144 192 l +1143 193 l +f +*U +0.000 0.129 0.102 0.196 k +*u +1211 193 m +1212 192 l +1211 193 l +f +*U +0.000 0.208 0.161 0.227 k +*u +1287 193 m +1288 192 l +1287 193 l +f +*U +0.000 0.714 0.714 0.286 k +*u +1288 193 m +1290.332 192 1292.457 192 1295 192 c +1292.668 192.985 1290.543 192.981 1288 193 c +f +*U +0.000 0.694 0.537 0.306 k +*u +1295 193 m +1296.506 192.317 1297.315 192.174 1299 192 c +1297.494 192.683 1296.685 192.826 1295 193 c +f +*U +0.000 0.537 0.392 0.463 k +*u +1299 193 m +1300.769 192.221 1302 192 1304 192 c +1302.231 192.779 1300.964 192.912 1299 193 c +f +*U +0.000 0.769 0.561 0.231 k +*u +1304 193 m +1304.457 191 1304.581 190.792 1304 189 c +1306.905 187.905 1306.880 190.550 1307 193 c +1304 193 l +f +*U +0.000 0.306 0.345 0.271 k +*u +1364 193 m +1365 192 l +1364 193 l +f +*U +0.000 0.475 0.325 0.525 k +*u +2026 193 m +2027 192 l +2026 193 l +f +*U +0.000 0.224 0.145 0.333 k +*u +2027 193 m +2028 192 l +2027 193 l +f +*U +0.000 0.490 0.337 0.384 k +*u +4.333 191.333 m +4.278 191.278 4.222 190.222 4.667 190.667 c +4.722 190.722 4.778 191.778 4.333 191.333 c +f +*U +0.000 0.290 0.216 0.149 k +*u +36 192 m +37 191 l +36 192 l +f +*U +0.020 0.000 0.020 0.000 k +*u +46 192 m +53 188.996 64.256 191 72 191 c +130 191 l +332 191 l +1032 191 l +1024.841 194 1013.744 192 1006 192 c +948 192 l +746 192 l +46 192 l +f +*U +0.008 0.012 0.000 0.000 k +*u +56 189 m +62.919 186 73.520 188 81 188 c +138 188 l +335 188 l +804 188 l +955 188 l +982.955 188 1012.512 185.346 1040 190 c +1034.725 193 1028 189 1022 189 c +969 189 l +775 189 l +56 189 l +f +*U +0.000 0.369 0.239 0.612 k +*u +1085 192 m +1086 191 l +1085 192 l +f +*U +0.000 0.580 0.396 0.420 k +*u +1086.333 191.333 m +1086.278 191.278 1086.222 190.222 1086.667 190.667 c +1086.722 190.722 1086.778 191.778 1086.333 191.333 c +f +*U +0.000 0.325 0.325 0.675 k +*u +1144.333 191.333 m +1144.278 191.278 1144.222 190.222 1144.667 190.667 c +1144.722 190.722 1144.778 191.778 1144.333 191.333 c +f +*U +0.000 0.365 0.267 0.090 k +*u +1165 192 m +1166 191 l +1165 192 l +f +*U +0.000 0.369 0.337 0.224 k +*u +1211 192 m +1212 191 l +1211 192 l +f +*U +0.000 0.443 0.302 0.239 k +*u +1304 192 m +1305 191 l +1304 192 l +f +*U +0.000 0.384 0.259 0.518 k +*u +1361 190 m +1362.580 190.684 1362.777 190.805 1364 192 c +1362.420 191.316 1362.223 191.195 1361 190 c +f +*U +0.020 0.000 0.020 0.000 k +*u +1432 192 m +1436.720 190 1442.920 191 1448 191 c +1479 191 l +1588 191 l +1968 191 l +1963.280 192.981 1957 192 1952 192 c +1921 192 l +1812 192 l +1432 192 l +f +*U +0.000 0.349 0.255 0.031 k +*u +2029 192 m +2030 191 l +2029 192 l +f +*U +0.000 0.365 0.263 0.286 k +*u +37 191 m +38 190 l +37 191 l +f +*U +0.000 0.020 0.012 0.000 k +*u +48 191 m +55 187.996 66.256 190 74 190 c +132 190 l +333 190 l +1032 190 l +1024.841 193 1013.744 191 1006 191 c +948 191 l +747 191 l +48 191 l +f +*U +0.000 0.251 0.169 0.157 k +*u +1085 191 m +1086 190 l +1085 191 l +f +*U +0.000 0.153 0.118 0.114 k +*u +1145 191 m +1146 190 l +1145 191 l +f +*U +0.000 0.565 0.459 0.435 k +*u +1211.333 190.333 m +1211.278 190.278 1211.222 189.222 1211.667 189.667 c +1211.722 189.722 1211.778 190.778 1211.333 190.333 c +f +*U +0.000 0.388 0.290 0.039 k +*u +1278 191 m +1279 190 l +1278 191 l +f +*U +0.000 0.318 0.235 0.129 k +*u +1305 191 m +1306 190 l +1305 191 l +f +*U +0.000 0.020 0.012 0.000 k +*u +1432 191 m +1436.720 189 1442.920 190 1448 190 c +1479 190 l +1588 190 l +1968 190 l +1963.280 191.981 1957 191 1952 191 c +1921 191 l +1812 191 l +1432 191 l +f +*U +0.000 0.506 0.369 0.490 k +*u +2028.667 190.667 m +2028.222 190.223 2029.277 190.277 2029.333 190.333 c +2029.778 190.778 2028.722 190.722 2028.667 190.667 c +f +*U +0.000 0.322 0.235 0.239 k +*u +2030 191 m +2031 190 l +2030 191 l +f +*U +0.000 0.282 0.200 0.016 k +*u +4 190 m +5 189 l +4 190 l +f +*U +0.000 0.569 0.388 0.431 k +*u +5.333 189.333 m +5.278 189.278 5.222 188.222 5.667 188.667 c +5.722 188.722 5.778 189.778 5.333 189.333 c +f +*U +0.000 0.780 0.537 0.220 k +*u +37 190 m +37.980 188.217 37.908 188.406 40 188 c +38.777 189.195 38.580 189.316 37 190 c +f +*U +0.000 0.322 0.235 0.004 k +*u +39 190 m +40 189 l +39 190 l +f +*U +0.004 0.000 0.000 0.000 k +*u +44 190 m +48.869 186.970 58.251 189 64 189 c +116 189 l +310 189 l +1032 189 l +1024.841 192 1013.744 190 1006 190 c +948 190 l +745 190 l +44 190 l +f +*U +0.000 0.408 0.275 0.173 k +*u +1086 190 m +1087 189 l +1086 190 l +f +*U +0.000 0.329 0.235 0.341 k +*u +1144.333 189.333 m +1144.278 189.278 1144.222 188.222 1144.667 188.667 c +1144.722 188.722 1144.778 189.778 1144.333 189.333 c +f +*U +0.000 0.467 0.333 0.114 k +*u +1165.667 189.667 m +1165.222 189.222 1166.278 189.278 1166.333 189.333 c +1166.778 189.778 1165.722 189.722 1165.667 189.667 c +f +*U +0.000 0.384 0.384 0.616 k +*u +1168 190 m +1169 189 l +1168 190 l +f +*U +0.000 0.278 0.204 0.145 k +*u +1212 190 m +1213 189 l +1212 190 l +f +*U +0.000 0.353 0.255 0.184 k +*u +1265 190 m +1266 189 l +1265 190 l +f +*U +0.000 0.561 0.396 0.416 k +*u +1277 190 m +1275.554 187.717 1274.689 187.418 1272 187 c +1274 186 1275.747 186 1278 186 c +1277.826 187.685 1277.683 188.494 1277 190 c +f +*U +0.000 0.267 0.208 0.082 k +*u +1304 190 m +1305 189 l +1304 190 l +f +*U +0.000 0.443 0.325 0.306 k +*u +1305 190 m +1306 189 l +1305 190 l +f +*U +0.000 0.525 0.412 0.471 k +*u +1358.667 189.667 m +1358.222 189.222 1359.278 189.278 1359.333 189.333 c +1359.778 189.778 1358.722 189.722 1358.667 189.667 c +f +*U +0.000 0.318 0.204 0.294 k +*u +1360 190 m +1361 189 l +1360 190 l +f +*U +0.000 0.263 0.176 0.114 k +*u +1361 190 m +1362 189 l +1361 190 l +f +*U +0.000 0.600 0.455 0.400 k +*u +2030.667 189.667 m +2030.222 189.222 2031.278 189.278 2031.333 189.333 c +2031.778 189.778 2030.722 189.722 2030.667 189.667 c +f +*U +0.000 0.137 0.090 0.180 k +*u +2032 190 m +2033 189 l +2032 190 l +f +*U +0.000 0.439 0.298 0.553 k +*u +40 189 m +41 188 l +40 189 l +f +*U +0.000 0.400 0.275 0.314 k +*u +41 189 m +42 188 l +41 189 l +f +*U +0.000 0.290 0.204 0.027 k +*u +42 189 m +43 188 l +42 189 l +f +*U +0.000 0.376 0.243 0.408 k +*u +1087 189 m +1088 188 l +1087 189 l +f +*U +0.000 0.173 0.200 0.118 k +*u +1169 189 m +1170 188 l +1169 189 l +f +*U +0.000 0.404 0.345 0.243 k +*u +1170 189 m +1171 188 l +1170 189 l +f +*U +0.000 0.224 0.149 0.298 k +*u +1263 189 m +1264 188 l +1263 189 l +f +*U +0.000 0.141 0.145 0.392 k +*u +1303 189 m +1304 188 l +1303 189 l +f +*U +0.000 0.596 0.486 0.404 k +*u +1357.333 188.333 m +1357.278 188.278 1357.222 187.222 1357.667 187.667 c +1357.722 187.722 1357.778 188.778 1357.333 188.333 c +f +*U +0.000 0.482 0.373 0.322 k +*u +1358 189 m +1359 188 l +1358 189 l +f +*U +0.008 0.012 0.000 0.000 k +*u +1430 189 m +1434.720 187 1440.920 188 1446 188 c +1477 188 l +1587 188 l +1968 188 l +1963.280 189.981 1957 189 1952 189 c +1921 189 l +1811 189 l +1430 189 l +f +*U +0.000 0.561 0.388 0.439 k +*u +2032 189 m +2033 188 l +2032 189 l +f +*U +0.000 0.420 0.286 0.235 k +*u +2033 189 m +2034 188 l +2033 189 l +f +*U +0.000 0.365 0.239 0.035 k +*u +5 188 m +6 187 l +5 188 l +f +*U +0.000 0.604 0.467 0.396 k +*u +41 188 m +42.248 187.315 42.549 187.251 44 187 c +42.752 187.685 42.452 187.749 41 188 c +f +*U +0.000 0.392 0.278 0.353 k +*u +44 188 m +45 187 l +44 188 l +f +*U +0.000 0.216 0.161 0.110 k +*u +45 188 m +46.248 187.315 46.549 187.251 48 187 c +46.752 187.685 46.452 187.749 45 188 c +f +*U +0.000 0.192 0.149 0.671 k +*u +1144.333 187.333 m +1144.278 187.278 1144.222 186.222 1144.667 186.667 c +1144.722 186.722 1144.778 187.778 1144.333 187.333 c +f +*U +0.000 0.341 0.278 0.384 k +*u +1172 188 m +1173 187 l +1172 188 l +f +*U +0.000 0.373 0.271 0.557 k +*u +1212 188 m +1212 186 l +1214 186 l +1213.455 187.635 1213.635 187.455 1212 188 c +f +*U +0.000 0.373 0.263 0.318 k +*u +1213 188 m +1214 187 l +1213 188 l +f +*U +0.000 0.490 0.349 0.467 k +*u +1261 188 m +1262.926 185.792 1265 186 1268 186 c +1265.717 187.222 1263.572 187.652 1261 188 c +f +*U +0.000 0.365 0.278 0.047 k +*u +1301 188 m +1302 187 l +1301 188 l +f +*U +0.000 0.498 0.365 0.502 k +*u +1302 188 m +1301 186 l +1303 186 l +1303 187.853 1303.300 187.350 1302 188 c +f +*U +0.000 0.663 0.475 0.275 k +*u +1303.333 187.333 m +1303.278 187.278 1303.222 186.222 1303.667 186.667 c +1303.722 186.722 1303.778 187.778 1303.333 187.333 c +f +*U +0.000 0.341 0.278 0.204 k +*u +1358 188 m +1359 187 l +1358 188 l +f +*U +0.000 0.753 0.514 0.227 k +*u +1973 188 m +1974 184 l +1975 185.458 1975.436 186.248 1976 188 c +1973 188 l +f +*U +0.000 0.573 0.396 0.376 k +*u +2033.667 187.667 m +2033.222 187.222 2034.278 187.278 2034.333 187.333 c +2034.778 187.778 2033.722 187.722 2033.667 187.667 c +f +*U +0.000 0.271 0.200 0.200 k +*u +2035 188 m +2036 187 l +2035 188 l +f +*U +0.000 0.455 0.298 0.247 k +*u +6 187 m +7 186 l +6 187 l +f +*U +0.000 0.506 0.337 0.494 k +*u +7.333 186.333 m +7.278 186.278 7.222 185.222 7.667 185.667 c +7.722 185.722 7.778 186.778 7.333 186.333 c +f +*U +0.000 0.914 0.635 0.086 k +*u +40 186 m +44.917 182.699 54 185 60 185 c +111 185 l +303 185 l +795 185 l +953 185 l +1004 185 l +1014.283 185 1024.836 185.752 1035 184 c +1031.803 187.658 1023.577 186 1019 186 c +975 186 l +796 186 l +279 186 l +116 186 l +64 186 l +56.424 186 47.290 187.580 40 186 c +f +*U +0.000 0.655 0.494 0.345 k +*u +44 187 m +45.506 186.317 46.315 186.174 48 186 c +46.494 186.683 45.685 186.826 44 187 c +f +*U +0.000 0.525 0.424 0.475 k +*u +48 187 m +55 183.996 66.256 186 74 186 c +132 186 l +334 186 l +1035 186 l +1027.841 189 1016.744 187 1009 187 c +951 187 l +749 187 l +48 187 l +f +*U +0.000 0.325 0.239 0.475 k +*u +1035 187 m +1036 186 l +1035 187 l +f +*U +0.000 0.247 0.184 0.118 k +*u +1036 187 m +1037 186 l +1036 187 l +f +*U +0.000 0.459 0.349 0.122 k +*u +1088 187 m +1089 186 l +1088 187 l +f +*U +0.000 0.443 0.329 0.494 k +*u +1089 187 m +1094.216 184.811 1101.381 186 1107 186 c +1144 186 l +1138.783 188.189 1131.619 187 1126 187 c +1089 187 l +f +*U +0.024 0.000 0.027 0.227 k +*u +1145 187 m +1146 186 l +1145 187 l +f +*U +0.000 0.259 0.224 0.278 k +*u +1173 187 m +1174 186 l +1173 187 l +f +*U +0.000 0.443 0.329 0.494 k +*u +1174 187 m +1177.699 185.448 1182 186 1186 186 c +1209 186 l +1205.301 187.552 1200.983 187 1197 187 c +1174 187 l +f +*U +0.000 0.478 0.314 0.373 k +*u +1209 187 m +1210.248 186.315 1210.549 186.251 1212 186 c +1210.752 186.685 1210.452 186.749 1209 187 c +f +*U +0.000 0.380 0.275 0.306 k +*u +1268 187 m +1269.506 186.317 1270.315 186.174 1272 186 c +1270.494 186.683 1269.685 186.826 1268 187 c +f +*U +0.000 0.443 0.329 0.494 k +*u +1304 187 m +1308.969 184.915 1315.650 186 1321 186 c +1357 186 l +1352 188 1345.350 187 1340 187 c +1304 187 l +f +*U +0.000 0.271 0.212 0.275 k +*u +1357 187 m +1358 186 l +1357 187 l +f +*U +0.000 0.216 0.192 0.039 k +*u +1425 187 m +1426 186 l +1425 187 l +f +*U +0.000 0.306 0.243 0.271 k +*u +1426 187 m +1427 186 l +1426 187 l +f +*U +0.000 0.416 0.345 0.584 k +*u +1427 187 m +1428.506 186.317 1429.314 186.174 1431 186 c +1429.494 186.683 1428.685 186.826 1427 187 c +f +*U +0.000 0.525 0.424 0.475 k +*u +1431 187 m +1435.720 185 1441.920 186 1447 186 c +1478 186 l +1589 186 l +1973 186 l +1968.280 187.980 1962 187 1957 187 c +1926 187 l +1815 187 l +1431 187 l +f +*U +0.000 0.384 0.278 0.412 k +*u +2035.667 186.667 m +2035.222 186.222 2036.278 186.278 2036.333 186.333 c +2036.778 186.778 2035.722 186.722 2035.667 186.667 c +f +*U +0.000 0.694 0.514 0.306 k +*u +1035 186 m +1036.693 184.938 1038 184.480 1040 184 c +1038.211 185.422 1037.294 185.697 1035 186 c +f +*U +0.000 0.314 0.200 0.145 k +*u +1423 186 m +1424 185 l +1423 186 l +f +*U +0.000 0.643 0.510 0.337 k +*u +1424.667 185.667 m +1424.222 185.222 1425.278 185.278 1425.333 185.333 c +1425.778 185.778 1424.722 185.722 1424.667 185.667 c +f +*U +0.000 0.914 0.635 0.086 k +*u +1429 184 m +1436.724 185.839 1445 185 1453 185 c +1493 185 l +1623 185 l +1853 185 l +1927 185 l +1941.930 185 1957.180 185.947 1972 184 c +1969.897 186.407 1967 185.994 1964 186 c +1945 186 l +1866 186 l +1547 186 l +1459 186 l +1438 186 l +1434.683 185.999 1431.276 186.604 1429 184 c +f +*U +0.000 0.459 0.392 0.541 k +*u +2037 186 m +2038 185 l +2037 186 l +f +*U +0.000 0.349 0.263 0.082 k +*u +2038 186 m +2039 185 l +2038 186 l +f +*U +0.000 0.478 0.314 0.251 k +*u +7 185 m +8 184 l +7 185 l +f +*U +0.000 0.878 0.616 0.122 k +*u +48 185 m +55 181.996 66.256 184 74 184 c +132 184 l +333 184 l +1032 184 l +1024.841 187 1013.744 185 1006 185 c +948 185 l +747 185 l +48 185 l +f +*U +0.000 0.094 0.047 0.463 k +*u +1040 185 m +1041 184 l +1040 185 l +f +*U +0.000 0.482 0.306 0.510 k +*u +1422.667 184.667 m +1422.222 184.222 1423.278 184.278 1423.333 184.333 c +1423.778 184.778 1422.722 184.722 1422.667 184.667 c +f +*U +0.000 0.878 0.616 0.122 k +*u +1431 185 m +1435.720 183 1441.920 184 1447 184 c +1478 184 l +1587 184 l +1968 184 l +1963.280 185.981 1957 185 1952 185 c +1921 185 l +1812 185 l +1431 185 l +f +*U +0.000 0.545 0.388 0.431 k +*u +2038.667 184.667 m +2038.222 184.223 2039.277 184.277 2039.333 184.333 c +2039.778 184.778 2038.722 184.722 2038.667 184.667 c +f +*U +0.000 0.686 0.435 0.302 k +*u +8 184 m +9 181.783 10 180.606 12 179 c +11 184 l +8 184 l +f +*U +0.000 0.800 0.686 0.161 k +*u +1040 184 m +1040.684 181.791 1041 181.297 1043 180 c +1042 181.769 1041.459 182.688 1040 184 c +f +*U +0.000 0.561 0.482 0.388 k +*u +1041 184 m +1041 182 l +1043 182 l +1042.455 183.635 1042.635 183.455 1041 184 c +f +*U +0.000 0.365 0.333 0.012 k +*u +1420 184 m +1421 183 l +1420 184 l +f +*U +0.000 0.463 0.463 0.537 k +*u +1421 184 m +1422 183 l +1421 184 l +f +*U +0.000 0.502 0.498 0.475 k +*u +2040 184 m +2041 183 l +2040 184 l +f +*U +0.000 0.365 0.380 0.239 k +*u +2041 184 m +2042 183 l +2041 184 l +f +*U +0.000 0.349 0.212 0.086 k +*u +8 183 m +9 182 l +8 183 l +f +*U +0.000 0.259 0.247 0.188 k +*u +1419 183 m +1420 182 l +1419 183 l +f +*U +0.000 0.435 0.412 0.565 k +*u +1420 183 m +1421 182 l +1420 183 l +f +*U +0.000 0.439 0.365 0.459 k +*u +2041.667 182.667 m +2041.222 182.222 2042.278 182.278 2042.333 182.333 c +2042.778 182.778 2041.722 182.722 2041.667 182.667 c +f +*U +0.000 0.180 0.157 0.169 k +*u +2043 183 m +2044 182 l +2043 183 l +f +*U +0.000 0.651 0.537 0.349 k +*u +1043.333 181.333 m +1043.278 181.278 1043.222 180.222 1043.667 180.667 c +1043.722 180.722 1043.778 181.778 1043.333 181.333 c +f +*U +0.000 0.282 0.220 0.098 k +*u +1418 182 m +1419 181 l +1418 182 l +f +*U +0.000 0.686 0.529 0.314 k +*u +1419 182 m +1417.738 179.990 1416.810 178.222 1416 176 c +1418.583 177.570 1419.675 179.282 1421 182 c +1419 182 l +f +*U +0.000 0.537 0.420 0.416 k +*u +2043 182 m +2044 181 l +2043 182 l +f +*U +0.000 0.259 0.216 0.251 k +*u +2044 182 m +2045 181 l +2044 182 l +f +*U +0.000 0.235 0.212 0.176 k +*u +1044 181 m +1045 180 l +1044 181 l +f +*U +0.000 0.212 0.137 0.169 k +*u +2046 181 m +2047 180 l +2046 181 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1044 180 m +1045 179 l +1044 180 l +f +*U +0.000 0.235 0.173 0.129 k +*u +1417 180 m +1418 179 l +1417 180 l +f +*U +0.000 0.471 0.388 0.529 k +*u +2046 180 m +2047 179 l +2046 180 l +f +*U +0.000 0.376 0.231 0.318 k +*u +2047 180 m +2048 179 l +2047 180 l +f +*U +0.000 0.635 0.498 0.365 k +*u +1045.333 178.333 m +1045.278 178.278 1045.222 177.222 1045.667 177.667 c +1045.722 177.722 1045.778 178.778 1045.333 178.333 c +f +*U +0.000 0.988 0.671 0.012 k +*u +1419 179 m +1418 177.521 1418 177.797 1418 176 c +1419.290 177.443 1419.401 177.233 1419 179 c +f +*U +0.000 0.376 0.290 0.600 k +*u +2048 179 m +2049 178 l +2048 179 l +f +*U +0.000 0.322 0.259 0.075 k +*u +2049 179 m +2050 178 l +2049 179 l +f +*U +0.000 0.106 0.059 0.118 k +*u +12 178 m +13 177 l +12 178 l +f +*U +0.000 0.227 0.173 0.341 k +*u +1046 178 m +1047 177 l +1046 178 l +f +*U +0.000 0.627 0.502 0.373 k +*u +2049 178 m +2050 177 l +2049 178 l +f +*U +0.000 0.455 0.341 0.290 k +*u +2050 178 m +2051 177 l +2050 178 l +f +*U +0.000 0.290 0.188 0.078 k +*u +13 177 m +14 176 l +13 177 l +f +*U +0.000 0.447 0.329 0.553 k +*u +2050.667 176.667 m +2050.223 176.223 2051.278 176.278 2051.333 176.333 c +2051.778 176.778 2050.722 176.722 2050.667 176.667 c +f +*U +0.000 0.212 0.157 0.251 k +*u +2052 177 m +2053 176 l +2052 177 l +f +*U +0.000 0.247 0.157 0.145 k +*u +14 176 m +15 175 l +14 176 l +f +*U +0.000 0.349 0.224 0.510 k +*u +15 176 m +16 175 l +15 176 l +f +*U +0.000 0.078 0.051 0.169 k +*u +1098.333 175.333 m +1098.278 175.278 1098.222 174.222 1098.667 174.667 c +1098.722 174.722 1098.778 175.778 1098.333 175.333 c +f +*U +0.000 0.384 0.412 0.133 k +*u +1099 176 m +1103.720 174 1109.920 175 1115 175 c +1149 175 l +1144.280 176.980 1138 176 1133 176 c +1099 176 l +f +*U +0.000 0.361 0.333 0.306 k +*u +1149 176 m +1150 175 l +1149 176 l +f +*U +0.000 0.102 0.133 0.204 k +*u +1150 176 m +1151 175 l +1150 176 l +f +*U +0.000 0.384 0.412 0.133 k +*u +1185 176 m +1189.215 174.231 1194.465 175 1199 175 c +1227 175 l +1222.785 176.769 1217.536 176 1213 176 c +1185 176 l +f +*U +0.000 0.235 0.282 0.039 k +*u +1227 176 m +1228 175 l +1227 176 l +f +*U +0.000 0.318 0.251 0.141 k +*u +1256 176 m +1257.506 175.317 1258.315 175.174 1260 175 c +1258.494 175.683 1257.685 175.826 1256 176 c +f +*U +0.000 0.392 0.373 0.129 k +*u +1260 176 m +1264.217 174.231 1269.459 175 1274 175 c +1269.783 176.769 1264.541 176 1260 176 c +f +*U +0.000 0.008 0.004 0.243 k +*u +1296 176 m +1297 175 l +1296 176 l +f +*U +0.000 0.055 0.098 0.490 k +*u +1297 176 m +1298 174 l +1299.635 174.545 1299.455 174.365 1300 176 c +1297 176 l +f +*U +0.000 0.231 0.224 0.098 k +*u +1300.667 175.667 m +1300.222 175.222 1301.278 175.278 1301.333 175.333 c +1301.778 175.778 1300.722 175.722 1300.667 175.667 c +f +*U +0.000 0.384 0.412 0.133 k +*u +1302 176 m +1306.469 174 1312.191 175 1317 175 c +1348 175 l +1343.531 176.875 1337.809 176 1333 176 c +1302 176 l +f +*U +0.000 0.039 0.165 0.431 k +*u +1348.667 175.667 m +1348.222 175.222 1349.278 175.278 1349.333 175.333 c +1349.778 175.778 1348.722 175.722 1348.667 175.667 c +f +*U +0.000 0.161 0.141 0.176 k +*u +1350 176 m +1351 175 l +1350 176 l +f +*U +0.000 0.694 0.545 0.306 k +*u +1415 176 m +1413.545 173.344 1412 170.832 1411 168 c +1413.665 170.231 1415.825 172.419 1415 176 c +f +*U +0.000 0.690 0.494 0.310 k +*u +2053 176 m +2053 174 l +2055 174 l +2054.455 175.635 2054.635 175.455 2053 176 c +f +*U +0.000 0.286 0.176 0.047 k +*u +2054 176 m +2055 175 l +2054 176 l +f +*U +0.000 0.263 0.173 0.063 k +*u +15 175 m +16 174 l +15 175 l +f +*U +0.000 0.271 0.176 0.400 k +*u +1048 175 m +1049 174 l +1048 175 l +f +*U +0.000 0.510 0.384 0.490 k +*u +1099 175 m +1099.545 173.365 1099.365 173.545 1101 173 c +1101 175 l +1099 175 l +f +*U +0.000 0.910 0.663 0.082 k +*u +1101 175 m +1102 173 1103 172.260 1105 171 c +1105 175 l +1101 175 l +f +*U +0.000 0.867 0.753 0.075 k +*u +1105 175 m +1105 170 l +1107 170 l +1107 175 l +1105 175 l +f +*U +0.000 0.871 0.616 0.125 k +*u +1107 175 m +1106 169 l +1108 167 1109.547 165.421 1111 163 c +1124.682 166.257 1140.961 164 1155 164 c +1154 167.322 1153 169.275 1150 171 c +1149.461 175.291 1143.577 174 1140 174 c +1128.929 174 1118 174.657 1107 175 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1112 175 m +1115.699 173.448 1120 174 1124 174 c +1145 174 l +1141.301 175.552 1136.983 175 1133 175 c +1112 175 l +f +*U +0.000 0.678 0.525 0.286 k +*u +1145 175 m +1146.940 174 1148.898 173.561 1151 173 c +1149.266 175 1147.645 174.923 1145 175 c +f +*U +0.000 0.522 0.365 0.298 k +*u +1185.333 174.333 m +1185.278 174.278 1185.222 173.222 1185.667 173.667 c +1185.722 173.722 1185.778 174.778 1185.333 174.333 c +f +*U +0.000 0.690 0.541 0.306 k +*u +1186 173 m +1192 174 l +1189.471 175 1187.824 175 1186 173 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1192 175 m +1195.699 173.448 1200 174 1204 174 c +1225 174 l +1221.301 175.552 1216.983 175 1213 175 c +1192 175 l +f +*U +0.000 0.831 0.600 0.149 k +*u +1225 175 m +1221.309 172.204 1216.485 173 1212 173 c +1202.898 173 1194 172.648 1185 172 c +1181 165 l +1191.522 168.283 1203 167 1214 167 c +1272 167 l +1267 169 1260.362 168 1255 168 c +1258 168.900 1260.831 168.992 1264 169 c +1260.881 170.312 1257.782 169.891 1255 172 c +1252.280 170.967 1249.813 170.278 1248 168 c +1244.336 170.567 1239.395 170.445 1235 171 c +1235.980 169.217 1235.907 169.406 1238 169 c +1234.414 168.319 1230.664 168.259 1227 168 c +1228.479 168.986 1228.203 169 1230 169 c +1226 170.661 1221.260 170 1217 170 c +1192 170 l +1192 172 l +1216 172 l +1220.296 172 1224.302 171.260 1227 175 c +1225 175 l +f +*U +0.000 0.392 0.392 0.608 k +*u +1227 175 m +1228 174 l +1227 175 l +f +*U +0.000 0.655 0.518 0.322 k +*u +1228 175 m +1228.980 173.217 1228.907 173.406 1231 173 c +1229.860 174 1229.389 174.309 1228 175 c +f +*U +0.000 0.259 0.192 0.106 k +*u +1237 175 m +1238 174 l +1237 175 l +f +*U +0.000 0.757 0.588 0.243 k +*u +1238.333 174.333 m +1238.278 174.278 1238.222 173.222 1238.667 173.667 c +1238.722 173.722 1238.778 174.778 1238.333 174.333 c +f +*U +0.000 0.573 0.447 0.427 k +*u +1239 175 m +1241.836 173.693 1244.998 172.939 1248 172 c +1245.271 174.787 1242.827 174.956 1239 175 c +f +*U +0.000 0.251 0.188 0.157 k +*u +1246 175 m +1247 174 l +1246 175 l +f +*U +0.000 0.251 0.196 0.133 k +*u +1253 175 m +1254 174 l +1253 175 l +f +*U +0.000 0.486 0.380 0.365 k +*u +1254.667 174.667 m +1254.222 174.222 1255.278 174.278 1255.333 174.333 c +1255.778 174.778 1254.722 174.722 1254.667 174.667 c +f +*U +0.000 0.690 0.749 0.251 k +*u +1256 175 m +1258.613 173.902 1261 174 1264 174 c +1261.387 175 1258.835 174.993 1256 175 c +f +*U +0.000 0.749 0.847 0.145 k +*u +1264 175 m +1266.613 173.902 1269 174 1272 174 c +1269.387 175 1266.836 174.993 1264 175 c +f +*U +0.000 0.882 0.627 0.118 k +*u +1254 173 m +1256.529 169.493 1259.940 170 1264 170 c +1260.959 169 1258.169 169 1255 169 c +1259.974 166.913 1266.638 168 1272 168 c +1264.848 165.886 1256.427 167 1249 167 c +1206 167 l +1199.931 167 1186.617 169.579 1183 164 c +1250 164 l +1267 164 l +1269.301 164 1272.496 163.564 1274.471 165 c +1277.520 167.286 1276.363 172.889 1272.856 173.972 c +1267.975 175.480 1258.816 174.424 1254 173 c +f +*U +0.000 0.384 0.384 0.616 k +*u +1273 175 m +1274 174 l +1273 175 l +f +*U +0.000 0.263 0.224 0.322 k +*u +1274 175 m +1275 174 l +1274 175 l +f +*U +0.075 0.216 0.000 0.192 k +*u +1297 175 m +1298 174 l +1297 175 l +f +*U +0.000 0.631 0.639 0.361 k +*u +1299 175 m +1300.223 173.805 1300.420 173.684 1302 173 c +1300.777 174.195 1300.580 174.316 1299 175 c +f +*U +0.000 0.773 0.631 0.212 k +*u +1301.667 174.667 m +1301.222 174.222 1302.278 174.278 1302.333 174.333 c +1302.778 174.778 1301.722 174.722 1301.667 174.667 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1302 174 m +1305.985 173 1310.830 174.000 1315 174 c +1344 174 l +1340 175.661 1335.260 175 1331 175 c +1321.805 175 1310.842 176.614 1302 174 c +f +*U +0.000 0.918 0.659 0.082 k +*u +1312 174 m +1318.965 171 1329.475 173 1337 172.996 c +1340.593 172.961 1343.614 172 1346 175 c +1334.957 172.950 1323.203 174 1312 174 c +f +*U +0.000 0.788 0.616 0.212 k +*u +1346 175 m +1345 172.896 1344.954 172.248 1345 170 c +1346.840 171.717 1347.349 172.566 1348 175 c +1346 175 l +f +*U +0.000 0.580 0.522 0.306 k +*u +1348 175 m +1348 173 l +1349.635 173.545 1349.455 173.365 1350 175 c +1348 175 l +f +*U +0.000 0.408 0.325 0.224 k +*u +1414 175 m +1415 174 l +1414 175 l +f +*U +0.000 0.475 0.349 0.098 k +*u +2055 175 m +2056 174 l +2055 175 l +f +*U +0.000 0.204 0.145 0.102 k +*u +1049 174 m +1050 173 l +1049 174 l +f +*U +0.000 0.533 0.475 0.035 k +*u +1151 174 m +1152 173 l +1151 174 l +f +*U +0.000 0.918 0.659 0.082 k +*u +1186 171 m +1197.524 175.489 1212.781 173 1225 173 c +1217 176.305 1204.531 174 1196 174 c +1191.995 173.998 1188.334 174.600 1186 171 c +f +*U +0.000 0.894 0.643 0.106 k +*u +1226 174 m +1222.730 171.523 1219 172 1215 172 c +1192 172 l +1192 170 l +1230 170 l +1228.521 169 1228.797 169 1227 169 c +1230.382 167.640 1234.352 168 1238 168 c +1235 171 l +1239 170.240 1243.650 170.538 1247 168 c +1248 171 1246.257 173 1242.981 173.682 c +1237.459 174.621 1231.755 172.932 1226 174 c +f +*U +0.000 0.357 0.298 0.020 k +*u +1231 174 m +1232.769 173.221 1234 173 1236 173 c +1234.231 173.779 1232.964 173.912 1231 174 c +f +*U +0.000 0.608 0.490 0.392 k +*u +1236.667 173.667 m +1236.222 173.222 1237.278 173.278 1237.333 173.333 c +1237.778 173.778 1236.722 173.722 1236.667 173.667 c +f +*U +0.000 0.329 0.275 0.137 k +*u +1247 174 m +1248 173 l +1247 174 l +f +*U +0.000 0.388 0.314 0.125 k +*u +1252.333 173.333 m +1252.278 173.278 1252.222 172.222 1252.667 172.667 c +1252.722 172.722 1252.778 173.778 1252.333 173.333 c +f +*U +0.000 0.714 0.588 0.286 k +*u +1252 171 m +1253.923 171.902 1253.999 172 1255 174 c +1253 173 1253 172.924 1252 171 c +f +*U +0.000 0.318 0.294 0.216 k +*u +1275 174 m +1276 173 l +1275 174 l +f +*U +0.000 0.859 0.604 0.137 k +*u +1301 173 m +1302 170.237 1307.468 166.678 1304 165 c +1308 162.843 1312.478 163.944 1317 163.996 c +1327.786 164 1335.368 163.682 1345 169 c +1343 173.893 1338.660 173.000 1334 173 c +1323.230 173 1311.529 174.955 1301 173 c +f +*U +0.000 0.710 0.537 0.290 k +*u +2055 174 m +2053.964 172.813 2053.662 172.397 2053 171 c +2054.849 171.967 2055.722 172 2055 174 c +f +*U +0.016 0.008 0.000 0.741 k +*u +2056 174 m +2057 173 l +2056 174 l +f +*U +0.000 0.408 0.286 0.329 k +*u +18 173 m +19 172 l +18 173 l +f +*U +0.000 0.627 0.471 0.373 k +*u +19 173 m +20 171.543 20.543 171 22 170 c +21 172 21 172 19 173 c +f +*U +0.000 0.365 0.306 0.635 k +*u +1049 173 m +1050 172 l +1049 173 l +f +*U +0.000 0.267 0.196 0.082 k +*u +1100 173 m +1101 172 l +1100 173 l +f +*U +0.000 0.698 0.553 0.302 k +*u +1101 173 m +1103.732 169 1106.678 166 1111 164 c +1108.464 168 1105.345 171 1101 173 c +f +*U +0.000 0.651 0.471 0.349 k +*u +1150 172 m +1151.551 170 1152.855 168.218 1154 166 c +1154.785 168.916 1153.644 170.511 1152 173 c +1150 172 l +f +*U +0.000 0.208 0.188 0.302 k +*u +1182 173 m +1183 172 l +1182 173 l +f +*U +0.000 0.714 0.514 0.286 k +*u +1183 171 m +1184.580 171.684 1184.777 171.805 1186 173 c +1183.907 172.594 1183.980 172.783 1183 171 c +f +*U +0.000 0.357 0.337 0.392 k +*u +1276 173 m +1277 172 l +1276 173 l +f +*U +0.000 0.141 0.114 0.145 k +*u +1289 173 m +1290 172 l +1289 173 l +f +*U +0.000 0.384 0.310 0.106 k +*u +1300 173 m +1301 172 l +1300 173 l +f +*U +0.000 0.004 0.000 0.298 k +*u +2056 173 m +2057 172 l +2056 173 l +f +*U +0.000 0.094 0.071 0.184 k +*u +19 172 m +20 171 l +19 172 l +f +*U +0.000 0.761 0.522 0.239 k +*u +22 172 m +23.382 169.580 24.363 168.939 27 168 c +25.410 169.752 24 170.794 22 172 c +f +*U +0.000 0.655 0.525 0.345 k +*u +1050.333 171.333 m +1050.278 171.278 1050.222 170.222 1050.667 170.667 c +1050.722 170.722 1050.778 171.778 1050.333 171.333 c +f +*U +0.000 0.106 0.110 0.278 k +*u +1181 172 m +1182 171 l +1181 172 l +f +*U +0.000 0.333 0.333 0.667 k +*u +1182 172 m +1183 171 l +1182 172 l +f +*U +0.000 0.294 0.184 0.165 k +*u +1248 172 m +1249 171 l +1248 172 l +f +*U +0.000 0.271 0.243 0.188 k +*u +1251 172 m +1252 171 l +1251 172 l +f +*U +0.000 0.514 0.408 0.478 k +*u +1276 172 m +1276 169 l +1276.696 170.554 1276.696 170.446 1276 172 c +f +*U +0.000 0.322 0.271 0.424 k +*u +1287 172 m +1288 171 l +1287 172 l +f +*U +0.000 0.631 0.475 0.369 k +*u +1288 172 m +1289.248 171.315 1289.548 171.251 1291 171 c +1289.751 171.685 1289.452 171.749 1288 172 c +f +*U +0.000 0.361 0.267 0.220 k +*u +1291 172 m +1292 171 l +1291 172 l +f +*U +0.000 0.118 0.176 0.267 k +*u +1299 172 m +1300 171 l +1299 172 l +f +*U +0.000 0.275 0.275 0.725 k +*u +1300 172 m +1301 171 l +1300 172 l +f +*U +0.000 0.392 0.298 0.239 k +*u +1412 172 m +1413 171 l +1412 172 l +f +*U +0.000 0.341 0.231 0.314 k +*u +2054 172 m +2055 171 l +2054 172 l +f +*U +0.000 0.412 0.306 0.235 k +*u +1051 171 m +1052 170 l +1051 171 l +f +*U +0.000 0.800 0.784 0.122 k +*u +1182 171 m +1183 168 l +1183.685 169.249 1183.749 169.548 1184 171 c +1182 171 l +f +*U +0.000 0.557 0.435 0.443 k +*u +1248 171 m +1249.506 170.317 1250.315 170.174 1252 170 c +1250.494 170.683 1249.685 170.826 1248 171 c +f +*U +0.000 0.212 0.196 0.137 k +*u +1286 171 m +1287 170 l +1286 171 l +f +*U +0.000 0.478 0.408 0.498 k +*u +1287 171 m +1288 170 l +1287 171 l +f +*U +0.000 0.937 0.678 0.063 k +*u +1288 171 m +1287 164 l +1291 164 l +1291.262 166.428 1291.262 168.572 1291 171 c +1288 171 l +f +*U +0.000 0.627 0.475 0.373 k +*u +1291 171 m +1291 168 l +1291.696 169.554 1291.696 169.446 1291 171 c +f +*U +0.000 0.294 0.220 0.271 k +*u +1292 171 m +1293 170 l +1292 171 l +f +*U +0.000 0.294 0.208 0.314 k +*u +1300 171 m +1301 170 l +1300 171 l +f +*U +0.000 0.478 0.427 0.522 k +*u +1301 171 m +1302 170 l +1301 171 l +f +*U +0.000 0.475 0.349 0.412 k +*u +2051.667 170.667 m +2051.223 170.223 2052.278 170.278 2052.333 170.333 c +2052.778 170.778 2051.722 170.722 2051.667 170.667 c +f +*U +0.000 0.275 0.176 0.102 k +*u +2053 171 m +2054 170 l +2053 171 l +f +*U +0.000 0.114 0.090 0.173 k +*u +22 170 m +23 169 l +22 170 l +f +*U +0.000 0.337 0.247 0.027 k +*u +1052 170 m +1053 169 l +1052 170 l +f +*U +0.000 0.184 0.157 0.078 k +*u +1103 170 m +1104 169 l +1103 170 l +f +*U +0.000 0.353 0.255 0.204 k +*u +1154 170 m +1155 169 l +1154 170 l +f +*U +0.000 0.396 0.412 0.075 k +*u +1182.333 169.333 m +1182.278 169.278 1182.222 168.222 1182.667 168.667 c +1182.722 168.722 1182.778 169.778 1182.333 169.333 c +f +*U +0.000 0.322 0.208 0.059 k +*u +1277 170 m +1277 167 l +1277.696 168.554 1277.696 168.446 1277 170 c +f +*U +0.000 0.314 0.275 0.290 k +*u +1286 170 m +1287 169 l +1286 170 l +f +*U +0.000 0.722 0.596 0.278 k +*u +1287.333 169.333 m +1287.278 169.278 1287.222 168.222 1287.667 168.667 c +1287.722 168.722 1287.778 169.778 1287.333 169.333 c +f +*U +0.000 0.522 0.376 0.400 k +*u +1292 170 m +1292 165 l +1292.830 167 1292.830 167.969 1292 170 c +f +*U +0.000 0.667 0.592 0.333 k +*u +1302.667 169.667 m +1302.222 169.222 1303.278 169.278 1303.333 169.333 c +1303.778 169.778 1302.722 169.722 1302.667 169.667 c +f +*U +0.000 0.584 0.427 0.349 k +*u +2049 170 m +2048 168 l +2050 168 l +2050 169.853 2050.300 169.350 2049 170 c +f +*U +0.000 0.396 0.380 0.604 k +*u +2050 170 m +2051 169 l +2050 170 l +f +*U +0.000 0.310 0.255 0.290 k +*u +2051 170 m +2052 169 l +2051 170 l +f +*U +0.000 0.686 0.506 0.031 k +*u +24 169 m +25 168 l +24 169 l +f +*U +0.000 0.882 0.635 0.118 k +*u +54 169 m +60.919 166 71.520 168 79 168 c +136 168 l +333 168 l +1016 168 l +1009 170.903 998.480 169 991 169 c +934 169 l +737 169 l +54 169 l +f +*U +0.000 0.655 0.455 0.314 k +*u +1052 169 m +1053.523 164.519 1056.174 161.720 1060 159 c +1058 163 1055.451 166.215 1052 169 c +f +*U +0.000 0.584 0.337 0.000 k +*u +1104 169 m +1105 168 l +1104 169 l +f +*U +0.000 0.478 0.380 0.522 k +*u +1286 169 m +1286 163 l +1286.951 165.285 1286.951 166.715 1286 169 c +f +*U +0.000 0.361 0.282 0.243 k +*u +1303 169 m +1304 168 l +1303 169 l +f +*U +0.431 0.000 0.184 0.000 k +*u +1344 169 m +1345 168 l +1344 169 l +f +*U +0.000 0.263 0.212 0.220 k +*u +1410 169 m +1411 168 l +1410 169 l +f +*U +0.000 0.882 0.635 0.118 k +*u +1449 169 m +1453.469 167 1459.191 168 1464 168 c +1494 168 l +1600 168 l +1967 168 l +1962.531 169.875 1956.809 169 1952 169 c +1922 169 l +1816 169 l +1449 169 l +f +*U +0.000 0.282 0.220 0.082 k +*u +2050 169 m +2051 168 l +2050 169 l +f +*U +0.000 0.204 0.133 0.118 k +*u +26 168 m +27 167 l +26 168 l +f +*U +0.000 0.510 0.431 0.490 k +*u +27.667 167.667 m +27.222 167.222 28.278 167.278 28.333 167.333 c +28.778 167.778 27.722 167.722 27.667 167.667 c +f +*U +0.000 0.882 0.627 0.118 k +*u +48 168 m +55.782 163.635 65.383 165 74 165 c +125 165 l +317 165 l +1020 165 l +1012.841 168 1001.744 166 994 166 c +937 166 l +737 166 l +512.682 166 288.312 164.556 64 166 c +58.486 166 53.541 167.981 48 168 c +f +*U +0.000 0.831 0.600 0.149 k +*u +56 168 m +63 164.996 74.256 167 82 167 c +139 167 l +337 167 l +1026 167 l +1018.841 170 1007.744 168 1000 168 c +943 168 l +744 168 l +56 168 l +f +*U +0.000 0.478 0.373 0.502 k +*u +1276 168 m +1276 165 l +1276.696 166.554 1276.696 166.446 1276 168 c +f +*U +0.000 0.078 0.047 0.184 k +*u +1285 168 m +1286 167 l +1285 168 l +f +*U +0.000 0.388 0.243 0.188 k +*u +1304 168 m +1305 167 l +1304 168 l +f +*U +0.000 0.467 0.467 0.533 k +*u +1341 168 m +1342 167 l +1341 168 l +f +*U +0.000 0.251 0.259 0.435 k +*u +1342 168 m +1343 167 l +1342 168 l +f +*U +0.000 0.310 0.267 0.129 k +*u +1409 168 m +1410 167 l +1409 168 l +f +*U +0.000 0.561 0.427 0.357 k +*u +1410 168 m +1409 166.521 1409 166.797 1409 165 c +1410.289 166.443 1410.401 166.234 1410 168 c +f +*U +0.000 0.831 0.600 0.149 k +*u +1448 168 m +1452.469 166 1458.191 167 1463 167 c +1494 167 l +1600 167 l +1968 167 l +1963.531 168.875 1957.809 168 1953 168 c +1922 168 l +1816 168 l +1448 168 l +f +*U +0.000 0.737 0.561 0.263 k +*u +2042 164 m +2044.222 164.810 2045.990 165.739 2048 167 c +2045 167.698 2043.578 166.511 2042 164 c +f +*U +0.063 0.000 0.012 0.278 k +*u +2048 168 m +2049 167 l +2048 168 l +f +*U +0.000 0.259 0.196 0.106 k +*u +28 167 m +29 166 l +28 167 l +f +*U +0.000 0.502 0.420 0.498 k +*u +29.667 166.667 m +29.222 166.222 30.278 166.278 30.333 166.333 c +30.778 166.778 29.722 166.722 29.667 166.667 c +f +*U +0.000 0.906 0.655 0.094 k +*u +56 167 m +63 163.996 74.256 166 82 166 c +139 166 l +337 166 l +1024 166 l +1016.841 169 1005.744 167 998 167 c +941 167 l +743 167 l +56 167 l +f +*U +0.000 0.208 0.247 0.267 k +*u +1155 167 m +1156 166 l +1155 167 l +f +*U +0.000 0.345 0.263 0.212 k +*u +1180.667 166.667 m +1180.222 166.222 1181.278 166.278 1181.333 166.333 c +1181.778 166.778 1180.722 166.722 1180.667 166.667 c +f +*U +0.000 0.667 0.494 0.333 k +*u +1291 167 m +1289.774 164.965 1289.298 164.674 1287 164 c +1288.769 163.221 1290 163 1292 163 c +1291.826 164.685 1291.683 165.494 1291 167 c +f +*U +0.000 0.482 0.447 0.118 k +*u +1306 167 m +1307 166 l +1306 167 l +f +*U +0.000 0.412 0.345 0.412 k +*u +1340.667 166.667 m +1340.222 166.222 1341.278 166.278 1341.333 166.333 c +1341.778 166.778 1340.722 166.722 1340.667 166.667 c +f +*U +0.000 0.906 0.655 0.094 k +*u +1448 167 m +1452.469 165 1458.191 166 1463 166 c +1494 166 l +1600 166 l +1968 166 l +1963.531 167.875 1957.809 167 1953 167 c +1922 167 l +1816 167 l +1448 167 l +f +*U +0.000 0.220 0.176 0.102 k +*u +31 166 m +32 165 l +31 166 l +f +*U +0.000 0.584 0.424 0.400 k +*u +32 166 m +33.248 165.315 33.548 165.251 35 165 c +33.752 165.685 33.452 165.749 32 166 c +f +*U +0.000 0.400 0.286 0.212 k +*u +1055 166 m +1056 165 l +1055 166 l +f +*U +0.000 0.580 0.459 0.349 k +*u +1155.333 165.333 m +1155.278 165.278 1155.222 164.222 1155.667 164.667 c +1155.722 164.722 1155.778 165.778 1155.333 165.333 c +f +*U +0.000 0.553 0.467 0.447 k +*u +1178 163 m +1181 165 l +1178.860 166 1178.473 165.251 1178 163 c +f +*U +0.000 0.290 0.345 0.243 k +*u +1304 166 m +1305 165 l +1304 166 l +f +*U +0.000 0.592 0.490 0.333 k +*u +1305.667 165.667 m +1305.222 165.222 1306.278 165.278 1306.333 165.333 c +1306.778 165.778 1305.722 165.722 1305.667 165.667 c +f +*U +0.000 0.573 0.482 0.427 k +*u +1339 166 m +1340 165 l +1339 166 l +f +*U +0.000 0.318 0.271 0.259 k +*u +1340 166 m +1341 165 l +1340 166 l +f +*U +0.000 0.408 0.329 0.247 k +*u +1408 166 m +1409 165 l +1408 166 l +f +*U +0.000 0.882 0.627 0.118 k +*u +1448 166 m +1452.469 164 1458.191 165 1463 165 c +1493 165 l +1597 165 l +1851 165 l +1933 165 l +1945.430 165 1959.861 162.946 1972 165 c +1967.531 166.875 1961.809 166 1957 166 c +1926 166 l +1819 166 l +1448 166 l +f +*U +0.000 0.357 0.278 0.125 k +*u +2045 166 m +2046 165 l +2045 166 l +f +*U +0.000 0.216 0.161 0.176 k +*u +34 165 m +35 164 l +34 165 l +f +*U +0.000 0.667 0.525 0.333 k +*u +35 165 m +36.769 164.221 38 164 40 164 c +38.231 164.779 36.964 164.912 35 165 c +f +*U +0.000 0.871 0.616 0.125 k +*u +56 165 m +61.707 162.605 69.846 164 76 164 c +120 164 l +273 164 l +803 164 l +974 164 l +988.325 164 1002.677 164.265 1016.999 163.995 c +1022.983 163.883 1026.670 158.761 1032 163 c +1024.402 166.657 1014.282 165 1006 165 c +951 165 l +755 165 l +56 165 l +f +*U +0.000 0.094 0.086 0.192 k +*u +1056 165 m +1057 164 l +1056 165 l +f +*U +0.000 0.255 0.176 0.118 k +*u +1177.333 164.333 m +1177.278 164.278 1177.222 163.222 1177.667 163.667 c +1177.722 163.722 1177.778 164.778 1177.333 164.333 c +f +*U +0.000 0.992 0.753 0.000 k +*u +1179 165 m +1180.506 164.317 1181.315 164.174 1183 164 c +1181.494 164.683 1180.685 164.826 1179 165 c +f +*U +0.000 0.490 0.345 0.490 k +*u +1275.333 164.333 m +1275.278 164.278 1275.222 163.222 1275.667 163.667 c +1275.722 163.722 1275.778 164.778 1275.333 164.333 c +f +*U +0.000 0.369 0.267 0.231 k +*u +1276 165 m +1277 164 l +1276 165 l +f +*U +0.000 0.302 0.231 0.267 k +*u +1292.333 164.333 m +1292.278 164.278 1292.222 163.222 1292.667 163.667 c +1292.722 163.722 1292.778 164.778 1292.333 164.333 c +f +*U +0.000 0.329 0.267 0.196 k +*u +1301 165 m +1302 164 l +1301 165 l +f +*U +0.000 0.706 0.678 0.251 k +*u +1299 164 m +1301 163 1302.747 163 1305 163 c +1302.817 164.430 1301.625 164.328 1299 164 c +f +*U +0.000 0.729 0.549 0.271 k +*u +1310 164 m +1316.988 161 1331.781 161.866 1339 164 c +1330.505 166 1318.899 164 1310 164 c +f +*U +0.000 0.325 0.278 0.384 k +*u +1339 165 m +1340 164 l +1339 165 l +f +*U +0.000 0.192 0.125 0.129 k +*u +1407 165 m +1408 164 l +1407 165 l +f +*U +0.000 0.871 0.616 0.125 k +*u +1448 165 m +1452.469 163 1458.191 164 1463 164 c +1494 164 l +1600 164 l +1969 164 l +1964.531 165.875 1958.809 165 1954 165 c +1923 165 l +1817 165 l +1448 165 l +f +*U +0.000 0.259 0.188 0.224 k +*u +38.667 163.667 m +38.222 163.222 39.278 163.278 39.333 163.333 c +39.778 163.778 38.722 163.722 38.667 163.667 c +f +*U +0.000 0.608 0.478 0.392 k +*u +40 164 m +41.769 163.221 43 163 45 163 c +43.231 163.779 41.964 163.912 40 164 c +f +*U +0.000 0.729 0.549 0.271 k +*u +45 164 m +52 160.996 63.256 163 71 163 c +129 163 l +329 163 l +1024 163 l +1016.841 166 1005.744 164 998 164 c +940 164 l +740 164 l +45 164 l +f +*U +0.000 0.408 0.294 0.306 k +*u +1110 164 m +1111 163 l +1110 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1112 164 m +1116.215 162.231 1121.464 163 1126 163 c +1155 163 l +1150.785 164.769 1145.536 164 1141 164 c +1112 164 l +f +*U +0.000 0.408 0.408 0.592 k +*u +1155 164 m +1156 163 l +1155 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1179 164 m +1186.879 160.694 1199.466 163 1208 163 c +1275 163 l +1267 166.306 1254.534 164 1246 164 c +1179 164 l +f +*U +0.000 0.161 0.180 0.192 k +*u +1298.333 163.333 m +1298.278 163.278 1298.222 162.222 1298.667 162.667 c +1298.722 162.722 1298.778 163.778 1298.333 163.333 c +f +*U +0.000 0.749 0.804 0.118 k +*u +1305 164 m +1306.248 163.315 1306.548 163.251 1308 163 c +1306.752 163.685 1306.452 163.749 1305 164 c +f +*U +0.000 0.275 0.235 0.216 k +*u +1338 164 m +1339 163 l +1338 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1438 162 m +1445 163.695 1452.719 163 1460 163 c +1495 163 l +1609 163 l +1973 163 l +1973 120 l +1974.875 124.469 1974 130.191 1974 135 c +1974 164 l +1571 164 l +1472 164 l +1448 164 l +1444.483 164.000 1440.435 164.786 1438 162 c +f +*U +0.000 0.596 0.471 0.404 k +*u +2040 164 m +2040 162 l +2041.635 162.545 2041.455 162.365 2042 164 c +2040 164 l +f +*U +0.000 0.318 0.227 0.051 k +*u +2042 164 m +2043 163 l +2042 164 l +f +*U +0.000 0.176 0.125 0.157 k +*u +45.667 162.667 m +45.222 162.222 46.278 162.278 46.333 162.333 c +46.778 162.778 45.722 162.722 45.667 162.667 c +f +*U +0.000 0.384 0.290 0.129 k +*u +47 163 m +54 159.996 65.256 162 73 162 c +130 162 l +329 162 l +1020 162 l +1012.841 165 1001.744 163 994 163 c +937 163 l +738 163 l +47 163 l +f +*U +0.000 0.361 0.271 0.227 k +*u +1020 163 m +1021.506 162.317 1022.315 162.174 1024 162 c +1022.494 162.683 1021.685 162.826 1020 163 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1111 163 m +1115.469 161 1121.192 162 1126 162 c +1155 162 l +1150.531 163.875 1144.809 163 1140 163 c +1111 163 l +f +*U +0.000 0.263 0.204 0.361 k +*u +1155 163 m +1156 162 l +1155 163 l +f +*U +0.000 0.384 0.290 0.129 k +*u +1178 163 m +1186 159.593 1199.203 162 1208 162 c +1276 162 l +1267.882 165.407 1254.797 163 1246 163 c +1178 163 l +f +*U +0.000 0.271 0.231 0.255 k +*u +1286 163 m +1288 162 1289.747 162 1292 162 c +1289.948 162.874 1288.253 162.953 1286 163 c +f +*U +0.000 0.106 0.090 0.208 k +*u +1292 163 m +1293 162 l +1292 163 l +f +*U +0.000 0.412 0.455 0.141 k +*u +1299 163 m +1300.506 162.317 1301.315 162.174 1303 162 c +1301.494 162.683 1300.685 162.826 1299 163 c +f +*U +0.000 0.290 0.325 0.184 k +*u +1303 163 m +1305.890 161.787 1308.874 162 1312 162 c +1309 163.213 1306 162.998 1303 163 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1312 163 m +1319.169 159.992 1330.239 162 1338 162 c +1330.831 165 1319.761 163 1312 163 c +f +*U +0.000 0.522 0.380 0.431 k +*u +1437.333 162.333 m +1437.278 162.278 1437.222 161.222 1437.667 161.667 c +1437.722 161.722 1437.778 162.778 1437.333 162.333 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1439 163 m +1443.720 161 1449.920 162 1455 162 c +1486 162 l +1595 162 l +1973 162 l +1968.280 163.980 1962 163 1957 163 c +1926 163 l +1817 163 l +1439 163 l +f +*U +0.000 0.286 0.212 0.118 k +*u +1024 162 m +1025 161 l +1024 162 l +f +*U +0.000 0.424 0.282 0.251 k +*u +1405 162 m +1406 161 l +1405 162 l +f +*U +0.000 0.725 0.518 0.275 k +*u +1436.333 161.333 m +1436.278 161.278 1436.223 160.222 1436.667 160.667 c +1436.722 160.722 1436.778 161.778 1436.333 161.333 c +f +*U +0.000 0.275 0.200 0.102 k +*u +1438 162 m +1439 161 l +1438 162 l +f +*U +0.000 0.435 0.329 0.380 k +*u +2037 162 m +2037 160 l +2038.635 160.545 2038.455 160.365 2039 162 c +2037 162 l +f +*U +0.000 0.353 0.282 0.043 k +*u +2039 162 m +2040 161 l +2039 162 l +f +*U +0.020 0.000 0.027 0.000 k +*u +56 161 m +63 157.996 74.256 160 82 160 c +139 160 l +337 160 l +1023 160 l +1015.841 163 1004.744 161 997 161 c +940 161 l +742 161 l +56 161 l +f +*U +0.000 0.333 0.243 0.376 k +*u +1025 161 m +1026 160 l +1025 161 l +f +*U +0.000 0.243 0.157 0.122 k +*u +1404 161 m +1405 160 l +1404 161 l +f +*U +0.000 0.408 0.294 0.247 k +*u +1437 161 m +1438 160 l +1437 161 l +f +*U +0.020 0.000 0.027 0.000 k +*u +1440 161 m +1444.469 159 1450.191 160 1455 160 c +1486 160 l +1595 160 l +1971 160 l +1971 128 l +1972.552 131.699 1972 136 1972 140 c +1972 161 l +1440 161 l +f +*U +0.000 0.514 0.463 0.486 k +*u +2036 161 m +2037 160 l +2036 161 l +f +*U +0.000 0.290 0.235 0.439 k +*u +1026 160 m +1027 159 l +1026 160 l +f +*U +0.000 0.498 0.373 0.408 k +*u +1027.333 159.333 m +1027.278 159.278 1027.222 158.222 1027.667 158.667 c +1027.722 158.722 1027.778 159.778 1027.333 159.333 c +f +*U +0.000 0.400 0.333 0.220 k +*u +1060 160 m +1061 159 l +1060 160 l +f +*U +0.000 0.600 0.486 0.400 k +*u +1404 160 m +1403 158.521 1403 158.797 1403 157 c +1404.289 158.443 1404.401 158.234 1404 160 c +f +*U +0.000 0.400 0.325 0.447 k +*u +1435.667 159.667 m +1435.222 159.222 1436.278 159.278 1436.333 159.333 c +1436.778 159.778 1435.722 159.722 1435.667 159.667 c +f +*U +0.000 0.694 0.478 0.282 k +*u +1974 160 m +1974 122 l +1977 129.399 1975 140.993 1975 149 c +1975 152.702 1975.441 156.566 1974 160 c +f +*U +0.000 0.259 0.165 0.565 k +*u +2034.667 159.667 m +2034.222 159.222 2035.278 159.278 2035.333 159.333 c +2035.778 159.778 2034.722 159.722 2034.667 159.667 c +f +*U +0.000 0.051 0.031 0.192 k +*u +2036 160 m +2037 159 l +2036 160 l +f +*U +0.000 0.749 0.553 0.251 k +*u +1060 159 m +1061 155 l +1061.553 157 1061.303 157.332 1060 159 c +f +*U +0.000 0.314 0.243 0.271 k +*u +1061 159 m +1062 158 l +1061 159 l +f +*U +0.000 0.420 0.416 0.580 k +*u +1435 159 m +1436 158 l +1435 159 l +f +*U +0.000 0.510 0.373 0.490 k +*u +2032 159 m +2032 157 l +2033.635 157.545 2033.455 157.365 2034 159 c +2032 159 l +f +*U +0.000 0.376 0.255 0.267 k +*u +2034 159 m +2035 158 l +2034 159 l +f +*U +0.000 0.157 0.133 0.188 k +*u +1027 158 m +1028 157 l +1027 158 l +f +*U +0.000 0.420 0.384 0.580 k +*u +1028 158 m +1029 157 l +1028 158 l +f +*U +0.000 0.251 0.184 0.133 k +*u +1062 158 m +1063 157 l +1062 158 l +f +*U +0.000 0.392 0.302 0.357 k +*u +1402 158 m +1403 157 l +1402 158 l +f +*U +0.000 0.533 0.396 0.384 k +*u +1434.333 157.333 m +1434.278 157.278 1434.222 156.222 1434.667 156.667 c +1434.722 156.722 1434.778 157.778 1434.333 157.333 c +f +*U +0.000 0.325 0.267 0.263 k +*u +1435 158 m +1436 157 l +1435 158 l +f +*U +0.000 0.227 0.180 0.357 k +*u +1028 157 m +1029 156 l +1028 157 l +f +*U +0.000 0.624 0.490 0.376 k +*u +1062 157 m +1063.324 154.313 1064.313 153.324 1067 152 c +1065.451 154 1064 155.451 1062 157 c +f +*U +0.000 0.267 0.200 0.165 k +*u +1063 157 m +1064 156 l +1063 157 l +f +*U +0.000 0.290 0.235 0.227 k +*u +1401 157 m +1402 156 l +1401 157 l +f +*U +0.000 0.569 0.467 0.431 k +*u +1402 157 m +1403 156 l +1402 157 l +f +*U +0.000 0.471 0.420 0.529 k +*u +2030 157 m +2031 156 l +2030 157 l +f +*U +0.000 0.388 0.329 0.110 k +*u +2031 157 m +2032 156 l +2031 157 l +f +*U +0.000 0.427 0.345 0.114 k +*u +1400 156 m +1401 155 l +1400 156 l +f +*U +0.000 0.537 0.420 0.463 k +*u +1433 156 m +1434 155 l +1433 156 l +f +*U +0.000 0.200 0.165 0.129 k +*u +1434 156 m +1435 155 l +1434 156 l +f +*U +0.000 0.361 0.294 0.357 k +*u +2029 156 m +2030 155 l +2029 156 l +f +*U +0.000 0.216 0.141 0.173 k +*u +1399 155 m +1400 154 l +1399 155 l +f +*U +0.000 0.298 0.251 0.243 k +*u +1433 155 m +1434 154 l +1433 155 l +f +*U +0.000 0.494 0.376 0.498 k +*u +2027 155 m +2028 154 l +2027 155 l +f +*U +0.000 0.192 0.169 0.157 k +*u +2028 155 m +2029 154 l +2028 155 l +f +*U +0.000 0.267 0.196 0.110 k +*u +1030 154 m +1031 153 l +1030 154 l +f +*U +0.000 0.620 0.431 0.380 k +*u +1399.333 153.333 m +1399.278 153.278 1399.222 152.222 1399.667 152.667 c +1399.722 152.722 1399.778 153.778 1399.333 153.333 c +f +*U +0.000 0.612 0.561 0.388 k +*u +1431.333 153.333 m +1431.278 153.278 1431.222 152.222 1431.667 152.667 c +1431.722 152.722 1431.778 153.778 1431.333 153.333 c +f +*U +0.000 0.306 0.267 0.435 k +*u +1432 154 m +1433 153 l +1432 154 l +f +*U +0.000 0.396 0.306 0.365 k +*u +2026 154 m +2027 153 l +2026 154 l +f +*U +0.000 0.259 0.196 0.231 k +*u +1031 153 m +1032 152 l +1031 153 l +f +*U +0.000 0.427 0.271 0.349 k +*u +1398 153 m +1399 152 l +1398 153 l +f +*U +0.000 0.467 0.420 0.533 k +*u +2024 153 m +2025 152 l +2024 153 l +f +*U +0.000 0.392 0.294 0.012 k +*u +2025 153 m +2026 152 l +2025 153 l +f +*U +0.000 0.322 0.224 0.255 k +*u +1032 152 m +1033 151 l +1032 152 l +f +*U +0.000 0.384 0.365 0.616 k +*u +1033 152 m +1034 151 l +1033 152 l +f +*U +0.000 0.710 0.498 0.282 k +*u +1067 152 m +1067.684 149.791 1068 149.297 1070 148 c +1069 149.948 1068.607 150.550 1067 152 c +f +*U +0.000 0.180 0.129 0.188 k +*u +1125 152 m +1126 151 l +1125 152 l +f +*U +0.000 0.616 0.455 0.373 k +*u +1126 152 m +1130.564 149.361 1138.689 151 1144 151 c +1138.777 153.191 1131.632 152 1126 152 c +f +*U +0.000 0.522 0.400 0.447 k +*u +1144 152 m +1147.959 150.339 1152.740 151 1157 151 c +1180 151 l +1176 152.661 1171.260 152 1167 152 c +1144 152 l +f +*U +0.000 0.718 0.545 0.282 k +*u +1180 152 m +1181.458 150.919 1182.248 150.564 1184 150 c +1182.686 151.618 1182 151.693 1180 152 c +f +*U +0.000 0.000 0.000 0.298 k +*u +1214.667 151.667 m +1214.222 151.222 1215.278 151.278 1215.333 151.333 c +1215.778 151.778 1214.722 151.722 1214.667 151.667 c +f +*U +0.000 0.145 0.114 0.180 k +*u +1233 152 m +1234 151 l +1233 152 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1234 152 m +1235 151 l +1234 152 l +f +*U +0.000 0.529 0.384 0.467 k +*u +1235.333 151.333 m +1235.278 151.278 1235.222 150.222 1235.667 150.667 c +1235.722 150.722 1235.778 151.778 1235.333 151.333 c +f +*U +0.000 0.741 0.529 0.251 k +*u +1236 152 m +1236.307 149.877 1236.382 149.314 1238 148 c +1237.404 149.560 1236.911 150.623 1236 152 c +f +*U +0.000 0.616 0.463 0.376 k +*u +1237 152 m +1242.469 149.705 1250 151 1256 151 c +1250.531 153.295 1242.901 152 1237 152 c +f +*U +0.000 0.522 0.400 0.447 k +*u +1256 152 m +1261.707 149.605 1269.846 151 1276 151 c +1290.998 151 1307.230 152.742 1322 150 c +1318.696 153.781 1309.740 152 1305 152 c +1256 152 l +f +*U +0.000 0.278 0.251 0.722 k +*u +1322 152 m +1323 151 l +1322 152 l +f +*U +0.000 0.145 0.094 0.333 k +*u +1323 152 m +1324 151 l +1323 152 l +f +*U +0.000 0.804 0.600 0.196 k +*u +1397 152 m +1395.998 149.386 1395.678 147.773 1396 145 c +1399 146 l +1397 149 l +1398.924 150 1399 150 1400 152 c +1397 152 l +f +*U +0.000 0.455 0.463 0.490 k +*u +1430 152 m +1431 151 l +1430 152 l +f +*U +0.110 0.000 0.071 0.133 k +*u +1431 152 m +1432 151 l +1431 152 l +f +*U +0.000 0.514 0.337 0.486 k +*u +2022 152 m +2023 151 l +2022 152 l +f +*U +0.000 0.349 0.204 0.290 k +*u +2023 152 m +2024 151 l +2023 152 l +f +*U +0.000 0.263 0.184 0.325 k +*u +1126 151 m +1127 150 l +1126 151 l +f +*U +0.000 0.894 0.651 0.106 k +*u +1128 151 m +1131.547 146.985 1139.689 140.968 1145 139.938 c +1151 138.752 1158.724 140 1165 140 c +1205 140 l +1205 142 l +1202.214 142.355 1199.684 143.535 1196.911 143.871 c +1193.952 144.229 1190.807 143.588 1188 145 c +1184.936 146.650 1183.611 150 1179.946 150.772 c +1174.300 151.876 1167.742 151 1162 151 c +1128 151 l +f +*U +0.000 0.243 0.176 0.090 k +*u +1234 151 m +1235 150 l +1234 151 l +f +*U +0.000 0.882 0.635 0.118 k +*u +1237 151 m +1238.959 144.618 1244.912 145.185 1248 140 c +1265.500 140 1284.675 137.762 1302 140 c +1307.844 140.959 1317 145.842 1320 151 c +1237 151 l +f +*U +0.000 0.263 0.176 0.133 k +*u +1322 151 m +1323 150 l +1322 151 l +f +*U +0.000 0.341 0.282 0.286 k +*u +1396 151 m +1397 150 l +1396 151 l +f +*U +0.000 0.306 0.345 0.365 k +*u +1430 151 m +1431 150 l +1430 151 l +f +*U +0.000 0.545 0.451 0.455 k +*u +1034 150 m +1035 149 l +1034 150 l +f +*U +0.000 0.698 0.510 0.278 k +*u +1128.667 149.667 m +1128.222 149.222 1129.278 149.278 1129.333 149.333 c +1129.778 149.778 1128.722 149.722 1128.667 149.667 c +f +*U +0.000 0.282 0.208 0.224 k +*u +1235 150 m +1236 149 l +1235 150 l +f +*U +0.000 0.275 0.180 0.329 k +*u +1320 150 m +1321 149 l +1320 150 l +f +*U +0.000 0.286 0.208 0.369 k +*u +1395 150 m +1396 149 l +1395 150 l +f +*U +0.000 0.310 0.231 0.396 k +*u +1429 150 m +1430 149 l +1429 150 l +f +*U +0.000 0.384 0.267 0.259 k +*u +2020 150 m +2021 149 l +2020 150 l +f +*U +0.000 0.294 0.212 0.176 k +*u +1034 149 m +1035 148 l +1034 149 l +f +*U +0.000 0.349 0.271 0.243 k +*u +1070 149 m +1071 148 l +1070 149 l +f +*U +0.000 0.282 0.220 0.204 k +*u +1129 149 m +1130 148 l +1129 149 l +f +*U +0.000 0.224 0.169 0.443 k +*u +1184 149 m +1185 148 l +1184 149 l +f +*U +0.000 0.459 0.302 0.525 k +*u +1317.667 148.667 m +1317.222 148.222 1318.278 148.278 1318.333 148.333 c +1318.778 148.778 1317.722 148.722 1317.667 148.667 c +f +*U +0.000 0.278 0.141 0.086 k +*u +1319 149 m +1320 148 l +1319 149 l +f +*U +0.000 0.271 0.180 0.204 k +*u +1394 149 m +1395 148 l +1394 149 l +f +*U +0.000 0.651 0.494 0.349 k +*u +1427 149 m +1427 147 l +1428.635 147.545 1428.455 147.365 1429 149 c +1427 149 l +f +*U +0.000 0.553 0.384 0.380 k +*u +2017.667 148.667 m +2017.222 148.222 2018.278 148.278 2018.333 148.333 c +2018.778 148.778 2017.722 148.722 2017.667 148.667 c +f +*U +0.000 0.247 0.169 0.110 k +*u +2019 149 m +2020 148 l +2019 149 l +f +*U +0.000 0.306 0.224 0.259 k +*u +1035 148 m +1036 147 l +1035 148 l +f +*U +0.000 0.486 0.365 0.125 k +*u +1071 148 m +1072 147 l +1071 148 l +f +*U +0.000 0.420 0.314 0.275 k +*u +1131 148 m +1132 147 l +1131 148 l +f +*U +0.000 0.553 0.361 0.412 k +*u +1184 148 m +1188 143.180 1193.174 144 1199 144 c +1194.338 145.956 1188.933 146 1184 148 c +f +*U +0.000 0.200 0.165 0.165 k +*u +1236 148 m +1237 147 l +1236 148 l +f +*U +0.000 0.431 0.325 0.424 k +*u +1237 148 m +1237.684 146.420 1237.805 146.223 1239 145 c +1238.316 146.580 1238.195 146.777 1237 148 c +f +*U +0.000 0.318 0.251 0.431 k +*u +1317 148 m +1318 147 l +1317 148 l +f +*U +0.000 0.306 0.204 0.188 k +*u +1393 148 m +1394 147 l +1393 148 l +f +*U +0.000 0.522 0.404 0.478 k +*u +1394 148 m +1395 147 l +1394 148 l +f +*U +0.000 0.278 0.231 0.102 k +*u +1428 148 m +1429 147 l +1428 148 l +f +*U +0.000 0.380 0.259 0.290 k +*u +2017 148 m +2018 147 l +2017 148 l +f +*U +0.000 0.208 0.161 0.306 k +*u +1036 147 m +1037 146 l +1036 147 l +f +*U +0.000 0.243 0.212 0.416 k +*u +1072 147 m +1073 146 l +1072 147 l +f +*U +0.000 0.255 0.204 0.133 k +*u +1132 147 m +1133 146 l +1132 147 l +f +*U +0.000 0.714 0.537 0.286 k +*u +1133.667 146.667 m +1133.222 146.222 1134.278 146.278 1134.333 146.333 c +1134.778 146.778 1133.722 146.722 1133.667 146.667 c +f +*U +0.000 0.196 0.184 0.153 k +*u +1316 147 m +1317 146 l +1316 147 l +f +*U +0.000 0.400 0.290 0.035 k +*u +1392 147 m +1393 146 l +1392 147 l +f +*U +0.000 0.718 0.545 0.282 k +*u +1393 147 m +1392 145 l +1394 145 l +1394 146.853 1394.300 146.350 1393 147 c +f +*U +0.000 0.667 0.424 0.333 k +*u +1425 147 m +1425 144 l +1426.195 145.223 1426.316 145.420 1427 147 c +1425 147 l +f +*U +0.000 0.361 0.275 0.184 k +*u +1427 147 m +1428 146 l +1427 147 l +f +*U +0.000 0.204 0.133 0.122 k +*u +2016 147 m +2017 146 l +2016 147 l +f +*U +0.000 0.412 0.306 0.282 k +*u +1037 146 m +1038 145 l +1037 146 l +f +*U +0.000 0.565 0.467 0.435 k +*u +1072 146 m +1073 145 l +1072 146 l +f +*U +0.000 0.412 0.341 0.141 k +*u +1073 146 m +1074 145 l +1073 146 l +f +*U +0.000 0.306 0.243 0.216 k +*u +1134 146 m +1135 145 l +1134 146 l +f +*U +0.000 0.475 0.392 0.525 k +*u +1135 146 m +1136 145 l +1135 146 l +f +*U +0.000 0.102 0.067 0.227 k +*u +1195 146 m +1196.248 145.315 1196.549 145.251 1198 145 c +1196.751 145.685 1196.452 145.749 1195 146 c +f +*U +0.000 0.200 0.173 0.329 k +*u +1237 146 m +1238 145 l +1237 146 l +f +*U +0.000 0.592 0.498 0.408 k +*u +1313 146 m +1314 145 l +1313 146 l +f +*U +0.000 0.471 0.353 0.208 k +*u +1314 146 m +1315 145 l +1314 146 l +f +*U +0.000 0.506 0.396 0.451 k +*u +2012.667 145.667 m +2012.222 145.222 2013.278 145.278 2013.333 145.333 c +2013.778 145.778 2012.722 145.722 2012.667 145.667 c +f +*U +0.000 0.345 0.259 0.220 k +*u +2014 146 m +2015 145 l +2014 146 l +f +*U +0.000 0.569 0.467 0.431 k +*u +1073 145 m +1074 144 l +1073 145 l +f +*U +0.000 0.247 0.212 0.341 k +*u +1074 145 m +1075 144 l +1074 145 l +f +*U +0.000 0.114 0.129 0.125 k +*u +1135 145 m +1136 144 l +1135 145 l +f +*U +0.000 0.647 0.420 0.133 k +*u +1199 145 m +1200 144 l +1199 145 l +f +*U +0.000 0.180 0.169 0.153 k +*u +1238 145 m +1239 144 l +1238 145 l +f +*U +0.000 0.459 0.361 0.125 k +*u +1239 145 m +1240 144 l +1239 145 l +f +*U +0.000 0.580 0.486 0.420 k +*u +1240 145 m +1241.506 144.317 1242.315 144.174 1244 144 c +1242.494 144.683 1241.686 144.826 1240 145 c +f +*U +0.000 0.329 0.282 0.580 k +*u +1312 145 m +1313 144 l +1312 145 l +f +*U +0.000 0.224 0.141 0.584 k +*u +1391 145 m +1392 144 l +1391 145 l +f +*U +0.000 0.482 0.427 0.231 k +*u +2012 145 m +2013 144 l +2012 145 l +f +*U +0.000 0.188 0.118 0.671 k +*u +1039 144 m +1040 143 l +1039 144 l +f +*U +0.000 0.741 0.463 0.259 k +*u +1040 144 m +1040.684 142.420 1040.805 142.223 1042 141 c +1042 144 l +1040 144 l +f +*U +0.000 0.463 0.443 0.173 k +*u +1075 144 m +1076 143 l +1075 144 l +f +*U +0.000 0.192 0.137 0.294 k +*u +1137 144 m +1138 143 l +1137 144 l +f +*U +0.000 0.698 0.533 0.302 k +*u +1138.667 143.667 m +1138.222 143.222 1139.278 143.278 1139.333 143.333 c +1139.778 143.778 1138.722 143.722 1138.667 143.667 c +f +*U +0.000 0.067 0.114 0.302 k +*u +1200 144 m +1201 143 l +1200 144 l +f +*U +0.000 0.086 0.012 0.192 k +*u +1243 144 m +1244 143 l +1243 144 l +f +*U +0.000 0.290 0.161 0.376 k +*u +1244 144 m +1245 143 l +1244 144 l +f +*U +0.000 0.416 0.259 0.573 k +*u +1309.667 143.667 m +1309.222 143.222 1310.278 143.278 1310.333 143.333 c +1310.778 143.778 1309.722 143.722 1309.667 143.667 c +f +*U +0.000 0.337 0.180 0.039 k +*u +1311 144 m +1312 143 l +1311 144 l +f +*U +0.000 0.682 0.498 0.282 k +*u +1390 144 m +1387.794 141.748 1385.807 139.576 1384 137 c +1387 138.489 1390 140.283 1390 144 c +f +*U +0.000 0.243 0.149 0.686 k +*u +1424 144 m +1425 143 l +1424 144 l +f +*U +0.000 0.180 0.114 0.125 k +*u +1425 144 m +1426 143 l +1425 144 l +f +*U +0.000 0.443 0.286 0.463 k +*u +2009.667 143.667 m +2009.222 143.223 2010.277 143.277 2010.333 143.333 c +2010.778 143.778 2009.722 143.722 2009.667 143.667 c +f +*U +0.000 0.169 0.102 0.173 k +*u +2011 144 m +2012 143 l +2011 144 l +f +*U +0.000 0.180 0.118 0.176 k +*u +1039 143 m +1040 142 l +1039 143 l +f +*U +0.000 0.502 0.400 0.341 k +*u +1075 143 m +1076.223 141.805 1076.420 141.684 1078 141 c +1076.777 142.195 1076.580 142.316 1075 143 c +f +*U +0.000 0.365 0.263 0.247 k +*u +1139 143 m +1140 142 l +1139 143 l +f +*U +0.000 0.471 0.365 0.486 k +*u +1200 143 m +1201 142 l +1200 143 l +f +*U +0.000 0.420 0.329 0.259 k +*u +1201 143 m +1202 142 l +1201 143 l +f +*U +0.000 0.275 0.235 0.067 k +*u +1202 143 m +1203 142 l +1202 143 l +f +*U +0.000 0.137 0.110 0.122 k +*u +1210 143 m +1211 142 l +1210 143 l +f +*U +0.000 0.290 0.216 0.306 k +*u +1211 143 m +1212 142 l +1211 143 l +f +*U +0.000 0.537 0.467 0.431 k +*u +1212 143 m +1214 142 1215.747 142 1218 142 c +1215.948 142.874 1214.253 142.953 1212 143 c +f +*U +0.000 0.267 0.216 0.259 k +*u +1218 143 m +1219 142 l +1218 143 l +f +*U +0.000 0.349 0.224 0.000 k +*u +1245 143 m +1246 142 l +1245 143 l +f +*U +0.000 0.471 0.345 0.306 k +*u +1246 143 m +1246 140 l +1246.696 141.554 1246.696 141.446 1246 143 c +f +*U +0.000 0.576 0.435 0.353 k +*u +1247 143 m +1246 139 l +1247.656 140.404 1247.751 140.954 1247 143 c +f +*U +0.000 0.357 0.259 0.310 k +*u +1309 143 m +1310 142 l +1309 143 l +f +*U +0.000 0.161 0.098 0.263 k +*u +1424 143 m +1425 142 l +1424 143 l +f +*U +0.000 0.557 0.361 0.427 k +*u +2008 143 m +2009 142 l +2008 143 l +f +*U +0.000 0.478 0.322 0.098 k +*u +2009 143 m +2010 142 l +2009 143 l +f +*U +0.000 0.282 0.212 0.075 k +*u +1040 142 m +1041 141 l +1040 142 l +f +*U +0.000 0.329 0.239 0.055 k +*u +1140 142 m +1141 141 l +1140 142 l +f +*U +0.000 0.580 0.455 0.420 k +*u +1205 142 m +1206.769 141.221 1208 141 1210 141 c +1208.231 141.779 1206.964 141.912 1205 142 c +f +*U +0.000 0.945 0.667 0.055 k +*u +1205 141 m +1208.959 139.339 1213.737 140 1218 140 c +1218 142 l +1205 141 l +f +*U +0.000 0.667 0.522 0.333 k +*u +1218 142 m +1212.887 138 1203.218 140 1197 140 c +1146 140 l +1152.436 137.299 1162 139 1169 139 c +1220 139 l +1219.316 140.580 1219.195 140.777 1218 142 c +f +*U +0.000 0.329 0.251 0.075 k +*u +1219 142 m +1220 141 l +1219 142 l +f +*U +0.000 0.604 0.459 0.396 k +*u +1306 142 m +1307 141 l +1306 142 l +f +*U +0.000 0.361 0.298 0.396 k +*u +1307 142 m +1308 141 l +1307 142 l +f +*U +0.000 0.369 0.306 0.353 k +*u +1423 142 m +1424 141 l +1423 142 l +f +*U +0.000 0.659 0.471 0.341 k +*u +2006.667 141.667 m +2006.222 141.222 2007.278 141.278 2007.333 141.333 c +2007.778 141.778 2006.722 141.722 2006.667 141.667 c +f +*U +0.000 0.184 0.125 0.133 k +*u +2008 142 m +2009 141 l +2008 142 l +f +*U +0.000 0.361 0.337 0.086 k +*u +1041 141 m +1042 140 l +1041 141 l +f +*U +0.000 0.620 0.475 0.380 k +*u +1042 141 m +1043 140 l +1042 141 l +f +*U +0.000 0.706 0.490 0.294 k +*u +1077 141 m +1078.573 138.338 1080 137.228 1083 136 c +1081 138.447 1079.763 139.700 1077 141 c +f +*U +0.000 0.325 0.235 0.082 k +*u +1142 141 m +1143 140 l +1142 141 l +f +*U +0.000 0.443 0.337 0.188 k +*u +1220 141 m +1221 140 l +1220 141 l +f +*U +0.000 0.412 0.388 0.588 k +*u +1304 141 m +1305 140 l +1304 141 l +f +*U +0.000 0.420 0.318 0.380 k +*u +1305 141 m +1306 140 l +1305 141 l +f +*U +0.000 0.427 0.325 0.341 k +*u +1422 141 m +1423 140 l +1422 141 l +f +*U +0.000 0.439 0.431 0.561 k +*u +2005 141 m +2006 140 l +2005 141 l +f +*U +0.000 0.329 0.227 0.325 k +*u +2006 141 m +2007 140 l +2006 141 l +f +*U +0.000 0.267 0.220 0.235 k +*u +1042 140 m +1043 139 l +1042 140 l +f +*U +0.000 0.604 0.412 0.000 k +*u +1144 140 m +1145 139 l +1144 140 l +f +*U +0.000 0.400 0.388 0.600 k +*u +1220.667 139.667 m +1220.222 139.222 1221.278 139.278 1221.333 139.333 c +1221.778 139.778 1220.722 139.722 1220.667 139.667 c +f +*U +0.000 0.416 0.267 0.325 k +*u +1222 140 m +1223 139 l +1222 140 l +f +*U +0.000 0.145 0.075 0.220 k +*u +1222 138 m +1223.580 138.684 1223.777 138.805 1225 140 c +1223.420 139.316 1223.223 139.195 1222 138 c +f +*U +0.000 0.204 0.137 0.169 k +*u +1227 139 m +1230.607 137.487 1234.260 138 1238 139 c +1234.672 140 1230.479 139.411 1227 139 c +f +*U +0.000 0.259 0.165 0.396 k +*u +1229 140 m +1230.248 139.315 1230.548 139.251 1232 139 c +1230.751 139.685 1230.452 139.749 1229 140 c +f +*U +0.000 0.227 0.153 0.286 k +*u +1232 140 m +1233.248 139.315 1233.548 139.251 1235 139 c +1233.751 139.685 1233.452 139.749 1232 140 c +f +*U +0.000 0.067 0.078 0.518 k +*u +1239.667 139.667 m +1239.222 139.222 1240.278 139.278 1240.333 139.333 c +1240.778 139.778 1239.722 139.722 1239.667 139.667 c +f +*U +0.000 0.667 0.522 0.333 k +*u +1248 140 m +1253.216 137.811 1260.381 139 1266 139 c +1304 139 l +1298.783 141.189 1291.619 140 1286 140 c +1248 140 l +f +*U +0.000 0.404 0.314 0.596 k +*u +1421 140 m +1422 139 l +1421 140 l +f +*U +0.000 0.498 0.384 0.427 k +*u +2003.667 139.667 m +2003.222 139.222 2004.278 139.278 2004.333 139.333 c +2004.778 139.778 2003.722 139.722 2003.667 139.667 c +f +*U +0.000 0.373 0.298 0.259 k +*u +1043 139 m +1044 138 l +1043 139 l +f +*U +0.000 0.675 0.533 0.294 k +*u +1044 139 m +1045 136.643 1045.956 135.624 1048 134 c +1046.987 136.485 1046.274 137.598 1044 139 c +f +*U +0.012 0.000 0.024 0.145 k +*u +1145.667 138.667 m +1145.222 138.222 1146.278 138.278 1146.333 138.333 c +1146.778 138.778 1145.722 138.722 1145.667 138.667 c +f +*U +0.000 0.035 0.024 0.251 k +*u +1238 139 m +1239 138 l +1238 139 l +f +*U +0.000 0.310 0.251 0.071 k +*u +1247 139 m +1248 138 l +1247 139 l +f +*U +0.000 0.039 0.035 0.220 k +*u +1299.667 138.667 m +1299.222 138.222 1300.278 138.278 1300.333 138.333 c +1300.778 138.778 1299.722 138.722 1299.667 138.667 c +f +*U +0.000 0.424 0.365 0.576 k +*u +1420 139 m +1421 138 l +1420 139 l +f +*U +0.000 0.455 0.357 0.102 k +*u +2003 139 m +2004 138 l +2003 139 l +f +*U +0.000 0.420 0.388 0.580 k +*u +1419 138 m +1420 137 l +1419 138 l +f +*U +0.000 0.235 0.173 0.110 k +*u +1420 138 m +1421 137 l +1420 138 l +f +*U +0.000 0.561 0.424 0.192 k +*u +2001 138 m +2002 137 l +2001 138 l +f +*U +0.000 0.337 0.255 0.071 k +*u +2002 138 m +2003 137 l +2002 138 l +f +*U +0.000 0.145 0.086 0.169 k +*u +1083 137 m +1084 136 l +1083 137 l +f +*U +0.000 0.110 0.047 0.729 k +*u +1383 137 m +1384 136 l +1383 137 l +f +*U +0.000 0.318 0.251 0.110 k +*u +1419 137 m +1420 136 l +1419 137 l +f +*U +0.000 0.333 0.302 0.153 k +*u +2000 137 m +2001 136 l +2000 137 l +f +*U +0.000 0.796 0.576 0.204 k +*u +1083 136 m +1084 132.767 1085.455 130.310 1088 128 c +1089.198 129.245 1089 129 1091 129 c +1088.615 131.749 1086 133.943 1083 136 c +f +*U +0.000 0.271 0.290 0.102 k +*u +1084 136 m +1085 135 l +1084 136 l +f +*U +0.000 0.490 0.365 0.510 k +*u +1417 136 m +1418 135 l +1417 136 l +f +*U +0.000 0.231 0.149 0.318 k +*u +1418 136 m +1419 135 l +1418 136 l +f +*U +0.000 0.463 0.345 0.431 k +*u +1995 134 m +1996.580 134.684 1996.777 134.805 1998 136 c +1996.420 135.316 1996.223 135.195 1995 134 c +f +*U +0.000 0.129 0.102 0.475 k +*u +1998 136 m +1999 135 l +1998 136 l +f +*U +0.000 0.267 0.196 0.251 k +*u +1085 135 m +1086 134 l +1085 135 l +f +*U +0.000 0.545 0.361 0.455 k +*u +1416 135 m +1417 134 l +1416 135 l +f +*U +0.000 0.384 0.255 0.157 k +*u +1417 135 m +1418 134 l +1417 135 l +f +*U +0.000 0.275 0.216 0.082 k +*u +1997 135 m +1998 134 l +1997 135 l +f +*U +0.000 0.341 0.239 0.271 k +*u +1086 134 m +1087 133 l +1086 134 l +f +*U +0.000 0.514 0.380 0.486 k +*u +1380 134 m +1381 133 l +1380 134 l +f +*U +0.000 0.616 0.431 0.380 k +*u +1415 134 m +1413.242 131.988 1412 130.419 1411 128 c +1413.348 129.773 1415 131 1415 134 c +f +*U +0.000 0.224 0.137 0.314 k +*u +1416 134 m +1417 133 l +1416 134 l +f +*U +0.000 0.525 0.408 0.475 k +*u +1994 134 m +1995 133 l +1994 134 l +f +*U +0.000 0.337 0.243 0.306 k +*u +1995 134 m +1996 133 l +1995 134 l +f +*U +0.000 0.204 0.157 0.125 k +*u +1048 133 m +1049 132 l +1048 133 l +f +*U +0.000 0.494 0.420 0.227 k +*u +1087 133 m +1088 132 l +1087 133 l +f +*U +0.000 0.510 0.510 0.459 k +*u +1379 133 m +1380 132 l +1379 133 l +f +*U +0.000 0.796 0.600 0.196 k +*u +1380 133 m +1378.390 131.672 1377.299 130.617 1376 129 c +1380 128 l +1379.402 129.196 1379.534 128.977 1378 130 c +1379.994 130.847 1380.699 131 1380 133 c +f +*U +0.000 0.533 0.400 0.455 k +*u +1992.667 132.667 m +1992.222 132.222 1993.278 132.278 1993.333 132.333 c +1993.778 132.778 1992.722 132.722 1992.667 132.667 c +f +*U +0.000 0.318 0.220 0.051 k +*u +1994 133 m +1995 132 l +1994 133 l +f +*U +0.000 0.341 0.235 0.439 k +*u +1088 132 m +1089 131 l +1088 132 l +f +*U +0.000 0.251 0.271 0.157 k +*u +1377 132 m +1378 131 l +1377 132 l +f +*U +0.000 0.212 0.188 0.373 k +*u +1992 132 m +1993 131 l +1992 132 l +f +*U +0.000 0.525 0.424 0.475 k +*u +1051 131 m +1052 130 l +1051 131 l +f +*U +0.000 0.286 0.263 0.180 k +*u +1376 131 m +1377 130 l +1376 131 l +f +*U +0.000 0.439 0.341 0.349 k +*u +1989 131 m +1989 129 l +1990.635 129.545 1990.455 129.365 1991 131 c +1989 131 l +f +*U +0.000 0.337 0.275 0.059 k +*u +1991 131 m +1992 130 l +1991 131 l +f +*U +0.000 0.486 0.431 0.514 k +*u +1052 130 m +1053 129 l +1052 130 l +f +*U +0.000 0.275 0.200 0.286 k +*u +1091 130 m +1092 129 l +1091 130 l +f +*U +0.000 0.325 0.204 0.204 k +*u +1375 130 m +1376 129 l +1375 130 l +f +*U +0.000 0.953 0.620 0.047 k +*u +1380 128 m +1381.580 128.684 1381.777 128.805 1383 130 c +1381.420 129.317 1381.223 129.195 1380 128 c +f +*U +0.000 0.525 0.396 0.475 k +*u +1988 130 m +1989 129 l +1988 130 l +f +*U +0.000 0.251 0.180 0.349 k +*u +1092 129 m +1093 128 l +1092 129 l +f +*U +0.000 0.306 0.200 0.302 k +*u +1374 129 m +1375 128 l +1374 129 l +f +*U +0.000 0.486 0.310 0.514 k +*u +1375 129 m +1376 128 l +1375 129 l +f +*U +0.000 0.180 0.141 0.059 k +*u +1412 129 m +1413 128 l +1412 129 l +f +*U +0.000 0.408 0.333 0.424 k +*u +1986.667 128.667 m +1986.222 128.223 1987.277 128.277 1987.333 128.333 c +1987.778 128.778 1986.722 128.722 1986.667 128.667 c +f +*U +0.000 0.192 0.173 0.149 k +*u +1988 129 m +1989 128 l +1988 129 l +f +*U +0.000 0.506 0.561 0.427 k +*u +1054 128 m +1054.545 126.365 1054.365 126.545 1056 126 c +1056 128 l +1054 128 l +f +*U +0.000 0.588 0.443 0.329 k +*u +1092 128 m +1093.624 125.956 1094.643 125 1097 124 c +1095.376 126 1094.357 126.896 1092 128 c +f +*U +0.000 0.192 0.129 0.506 k +*u +1173 128 m +1174 127 l +1173 128 l +f +*U +0.000 0.220 0.220 0.780 k +*u +1174.667 127.667 m +1174.222 127.223 1175.278 127.278 1175.333 127.333 c +1175.778 127.778 1174.722 127.722 1174.667 127.667 c +f +*U +0.000 0.580 0.420 0.420 k +*u +1176 128 m +1180.271 125 1188.772 127 1194 127 c +1240 127 l +1234.293 129.395 1226 128 1220 128 c +1176 128 l +f +*U +0.000 0.529 0.412 0.471 k +*u +1240 128 m +1247.409 124.891 1258.975 127 1267 127 c +1259.591 130 1248 128 1240 128 c +f +*U +0.000 0.620 0.467 0.380 k +*u +1264 126 m +1266.698 125 1269 125.647 1272 126 c +1269 128 1267.224 127 1264 126 c +f +*U +0.000 0.247 0.247 0.753 k +*u +1271 128 m +1272.506 127.317 1273.315 127.174 1275 127 c +1273.494 127.683 1272.685 127.826 1271 128 c +f +*U +0.000 0.192 0.192 0.478 k +*u +1275 128 m +1276 127 l +1275 128 l +f +*U +0.000 0.098 0.102 0.200 k +*u +1276 128 m +1277 127 l +1276 128 l +f +*U +0.000 0.675 0.482 0.325 k +*u +1373 125 m +1374 126 1374.309 126.612 1375 128 c +1372.797 127 1372.952 127.330 1373 125 c +f +*U +0.000 0.545 0.435 0.384 k +*u +1409 128 m +1408 126.522 1408 126.797 1408 125 c +1409.289 126.443 1409.401 126.234 1409 128 c +f +*U +0.000 0.322 0.298 0.678 k +*u +1410 128 m +1411 127 l +1410 128 l +f +*U +0.000 0.443 0.282 0.475 k +*u +1984 128 m +1984 126 l +1985.635 126.545 1985.455 126.365 1986 128 c +1984 128 l +f +*U +0.000 0.212 0.133 0.169 k +*u +1986 128 m +1987 127 l +1986 128 l +f +*U +0.000 0.792 0.620 0.208 k +*u +1057 127 m +1057.514 124 1058.289 123.366 1061 122 c +1059.774 123.922 1058.627 125.412 1057 127 c +f +*U +0.000 0.478 0.365 0.161 k +*u +1176 127 m +1177 126 l +1176 127 l +f +*U +0.000 0.878 0.620 0.122 k +*u +1180 127 m +1184 124 l +1192.981 124.818 1202.873 121.439 1212 121 c +1230.863 120.213 1248.573 122.424 1267 126 c +1259.601 129 1248 127 1240 127 c +1180 127 l +f +*U +0.000 0.259 0.224 0.122 k +*u +1410 127 m +1411 126 l +1410 127 l +f +*U +0.000 0.192 0.145 0.125 k +*u +1096 126 m +1097 125 l +1096 126 l +f +*U +0.000 0.220 0.188 0.318 k +*u +1180 126 m +1181 125 l +1180 126 l +f +*U +0.000 0.604 0.451 0.392 k +*u +1181 126 m +1182.249 125.315 1182.548 125.251 1184 125 c +1182.752 125.685 1182.451 125.749 1181 126 c +f +*U +0.000 0.263 0.263 0.220 k +*u +1268 126 m +1269 125 l +1268 126 l +f +*U +0.000 0.224 0.173 0.051 k +*u +1370 126 m +1371 125 l +1370 126 l +f +*U +0.000 0.353 0.290 0.173 k +*u +1409 126 m +1410 125 l +1409 126 l +f +*U +0.000 0.443 0.357 0.373 k +*u +1981 126 m +1981 124 l +1982.635 124.545 1982.455 124.365 1983 126 c +1981 126 l +f +*U +0.000 0.243 0.243 0.278 k +*u +1983 126 m +1984 125 l +1983 126 l +f +*U +0.000 0.325 0.231 0.275 k +*u +1097 125 m +1098 124 l +1097 125 l +f +*U +0.000 0.294 0.239 0.027 k +*u +1183 125 m +1184 124 l +1183 125 l +f +*U +0.000 0.620 0.463 0.361 k +*u +1185 125 m +1186.249 124.315 1186.548 124.251 1188 124 c +1186.752 124.685 1186.451 124.749 1185 125 c +f +*U +0.000 0.600 0.459 0.400 k +*u +1256 124 m +1258.698 123 1261 123.647 1264 124 c +1261.244 125 1258.893 124.532 1256 124 c +f +*U +0.000 0.173 0.141 0.380 k +*u +1264 125 m +1265 124 l +1264 125 l +f +*U +0.000 0.149 0.129 0.110 k +*u +1265 125 m +1266 124 l +1265 125 l +f +*U +0.000 0.216 0.165 0.263 k +*u +1369 125 m +1370 124 l +1369 125 l +f +*U +0.000 0.643 0.475 0.341 k +*u +1404 121 m +1405.753 122.330 1406.670 123.247 1408 125 c +1405.751 123.847 1405 123.249 1404 121 c +f +*U +0.000 0.298 0.255 0.176 k +*u +1408 125 m +1409 124 l +1408 125 l +f +*U +0.000 0.247 0.220 0.094 k +*u +1187 124 m +1188 123 l +1187 124 l +f +*U +0.000 0.412 0.325 0.231 k +*u +1188 124 m +1189 123 l +1188 124 l +f +*U +0.000 0.600 0.506 0.400 k +*u +1189.667 123.667 m +1189.223 123.223 1190.278 123.278 1190.333 123.333 c +1190.778 123.778 1189.722 123.722 1189.667 123.667 c +f +*U +0.000 0.306 0.208 0.204 k +*u +1260 124 m +1261 123 l +1260 124 l +f +*U +0.000 0.290 0.204 0.341 k +*u +1368 124 m +1369 123 l +1368 124 l +f +*U +0.000 0.376 0.298 0.118 k +*u +1407 124 m +1408 123 l +1407 124 l +f +*U +0.000 0.220 0.153 0.118 k +*u +1980 124 m +1981 123 l +1980 124 l +f +*U +0.000 0.302 0.220 0.071 k +*u +1100 123 m +1101 122 l +1100 123 l +f +*U +0.000 0.310 0.224 0.059 k +*u +1192 123 m +1193 122 l +1192 123 l +f +*U +0.000 0.333 0.243 0.212 k +*u +1193 123 m +1194 122 l +1193 123 l +f +*U +0.000 0.510 0.357 0.475 k +*u +1194 123 m +1195.249 122.315 1195.548 122.251 1197 122 c +1195.752 122.685 1195.451 122.749 1194 123 c +f +*U +0.000 0.753 0.569 0.247 k +*u +1248 123 m +1249.249 122.315 1249.548 122.251 1251 122 c +1249.752 122.685 1249.452 122.749 1248 123 c +f +*U +0.000 0.549 0.455 0.451 k +*u +1251 123 m +1252.249 122.315 1252.548 122.251 1254 122 c +1252.752 122.685 1252.451 122.749 1251 123 c +f +*U +0.000 0.498 0.369 0.200 k +*u +1254 123 m +1255 122 l +1254 123 l +f +*U +0.000 0.502 0.376 0.031 k +*u +1255 123 m +1256 122 l +1255 123 l +f +*U +0.000 0.086 0.027 0.153 k +*u +1256 123 m +1257 122 l +1256 123 l +f +*U +0.000 0.271 0.275 0.388 k +*u +1367 123 m +1368 122 l +1367 123 l +f +*U +0.000 0.459 0.416 0.541 k +*u +1368 123 m +1369 122 l +1368 123 l +f +*U +0.000 0.380 0.298 0.094 k +*u +1406 123 m +1407 122 l +1406 123 l +f +*U +0.000 0.553 0.478 0.447 k +*u +1977 123 m +1978 122 l +1977 123 l +f +*U +0.000 0.325 0.224 0.310 k +*u +1978 123 m +1979 122 l +1978 123 l +f +*U +0.000 0.365 0.263 0.224 k +*u +1101 122 m +1102 121 l +1101 122 l +f +*U +0.000 0.176 0.137 0.125 k +*u +1198 122 m +1199 121 l +1198 122 l +f +*U +0.000 0.176 0.137 0.298 k +*u +1199 122 m +1200 121 l +1199 122 l +f +*U +0.000 0.643 0.498 0.357 k +*u +1200 122 m +1202.613 120.902 1205 121 1208 121 c +1205.387 122 1202.835 121.993 1200 122 c +f +*U +0.000 0.706 0.518 0.294 k +*u +1240 122 m +1241.769 121.221 1243 121 1245 121 c +1243.231 121.779 1241.964 121.912 1240 122 c +f +*U +0.000 0.545 0.424 0.455 k +*u +1245 122 m +1246.249 121.315 1246.548 121.251 1248 121 c +1246.752 121.685 1246.451 121.749 1245 122 c +f +*U +0.000 0.235 0.176 0.278 k +*u +1248.667 121.667 m +1248.222 121.222 1249.278 121.278 1249.333 121.333 c +1249.778 121.778 1248.722 121.722 1248.667 121.667 c +f +*U +0.000 0.200 0.149 0.071 k +*u +1250 122 m +1251 121 l +1250 122 l +f +*U +0.000 0.294 0.243 0.204 k +*u +1405 122 m +1406 121 l +1405 122 l +f +*U +0.000 0.471 0.380 0.529 k +*u +1974.333 121.333 m +1974.278 121.278 1974.222 120.222 1974.667 120.667 c +1974.722 120.722 1974.778 121.778 1974.333 121.333 c +f +*U +0.000 0.408 0.294 0.424 k +*u +1102 121 m +1103 120 l +1102 121 l +f +*U +0.000 0.173 0.161 0.247 k +*u +1205 121 m +1206.249 120.315 1206.548 120.251 1208 120 c +1206.752 120.685 1206.451 120.749 1205 121 c +f +*U +0.000 0.502 0.357 0.192 k +*u +1208 121 m +1209 120 l +1208 121 l +f +*U +0.000 0.604 0.514 0.396 k +*u +1209 121 m +1211.331 120 1213.457 120 1216 120 c +1213.668 120.985 1211.543 120.981 1209 121 c +f +*U +0.000 0.843 0.851 0.149 k +*u +1216 121 m +1221.469 118.705 1229 120 1235 120 c +1229.531 122.295 1221.901 121 1216 121 c +f +*U +0.000 0.553 0.541 0.447 k +*u +1235 121 m +1236.249 120.315 1236.548 120.251 1238 120 c +1236.752 120.685 1236.452 120.749 1235 121 c +f +*U +0.000 0.675 0.400 0.243 k +*u +1238.667 120.667 m +1238.222 120.223 1239.278 120.278 1239.333 120.333 c +1239.778 120.778 1238.722 120.722 1238.667 120.667 c +f +*U +0.000 0.337 0.255 0.204 k +*u +1240 121 m +1241.249 120.315 1241.548 120.251 1243 120 c +1241.752 120.685 1241.451 120.749 1240 121 c +f +*U +0.000 0.169 0.137 0.082 k +*u +1243 121 m +1244 120 l +1243 121 l +f +*U +0.000 0.122 0.055 0.204 k +*u +1364 121 m +1365 120 l +1364 121 l +f +*U +0.000 0.400 0.298 0.600 k +*u +1365 121 m +1366 120 l +1365 121 l +f +*U +0.000 0.510 0.392 0.059 k +*u +1404 121 m +1405 120 l +1404 121 l +f +*U +0.000 0.671 0.463 0.094 k +*u +1975 121 m +1976 120 l +1975 121 l +f +*U +0.000 0.322 0.204 0.298 k +*u +1062 120 m +1063 119 l +1062 120 l +f +*U +0.000 0.427 0.286 0.573 k +*u +1063 120 m +1064 119 l +1063 120 l +f +*U +0.000 0.133 0.114 0.161 k +*u +1104 120 m +1105 119 l +1104 120 l +f +*U +0.000 0.090 0.020 0.224 k +*u +1218 120 m +1220.890 118.787 1223.874 119 1227 119 c +1224 120.213 1221 119.998 1218 120 c +f +*U +0.000 0.384 0.416 0.263 k +*u +1363 120 m +1364 119 l +1363 120 l +f +*U +0.000 0.506 0.329 0.443 k +*u +1402 120 m +1403 119 l +1402 120 l +f +*U +0.000 0.200 0.125 0.176 k +*u +1403 120 m +1404 119 l +1403 120 l +f +*U +0.031 0.000 0.012 0.588 k +*u +1973 120 m +1974 119 l +1973 120 l +f +*U +0.000 0.290 0.184 0.235 k +*u +1063 119 m +1064 118 l +1063 119 l +f +*U +0.000 0.494 0.357 0.455 k +*u +1104 119 m +1105 118 l +1104 119 l +f +*U +0.000 0.424 0.302 0.290 k +*u +1105 119 m +1106 118 l +1105 119 l +f +*U +0.000 0.627 0.506 0.373 k +*u +1362.667 118.667 m +1362.222 118.223 1363.278 118.278 1363.333 118.333 c +1363.778 118.778 1362.722 118.722 1362.667 118.667 c +f +*U +0.000 0.537 0.408 0.463 k +*u +1401 119 m +1402 118 l +1401 119 l +f +*U +0.000 0.329 0.220 0.075 k +*u +1402 119 m +1403 118 l +1402 119 l +f +*U +0.000 0.376 0.294 0.188 k +*u +1064 118 m +1065 117 l +1064 118 l +f +*U +0.000 0.522 0.424 0.478 k +*u +1065 118 m +1066 117 l +1065 118 l +f +*U +0.000 0.235 0.180 0.090 k +*u +1107 118 m +1108 117 l +1107 118 l +f +*U +0.000 0.318 0.388 0.086 k +*u +1360 118 m +1361 117 l +1360 118 l +f +*U +0.000 0.459 0.451 0.541 k +*u +1361 118 m +1362 117 l +1361 118 l +f +*U +0.000 0.522 0.341 0.431 k +*u +1400 118 m +1401 117 l +1400 118 l +f +*U +0.000 0.329 0.224 0.067 k +*u +1401 118 m +1402 117 l +1401 118 l +f +*U +0.000 0.404 0.325 0.561 k +*u +1066 117 m +1067 116 l +1066 117 l +f +*U +0.000 0.541 0.424 0.459 k +*u +1107 117 m +1108 116 l +1107 117 l +f +*U +0.000 0.322 0.247 0.310 k +*u +1108 117 m +1109 116 l +1108 117 l +f +*U +0.000 0.278 0.192 0.322 k +*u +1359 117 m +1360 116 l +1359 117 l +f +*U +0.000 0.553 0.404 0.447 k +*u +1399 117 m +1400 116 l +1399 117 l +f +*U +0.000 0.224 0.145 0.180 k +*u +1400 117 m +1401 116 l +1400 117 l +f +*U +0.055 0.000 0.059 0.157 k +*u +1066 116 m +1067 115 l +1066 116 l +f +*U +0.000 0.329 0.329 0.671 k +*u +1067 116 m +1068 115 l +1067 116 l +f +*U +0.000 0.486 0.353 0.404 k +*u +1108.667 115.667 m +1108.222 115.222 1109.278 115.278 1109.333 115.333 c +1109.778 115.778 1108.722 115.722 1108.667 115.667 c +f +*U +0.000 0.235 0.196 0.114 k +*u +1357 116 m +1358 115 l +1357 116 l +f +*U +0.000 0.490 0.388 0.510 k +*u +1358 116 m +1359 115 l +1358 116 l +f +*U +0.000 0.706 0.525 0.239 k +*u +1396 116 m +1396 113 l +1397.196 114.223 1397.316 114.420 1398 116 c +1396 116 l +f +*U +0.000 0.365 0.310 0.635 k +*u +1398 116 m +1399 115 l +1398 116 l +f +*U +0.000 0.212 0.157 0.075 k +*u +1399 116 m +1400 115 l +1399 116 l +f +*U +0.000 0.455 0.380 0.545 k +*u +1068 115 m +1069 114 l +1068 115 l +f +*U +0.000 0.443 0.341 0.196 k +*u +1111 115 m +1112 114 l +1111 115 l +f +*U +0.000 0.373 0.302 0.231 k +*u +1356 115 m +1357 114 l +1356 115 l +f +*U +0.000 0.451 0.451 0.549 k +*u +1357 115 m +1358 114 l +1357 115 l +f +*U +0.000 0.659 0.451 0.341 k +*u +1112 114 m +1112 112 l +1114 112 l +1113.455 113.635 1113.635 113.455 1112 114 c +f +*U +0.000 0.380 0.255 0.063 k +*u +1113 114 m +1114 113 l +1113 114 l +f +*U +0.000 0.490 0.408 0.263 k +*u +1070 113 m +1071 112 l +1070 113 l +f +*U +0.000 0.310 0.192 0.196 k +*u +1114 113 m +1115 112 l +1114 113 l +f +*U +0.000 0.106 0.102 0.404 k +*u +1353 113 m +1354 112 l +1353 113 l +f +*U +0.000 0.514 0.431 0.239 k +*u +1395 113 m +1396 112 l +1395 113 l +f +*U +0.000 0.094 0.055 0.329 k +*u +1071 112 m +1072 111 l +1071 112 l +f +*U +0.000 0.643 0.431 0.357 k +*u +1072 112 m +1072.545 110.365 1072.365 110.545 1074 110 c +1074 112 l +1072 112 l +f +*U +0.000 0.467 0.467 0.533 k +*u +1115 112 m +1116 111 l +1115 112 l +f +*U +0.000 0.302 0.318 0.110 k +*u +1116 112 m +1117 111 l +1116 112 l +f +*U +0.000 0.549 0.384 0.451 k +*u +1393 112 m +1394 111 l +1393 112 l +f +*U +0.000 0.220 0.137 0.333 k +*u +1394 112 m +1395 111 l +1394 112 l +f +*U +0.000 0.267 0.165 0.082 k +*u +1072 111 m +1073 110 l +1072 111 l +f +*U +0.000 0.384 0.318 0.251 k +*u +1117 111 m +1118 110 l +1117 111 l +f +*U +0.000 0.310 0.263 0.196 k +*u +1350 111 m +1351 110 l +1350 111 l +f +*U +0.000 0.471 0.369 0.478 k +*u +1351 111 m +1352 110 l +1351 111 l +f +*U +0.000 0.412 0.275 0.141 k +*u +1393 111 m +1394 110 l +1393 111 l +f +*U +0.000 0.361 0.243 0.016 k +*u +1119 110 m +1120 109 l +1119 110 l +f +*U +0.000 0.278 0.216 0.075 k +*u +1348 110 m +1349 109 l +1348 110 l +f +*U +0.000 0.475 0.333 0.463 k +*u +1388 107 m +1389.949 107.936 1390.550 108.392 1392 110 c +1390 109 1389.450 108.608 1388 107 c +f +*U +0.000 0.235 0.153 0.098 k +*u +1392 110 m +1393 109 l +1392 110 l +f +*U +0.000 0.663 0.537 0.337 k +*u +1075.667 108.667 m +1075.222 108.222 1076.278 108.278 1076.333 108.333 c +1076.778 108.778 1075.722 108.722 1075.667 108.667 c +f +*U +0.000 0.627 0.506 0.373 k +*u +1120 109 m +1120 107 l +1122 107 l +1121.455 108.635 1121.635 108.455 1120 109 c +f +*U +0.000 0.216 0.192 0.125 k +*u +1121 109 m +1122 108 l +1121 109 l +f +*U +0.000 0.369 0.263 0.341 k +*u +1347 109 m +1348 108 l +1347 109 l +f +*U +0.000 0.310 0.235 0.071 k +*u +1391 109 m +1392 108 l +1391 109 l +f +*U +0.000 0.227 0.220 0.212 k +*u +1076 108 m +1077 107 l +1076 108 l +f +*U +0.000 0.584 0.471 0.416 k +*u +1077 108 m +1078 107 l +1077 108 l +f +*U +0.000 0.341 0.275 0.290 k +*u +1122 108 m +1123 107 l +1122 108 l +f +*U +0.000 0.282 0.204 0.133 k +*u +1345 108 m +1346 107 l +1345 108 l +f +*U +0.000 0.184 0.169 0.176 k +*u +1077 107 m +1078 106 l +1077 107 l +f +*U +0.000 0.486 0.408 0.514 k +*u +1078 107 m +1079 106 l +1078 107 l +f +*U +0.000 0.592 0.431 0.392 k +*u +1122.667 106.667 m +1122.222 106.222 1123.278 106.278 1123.333 106.333 c +1123.778 106.778 1122.722 106.722 1122.667 106.667 c +f +*U +0.000 0.380 0.282 0.082 k +*u +1124 107 m +1125 106 l +1124 107 l +f +*U +0.000 0.620 0.447 0.353 k +*u +1344.667 106.667 m +1344.223 106.223 1345.278 106.278 1345.333 106.333 c +1345.778 106.778 1344.722 106.722 1344.667 106.667 c +f +*U +0.000 0.561 0.455 0.439 k +*u +1387 107 m +1388 106 l +1387 107 l +f +*U +0.000 0.322 0.243 0.267 k +*u +1388 107 m +1389 106 l +1388 107 l +f +*U +0.000 0.663 0.518 0.271 k +*u +1079 106 m +1080.543 104.733 1081 104.511 1083 104 c +1081.457 105.267 1080.952 105.489 1079 106 c +f +*U +0.000 0.761 0.576 0.239 k +*u +1125 106 m +1125.980 104.217 1125.908 104.406 1128 104 c +1126.861 105 1126.388 105.309 1125 106 c +f +*U +0.000 0.275 0.235 0.161 k +*u +1126 106 m +1127 105 l +1126 106 l +f +*U +0.000 0.373 0.255 0.208 k +*u +1342 106 m +1343 105 l +1342 106 l +f +*U +0.000 0.365 0.290 0.635 k +*u +1343 106 m +1344 105 l +1343 106 l +f +*U +0.000 0.455 0.404 0.545 k +*u +1386 106 m +1387 105 l +1386 106 l +f +*U +0.000 0.298 0.239 0.278 k +*u +1387 106 m +1388 105 l +1387 106 l +f +*U +0.102 0.000 0.027 0.137 k +*u +1128 105 m +1129 104 l +1128 105 l +f +*U +0.000 0.251 0.161 0.129 k +*u +1340 105 m +1341 104 l +1340 105 l +f +*U +0.000 0.655 0.506 0.345 k +*u +1341.667 104.667 m +1341.222 104.223 1342.278 104.278 1342.333 104.333 c +1342.778 104.778 1341.722 104.722 1341.667 104.667 c +f +*U +0.000 0.490 0.471 0.510 k +*u +1385 105 m +1386 104 l +1385 105 l +f +*U +0.000 0.286 0.251 0.141 k +*u +1386 105 m +1387 104 l +1386 105 l +f +*U +0.000 0.098 0.067 0.231 k +*u +1081 104 m +1082 103 l +1081 104 l +f +*U +0.000 0.455 0.322 0.545 k +*u +1082 104 m +1083 103 l +1082 104 l +f +*U +0.000 0.510 0.384 0.490 k +*u +1128 104 m +1129 103 l +1128 104 l +f +*U +0.000 0.439 0.310 0.278 k +*u +1129 104 m +1130 103 l +1129 104 l +f +*U +0.000 0.580 0.490 0.420 k +*u +1338 102 m +1339.581 102.684 1339.777 102.804 1341 104 c +1339.420 103.317 1339.223 103.195 1338 102 c +f +*U +0.000 0.753 0.686 0.192 k +*u +1380 104 m +1380 100 l +1384 102 l +1382.542 103 1381.752 103.436 1380 104 c +f +*U +0.000 0.075 0.039 0.651 k +*u +1384 104 m +1385 103 l +1384 104 l +f +*U +0.000 0.678 0.486 0.322 k +*u +1083.667 102.667 m +1083.222 102.222 1084.278 102.278 1084.333 102.333 c +1084.778 102.778 1083.722 102.722 1083.667 102.667 c +f +*U +0.000 0.463 0.361 0.537 k +*u +1130 103 m +1131 102 l +1130 103 l +f +*U +0.000 0.325 0.235 0.329 k +*u +1131 103 m +1132 102 l +1131 103 l +f +*U +0.000 0.322 0.267 0.361 k +*u +1337 103 m +1338 102 l +1337 103 l +f +*U +0.000 0.365 0.259 0.322 k +*u +1084 102 m +1085 101 l +1084 102 l +f +*U +0.000 0.561 0.451 0.439 k +*u +1085 102 m +1086 101 l +1085 102 l +f +*U +0.000 0.522 0.388 0.478 k +*u +1132 102 m +1133 101 l +1132 102 l +f +*U +0.000 0.325 0.224 0.337 k +*u +1133 102 m +1134 101 l +1133 102 l +f +*U +0.000 0.294 0.247 0.306 k +*u +1335 102 m +1336 101 l +1335 102 l +f +*U +0.000 0.620 0.514 0.380 k +*u +1336.667 101.667 m +1336.222 101.223 1337.278 101.278 1337.333 101.333 c +1337.778 101.778 1336.722 101.722 1336.667 101.667 c +f +*U +0.000 0.306 0.337 0.243 k +*u +1382 102 m +1383 101 l +1382 102 l +f +*U +0.000 0.255 0.188 0.098 k +*u +1085 101 m +1086 100 l +1085 101 l +f +*U +0.000 0.651 0.514 0.349 k +*u +1133 101 m +1134.543 99.733 1135 99.511 1137 99 c +1135.542 100 1134.752 100.436 1133 101 c +f +*U +0.000 0.388 0.282 0.212 k +*u +1135 101 m +1136 100 l +1135 101 l +f +*U +0.000 0.286 0.267 0.306 k +*u +1333 101 m +1334 100 l +1333 101 l +f +*U +0.000 0.494 0.471 0.506 k +*u +1334 101 m +1335 100 l +1334 101 l +f +*U +0.000 0.224 0.216 0.235 k +*u +1381 101 m +1382 100 l +1381 101 l +f +*U +0.000 0.329 0.235 0.525 k +*u +1087 100 m +1088 99 l +1087 100 l +f +*U +0.000 0.392 0.247 0.267 k +*u +1137 100 m +1138 99 l +1137 100 l +f +*U +0.000 0.278 0.231 0.239 k +*u +1331 100 m +1332 99 l +1331 100 l +f +*U +0.000 0.631 0.502 0.369 k +*u +1332.667 99.667 m +1332.222 99.222 1333.278 99.278 1333.333 99.333 c +1333.778 99.778 1332.722 99.722 1332.667 99.667 c +f +*U +0.000 0.722 0.600 0.204 k +*u +1373 96 m +1375.403 96.628 1376.958 97.562 1379 99 c +1376 99.483 1374.593 98.410 1373 96 c +f +*U +0.000 0.392 0.235 0.275 k +*u +1379 100 m +1380 99 l +1379 100 l +f +*U +0.000 0.533 0.361 0.165 k +*u +1088 99 m +1089 98 l +1088 99 l +f +*U +0.000 0.584 0.471 0.416 k +*u +1089 99 m +1090.223 97.805 1090.420 97.684 1092 97 c +1090.777 98.195 1090.580 98.316 1089 99 c +f +*U +0.000 0.478 0.392 0.522 k +*u +1138 99 m +1139 98 l +1138 99 l +f +*U +0.000 0.294 0.239 0.318 k +*u +1139 99 m +1140 98 l +1139 99 l +f +*U +0.000 0.251 0.208 0.165 k +*u +1329 99 m +1330 98 l +1329 99 l +f +*U +0.000 0.647 0.533 0.353 k +*u +1330.667 98.667 m +1330.222 98.223 1331.278 98.278 1331.333 98.333 c +1331.778 98.778 1330.722 98.722 1330.667 98.667 c +f +*U +0.000 0.243 0.235 0.357 k +*u +1378 99 m +1379 98 l +1378 99 l +f +*U +0.000 0.396 0.318 0.220 k +*u +1141 98 m +1142 97 l +1141 98 l +f +*U +0.000 0.278 0.235 0.239 k +*u +1327 98 m +1328 97 l +1327 98 l +f +*U +0.000 0.635 0.475 0.329 k +*u +1328.667 97.667 m +1328.222 97.222 1329.278 97.278 1329.333 97.333 c +1329.778 97.778 1328.722 97.722 1328.667 97.667 c +f +*U +0.000 0.349 0.271 0.506 k +*u +1376 98 m +1377 97 l +1376 98 l +f +*U +0.000 0.247 0.161 0.118 k +*u +1377 98 m +1378 97 l +1377 98 l +f +*U +0.000 0.482 0.420 0.114 k +*u +1091 97 m +1092 96 l +1091 97 l +f +*U +0.000 0.541 0.541 0.459 k +*u +1092 97 m +1093 96 l +1092 97 l +f +*U +0.000 0.588 0.459 0.412 k +*u +1141.667 96.667 m +1141.222 96.222 1142.278 96.278 1142.333 96.333 c +1142.778 96.778 1141.722 96.722 1141.667 96.667 c +f +*U +0.000 0.263 0.204 0.145 k +*u +1325 97 m +1326 96 l +1325 97 l +f +*U +0.000 0.522 0.396 0.392 k +*u +1326.667 96.667 m +1326.222 96.223 1327.278 96.278 1327.333 96.333 c +1327.778 96.778 1326.722 96.722 1326.667 96.667 c +f +*U +0.000 0.725 0.518 0.275 k +*u +1333.667 96.667 m +1333.222 96.222 1334.278 96.278 1334.333 96.333 c +1334.778 96.778 1333.722 96.722 1333.667 96.667 c +f +*U +0.000 0.514 0.337 0.435 k +*u +1093 96 m +1094 94.985 1094.611 94.691 1096 94 c +1095 95.783 1095 95.594 1093 96 c +f +*U +0.000 0.365 0.267 0.031 k +*u +1146 96 m +1147 95 l +1146 96 l +f +*U +0.000 0.416 0.322 0.243 k +*u +1323 96 m +1324 95 l +1323 96 l +f +*U +0.000 0.482 0.376 0.518 k +*u +1373 96 m +1374 95 l +1373 96 l +f +*U +0.000 0.224 0.169 0.196 k +*u +1374 96 m +1375 95 l +1374 96 l +f +*U +0.000 0.427 0.286 0.114 k +*u +1094 95 m +1095 94 l +1094 95 l +f +*U +0.000 0.522 0.369 0.475 k +*u +1146.667 94.667 m +1146.222 94.222 1147.278 94.278 1147.333 94.333 c +1147.778 94.778 1146.722 94.722 1146.667 94.667 c +f +*U +0.000 0.349 0.251 0.094 k +*u +1148 95 m +1149 94 l +1148 95 l +f +*U +0.000 0.353 0.267 0.082 k +*u +1320 95 m +1321 94 l +1320 95 l +f +*U +0.000 0.627 0.455 0.310 k +*u +1321.667 94.667 m +1321.222 94.222 1322.278 94.278 1322.333 94.333 c +1322.778 94.778 1321.722 94.722 1321.667 94.667 c +f +*U +0.000 0.690 0.506 0.294 k +*u +1326 95 m +1326.545 93.365 1326.365 93.545 1328 93 c +1328 95 l +1326 95 l +f +*U +0.000 0.412 0.318 0.451 k +*u +1372 95 m +1373 94 l +1372 95 l +f +*U +0.000 0.204 0.133 0.133 k +*u +1095 94 m +1096 93 l +1095 94 l +f +*U +0.000 0.471 0.392 0.529 k +*u +1096 94 m +1097 93 l +1096 94 l +f +*U +0.000 0.471 0.349 0.529 k +*u +1149 94 m +1150 93 l +1149 94 l +f +*U +0.000 0.278 0.204 0.329 k +*u +1150 94 m +1151 93 l +1150 94 l +f +*U +0.000 0.357 0.255 0.016 k +*u +1318 94 m +1319 93 l +1318 94 l +f +*U +0.000 0.565 0.475 0.435 k +*u +1370 94 m +1371 93 l +1370 94 l +f +*U +0.000 0.353 0.275 0.047 k +*u +1371 94 m +1372 93 l +1371 94 l +f +*U +0.000 0.349 0.251 0.322 k +*u +1097 93 m +1098 92 l +1097 93 l +f +*U +0.000 0.427 0.302 0.478 k +*u +1151.667 92.667 m +1151.222 92.222 1152.278 92.278 1152.333 92.333 c +1152.778 92.778 1151.722 92.722 1151.667 92.667 c +f +*U +0.000 0.212 0.161 0.153 k +*u +1153 93 m +1154 92 l +1153 93 l +f +*U +0.000 0.282 0.227 0.263 k +*u +1316 93 m +1317 92 l +1316 93 l +f +*U +0.000 0.431 0.431 0.569 k +*u +1368 93 m +1369 92 l +1368 93 l +f +*U +0.000 0.431 0.325 0.361 k +*u +1369 93 m +1370 92 l +1369 93 l +f +*U +0.000 0.125 0.102 0.129 k +*u +1098 92 m +1099 91 l +1098 92 l +f +*U +0.000 0.682 0.545 0.318 k +*u +1099.667 91.667 m +1099.222 91.222 1100.278 91.278 1100.333 91.333 c +1100.778 91.778 1099.722 91.722 1099.667 91.667 c +f +*U +0.000 0.737 0.545 0.263 k +*u +1152 92 m +1153.458 90.919 1154.248 90.564 1156 90 c +1154.457 91.267 1153.952 91.489 1152 92 c +f +*U +0.000 0.431 0.306 0.275 k +*u +1155 92 m +1156 91 l +1155 92 l +f +*U +0.000 0.051 0.055 0.149 k +*u +1156 92 m +1157 91 l +1156 92 l +f +*U +0.000 0.243 0.184 0.149 k +*u +1313 92 m +1314 91 l +1313 92 l +f +*U +0.000 0.624 0.478 0.333 k +*u +1314.667 91.667 m +1314.222 91.223 1315.278 91.278 1315.333 91.333 c +1315.778 91.778 1314.722 91.722 1314.667 91.667 c +f +*U +0.000 0.639 0.475 0.361 k +*u +1366.667 91.667 m +1366.223 91.223 1367.278 91.278 1367.333 91.333 c +1367.778 91.778 1366.722 91.722 1366.667 91.667 c +f +*U +0.000 0.184 0.153 0.263 k +*u +1368 92 m +1369 91 l +1368 92 l +f +*U +0.000 0.341 0.247 0.271 k +*u +1100 91 m +1101 90 l +1100 91 l +f +*U +0.000 0.737 0.573 0.263 k +*u +1101.667 90.667 m +1101.222 90.222 1102.278 90.278 1102.333 90.333 c +1102.778 90.778 1101.722 90.722 1101.667 90.667 c +f +*U +0.000 0.443 0.333 0.486 k +*u +1156.667 90.667 m +1156.222 90.222 1157.278 90.278 1157.333 90.333 c +1157.778 90.778 1156.722 90.722 1156.667 90.667 c +f +*U +0.000 0.227 0.196 0.204 k +*u +1158 91 m +1159 90 l +1158 91 l +f +*U +0.000 0.259 0.231 0.192 k +*u +1311 91 m +1312 90 l +1311 91 l +f +*U +0.000 0.392 0.282 0.435 k +*u +1365.667 90.667 m +1365.222 90.222 1366.278 90.278 1366.333 90.333 c +1366.778 90.778 1365.722 90.722 1365.667 90.667 c +f +*U +0.000 0.435 0.365 0.565 k +*u +1102.667 89.667 m +1102.222 89.222 1103.278 89.278 1103.333 89.333 c +1103.778 89.778 1102.722 89.722 1102.667 89.667 c +f +*U +0.000 0.451 0.451 0.549 k +*u +1159 90 m +1160 89 l +1159 90 l +f +*U +0.000 0.286 0.184 0.475 k +*u +1160 90 m +1161 89 l +1160 90 l +f +*U +0.000 0.263 0.173 0.118 k +*u +1161 90 m +1162 89 l +1161 90 l +f +*U +0.000 0.298 0.243 0.204 k +*u +1308 90 m +1309 89 l +1308 90 l +f +*U +0.000 0.580 0.447 0.408 k +*u +1309 90 m +1310.249 89.315 1310.548 89.251 1312 89 c +1310.752 89.685 1310.452 89.749 1309 90 c +f +*U +0.000 0.541 0.408 0.459 k +*u +1363 90 m +1363 88 l +1364.635 88.545 1364.455 88.365 1365 90 c +1363 90 l +f +*U +0.000 0.322 0.235 0.035 k +*u +1365 90 m +1366 89 l +1365 90 l +f +*U +0.067 0.000 0.067 0.176 k +*u +1103 89 m +1104 88 l +1103 89 l +f +*U +0.000 0.475 0.329 0.525 k +*u +1161.667 88.667 m +1161.222 88.222 1162.278 88.278 1162.333 88.333 c +1162.778 88.778 1161.722 88.722 1161.667 88.667 c +f +*U +0.000 0.278 0.176 0.412 k +*u +1163 89 m +1164 88 l +1163 89 l +f +*U +0.000 0.094 0.059 0.137 k +*u +1164 89 m +1165 88 l +1164 89 l +f +*U +0.000 0.094 0.055 0.208 k +*u +1305 89 m +1306 88 l +1305 89 l +f +*U +0.000 0.580 0.447 0.420 k +*u +1306.667 88.667 m +1306.222 88.222 1307.278 88.278 1307.333 88.333 c +1307.778 88.778 1306.722 88.722 1306.667 88.667 c +f +*U +0.000 0.271 0.200 0.349 k +*u +1105 88 m +1106 87 l +1105 88 l +f +*U +0.000 0.690 0.557 0.310 k +*u +1106.667 87.667 m +1106.222 87.222 1107.278 87.278 1107.333 87.333 c +1107.778 87.778 1106.722 87.722 1106.667 87.667 c +f +*U +0.000 0.588 0.447 0.412 k +*u +1164.667 87.667 m +1164.222 87.222 1165.278 87.278 1165.333 87.333 c +1165.778 87.778 1164.722 87.722 1164.667 87.667 c +f +*U +0.000 0.710 0.522 0.255 k +*u +1165 87 m +1166.506 86.317 1167.315 86.174 1169 86 c +1167.265 87 1167 87 1165 87 c +f +*U +0.000 0.486 0.365 0.000 k +*u +1167 88 m +1168 87 l +1167 88 l +f +*U +0.000 0.235 0.263 0.090 k +*u +1302 88 m +1303 87 l +1302 88 l +f +*U +0.000 0.298 0.314 0.455 k +*u +1303 88 m +1304 87 l +1303 88 l +f +*U +0.000 0.400 0.255 0.498 k +*u +1360.667 87.667 m +1360.222 87.222 1361.278 87.278 1361.333 87.333 c +1361.778 87.778 1360.722 87.722 1360.667 87.667 c +f +*U +0.000 0.220 0.141 0.165 k +*u +1362 88 m +1363 87 l +1362 88 l +f +*U +0.000 0.329 0.251 0.416 k +*u +1107 87 m +1108 86 l +1107 87 l +f +*U +0.000 0.494 0.345 0.235 k +*u +1169 87 m +1170 86 l +1169 87 l +f +*U +0.000 0.263 0.192 0.000 k +*u +1170 87 m +1171 86 l +1170 87 l +f +*U +0.000 0.271 0.227 0.118 k +*u +1299 87 m +1300 86 l +1299 87 l +f +*U +0.000 0.431 0.349 0.404 k +*u +1300 87 m +1301 86 l +1300 87 l +f +*U +0.000 0.612 0.545 0.388 k +*u +1301.667 86.667 m +1301.222 86.222 1302.278 86.278 1302.333 86.333 c +1302.778 86.778 1301.722 86.722 1301.667 86.667 c +f +*U +0.000 0.329 0.216 0.224 k +*u +1360 87 m +1361 86 l +1360 87 l +f +*U +0.000 0.263 0.192 0.078 k +*u +1108 86 m +1109 85 l +1108 86 l +f +*U +0.000 0.612 0.498 0.388 k +*u +1109.667 85.667 m +1109.222 85.222 1110.278 85.278 1110.333 85.333 c +1110.778 85.778 1109.722 85.722 1109.667 85.667 c +f +*U +0.000 0.616 0.486 0.384 k +*u +1170.667 85.667 m +1170.222 85.222 1171.278 85.278 1171.333 85.333 c +1171.778 85.778 1170.722 85.722 1170.667 85.667 c +f +*U +0.000 0.322 0.220 0.106 k +*u +1173 86 m +1174 85 l +1173 86 l +f +*U +0.000 0.369 0.314 0.224 k +*u +1296 86 m +1297 85 l +1296 86 l +f +*U +0.000 0.565 0.447 0.435 k +*u +1297.667 85.667 m +1297.223 85.223 1298.278 85.278 1298.333 85.333 c +1298.778 85.778 1297.722 85.722 1297.667 85.667 c +f +*U +0.000 0.416 0.294 0.502 k +*u +1358 86 m +1359 85 l +1358 86 l +f +*U +0.000 0.294 0.220 0.016 k +*u +1110 85 m +1111 84 l +1110 85 l +f +*U +0.000 0.737 0.561 0.263 k +*u +1111.667 84.667 m +1111.222 84.222 1112.278 84.278 1112.333 84.333 c +1112.778 84.778 1111.722 84.722 1111.667 84.667 c +f +*U +0.000 0.439 0.349 0.561 k +*u +1174.667 84.667 m +1174.222 84.223 1175.278 84.278 1175.333 84.333 c +1175.778 84.778 1174.722 84.722 1174.667 84.667 c +f +*U +0.000 0.259 0.192 0.306 k +*u +1176 85 m +1177 84 l +1176 85 l +f +*U +0.000 0.208 0.169 0.098 k +*u +1177 85 m +1178 84 l +1177 85 l +f +*U +0.000 0.110 0.090 0.192 k +*u +1292 85 m +1293 84 l +1292 85 l +f +*U +0.000 0.753 0.588 0.247 k +*u +1288 83 m +1291 82 1293.942 82.554 1296 85 c +1293.225 84.590 1290.673 83.851 1288 83 c +f +*U +0.000 0.545 0.388 0.455 k +*u +1356 85 m +1357 84 l +1356 85 l +f +*U +0.000 0.243 0.180 0.141 k +*u +1357 85 m +1358 84 l +1357 85 l +f +*U +0.000 0.447 0.322 0.239 k +*u +1112 84 m +1113 83 l +1112 84 l +f +*U +0.000 0.533 0.380 0.467 k +*u +1113 84 m +1114 83 l +1113 84 l +f +*U +0.000 0.663 0.565 0.271 k +*u +1176 84 m +1177.377 83 1178.440 82.596 1180 82 c +1178.686 83.618 1178 83.693 1176 84 c +f +*U +0.000 0.373 0.357 0.239 k +*u +1180 84 m +1181 83 l +1180 84 l +f +*U +0.000 0.208 0.227 0.055 k +*u +1181 84 m +1182 83 l +1181 84 l +f +*U +0.000 0.173 0.137 0.153 k +*u +1288 84 m +1289 83 l +1288 84 l +f +*U +0.000 0.310 0.224 0.290 k +*u +1289 84 m +1290 83 l +1289 84 l +f +*U +0.000 0.557 0.427 0.443 k +*u +1354 84 m +1355 83 l +1354 84 l +f +*U +0.000 0.294 0.216 0.349 k +*u +1355 84 m +1356 83 l +1355 84 l +f +*U +0.000 0.549 0.420 0.451 k +*u +1114.667 82.667 m +1114.222 82.222 1115.278 82.278 1115.333 82.333 c +1115.778 82.778 1114.722 82.722 1114.667 82.667 c +f +*U +0.000 0.612 0.514 0.388 k +*u +1180 83 m +1181.506 82.317 1182.315 82.174 1184 82 c +1182.494 82.683 1181.685 82.826 1180 83 c +f +*U +0.000 0.196 0.141 0.314 k +*u +1184 83 m +1185 82 l +1184 83 l +f +*U +0.000 0.188 0.141 0.137 k +*u +1185 83 m +1186 82 l +1185 83 l +f +*U +0.000 0.255 0.188 0.051 k +*u +1284 83 m +1285 82 l +1284 83 l +f +*U +0.000 0.333 0.239 0.255 k +*u +1285 83 m +1286 82 l +1285 83 l +f +*U +0.000 0.424 0.302 0.569 k +*u +1287 83 m +1288 82 l +1287 83 l +f +*U +0.000 0.565 0.431 0.373 k +*u +1348 81 m +1350.274 80.591 1351.781 81.212 1354 82 c +1351.538 82.697 1350.335 82 1348 81 c +f +*U +0.000 0.184 0.141 0.086 k +*u +1115 82 m +1116 81 l +1115 82 l +f +*U +0.000 0.584 0.408 0.365 k +*u +1116 82 m +1117.458 80.919 1118.248 80.564 1120 80 c +1118.457 81.267 1117.952 81.489 1116 82 c +f +*U +0.000 0.678 0.498 0.322 k +*u +1185 82 m +1186.249 81.315 1186.548 81.251 1188 81 c +1186.752 81.685 1186.451 81.749 1185 82 c +f +*U +0.000 0.388 0.275 0.322 k +*u +1188 82 m +1189 81 l +1188 82 l +f +*U +0.000 0.212 0.161 0.212 k +*u +1189 82 m +1190 81 l +1189 82 l +f +*U +0.000 0.416 0.286 0.078 k +*u +1280 82 m +1281 81 l +1280 82 l +f +*U +0.000 0.600 0.451 0.400 k +*u +1281 82 m +1282.769 81.221 1284 81 1286 81 c +1284.231 81.779 1282.964 81.912 1281 82 c +f +*U +0.000 0.059 0.043 0.149 k +*u +1352 82 m +1353 81 l +1352 82 l +f +*U +0.000 0.278 0.212 0.090 k +*u +1117 81 m +1118 80 l +1117 81 l +f +*U +0.000 0.667 0.537 0.333 k +*u +1190.667 80.667 m +1190.222 80.222 1191.278 80.278 1191.333 80.333 c +1191.778 80.778 1190.722 80.722 1190.667 80.667 c +f +*U +0.000 0.361 0.243 0.639 k +*u +1192 81 m +1193 80 l +1192 81 l +f +*U +0.000 0.345 0.224 0.439 k +*u +1193 81 m +1194 80 l +1193 81 l +f +*U +0.000 0.263 0.173 0.255 k +*u +1194 81 m +1195 80 l +1194 81 l +f +*U +0.000 0.153 0.098 0.129 k +*u +1195 81 m +1196 80 l +1195 81 l +f +*U +0.000 0.157 0.098 0.255 k +*u +1275 81 m +1276 80 l +1275 81 l +f +*U +0.000 0.349 0.227 0.322 k +*u +1276 81 m +1277 80 l +1276 81 l +f +*U +0.000 0.612 0.435 0.388 k +*u +1277 81 m +1278.249 80.315 1278.548 80.251 1280 80 c +1278.752 80.685 1278.452 80.749 1277 81 c +f +*U +0.000 0.310 0.267 0.129 k +*u +1350 81 m +1351 80 l +1350 81 l +f +*U +0.000 0.416 0.345 0.584 k +*u +1120.667 79.667 m +1120.222 79.222 1121.278 79.278 1121.333 79.333 c +1121.778 79.778 1120.722 79.722 1120.667 79.667 c +f +*U +0.000 0.278 0.227 0.098 k +*u +1268 80 m +1269.249 79.315 1269.548 79.251 1271 79 c +1269.752 79.685 1269.452 79.749 1268 80 c +f +*U +0.000 0.737 0.541 0.263 k +*u +1268 79 m +1270.698 78 1273 78.647 1276 79 c +1273.244 80 1270.893 79.532 1268 79 c +f +*U +0.000 0.302 0.196 0.569 k +*u +1346.667 79.667 m +1346.223 79.223 1347.278 79.278 1347.333 79.333 c +1347.778 79.778 1346.722 79.722 1346.667 79.667 c +f +*U +0.000 0.102 0.063 0.220 k +*u +1348 80 m +1349 79 l +1348 80 l +f +*U +0.000 0.176 0.141 0.110 k +*u +1121 79 m +1122 78 l +1121 79 l +f +*U +0.000 0.616 0.478 0.384 k +*u +1122.667 78.667 m +1122.222 78.222 1123.278 78.278 1123.333 78.333 c +1123.778 78.778 1122.722 78.722 1122.667 78.667 c +f +*U +0.000 0.514 0.392 0.486 k +*u +1202 79 m +1203.249 78.315 1203.548 78.251 1205 78 c +1203.752 78.685 1203.452 78.749 1202 79 c +f +*U +0.000 0.259 0.180 0.251 k +*u +1205.667 78.667 m +1205.222 78.222 1206.278 78.278 1206.333 78.333 c +1206.778 78.778 1205.722 78.722 1205.667 78.667 c +f +*U +0.000 0.063 0.039 0.149 k +*u +1207.667 78.667 m +1207.222 78.222 1208.278 78.278 1208.333 78.333 c +1208.778 78.778 1207.722 78.722 1207.667 78.667 c +f +*U +0.000 0.188 0.133 0.184 k +*u +1260.667 78.667 m +1260.222 78.223 1261.278 78.278 1261.333 78.333 c +1261.778 78.778 1260.722 78.722 1260.667 78.667 c +f +*U +0.000 0.239 0.161 0.322 k +*u +1262.667 78.667 m +1262.222 78.222 1263.278 78.278 1263.333 78.333 c +1263.778 78.778 1262.722 78.722 1262.667 78.667 c +f +*U +0.000 0.569 0.392 0.384 k +*u +1264 79 m +1265.506 78.317 1266.315 78.174 1268 78 c +1266.494 78.683 1265.685 78.826 1264 79 c +f +*U +0.000 0.561 0.369 0.439 k +*u +1344.667 78.667 m +1344.223 78.223 1345.278 78.278 1345.333 78.333 c +1345.778 78.778 1344.722 78.722 1344.667 78.667 c +f +*U +0.000 0.373 0.247 0.118 k +*u +1346 79 m +1347 78 l +1346 79 l +f +*U +0.000 0.627 0.463 0.373 k +*u +1124.667 77.667 m +1124.222 77.222 1125.278 77.278 1125.333 77.333 c +1125.778 77.778 1124.722 77.722 1124.667 77.667 c +f +*U +0.000 0.627 0.439 0.373 k +*u +1208 78 m +1209.249 77.315 1209.548 77.251 1211 77 c +1209.752 77.685 1209.452 77.749 1208 78 c +f +*U +0.000 0.482 0.416 0.518 k +*u +1211 78 m +1212.249 77.315 1212.548 77.251 1214 77 c +1212.752 77.685 1212.452 77.749 1211 78 c +f +*U +0.000 0.278 0.231 0.224 k +*u +1215.667 77.667 m +1215.222 77.222 1216.278 77.278 1216.333 77.333 c +1216.778 77.778 1215.722 77.722 1215.667 77.667 c +f +*U +0.000 0.231 0.192 0.137 k +*u +1217 78 m +1218.506 77.317 1219.315 77.174 1221 77 c +1219.494 77.683 1218.685 77.826 1217 78 c +f +*U +0.000 0.212 0.082 0.129 k +*u +1249 78 m +1250.506 77.317 1251.315 77.174 1253 77 c +1251.494 77.683 1250.685 77.826 1249 78 c +f +*U +0.000 0.349 0.251 0.216 k +*u +1253 78 m +1254.249 77.315 1254.548 77.251 1256 77 c +1254.752 77.685 1254.451 77.749 1253 78 c +f +*U +0.000 0.506 0.416 0.494 k +*u +1256 78 m +1257.249 77.315 1257.548 77.251 1259 77 c +1257.752 77.685 1257.451 77.749 1256 78 c +f +*U +0.000 0.702 0.537 0.298 k +*u +1259 78 m +1260.249 77.315 1260.548 77.251 1262 77 c +1260.752 77.685 1260.452 77.749 1259 78 c +f +*U +0.000 0.631 0.471 0.325 k +*u +1341 78 m +1342.249 77.315 1342.548 77.251 1344 77 c +1342.752 77.685 1342.451 77.749 1341 78 c +f +*U +0.000 0.204 0.129 0.286 k +*u +1344 78 m +1345 77 l +1344 78 l +f +*U +0.000 0.255 0.188 0.047 k +*u +1125 77 m +1126 76 l +1125 77 l +f +*U +0.000 0.659 0.455 0.314 k +*u +1126 77 m +1127.750 75.745 1128.857 75.386 1131 75 c +1129.249 76.255 1128 76.614 1126 77 c +f +*U +0.000 0.729 0.596 0.271 k +*u +1219 77 m +1220.769 76.221 1222 76 1224 76 c +1222.231 76.779 1220.964 76.912 1219 77 c +f +*U +0.000 0.447 0.353 0.553 k +*u +1224 77 m +1226.613 75.902 1229 76 1232 76 c +1229.387 77 1226.836 76.993 1224 77 c +f +*U +0.000 0.541 0.380 0.447 k +*u +1232 77 m +1234.613 75.902 1237 76 1240 76 c +1237.387 77 1234.835 76.993 1232 77 c +f +*U +0.000 0.478 0.373 0.522 k +*u +1240 77 m +1242.613 75.902 1245 76 1248 76 c +1245.387 77 1242.836 76.993 1240 77 c +f +*U +0.000 0.753 0.690 0.247 k +*u +1248 77 m +1249.249 76.315 1249.548 76.251 1251 76 c +1249.752 76.685 1249.452 76.749 1248 77 c +f +*U +0.000 0.894 0.922 0.078 k +*u +1251 77 m +1252.506 76.317 1253.315 76.174 1255 76 c +1253.494 76.683 1252.685 76.826 1251 77 c +f +*U +0.000 0.427 0.400 0.573 k +*u +1340.667 76.667 m +1340.222 76.222 1341.278 76.278 1341.333 76.333 c +1341.778 76.778 1340.722 76.722 1340.667 76.667 c +f +*U +0.000 0.294 0.247 0.184 k +*u +1342 77 m +1343 76 l +1342 77 l +f +*U +0.000 0.043 0.047 0.216 k +*u +1127 76 m +1128 75 l +1127 76 l +f +*U +0.000 0.533 0.443 0.467 k +*u +1338.667 75.667 m +1338.222 75.222 1339.278 75.278 1339.333 75.333 c +1339.778 75.778 1338.722 75.722 1338.667 75.667 c +f +*U +0.000 0.404 0.322 0.141 k +*u +1340 76 m +1341 75 l +1340 76 l +f +*U +0.000 0.365 0.263 0.231 k +*u +1130 75 m +1131 74 l +1130 75 l +f +*U +0.000 0.733 0.529 0.267 k +*u +1131.667 74.667 m +1131.222 74.222 1132.278 74.278 1132.333 74.333 c +1132.778 74.778 1131.722 74.722 1131.667 74.667 c +f +*U +0.000 0.510 0.400 0.447 k +*u +1336.667 74.667 m +1336.222 74.223 1337.278 74.278 1337.333 74.333 c +1337.778 74.778 1336.722 74.722 1336.667 74.667 c +f +*U +0.000 0.325 0.271 0.063 k +*u +1338 75 m +1339 74 l +1338 75 l +f +*U +0.000 0.349 0.243 0.271 k +*u +1132 74 m +1133 73 l +1132 74 l +f +*U +0.000 0.722 0.486 0.278 k +*u +1133 74 m +1134 72.985 1134.611 72.691 1136 72 c +1135 73.783 1135 73.594 1133 74 c +f +*U +0.000 0.565 0.549 0.357 k +*u +1331 73 m +1332.846 72.533 1334 72.699 1336 73 c +1333.955 73.775 1333 73.592 1331 73 c +f +*U +0.000 0.208 0.196 0.208 k +*u +1336 74 m +1337 73 l +1336 74 l +f +*U +0.000 0.427 0.278 0.000 k +*u +1134 73 m +1135 72 l +1134 73 l +f +*U +0.000 0.341 0.369 0.298 k +*u +1333 73 m +1334 72 l +1333 73 l +f +*U +0.000 0.137 0.173 0.098 k +*u +1334 73 m +1335 72 l +1334 73 l +f +*U +0.000 0.239 0.110 0.118 k +*u +1136 72 m +1137 71 l +1136 72 l +f +*U +0.000 0.345 0.200 0.396 k +*u +1137 72 m +1138 71 l +1137 72 l +f +*U +0.000 0.757 0.545 0.243 k +*u +1138 72 m +1139.750 70.745 1140.857 70.386 1143 70 c +1141.212 71.421 1140.294 71.697 1138 72 c +f +*U +0.000 0.788 0.620 0.212 k +*u +1326 70 m +1329 70 l +1328 72 l +1326.365 71.455 1326.545 71.635 1326 70 c +f +*U +0.000 0.486 0.314 0.514 k +*u +1329.667 71.667 m +1329.222 71.222 1330.278 71.278 1330.333 71.333 c +1330.778 71.778 1329.722 71.722 1329.667 71.667 c +f +*U +0.000 0.239 0.141 0.333 k +*u +1331 72 m +1332 71 l +1331 72 l +f +*U +0.000 0.271 0.169 0.290 k +*u +1139 71 m +1140 70 l +1139 71 l +f +*U +0.000 0.376 0.255 0.000 k +*u +1329 71 m +1330 70 l +1329 71 l +f +*U +0.000 0.463 0.325 0.271 k +*u +1142 70 m +1143 69 l +1142 70 l +f +*U +0.000 0.714 0.573 0.286 k +*u +1143.667 69.667 m +1143.222 69.222 1144.278 69.278 1144.333 69.333 c +1144.778 69.778 1143.722 69.722 1143.667 69.667 c +f +*U +0.000 0.333 0.255 0.282 k +*u +1326 70 m +1327 69 l +1326 70 l +f +*U +0.000 0.431 0.322 0.180 k +*u +1144 69 m +1145 68 l +1144 69 l +f +*U +0.000 0.545 0.420 0.455 k +*u +1145.667 68.667 m +1145.222 68.223 1146.278 68.278 1146.333 68.333 c +1146.778 68.778 1145.722 68.722 1145.667 68.667 c +f +*U +0.000 0.263 0.192 0.102 k +*u +1324 69 m +1325 68 l +1324 69 l +f +*U +0.000 0.267 0.200 0.275 k +*u +1147 68 m +1148 67 l +1147 68 l +f +*U +0.000 0.616 0.490 0.384 k +*u +1148.667 67.667 m +1148.222 67.222 1149.278 67.278 1149.333 67.333 c +1149.778 67.778 1148.722 67.722 1148.667 67.667 c +f +*U +0.000 0.796 0.620 0.204 k +*u +1152 68 m +1152.980 66.217 1152.908 66.406 1155 66 c +1153.860 67 1153.388 67.309 1152 68 c +f +*U +0.000 0.710 0.522 0.271 k +*u +1317 68 m +1318.506 67.317 1319.315 67.174 1321 67 c +1319.494 67.683 1318.685 67.826 1317 68 c +f +*U +0.000 0.388 0.278 0.322 k +*u +1321 68 m +1322 67 l +1321 68 l +f +*U +0.000 0.161 0.129 0.145 k +*u +1322 68 m +1323 67 l +1322 68 l +f +*U +0.000 0.286 0.208 0.067 k +*u +1149 67 m +1150 66 l +1149 67 l +f +*U +0.000 0.525 0.365 0.416 k +*u +1150.667 66.667 m +1150.222 66.222 1151.278 66.278 1151.333 66.333 c +1151.778 66.778 1150.722 66.722 1150.667 66.667 c +f +*U +0.000 0.518 0.384 0.447 k +*u +1316.667 66.667 m +1316.222 66.222 1317.278 66.278 1317.333 66.333 c +1317.778 66.778 1316.722 66.722 1316.667 66.667 c +f +*U +0.000 0.263 0.216 0.361 k +*u +1318 67 m +1319 66 l +1318 67 l +f +*U +0.000 0.118 0.122 0.180 k +*u +1319 67 m +1320 66 l +1319 67 l +f +*U +0.000 0.518 0.361 0.129 k +*u +1152 66 m +1153 65 l +1152 66 l +f +*U +0.000 0.576 0.471 0.416 k +*u +1153.667 65.667 m +1153.222 65.222 1154.278 65.278 1154.333 65.333 c +1154.778 65.778 1153.722 65.722 1153.667 65.667 c +f +*U +0.000 0.745 0.659 0.239 k +*u +1155 66 m +1156.789 64.578 1157.706 64.303 1160 64 c +1158.307 65 1156.960 65.520 1155 66 c +f +*U +0.000 0.502 0.341 0.396 k +*u +1312.333 65.333 m +1312.278 65.278 1312.223 64.222 1312.667 64.667 c +1312.722 64.722 1312.778 65.778 1312.333 65.333 c +f +*U +0.000 0.490 0.412 0.510 k +*u +1313 66 m +1314.249 65.315 1314.549 65.251 1316 65 c +1314.752 65.685 1314.451 65.749 1313 66 c +f +*U +0.000 0.333 0.243 0.137 k +*u +1316 66 m +1317 65 l +1316 66 l +f +*U +0.000 0.314 0.373 0.047 k +*u +1155 65 m +1156 64 l +1155 65 l +f +*U +0.000 0.749 0.710 0.251 k +*u +1310.667 64.667 m +1310.222 64.223 1311.278 64.278 1311.333 64.333 c +1311.778 64.778 1310.722 64.722 1310.667 64.667 c +f +*U +0.000 0.388 0.278 0.027 k +*u +1313 65 m +1314 64 l +1313 65 l +f +*U +0.008 0.024 0.000 0.220 k +*u +1158 64 m +1159 63 l +1158 64 l +f +*U +0.004 0.012 0.000 0.549 k +*u +1159 64 m +1160 63 l +1159 64 l +f +*U +0.000 0.631 0.455 0.369 k +*u +1160.667 63.667 m +1160.222 63.222 1161.278 63.278 1161.333 63.333 c +1161.778 63.778 1160.722 63.722 1160.667 63.667 c +f +*U +0.000 0.412 0.337 0.588 k +*u +1307 64 m +1308.249 63.315 1308.548 63.251 1310 63 c +1308.752 63.685 1308.452 63.749 1307 64 c +f +*U +0.000 0.239 0.192 0.153 k +*u +1310 64 m +1311 63 l +1310 64 l +f +*U +0.000 0.204 0.129 0.071 k +*u +1161 63 m +1162 62 l +1161 63 l +f +*U +0.000 0.325 0.216 0.302 k +*u +1162 63 m +1163 62 l +1162 63 l +f +*U +0.000 0.608 0.451 0.392 k +*u +1163 63 m +1164.249 62.315 1164.548 62.251 1166 62 c +1164.752 62.685 1164.451 62.749 1163 63 c +f +*U +0.000 0.576 0.455 0.424 k +*u +1304.667 62.667 m +1304.222 62.222 1305.278 62.278 1305.333 62.333 c +1305.778 62.778 1304.722 62.722 1304.667 62.667 c +f +*U +0.000 0.341 0.259 0.118 k +*u +1307 63 m +1308 62 l +1307 63 l +f +*U +0.000 0.318 0.231 0.129 k +*u +1165 62 m +1166 61 l +1165 62 l +f +*U +0.000 0.392 0.290 0.408 k +*u +1166 62 m +1167 61 l +1166 62 l +f +*U +0.000 0.565 0.420 0.435 k +*u +1167 62 m +1168.249 61.315 1168.548 61.251 1170 61 c +1168.752 61.685 1168.452 61.749 1167 62 c +f +*U +0.000 0.514 0.384 0.486 k +*u +1300 62 m +1301.249 61.315 1301.548 61.251 1303 61 c +1301.752 61.685 1301.451 61.749 1300 62 c +f +*U +0.000 0.322 0.212 0.145 k +*u +1303 62 m +1304 61 l +1303 62 l +f +*U +0.000 0.122 0.055 0.129 k +*u +1168 61 m +1169 60 l +1168 61 l +f +*U +0.000 0.220 0.161 0.318 k +*u +1169 61 m +1170 60 l +1169 61 l +f +*U +0.000 0.580 0.478 0.420 k +*u +1170.667 60.667 m +1170.222 60.222 1171.278 60.278 1171.333 60.333 c +1171.778 60.778 1170.722 60.722 1170.667 60.667 c +f +*U +0.000 0.600 0.431 0.373 k +*u +1293 60 m +1295 59.324 1296.732 59.613 1299 60 c +1296.761 60.811 1295.353 60.529 1293 60 c +f +*U +0.000 0.475 0.369 0.165 k +*u +1299 61 m +1300 60 l +1299 61 l +f +*U +0.000 0.314 0.263 0.047 k +*u +1300 61 m +1301 60 l +1300 61 l +f +*U +0.000 0.141 0.173 0.071 k +*u +1172 60 m +1173 59 l +1172 60 l +f +*U +0.000 0.325 0.255 0.306 k +*u +1173 60 m +1174 59 l +1173 60 l +f +*U +0.000 0.541 0.376 0.459 k +*u +1174 60 m +1175.506 59.317 1176.315 59.174 1178 59 c +1176.494 59.683 1175.685 59.826 1174 60 c +f +*U +0.000 0.161 0.098 0.282 k +*u +1296 60 m +1297 59 l +1296 60 l +f +*U +0.000 0.082 0.078 0.157 k +*u +1176 59 m +1177 58 l +1176 59 l +f +*U +0.000 0.247 0.184 0.239 k +*u +1177 59 m +1178 58 l +1177 59 l +f +*U +0.000 0.561 0.424 0.439 k +*u +1178 59 m +1179.506 58.317 1180.315 58.174 1182 58 c +1180.494 58.683 1179.685 58.826 1178 59 c +f +*U +0.000 0.663 0.486 0.337 k +*u +1288 59 m +1289.249 58.315 1289.548 58.251 1291 58 c +1289.752 58.685 1289.451 58.749 1288 59 c +f +*U +0.000 0.459 0.318 0.227 k +*u +1291 59 m +1292 58 l +1291 59 l +f +*U +0.000 0.129 0.086 0.071 k +*u +1292.667 58.667 m +1292.222 58.222 1293.278 58.278 1293.333 58.333 c +1293.778 58.778 1292.722 58.722 1292.667 58.667 c +f +*U +0.000 0.176 0.125 0.110 k +*u +1181 58 m +1182 57 l +1181 58 l +f +*U +0.000 0.478 0.325 0.267 k +*u +1182 58 m +1183 57 l +1182 58 l +f +*U +0.000 0.490 0.369 0.510 k +*u +1183 58 m +1184.249 57.315 1184.548 57.251 1186 57 c +1184.752 57.685 1184.452 57.749 1183 58 c +f +*U +0.000 0.631 0.498 0.369 k +*u +1282 58 m +1283.769 57.221 1285 57 1287 57 c +1285.231 57.779 1283.964 57.912 1282 58 c +f +*U +0.000 0.541 0.392 0.114 k +*u +1287 58 m +1288 57 l +1287 58 l +f +*U +0.000 0.239 0.157 0.082 k +*u +1186 57 m +1187 56 l +1186 57 l +f +*U +0.000 0.384 0.275 0.290 k +*u +1187 57 m +1188 56 l +1187 57 l +f +*U +0.000 0.573 0.525 0.427 k +*u +1188 57 m +1189.249 56.315 1189.548 56.251 1191 56 c +1189.752 56.685 1189.452 56.749 1188 57 c +f +*U +0.000 0.420 0.361 0.580 k +*u +1280 57 m +1281 56 l +1280 57 l +f +*U +0.000 0.482 0.353 0.216 k +*u +1281 57 m +1282 56 l +1281 57 l +f +*U +0.000 0.282 0.224 0.047 k +*u +1282.667 56.667 m +1282.222 56.222 1283.278 56.278 1283.333 56.333 c +1283.778 56.778 1282.722 56.722 1282.667 56.667 c +f +*U +0.000 0.384 0.259 0.306 k +*u +1192.667 55.667 m +1192.222 55.222 1193.278 55.278 1193.333 55.333 c +1193.778 55.778 1192.722 55.722 1192.667 55.667 c +f +*U +0.000 0.498 0.373 0.502 k +*u +1194.667 55.667 m +1194.222 55.222 1195.278 55.278 1195.333 55.333 c +1195.778 55.778 1194.722 55.722 1194.667 55.667 c +f +*U +0.000 0.749 0.545 0.251 k +*u +1196 56 m +1197.506 55.317 1198.315 55.174 1200 55 c +1198.494 55.683 1197.685 55.826 1196 56 c +f +*U +0.000 0.580 0.431 0.420 k +*u +1272 56 m +1273.506 55.317 1274.315 55.174 1276 55 c +1274.494 55.683 1273.685 55.826 1272 56 c +f +*U +0.000 0.333 0.208 0.333 k +*u +1276 56 m +1277 55 l +1276 56 l +f +*U +0.000 0.137 0.078 0.102 k +*u +1277.667 55.667 m +1277.222 55.222 1278.278 55.278 1278.333 55.333 c +1278.778 55.777 1277.723 55.723 1277.667 55.667 c +f +*U +0.000 0.176 0.125 0.235 k +*u +1198.667 54.667 m +1198.222 54.222 1199.278 54.278 1199.333 54.333 c +1199.778 54.777 1198.723 54.723 1198.667 54.667 c +f +*U +0.000 0.545 0.451 0.455 k +*u +1200 55 m +1201.769 54.221 1203 54 1205 54 c +1203.231 54.779 1201.964 54.912 1200 55 c +f +*U +0.000 0.741 0.620 0.259 k +*u +1216 55 m +1217.314 53.382 1217.877 53.307 1220 53 c +1218.624 53.911 1217.560 54.404 1216 55 c +f +*U +0.000 0.588 0.612 0.388 k +*u +1264.667 54.667 m +1264.222 54.222 1265.278 54.278 1265.333 54.333 c +1265.778 54.777 1264.723 54.723 1264.667 54.667 c +f +*U +0.000 0.420 0.447 0.553 k +*u +1266 55 m +1267.249 54.315 1267.548 54.251 1269 54 c +1267.752 54.685 1267.452 54.749 1266 55 c +f +*U +0.000 0.200 0.333 0.329 k +*u +1269 55 m +1270 54 l +1269 55 l +f +*U +0.000 0.078 0.251 0.157 k +*u +1270.667 54.667 m +1270.222 54.222 1271.278 54.278 1271.333 54.333 c +1271.778 54.777 1270.723 54.723 1270.667 54.667 c +f +*U +0.000 0.122 0.118 0.302 k +*u +1206.667 53.667 m +1206.222 53.222 1207.278 53.278 1207.333 53.333 c +1207.778 53.778 1206.722 53.722 1206.667 53.667 c +f +*U +0.000 0.612 0.510 0.035 k +*u +1208 54 m +1209 53 l +1208 54 l +f +*U +0.000 0.529 0.420 0.471 k +*u +1210 54 m +1212 53 1213.747 53 1216 53 c +1213.948 53.874 1212.253 53.953 1210 54 c +f +*U +0.000 0.557 0.447 0.443 k +*u +1253 54 m +1255.332 53 1257.457 53 1260 53 c +1257.668 53.985 1255.543 53.981 1253 54 c +f +*U +0.000 0.329 0.239 0.192 k +*u +1260 54 m +1261.506 53.317 1262.315 53.174 1264 53 c +1262.494 53.683 1261.685 53.826 1260 54 c +f +*U +0.000 0.345 0.282 0.173 k +*u +1217 53 m +1219.332 52 1221.457 52 1224 52 c +1221.668 52.985 1219.544 52.981 1217 53 c +f +*U +0.000 0.608 0.424 0.227 k +*u +1224.667 52.667 m +1224.222 52.222 1225.278 52.278 1225.333 52.333 c +1225.778 52.778 1224.722 52.722 1224.667 52.667 c +f +*U +0.000 0.525 0.424 0.475 k +*u +1226 53 m +1228 52 1229.747 52 1232 52 c +1229.948 52.874 1228.253 52.953 1226 53 c +f +*U +0.000 0.392 0.392 0.608 k +*u +1232 53 m +1234.613 51.902 1237 52 1240 52 c +1237.387 53 1234.835 52.993 1232 53 c +f +*U +0.000 0.478 0.337 0.506 k +*u +1240 53 m +1241.506 52.317 1242.315 52.174 1244 52 c +1242.494 52.683 1241.685 52.826 1240 53 c +f +*U +0.000 0.467 0.329 0.275 k +*u +1244.667 52.667 m +1244.222 52.222 1245.278 52.278 1245.333 52.333 c +1245.778 52.778 1244.722 52.722 1244.667 52.667 c +f +*U +0.000 0.404 0.286 0.110 k +*u +1246 53 m +1248 52 1249.747 52 1252 52 c +1249.948 52.874 1248.253 52.953 1246 53 c +f +*U +0.000 0.106 0.090 0.067 k +*u +1252.667 52.667 m +1252.222 52.222 1253.278 52.278 1253.333 52.333 c +1253.778 52.777 1252.723 52.723 1252.667 52.667 c +f +*U +%%Trailer +%%EOF diff --git a/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.svg b/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.svg new file mode 100644 index 0000000..a98e41e --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/img/technicalkorea_Logo.svg @@ -0,0 +1,3390 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy/tkfb-package/fastapi-bridge/static/index.html b/deploy/tkfb-package/fastapi-bridge/static/index.html new file mode 100644 index 0000000..1e91260 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/index.html @@ -0,0 +1,80 @@ + + + + + + (주)테크니컬코리아 생산팀 포털 + + + + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/admin.js b/deploy/tkfb-package/fastapi-bridge/static/js/admin.js new file mode 100644 index 0000000..b48105d --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/admin.js @@ -0,0 +1,34 @@ +// ✅ /js/admin.js (수정됨 - 중복 로딩 제거) +async function initDashboard() { + // 로그인 토큰 확인 + const token = localStorage.getItem('token'); + if (!token) { + location.href = '/index.html'; + return; + } + + // ✅ navbar, sidebar는 각각의 모듈에서 처리하도록 변경 + // load-navbar.js, load-sidebar.js가 자동으로 처리함 + + // ✅ 콘텐츠만 직접 로딩 (admin-sections.html이 자동 로딩됨) + console.log('관리자 대시보드 초기화 완료'); +} + +// ✅ 보조 함수 - 필요시 수동 컴포넌트 로딩용 +async function loadComponent(id, url) { + try { + const res = await fetch(url); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const html = await res.text(); + const element = document.getElementById(id); + if (element) { + element.innerHTML = html; + } else { + console.warn(`요소를 찾을 수 없습니다: ${id}`); + } + } catch (err) { + console.error(`컴포넌트 로딩 실패 (${url}):`, err); + } +} + +document.addEventListener('DOMContentLoaded', initDashboard); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/api-config.js b/deploy/tkfb-package/fastapi-bridge/static/js/api-config.js new file mode 100644 index 0000000..888a530 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/api-config.js @@ -0,0 +1,143 @@ +// api-config.js - nginx 프록시 대응 API 설정 + +function getApiBaseUrl() { + const hostname = window.location.hostname; + const protocol = window.location.protocol; + const port = window.location.port; + + console.log('🌐 감지된 환경:', { hostname, protocol, port }); + + // 🔗 nginx 프록시를 통한 접근 (권장) + // nginx가 /api/ 요청을 백엔드로 프록시하므로 포트 없이 접근 + if (hostname.startsWith('192.168.') || hostname.startsWith('10.') || hostname.startsWith('172.') || + hostname === 'localhost' || hostname === '127.0.0.1' || + hostname.includes('.local') || hostname.includes('hyungi')) { + + // 현재 웹서버의 도메인/IP를 그대로 사용하되 /api 경로만 추가 + const baseUrl = port && port !== '80' && port !== '443' + ? `${protocol}//${hostname}:${port}/api` + : `${protocol}//${hostname}/api`; + + console.log('✅ nginx 프록시 사용:', baseUrl); + return baseUrl; + } + + // 🚨 백업: 직접 접근 (nginx 프록시 실패시에만) + console.warn('⚠️ 직접 API 접근 (백업 모드)'); + return `${protocol}//${hostname}:8000/api`; +} + +export const API = getApiBaseUrl(); + +export function ensureAuthenticated() { + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + alert('로그인이 필요합니다'); + localStorage.removeItem('token'); + window.location.href = '/'; + return null; + } + return token; +} + +export function getAuthHeaders() { + const token = localStorage.getItem('token'); + return { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }; +} + +// 🔧 개선된 API 호출 함수 (에러 처리 강화) +export async function apiCall(url, options = {}) { + const defaultOptions = { + headers: getAuthHeaders() + }; + + const finalOptions = { + ...defaultOptions, + ...options, + headers: { + ...defaultOptions.headers, + ...options.headers + } + }; + + try { + console.log(`📡 API 호출: ${url}`); + const response = await fetch(url, finalOptions); + + // 인증 만료 처리 + if (response.status === 401) { + console.error('❌ 인증 만료'); + localStorage.removeItem('token'); + alert('인증이 만료되었습니다. 다시 로그인해주세요.'); + window.location.href = '/'; + return; + } + + // 응답 실패 처리 + if (!response.ok) { + let errorMessage = `HTTP ${response.status}`; + try { + const errorData = await response.json(); + errorMessage = errorData.error || errorData.message || errorMessage; + } catch (e) { + // JSON 파싱 실패시 기본 메시지 사용 + } + throw new Error(errorMessage); + } + + const result = await response.json(); + console.log(`✅ API 성공: ${url}`); + return result; + + } catch (error) { + console.error(`❌ API 오류 (${url}):`, error); + + // 네트워크 오류 vs 서버 오류 구분 + if (error.name === 'TypeError' && error.message.includes('fetch')) { + throw new Error('네트워크 연결 오류입니다. 인터넷 연결을 확인해주세요.'); + } + + throw error; + } +} + +// 디버깅 정보 +console.log('🔗 API Base URL:', API); +console.log('🌐 Current Location:', { + hostname: window.location.hostname, + protocol: window.location.protocol, + port: window.location.port, + href: window.location.href +}); + +// 🧪 API 연결 테스트 함수 (개발용) +export async function testApiConnection() { + try { + console.log('🧪 API 연결 테스트 시작...'); + const response = await fetch(`${API}/health`, { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + + if (response.ok) { + console.log('✅ API 연결 성공!'); + return true; + } else { + console.log('❌ API 연결 실패:', response.status); + return false; + } + } catch (error) { + console.log('❌ API 연결 오류:', error.message); + return false; + } +} + +// 개발 모드에서 자동 테스트 +if (window.location.hostname === 'localhost' || window.location.hostname.startsWith('192.168.')) { + setTimeout(() => { + testApiConnection(); + }, 1000); +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/api-helper.js b/deploy/tkfb-package/fastapi-bridge/static/js/api-helper.js new file mode 100644 index 0000000..8057bc9 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/api-helper.js @@ -0,0 +1,115 @@ +// /public/js/api-helper.js + +import { API_BASE_URL } from './api-config.js'; +import { getToken, clearAuthData } from './auth.js'; + +/** + * 로그인 API를 호출합니다. (인증이 필요 없는 public 요청) + * @param {string} username - 사용자 아이디 + * @param {string} password - 사용자 비밀번호 + * @returns {Promise} - API 응답 결과 + */ +export async function login(username, password) { + const response = await fetch(`${API_BASE_URL}/auth/login`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username, password }), + }); + + const result = await response.json(); + if (!response.ok) { + // API 에러 응답을 그대로 에러 객체로 던져서 호출부에서 처리하도록 함 + throw new Error(result.error || '로그인에 실패했습니다.'); + } + return result; +} + + +/** + * 인증이 필요한 API 요청을 위한 fetch 래퍼 함수 + * @param {string} endpoint - /로 시작하는 API 엔드포인트 + * @param {object} options - fetch 함수에 전달할 옵션 + * @returns {Promise} - fetch 응답 객체 + */ +async function authFetch(endpoint, options = {}) { + const token = getToken(); + + if (!token) { + console.error('토큰이 없습니다. 로그인이 필요합니다.'); + clearAuthData(); // 인증 정보 정리 + window.location.href = '/index.html'; // 로그인 페이지로 리디렉션 + // 에러를 던져서 후속 실행을 중단 + throw new Error('인증 토큰이 없습니다.'); + } + + const defaultHeaders = { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }; + + const response = await fetch(`${API_BASE_URL}${endpoint}`, { + ...options, + headers: { + ...defaultHeaders, + ...options.headers + } + }); + + // 401 Unauthorized 에러 발생 시, 토큰이 유효하지 않다는 의미 + if (response.status === 401) { + console.error('인증 실패. 토큰이 만료되었거나 유효하지 않습니다.'); + clearAuthData(); // 만료된 인증 정보 정리 + window.location.href = '/index.html'; + throw new Error('인증에 실패했습니다.'); + } + + return response; +} + +// 공통 API 요청 함수들 + +/** + * GET 요청 헬퍼 + * @param {string} endpoint - API 엔드포인트 + */ +export async function apiGet(endpoint) { + const response = await authFetch(endpoint); + return response.json(); +} + +/** + * POST 요청 헬퍼 + * @param {string} endpoint - API 엔드포인트 + * @param {object} data - 전송할 데이터 + */ +export async function apiPost(endpoint, data) { + const response = await authFetch(endpoint, { + method: 'POST', + body: JSON.stringify(data) + }); + return response.json(); +} + +/** + * PUT 요청 헬퍼 + * @param {string} endpoint - API 엔드포인트 + * @param {object} data - 전송할 데이터 + */ +export async function apiPut(endpoint, data) { + const response = await authFetch(endpoint, { + method: 'PUT', + body: JSON.stringify(data) + }); + return response.json(); +} + +/** + * DELETE 요청 헬퍼 + * @param {string} endpoint - API 엔드포인트 + */ +export async function apiDelete(endpoint) { + const response = await authFetch(endpoint, { + method: 'DELETE' + }); + return response.json(); +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/attendance-validation.js b/deploy/tkfb-package/fastapi-bridge/static/js/attendance-validation.js new file mode 100644 index 0000000..2eb16e1 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/attendance-validation.js @@ -0,0 +1,1038 @@ +// 근태 검증 관리 시스템 - API 통합 개선판 + +// ======================================== +// API 설정 및 인증 (통합 방식) +// ======================================== +import { API, getAuthHeaders, apiCall } from '/js/api-config.js'; + +// ======================================== +// 전역 변수 및 설정 +// ======================================== + +let currentDate = new Date(); +let selectedDate = null; +let selectedDateWorkers = []; +let currentFilter = 'all'; +let editingWorker = null; + +// Rate Limiting 설정 - 더욱 엄격하게 +const RATE_LIMIT = { + maxConcurrent: 1, // 동시 최대 1개 요청만! + delayBetweenRequests: 2000, // 요청 간 2초 딜레이 + retryDelay: 5000, // 429 에러 시 5초 후 재시도 + maxRetries: 1 // 최대 1번만 재시도 +}; + +// 캐시 및 상태 관리 +let dateStatusCache = new Map(); +let requestQueue = []; +let activeRequests = 0; +let isProcessingQueue = false; + +// ======================================== +// 캐시 및 성능 관리 유틸리티 +// ======================================== + +/** + * 캐시 상태 확인 + */ +function getCacheStatus() { + return { + cachedDates: dateStatusCache.size, + activeRequests: activeRequests, + queuedRequests: requestQueue.length, + isProcessingQueue: isProcessingQueue + }; +} + +/** + * 캐시 클리어 + */ +function clearCache() { + dateStatusCache.clear(); + console.log('📦 캐시가 클리어되었습니다.'); +} + +/** + * 성능 상태 UI 업데이트 + */ +function updatePerformanceUI() { + const status = getCacheStatus(); + const performanceEl = document.getElementById('performanceStatus'); + + if (performanceEl) { + document.getElementById('activeReq').textContent = status.activeRequests; + document.getElementById('cacheCount').textContent = status.cachedDates; + document.getElementById('queueCount').textContent = status.queuedRequests; + + // 개발 환경에서만 표시 + if (window.location.hostname === 'localhost' || window.location.hostname.includes('dev')) { + performanceEl.classList.remove('hidden'); + } + } +} + +/** + * 성능 모니터링 (디버그용) + */ +function logPerformanceStatus() { + const status = getCacheStatus(); + console.log('📊 성능 상태:', status); + updatePerformanceUI(); +} + +// 개발 모드에서 성능 모니터링 (2초마다) +if (window.location.hostname === 'localhost' || window.location.hostname.includes('dev')) { + setInterval(logPerformanceStatus, 2000); +} + +// ======================================== +// 유틸리티 함수들 +// ======================================== + +/** + * 한국 시간 기준 날짜 문자열 반환 + */ +function getKoreaDateString(date = new Date()) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +/** + * 현재 로그인한 사용자 정보 가져오기 + */ +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + + try { + const userInfo = localStorage.getItem('user') || localStorage.getItem('userInfo'); + if (userInfo) { + return JSON.parse(userInfo); + } + } catch (error) { + console.log('localStorage에서 사용자 정보 가져오기 실패:', error); + } + + return null; +} + +// ======================================== +// Rate Limiting 및 Queue 시스템 +// ======================================== + +/** + * Rate Limited API 호출을 위한 Queue 처리 + */ +async function processRequestQueue() { + if (isProcessingQueue || requestQueue.length === 0) return; + + isProcessingQueue = true; + + while (requestQueue.length > 0 && activeRequests < RATE_LIMIT.maxConcurrent) { + const { resolve, reject, url, options, retryCount } = requestQueue.shift(); + activeRequests++; + + try { + const result = await makeRateLimitedRequest(url, options, retryCount); + resolve(result); + } catch (error) { + reject(error); + } finally { + activeRequests--; + updatePerformanceUI(); // UI 업데이트 + // 요청 간 딜레이 + if (requestQueue.length > 0) { + await new Promise(resolve => setTimeout(resolve, RATE_LIMIT.delayBetweenRequests)); + } + } + } + + isProcessingQueue = false; + + // 큐에 남은 요청이 있으면 다시 처리 + if (requestQueue.length > 0) { + setTimeout(processRequestQueue, RATE_LIMIT.delayBetweenRequests); + } +} + +/** + * Rate Limiting이 적용된 실제 API 호출 + */ +async function makeRateLimitedRequest(url, options = {}, retryCount = 0) { + const defaultOptions = { + headers: getAuthHeaders() + }; + + const finalOptions = { + ...defaultOptions, + ...options, + headers: { + ...defaultOptions.headers, + ...options.headers + } + }; + + try { + const response = await fetch(url, finalOptions); + + if (response.status === 401) { + showMessage('인증이 만료되었습니다. 다시 로그인해주세요.', 'error'); + localStorage.removeItem('token'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + if (response.status === 429) { + // Rate Limit 에러 처리 + if (retryCount < RATE_LIMIT.maxRetries) { + console.log(`Rate limit 도달, ${RATE_LIMIT.retryDelay}ms 후 재시도 (${retryCount + 1}/${RATE_LIMIT.maxRetries})`); + await new Promise(resolve => setTimeout(resolve, RATE_LIMIT.retryDelay * (retryCount + 1))); + return makeRateLimitedRequest(url, options, retryCount + 1); + } else { + throw new Error('Rate limit exceeded - 요청이 너무 많습니다. 잠시 후 다시 시도해주세요.'); + } + } + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.error || errorData.message || `HTTP ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('API 호출 오류:', error); + throw error; + } +} + +/** + * API 호출 헬퍼 (Queue 시스템 사용) - 통합 apiCall 대신 사용 + */ +async function queuedApiCall(url, options = {}) { + return new Promise((resolve, reject) => { + requestQueue.push({ + resolve, + reject, + url, + options, + retryCount: 0 + }); + updatePerformanceUI(); // UI 업데이트 + processRequestQueue(); + }); +} + +// ======================================== +// 메시지 및 UI 헬퍼 함수들 +// ======================================== + +/** + * 메시지 표시 + */ +function showMessage(message, type = 'info') { + const container = document.getElementById('message-container'); + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => { + hideMessage(); + }, 5000); + } +} + +function hideMessage() { + document.getElementById('message-container').innerHTML = ''; +} + +/** + * 로딩 상태 표시 + */ +function showLoadingState() { + const workersList = document.getElementById('workersList'); + workersList.innerHTML = ` +
+
+
+ 작업자 데이터를 불러오는 중... +
+
+ `; +} + +/** + * 오류 상태 표시 + */ +function showErrorState(message = '데이터를 불러오는 중 오류가 발생했습니다.') { + const workersList = document.getElementById('workersList'); + workersList.innerHTML = ` +
+
⚠️
+

데이터 로딩 오류

+

${message}

+
+ `; +} + +// ======================================== +// API 호출 함수들 (통합 설정 사용) +// ======================================== + +/** + * 특정 날짜의 작업 보고서를 가져옵니다 + */ +async function fetchWorkReports(date) { + try { + return await queuedApiCall(`${API}/workreports/date/${date}`); + } catch (error) { + console.error('WorkReports API 호출 실패:', error); + return []; + } +} + +/** + * 특정 날짜의 일일 작업 보고서를 가져옵니다 + */ +async function fetchDailyWorkReports(date) { + try { + return await queuedApiCall(`${API}/daily-work-reports/date/${date}`); + } catch (error) { + console.error('DailyWorkReports API 호출 실패:', error); + return []; + } +} + +/** + * 특정 작업자의 근무시간을 수정합니다 + */ +async function updateWorkerHours(workerId, date, newHours, reason = '') { + try { + const data = { + worker_id: workerId, + report_date: date, + work_hours: parseFloat(newHours), + modification_reason: reason, + modified_by: getCurrentUser()?.user_id || getCurrentUser()?.id + }; + + return await queuedApiCall(`${API}/daily-work-reports/update-hours`, { + method: 'PUT', + body: JSON.stringify(data) + }); + } catch (error) { + console.error('작업자 시간 수정 실패:', error); + throw error; + } +} + +/** + * 특정 작업자의 작업 데이터를 삭제합니다 + */ +async function deleteWorkerReport(workerId, date) { + try { + return await queuedApiCall(`${API}/daily-work-reports/worker/${workerId}/date/${date}`, { + method: 'DELETE' + }); + } catch (error) { + console.error('작업자 데이터 삭제 실패:', error); + throw error; + } +} + +// ======================================== +// 계산 및 검증 함수들 +// ======================================== + +/** + * 상태에 따른 예상 근무시간을 계산합니다 + */ +function calculateExpectedHours(status, overtime_hours = 0) { + const baseHours = { + 'normal': 8, // 정상 출근 + 'half_day': 4, // 반차 + 'early_leave': 4, // 조퇴 + 'quarter_day': 2, // 1/4 휴가 + 'vacation': 0, // 휴가 + 'sick_leave': 0 // 병가 + }; + return (baseHours[status] || 8) + (overtime_hours || 0); +} + +/** + * 작업자의 검증 상태를 계산합니다 + */ +function getValidationStatus(worker) { + if (!worker.hasWorkReport || !worker.hasDailyReport) return 'missing'; + if (Math.abs(worker.difference) > 0) return 'needs-review'; + return 'normal'; +} + +/** + * 특정 날짜의 전체 상태를 계산합니다 (순차 호출) + */ +async function calculateDateStatus(dateStr) { + // 캐시 확인 + if (dateStatusCache.has(dateStr)) { + return dateStatusCache.get(dateStr); + } + + try { + console.log(`📊 ${dateStr} 상태 계산 시작 - 순차 호출`); + + // 1단계: WorkReports 먼저 가져오기 + console.log(`📝 1단계: WorkReports 조회 중...`); + const workReports = await fetchWorkReports(dateStr); + + // 2초 대기 (서버 부하 방지) + console.log(`⏳ 2초 대기 중... (서버 부하 방지)`); + await new Promise(resolve => setTimeout(resolve, 2000)); + + // 2단계: DailyWorkReports 가져오기 + console.log(`📊 2단계: DailyWorkReports 조회 중...`); + const dailyReports = await fetchDailyWorkReports(dateStr); + + let status; + if (workReports.length === 0 && dailyReports.length === 0) { + status = 'no-data'; + } else if (workReports.length === 0 || dailyReports.length === 0) { + status = 'missing'; + } else { + const hasDiscrepancy = workReports.some(wr => { + const dr = dailyReports.find(d => d.worker_id === wr.worker_id); + if (!dr) return true; + + const expected = calculateExpectedHours(wr.status, wr.overtime_hours); + return Math.abs(dr.work_hours - expected) > 0; + }); + status = hasDiscrepancy ? 'needs-review' : 'normal'; + } + + // 캐시에 저장 + dateStatusCache.set(dateStr, status); + console.log(`✅ ${dateStr} 상태 계산 완료: ${status}`); + return status; + } catch (error) { + console.error('날짜 상태 계산 오류:', error); + // 에러 시 캐시하지 않고 기본값 반환 + return 'no-data'; + } +} + +// ======================================== +// 캘린더 관련 함수들 +// ======================================== + +/** + * 현재 월의 캘린더 데이터를 생성합니다 (온디맨드 로딩) + */ +function generateCalendarStructure() { + const year = currentDate.getFullYear(); + const month = currentDate.getMonth(); + const firstDay = new Date(year, month, 1); + const startDate = new Date(firstDay); + startDate.setDate(startDate.getDate() - firstDay.getDay()); + + const calendar = []; + const current = new Date(startDate); + + for (let week = 0; week < 6; week++) { + const weekDays = []; + for (let day = 0; day < 7; day++) { + const dateStr = getKoreaDateString(current); + const isCurrentMonth = current.getMonth() === month; + + weekDays.push({ + date: new Date(current), + dateStr, + isCurrentMonth, + status: 'no-data' // 모든 날짜를 no-data로 시작 + }); + current.setDate(current.getDate() + 1); + } + calendar.push(weekDays); + } + + return calendar; +} + +/** + * 캘린더를 화면에 렌더링합니다 (자동 로딩 없음) + */ +async function renderCalendar() { + try { + showMessage('📅 캘린더를 표시합니다. 날짜를 클릭하면 순차적으로 상태를 확인할 수 있습니다.', 'success'); + + // 캘린더 구조만 렌더링 (API 호출 없음) + const calendar = generateCalendarStructure(); + const calendarGrid = document.getElementById('calendarGrid'); + calendarGrid.innerHTML = ''; + + // 캘린더 날짜들을 생성 (상태 로딩 없음) + calendar.flat().forEach((dateInfo) => { + const button = document.createElement('button'); + button.className = ` + calendar-day + ${dateInfo.isCurrentMonth ? 'text-gray-900 hover-enabled' : 'text-gray-400'} + ${selectedDate === dateInfo.dateStr ? 'selected' : ''} + no-data + `; + + button.innerHTML = ` +
+ ${dateInfo.date.getDate()} + ${dateInfo.isCurrentMonth ? + `
` : '' + } +
+ `; + + // 현재 월의 날짜만 클릭 가능 + if (dateInfo.isCurrentMonth) { + button.addEventListener('click', () => handleDateClick(dateInfo)); + button.title = `${dateInfo.dateStr} - 클릭하여 상태 확인`; + } else { + button.disabled = true; + button.style.cursor = 'not-allowed'; + } + + calendarGrid.appendChild(button); + }); + + // 월/년 표시 업데이트 + const monthNames = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월']; + document.getElementById('currentMonthYear').textContent = + `${currentDate.getFullYear()}년 ${monthNames[currentDate.getMonth()]}`; + + // 월간 요약 정보 초기화 + document.getElementById('normalCount').textContent = '?'; + document.getElementById('reviewCount').textContent = '?'; + document.getElementById('missingCount').textContent = '?'; + + hideMessage(); + + } catch (error) { + console.error('캘린더 렌더링 오류:', error); + showMessage('캘린더 로딩 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 특정 날짜의 상태만 로드하고 업데이트합니다 (순차 호출) + */ +async function loadAndUpdateDateStatus(dateStr, buttonElement) { + try { + // 로딩 상태 표시 + buttonElement.classList.add('loading-state'); + const statusDot = buttonElement.querySelector('.status-dot'); + if (statusDot) { + statusDot.style.background = '#3b82f6'; + statusDot.style.opacity = '1'; + statusDot.classList.add('pulse'); + } + + // 진행 상황 표시 + buttonElement.title = '1단계: WorkReports 조회 중...'; + + const status = await calculateDateStatus(dateStr); + + // 버튼 스타일 업데이트 + buttonElement.classList.remove('loading-state', 'no-data'); + buttonElement.classList.add(status); + buttonElement.title = `${dateStr} - 상태: ${status}`; + + // 상태 점 업데이트 + if (statusDot && status !== 'no-data') { + statusDot.classList.remove('pulse'); + statusDot.className = `status-dot ${ + status === 'needs-review' ? 'warning' : + status === 'missing' ? 'error' : + status === 'normal' ? 'normal' : '' + }`; + } + + console.log(`✅ ${dateStr} 상태 로드 완료: ${status}`); + + } catch (error) { + console.error(`❌ ${dateStr} 상태 로드 실패:`, error); + buttonElement.classList.remove('loading-state'); + buttonElement.classList.add('error-state'); + buttonElement.title = `${dateStr} - 로드 실패: ${error.message}`; + + const statusDot = buttonElement.querySelector('.status-dot'); + if (statusDot) { + statusDot.style.background = '#ef4444'; + statusDot.classList.remove('pulse'); + } + } +} + +// ======================================== +// 작업자 데이터 관련 함수들 +// ======================================== + +/** + * 특정 날짜의 모든 작업자 데이터를 조합합니다 (순차 호출) + */ +async function getWorkersForDate(dateStr) { + try { + console.log(`👥 ${dateStr} 작업자 데이터 조합 시작 - 순차 호출`); + + // 1단계: WorkReports 먼저 가져오기 + console.log(`📝 1단계: WorkReports 조회 중...`); + const workReports = await fetchWorkReports(dateStr); + + // 2초 대기 (서버 부하 방지) + console.log(`⏳ 2초 대기 중... (서버 부하 방지)`); + await new Promise(resolve => setTimeout(resolve, 2000)); + + // 2단계: DailyWorkReports 가져오기 + console.log(`📊 2단계: DailyWorkReports 조회 중...`); + const dailyReports = await fetchDailyWorkReports(dateStr); + + const workerMap = new Map(); + + // WorkReports 데이터 추가 + workReports.forEach(wr => { + workerMap.set(wr.worker_id, { + worker_id: wr.worker_id, + worker_name: wr.worker_name, + overtime_hours: wr.overtime_hours || 0, + status: wr.status || 'normal', + expected_hours: calculateExpectedHours(wr.status || 'normal', wr.overtime_hours), + reported_hours: null, + hasWorkReport: true, + hasDailyReport: false + }); + }); + + // DailyReports 데이터 추가 + dailyReports.forEach(dr => { + if (workerMap.has(dr.worker_id)) { + const worker = workerMap.get(dr.worker_id); + worker.reported_hours = dr.work_hours; + worker.hasDailyReport = true; + } else { + workerMap.set(dr.worker_id, { + worker_id: dr.worker_id, + worker_name: dr.worker_name, + overtime_hours: 0, + status: 'normal', + expected_hours: 8, + reported_hours: dr.work_hours, + hasWorkReport: false, + hasDailyReport: true + }); + } + }); + + const result = Array.from(workerMap.values()).map(worker => ({ + ...worker, + difference: worker.reported_hours !== null ? worker.reported_hours - worker.expected_hours : -worker.expected_hours, + validationStatus: getValidationStatus(worker) + })); + + console.log(`✅ ${dateStr} 작업자 데이터 조합 완료: ${result.length}명`); + return result; + + } catch (error) { + console.error('데이터 조합 오류:', error); + return []; + } +} + +// ======================================== +// 이벤트 핸들러 함수들 +// ======================================== + +/** + * 캘린더 날짜 클릭 이벤트 핸들러 (순차 호출) + */ +async function handleDateClick(dateInfo) { + if (!dateInfo.isCurrentMonth) return; + + selectedDate = dateInfo.dateStr; + + // 선택된 날짜 표시 업데이트 + document.querySelectorAll('.calendar-day').forEach(btn => { + btn.classList.remove('selected'); + }); + + const clickedButton = event.target.closest('.calendar-day'); + if (clickedButton) { + clickedButton.classList.add('selected'); + + // 해당 날짜의 상태가 아직 로드되지 않았다면 로드 + if (clickedButton.classList.contains('no-data')) { + showMessage(`📊 ${dateInfo.dateStr} 날짜의 상태를 확인하는 중... (순차 호출로 약 5초 소요)`, 'loading'); + await loadAndUpdateDateStatus(dateInfo.dateStr, clickedButton); + } + } + + // 작업자 데이터 로드 (순차 호출) + showLoadingState(); + showMessage(`👥 ${dateInfo.dateStr} 작업자 데이터를 순차적으로 로드 중... (약 5초 소요)`, 'loading'); + + try { + const workers = await getWorkersForDate(dateInfo.dateStr); + selectedDateWorkers = workers; + renderWorkersList(workers); + + showMessage(`✅ ${dateInfo.dateStr} 날짜의 데이터를 성공적으로 로드했습니다! (${workers.length}명)`, 'success'); + + } catch (error) { + console.error('날짜별 데이터 로딩 오류:', error); + showErrorState('해당 날짜의 데이터를 불러올 수 없습니다. 잠시 후 다시 시도해주세요.'); + showMessage(`❌ ${dateInfo.dateStr} 데이터 로드 실패: ${error.message}`, 'error'); + } +} + +/** + * 작업자 근무시간 수정 모달 열기 + */ +function openEditModal(worker) { + editingWorker = worker; + + document.getElementById('editWorkerName').value = worker.worker_name; + document.getElementById('editWorkerStatus').value = getStatusText(worker.status); + document.getElementById('editWorkHours').value = worker.reported_hours || 0; + document.getElementById('editReason').value = ''; + + document.getElementById('editModal').classList.remove('hidden'); +} + +/** + * 수정 모달 닫기 + */ +function closeEditModal() { + editingWorker = null; + document.getElementById('editModal').classList.add('hidden'); +} + +/** + * 수정된 작업 저장 + */ +async function saveEditedWork() { + if (!editingWorker) return; + + try { + const newHours = document.getElementById('editWorkHours').value; + const reason = document.getElementById('editReason').value; + + if (!newHours || isNaN(newHours)) { + showMessage('올바른 시간을 입력해주세요.', 'error'); + return; + } + + showMessage('수정 중...', 'loading'); + + await updateWorkerHours(editingWorker.worker_id, selectedDate, newHours, reason); + + showMessage('✅ 근무시간이 성공적으로 수정되었습니다!', 'success'); + closeEditModal(); + + // 데이터 새로고침 + const workers = await getWorkersForDate(selectedDate); + selectedDateWorkers = workers; + renderWorkersList(workers); + renderCalendar(); + + } catch (error) { + console.error('수정 실패:', error); + showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +/** + * 작업자 데이터 삭제 + */ +async function deleteWorker(worker) { + if (!confirm(`정말로 ${worker.worker_name}의 ${selectedDate} 작업 데이터를 삭제하시겠습니까?\n삭제된 데이터는 복구할 수 없습니다.`)) { + return; + } + + try { + showMessage('삭제 중...', 'loading'); + + await deleteWorkerReport(worker.worker_id, selectedDate); + + showMessage('✅ 작업 데이터가 성공적으로 삭제되었습니다!', 'success'); + + // 데이터 새로고침 + const workers = await getWorkersForDate(selectedDate); + selectedDateWorkers = workers; + renderWorkersList(workers); + renderCalendar(); + + } catch (error) { + console.error('삭제 실패:', error); + showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// ======================================== +// UI 렌더링 함수들 +// ======================================== + +/** + * 상태 텍스트 반환 + */ +function getStatusText(status) { + const statusMap = { + 'normal': '정상출근', + 'half_day': '반차', + 'vacation': '휴가', + 'early_leave': '조퇴', + 'quarter_day': '1/4 휴가', + 'sick_leave': '병가' + }; + return statusMap[status] || status; +} + +/** + * 상태 아이콘 반환 + */ +function getStatusIcon(status) { + switch (status) { + case 'normal': return '✅'; + case 'needs-review': return '⚠️'; + case 'missing': return '❌'; + default: return '❓'; + } +} + +/** + * 날짜 포맷팅 + */ +function formatDate(dateStr) { + const date = new Date(dateStr); + const month = date.getMonth() + 1; + const day = date.getDate(); + const weekdays = ['일', '월', '화', '수', '목', '금', '토']; + const weekday = weekdays[date.getDay()]; + return `${month}월 ${day}일 (${weekday})`; +} + +/** + * 작업자 리스트를 화면에 렌더링합니다 + */ +function renderWorkersList(workers) { + const workersList = document.getElementById('workersList'); + + if (!selectedDate || workers.length === 0) { + workersList.innerHTML = ` +
+
🔄
+

날짜를 클릭해주세요

+

+ 캘린더에서 날짜를 클릭하면 해당 날짜의 작업자 검증 내역을 확인할 수 있습니다.
+ 순차 호출 방식으로 안정적이지만 약 5초의 로딩 시간이 있습니다. +

+
+ `; + return; + } + + // 필터링 적용 + const filteredWorkers = workers.filter(worker => { + if (currentFilter === 'all') return true; + if (currentFilter === 'needsReview') return worker.validationStatus === 'needs-review'; + if (currentFilter === 'normal') return worker.validationStatus === 'normal'; + if (currentFilter === 'missing') return worker.validationStatus === 'missing'; + return true; + }); + + // HTML 생성 + workersList.innerHTML = ` +
+ +
+
+

📋 작업자 검증 현황

+

${formatDate(selectedDate)}

+
+ +
+ + +
+ ${filteredWorkers.map(worker => ` +
+ +
+
+
+ ${worker.worker_name.charAt(0)} +
+
+
${worker.worker_name}
+
작업자 ID: ${worker.worker_id}
+
+
+
${getStatusIcon(worker.validationStatus)}
+
+ + +
+
+ 그룹장 입력 + + ${worker.reported_hours !== null ? `${worker.reported_hours}시간` : '미입력'} + +
+ +
+ 시스템 계산 + ${worker.expected_hours}시간 +
+ +
+ 근무 상태 + + ${getStatusText(worker.status)} + ${worker.overtime_hours > 0 ? ` + 연장 ${worker.overtime_hours}시간` : ''} + +
+ + ${worker.difference !== 0 ? ` +
+ 시간 차이 + + ${worker.difference > 0 ? '+' : ''}${worker.difference}시간 + +
+ ` : ''} +
+ + +
+ + ${worker.hasDailyReport ? ` + + ` : ''} +
+
+ `).join('')} +
+ + + ${filteredWorkers.length === 0 ? ` +
+
🔍
+

해당 조건의 작업자가 없습니다

+

+ 다른 필터를 선택하거나 전체 보기를 확인해주세요.
+ 또는 해당 날짜에 등록된 작업자가 없을 수 있습니다. +

+
+ ` : ''} +
+ `; + + // 필터 이벤트 리스너 추가 + const filterSelect = document.getElementById('workerFilter'); + filterSelect.value = currentFilter; + filterSelect.addEventListener('change', (e) => { + currentFilter = e.target.value; + renderWorkersList(selectedDateWorkers); + }); +} + +// ======================================== +// 초기화 및 이벤트 리스너 등록 +// ======================================== + +/** + * 페이지 로드 시 초기화 함수 + */ +async function init() { + try { + // 인증 확인 (api-config.js의 ensureAuthenticated 대신 직접 확인) + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + showMessage('로그인이 필요합니다.', 'error'); + localStorage.removeItem('token'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + // 월 이동 버튼 이벤트 리스너 + document.getElementById('prevMonth').addEventListener('click', async () => { + currentDate.setMonth(currentDate.getMonth() - 1); + selectedDate = null; + dateStatusCache.clear(); // 캐시 클리어 + clearCache(); // 추가 캐시 클리어 + await renderCalendar(); + renderWorkersList([]); + showMessage('📅 이전 달로 이동했습니다. 날짜를 클릭하여 순차적으로 데이터를 확인하세요.', 'success'); + }); + + document.getElementById('nextMonth').addEventListener('click', async () => { + currentDate.setMonth(currentDate.getMonth() + 1); + selectedDate = null; + dateStatusCache.clear(); // 캐시 클리어 + clearCache(); // 추가 캐시 클리어 + await renderCalendar(); + renderWorkersList([]); + showMessage('📅 다음 달로 이동했습니다. 날짜를 클릭하여 순차적으로 데이터를 확인하세요.', 'success'); + }); + + // 모달 이벤트 리스너 + document.getElementById('editModal').addEventListener('click', (e) => { + if (e.target.id === 'editModal') { + closeEditModal(); + } + }); + + // 초기 렌더링 + await renderCalendar(); + + // 순차 호출 안내 메시지 + showMessage('🔄 API 통합 적용 완료! 순차 호출 시스템으로 안정성이 개선되었습니다.', 'success'); + + // 전역 함수로 등록 + window.openEditModal = openEditModal; + window.closeEditModal = closeEditModal; + window.saveEditedWork = saveEditedWork; + window.deleteWorker = deleteWorker; + + console.log('✅ 근태 검증 관리 시스템 초기화 완료 (API 통합)'); + console.log(`🔗 API 경로: ${API}`); + console.log(`📊 설정: 동시 최대 ${RATE_LIMIT.maxConcurrent}개 요청, ${RATE_LIMIT.delayBetweenRequests}ms 딜레이`); + console.log('🔄 API 호출 방식: 통합 설정 + 순차 호출'); + console.log('🚫 429 에러 방지: 각 날짜당 최소 5초 간격'); + + } catch (error) { + console.error('초기화 오류:', error); + showMessage('시스템 초기화 중 오류가 발생했습니다.', 'error'); + } +} + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', init); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/attendance.js b/deploy/tkfb-package/fastapi-bridge/static/js/attendance.js new file mode 100644 index 0000000..e2db96d --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/attendance.js @@ -0,0 +1,170 @@ +import { API, getAuthHeaders } from '/js/api-config.js'; + +const yearSel = document.getElementById('year'); +const monthSel = document.getElementById('month'); +const container = document.getElementById('attendanceTableContainer'); + +const holidays = [ + '2025-01-01','2025-01-27','2025-01-28','2025-01-29','2025-01-30','2025-01-31', + '2025-03-01','2025-03-03','2025-05-01','2025-05-05','2025-05-06', + '2025-06-03','2025-06-06','2025-08-15','2025-10-03','2025-10-09','2025-12-25' +]; + +const leaveDefaults = { + '김두수':16,'임영규':16,'반치원':16,'황인용':16,'표영진':15, + '김윤섭':16,'이창호':16,'최광욱':16,'박현수':14,'조윤호':0 +}; + +let workers = []; + +// ✅ 셀렉트 박스 옵션 + 기본 선택 추가 +function fillSelectOptions() { + const currentY = new Date().getFullYear(); + const currentM = String(new Date().getMonth() + 1).padStart(2, '0'); + + for (let y = currentY; y <= currentY + 5; y++) { + const selected = y === currentY ? 'selected' : ''; + yearSel.insertAdjacentHTML('beforeend', ``); + } + + for (let m = 1; m <= 12; m++) { + const mm = String(m).padStart(2, '0'); + const selected = mm === currentM ? 'selected' : ''; + monthSel.insertAdjacentHTML('beforeend', ``); + } +} + +// ✅ 작업자 목록 불러오기 +async function fetchWorkers() { + try { + const res = await fetch(`${API}/workers`, { headers: getAuthHeaders() }); + workers = await res.json(); + workers.sort((a, b) => a.worker_id - b.worker_id); + } catch (err) { + alert('작업자 불러오기 실패'); + } +} + +// ✅ 출근부 불러오기 (해당 연도 전체) +async function loadAttendance() { + const year = yearSel.value; + const month = monthSel.value; + if (!year || !month) return alert('연도와 월을 선택하세요'); + + const lastDay = new Date(+year, +month, 0).getDate(); + const start = `${year}-01-01`; + const end = `${year}-12-31`; + + try { + const res = await fetch(`${API}/workreports?start=${start}&end=${end}`, { + headers: getAuthHeaders() + }); + const data = await res.json(); + renderTable(data, year, month, lastDay); + } catch (err) { + alert('출근부 로딩 실패'); + } +} + +// ✅ 테이블 렌더링 +function renderTable(data, year, month, lastDay) { + container.innerHTML = ''; + const weekdays = ['일','월','화','수','목','금','토']; + const tbl = document.createElement('table'); + + // ⬆️ 헤더 구성 + let thead = `작업자`; + for (let d = 1; d <= lastDay; d++) thead += `${d}`; + thead += `잔업합계사용연차잔여연차`; + for (let d = 1; d <= lastDay; d++) { + const dow = new Date(+year, +month - 1, d).getDay(); + thead += `${weekdays[dow]}`; + } + thead += ''; + tbl.innerHTML = thead; + + // ⬇️ 본문 + workers.forEach(w => { + // ✅ 월간 데이터 (표에 표시용) + const recsThisMonth = data.filter(r => + r.worker_id === w.worker_id && + new Date(r.date).getFullYear() === +year && + new Date(r.date).getMonth() + 1 === +month + ); + + // ✅ 연간 데이터 (연차 계산용) + const recsThisYear = data.filter(r => + r.worker_id === w.worker_id && + new Date(r.date).getFullYear() === +year + ); + + let otSum = 0; + let row = `${w.worker_name}`; + + for (let d = 1; d <= lastDay; d++) { + const dd = String(d).padStart(2, '0'); + const date = `${year}-${month}-${dd}`; + + const rec = recsThisMonth.find(r => { + const rDate = new Date(r.date); + const yyyy = rDate.getFullYear(); + const mm = String(rDate.getMonth() + 1).padStart(2, '0'); + const dd = String(rDate.getDate()).padStart(2, '0'); + return `${yyyy}-${mm}-${dd}` === date; + }); + + const dow = new Date(+year, +month - 1, d).getDay(); + const isWe = dow === 0 || dow === 6; + const isHo = holidays.includes(date); + + let txt = '', cls = ''; + if (rec) { + const ot = +rec.overtime_hours || 0; + if (ot > 0) { + txt = ot; cls = 'overtime-cell'; otSum += ot; + } else if (rec.work_details) { + const d = rec.work_details; + if (['연차','반차','반반차','조퇴'].includes(d)) { + txt = d; cls = 'leave'; + } else if (d === '유급') { + txt = d; cls = 'paid-leave'; + } else if (d === '휴무') { + txt = d; cls = 'holiday'; + } else { + txt = d; + } + } + } else { + txt = (isWe || isHo) ? '휴무' : ''; + cls = (isWe || isHo) ? 'holiday' : 'no-data'; + } + + row += `${txt}`; + } + + const usedTot = recsThisYear + .filter(r => ['연차','반차','반반차','조퇴'].includes(r.work_details)) + .reduce((s, r) => s + ( + r.work_details === '연차' ? 1 : + r.work_details === '반차' ? 0.5 : + r.work_details === '반반차' ? 0.25 : 0.75 + ), 0); + + const remain = (leaveDefaults[w.worker_name] || 0) - usedTot; + + row += `${otSum.toFixed(1)}`; + row += `${usedTot.toFixed(2)}${remain.toFixed(2)}`; + row += ``; + + tbl.insertAdjacentHTML('beforeend', row); + }); + + container.appendChild(tbl); +} + +// ✅ 초기 로딩 +fillSelectOptions(); +fetchWorkers().then(() => { + loadAttendance(); // 자동 조회 +}); +document.getElementById('loadAttendance').addEventListener('click', loadAttendance); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/auth-check.js b/deploy/tkfb-package/fastapi-bridge/static/js/auth-check.js new file mode 100644 index 0000000..d43e51a --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/auth-check.js @@ -0,0 +1,27 @@ +// /js/auth-check.js +import { isLoggedIn, getUser, clearAuthData } from './auth.js'; + +// 즉시 실행 함수로 스코프를 보호하고 로직을 실행 +(function() { + if (!isLoggedIn()) { + console.log('🚨 인증되지 않은 사용자. 로그인 페이지로 이동합니다.'); + clearAuthData(); // 만약을 위해 한번 더 정리 + window.location.href = '/index.html'; + return; // 이후 코드 실행 방지 + } + + const currentUser = getUser(); + + // 사용자 정보가 유효한지 확인 (토큰은 있지만 유저 정보가 깨졌을 경우) + if (!currentUser || !currentUser.username || !currentUser.role) { + console.error('🚨 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.'); + clearAuthData(); + window.location.href = '/index.html'; + return; + } + + console.log(`✅ ${currentUser.username}(${currentUser.role})님 인증 성공.`); + + // 역할 기반 메뉴 제어 로직은 각 컴포넌트 로더(load-navbar.js 등)로 이전함. + // 전역 변수 할당(window.currentUser) 제거. +})(); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/auth.js b/deploy/tkfb-package/fastapi-bridge/static/js/auth.js new file mode 100644 index 0000000..7a8e6e5 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/auth.js @@ -0,0 +1,76 @@ +// js/auth.js + +/** + * JWT 토큰을 디코딩하여 페이로드(내용)를 반환합니다. + * @param {string} token - JWT 토큰 + * @returns {object|null} - 디코딩된 페이로드 객체 또는 파싱 실패 시 null + */ +export function parseJwt(token) { + try { + // 토큰의 두 번째 부분(payload)을 base64 디코딩하고 JSON으로 파싱 + return JSON.parse(atob(token.split('.')[1])); + } catch (e) { + console.error("잘못된 토큰입니다.", e); + return null; + } +} + +/** + * localStorage에서 인증 토큰을 가져옵니다. + * @returns {string|null} - 저장된 토큰 또는 토큰이 없을 경우 null + */ +export function getToken() { + return localStorage.getItem('token'); +} + +/** + * localStorage에서 사용자 정보를 가져옵니다. + * @returns {object|null} - 저장된 사용자 객체 또는 정보가 없을 경우 null + */ +export function getUser() { + const user = localStorage.getItem('user'); + try { + return user ? JSON.parse(user) : null; + } catch(e) { + console.error("사용자 정보를 파싱하는 데 실패했습니다.", e); + return null; + } +} + +/** + * 로그인 성공 후 토큰과 사용자 정보를 localStorage에 저장합니다. + * @param {string} token - 서버에서 받은 JWT 토큰 + * @param {object} user - 서버에서 받은 사용자 정보 객체 + */ +export function saveAuthData(token, user) { + localStorage.setItem('token', token); + localStorage.setItem('user', JSON.stringify(user)); +} + +/** + * 로그아웃 시 localStorage에서 인증 정보를 제거합니다. + */ +export function clearAuthData() { + localStorage.removeItem('token'); + localStorage.removeItem('user'); +} + +/** + * 현재 사용자가 로그인 상태인지 확인합니다. + * @returns {boolean} - 로그인 상태이면 true, 아니면 false + */ +export function isLoggedIn() { + const token = getToken(); + if (!token) { + return false; + } + + // 선택 사항: 토큰 만료 여부 확인 로직 추가 가능 + // const payload = parseJwt(token); + // if (payload && payload.exp * 1000 > Date.now()) { + // return true; + // } + // return false; + + return !!token; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/calendar.js b/deploy/tkfb-package/fastapi-bridge/static/js/calendar.js new file mode 100644 index 0000000..d5c591b --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/calendar.js @@ -0,0 +1,59 @@ +// ✅ /js/calendar.js +export function renderCalendar(containerId, onDateSelect) { + const container = document.getElementById(containerId); + if (!container) return; + + let currentDate = new Date(); + let selectedDateStr = ''; + + function drawCalendar(date) { + container.innerHTML = ''; + const year = date.getFullYear(); + const month = date.getMonth(); + const firstDay = new Date(year, month, 1).getDay(); + const lastDate = new Date(year, month + 1, 0).getDate(); + + const nav = document.createElement('div'); + nav.className = 'nav'; + const prev = document.createElement('button'); + prev.textContent = '◀'; + prev.addEventListener('click', () => { + currentDate = new Date(year, month - 1, 1); + drawCalendar(currentDate); + }); + const title = document.createElement('div'); + title.innerHTML = `${year}년 ${month + 1}월`; + const next = document.createElement('button'); + next.textContent = '▶'; + next.addEventListener('click', () => { + currentDate = new Date(year, month + 1, 1); + drawCalendar(currentDate); + }); + nav.append(prev, title, next); + container.appendChild(nav); + + ['일','월','화','수','목','금','토'].forEach(day => { + const el = document.createElement('div'); + el.innerHTML = `${day}`; + container.appendChild(el); + }); + + for (let i = 0; i < firstDay; i++) container.appendChild(document.createElement('div')); + + for (let i = 1; i <= lastDate; i++) { + const btn = document.createElement('button'); + const ymd = `${year}-${String(month + 1).padStart(2, '0')}-${String(i).padStart(2, '0')}`; + btn.textContent = i; + btn.className = (ymd === selectedDateStr) ? 'selected-date' : ''; + btn.addEventListener('click', () => { + selectedDateStr = ymd; + drawCalendar(currentDate); + onDateSelect(ymd); + }); + container.appendChild(btn); + } + } + + drawCalendar(currentDate); +} + diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/change-password.js b/deploy/tkfb-package/fastapi-bridge/static/js/change-password.js new file mode 100644 index 0000000..4858a9e --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/change-password.js @@ -0,0 +1,211 @@ +// js/change-password.js +// 개인 비밀번호 변경 페이지 JavaScript + +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +const token = ensureAuthenticated(); + +// DOM 요소 +const form = document.getElementById('changePasswordForm'); +const messageArea = document.getElementById('message-area'); +const submitBtn = document.getElementById('submitBtn'); +const resetBtn = document.getElementById('resetBtn'); + +// 비밀번호 토글 기능 +document.querySelectorAll('.password-toggle').forEach(button => { + button.addEventListener('click', function() { + const targetId = this.getAttribute('data-target'); + const input = document.getElementById(targetId); + + if (input) { + const isPassword = input.type === 'password'; + input.type = isPassword ? 'text' : 'password'; + this.textContent = isPassword ? '👁️‍🗨️' : '👁️'; + } + }); +}); + +// 초기화 버튼 +resetBtn?.addEventListener('click', () => { + form.reset(); + clearMessages(); + document.getElementById('passwordStrength').innerHTML = ''; +}); + +// 메시지 표시 함수 +function showMessage(type, message) { + messageArea.innerHTML = ` +
+ ${type === 'error' ? '❌' : '✅'} ${message} +
+ `; + + // 에러 메시지는 5초 후 자동 제거 + if (type === 'error') { + setTimeout(clearMessages, 5000); + } +} + +function clearMessages() { + messageArea.innerHTML = ''; +} + +// 비밀번호 강도 체크 +async function checkPasswordStrength(password) { + if (!password) { + document.getElementById('passwordStrength').innerHTML = ''; + return; + } + + try { + const res = await fetch(`${API}/auth/check-password-strength`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ password }) + }); + + const result = await res.json(); + updatePasswordStrengthUI(result); + } catch (error) { + console.error('Password strength check error:', error); + } +} + +// 비밀번호 강도 UI 업데이트 +function updatePasswordStrengthUI(strength) { + const container = document.getElementById('passwordStrength'); + if (!container) return; + + const colors = { + 0: '#f44336', + 1: '#ff9800', + 2: '#ffc107', + 3: '#4caf50', + 4: '#2196f3' + }; + + const strengthText = strength.strengthText || '비밀번호를 입력하세요'; + const color = colors[strength.strength] || '#ccc'; + const percentage = (strength.score / strength.maxScore) * 100; + + container.innerHTML = ` +
+
+ + ${strengthText} + + + ${strength.score}/${strength.maxScore} + +
+
+
+
+ ${strength.feedback && strength.feedback.length > 0 ? ` +
    + ${strength.feedback.map(f => `
  • ${f}
  • `).join('')} +
+ ` : ''} +
+ `; +} + +// 비밀번호 입력 이벤트 +let strengthCheckTimer; +document.getElementById('newPassword')?.addEventListener('input', (e) => { + clearTimeout(strengthCheckTimer); + strengthCheckTimer = setTimeout(() => { + checkPasswordStrength(e.target.value); + }, 300); +}); + +// 폼 제출 +form?.addEventListener('submit', async (e) => { + e.preventDefault(); + clearMessages(); + + const currentPassword = document.getElementById('currentPassword').value; + const newPassword = document.getElementById('newPassword').value; + const confirmPassword = document.getElementById('confirmPassword').value; + + // 유효성 검사 + if (!currentPassword || !newPassword || !confirmPassword) { + showMessage('error', '모든 필드를 입력해주세요.'); + return; + } + + if (newPassword !== confirmPassword) { + showMessage('error', '새 비밀번호가 일치하지 않습니다.'); + return; + } + + if (newPassword.length < 6) { + showMessage('error', '비밀번호는 최소 6자 이상이어야 합니다.'); + return; + } + + if (currentPassword === newPassword) { + showMessage('error', '새 비밀번호는 현재 비밀번호와 달라야 합니다.'); + return; + } + + // 버튼 상태 변경 + const originalText = submitBtn.innerHTML; + submitBtn.disabled = true; + submitBtn.innerHTML = '처리 중...'; + + try { + const res = await fetch(`${API}/auth/change-password`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + currentPassword, + newPassword + }) + }); + + const result = await res.json(); + + if (res.ok && result.success) { + showMessage('success', '비밀번호가 성공적으로 변경되었습니다.'); + form.reset(); + document.getElementById('passwordStrength').innerHTML = ''; + + // 카운트다운 시작 + let countdown = 3; + const countdownInterval = setInterval(() => { + showMessage('success', + `비밀번호가 변경되었습니다. ${countdown}초 후 로그인 페이지로 이동합니다.` + ); + countdown--; + + if (countdown < 0) { + clearInterval(countdownInterval); + localStorage.removeItem('token'); + localStorage.removeItem('user'); + window.location.href = '/index.html'; + } + }, 1000); + + } else { + const errorMessage = result.error || '비밀번호 변경에 실패했습니다.'; + showMessage('error', errorMessage); + } + } catch (error) { + console.error('Password change error:', error); + showMessage('error', '서버와의 연결에 실패했습니다. 잠시 후 다시 시도해주세요.'); + } finally { + submitBtn.disabled = false; + submitBtn.innerHTML = originalText; + } +}); + +// 페이지 로드 시 현재 사용자 정보 표시 +document.addEventListener('DOMContentLoaded', () => { + const user = JSON.parse(localStorage.getItem('user') || '{}'); + console.log('🔐 비밀번호 변경 페이지 로드됨'); + console.log('👤 현재 사용자:', user.username || 'Unknown'); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue-api.js b/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue-api.js new file mode 100644 index 0000000..ef9bcec --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue-api.js @@ -0,0 +1,66 @@ +// /js/daily-issue-api.js +import { apiGet, apiPost } from './api-helper.js'; + +/** + * 이슈 보고서 작성을 위해 필요한 초기 데이터(프로젝트, 이슈 유형)를 가져옵니다. + * @returns {Promise<{projects: Array, issueTypes: Array}>} + */ +export async function getInitialData() { + try { + const [projects, issueTypes] = await Promise.all([ + apiGet('/projects'), + apiGet('/issue-types') + ]); + return { projects, issueTypes }; + } catch (error) { + console.error('이슈 보고서 초기 데이터 로딩 실패:', error); + throw error; + } +} + +/** + * 특정 날짜에 근무한 작업자 목록을 가져옵니다. + * @param {string} date - 조회할 날짜 (YYYY-MM-DD) + * @returns {Promise} - 작업자 목록 + */ +export async function getWorkersByDate(date) { + try { + // 백엔드에 해당 날짜의 작업자 목록을 요청하는 API가 있다고 가정합니다. + // (예: /api/workers?work_date=YYYY-MM-DD) + // 현재는 기존 로직을 최대한 활용하여 구현합니다. + let workers = []; + const reports = await apiGet(`/daily-work-reports?date=${date}`); + + if (reports && reports.length > 0) { + const workerMap = new Map(); + reports.forEach(r => { + if (!workerMap.has(r.worker_id)) { + workerMap.set(r.worker_id, { worker_id: r.worker_id, worker_name: r.worker_name }); + } + }); + workers = Array.from(workerMap.values()); + } else { + // 보고서가 없으면 전체 작업자 목록을 가져옵니다. + workers = await apiGet('/workers'); + } + return workers.sort((a, b) => a.worker_name.localeCompare(b.worker_name)); + } catch (error) { + console.error(`${date}의 작업자 목록 로딩 실패:`, error); + throw error; + } +} + +/** + * 작성된 이슈 보고서 데이터를 서버에 전송합니다. + * @param {object} issueData - 전송할 이슈 데이터 + * @returns {Promise} - 서버 응답 결과 + */ +export async function createIssueReport(issueData) { + try { + const result = await apiPost('/issue-reports', issueData); + return result; + } catch (error) { + console.error('이슈 보고서 생성 요청 실패:', error); + throw error; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue-ui.js b/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue-ui.js new file mode 100644 index 0000000..c125ea8 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue-ui.js @@ -0,0 +1,103 @@ +// /js/daily-issue-ui.js + +const DOM = { + dateSelect: document.getElementById('dateSelect'), + projectSelect: document.getElementById('projectSelect'), + issueTypeSelect: document.getElementById('issueTypeSelect'), + timeStart: document.getElementById('timeStart'), + timeEnd: document.getElementById('timeEnd'), + workerList: document.getElementById('workerList'), + form: document.getElementById('issueForm'), + submitBtn: document.getElementById('submitBtn'), +}; + +function createOption(value, text) { + const option = document.createElement('option'); + option.value = value; + option.textContent = text; + return option; +} + +export function populateProjects(projects) { + DOM.projectSelect.innerHTML = ''; + if (Array.isArray(projects)) { + projects.forEach(p => DOM.projectSelect.appendChild(createOption(p.project_id, p.project_name))); + } +} + +export function populateIssueTypes(issueTypes) { + DOM.issueTypeSelect.innerHTML = ''; + if (Array.isArray(issueTypes)) { + issueTypes.forEach(t => DOM.issueTypeSelect.appendChild(createOption(t.issue_type_id, `${t.category}:${t.subcategory}`))); + } +} + +export function populateTimeOptions() { + for (let h = 0; h < 24; h++) { + for (let m of [0, 30]) { + const time = `${String(h).padStart(2, '0')}:${m === 0 ? '00' : '30'}`; + DOM.timeStart.appendChild(createOption(time, time)); + DOM.timeEnd.appendChild(createOption(time, time.replace('00:00', '24:00'))); + } + } + DOM.timeEnd.value = "24:00"; // 기본값 설정 +} + +export function renderWorkerList(workers) { + DOM.workerList.innerHTML = ''; + if (!Array.isArray(workers) || workers.length === 0) { + DOM.workerList.textContent = '선택 가능한 작업자가 없습니다.'; + return; + } + workers.forEach(worker => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'btn'; + btn.textContent = worker.worker_name; + btn.dataset.id = worker.worker_id; + btn.addEventListener('click', () => btn.classList.toggle('selected')); + DOM.workerList.appendChild(btn); + }); +} + +export function getFormData() { + const selectedWorkers = [...DOM.workerList.querySelectorAll('.btn.selected')].map(b => b.dataset.id); + + if (selectedWorkers.length === 0) { + alert('작업자를 한 명 이상 선택해주세요.'); + return null; + } + if (DOM.timeEnd.value <= DOM.timeStart.value) { + alert('종료 시간은 시작 시간보다 이후여야 합니다.'); + return null; + } + + const formData = new FormData(DOM.form); + const data = { + date: formData.get('dateSelect'), // input name 속성이 없어 직접 가져옴 + project_id: DOM.projectSelect.value, + issue_type_id: DOM.issueTypeSelect.value, + start_time: DOM.timeStart.value, + end_time: DOM.timeEnd.value, + worker_ids: selectedWorkers, // worker_id -> worker_ids 로 명확하게 변경 + }; + + for (const key in data) { + if (!data[key] || (Array.isArray(data[key]) && data[key].length === 0)) { + alert('모든 필수 항목을 입력해주세요.'); + return null; + } + } + + return data; +} + +export function setSubmitButtonState(isLoading) { + if (isLoading) { + DOM.submitBtn.disabled = true; + DOM.submitBtn.textContent = '등록 중...'; + } else { + DOM.submitBtn.disabled = false; + DOM.submitBtn.textContent = '등록'; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue.js b/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue.js new file mode 100644 index 0000000..f7f024b --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/daily-issue.js @@ -0,0 +1,89 @@ +// /js/daily-issue.js + +import { getInitialData, getWorkersByDate, createIssueReport } from './daily-issue-api.js'; +import { + populateProjects, + populateIssueTypes, + populateTimeOptions, + renderWorkerList, + getFormData, + setSubmitButtonState +} from './daily-issue-ui.js'; + +const dateSelect = document.getElementById('dateSelect'); +const form = document.getElementById('issueForm'); + +/** + * 날짜가 변경될 때마다 해당 날짜의 작업자 목록을 다시 불러옵니다. + */ +async function handleDateChange() { + const selectedDate = dateSelect.value; + if (!selectedDate) { + document.getElementById('workerList').textContent = '날짜를 먼저 선택하세요.'; + return; + } + + document.getElementById('workerList').textContent = '작업자 목록을 불러오는 중...'; + try { + const workers = await getWorkersByDate(selectedDate); + renderWorkerList(workers); + } catch (error) { + document.getElementById('workerList').textContent = '작업자 목록 로딩에 실패했습니다.'; + } +} + +/** + * 폼 제출 이벤트를 처리합니다. + */ +async function handleSubmit(event) { + event.preventDefault(); + const issueData = getFormData(); + + if (!issueData) return; // 유효성 검사 실패 + + setSubmitButtonState(true); + try { + const result = await createIssueReport(issueData); + if (result.success) { + alert('✅ 이슈가 성공적으로 등록되었습니다.'); + form.reset(); // 폼 초기화 + dateSelect.value = new Date().toISOString().split('T')[0]; // 날짜 오늘로 리셋 + handleDateChange(); // 작업자 목록 새로고침 + } else { + throw new Error(result.error || '알 수 없는 오류가 발생했습니다.'); + } + } catch (error) { + alert(`🚨 등록 실패: ${error.message}`); + } finally { + setSubmitButtonState(false); + } +} + +/** + * 페이지 초기화 함수 + */ +async function initializePage() { + // 오늘 날짜 기본 설정 + dateSelect.value = new Date().toISOString().split('T')[0]; + + populateTimeOptions(); + + // 프로젝트, 이슈유형, 작업자 목록을 병렬로 로드 + try { + const [initialData] = await Promise.all([ + getInitialData(), + handleDateChange() // 초기 작업자 목록 로드 + ]); + populateProjects(initialData.projects); + populateIssueTypes(initialData.issueTypes); + } catch (error) { + alert('페이지 초기화 중 오류가 발생했습니다. 새로고침 해주세요.'); + } + + // 이벤트 리스너 설정 + dateSelect.addEventListener('change', handleDateChange); + form.addEventListener('submit', handleSubmit); +} + +// DOM이 로드되면 페이지 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializePage); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/daily-report-viewer.js b/deploy/tkfb-package/fastapi-bridge/static/js/daily-report-viewer.js new file mode 100644 index 0000000..6710b93 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/daily-report-viewer.js @@ -0,0 +1,81 @@ +// /js/daily-report-viewer.js + +import { fetchReportData } from './report-viewer-api.js'; +import { renderReport, processReportData, showLoading, showError } from './report-viewer-ui.js'; +import { exportToExcel, printReport } from './report-viewer-export.js'; +import { getUser } from './auth.js'; + +// 전역 상태: 현재 화면에 표시된 데이터 +let currentProcessedData = null; + +/** + * 날짜를 기준으로 보고서를 검색하고 화면에 렌더링합니다. + */ +async function searchReports() { + const dateInput = document.getElementById('reportDate'); + const selectedDate = dateInput.value; + + if (!selectedDate) { + showError('날짜를 선택해주세요.'); + return; + } + + showLoading(true); + currentProcessedData = null; // 새 검색이 시작되면 이전 데이터 초기화 + + try { + const rawData = await fetchReportData(selectedDate); + currentProcessedData = processReportData(rawData, selectedDate); + renderReport(currentProcessedData); + } catch (error) { + showError(error.message); + renderReport(null); // 에러 발생 시 데이터 없는 화면 표시 + } finally { + showLoading(false); + } +} + +/** + * 페이지의 모든 이벤트 리스너를 설정합니다. + */ +function setupEventListeners() { + document.getElementById('searchBtn')?.addEventListener('click', searchReports); + document.getElementById('todayBtn')?.addEventListener('click', () => { + const today = new Date().toISOString().split('T')[0]; + document.getElementById('reportDate').value = today; + searchReports(); + }); + + document.getElementById('reportDate')?.addEventListener('keypress', (e) => { + if (e.key === 'Enter') searchReports(); + }); + + document.getElementById('exportExcelBtn')?.addEventListener('click', () => { + exportToExcel(currentProcessedData); + }); + + document.getElementById('printBtn')?.addEventListener('click', printReport); +} + +/** + * 페이지가 처음 로드될 때 실행되는 초기화 함수 + */ +function initializePage() { + // auth.js를 사용하여 인증 상태 확인 + const user = getUser(); + if (!user) { + showError('로그인이 필요합니다. 2초 후 로그인 페이지로 이동합니다.'); + setTimeout(() => window.location.href = '/index.html', 2000); + return; + } + + setupEventListeners(); + + // 페이지 로드 시 오늘 날짜로 자동 검색 + const dateInput = document.getElementById('reportDate'); + dateInput.value = new Date().toISOString().split('T')[0]; + searchReports(); +} + +// DOM이 로드되면 페이지 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializePage); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/daily-work-report.js b/deploy/tkfb-package/fastapi-bridge/static/js/daily-work-report.js new file mode 100644 index 0000000..defd805 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/daily-work-report.js @@ -0,0 +1,897 @@ +// daily-work-report.js - 통합 API 설정 적용 버전 + +// ================================================================= +// 🌐 통합 API 설정 import +// ================================================================= +import { API, getAuthHeaders, apiCall } from '/js/api-config.js'; + +// 전역 변수 +let workTypes = []; +let workStatusTypes = []; +let errorTypes = []; +let workers = []; +let projects = []; +let selectedWorkers = new Set(); +let workEntryCounter = 0; +let currentStep = 1; +let editingWorkId = null; // 수정 중인 작업 ID + +// 한국 시간 기준 오늘 날짜 가져오기 +function getKoreaToday() { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const day = String(today.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +// 현재 로그인한 사용자 정보 가져오기 +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + console.log('토큰에서 추출한 사용자 정보:', payload); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + + try { + const userInfo = localStorage.getItem('user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + if (userInfo) { + const parsed = JSON.parse(userInfo); + console.log('localStorage에서 가져온 사용자 정보:', parsed); + return parsed; + } + } catch (error) { + console.log('localStorage에서 사용자 정보 가져오기 실패:', error); + } + + return null; +} + +// 메시지 표시 +function showMessage(message, type = 'info') { + const container = document.getElementById('message-container'); + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => { + hideMessage(); + }, 5000); + } +} + +function hideMessage() { + document.getElementById('message-container').innerHTML = ''; +} + +// 단계 이동 +function goToStep(stepNumber) { + for (let i = 1; i <= 3; i++) { + const step = document.getElementById(`step${i}`); + if (step) { + step.classList.remove('active', 'completed'); + if (i < stepNumber) { + step.classList.add('completed'); + const stepNum = step.querySelector('.step-number'); + if (stepNum) stepNum.classList.add('completed'); + } else if (i === stepNumber) { + step.classList.add('active'); + } + } + } + currentStep = stepNumber; +} + +// 초기 데이터 로드 (통합 API 사용) +async function loadData() { + try { + showMessage('데이터를 불러오는 중...', 'loading'); + + console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩 시작...'); + await loadWorkers(); + await loadProjects(); + await loadWorkTypes(); + await loadWorkStatusTypes(); + await loadErrorTypes(); + + console.log('로드된 작업자 수:', workers.length); + console.log('로드된 프로젝트 수:', projects.length); + console.log('작업 유형 수:', workTypes.length); + + populateWorkerGrid(); + hideMessage(); + + } catch (error) { + console.error('데이터 로드 실패:', error); + showMessage('데이터 로드 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +async function loadWorkers() { + try { + console.log('Workers API 호출 중... (통합 API 사용)'); + const data = await apiCall(`${API}/workers`); + workers = Array.isArray(data) ? data : (data.workers || []); + console.log('✅ Workers 로드 성공:', workers.length); + } catch (error) { + console.error('작업자 로딩 오류:', error); + throw error; + } +} + +async function loadProjects() { + try { + console.log('Projects API 호출 중... (통합 API 사용)'); + const data = await apiCall(`${API}/projects`); + projects = Array.isArray(data) ? data : (data.projects || []); + console.log('✅ Projects 로드 성공:', projects.length); + } catch (error) { + console.error('프로젝트 로딩 오류:', error); + throw error; + } +} + +async function loadWorkTypes() { + try { + const data = await apiCall(`${API}/daily-work-reports/work-types`); + if (Array.isArray(data) && data.length > 0) { + workTypes = data; + console.log('✅ 작업 유형 API 사용 (통합 설정)'); + return; + } + throw new Error('API 실패'); + } catch (error) { + console.log('⚠️ 작업 유형 API 사용 불가, 기본값 사용'); + workTypes = [ + {id: 1, name: 'Base'}, + {id: 2, name: 'Vessel'}, + {id: 3, name: 'Piping'} + ]; + } +} + +async function loadWorkStatusTypes() { + try { + const data = await apiCall(`${API}/daily-work-reports/work-status-types`); + if (Array.isArray(data) && data.length > 0) { + workStatusTypes = data; + console.log('✅ 업무 상태 유형 API 사용 (통합 설정)'); + return; + } + throw new Error('API 실패'); + } catch (error) { + console.log('⚠️ 업무 상태 유형 API 사용 불가, 기본값 사용'); + workStatusTypes = [ + {id: 1, name: '정규'}, + {id: 2, name: '에러'} + ]; + } +} + +async function loadErrorTypes() { + try { + const data = await apiCall(`${API}/daily-work-reports/error-types`); + if (Array.isArray(data) && data.length > 0) { + errorTypes = data; + console.log('✅ 에러 유형 API 사용 (통합 설정)'); + return; + } + throw new Error('API 실패'); + } catch (error) { + console.log('⚠️ 에러 유형 API 사용 불가, 기본값 사용'); + errorTypes = [ + {id: 1, name: '설계미스'}, + {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, + {id: 4, name: '작업 불량'} + ]; + } +} + +// 작업자 그리드 생성 +function populateWorkerGrid() { + const grid = document.getElementById('workerGrid'); + grid.innerHTML = ''; + + workers.forEach(worker => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'worker-btn'; + btn.textContent = worker.worker_name; + btn.dataset.id = worker.worker_id; + + btn.addEventListener('click', () => { + toggleWorkerSelection(worker.worker_id, btn); + }); + + grid.appendChild(btn); + }); +} + +// 작업자 선택 토글 +function toggleWorkerSelection(workerId, btnElement) { + if (selectedWorkers.has(workerId)) { + selectedWorkers.delete(workerId); + btnElement.classList.remove('selected'); + } else { + selectedWorkers.add(workerId); + btnElement.classList.add('selected'); + } + + const nextBtn = document.getElementById('nextStep2'); + nextBtn.disabled = selectedWorkers.size === 0; +} + +// 작업 항목 추가 +function addWorkEntry() { + const container = document.getElementById('workEntriesList'); + workEntryCounter++; + + const entryDiv = document.createElement('div'); + entryDiv.className = 'work-entry'; + entryDiv.dataset.id = workEntryCounter; + + entryDiv.innerHTML = ` +
+
작업 ${workEntryCounter}
+ +
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+ +
+ + +
+
+ +
+
+ + +
+
1시간
+
2시간
+
4시간
+
8시간
+
+
+
+ `; + + container.appendChild(entryDiv); + setupWorkEntryEvents(entryDiv); +} + +// 작업 항목 이벤트 설정 +function setupWorkEntryEvents(entryDiv) { + const timeInput = entryDiv.querySelector('.time-input'); + timeInput.addEventListener('input', updateTotalHours); + + entryDiv.querySelectorAll('.quick-time-btn').forEach(btn => { + btn.addEventListener('click', () => { + timeInput.value = btn.dataset.hours; + updateTotalHours(); + }); + }); + + const workStatusSelect = entryDiv.querySelector('.work-status-select'); + const errorTypeSection = entryDiv.querySelector('.error-type-section'); + + workStatusSelect.addEventListener('change', (e) => { + if (e.target.value === '2') { + errorTypeSection.classList.add('visible'); + errorTypeSection.querySelector('.error-type-select').required = true; + } else { + errorTypeSection.classList.remove('visible'); + errorTypeSection.querySelector('.error-type-select').required = false; + errorTypeSection.querySelector('.error-type-select').value = ''; + } + }); +} + +// 작업 항목 제거 +function removeWorkEntry(id) { + const entry = document.querySelector(`[data-id="${id}"]`); + if (entry) { + entry.remove(); + updateTotalHours(); + } +} + +// 총 시간 업데이트 +function updateTotalHours() { + const timeInputs = document.querySelectorAll('.time-input'); + let total = 0; + + timeInputs.forEach(input => { + const value = parseFloat(input.value) || 0; + total += value; + }); + + const display = document.getElementById('totalHoursDisplay'); + display.textContent = `총 작업시간: ${total}시간`; + + if (total > 24) { + display.style.background = 'linear-gradient(135deg, #e74c3c 0%, #c0392b 100%)'; + display.textContent += ' ⚠️ 24시간 초과'; + } else { + display.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'; + } +} + +// 저장 함수 (통합 API 사용) +async function saveWorkReport() { + const reportDate = document.getElementById('reportDate').value; + + if (!reportDate || selectedWorkers.size === 0) { + showMessage('날짜와 작업자를 선택해주세요.', 'error'); + return; + } + + const entries = document.querySelectorAll('.work-entry'); + if (entries.length === 0) { + showMessage('최소 하나의 작업을 추가해주세요.', 'error'); + return; + } + + const newWorkEntries = []; + + for (const entry of entries) { + const projectId = entry.querySelector('.project-select').value; + const workTypeId = entry.querySelector('.work-type-select').value; + const workStatusId = entry.querySelector('.work-status-select').value; + const errorTypeId = entry.querySelector('.error-type-select').value; + const workHours = entry.querySelector('.time-input').value; + + if (!projectId || !workTypeId || !workStatusId || !workHours) { + showMessage('모든 작업 항목을 완성해주세요.', 'error'); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showMessage('에러 상태인 경우 에러 유형을 선택해주세요.', 'error'); + return; + } + + newWorkEntries.push({ + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: errorTypeId ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours) + }); + } + + try { + const submitBtn = document.getElementById('submitBtn'); + submitBtn.disabled = true; + submitBtn.textContent = '💾 저장 중...'; + + const currentUser = getCurrentUser(); + let totalSaved = 0; + let totalFailed = 0; + const failureDetails = []; + + for (const workerId of selectedWorkers) { + const requestData = { + report_date: reportDate, + worker_id: parseInt(workerId), + work_entries: newWorkEntries, + created_by: currentUser?.user_id || currentUser?.id + }; + + console.log('전송 데이터 (통합 API 사용):', requestData); + + try { + const result = await apiCall(`${API}/daily-work-reports`, { + method: 'POST', + body: JSON.stringify(requestData) + }); + + console.log('✅ 저장 성공 (통합 API):', result); + totalSaved++; + } catch (error) { + console.error('❌ 저장 실패:', error); + totalFailed++; + + const workerName = workers.find(w => w.worker_id == workerId)?.worker_name || '알 수 없음'; + failureDetails.push(`${workerName}: ${error.message}`); + } + } + + if (totalSaved > 0 && totalFailed === 0) { + showMessage(`✅ ${totalSaved}명의 작업보고서가 성공적으로 저장되었습니다!`, 'success'); + } else if (totalSaved > 0 && totalFailed > 0) { + showMessage(`⚠️ ${totalSaved}명 성공, ${totalFailed}명 실패. 실패: ${failureDetails.join(', ')}`, 'warning'); + } else { + showMessage(`❌ 모든 저장이 실패했습니다. 상세: ${failureDetails.join(', ')}`, 'error'); + } + + if (totalSaved > 0) { + setTimeout(() => { + refreshTodayWorkers(); + resetForm(); + }, 2000); + } + + } catch (error) { + console.error('저장 오류:', error); + showMessage('저장 중 예기치 못한 오류가 발생했습니다: ' + error.message, 'error'); + } finally { + const submitBtn = document.getElementById('submitBtn'); + submitBtn.disabled = false; + submitBtn.textContent = '💾 작업보고서 저장'; + } +} + +// 폼 초기화 +function resetForm() { + goToStep(1); + + selectedWorkers.clear(); + document.querySelectorAll('.worker-btn.selected').forEach(btn => { + btn.classList.remove('selected'); + }); + + const container = document.getElementById('workEntriesList'); + container.innerHTML = ''; + + workEntryCounter = 0; + updateTotalHours(); + + document.getElementById('nextStep2').disabled = true; +} + +// 당일 작업자 현황 로드 (본인 입력분만) - 통합 API 사용 +async function loadTodayWorkers() { + const section = document.getElementById('dailyWorkersSection'); + const content = document.getElementById('dailyWorkersContent'); + + if (!section || !content) { + console.log('당일 현황 섹션이 HTML에 없습니다.'); + return; + } + + try { + const today = getKoreaToday(); + const currentUser = getCurrentUser(); + + content.innerHTML = '
📊 내가 입력한 오늘의 작업 현황을 불러오는 중... (통합 API)
'; + section.style.display = 'block'; + + // 본인이 입력한 데이터만 조회 (통합 API 사용) + let queryParams = `date=${today}`; + if (currentUser?.user_id) { + queryParams += `&created_by=${currentUser.user_id}`; + } else if (currentUser?.id) { + queryParams += `&created_by=${currentUser.id}`; + } + + console.log(`🔒 본인 입력분만 조회 (통합 API): ${API}/daily-work-reports?${queryParams}`); + + const rawData = await apiCall(`${API}/daily-work-reports?${queryParams}`); + console.log('📊 당일 작업 데이터 (통합 API):', rawData); + + let data = []; + if (Array.isArray(rawData)) { + data = rawData; + } else if (rawData?.data) { + data = rawData.data; + } + + displayMyDailyWorkers(data, today); + + } catch (error) { + console.error('당일 작업자 로드 오류:', error); + content.innerHTML = ` +
+ ❌ 오늘의 작업 현황을 불러올 수 없습니다.
+ ${error.message} +
+ `; + } +} + +// 본인 입력 작업자 현황 표시 (수정/삭제 기능 포함) +function displayMyDailyWorkers(data, date) { + const content = document.getElementById('dailyWorkersContent'); + + if (!Array.isArray(data) || data.length === 0) { + content.innerHTML = ` +
+ 📝 내가 오늘(${date}) 입력한 작업이 없습니다.
+ 새로운 작업을 추가해보세요! +
+ `; + return; + } + + // 작업자별로 데이터 그룹화 + const workerGroups = {}; + data.forEach(work => { + const workerName = work.worker_name || '미지정'; + if (!workerGroups[workerName]) { + workerGroups[workerName] = []; + } + workerGroups[workerName].push(work); + }); + + const totalWorkers = Object.keys(workerGroups).length; + const totalWorks = data.length; + + const headerHtml = ` +
+

📊 내가 입력한 오늘(${date}) 작업 현황 - 총 ${totalWorkers}명, ${totalWorks}개 작업

+ +
+ `; + + const workersHtml = Object.entries(workerGroups).map(([workerName, works]) => { + const totalHours = works.reduce((sum, work) => { + return sum + parseFloat(work.work_hours || 0); + }, 0); + + // 개별 작업 항목들 (수정/삭제 버튼 포함) + const individualWorksHtml = works.map((work) => { + const projectName = work.project_name || '미지정'; + const workTypeName = work.work_type_name || '미지정'; + const workStatusName = work.work_status_name || '미지정'; + const workHours = work.work_hours || 0; + const errorTypeName = work.error_type_name || null; + const workId = work.id; + + return ` +
+
+
+
🏗️ 프로젝트
+
${projectName}
+
+
+
⚙️ 작업종류
+
${workTypeName}
+
+
+
📊 작업상태
+
${workStatusName}
+
+
+
⏰ 작업시간
+
${workHours}시간
+
+ ${errorTypeName ? ` +
+
❌ 에러유형
+
${errorTypeName}
+
+ ` : ''} +
+
+ + +
+
+ `; + }).join(''); + + return ` +
+
+
👤 ${workerName}
+
총 ${totalHours}시간
+
+
+ ${individualWorksHtml} +
+
+ `; + }).join(''); + + content.innerHTML = headerHtml + '
' + workersHtml + '
'; +} + +// 작업 항목 수정 함수 (통합 API 사용) +async function editWorkItem(workId) { + try { + console.log('수정할 작업 ID:', workId); + + // 1. 기존 데이터 조회 (통합 API 사용) + showMessage('작업 정보를 불러오는 중... (통합 API)', 'loading'); + + const workData = await apiCall(`${API}/daily-work-reports/${workId}`); + console.log('수정할 작업 데이터 (통합 API):', workData); + + // 2. 수정 모달 표시 + showEditModal(workData); + hideMessage(); + + } catch (error) { + console.error('작업 정보 조회 오류:', error); + showMessage('작업 정보를 불러올 수 없습니다: ' + error.message, 'error'); + } +} + +// 수정 모달 표시 +function showEditModal(workData) { + editingWorkId = workData.id; + + const modalHtml = ` +
+
+
+

✏️ 작업 수정

+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ `; + + document.body.insertAdjacentHTML('beforeend', modalHtml); + + // 업무 상태 변경 이벤트 + document.getElementById('editWorkStatus').addEventListener('change', (e) => { + const errorTypeGroup = document.getElementById('editErrorTypeGroup'); + if (e.target.value === '2') { + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + } + }); +} + +// 수정 모달 닫기 +function closeEditModal() { + const modal = document.getElementById('editModal'); + if (modal) { + modal.remove(); + } + editingWorkId = null; +} + +// 수정된 작업 저장 (통합 API 사용) +async function saveEditedWork() { + try { + const projectId = document.getElementById('editProject').value; + const workTypeId = document.getElementById('editWorkType').value; + const workStatusId = document.getElementById('editWorkStatus').value; + const errorTypeId = document.getElementById('editErrorType').value; + const workHours = document.getElementById('editWorkHours').value; + + if (!projectId || !workTypeId || !workStatusId || !workHours) { + showMessage('모든 필수 항목을 입력해주세요.', 'error'); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showMessage('에러 상태인 경우 에러 유형을 선택해주세요.', 'error'); + return; + } + + const updateData = { + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: errorTypeId ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours) + }; + + showMessage('작업을 수정하는 중... (통합 API)', 'loading'); + + const result = await apiCall(`${API}/daily-work-reports/${editingWorkId}`, { + method: 'PUT', + body: JSON.stringify(updateData) + }); + + console.log('✅ 수정 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); + + closeEditModal(); + refreshTodayWorkers(); + + } catch (error) { + console.error('❌ 수정 실패:', error); + showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 작업 항목 삭제 함수 (통합 API 사용) +async function deleteWorkItem(workId) { + if (!confirm('정말로 이 작업을 삭제하시겠습니까?\n삭제된 작업은 복구할 수 없습니다.')) { + return; + } + + try { + console.log('삭제할 작업 ID:', workId); + + showMessage('작업을 삭제하는 중... (통합 API)', 'loading'); + + // 개별 항목 삭제 API 호출 (본인 작성분만 삭제 가능) - 통합 API 사용 + const result = await apiCall(`${API}/daily-work-reports/my-entry/${workId}`, { + method: 'DELETE' + }); + + console.log('✅ 삭제 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); + + // 화면 새로고침 + refreshTodayWorkers(); + + } catch (error) { + console.error('❌ 삭제 실패:', error); + showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 오늘 현황 새로고침 +function refreshTodayWorkers() { + loadTodayWorkers(); +} + +// 이벤트 리스너 설정 +function setupEventListeners() { + document.getElementById('nextStep1').addEventListener('click', () => { + const dateInput = document.getElementById('reportDate'); + if (dateInput && dateInput.value) { + goToStep(2); + } else { + showMessage('날짜를 선택해주세요.', 'error'); + } + }); + + document.getElementById('nextStep2').addEventListener('click', () => { + if (selectedWorkers.size > 0) { + goToStep(3); + addWorkEntry(); + } else { + showMessage('작업자를 선택해주세요.', 'error'); + } + }); + + document.getElementById('addWorkBtn').addEventListener('click', addWorkEntry); + document.getElementById('submitBtn').addEventListener('click', saveWorkReport); +} + +// 초기화 +async function init() { + try { + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + showMessage('로그인이 필요합니다.', 'error'); + localStorage.removeItem('token'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + document.getElementById('reportDate').value = getKoreaToday(); + + await loadData(); + setupEventListeners(); + loadTodayWorkers(); + + console.log('✅ 시스템 초기화 완료 (통합 API 설정 적용)'); + + } catch (error) { + console.error('초기화 오류:', error); + showMessage('초기화 중 오류가 발생했습니다.', 'error'); + } +} + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', init); + +// 전역 함수로 노출 +window.removeWorkEntry = removeWorkEntry; +window.refreshTodayWorkers = refreshTodayWorkers; +window.editWorkItem = editWorkItem; +window.deleteWorkItem = deleteWorkItem; +window.closeEditModal = closeEditModal; +window.saveEditedWork = saveEditedWork; \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/factory-upload.js b/deploy/tkfb-package/fastapi-bridge/static/js/factory-upload.js new file mode 100644 index 0000000..e2288ce --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/factory-upload.js @@ -0,0 +1,49 @@ +import { API, getAuthHeaders } from '/js/api-config.js'; + +document.getElementById('uploadForm').addEventListener('submit', async (e) => { + e.preventDefault(); + const formData = new FormData(e.target); + + try { + // FormData를 사용할 때는 Content-Type을 설정하지 않음 (자동 설정됨) + const token = localStorage.getItem('token'); + const res = await fetch(`${API}/factoryinfo`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}` + }, + body: formData + }); + + if (!res.ok) { + const error = await res.json(); + throw new Error(error.message || '등록 실패'); + } + + alert('등록 완료!'); + location.reload(); + } catch (err) { + console.error(err); + alert('등록 실패: ' + err.message); + } +}); + +// 파일 선택 시 미리보기 (선택사항) +const fileInput = document.querySelector('input[name="map_image"]'); +if (fileInput) { + fileInput.addEventListener('change', function(e) { + const file = e.target.files[0]; + + if (file && file.type.startsWith('image/')) { + // 미리보기 요소가 있을 경우에만 동작 + const preview = document.getElementById('file-preview'); + if (preview) { + const reader = new FileReader(); + reader.onload = function(e) { + preview.innerHTML = `미리보기`; + }; + reader.readAsDataURL(file); + } + } + }); +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/factory-view.js b/deploy/tkfb-package/fastapi-bridge/static/js/factory-view.js new file mode 100644 index 0000000..00a6b9c --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/factory-view.js @@ -0,0 +1,38 @@ +import { API, getAuthHeaders } from '/js/api-config.js'; + +(async () => { + const pathParts = location.pathname.split('/'); + const id = pathParts[pathParts.length - 1]; + + try { + const res = await fetch(`${API}/factoryinfo/${id}`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error('조회 실패'); + } + + const data = await res.json(); + + // DOM 요소가 존재하는지 확인 후 설정 + const nameEl = document.getElementById('factoryName'); + if (nameEl) nameEl.textContent = data.factory_name; + + const addressEl = document.getElementById('factoryAddress'); + if (addressEl) addressEl.textContent = '📍 ' + data.address; + + const imageEl = document.getElementById('factoryImage'); + if (imageEl) imageEl.src = data.map_image_url; + + const descEl = document.getElementById('factoryDescription'); + if (descEl) descEl.textContent = data.description; + + } catch (err) { + console.error(err); + const container = document.querySelector('.container'); + if (container) { + container.innerHTML = '

공장 정보를 불러올 수 없습니다.

'; + } + } +})(); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/group-leader-dashboard.js b/deploy/tkfb-package/fastapi-bridge/static/js/group-leader-dashboard.js new file mode 100644 index 0000000..1fa0292 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/group-leader-dashboard.js @@ -0,0 +1,103 @@ +// /js/group-leader-dashboard.js +// 그룹장 전용 대시보드 기능 + +console.log('📊 그룹장 대시보드 스크립트 로딩'); + +// 팀 현황 새로고침 +async function refreshTeamStatus() { + console.log('🔄 팀 현황 새로고침 시작'); + + try { + // 로딩 상태 표시 + const teamList = document.getElementById('team-list'); + if (teamList) { + teamList.innerHTML = '
⏳ 로딩 중...
'; + } + + // 실제로는 API 호출 + // const response = await fetch('/api/team-status', { headers: getAuthHeaders() }); + // const data = await response.json(); + + // 임시 데이터로 업데이트 (실제 API 연동 시 교체) + setTimeout(() => { + updateTeamStatusUI(); + }, 1000); + + } catch (error) { + console.error('❌ 팀 현황 로딩 실패:', error); + const teamList = document.getElementById('team-list'); + if (teamList) { + teamList.innerHTML = '
❌ 로딩 실패
'; + } + } +} + +// 팀 현황 UI 업데이트 (임시 데이터) +function updateTeamStatusUI() { + const teamData = [ + { name: '김작업', status: 'present', statusText: '출근' }, + { name: '이현장', status: 'present', statusText: '출근' }, + { name: '박휴가', status: 'absent', statusText: '휴가' }, + { name: '최작업', status: 'present', statusText: '출근' }, + { name: '정현장', status: 'present', statusText: '출근' } + ]; + + const teamList = document.getElementById('team-list'); + if (teamList) { + teamList.innerHTML = teamData.map(member => ` +
+ ${member.name} + ${member.statusText} +
+ `).join(''); + } + + // 통계 업데이트 + const presentCount = teamData.filter(m => m.status === 'present').length; + const absentCount = teamData.filter(m => m.status === 'absent').length; + + const totalEl = document.getElementById('team-total'); + const presentEl = document.getElementById('team-present'); + const absentEl = document.getElementById('team-absent'); + + if (totalEl) totalEl.textContent = teamData.length; + if (presentEl) presentEl.textContent = presentCount; + if (absentEl) absentEl.textContent = absentCount; + + console.log('✅ 팀 현황 업데이트 완료'); +} + +// 환영 메시지 개인화 +function personalizeWelcome() { + const user = JSON.parse(localStorage.getItem('user') || '{}'); + const welcomeMsg = document.getElementById('welcome-message'); + + if (user && user.name && welcomeMsg) { + welcomeMsg.textContent = `${user.name}님의 실시간 팀 현황 및 작업 모니터링`; + console.log('✅ 환영 메시지 개인화 완료'); + } +} + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', function() { + console.log('🚀 그룹장 대시보드 초기화 시작'); + + // 사용자 정보 확인 + const user = JSON.parse(localStorage.getItem('user') || '{}'); + console.log('👤 현재 사용자:', user); + + // 권한 확인 + if (user.access_level !== 'group_leader') { + console.warn('⚠️ 그룹장 권한 없음:', user.access_level); + // 필요시 다른 페이지로 리다이렉트 + } + + // 초기화 작업 + personalizeWelcome(); + updateTeamStatusUI(); + + console.log('✅ 그룹장 대시보드 초기화 완료'); +}); + +// 전역 함수로 내보내기 (HTML에서 사용) +window.refreshTeamStatus = refreshTeamStatus; \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/load-navbar.js b/deploy/tkfb-package/fastapi-bridge/static/js/load-navbar.js new file mode 100644 index 0000000..79e000f --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/load-navbar.js @@ -0,0 +1,144 @@ +// js/load-navbar.js +import { getUser, clearAuthData } from './auth.js'; + +// 역할 이름을 한글로 변환하는 맵 +const ROLE_NAMES = { + admin: '관리자', + system: '시스템 관리자', + leader: '그룹장', + user: '작업자', + support: '지원팀', + default: '사용자', +}; + +/** + * 사용자 역할에 따라 메뉴 항목을 필터링합니다. + * @param {Document} doc - 파싱된 HTML 문서 객체 + * @param {string} userRole - 현재 사용자의 역할 + */ +function filterMenuByRole(doc, userRole) { + const selectors = [ + { role: 'admin', selector: '.admin-only' }, + { role: 'system', selector: '.system-only' }, + { role: 'leader', selector: '.leader-only' }, + ]; + + selectors.forEach(({ role, selector }) => { + // 사용자가 해당 역할을 가지고 있지 않으면 메뉴 항목을 제거 + if (userRole !== role) { + doc.querySelectorAll(selector).forEach(el => el.remove()); + } + }); +} + +/** + * 네비게이션 바에 사용자 정보를 채웁니다. + * @param {Document} doc - 파싱된 HTML 문서 객체 + * @param {object} user - 현재 사용자 객체 + */ +function populateUserInfo(doc, user) { + const displayName = user.name || user.username; + const roleName = ROLE_NAMES[user.role] || ROLE_NAMES.default; + + // 상단 바 사용자 이름 + const userNameEl = doc.getElementById('user-name'); + if (userNameEl) userNameEl.textContent = displayName; + + // 상단 바 사용자 역할 + const userRoleEl = doc.getElementById('user-role'); + if (userRoleEl) userRoleEl.textContent = roleName; + + // 드롭다운 메뉴 사용자 이름 + const dropdownNameEl = doc.getElementById('dropdown-user-fullname'); + if (dropdownNameEl) dropdownNameEl.textContent = displayName; + + // 드롭다운 메뉴 사용자 아이디 + const dropdownIdEl = doc.getElementById('dropdown-user-id'); + if (dropdownIdEl) dropdownIdEl.textContent = `@${user.username}`; +} + +/** + * 네비게이션 바와 관련된 모든 이벤트를 설정합니다. + */ +function setupNavbarEvents() { + const userInfoDropdown = document.getElementById('user-info-dropdown'); + const profileDropdownMenu = document.getElementById('profile-dropdown-menu'); + + // 드롭다운 토글 + if (userInfoDropdown && profileDropdownMenu) { + userInfoDropdown.addEventListener('click', (e) => { + e.stopPropagation(); + profileDropdownMenu.classList.toggle('show'); + userInfoDropdown.classList.toggle('active'); + }); + } + + // 로그아웃 버튼 + const logoutButton = document.getElementById('dropdown-logout'); + if (logoutButton) { + logoutButton.addEventListener('click', () => { + if (confirm('로그아웃 하시겠습니까?')) { + clearAuthData(); + window.location.href = '/index.html'; + } + }); + } + + // 외부 클릭 시 드롭다운 닫기 + document.addEventListener('click', (e) => { + if (profileDropdownMenu && !userInfoDropdown.contains(e.target) && !profileDropdownMenu.contains(e.target)) { + profileDropdownMenu.classList.remove('show'); + userInfoDropdown.classList.remove('active'); + } + }); +} + +/** + * 현재 시간을 업데이트하는 함수 + */ +function updateTime() { + const timeElement = document.getElementById('current-time'); + if (timeElement) { + const now = new Date(); + timeElement.textContent = now.toLocaleTimeString('ko-KR', { hour12: false }); + } +} + + +// 메인 로직: DOMContentLoaded 시 실행 +document.addEventListener('DOMContentLoaded', async () => { + const navbarContainer = document.getElementById('navbar-container'); + if (!navbarContainer) return; + + const currentUser = getUser(); + if (!currentUser) return; // 사용자가 없으면 아무 작업도 하지 않음 + + try { + const response = await fetch('/components/navbar.html'); + const htmlText = await response.text(); + + // 1. 텍스트를 가상 DOM으로 파싱 + const parser = new DOMParser(); + const doc = parser.parseFromString(htmlText, 'text/html'); + + // 2. DOM에 삽입하기 *전*에 내용 수정 + filterMenuByRole(doc, currentUser.role); + populateUserInfo(doc, currentUser); + + // 3. 수정 완료된 HTML을 실제 DOM에 삽입 (깜빡임 방지) + navbarContainer.innerHTML = doc.body.innerHTML; + + // 4. DOM에 삽입된 후에 이벤트 리스너 설정 + setupNavbarEvents(); + + // 5. 실시간 시간 업데이트 시작 + updateTime(); + setInterval(updateTime, 1000); + + console.log('✅ 네비게이션 바 로딩 완료'); + + } catch (error) { + console.error('🔴 네비게이션 바 로딩 중 오류 발생:', error); + navbarContainer.innerHTML = '

네비게이션 바를 불러오는 데 실패했습니다.

'; + } +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/load-sections.js b/deploy/tkfb-package/fastapi-bridge/static/js/load-sections.js new file mode 100644 index 0000000..6b735ff --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/load-sections.js @@ -0,0 +1,104 @@ +// /js/load-sections.js +import { getUser } from './auth.js'; +import { apiGet } from './api-helper.js'; + +// 역할에 따라 불러올 섹션 HTML 파일을 매핑합니다. +const SECTION_MAP = { + admin: '/components/sections/admin-sections.html', + system: '/components/sections/admin-sections.html', // system도 admin과 동일한 섹션을 사용 + leader: '/components/sections/leader-sections.html', + user: '/components/sections/user-sections.html', + default: '/components/sections/user-sections.html', // 역할이 없는 경우 기본값 +}; + +/** + * API를 통해 대시보드 통계 데이터를 가져옵니다. + * @returns {Promise} 통계 데이터 또는 에러 시 null + */ +async function fetchDashboardStats() { + try { + const today = new Date().toISOString().split('T')[0]; + // 실제 백엔드 엔드포인트는 /api/dashboard/stats 와 같은 형태로 구현될 수 있습니다. + const stats = await apiGet(`/workreports?start=${today}&end=${today}`); + // 필요한 데이터 형태로 가공 (예시) + return { + today_reports_count: stats.length, + today_workers_count: new Set(stats.map(d => d.worker_id)).size, + }; + } catch (error) { + console.error('대시보드 통계 데이터 로드 실패:', error); + return null; + } +} + +/** + * 가상 DOM에 통계 데이터를 채워 넣습니다. + * @param {Document} doc - 파싱된 HTML 문서 객체 + * @param {object} stats - 통계 데이터 + */ +function populateStatsData(doc, stats) { + if (!stats) return; + + const todayStatsEl = doc.getElementById('today-stats'); + if (todayStatsEl) { + todayStatsEl.innerHTML = ` +

📝 오늘 등록된 작업: ${stats.today_reports_count}건

+

👥 참여 작업자: ${stats.today_workers_count}명

+ `; + } +} + +/** + * 메인 로직: 페이지에 역할별 섹션을 로드하고 내용을 채웁니다. + */ +async function initializeSections() { + const mainContainer = document.querySelector('main[id$="-sections"]'); + if (!mainContainer) { + console.error('섹션을 담을 메인 컨테이너를 찾을 수 없습니다.'); + return; + } + mainContainer.innerHTML = '
콘텐츠를 불러오는 중...
'; + + const currentUser = getUser(); + if (!currentUser) { + mainContainer.innerHTML = '
사용자 정보를 찾을 수 없습니다.
'; + return; + } + + const sectionFile = SECTION_MAP[currentUser.role] || SECTION_MAP.default; + + try { + // 1. 역할에 맞는 HTML 템플릿과 동적 데이터를 동시에 로드 (Promise.all 활용) + const [htmlResponse, statsData] = await Promise.all([ + fetch(sectionFile), + fetchDashboardStats() + ]); + + if (!htmlResponse.ok) { + throw new Error(`섹션 파일(${sectionFile})을 불러오는 데 실패했습니다.`); + } + const htmlText = await htmlResponse.text(); + + // 2. 텍스트를 가상 DOM으로 파싱 + const parser = new DOMParser(); + const doc = parser.parseFromString(htmlText, 'text/html'); + + // 3. (필요 시) 역할 기반으로 가상 DOM 필터링 - 현재는 파일 자체가 역할별로 나뉘어 불필요 + // filterByRole(doc, currentUser.role); + + // 4. 가상 DOM에 동적 데이터 채우기 + populateStatsData(doc, statsData); + + // 5. 모든 수정이 완료된 HTML을 실제 DOM에 한 번에 삽입 + mainContainer.innerHTML = doc.body.innerHTML; + + console.log(`✅ ${currentUser.role} 역할의 섹션 로딩 완료.`); + + } catch (error) { + console.error('섹션 로딩 중 오류 발생:', error); + mainContainer.innerHTML = `
콘텐츠 로딩에 실패했습니다: ${error.message}
`; + } +} + +// DOM이 로드되면 섹션 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializeSections); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/load-sidebar.js b/deploy/tkfb-package/fastapi-bridge/static/js/load-sidebar.js new file mode 100644 index 0000000..5f912a2 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/load-sidebar.js @@ -0,0 +1,67 @@ +// /js/load-sidebar.js +import { getUser } from './auth.js'; + +/** + * 사용자 역할에 따라 사이드바 메뉴 항목을 필터링합니다. + * @param {Document} doc - 파싱된 HTML 문서 객체 + * @param {string} userRole - 현재 사용자의 역할 + */ +function filterSidebarByRole(doc, userRole) { + // 'system' 역할은 모든 메뉴를 볼 수 있으므로 필터링하지 않음 + if (userRole === 'system') { + return; + } + + // 역할과 그에 해당하는 클래스 선택자 매핑 + const roleClassMap = { + admin: '.admin-only', + leader: '.leader-only', + user: '.user-only', // 또는 'worker-only' 등, sidebar.html에 정의된 클래스에 맞춰야 함 + support: '.support-only' + }; + + // 모든 역할 기반 선택자를 가져옴 + const allRoleSelectors = Object.values(roleClassMap).join(', '); + const allRoleElements = doc.querySelectorAll(allRoleSelectors); + + allRoleElements.forEach(el => { + // 요소가 현재 사용자 역할에 해당하는 클래스를 가지고 있는지 확인 + const userRoleSelector = roleClassMap[userRole]; + if (!userRoleSelector || !el.matches(userRoleSelector)) { + el.remove(); + } + }); +} + + +document.addEventListener('DOMContentLoaded', async () => { + const sidebarContainer = document.getElementById('sidebar-container'); + if (!sidebarContainer) return; + + const currentUser = getUser(); + if (!currentUser) return; // 비로그인 상태면 사이드바를 로드하지 않음 + + try { + const response = await fetch('/components/sidebar.html'); + if (!response.ok) { + throw new Error(`사이드바 파일을 불러올 수 없습니다: ${response.statusText}`); + } + const htmlText = await response.text(); + + // 1. 텍스트를 가상 DOM으로 파싱 + const parser = new DOMParser(); + const doc = parser.parseFromString(htmlText, 'text/html'); + + // 2. DOM에 삽입하기 *전*에 역할에 따라 메뉴 필터링 + filterSidebarByRole(doc, currentUser.role); + + // 3. 수정 완료된 HTML을 실제 DOM에 삽입 + sidebarContainer.innerHTML = doc.body.innerHTML; + + console.log('✅ 사이드바 로딩 및 필터링 완료'); + + } catch (error) { + console.error('🔴 사이드바 로딩 실패:', error); + sidebarContainer.innerHTML = '

메뉴 로딩 실패

'; + } +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/login.js b/deploy/tkfb-package/fastapi-bridge/static/js/login.js new file mode 100644 index 0000000..9e79b91 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/login.js @@ -0,0 +1,58 @@ +// /js/login.js + +import { login } from './api-helper.js'; +import { saveAuthData, clearAuthData } from './auth.js'; + +document.getElementById('loginForm').addEventListener('submit', async function (e) { + e.preventDefault(); + + const username = document.getElementById('username').value; + const password = document.getElementById('password').value; + const errorDiv = document.getElementById('error'); + + const submitBtn = e.target.querySelector('button[type="submit"]'); + const originalText = submitBtn.textContent; + + // 로딩 상태 시작 + submitBtn.disabled = true; + submitBtn.textContent = '로그인 중...'; + errorDiv.style.display = 'none'; + + try { + // API 헬퍼를 통해 로그인 요청 + const result = await login(username, password); + + if (result.success && result.token) { + // 인증 정보 저장 + saveAuthData(result.token, result.user); + + // 백엔드가 지정한 URL로 리디렉션 + const redirectUrl = result.redirectUrl || '/pages/dashboard/user.html'; // 혹시 모를 예외처리 + + // 부드러운 화면 전환 효과 + document.body.style.transition = 'opacity 0.3s ease-out'; + document.body.style.opacity = '0'; + + setTimeout(() => { + window.location.href = redirectUrl; + }, 300); + + } else { + // 이 케이스는 api-helper에서 throw new Error()로 처리되어 catch 블록으로 바로 이동합니다. + // 하지만, 만약의 경우를 대비해 방어 코드를 남겨둡니다. + clearAuthData(); + errorDiv.textContent = result.error || '로그인에 실패했습니다.'; + errorDiv.style.display = 'block'; + } + } catch (err) { + console.error('로그인 오류:', err); + clearAuthData(); + // api-helper에서 보낸 에러 메시지를 표시 + errorDiv.textContent = err.message || '서버 연결에 실패했습니다.'; + errorDiv.style.display = 'block'; + } finally { + // 로딩 상태 해제 + submitBtn.disabled = false; + submitBtn.textContent = originalText; + } +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/manage-issue.js b/deploy/tkfb-package/fastapi-bridge/static/js/manage-issue.js new file mode 100644 index 0000000..dba6317 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/manage-issue.js @@ -0,0 +1,86 @@ +import { API, getAuthHeaders } from '/js/api-config.js'; + +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key]; + tr.appendChild(td); + }); + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + return tr; +} + +const form = document.getElementById('issueTypeForm'); +form?.addEventListener('submit', async e => { + e.preventDefault(); + const body = { + category: document.getElementById('category').value, + subcategory: document.getElementById('subcategory').value + }; + try { + const res = await fetch(`${API}/issue-types`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(body) + }); + const result = await res.json(); + if (res.ok && result.success) { + alert('✅ 등록 완료'); + form.reset(); + loadIssueTypes(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +async function loadIssueTypes() { + const tbody = document.getElementById('issueTypeTableBody'); + tbody.innerHTML = '불러오는 중...'; + try { + const res = await fetch(`${API}/issue-types`, { + headers: getAuthHeaders() + }); + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + list.forEach(item => { + const row = createRow(item, ['issue_type_id', 'category', 'subcategory'], async t => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/issue-types/${t.issue_type_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + loadIssueTypes(); + } else { + alert('삭제 실패'); + } + } catch (err) { + alert('삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +document.addEventListener('DOMContentLoaded', () => { + loadIssueTypes(); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/manage-pipespec.js b/deploy/tkfb-package/fastapi-bridge/static/js/manage-pipespec.js new file mode 100644 index 0000000..cceabb4 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/manage-pipespec.js @@ -0,0 +1,93 @@ +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +ensureAuthenticated(); + +// 행 생성 +function createRow(item, delHandler) { + const tr = document.createElement('tr'); + const label = `${item.material} / ${item.diameter_in} / ${item.schedule}`; + tr.innerHTML = ` + ${item.spec_id} + ${label} + + `; + tr.querySelector('.btn-delete').onclick = () => delHandler(item); + return tr; +} + +// 등록 +document.getElementById('specForm')?.addEventListener('submit', async e => { + e.preventDefault(); + const material = document.getElementById('material').value.trim(); + const diameter = document.getElementById('diameter_in').value.trim(); + const schedule = document.getElementById('schedule').value.trim(); + + if (!material || !diameter || !schedule) { + return alert('모든 항목을 입력하세요.'); + } + + try { + const res = await fetch(`${API}/pipespecs`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ material, diameter_in: diameter, schedule }) + }); + const result = await res.json(); + if (res.ok && result.success) { + alert('✅ 등록 완료'); + e.target.reset(); + loadSpecs(); + } else { + alert('❌ 실패: ' + (result.error || '등록 실패')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +// 불러오기 +async function loadSpecs() { + const tbody = document.getElementById('specTableBody'); + tbody.innerHTML = '불러오는 중...'; + try { + const res = await fetch(`${API}/pipespecs`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + list.forEach(item => { + const row = createRow(item, async (spec) => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/pipespecs/${spec.spec_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + loadSpecs(); + } else { + alert('삭제 실패'); + } + } catch (err) { + alert('삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +window.addEventListener('DOMContentLoaded', loadSpecs); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/manage-project.js b/deploy/tkfb-package/fastapi-bridge/static/js/manage-project.js new file mode 100644 index 0000000..323b6ed --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/manage-project.js @@ -0,0 +1,108 @@ +// /js/manage-project.js + +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +ensureAuthenticated(); + +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key]; + tr.appendChild(td); + }); + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + return tr; +} + +const projectForm = document.getElementById('projectForm'); +projectForm?.addEventListener('submit', async e => { + e.preventDefault(); + const body = { + job_no: document.getElementById('job_no').value.trim(), + project_name: document.getElementById('project_name').value.trim(), + contract_date: document.getElementById('contract_date').value, + due_date: document.getElementById('due_date').value, + delivery_method: document.getElementById('delivery_method').value.trim(), + site: document.getElementById('site').value.trim(), + pm: document.getElementById('pm').value.trim() + }; + + if (!body.project_name || !body.job_no) { + return alert('필수 항목을 입력하세요.'); + } + + try { + const res = await fetch(`${API}/projects`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(body) + }); + const result = await res.json(); + if (res.ok && result.success) { + alert('✅ 등록 완료'); + projectForm.reset(); + loadProjects(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +async function loadProjects() { + const tbody = document.getElementById('projectTableBody'); + tbody.innerHTML = '불러오는 중...'; + try { + const res = await fetch(`${API}/projects`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + list.forEach(item => { + const row = createRow(item, [ + 'project_id', 'job_no', 'project_name', 'contract_date', + 'due_date', 'delivery_method', 'site', 'pm' + ], async p => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/projects/${p.project_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + alert('✅ 삭제 완료'); + loadProjects(); + } else { + alert('❌ 삭제 실패'); + } + } catch (err) { + alert('🚨 삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +window.addEventListener('DOMContentLoaded', loadProjects); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/manage-task.js b/deploy/tkfb-package/fastapi-bridge/static/js/manage-task.js new file mode 100644 index 0000000..b6288bd --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/manage-task.js @@ -0,0 +1,104 @@ +// /js/manage-task.js + +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +ensureAuthenticated(); + +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key]; + tr.appendChild(td); + }); + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + return tr; +} + +const taskForm = document.getElementById('taskForm'); +taskForm?.addEventListener('submit', async e => { + e.preventDefault(); + const body = { + category: document.getElementById('category').value.trim(), + subcategory: document.getElementById('subcategory').value.trim(), + task_name: document.getElementById('task_name').value.trim(), + description: document.getElementById('description').value.trim() + }; + + if (!body.category || !body.task_name) { + return alert('필수 항목을 입력하세요'); + } + + try { + const res = await fetch(`${API}/tasks`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(body) + }); + const result = await res.json(); + if (res.ok && result.success) { + alert('✅ 등록 완료'); + taskForm.reset(); + loadTasks(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +async function loadTasks() { + const tbody = document.getElementById('taskTableBody'); + tbody.innerHTML = '불러오는 중...'; + try { + const res = await fetch(`${API}/tasks`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + list.forEach(item => { + const row = createRow(item, [ + 'task_id', 'category', 'subcategory', 'task_name', 'description' + ], async t => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/tasks/${t.task_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + alert('✅ 삭제 완료'); + loadTasks(); + } else { + alert('❌ 삭제 실패'); + } + } catch (err) { + alert('🚨 삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +window.addEventListener('DOMContentLoaded', loadTasks); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/manage-user.js b/deploy/tkfb-package/fastapi-bridge/static/js/manage-user.js new file mode 100644 index 0000000..4f07386 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/manage-user.js @@ -0,0 +1,288 @@ +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +const token = ensureAuthenticated(); + +const accessLabels = { + worker: '작업자', + group_leader: '그룹장', + support_team: '지원팀', + admin: '관리자', + system: '시스템' +}; + +// 현재 사용자 정보 가져오기 +const currentUser = JSON.parse(localStorage.getItem('user') || '{}'); +const isSystemUser = currentUser.access_level === 'system'; + +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key] || '-'; + tr.appendChild(td); + }); + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + return tr; +} + +// 내 비밀번호 변경 +const myPasswordForm = document.getElementById('myPasswordForm'); +myPasswordForm?.addEventListener('submit', async e => { + e.preventDefault(); + + const currentPassword = document.getElementById('currentPassword').value; + const newPassword = document.getElementById('newPassword').value; + const confirmPassword = document.getElementById('confirmPassword').value; + + // 새 비밀번호 확인 + if (newPassword !== confirmPassword) { + alert('❌ 새 비밀번호가 일치하지 않습니다.'); + return; + } + + // 비밀번호 강도 검사 + if (newPassword.length < 6) { + alert('❌ 비밀번호는 최소 6자 이상이어야 합니다.'); + return; + } + + try { + const res = await fetch(`${API}/auth/change-password`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + currentPassword, + newPassword + }) + }); + + const result = await res.json(); + + if (res.ok && result.success) { + showToast('✅ 비밀번호가 변경되었습니다.'); + myPasswordForm.reset(); + + // 3초 후 로그인 페이지로 이동 + setTimeout(() => { + alert('비밀번호가 변경되어 다시 로그인해주세요.'); + localStorage.removeItem('token'); + localStorage.removeItem('user'); + window.location.href = '/index.html'; + }, 2000); + } else { + alert('❌ 비밀번호 변경 실패: ' + (result.error || '현재 비밀번호가 올바르지 않습니다.')); + } + } catch (error) { + console.error('Password change error:', error); + alert('🚨 서버 오류: ' + error.message); + } +}); + +// 시스템 권한자만 볼 수 있는 사용자 비밀번호 변경 섹션 +if (isSystemUser) { + const systemCard = document.getElementById('systemPasswordChangeCard'); + if (systemCard) { + systemCard.style.display = 'block'; + } + + // 사용자 비밀번호 변경 (시스템 권한자) + const userPasswordForm = document.getElementById('userPasswordForm'); + userPasswordForm?.addEventListener('submit', async e => { + e.preventDefault(); + + const targetUserId = document.getElementById('targetUserId').value; + const newPassword = document.getElementById('targetNewPassword').value; + + if (!targetUserId) { + alert('❌ 사용자를 선택해주세요.'); + return; + } + + if (newPassword.length < 6) { + alert('❌ 비밀번호는 최소 6자 이상이어야 합니다.'); + return; + } + + if (!confirm('정말로 이 사용자의 비밀번호를 변경하시겠습니까?')) { + return; + } + + try { + const res = await fetch(`${API}/auth/admin/change-password`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + userId: targetUserId, + newPassword + }) + }); + + const result = await res.json(); + + if (res.ok && result.success) { + showToast('✅ 사용자 비밀번호가 변경되었습니다.'); + userPasswordForm.reset(); + } else { + alert('❌ 비밀번호 변경 실패: ' + (result.error || '권한이 없습니다.')); + } + } catch (error) { + console.error('Admin password change error:', error); + alert('🚨 서버 오류: ' + error.message); + } + }); +} + +// 사용자 등록 +const userForm = document.getElementById('userForm'); +userForm?.addEventListener('submit', async e => { + e.preventDefault(); + const body = { + username: document.getElementById('username').value.trim(), + password: document.getElementById('password').value.trim(), + name: document.getElementById('name').value.trim(), + access_level: document.getElementById('access_level').value, + worker_id: document.getElementById('worker_id').value || null + }; + + try { + const res = await fetch(`${API}/auth/register`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(body) + }); + const result = await res.json(); + if (res.ok && result.success) { + showToast('✅ 등록 완료'); + userForm.reset(); + loadUsers(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (error) { + console.error('Registration error:', error); + alert('🚨 서버 오류: ' + error.message); + } +}); + +async function loadUsers() { + const tbody = document.getElementById('userTableBody'); + tbody.innerHTML = '불러오는 중...'; + + try { + const res = await fetch(`${API}/auth/users`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + // 시스템 권한자용 사용자 선택 옵션도 업데이트 + if (isSystemUser) { + const targetUserSelect = document.getElementById('targetUserId'); + if (targetUserSelect) { + targetUserSelect.innerHTML = ''; + list.forEach(user => { + // 본인은 제외 + if (user.user_id !== currentUser.user_id) { + const opt = document.createElement('option'); + opt.value = user.user_id; + opt.textContent = `${user.name} (${user.username})`; + targetUserSelect.appendChild(opt); + } + }); + } + } + + list.forEach(item => { + item.access_level = accessLabels[item.access_level] || item.access_level; + item.worker_id = item.worker_id || '-'; + const row = createRow(item, [ + 'user_id', 'username', 'name', 'access_level', 'worker_id' + ], async u => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/auth/users/${u.user_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + showToast('✅ 삭제 완료'); + loadUsers(); + } else { + alert('❌ 삭제 실패'); + } + } catch (error) { + alert('🚨 삭제 중 오류 발생'); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (error) { + console.error('Load users error:', error); + tbody.innerHTML = '로드 실패: ' + error.message + ''; + } +} + +async function loadWorkerOptions() { + const select = document.getElementById('worker_id'); + if (!select) return; + + try { + const res = await fetch(`${API}/workers`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const workers = await res.json(); + if (Array.isArray(workers)) { + workers.forEach(w => { + const opt = document.createElement('option'); + opt.value = w.worker_id; + opt.textContent = `${w.worker_name} (${w.worker_id})`; + select.appendChild(opt); + }); + } + } catch (error) { + console.warn('작업자 목록 불러오기 실패:', error); + } +} + +function showToast(message) { + const toast = document.createElement('div'); + toast.textContent = message; + toast.style.position = 'fixed'; + toast.style.bottom = '30px'; + toast.style.left = '50%'; + toast.style.transform = 'translateX(-50%)'; + toast.style.background = '#323232'; + toast.style.color = '#fff'; + toast.style.padding = '10px 20px'; + toast.style.borderRadius = '6px'; + toast.style.fontSize = '14px'; + toast.style.zIndex = 9999; + document.body.appendChild(toast); + setTimeout(() => toast.remove(), 2000); +} + +window.addEventListener('DOMContentLoaded', () => { + loadUsers(); + loadWorkerOptions(); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/manage-worker.js b/deploy/tkfb-package/fastapi-bridge/static/js/manage-worker.js new file mode 100644 index 0000000..93202e4 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/manage-worker.js @@ -0,0 +1,110 @@ +// /js/manage-worker.js + +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +ensureAuthenticated(); + +// ✅ 테이블 행 생성 +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key] || '-'; + tr.appendChild(td); + }); + + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + + return tr; +} + +// ✅ 작업자 등록 +const workerForm = document.getElementById('workerForm'); +workerForm?.addEventListener('submit', async e => { + e.preventDefault(); + + const body = { + worker_name: document.getElementById('workerName').value.trim(), + position: document.getElementById('position').value.trim() + }; + + if (!body.worker_name || !body.position) { + return alert('모든 필드를 입력해주세요.'); + } + + try { + const res = await fetch(`${API}/workers`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(body) + }); + const result = await res.json(); + + if (res.ok && result.success) { + alert('✅ 등록 완료'); + workerForm.reset(); + loadWorkers(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +// ✅ 작업자 목록 불러오기 +async function loadWorkers() { + const tbody = document.getElementById('workerTableBody'); + tbody.innerHTML = '불러오는 중...'; + + try { + const res = await fetch(`${API}/workers`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + list.forEach(item => { + const row = createRow(item, ['worker_id', 'worker_name', 'position'], async w => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/workers/${w.worker_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + alert('✅ 삭제 완료'); + loadWorkers(); + } else { + alert('❌ 삭제 실패'); + } + } catch (err) { + alert('🚨 삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +// ✅ 초기 로딩 +window.addEventListener('DOMContentLoaded', loadWorkers); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/management-dashboard.js b/deploy/tkfb-package/fastapi-bridge/static/js/management-dashboard.js new file mode 100644 index 0000000..e43cb7e --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/management-dashboard.js @@ -0,0 +1,954 @@ +// management-dashboard.js - 관리자 대시보드 전용 스크립트 + +// ================================================================= +// 🌐 통합 API 설정 import +// ================================================================= +import { API, getAuthHeaders, apiCall } from '/js/api-config.js'; + +// 전역 변수 +let workers = []; +let workData = []; +let filteredWorkData = []; +let currentDate = ''; +let currentUser = null; + +// 권한 레벨 매핑 +const ACCESS_LEVELS = { + worker: 1, + group_leader: 2, + support_team: 3, + admin: 4, + system: 5 +}; + +// 한국 시간 기준 오늘 날짜 가져오기 +function getKoreaToday() { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const day = String(today.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +// 현재 로그인한 사용자 정보 가져오기 +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + console.log('토큰에서 추출한 사용자 정보:', payload); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + + try { + const userInfo = localStorage.getItem('user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + if (userInfo) { + const parsed = JSON.parse(userInfo); + console.log('localStorage에서 가져온 사용자 정보:', parsed); + return parsed; + } + } catch (error) { + console.log('localStorage에서 사용자 정보 가져오기 실패:', error); + } + + return null; +} + +// 권한 체크 함수 +function checkPermission() { + currentUser = getCurrentUser(); + + if (!currentUser) { + showMessage('로그인이 필요합니다.', 'error'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return false; + } + + const userAccessLevel = currentUser.access_level; + const accessLevelValue = ACCESS_LEVELS[userAccessLevel] || 0; + + console.log('사용자 권한 체크:', { + username: currentUser.username || currentUser.name, + access_level: userAccessLevel, + level_value: accessLevelValue, + required_level: ACCESS_LEVELS.group_leader + }); + + if (accessLevelValue < ACCESS_LEVELS.group_leader) { + showMessage('그룹장 이상의 권한이 필요합니다. 현재 권한: ' + userAccessLevel, 'error'); + setTimeout(() => { + window.location.href = '/'; + }, 3000); + return false; + } + + return true; +} + +// 메시지 표시 +function showMessage(message, type = 'info') { + const container = document.getElementById('message-container'); + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => { + hideMessage(); + }, 5000); + } +} + +function hideMessage() { + document.getElementById('message-container').innerHTML = ''; +} + +// 로딩 표시 +function showLoading() { + document.getElementById('loadingSpinner').style.display = 'flex'; + document.getElementById('summarySection').style.display = 'none'; + document.getElementById('actionBar').style.display = 'none'; + document.getElementById('workersSection').style.display = 'none'; + document.getElementById('noDataMessage').style.display = 'none'; +} + +function hideLoading() { + document.getElementById('loadingSpinner').style.display = 'none'; +} + +// 작업자 데이터 로드 +async function loadWorkers() { + try { + console.log('작업자 데이터 로딩 중... (통합 API)'); + const data = await apiCall(`${API}/workers`); + workers = Array.isArray(data) ? data : (data.workers || []); + console.log('✅ 작업자 로드 성공:', workers.length); + } catch (error) { + console.error('작업자 로딩 오류:', error); + throw error; + } +} + +// 특정 날짜의 작업 데이터 로드 (개선된 버전) +async function loadWorkData(date) { + try { + console.log(`${date} 날짜의 작업 데이터 로딩 중... (통합 API)`); + + // 1차: view_all=true로 전체 데이터 시도 + let queryParams = `date=${date}&view_all=true`; + console.log(`🔍 1차 시도: ${API}/daily-work-reports?${queryParams}`); + + let data = await apiCall(`${API}/daily-work-reports?${queryParams}`); + workData = Array.isArray(data) ? data : (data.data || []); + + // 데이터가 없으면 다른 방법들 시도 + if (workData.length === 0) { + console.log('⚠️ view_all로 데이터 없음, 다른 방법 시도...'); + + // 2차: admin=true로 시도 + queryParams = `date=${date}&admin=true`; + console.log(`🔍 2차 시도: ${API}/daily-work-reports?${queryParams}`); + + data = await apiCall(`${API}/daily-work-reports?${queryParams}`); + workData = Array.isArray(data) ? data : (data.data || []); + + if (workData.length === 0) { + // 3차: 날짜 경로 파라미터로 시도 + console.log(`🔍 3차 시도: ${API}/daily-work-reports/date/${date}`); + + data = await apiCall(`${API}/daily-work-reports/date/${date}`); + workData = Array.isArray(data) ? data : (data.data || []); + + if (workData.length === 0) { + // 4차: 기본 파라미터만으로 시도 + console.log(`🔍 4차 시도: ${API}/daily-work-reports?date=${date}`); + + data = await apiCall(`${API}/daily-work-reports?date=${date}`); + workData = Array.isArray(data) ? data : (data.data || []); + } + } + } + + console.log(`✅ 최종 작업 데이터 로드 결과: ${workData.length}개`); + + // 디버깅을 위한 상세 로그 + if (workData.length > 0) { + console.log('📊 로드된 데이터 샘플:', workData.slice(0, 3)); + const uniqueWorkers = [...new Set(workData.map(w => w.worker_name))]; + console.log('👥 데이터에 포함된 작업자들:', uniqueWorkers); + } else { + console.log('❌ 해당 날짜에 작업 데이터가 없거나 접근 권한이 없습니다.'); + } + + return workData; + } catch (error) { + console.error('작업 데이터 로딩 오류:', error); + + // 에러 시에도 빈 배열 반환하여 앱이 중단되지 않도록 + workData = []; + + // 구체적인 에러 정보 표시 + if (error.message.includes('403')) { + console.log('🔒 권한 부족으로 인한 접근 제한'); + throw new Error('해당 날짜의 데이터에 접근할 권한이 없습니다.'); + } else if (error.message.includes('404')) { + console.log('📭 해당 날짜에 데이터 없음'); + throw new Error('해당 날짜에 입력된 작업 데이터가 없습니다.'); + } else { + throw error; + } + } +} + +// 대시보드 데이터 로드 +async function loadDashboardData() { + const selectedDate = document.getElementById('selectedDate').value; + + if (!selectedDate) { + showMessage('날짜를 선택해주세요.', 'error'); + return; + } + + currentDate = selectedDate; + showLoading(); + hideMessage(); + + try { + // 병렬로 데이터 로드 + await Promise.all([ + loadWorkers(), + loadWorkData(selectedDate) + ]); + + // 데이터 분석 및 표시 + const dashboardData = analyzeDashboardData(); + displayDashboard(dashboardData); + + hideLoading(); + + } catch (error) { + console.error('대시보드 데이터 로드 실패:', error); + hideLoading(); + showMessage('데이터를 불러오는 중 오류가 발생했습니다: ' + error.message, 'error'); + + // 에러 시 데이터 없음 메시지 표시 + document.getElementById('noDataMessage').style.display = 'block'; + } +} + +// 대시보드 데이터 분석 (개선된 버전) +function analyzeDashboardData() { + console.log('대시보드 데이터 분석 시작'); + + // 작업자별 데이터 그룹화 + const workerWorkData = {}; + workData.forEach(work => { + const workerId = work.worker_id; + if (!workerWorkData[workerId]) { + workerWorkData[workerId] = []; + } + workerWorkData[workerId].push(work); + }); + + // 전체 통계 계산 + const totalWorkers = workers.length; + const workersWithData = Object.keys(workerWorkData).length; + const workersWithoutData = totalWorkers - workersWithData; + const totalHours = workData.reduce((sum, work) => sum + parseFloat(work.work_hours || 0), 0); + const totalEntries = workData.length; + const errorCount = workData.filter(work => work.work_status_id === 2).length; + + // 작업자별 상세 분석 (개선된 버전) + const workerAnalysis = workers.map(worker => { + const workerWorks = workerWorkData[worker.worker_id] || []; + const workerHours = workerWorks.reduce((sum, work) => sum + parseFloat(work.work_hours || 0), 0); + + // 작업 유형 분석 (실제 이름으로) + const workTypes = [...new Set(workerWorks.map(work => work.work_type_name).filter(Boolean))]; + + // 프로젝트 분석 + const workerProjects = [...new Set(workerWorks.map(work => work.project_name).filter(Boolean))]; + + // 기여자 분석 + const workerContributors = [...new Set(workerWorks.map(work => work.created_by_name).filter(Boolean))]; + + // 상태 결정 (더 세밀한 기준) + let status = 'missing'; + if (workerWorks.length > 0) { + if (workerHours >= 6) { + status = 'completed'; // 6시간 이상을 완료로 간주 + } else { + status = 'partial'; // 1시간 이상이지만 6시간 미만은 부분입력 + } + } + + // 최근 업데이트 시간 + const lastUpdate = workerWorks.length > 0 + ? new Date(Math.max(...workerWorks.map(work => new Date(work.created_at)))) + : null; + + return { + ...worker, + status, + totalHours: Math.round(workerHours * 10) / 10, // 소수점 1자리로 반올림 + entryCount: workerWorks.length, + workTypes, // 작업 유형 배열 (실제 이름) + projects: workerProjects, + contributors: workerContributors, + lastUpdate, + works: workerWorks + }; + }); + + const summary = { + totalWorkers, + completedWorkers: workerAnalysis.filter(w => w.status === 'completed').length, + missingWorkers: workerAnalysis.filter(w => w.status === 'missing').length, + partialWorkers: workerAnalysis.filter(w => w.status === 'partial').length, + totalHours: Math.round(totalHours * 10) / 10, + totalEntries, + errorCount + }; + + console.log('대시보드 분석 결과:', { summary, workerAnalysis }); + + return { + summary, + workers: workerAnalysis, + date: currentDate + }; +} + +// 대시보드 표시 +function displayDashboard(data) { + displaySummary(data.summary); + displayWorkers(data.workers); + + // 섹션 표시 + document.getElementById('summarySection').style.display = 'block'; + document.getElementById('actionBar').style.display = 'flex'; + document.getElementById('workersSection').style.display = 'block'; + + // 필터링 설정 + filteredWorkData = data.workers; + setupFiltering(); + + console.log('✅ 대시보드 표시 완료'); +} + +// 요약 섹션 표시 +function displaySummary(summary) { + document.getElementById('totalWorkers').textContent = summary.totalWorkers; + document.getElementById('completedWorkers').textContent = summary.completedWorkers; + document.getElementById('missingWorkers').textContent = summary.missingWorkers; + document.getElementById('totalHours').textContent = summary.totalHours + 'h'; + document.getElementById('totalEntries').textContent = summary.totalEntries; + document.getElementById('errorCount').textContent = summary.errorCount; +} + +// 작업자 목록 표시 (테이블 형태로 개선) +function displayWorkers(workersData) { + const tableBody = document.getElementById('workersTableBody'); + tableBody.innerHTML = ''; + + if (workersData.length === 0) { + tableBody.innerHTML = ` + + 표시할 작업자가 없습니다. + + `; + return; + } + + workersData.forEach(worker => { + const row = createWorkerRow(worker); + tableBody.appendChild(row); + }); +} + +// 작업자 테이블 행 생성 (개선된 버전) +function createWorkerRow(worker) { + const row = document.createElement('tr'); + + const statusText = { + completed: '✅ 완료', + missing: '❌ 미입력', + partial: '⚠️ 부분입력' + }; + + const statusClass = { + completed: 'completed', + missing: 'missing', + partial: 'partial' + }; + + // 작업 유형 태그 생성 (실제 이름으로) + const workTypeTags = worker.workTypes && worker.workTypes.length > 0 + ? worker.workTypes.map(type => `${type}`).join('') + : '없음'; + + // 프로젝트 태그 생성 + const projectTags = worker.projects && worker.projects.length > 0 + ? worker.projects.map(project => `${project}`).join('') + : '없음'; + + // 기여자 태그 생성 + const contributorTags = worker.contributors && worker.contributors.length > 0 + ? worker.contributors.map(contributor => `${contributor}`).join('') + : '없음'; + + // 시간에 따른 스타일 클래스 + let hoursClass = 'zero'; + if (worker.totalHours > 0) { + hoursClass = worker.totalHours >= 6 ? 'full' : 'partial'; + } + + // 업데이트 시간 포맷팅 및 스타일 + let updateTimeText = '없음'; + let updateClass = ''; + if (worker.lastUpdate) { + const now = new Date(); + const diff = now - worker.lastUpdate; + const hours = diff / (1000 * 60 * 60); + + updateTimeText = formatDateTime(worker.lastUpdate); + updateClass = hours < 1 ? 'recent' : hours > 24 ? 'old' : ''; + } + + row.innerHTML = ` + +
+ 👤 ${worker.worker_name} +
+ + + ${statusText[worker.status]} + + +
${worker.totalHours}h
+ + + ${worker.entryCount}개 + + +
${workTypeTags}
+ + +
${projectTags}
+ + +
${contributorTags}
+ + +
${updateTimeText}
+ + + + + `; + + return row; +} + +// 날짜/시간 포맷팅 +function formatDateTime(date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + const hours = String(d.getHours()).padStart(2, '0'); + const minutes = String(d.getMinutes()).padStart(2, '0'); + + return `${year}-${month}-${day} ${hours}:${minutes}`; +} + +// 작업자 상세 모달 표시 (안전한 버전) +function showWorkerDetailSafe(workerId) { + // 현재 분석된 데이터에서 해당 작업자 찾기 + const worker = filteredWorkData.find(w => w.worker_id == workerId); + if (!worker) { + showMessage('작업자 정보를 찾을 수 없습니다.', 'error'); + return; + } + + showWorkerDetail(worker); +} + +// 작업자 상세 모달 표시 (개선된 버전) +function showWorkerDetail(worker) { + const modal = document.getElementById('workerDetailModal'); + const modalTitle = document.getElementById('modalWorkerName'); + const modalBody = document.getElementById('modalWorkerDetails'); + + modalTitle.textContent = `👤 ${worker.worker_name} 상세 현황`; + + let detailHtml = ` +
+

📊 기본 정보

+

작업자명: ${worker.worker_name}

+

총 작업시간: ${worker.totalHours}시간

+

작업 항목 수: ${worker.entryCount}개

+

상태: ${worker.status === 'completed' ? '✅ 완료' : worker.status === 'missing' ? '❌ 미입력' : '⚠️ 부분입력'}

+

작업 유형: ${worker.workTypes && worker.workTypes.length > 0 ? worker.workTypes.join(', ') : '없음'}

+
+ `; + + if (worker.works && worker.works.length > 0) { + detailHtml += ` +
+

🔧 작업 내역

+
+ `; + + worker.works.forEach((work, index) => { + detailHtml += ` +
+
+

작업 ${index + 1}

+
+ + +
+
+

프로젝트: ${work.project_name || '미지정'}

+

작업 유형: ${work.work_type_name || '미지정'}

+

작업 시간: ${work.work_hours}시간

+

상태: ${work.work_status_name || '미지정'}

+ ${work.error_type_name ? `

에러 유형: ${work.error_type_name}

` : ''} +

입력자: ${work.created_by_name || '미지정'}

+

입력 시간: ${formatDateTime(work.created_at)}

+
+ `; + }); + + detailHtml += ` +
+
+ `; + } else { + detailHtml += ` +
+

📭 작업 내역

+

입력된 작업이 없습니다.

+
+ `; + } + + if (worker.contributors && worker.contributors.length > 0) { + detailHtml += ` +
+

👥 기여자

+

${worker.contributors.join(', ')}

+
+ `; + } + + modalBody.innerHTML = detailHtml; + modal.style.display = 'flex'; +} + +// 작업 항목 수정 함수 (통합 API 사용) +async function editWorkItem(workId) { + try { + console.log('수정할 작업 ID:', workId); + + // 현재 작업 데이터에서 해당 작업 찾기 + let workData = null; + for (const worker of filteredWorkData) { + if (worker.works) { + workData = worker.works.find(work => work.id == workId); + if (workData) break; + } + } + + if (!workData) { + showMessage('수정할 작업을 찾을 수 없습니다.', 'error'); + return; + } + + // 필요한 마스터 데이터 로드 + await loadMasterDataForEdit(); + + // 수정 모달 표시 + showEditModal(workData); + + } catch (error) { + console.error('작업 정보 조회 오류:', error); + showMessage('작업 정보를 불러올 수 없습니다: ' + error.message, 'error'); + } +} + +// 수정용 마스터 데이터 로드 +async function loadMasterDataForEdit() { + try { + if (!window.projects || window.projects.length === 0) { + const projectData = await apiCall(`${API}/projects`); + window.projects = Array.isArray(projectData) ? projectData : (projectData.projects || []); + } + + if (!window.workTypes || window.workTypes.length === 0) { + const workTypeData = await apiCall(`${API}/daily-work-reports/work-types`); + window.workTypes = Array.isArray(workTypeData) ? workTypeData : []; + } + + if (!window.workStatusTypes || window.workStatusTypes.length === 0) { + const statusData = await apiCall(`${API}/daily-work-reports/work-status-types`); + window.workStatusTypes = Array.isArray(statusData) ? statusData : []; + } + + if (!window.errorTypes || window.errorTypes.length === 0) { + const errorData = await apiCall(`${API}/daily-work-reports/error-types`); + window.errorTypes = Array.isArray(errorData) ? errorData : []; + } + + } catch (error) { + console.error('마스터 데이터 로드 오류:', error); + + // 기본값 설정 + window.projects = window.projects || []; + window.workTypes = window.workTypes || [ + {id: 1, name: 'Base'}, + {id: 2, name: 'Vessel'}, + {id: 3, name: 'Piping'} + ]; + window.workStatusTypes = window.workStatusTypes || [ + {id: 1, name: '정규'}, + {id: 2, name: '에러'} + ]; + window.errorTypes = window.errorTypes || [ + {id: 1, name: '설계미스'}, + {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, + {id: 4, name: '작업 불량'} + ]; + } +} + +// 수정 모달 표시 +function showEditModal(workData) { + // 기존 상세 모달 닫기 + closeWorkerDetailModal(); + + const modalHtml = ` +
+
+
+

✏️ 작업 수정

+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ `; + + document.body.insertAdjacentHTML('beforeend', modalHtml); + + // 업무 상태 변경 이벤트 + document.getElementById('editWorkStatus').addEventListener('change', (e) => { + const errorTypeGroup = document.getElementById('editErrorTypeGroup'); + if (e.target.value === '2') { + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + } + }); +} + +// 수정 모달 닫기 +function closeEditModal() { + const modal = document.getElementById('editModal'); + if (modal) { + modal.remove(); + } +} + +// 수정된 작업 저장 (통합 API 사용) +async function saveEditedWork(workId) { + try { + const projectId = document.getElementById('editProject').value; + const workTypeId = document.getElementById('editWorkType').value; + const workStatusId = document.getElementById('editWorkStatus').value; + const errorTypeId = document.getElementById('editErrorType').value; + const workHours = document.getElementById('editWorkHours').value; + + if (!projectId || !workTypeId || !workStatusId || !workHours) { + showMessage('모든 필수 항목을 입력해주세요.', 'error'); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showMessage('에러 상태인 경우 에러 유형을 선택해주세요.', 'error'); + return; + } + + const updateData = { + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: errorTypeId ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours) + }; + + showMessage('작업을 수정하는 중... (통합 API)', 'loading'); + + const result = await apiCall(`${API}/daily-work-reports/${workId}`, { + method: 'PUT', + body: JSON.stringify(updateData) + }); + + console.log('✅ 수정 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); + + closeEditModal(); + closeWorkerDetailModal(); + + // 데이터 새로고침 + await loadDashboardData(); + + } catch (error) { + console.error('❌ 수정 실패:', error); + showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 작업 항목 삭제 함수 (통합 API 사용) +async function deleteWorkItem(workId) { + if (!confirm('정말로 이 작업을 삭제하시겠습니까?\n삭제된 작업은 복구할 수 없습니다.')) { + return; + } + + try { + console.log('삭제할 작업 ID:', workId); + + showMessage('작업을 삭제하는 중... (통합 API)', 'loading'); + + // 개별 항목 삭제 API 호출 - 통합 API 사용 + const result = await apiCall(`${API}/daily-work-reports/${workId}`, { + method: 'DELETE' + }); + + console.log('✅ 삭제 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); + + closeWorkerDetailModal(); + + // 데이터 새로고침 + await loadDashboardData(); + + } catch (error) { + console.error('❌ 삭제 실패:', error); + showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 작업자 상세 모달 닫기 +function closeWorkerDetailModal() { + document.getElementById('workerDetailModal').style.display = 'none'; +} + +// 필터링 설정 +function setupFiltering() { + const showOnlyMissingCheckbox = document.getElementById('showOnlyMissing'); + + showOnlyMissingCheckbox.addEventListener('change', (e) => { + if (e.target.checked) { + // 미입력자만 필터링 + const missingWorkers = filteredWorkData.filter(worker => worker.status === 'missing'); + displayWorkers(missingWorkers); + } else { + // 전체 표시 + displayWorkers(filteredWorkData); + } + }); +} + +// 엑셀 다운로드 (개선된 버전) +function exportToExcel() { + try { + // CSV 형태로 데이터 구성 (개선된 버전) + let csvContent = "작업자명,상태,총시간,작업항목수,작업유형,프로젝트,기여자,최근업데이트\n"; + + filteredWorkData.forEach(worker => { + const statusText = { + completed: '완료', + missing: '미입력', + partial: '부분입력' + }; + + const workTypes = worker.workTypes && worker.workTypes.length > 0 ? worker.workTypes.join('; ') : '없음'; + const projects = worker.projects && worker.projects.length > 0 ? worker.projects.join('; ') : '없음'; + const contributors = worker.contributors && worker.contributors.length > 0 ? worker.contributors.join('; ') : '없음'; + const lastUpdate = worker.lastUpdate ? formatDateTime(worker.lastUpdate) : '없음'; + + csvContent += `"${worker.worker_name}","${statusText[worker.status]}","${worker.totalHours}","${worker.entryCount}","${workTypes}","${projects}","${contributors}","${lastUpdate}"\n`; + }); + + // UTF-8 BOM 추가 (한글 깨짐 방지) + const BOM = '\uFEFF'; + const blob = new Blob([BOM + csvContent], { type: 'text/csv;charset=utf-8;' }); + const link = document.createElement('a'); + const url = URL.createObjectURL(blob); + + link.setAttribute('href', url); + link.setAttribute('download', `작업현황_${currentDate}.csv`); + link.style.visibility = 'hidden'; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + showMessage('✅ 엑셀 파일이 다운로드되었습니다!', 'success'); + + } catch (error) { + console.error('엑셀 다운로드 오류:', error); + showMessage('엑셀 다운로드 중 오류가 발생했습니다.', 'error'); + } +} + +// 새로고침 +function refreshData() { + loadDashboardData(); +} + +// 이벤트 리스너 설정 +function setupEventListeners() { + document.getElementById('loadDataBtn').addEventListener('click', loadDashboardData); + document.getElementById('refreshBtn').addEventListener('click', refreshData); + document.getElementById('exportBtn').addEventListener('click', exportToExcel); + + // 엔터키로 조회 + document.getElementById('selectedDate').addEventListener('keypress', (e) => { + if (e.key === 'Enter') { + loadDashboardData(); + } + }); +} + +// 초기화 +async function init() { + try { + // 권한 체크 + if (!checkPermission()) { + return; + } + + // 권한 체크 메시지 숨기기 + document.getElementById('permission-check-message').style.display = 'none'; + + // 오늘 날짜 설정 + document.getElementById('selectedDate').value = getKoreaToday(); + + // 이벤트 리스너 설정 + setupEventListeners(); + + console.log('✅ 관리자 대시보드 초기화 완료 (통합 API 설정 적용)'); + + // 자동으로 오늘 데이터 로드 + loadDashboardData(); + + } catch (error) { + console.error('초기화 오류:', error); + showMessage('초기화 중 오류가 발생했습니다.', 'error'); + } +} + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', () => { + // 권한 체크 메시지 표시 + document.getElementById('permission-check-message').style.display = 'block'; + + // 토큰 확인 + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + showMessage('로그인이 필요합니다.', 'error'); + localStorage.removeItem('token'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + // 초기화 실행 + init(); +}); + +// 전역 함수로 노출 +window.closeWorkerDetailModal = closeWorkerDetailModal; +window.refreshData = refreshData; +window.showWorkerDetailSafe = showWorkerDetailSafe; +window.showWorkerDetail = showWorkerDetail; +window.editWorkItem = editWorkItem; +window.deleteWorkItem = deleteWorkItem; +window.closeEditModal = closeEditModal; +window.saveEditedWork = saveEditedWork; \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/my-profile.js b/deploy/tkfb-package/fastapi-bridge/static/js/my-profile.js new file mode 100644 index 0000000..222ab99 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/my-profile.js @@ -0,0 +1,122 @@ +// js/my-profile.js +// 내 프로필 페이지 JavaScript + +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +const token = ensureAuthenticated(); + +// 권한 레벨 한글 매핑 +const accessLevelMap = { + worker: '작업자', + group_leader: '그룹장', + support_team: '지원팀', + admin: '관리자', + system: '시스템 관리자' +}; + +// 프로필 데이터 로드 +async function loadProfile() { + try { + // 먼저 로컬 스토리지에서 기본 정보 표시 + const storedUser = JSON.parse(localStorage.getItem('user') || '{}'); + if (storedUser) { + updateProfileUI(storedUser); + } + + // API에서 최신 정보 가져오기 + const res = await fetch(`${API}/auth/me`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const userData = await res.json(); + + // 로컬 스토리지 업데이트 + const updatedUser = { + ...storedUser, + ...userData + }; + localStorage.setItem('user', JSON.stringify(updatedUser)); + + // UI 업데이트 + updateProfileUI(userData); + + } catch (error) { + console.error('프로필 로딩 실패:', error); + showError('프로필 정보를 불러오는데 실패했습니다.'); + } +} + +// 프로필 UI 업데이트 +function updateProfileUI(user) { + // 헤더 정보 + const avatar = document.getElementById('profileAvatar'); + if (avatar && user.name) { + // 이름의 첫 글자를 아바타로 사용 + const initial = user.name.charAt(0).toUpperCase(); + if (initial.match(/[A-Z가-힣]/)) { + avatar.textContent = initial; + } + } + + document.getElementById('profileName').textContent = user.name || user.username || '사용자'; + document.getElementById('profileRole').textContent = accessLevelMap[user.access_level] || user.access_level || '역할 미지정'; + + // 기본 정보 + document.getElementById('userId').textContent = user.user_id || '-'; + document.getElementById('username').textContent = user.username || '-'; + document.getElementById('fullName').textContent = user.name || '-'; + document.getElementById('accessLevel').textContent = accessLevelMap[user.access_level] || user.access_level || '-'; + document.getElementById('workerId').textContent = user.worker_id || '연결되지 않음'; + + // 날짜 포맷팅 + if (user.created_at) { + const createdDate = new Date(user.created_at); + document.getElementById('createdAt').textContent = formatDate(createdDate); + } + + if (user.last_login_at) { + const lastLoginDate = new Date(user.last_login_at); + document.getElementById('lastLogin').textContent = formatDateTime(lastLoginDate); + } else { + document.getElementById('lastLogin').textContent = '첫 로그인'; + } + + // 이메일 + document.getElementById('email').textContent = user.email || '등록되지 않음'; +} + +// 날짜 포맷팅 함수 +function formatDate(date) { + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: 'long', + day: 'numeric' + }); +} + +function formatDateTime(date) { + return date.toLocaleString('ko-KR', { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); +} + +// 에러 표시 +function showError(message) { + // 간단한 알림으로 처리 + alert('❌ ' + message); +} + +// 페이지 로드 시 실행 +document.addEventListener('DOMContentLoaded', () => { + console.log('👤 프로필 페이지 로드됨'); + loadProfile(); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis-api.js b/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis-api.js new file mode 100644 index 0000000..2518597 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis-api.js @@ -0,0 +1,37 @@ +// /js/project-analysis-api.js +import { apiGet } from './api-helper.js'; + +/** + * 분석 페이지에 필요한 모든 초기 데이터(마스터 데이터)를 병렬로 가져옵니다. + * 이 데이터는 필터 옵션을 채우는 데 사용됩니다. + * @returns {Promise<{workers: Array, projects: Array, tasks: Array}>} + */ +export async function getMasterData() { + try { + const [workers, projects, tasks] = await Promise.all([ + apiGet('/workers'), + apiGet('/projects'), + apiGet('/tasks') + ]); + return { workers, projects, tasks }; + } catch (error) { + console.error('마스터 데이터 로딩 실패:', error); + throw new Error('필터링에 필요한 데이터를 불러오는 데 실패했습니다.'); + } +} + +/** + * 지정된 기간의 모든 분석 데이터를 백엔드에서 직접 가져옵니다. + * @param {string} startDate - 시작일 (YYYY-MM-DD) + * @param {string} endDate - 종료일 (YYYY-MM-DD) + * @returns {Promise} - 요약, 집계, 상세 데이터가 모두 포함된 분석 결과 객체 + */ +export async function getAnalysisReport(startDate, endDate) { + try { + const analysisData = await apiGet(`/analysis?startDate=${startDate}&endDate=${endDate}`); + return analysisData; + } catch (error) { + console.error('분석 보고서 데이터 로딩 실패:', error); + throw new Error(`분석 데이터를 불러오는 데 실패했습니다: ${error.message}`); + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis-ui.js b/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis-ui.js new file mode 100644 index 0000000..75c49e6 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis-ui.js @@ -0,0 +1,170 @@ +// /js/project-analysis-ui.js + +const DOM = { + // 기간 설정 + startDate: document.getElementById('startDate'), + endDate: document.getElementById('endDate'), + // 카드 및 필터 + analysisCard: document.getElementById('analysisCard'), + summaryCards: document.getElementById('summaryCards'), + projectFilter: document.getElementById('projectFilter'), + workerFilter: document.getElementById('workerFilter'), + taskFilter: document.getElementById('taskFilter'), + // 탭 + tabButtons: document.querySelectorAll('.tab-button'), + tabContents: document.querySelectorAll('.analysis-content'), + // 테이블 본문 + projectTableBody: document.getElementById('projectTableBody'), + workerTableBody: document.getElementById('workerTableBody'), + taskTableBody: document.getElementById('taskTableBody'), + detailTableBody: document.getElementById('detailTableBody'), +}; + +/** + * 날짜 input 값을 YYYY-MM-DD 형식의 문자열로 반환 + * @param {Date} date - 날짜 객체 + * @returns {string} - 포맷된 날짜 문자열 + */ +const formatDate = (date) => date.toISOString().split('T')[0]; + +/** + * UI상의 날짜 선택기를 기본값(이번 달)으로 설정합니다. + */ +export function setDefaultDates() { + const now = new Date(); + const firstDay = new Date(now.getFullYear(), now.getMonth(), 1); + const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0); + DOM.startDate.value = formatDate(firstDay); + DOM.endDate.value = formatDate(lastDay); +} + +/** + * 분석 실행 전후의 UI 상태를 관리합니다 (로딩 표시 등) + * @param {'loading' | 'data' | 'no-data' | 'error'} state - UI 상태 + */ +export function setUIState(state) { + const projectCols = 5; + const detailCols = 8; + const messages = { + loading: '📊 데이터 분석 중...', + 'no-data': '해당 기간에 분석할 데이터가 없습니다.', + error: '오류가 발생했습니다. 다시 시도해주세요.', + }; + + if (state === 'data') { + DOM.analysisCard.style.display = 'block'; + } else { + const message = messages[state]; + const html = `${message}`; + const detailHtml = `${message}`; + DOM.projectTableBody.innerHTML = html; + DOM.workerTableBody.innerHTML = html; + DOM.taskTableBody.innerHTML = html; + DOM.detailTableBody.innerHTML = detailHtml; + DOM.summaryCards.innerHTML = ''; + DOM.analysisCard.style.display = 'block'; + } +} + + +/** + * 마스터 데이터를 기반으로 필터 옵션을 채웁니다. + * @param {{workers: Array, projects: Array, tasks: Array}} masterData - 마스터 데이터 + */ +export function updateFilterOptions(masterData) { + const createOptions = (items, key, value) => { + let html = ''; + items.forEach(item => { + html += ``; + }); + return html; + }; + DOM.projectFilter.innerHTML = createOptions(masterData.projects, 'project_id', 'project_name'); + DOM.workerFilter.innerHTML = createOptions(masterData.workers, 'worker_id', 'worker_name'); + DOM.taskFilter.innerHTML = createOptions(masterData.tasks, 'task_id', 'category'); +} + +/** + * 요약 카드 데이터를 렌더링합니다. + * @param {object} summary - 요약 데이터 + */ +export function renderSummary(summary) { + DOM.summaryCards.innerHTML = ` +

총 투입 시간

${(summary.totalHours || 0).toFixed(1)}h
+

참여 프로젝트

${summary.totalProjects || 0}개
+

참여 인원

${summary.totalWorkers || 0}명
+

작업 분류

${summary.totalTasks || 0}개
+ `; +} + +/** + * 집계된 데이터를 받아 테이블을 렌더링하는 범용 함수 + * @param {HTMLElement} tableBodyEl - 렌더링할 테이블의 tbody 요소 + * @param {Array} data - 집계된 데이터 배열 + * @param {function} rowRenderer - 각 행을 렌더링하는 함수 + */ +function renderTable(tableBodyEl, data, rowRenderer) { + if (!data || data.length === 0) { + tableBodyEl.innerHTML = '데이터가 없습니다'; + return; + } + tableBodyEl.innerHTML = data.map(rowRenderer).join(''); +} + +/** + * 집계된 데이터를 기반으로 모든 분석 테이블을 렌더링합니다. + * @param {object} analysis - 프로젝트/작업자/작업별 집계 데이터 + */ +export function renderAnalysisTables(analysis) { + renderTable(DOM.projectTableBody, analysis.byProject, (p, i) => ` + ${i + 1}${p.name}${p.hours}h + ${p.percentage}%${p.participants}명`); + + renderTable(DOM.workerTableBody, analysis.byWorker, (w, i) => ` + ${i + 1}${w.name}${w.hours}h + ${w.percentage}%${w.participants}개`); + + renderTable(DOM.taskTableBody, analysis.byTask, (t, i) => ` + ${i + 1}${t.name}${t.hours}h + ${t.percentage}%${t.participants}명`); +} + +/** + * 상세 내역 테이블을 렌더링합니다. + * @param {Array} detailData - 필터링된 상세 데이터 + */ +export function renderDetailTable(detailData) { + if (!detailData || detailData.length === 0) { + DOM.detailTableBody.innerHTML = '데이터가 없습니다'; + return; + } + DOM.detailTableBody.innerHTML = detailData.map((item, index) => ` + ${index + 1}${formatDate(new Date(item.date))} + ${item.project_name} + ${item.worker_name}${item.task_category} + ${item.work_details || '정상근무'} + ${item.work_hours}h + ${(item.memo || '-').substring(0, 20)}` + ).join(''); +} + +/** + * 탭 UI를 제어합니다. + * @param {string} tabName - 활성화할 탭의 이름 + */ +export function switchTab(tabName) { + DOM.tabButtons.forEach(btn => btn.classList.toggle('active', btn.dataset.tab === tabName)); + DOM.tabContents.forEach(content => content.classList.toggle('active', content.id === `${tabName}Tab`)); +} + +/** + * 사용자로부터 현재 필터 값을 가져옵니다. + * @returns {{project: string, worker: string, task: string}} + */ +export function getCurrentFilters() { + return { + project: DOM.projectFilter.value, + worker: DOM.workerFilter.value, + task: DOM.taskFilter.value, + }; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis.js b/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis.js new file mode 100644 index 0000000..fcad431 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/project-analysis.js @@ -0,0 +1,106 @@ +// /js/project-analysis.js +import { getMasterData, getAnalysisReport } from './project-analysis-api.js'; +import { + setDefaultDates, + setUIState, + updateFilterOptions, + renderSummary, + renderAnalysisTables, + renderDetailTable, + switchTab, +} from './project-analysis-ui.js'; + +// DOM 요소 참조 (이벤트 리스너 설정용) +const DOM = { + startDate: document.getElementById('startDate'), + endDate: document.getElementById('endDate'), + analyzeBtn: document.getElementById('analyzeBtn'), + quickMonthBtn: document.getElementById('quickMonth'), + quickLastMonthBtn: document.getElementById('quickLastMonth'), + // 필터 버튼은 현재 아무 기능도 하지 않으므로 주석 처리 또는 제거 가능 + // applyFilterBtn: document.getElementById('applyFilter'), + tabButtons: document.querySelectorAll('.tab-button'), +}; + +/** + * 분석 실행 버튼 클릭 이벤트 핸들러 + */ +async function handleAnalysis() { + const startDate = DOM.startDate.value; + const endDate = DOM.endDate.value; + + if (!startDate || !endDate || startDate > endDate) { + alert('올바른 분석 기간을 설정해주세요.'); + return; + } + + setUIState('loading'); + try { + const analysisResult = await getAnalysisReport(startDate, endDate); + + if (!analysisResult.summary.totalHours) { + setUIState('no-data'); + return; + } + + renderSummary(analysisResult.summary); + renderAnalysisTables(analysisResult); + renderDetailTable(analysisResult.details); + setUIState('data'); + + } catch (error) { + console.error('분석 처리 중 오류:', error); + setUIState('error'); + alert(error.message); + } +} + +/** + * 빠른 날짜 설정 버튼 핸들러 + */ +function handleQuickDate(monthType) { + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + const firstDay = monthType === 'this' ? new Date(year, month, 1) : new Date(year, month - 1, 1); + const lastDay = monthType === 'this' ? new Date(year, month + 1, 0) : new Date(year, month, 0); + + DOM.startDate.value = firstDay.toISOString().split('T')[0]; + DOM.endDate.value = lastDay.toISOString().split('T')[0]; +} + +/** + * 이벤트 리스너 설정 + */ +function setupEventListeners() { + DOM.analyzeBtn.addEventListener('click', handleAnalysis); + DOM.quickMonthBtn.addEventListener('click', () => handleQuickDate('this')); + DOM.quickLastMonthBtn.addEventListener('click', () => handleQuickDate('last')); + + DOM.tabButtons.forEach(btn => { + btn.addEventListener('click', () => switchTab(btn.dataset.tab)); + }); + + // 프론트엔드 필터링은 제거되었으므로 관련 이벤트 리스너는 주석 처리합니다. + // DOM.applyFilterBtn.addEventListener('click', ...); +} + +/** + * 페이지 초기화 함수 + */ +async function initialize() { + setDefaultDates(); + setupEventListeners(); + + try { + const masterData = await getMasterData(); + updateFilterOptions(masterData); + await handleAnalysis(); + } catch (error) { + alert(error.message); + setUIState('error'); + } +} + +// 초기화 실행 +document.addEventListener('DOMContentLoaded', initialize); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-api.js b/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-api.js new file mode 100644 index 0000000..fe3963c --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-api.js @@ -0,0 +1,91 @@ +// /js/report-viewer-api.js +import { apiGet } from './api-helper.js'; +import { getUser } from './auth.js'; + +/** + * 보고서 조회를 위한 마스터 데이터를 로드합니다. (작업 유형, 상태 등) + * 실패 시 기본값을 반환할 수 있도록 개별적으로 처리합니다. + * @returns {Promise} - 각 마스터 데이터 배열을 포함하는 객체 + */ +export async function loadMasterData() { + const masterData = { + workTypes: [], + workStatusTypes: [], + errorTypes: [] + }; + try { + // Promise.allSettled를 사용해 일부 API가 실패해도 전체가 중단되지 않도록 함 + const results = await Promise.allSettled([ + apiGet('/daily-work-reports/work-types'), + apiGet('/daily-work-reports/work-status-types'), + apiGet('/daily-work-reports/error-types') + ]); + + if (results[0].status === 'fulfilled') masterData.workTypes = results[0].value; + if (results[1].status === 'fulfilled') masterData.workStatusTypes = results[1].value; + if (results[2].status === 'fulfilled') masterData.errorTypes = results[2].value; + + return masterData; + } catch (error) { + console.error('마스터 데이터 로딩 중 심각한 오류 발생:', error); + // 최소한의 기본값이라도 반환 + return masterData; + } +} + + +/** + * 사용자의 권한을 확인하여 적절한 API 엔드포인트와 파라미터를 결정합니다. + * @param {string} selectedDate - 조회할 날짜 + * @returns {string} - 호출할 API URL + */ +function getReportApiUrl(selectedDate) { + const user = getUser(); + + // 관리자(admin, system)는 모든 데이터를 조회 + if (user && (user.role === 'admin' || user.role === 'system')) { + // 백엔드에서 GET /daily-work-reports?date=YYYY-MM-DD 요청 시 + // 권한을 확인하고 모든 데이터를 내려준다고 가정 + return `/daily-work-reports?date=${selectedDate}`; + } + + // 그 외 사용자(leader, user)는 본인이 생성한 데이터만 조회 + // 백엔드에서 동일한 엔드포인트로 요청 시, 권한을 확인하고 + // 본인 데이터만 필터링해서 내려준다고 가정 + // (만약 엔드포인트가 다르다면 이 부분을 수정해야 함) + return `/daily-work-reports?date=${selectedDate}`; +} + + +/** + * 특정 날짜의 작업 보고서 데이터를 서버에서 가져옵니다. + * @param {string} selectedDate - 조회할 날짜 (YYYY-MM-DD) + * @returns {Promise} - 작업 보고서 데이터 배열 + */ +export async function fetchReportData(selectedDate) { + if (!selectedDate) { + throw new Error('조회할 날짜가 선택되지 않았습니다.'); + } + + const apiUrl = getReportApiUrl(selectedDate); + + try { + const rawData = await apiGet(apiUrl); + + // 서버 응답이 { success: true, data: [...] } 형태일 경우와 [...] 형태일 경우 모두 처리 + if (rawData && rawData.success && Array.isArray(rawData.data)) { + return rawData.data; + } + if (Array.isArray(rawData)) { + return rawData; + } + + // 예상치 못한 형식의 응답 + console.warn('예상치 못한 형식의 API 응답:', rawData); + return []; + + } catch (error) { + console.error(`${selectedDate}의 작업 보고서 조회 실패:`, error); + throw new Error('서버에서 데이터를 가져오는 데 실패했습니다.'); + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-export.js b/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-export.js new file mode 100644 index 0000000..d6f8d67 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-export.js @@ -0,0 +1,72 @@ +// /js/report-viewer-export.js + +/** + * 주어진 데이터를 CSV 형식의 문자열로 변환합니다. + * @param {object} reportData - 요약 및 작업자별 데이터 + * @returns {string} - CSV 형식의 문자열 + */ +function convertToCsv(reportData) { + let csvContent = "\uFEFF"; // UTF-8 BOM + csvContent += "작업자명,프로젝트명,작업유형,작업상태,에러유형,작업시간,입력자\n"; + + reportData.workers.forEach(worker => { + worker.entries.forEach(entry => { + const row = [ + worker.worker_name, + entry.project_name, + entry.work_type_name, + entry.work_status_name, + entry.error_type_name, + entry.work_hours, + entry.created_by_name + ].map(field => `"${String(field || '').replace(/"/g, '""')}"`).join(','); + csvContent += row + "\n"; + }); + }); + return csvContent; +} + +/** + * 가공된 보고서 데이터를 CSV 파일로 다운로드합니다. + * @param {object|null} reportData - UI에 표시된 가공된 데이터 + */ +export function exportToExcel(reportData) { + if (!reportData || !reportData.workers || reportData.workers.length === 0) { + alert('내보낼 데이터가 없습니다.'); + return; + } + + try { + const csv = convertToCsv(reportData); + const blob = new Blob([csv], { type: 'text/csv;charset=utf-8;' }); + const link = document.createElement('a'); + const url = URL.createObjectURL(blob); + + const fileName = `작업보고서_${reportData.summary.date}.csv`; + + link.setAttribute('href', url); + link.setAttribute('download', fileName); + link.style.visibility = 'hidden'; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + URL.revokeObjectURL(url); + + } catch (error) { + console.error('Excel 내보내기 실패:', error); + alert('Excel 파일을 생성하는 중 오류가 발생했습니다.'); + } +} + +/** + * 현재 페이지의 인쇄 기능을 호출합니다. + */ +export function printReport() { + try { + window.print(); + } catch (error) { + console.error('인쇄 실패:', error); + alert('인쇄 중 오류가 발생했습니다.'); + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-ui.js b/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-ui.js new file mode 100644 index 0000000..3669196 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/report-viewer-ui.js @@ -0,0 +1,144 @@ +// /js/report-viewer-ui.js + +/** + * 데이터를 가공하여 UI에 표시하기 좋은 요약 형태로 변환합니다. + * @param {Array} rawData - 서버에서 받은 원시 데이터 배열 + * @param {string} selectedDate - 선택된 날짜 + * @returns {object} - 요약 정보와 작업자별로 그룹화된 데이터를 포함하는 객체 + */ +export function processReportData(rawData, selectedDate) { + if (!Array.isArray(rawData) || rawData.length === 0) { + return null; + } + + const workerGroups = {}; + let totalHours = 0; + let errorCount = 0; + + rawData.forEach(item => { + const workerName = item.worker_name || '미지정'; + const workHours = parseFloat(item.work_hours || 0); + totalHours += workHours; + if (item.work_status_id === 2) errorCount++; // '에러' 상태 ID가 2라고 가정 + + if (!workerGroups[workerName]) { + workerGroups[workerName] = { + worker_name: workerName, + total_hours: 0, + entries: [] + }; + } + workerGroups[workerName].total_hours += workHours; + workerGroups[workerName].entries.push(item); + }); + + return { + summary: { + date: selectedDate, + total_workers: Object.keys(workerGroups).length, + total_hours: totalHours, + total_entries: rawData.length, + error_count: errorCount + }, + workers: Object.values(workerGroups) + }; +} + +function displaySummary(summary) { + const elements = { + totalWorkers: summary.total_workers, + totalHours: `${summary.total_hours}시간`, + totalEntries: `${summary.total_entries}개`, + errorCount: `${summary.error_count}개` + }; + Object.entries(elements).forEach(([id, value]) => { + const el = document.getElementById(id); + if (el) el.textContent = value; + }); + document.getElementById('reportSummary').style.display = 'block'; +} + +function createWorkEntryElement(entry) { + const entryDiv = document.createElement('div'); + entryDiv.className = `work-entry ${entry.work_status_id === 2 ? 'error-entry' : ''}`; + entryDiv.innerHTML = ` +
+
${entry.project_name || '프로젝트 미지정'}
+
${entry.work_hours || 0}시간
+
+
+
+ 작업 유형: + ${entry.work_type_name || '-'} +
+ ${entry.work_status_id === 2 ? ` +
+ 에러 유형: + ${entry.error_type_name || '에러'} +
` : ''} +
+ `; + return entryDiv; +} + +function displayWorkersDetails(workers) { + const workersListEl = document.getElementById('workersList'); + workersListEl.innerHTML = ''; + workers.forEach(worker => { + const workerCard = document.createElement('div'); + workerCard.className = 'worker-card'; + workerCard.innerHTML = ` +
+
👤 ${worker.worker_name}
+
총 ${worker.total_hours}시간
+
+ `; + const entriesContainer = document.createElement('div'); + entriesContainer.className = 'work-entries'; + worker.entries.forEach(entry => entriesContainer.appendChild(createWorkEntryElement(entry))); + workerCard.appendChild(entriesContainer); + workersListEl.appendChild(workerCard); + }); + document.getElementById('workersReport').style.display = 'block'; +} + +const hideElement = (id) => { + const el = document.getElementById(id); + if (el) el.style.display = 'none'; +}; + +/** + * 가공된 데이터를 받아 화면 전체를 렌더링합니다. + * @param {object|null} processedData - 가공된 데이터 또는 데이터가 없을 경우 null + */ +export function renderReport(processedData) { + hideElement('loadingSpinner'); + hideElement('errorMessage'); + hideElement('noDataMessage'); + hideElement('reportSummary'); + hideElement('workersReport'); + hideElement('exportSection'); + + if (!processedData) { + document.getElementById('noDataMessage').style.display = 'block'; + return; + } + displaySummary(processedData.summary); + displayWorkersDetails(processedData.workers); + document.getElementById('exportSection').style.display = 'block'; +} + +export function showLoading(isLoading) { + document.getElementById('loadingSpinner').style.display = isLoading ? 'flex' : 'none'; + if(isLoading) { + hideElement('errorMessage'); + hideElement('noDataMessage'); + } +} + +export function showError(message) { + const errorEl = document.getElementById('errorMessage'); + errorEl.querySelector('.error-text').textContent = message; + errorEl.style.display = 'block'; + hideElement('loadingSpinner'); +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/user-dashboard.js b/deploy/tkfb-package/fastapi-bridge/static/js/user-dashboard.js new file mode 100644 index 0000000..fee8d7a --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/user-dashboard.js @@ -0,0 +1,93 @@ +// /js/user-dashboard.js +import { getUser } from './auth.js'; +import { apiGet } from './api-helper.js'; // 개선된 api-helper를 사용합니다. + +/** + * API를 호출하여 오늘의 작업 일정을 불러와 화면에 표시합니다. + */ +async function loadTodaySchedule() { + const scheduleContainer = document.getElementById('today-schedule'); + scheduleContainer.innerHTML = '

📅 오늘의 작업 일정을 불러오는 중...

'; + + try { + // 예시: /api/dashboard/today-schedule 엔드포인트에서 데이터를 가져옵니다. + // 실제 엔드포인트는 백엔드 구현에 따라 달라질 수 있습니다. + const scheduleData = await apiGet('/dashboard/today-schedule'); + + if (scheduleData && scheduleData.length > 0) { + const scheduleHtml = scheduleData.map(item => ` +
+ ${item.time} + ${item.task_name} + ${item.status_kor} +
+ `).join(''); + scheduleContainer.innerHTML = scheduleHtml; + } else { + scheduleContainer.innerHTML = '

오늘 예정된 작업이 없습니다.

'; + } + } catch (error) { + console.error('오늘의 작업 일정 로드 실패:', error); + scheduleContainer.innerHTML = '

일정 정보를 불러오는 데 실패했습니다.

'; + } +} + +/** + * API를 호출하여 현재 사용자의 작업 통계를 불러와 화면에 표시합니다. + */ +async function loadWorkStats() { + const statsContainer = document.getElementById('work-stats'); + statsContainer.innerHTML = '

📈 내 작업 현황을 불러오는 중...

'; + + try { + // 예시: /api/dashboard/my-stats 엔드포인트에서 데이터를 가져옵니다. + const statsData = await apiGet('/dashboard/my-stats'); + + if (statsData) { + const statsHtml = ` +
+ 이번 주 작업 시간: + ${statsData.weekly_hours || 0} 시간 +
+
+ 이번 달 작업 시간: + ${statsData.monthly_hours || 0} 시간 +
+
+ 완료한 작업 수: + ${statsData.completed_tasks || 0} 건 +
+ `; + statsContainer.innerHTML = statsHtml; + } else { + statsContainer.innerHTML = '

표시할 통계 정보가 없습니다.

'; + } + } catch (error) { + console.error('작업 통계 로드 실패:', error); + statsContainer.innerHTML = '

통계 정보를 불러오는 데 실패했습니다.

'; + } +} + +/** + * 환영 메시지를 사용자 이름으로 개인화합니다. + */ +function personalizeWelcome() { + // 전역 변수 대신 auth.js 모듈을 통해 사용자 정보를 가져옵니다. + const user = getUser(); + if (user) { + const welcomeEl = document.getElementById('welcome-message'); + if (welcomeEl) { + welcomeEl.textContent = `${user.name || user.username}님, 환영합니다! 오늘 하루도 안전하게 작업하세요.`; + } + } +} + +// 페이지 초기화 함수 +function initializeDashboard() { + personalizeWelcome(); + loadTodaySchedule(); + loadWorkStats(); +} + +// DOM이 로드되면 대시보드 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializeDashboard); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/work-report-api.js b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-api.js new file mode 100644 index 0000000..bb206ae --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-api.js @@ -0,0 +1,46 @@ +// /js/work-report-api.js +import { apiGet, apiPost } from './api-helper.js'; + +/** + * 작업 보고서 작성을 위해 필요한 초기 데이터(작업자, 프로젝트, 태스크)를 가져옵니다. + * Promise.all을 사용하여 병렬로 API를 호출합니다. + * @returns {Promise<{workers: Array, projects: Array, tasks: Array}>} + */ +export async function getInitialData() { + try { + const [workers, projects, tasks] = await Promise.all([ + apiGet('/workers'), + apiGet('/projects'), + apiGet('/tasks') + ]); + + // 데이터 형식 검증 + if (!Array.isArray(workers) || !Array.isArray(projects) || !Array.isArray(tasks)) { + throw new Error('서버에서 받은 데이터 형식이 올바르지 않습니다.'); + } + + // 작업자 목록은 ID 기준으로 정렬 + workers.sort((a, b) => a.worker_id - b.worker_id); + + return { workers, projects, tasks }; + } catch (error) { + console.error('초기 데이터 로딩 중 오류 발생:', error); + // 에러를 다시 던져서 호출한 쪽에서 처리할 수 있도록 함 + throw error; + } +} + +/** + * 작성된 작업 보고서 데이터를 서버에 전송합니다. + * @param {Array} reportData - 전송할 작업 보고서 데이터 배열 + * @returns {Promise} - 서버의 응답 결과 + */ +export async function createWorkReport(reportData) { + try { + const result = await apiPost('/workreports', reportData); + return result; + } catch (error) { + console.error('작업 보고서 생성 요청 실패:', error); + throw error; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/work-report-create.js b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-create.js new file mode 100644 index 0000000..d61ed79 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-create.js @@ -0,0 +1,79 @@ +// /js/work-report-create.js +import { renderCalendar } from './calendar.js'; +import { getInitialData, createWorkReport } from './work-report-api.js'; +import { initializeReportTable, getReportData } from './work-report-ui.js'; + +// 전역 상태 변수 +let selectedDate = ''; + +/** + * 날짜가 선택되었을 때 실행되는 콜백 함수. + * 초기 데이터를 로드하고 테이블을 렌더링합니다. + * @param {string} date - 선택된 날짜 (YYYY-MM-DD 형식) + */ +async function onDateSelect(date) { + selectedDate = date; + const tableBody = document.getElementById('reportBody'); + tableBody.innerHTML = '데이터를 불러오는 중...'; + + try { + const initialData = await getInitialData(); + initializeReportTable(initialData); + } catch (error) { + alert('데이터를 불러오는 데 실패했습니다: ' + error.message); + tableBody.innerHTML = '오류 발생! 데이터를 불러올 수 없습니다.'; + } +} + +/** + * '전체 등록' 버튼 클릭 시 실행되는 이벤트 핸들러. + * 폼 데이터를 서버에 전송합니다. + */ +async function handleSubmit() { + if (!selectedDate) { + alert('먼저 달력에서 날짜를 선택해주세요.'); + return; + } + + const reportData = getReportData(); + if (!reportData) { + // getReportData 내부에서 이미 alert으로 사용자에게 알림 + return; + } + + // 각 항목에 선택된 날짜 추가 + const payload = reportData.map(item => ({ ...item, date: selectedDate })); + + const submitBtn = document.getElementById('submitBtn'); + submitBtn.disabled = true; + submitBtn.textContent = '등록 중...'; + + try { + const result = await createWorkReport(payload); + if (result.success) { + alert('✅ 작업 보고서가 성공적으로 등록되었습니다!'); + // 성공 후 폼을 다시 로드하거나, 다른 페이지로 이동 등의 로직 추가 가능 + onDateSelect(selectedDate); // 현재 날짜의 폼을 다시 로드 + } else { + throw new Error(result.error || '알 수 없는 오류로 등록에 실패했습니다.'); + } + } catch (error) { + alert('❌ 등록 실패: ' + error.message); + } finally { + submitBtn.disabled = false; + submitBtn.textContent = '전체 등록'; + } +} + +/** + * 페이지 초기화 함수 + */ +function initializePage() { + renderCalendar('calendar', onDateSelect); + + const submitBtn = document.getElementById('submitBtn'); + submitBtn.addEventListener('click', handleSubmit); +} + +// DOM이 로드되면 페이지 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializePage); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/work-report-manage.js b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-manage.js new file mode 100644 index 0000000..fd73ca2 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-manage.js @@ -0,0 +1,210 @@ +import { renderCalendar } from '/js/calendar.js'; +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +ensureAuthenticated(); + +const calendarEl = document.getElementById('calendar'); +const reportBody = document.getElementById('reportBody'); +let selectedDate = ''; + +// 캘린더 렌더링 +renderCalendar('calendar', (dateStr) => { + selectedDate = dateStr; + loadReports(); +}); + +// 보고서 로딩 +async function loadReports() { + if (!selectedDate) return; + reportBody.innerHTML = '불러오는 중...'; + + try { + const [wRes, pRes, tRes, rRes] = await Promise.all([ + fetch(`${API}/workers`, { headers: getAuthHeaders() }), + fetch(`${API}/projects`, { headers: getAuthHeaders() }), + fetch(`${API}/tasks`, { headers: getAuthHeaders() }), + fetch(`${API}/workreports?start=${selectedDate}&end=${selectedDate}`, { headers: getAuthHeaders() }) + ]); + + if (![wRes, pRes, tRes, rRes].every(res => res.ok)) throw new Error('불러오기 실패'); + + const [workers, projects, tasks, reports] = await Promise.all([ + wRes.json(), pRes.json(), tRes.json(), rRes.json() + ]); + + // 배열 체크 + if (!Array.isArray(workers) || !Array.isArray(projects) || !Array.isArray(tasks) || !Array.isArray(reports)) { + throw new Error('잘못된 데이터 형식'); + } + + if (!reports.length) { + reportBody.innerHTML = '등록된 보고서가 없습니다.'; + return; + } + + const nameMap = Object.fromEntries(workers.map(w => [w.worker_id, w.worker_name])); + const projMap = Object.fromEntries(projects.map(p => [p.project_id, p.project_name])); + const taskMap = Object.fromEntries(tasks.map(t => [t.task_id, `${t.category}:${t.subcategory}`])); + + reportBody.innerHTML = ''; + reports.forEach((r, i) => { + const tr = document.createElement('tr'); + tr.innerHTML = ` + ${i + 1} + ${nameMap[r.worker_id] || r.worker_id} + + + + + + + + + `; + + // 저장 버튼 + tr.querySelector('.save-btn').onclick = async () => { + // 입력값 검증 + const projectId = tr.querySelector('[data-id="project"]').value; + const taskId = tr.querySelector('[data-id="task"]').value; + const overtimeHours = tr.querySelector('[data-id="overtime"]').value; + + if (!projectId || !taskId) { + alert('❌ 프로젝트와 작업을 선택해주세요.'); + return; + } + + // 날짜 형식 처리 - MySQL DATE 형식으로 변환 + const formatDate = (dateStr) => { + if (!dateStr) return selectedDate; + + // 이미 YYYY-MM-DD 형식인지 확인 + if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) { + return dateStr; + } + + // ISO 형식이나 다른 형식을 YYYY-MM-DD로 변환 + const date = new Date(dateStr); + if (isNaN(date.getTime())) { + return selectedDate; // 잘못된 날짜면 선택된 날짜 사용 + } + + return date.toISOString().split('T')[0]; // YYYY-MM-DD 형식으로 변환 + }; + + const payload = { + date: formatDate(r.date), // 날짜 형식 변환 + worker_id: r.worker_id, // 기존 작업자 ID 유지 + project_id: Number(projectId), + task_id: Number(taskId), + overtime_hours: overtimeHours ? Number(overtimeHours) : null, + work_details: tr.querySelector('[data-id="work_details"]').value, + memo: tr.querySelector('[data-id="memo"]').value.trim() || null + }; + + // 저장 버튼 상태 변경 (로딩 중) + const saveBtn = tr.querySelector('.save-btn'); + const originalText = saveBtn.textContent; + const originalColor = saveBtn.style.backgroundColor; + + saveBtn.textContent = '저장 중...'; + saveBtn.style.backgroundColor = '#ffc107'; + saveBtn.disabled = true; + + try { + const res = await fetch(`${API}/workreports/${r.id}`, { + method: 'PUT', + headers: { + ...getAuthHeaders(), + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }); + + const result = await res.json(); + + if (res.ok && result.success) { + // 성공 상태 표시 + saveBtn.textContent = '✅ 완료'; + saveBtn.style.backgroundColor = '#28a745'; + saveBtn.style.color = 'white'; + + setTimeout(() => { + saveBtn.textContent = originalText; + saveBtn.style.backgroundColor = originalColor; + saveBtn.style.color = ''; + saveBtn.disabled = false; + }, 2000); + + // alert 대신 조용한 알림 + console.log('저장 완료:', result); + } else { + console.error('저장 실패:', result); + alert(`❌ 저장 실패: ${result.error || result.message || '알 수 없는 오류'}`); + + // 실패 시 버튼 복원 + saveBtn.textContent = originalText; + saveBtn.style.backgroundColor = originalColor; + saveBtn.disabled = false; + } + } catch (err) { + console.error('저장 요청 에러:', err); + alert('❌ 저장 요청 실패: ' + err.message); + + // 에러 시 버튼 복원 + saveBtn.textContent = originalText; + saveBtn.style.backgroundColor = originalColor; + saveBtn.disabled = false; + } + }; + + // 삭제 버튼 + tr.querySelector('.delete-btn').onclick = async () => { + if (!confirm('정말 삭제하시겠습니까?')) return; + + try { + const res = await fetch(`${API}/workreports/${r.id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + + if (res.ok) { + tr.remove(); + // 행 번호 다시 매기기 + updateRowNumbers(); + alert('✅ 삭제 완료'); + } else { + const result = await res.json(); + alert(`❌ 삭제 실패: ${result.error || result.message || '알 수 없는 오류'}`); + } + } catch (err) { + console.error('삭제 요청 에러:', err); + alert('❌ 삭제 요청 실패: ' + err.message); + } + }; + + reportBody.appendChild(tr); + }); + } catch (err) { + console.error('데이터 로딩 에러:', err); + reportBody.innerHTML = '❌ 불러오기 실패: ' + err.message + ''; + } +} + +// 행 번호 다시 매기기 +function updateRowNumbers() { + reportBody.querySelectorAll('tr').forEach((tr, i) => { + const firstTd = tr.querySelector('td:first-child'); + if (firstTd) firstTd.textContent = i + 1; + }); +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/work-report-review.js b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-review.js new file mode 100644 index 0000000..702cf3d --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-review.js @@ -0,0 +1,1055 @@ +// js/work-report-review.js - 휴가 연동 완전판 +import { API, getAuthHeaders } from '/js/api-config.js'; + +class WorkReportReviewManager { + constructor() { + this.workers = []; + this.projects = []; + this.workTypes = []; + this.workStatusTypes = []; + this.errorTypes = []; + this.reports = []; + this.filteredReports = []; + this.attendanceData = []; // 휴가 정보 + this.reviewedReports = new Set(); // 검토완료된 보고서 ID + this.selectedReport = null; + this.init(); + } + + async init() { + try { + // 필수 DOM 요소 확인 + const requiredElements = ['reportsTableBody', 'editPanelContent', 'totalReports']; + const missingElements = requiredElements.filter(id => !document.getElementById(id)); + + if (missingElements.length > 0) { + console.error('필수 DOM 요소가 없습니다:', missingElements); + return; + } + + this.showLoading(true); + await this.loadData(); + this.setupEventListeners(); + this.setDefaultDates(); + await this.loadReports(); + this.showLoading(false); + } catch (error) { + this.showMessage('데이터 로드 중 오류가 발생했습니다.', 'error'); + console.error('초기화 오류:', error); + this.showLoading(false); + } + } + + async loadData() { + try { + // 기본 데이터 로딩 + const [workersRes, projectsRes, workTypesRes, workStatusRes, errorTypesRes] = await Promise.all([ + fetch(`${API}/workers`, { headers: getAuthHeaders() }), + fetch(`${API}/projects`, { headers: getAuthHeaders() }), + fetch(`${API}/daily-work-reports/work-types`, { headers: getAuthHeaders() }), + fetch(`${API}/daily-work-reports/work-status-types`, { headers: getAuthHeaders() }), + fetch(`${API}/daily-work-reports/error-types`, { headers: getAuthHeaders() }) + ]); + + if (!workersRes.ok || !projectsRes.ok) { + throw new Error(`API 응답 오류: Workers(${workersRes.status}), Projects(${projectsRes.status})`); + } + + this.workers = await workersRes.json(); + this.projects = await projectsRes.json(); + + // 새로운 API들 로드 (실패해도 기본값 사용) + try { + this.workTypes = workTypesRes.ok ? await workTypesRes.json() : [ + {id: 1, name: 'Base'}, {id: 2, name: 'Vessel'}, {id: 3, name: 'Piping'} + ]; + this.workStatusTypes = workStatusRes.ok ? await workStatusRes.json() : [ + {id: 1, name: '정규'}, {id: 2, name: '에러'} + ]; + this.errorTypes = errorTypesRes.ok ? await errorTypesRes.json() : [ + {id: 1, name: '설계미스'}, {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, {id: 4, name: '작업 불량'} + ]; + } catch (error) { + console.log('⚠️ 일부 API 사용 불가, 기본값 사용'); + } + + // 휴가 정보 로드 + await this.loadAttendanceData(); + + this.populateFilters(); + console.log('기본 데이터 로드 완료'); + } catch (error) { + console.error('기본 데이터 로드 오류:', error); + throw error; + } + } + + async loadAttendanceData() { + try { + const startDate = document.getElementById('startDate').value; + const endDate = document.getElementById('endDate').value; + + if (!startDate || !endDate) return; + + // 휴가 정보 API 호출 (예상 엔드포인트) + const response = await fetch(`${API}/attendance?start_date=${startDate}&end_date=${endDate}`, { + headers: getAuthHeaders() + }); + + if (response.ok) { + this.attendanceData = await response.json(); + console.log('휴가 정보 로드 완료:', this.attendanceData.length); + } else if (response.status === 404) { + console.log('⚠️ 휴가 API 없음, 더미 데이터 생성'); + this.attendanceData = this.generateDummyAttendance(); + } else { + throw new Error(`휴가 정보 로드 실패: ${response.status}`); + } + } catch (error) { + console.log('⚠️ 휴가 정보 로드 오류, 더미 데이터 사용:', error.message); + this.attendanceData = this.generateDummyAttendance(); + } + } + + generateDummyAttendance() { + const startDate = document.getElementById('startDate').value; + const endDate = document.getElementById('endDate').value; + if (!startDate || !endDate) return []; + + const dummyAttendance = []; + const start = new Date(startDate); + const end = new Date(endDate); + + // 날짜별로 작업자들의 출근 상태 생성 + for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) { + const dateStr = d.toISOString().split('T')[0]; + + this.workers.forEach(worker => { + const rand = Math.random(); + let attendanceType = 'NORMAL'; // 기본값 + + // 5% 확률로 휴가 + if (rand < 0.05) { + const types = ['HALF_DAY', 'HALF_HALF_DAY', 'EARLY_LEAVE']; + attendanceType = types[Math.floor(Math.random() * types.length)]; + } + + dummyAttendance.push({ + id: `att_${worker.worker_id}_${dateStr}`, + worker_id: worker.worker_id, + worker_name: worker.worker_name, + date: dateStr, + attendance_type: attendanceType, + expected_hours: this.getExpectedHours(attendanceType) + }); + }); + } + + return dummyAttendance; + } + + getExpectedHours(attendanceType) { + switch (attendanceType) { + case 'HALF_DAY': return 4; // 반차 + case 'HALF_HALF_DAY': return 6; // 반반차 + case 'EARLY_LEAVE': return 2; // 조퇴 + case 'NORMAL': + default: return 8; // 일반근무 + } + } + + getAttendanceTypeName(attendanceType) { + switch (attendanceType) { + case 'HALF_DAY': return '반차'; + case 'HALF_HALF_DAY': return '반반차'; + case 'EARLY_LEAVE': return '조퇴'; + case 'NORMAL': + default: return '정상근무'; + } + } + + async loadReports() { + try { + const startDate = document.getElementById('startDate').value; + const endDate = document.getElementById('endDate').value; + const workerId = document.getElementById('workerFilter').value; + const projectId = document.getElementById('projectFilter').value; + + // 필수 조건 체크 + if (!startDate || !endDate) { + this.showMessage('시작 날짜와 종료 날짜는 필수입니다.', 'error'); + return; + } + + // 휴가 정보 먼저 로드 + await this.loadAttendanceData(); + + let url = `${API}/daily-work-reports/search?`; + const params = new URLSearchParams(); + + if (startDate) params.append('start_date', startDate); + if (endDate) params.append('end_date', endDate); + if (workerId) params.append('worker_id', workerId); + if (projectId) params.append('project_id', projectId); + + // 페이지네이션 (일단 많이 가져오기) + params.append('page', '1'); + params.append('limit', '1000'); + + url += params.toString(); + + const response = await fetch(url, { headers: getAuthHeaders() }); + + if (response.status === 404 || response.status === 500) { + // API가 아직 준비되지 않은 경우 더미 데이터 사용 + this.reports = this.generateDummyData(); + console.log('⚠️ API 응답 오류, 더미 데이터 사용:', response.status); + if (response.status === 404) { + this.showMessage('⚠️ 검토 API가 준비되지 않아 더미 데이터를 표시합니다.', 'warning'); + } else { + this.showMessage('⚠️ 서버 오류로 더미 데이터를 표시합니다.', 'warning'); + } + } else if (response.ok) { + const result = await response.json(); + this.reports = result.reports || []; + console.log('검색 결과:', result.summary); + } else { + throw new Error(`보고서 로드 실패: ${response.status}`); + } + + // 근무시간 검증 추가 + this.validateWorkHours(); + + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + + } catch (error) { + console.log('⚠️ 네트워크 오류로 더미 데이터 사용:', error.message); + // 더미 데이터로 대체 + this.reports = this.generateDummyData(); + this.validateWorkHours(); + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + // 사용자에게는 부드러운 메시지 표시 + this.showMessage('💡 데모 데이터로 화면을 구성했습니다.', 'info'); + } + } + + validateWorkHours() { + // 각 보고서에 대해 근무시간 검증 + this.reports.forEach(report => { + const attendance = this.attendanceData.find(att => + att.worker_id === report.worker_id && att.date === report.report_date + ); + + if (attendance) { + const expectedHours = attendance.expected_hours; + const actualHours = this.getWorkerDailyHours(report.worker_id, report.report_date); + + report.expected_hours = expectedHours; + report.actual_hours = actualHours; + report.attendance_type = attendance.attendance_type; + report.hours_status = this.getHoursStatus(actualHours, expectedHours); + report.is_reviewed = this.reviewedReports.has(`${report.worker_id}_${report.report_date}`); + } else { + // 휴가 정보가 없으면 기본 8시간으로 가정 + const actualHours = this.getWorkerDailyHours(report.worker_id, report.report_date); + report.expected_hours = 8; + report.actual_hours = actualHours; + report.attendance_type = 'NORMAL'; + report.hours_status = this.getHoursStatus(actualHours, 8); + report.is_reviewed = this.reviewedReports.has(`${report.worker_id}_${report.report_date}`); + } + }); + } + + getWorkerDailyHours(workerId, date) { + // 해당 작업자의 특정 날짜 총 작업시간 계산 + return this.reports + .filter(r => r.worker_id === workerId && r.report_date === date) + .reduce((sum, r) => sum + (r.work_hours || 0), 0); + } + + getHoursStatus(actualHours, expectedHours) { + const tolerance = 0.5; // 30분 허용 오차 + + if (Math.abs(actualHours - expectedHours) <= tolerance) { + return 'NORMAL'; // 정상 + } else if (actualHours < expectedHours) { + return 'UNDER'; // 부족 + } else { + return 'OVER'; // 초과 + } + } + + generateDummyData() { + const today = new Date(); + const dummyData = []; + + // 더미 데이터 생성 (최근 7일) + for (let i = 0; i < 7; i++) { + const date = new Date(today); + date.setDate(date.getDate() - i); + const dateStr = date.toISOString().split('T')[0]; + + this.workers.forEach(worker => { + // 80% 확률로 보고서 생성 + if (Math.random() > 0.2) { + const numEntries = Math.floor(Math.random() * 3) + 1; // 1-3개 작업 + + for (let j = 0; j < numEntries; j++) { + const workStatus = Math.random() > 0.9 ? 2 : 1; // 10% 확률로 에러 + const workHours = Math.random() > 0.95 ? + (Math.random() * 4 + 10) : // 5% 확률로 이상 시간 (10-14시간) + (Math.random() * 6 + 2); // 정상 시간 (2-8시간) + + dummyData.push({ + id: 1000000 + i * 100 + worker.worker_id * 10 + j, // 고유 정수 ID + report_date: dateStr, + worker_id: worker.worker_id, + worker_name: worker.worker_name, + project_id: this.projects[Math.floor(Math.random() * this.projects.length)]?.project_id || 1, + project_name: this.projects[Math.floor(Math.random() * this.projects.length)]?.project_name || 'Unknown', + work_type_id: Math.floor(Math.random() * 3) + 1, + work_type_name: this.workTypes[Math.floor(Math.random() * 3)]?.name || 'Base', + work_status_id: workStatus, + work_status_name: workStatus === 2 ? '에러' : '정규', + error_type_id: workStatus === 2 ? Math.floor(Math.random() * 4) + 1 : null, + error_type_name: workStatus === 2 ? this.errorTypes[Math.floor(Math.random() * 4)]?.name : null, + work_hours: Math.round(workHours * 2) / 2, // 0.5시간 단위 + created_at: `${dateStr}T${String(Math.floor(Math.random() * 24)).padStart(2, '0')}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}:00` + }); + } + } + }); + } + + return dummyData.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); + } + + populateFilters() { + // 작업자 필터 + const workerSelect = document.getElementById('workerFilter'); + if (workerSelect) { + workerSelect.innerHTML = ''; + this.workers.forEach(worker => { + workerSelect.innerHTML += ``; + }); + } + + // 프로젝트 필터 + const projectSelect = document.getElementById('projectFilter'); + if (projectSelect) { + projectSelect.innerHTML = ''; + this.projects.forEach(project => { + projectSelect.innerHTML += ``; + }); + } + } + + setDefaultDates() { + const today = new Date(); + const weekAgo = new Date(today); + weekAgo.setDate(weekAgo.getDate() - 7); + + const startDateInput = document.getElementById('startDate'); + const endDateInput = document.getElementById('endDate'); + + if (startDateInput) startDateInput.value = weekAgo.toISOString().split('T')[0]; + if (endDateInput) endDateInput.value = today.toISOString().split('T')[0]; + } + + updateDashboard() { + // 날짜별, 작업자별로 그룹화하여 계산 + const groupedReports = this.groupReportsByWorkerAndDate(); + const groups = Object.values(groupedReports); + + const total = groups.length; + const errors = groups.filter(group => group.some(r => r.work_status_id === 2)).length; + const warnings = groups.filter(group => { + const firstReport = group[0]; + return firstReport.hours_status === 'UNDER' || firstReport.hours_status === 'OVER'; + }).length; + const reviewed = groups.filter(group => group[0].is_reviewed).length; + + document.getElementById('totalReports').textContent = total; + document.getElementById('errorReports').textContent = errors; + document.getElementById('warningReports').textContent = warnings; + document.getElementById('missingReports').textContent = total - reviewed; // 미검토 건수 + } + + updateAlertsSection() { + const alertsList = document.getElementById('alertsList'); + if (!alertsList) return; + + const alerts = []; + const groupedReports = this.groupReportsByWorkerAndDate(); + + // 각 그룹별로 알림 체크 + Object.values(groupedReports).forEach(group => { + const firstReport = group[0]; + const hasError = group.some(r => r.work_status_id === 2); + const workerName = firstReport.worker_name; + const date = firstReport.report_date; + + // 에러 발생 건 + if (hasError) { + const errorReports = group.filter(r => r.work_status_id === 2); + alerts.push({ + type: 'error', + text: `${workerName} (${date}) - 에러 ${errorReports.length}건`, + time: this.formatDate(date), + priority: 1 + }); + } + + // 시간 불일치 + if (firstReport.hours_status === 'UNDER' || firstReport.hours_status === 'OVER') { + const statusText = firstReport.hours_status === 'UNDER' ? '부족' : '초과'; + alerts.push({ + type: 'warning', + text: `${workerName} (${date}) - 시간 ${statusText} (${firstReport.actual_hours}h/${firstReport.expected_hours}h)`, + time: this.formatDate(date), + priority: 2 + }); + } + + // 검토 대기 (정상이지만 아직 검토되지 않음) + if (!firstReport.is_reviewed && firstReport.hours_status === 'NORMAL' && !hasError) { + alerts.push({ + type: 'pending', + text: `${workerName} (${date}) - 검토 대기`, + time: this.formatDate(date), + priority: 3 + }); + } + }); + + // 우선순위별 정렬 + alerts.sort((a, b) => a.priority - b.priority); + + // 알림 표시 + if (alerts.length === 0) { + alertsList.innerHTML = ` +
+
+ ✅ 모든 항목이 정상이거나 검토 완료되었습니다 +
+
+ `; + } else { + alertsList.innerHTML = alerts.map(alert => ` +
+
+
+ ${this.getAlertTypeLabel(alert.type)} + ${alert.text} +
+
${alert.time}
+
+
+ `).join(''); + } + } + + getAlertTypeLabel(type) { + switch (type) { + case 'error': return '에러'; + case 'warning': return '주의'; + case 'pending': return '대기'; + case 'missing': return '미입력'; + default: return '알림'; + } + } + + updateTable() { + const tbody = document.getElementById('reportsTableBody'); + if (!tbody) return; + + if (this.filteredReports.length === 0) { + tbody.innerHTML = ` + + + 조회된 데이터가 없습니다 + + + `; + return; + } + + // 날짜별, 작업자별로 그룹화 + const groupedReports = this.groupReportsByWorkerAndDate(); + + tbody.innerHTML = Object.entries(groupedReports).map(([key, group]) => { + const [workerId, date] = key.split('_'); + const firstReport = group[0]; + const totalHours = group.reduce((sum, r) => sum + (r.work_hours || 0), 0); + const hasError = group.some(r => r.work_status_id === 2); + const rowClass = this.getGroupRowClass(firstReport, hasError); + + return ` + + ${this.formatDate(firstReport.report_date)} + ${firstReport.worker_name} + + + ${this.getAttendanceTypeName(firstReport.attendance_type)} + + + ${firstReport.expected_hours}h + ${totalHours}h + + + ${this.getHoursStatusName(firstReport.hours_status)} + + + ${group.map(r => r.project_name).join(', ')} + ${group.map(r => r.work_type_name).join(', ')} + + ${hasError ? '에러 포함' : '정상'} + + + ${firstReport.is_reviewed ? + '검토완료' : + '검토대기' + } + + + ${!firstReport.is_reviewed && firstReport.hours_status === 'NORMAL' && !hasError ? + `` : + '-' + } + + + `; + }).join(''); + } + + groupReportsByWorkerAndDate() { + const grouped = {}; + + this.filteredReports.forEach(report => { + const key = `${report.worker_id}_${report.report_date}`; + if (!grouped[key]) { + grouped[key] = []; + } + grouped[key].push(report); + }); + + return grouped; + } + + getGroupRowClass(report, hasError) { + if (report.is_reviewed) return 'row-reviewed'; + if (hasError || report.work_status_id === 2) return 'row-error'; + if (report.hours_status === 'UNDER' || report.hours_status === 'OVER') return 'row-warning'; + return 'row-normal'; + } + + getHoursStatusName(status) { + switch (status) { + case 'NORMAL': return '정상'; + case 'UNDER': return '부족'; + case 'OVER': return '초과'; + default: return '확인필요'; + } + } + + selectWorkerDate(workerId, date) { + // 해당 작업자의 특정 날짜 보고서들을 선택 + const reports = this.filteredReports.filter(r => + r.worker_id == workerId && r.report_date === date + ); + + if (reports.length > 0) { + this.selectedReport = reports[0]; // 첫 번째 보고서를 대표로 선택 + this.selectedReport.allReports = reports; // 전체 보고서 목록 추가 + this.updateEditPanel(); + + // 테이블에서 선택 표시 + document.querySelectorAll('.data-table tr.selected').forEach(tr => { + tr.classList.remove('selected'); + }); + + // 해당 행 선택 표시 + const rows = document.querySelectorAll('.data-table tr'); + rows.forEach(row => { + if (row.onclick && row.onclick.toString().includes(`'${workerId}', '${date}'`)) { + row.classList.add('selected'); + } + }); + } + } + + async markAsReviewed(workerId, date) { + try { + const key = `${workerId}_${date}`; + + // API 호출 (준비되면) + // const response = await fetch(`${API}/daily-work-reports/review`, { + // method: 'POST', + // headers: { ...getAuthHeaders(), 'Content-Type': 'application/json' }, + // body: JSON.stringify({ worker_id: workerId, report_date: date, reviewed: true }) + // }); + + // 현재는 로컬 상태만 업데이트 + this.reviewedReports.add(key); + + // 해당 보고서들의 검토 상태 업데이트 + this.reports.forEach(report => { + if (report.worker_id == workerId && report.report_date === date) { + report.is_reviewed = true; + } + }); + + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + + this.showMessage(`✅ ${this.getWorkerName(workerId)}의 ${date} 보고서가 검토완료 처리되었습니다.`, 'success'); + + } catch (error) { + this.showMessage('❌ 검토완료 처리 중 오류가 발생했습니다.', 'error'); + console.error('검토완료 오류:', error); + } + } + + getWorkerName(workerId) { + const worker = this.workers.find(w => w.worker_id == workerId); + return worker ? worker.worker_name : `작업자${workerId}`; + } + + updateEditPanel() { + const panelContent = document.getElementById('editPanelContent'); + if (!panelContent || !this.selectedReport) return; + + const report = this.selectedReport; + const allReports = report.allReports || [report]; + + panelContent.innerHTML = ` +
+

${report.worker_name} - ${this.formatDate(report.report_date)}

+
+
+ 출근형태:
+ + ${this.getAttendanceTypeName(report.attendance_type)} + +
+
+ 시간상태:
+ + ${this.getHoursStatusName(report.hours_status)} + +
+
기대시간: ${report.expected_hours}시간
+
실제시간: ${report.actual_hours}시간
+
+
+ +
+
작업 상세 (${allReports.length}건)
+ ${allReports.map((r, index) => ` +
+
+
프로젝트: ${r.project_name}
+
작업유형: ${r.work_type_name}
+
작업시간: ${r.work_hours}시간
+
상태: ${r.work_status_name}
+ ${r.error_type_name ? `
에러유형: ${r.error_type_name}
` : ''} +
+ +
+ `).join('')} +
+ +
+ ${!report.is_reviewed && report.hours_status === 'NORMAL' && !allReports.some(r => r.work_status_id === 2) ? + `` : '' + } + +
+ `; + } + + editSingleReport(reportId) { + // 개별 보고서 수정을 위해 기존 로직 사용 + this.selectedReport = this.filteredReports.find(r => r.id == reportId); + if (this.selectedReport) { + // 기존 수정 폼 표시 + this.showEditForm(); + } + } + + showEditForm() { + const panelContent = document.getElementById('editPanelContent'); + if (!panelContent || !this.selectedReport) return; + + const report = this.selectedReport; + + panelContent.innerHTML = ` +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + + +
+ `; + + // 업무 상태 변경 시 에러 유형 표시/숨김 + const workStatusSelect = document.getElementById('editWorkStatus'); + const errorTypeGroup = document.getElementById('editErrorTypeGroup'); + + if (workStatusSelect && errorTypeGroup) { + workStatusSelect.addEventListener('change', (e) => { + if (e.target.value === '2') { + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + document.getElementById('editErrorType').value = ''; + } + }); + } + } + + async saveReport() { + if (!this.selectedReport) return; + + try { + this.showLoading(true); + + const formData = { + report_date: document.getElementById('editReportDate').value, + project_id: parseInt(document.getElementById('editProject').value), + work_type_id: parseInt(document.getElementById('editWorkType').value), + work_status_id: parseInt(document.getElementById('editWorkStatus').value), + error_type_id: document.getElementById('editErrorType').value ? + parseInt(document.getElementById('editErrorType').value) : null, + work_hours: parseFloat(document.getElementById('editWorkHours').value) + }; + + const response = await fetch(`${API}/daily-work-reports/${this.selectedReport.id}`, { + method: 'PUT', + headers: { + ...getAuthHeaders(), + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formData) + }); + + if (response.status === 404 || response.status === 500) { + if (response.status === 404) { + this.showMessage('⚠️ 수정 API가 아직 준비되지 않았습니다.', 'warning'); + } else { + this.showMessage('⚠️ 서버 오류가 발생했습니다. 더미 데이터를 수정합니다.', 'warning'); + } + // 더미 데이터 업데이트 + this.updateDummyData(formData); + } else if (response.ok) { + this.showMessage('✅ 성공적으로 수정되었습니다.', 'success'); + await this.loadReports(); + } else { + const result = await response.json(); + throw new Error(result.error || '수정 중 오류가 발생했습니다.'); + } + + this.clearSelection(); + + } catch (error) { + this.showMessage(`❌ ${error.message}`, 'error'); + console.error('수정 오류:', error); + } finally { + this.showLoading(false); + } + } + + updateDummyData(formData) { + // 더미 데이터에서 수정 + const reportIndex = this.reports.findIndex(r => r.id === this.selectedReport.id); + if (reportIndex !== -1) { + this.reports[reportIndex] = { + ...this.reports[reportIndex], + ...formData, + project_name: this.projects.find(p => p.project_id === formData.project_id)?.project_name, + work_type_name: this.workTypes.find(wt => wt.id === formData.work_type_id)?.name, + work_status_name: this.workStatusTypes.find(ws => ws.id === formData.work_status_id)?.name, + error_type_name: formData.error_type_id ? + this.errorTypes.find(et => et.id === formData.error_type_id)?.name : null + }; + + // 시간 검증 다시 실행 + this.validateWorkHours(); + + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + } + } + + async deleteReport() { + if (!this.selectedReport) return; + + if (!confirm('정말로 이 보고서를 삭제하시겠습니까?')) return; + + try { + this.showLoading(true); + + const response = await fetch(`${API}/daily-work-reports/${this.selectedReport.id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + + if (response.status === 404 || response.status === 500) { + if (response.status === 404) { + this.showMessage('⚠️ 삭제 API가 아직 준비되지 않았습니다.', 'warning'); + } else { + this.showMessage('⚠️ 서버 오류가 발생했습니다. 더미 데이터를 삭제합니다.', 'warning'); + } + // 더미 데이터에서 삭제 + this.reports = this.reports.filter(r => r.id !== this.selectedReport.id); + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + } else if (response.ok) { + this.showMessage('✅ 성공적으로 삭제되었습니다.', 'success'); + await this.loadReports(); + } else { + const result = await response.json(); + throw new Error(result.error || '삭제 중 오류가 발생했습니다.'); + } + + this.clearSelection(); + + } catch (error) { + this.showMessage(`❌ ${error.message}`, 'error'); + console.error('삭제 오류:', error); + } finally { + this.showLoading(false); + } + } + + clearSelection() { + this.selectedReport = null; + + // 테이블 선택 해제 + document.querySelectorAll('.data-table tr.selected').forEach(tr => { + tr.classList.remove('selected'); + }); + + // 패널 초기화 + const panelContent = document.getElementById('editPanelContent'); + if (panelContent) { + panelContent.innerHTML = ` +
+
📝
+
수정할 항목을 선택해주세요
+
+ `; + } + } + + setupEventListeners() { + // 필터 적용 버튼 + const applyFilterBtn = document.getElementById('applyFilter'); + if (applyFilterBtn) { + applyFilterBtn.addEventListener('click', () => { + this.loadReports(); + }); + } + + // 새로고침 버튼 + const refreshBtn = document.getElementById('refreshBtn'); + if (refreshBtn) { + refreshBtn.addEventListener('click', () => { + this.loadReports(); + }); + } + + // 내보내기 버튼 + const exportBtn = document.getElementById('exportBtn'); + if (exportBtn) { + exportBtn.addEventListener('click', () => { + this.exportData(); + }); + } + + // 엔터키로 필터 적용 + ['startDate', 'endDate', 'workerFilter', 'projectFilter'].forEach(id => { + const element = document.getElementById(id); + if (element) { + element.addEventListener('change', () => { + this.loadReports(); + }); + } + }); + } + + exportData() { + if (this.filteredReports.length === 0) { + this.showMessage('내보낼 데이터가 없습니다.', 'warning'); + return; + } + + // CSV 생성 + const headers = ['날짜', '작업자', '출근형태', '기대시간', '실제시간', '시간상태', '프로젝트', '작업유형', '상태', '검토상태']; + + // 그룹화된 데이터로 CSV 생성 + const groupedReports = this.groupReportsByWorkerAndDate(); + const csvContent = [ + headers.join(','), + ...Object.entries(groupedReports).map(([key, group]) => { + const firstReport = group[0]; + const totalHours = group.reduce((sum, r) => sum + (r.work_hours || 0), 0); + const hasError = group.some(r => r.work_status_id === 2); + + return [ + firstReport.report_date, + firstReport.worker_name, + this.getAttendanceTypeName(firstReport.attendance_type), + firstReport.expected_hours, + totalHours, + this.getHoursStatusName(firstReport.hours_status), + group.map(r => r.project_name).join('; '), + group.map(r => r.work_type_name).join('; '), + hasError ? '에러 포함' : '정상', + firstReport.is_reviewed ? '검토완료' : '검토대기' + ].join(','); + }) + ].join('\n'); + + // 파일 다운로드 + const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8;' }); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.download = `작업보고서_검토_${new Date().toISOString().split('T')[0]}.csv`; + link.click(); + + this.showMessage('✅ 데이터가 내보내졌습니다.', 'success'); + } + + formatDate(dateStr) { + return new Date(dateStr).toLocaleDateString('ko-KR'); + } + + formatTime(dateTimeStr) { + return new Date(dateTimeStr).toLocaleString('ko-KR', { + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + } + + showLoading(show) { + const overlay = document.getElementById('loadingOverlay'); + if (overlay) { + overlay.style.display = show ? 'flex' : 'none'; + } + } + + showMessage(message, type) { + const container = document.getElementById('message-container'); + if (container) { + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => { + container.innerHTML = ''; + }, 5000); + } + } + } +} + +// 전역 인스턴스 생성 +let workReportReview; + +// DOM 준비 후 초기화 +document.addEventListener('DOMContentLoaded', () => { + workReportReview = new WorkReportReviewManager(); + // 전역 접근을 위해 window에 할당 + window.workReportReview = workReportReview; +}); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/work-report-ui.js b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-ui.js new file mode 100644 index 0000000..bdc6042 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/work-report-ui.js @@ -0,0 +1,141 @@ +// /js/work-report-ui.js + +const DEFAULT_PROJECT_ID = '13'; // 나중에는 API나 설정에서 받아오는 것이 좋음 +const DEFAULT_TASK_ID = '15'; + +/** + * 주어진 데이터를 바탕으로 + ${worker.worker_name} + + + + + + + + + + + + `; + + // 이벤트 리스너 설정 + const workTypeSelect = tr.querySelector('[name="work_type"]'); + const projectSelect = tr.querySelector('[name="project_id"]'); + const taskSelect = tr.querySelector('[name="task_id"]'); + + workTypeSelect.addEventListener('change', () => { + const isDisabled = ['연차', '휴무', '유급'].includes(workTypeSelect.value); + projectSelect.disabled = isDisabled; + taskSelect.disabled = isDisabled; + if (isDisabled) { + projectSelect.value = DEFAULT_PROJECT_ID; + taskSelect.value = DEFAULT_TASK_ID; + } + }); + + tr.querySelector('.remove-btn').addEventListener('click', () => { + tr.remove(); + updateRowNumbers(tr.parentElement); + }); + + return tr; +} + +/** + * 작업 보고서 테이블을 초기화하고 데이터를 채웁니다. + * @param {{workers: Array, projects: Array, tasks: Array}} initialData - 초기 데이터 + */ +export function initializeReportTable(initialData) { + const tableBody = document.getElementById('reportBody'); + if (!tableBody) return; + + tableBody.innerHTML = ''; // 기존 내용 초기화 + const { workers, projects, tasks } = initialData; + + if (!workers || workers.length === 0) { + tableBody.innerHTML = '등록할 작업자 정보가 없습니다.'; + return; + } + + workers.forEach((worker, index) => { + const row = createReportRow(worker, projects, tasks, index); + tableBody.appendChild(row); + }); +} + +/** + * 테이블에서 폼 데이터를 추출하여 배열로 반환합니다. + * @returns {Array|null} - 추출된 데이터 배열 또는 유효성 검사 실패 시 null + */ +export function getReportData() { + const tableBody = document.getElementById('reportBody'); + const rows = tableBody.querySelectorAll('tr'); + + if (rows.length === 0 || (rows.length === 1 && rows[0].cells.length < 2)) { + alert('등록할 내용이 없습니다.'); + return null; + } + + const reportData = []; + const workerIds = new Set(); + + for (const tr of rows) { + const workerId = tr.querySelector('[name="worker_id"]').value; + if (workerIds.has(workerId)) { + alert(`오류: 작업자 '${tr.cells[1].textContent.trim()}'가 중복 등록되었습니다.`); + return null; + } + workerIds.add(workerId); + + reportData.push({ + worker_id: workerId, + project_id: tr.querySelector('[name="project_id"]').value, + task_id: tr.querySelector('[name="task_id"]').value, + overtime_hours: tr.querySelector('[name="overtime"]').value || 0, + work_details: tr.querySelector('[name="work_type"]').value, + memo: tr.querySelector('[name="memo"]').value + }); + } + + return reportData; +} \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/js/work-review.js b/deploy/tkfb-package/fastapi-bridge/static/js/work-review.js new file mode 100644 index 0000000..a656b3c --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/js/work-review.js @@ -0,0 +1,776 @@ +// work-review.js - 통합 API 설정 적용 버전 + +// ================================================================= +// 🌐 통합 API 설정 import +// ================================================================= +import { API, getAuthHeaders, apiCall } from '/js/api-config.js'; + +// 전역 변수 +let currentDate = new Date(); +let selectedDate = null; +let selectedDateData = null; +let basicData = { + workTypes: [], + workStatusTypes: [], + errorTypes: [], + projects: [] +}; + +// 현재 사용자 정보 가져오기 +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + return null; +} + +// 메시지 표시 +function showMessage(message, type = 'info') { + const container = document.getElementById('message-container'); + container.innerHTML = `
${message}
`; + + if (type !== 'loading') { + setTimeout(() => { + container.innerHTML = ''; + }, 5000); + } +} + +// 날짜 포맷팅 +function formatDate(date) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +// 월 표시 업데이트 +function updateMonthDisplay() { + const monthElement = document.getElementById('currentMonth'); + const year = currentDate.getFullYear(); + const month = currentDate.getMonth() + 1; + monthElement.textContent = `${year}년 ${month}월`; +} + +// 근무 유형 분류 +function classifyWorkType(totalHours) { + if (totalHours === 0) return { type: 'vacation', label: '휴무' }; + if (totalHours === 2) return { type: 'vacation', label: '조퇴' }; + if (totalHours === 4) return { type: 'vacation', label: '반차' }; + if (totalHours === 6) return { type: 'vacation', label: '반반차' }; + if (totalHours === 8) return { type: 'normal-work', label: '정시근무' }; + if (totalHours > 8) return { type: 'overtime', label: '잔업' }; + return { type: 'vacation', label: '기타' }; +} + +// 캘린더 렌더링 (데이터 로드 없이) +function renderCalendar() { + const calendar = document.getElementById('calendar'); + + // 기존 날짜 셀들 제거 (헤더는 유지) + const dayHeaders = calendar.querySelectorAll('.day-header'); + calendar.innerHTML = ''; + dayHeaders.forEach(header => calendar.appendChild(header)); + + const year = currentDate.getFullYear(); + const month = currentDate.getMonth(); + + // 해당 월의 첫째 날과 마지막 날 + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + + // 첫째 주의 시작 (일요일부터 시작) + const startDate = new Date(firstDay); + startDate.setDate(startDate.getDate() - firstDay.getDay()); + + // 마지막 주의 끝 + const endDate = new Date(lastDay); + endDate.setDate(endDate.getDate() + (6 - lastDay.getDay())); + + // 오늘 날짜 + const today = new Date(); + const todayStr = formatDate(today); + + // 날짜 셀 생성 + let currentCalendarDate = new Date(startDate); + + while (currentCalendarDate <= endDate) { + const dateStr = formatDate(currentCalendarDate); + const isCurrentMonth = currentCalendarDate.getMonth() === month; + const isToday = dateStr === todayStr; + const isSelected = selectedDate === dateStr; + + const dayCell = document.createElement('div'); + dayCell.className = 'day-cell'; + + if (!isCurrentMonth) { + dayCell.classList.add('other-month'); + } + + if (isToday) { + dayCell.classList.add('today'); + } + + if (isSelected) { + dayCell.classList.add('selected'); + } + + // 날짜 번호 + const dayNumber = document.createElement('div'); + dayNumber.className = 'day-number'; + dayNumber.textContent = currentCalendarDate.getDate(); + dayCell.appendChild(dayNumber); + + // 클릭 이벤트 - 현재 월의 날짜만 클릭 가능 + if (isCurrentMonth) { + dayCell.style.cursor = 'pointer'; + dayCell.addEventListener('click', () => { + selectedDate = dateStr; + loadDayData(dateStr); + renderCalendar(); // 선택 상태 업데이트를 위해 재렌더링 + }); + } + + calendar.appendChild(dayCell); + currentCalendarDate.setDate(currentCalendarDate.getDate() + 1); + } +} + +// 특정 날짜 데이터 로드 (통합 API 사용) +async function loadDayData(dateStr) { + try { + showMessage(`${dateStr} 데이터를 불러오는 중... (통합 API)`, 'loading'); + + const data = await apiCall(`${API}/daily-work-reports?date=${dateStr}`); + const dataArray = Array.isArray(data) ? data : (data.data || []); + + // 데이터 처리 + processDayData(dateStr, dataArray); + renderDayInfo(); + + document.getElementById('message-container').innerHTML = ''; + + } catch (error) { + console.error('날짜 데이터 로드 실패:', error); + showMessage('데이터를 불러올 수 없습니다: ' + error.message, 'error'); + selectedDateData = null; + renderDayInfo(); + } +} + +// 일별 데이터 처리 +function processDayData(dateStr, works) { + const dayData = { + date: dateStr, + totalHours: 0, + workers: new Set(), + reviewed: Math.random() > 0.3, // 임시: 70% 확률로 검토 완료 + details: works + }; + + works.forEach(work => { + dayData.totalHours += parseFloat(work.work_hours || 0); + dayData.workers.add(work.worker_name || work.worker_id); + }); + + const workType = classifyWorkType(dayData.totalHours); + dayData.workType = workType.type; + dayData.workLabel = workType.label; + + selectedDateData = dayData; +} + +// 선택된 날짜 정보 렌더링 +function renderDayInfo() { + const dayInfoContainer = document.getElementById('day-info-container'); + + if (!selectedDate) { + dayInfoContainer.innerHTML = ` +
+

📅 날짜를 선택하세요

+

캘린더에서 날짜를 클릭하면 해당 날짜의 작업 정보를 확인할 수 있습니다.

+
+ `; + return; + } + + if (!selectedDateData) { + dayInfoContainer.innerHTML = ` +
+

📅 ${selectedDate}

+

해당 날짜에 등록된 작업이 없습니다.

+
+ `; + return; + } + + const data = selectedDateData; + + // 작업자별 상세 정보 생성 + const workerDetailsHtml = Array.from(data.workers).map(worker => { + const workerWorks = data.details.filter(w => (w.worker_name || w.worker_id) === worker); + const workerHours = workerWorks.reduce((sum, w) => sum + parseFloat(w.work_hours || 0), 0); + + const workerWorkItemsHtml = workerWorks.map(work => ` +
+
+ ${work.project_name || '프로젝트'} - ${work.work_hours}시간
+ 작업: ${work.work_type_name || '미지정'} | 상태: ${work.work_status_name || '미지정'} + ${work.error_type_name ? `
에러: ${work.error_type_name}` : ''} +
+
+ + +
+
+ `).join(''); + + return ` +
+
+ 👤 ${worker} - 총 ${workerHours}시간 + +
+
+ ${workerWorkItemsHtml} +
+
+ `; + }).join(''); + + dayInfoContainer.innerHTML = ` +
+
+

📅 ${selectedDate} 작업 정보

+
+ + +
+
+ +
+
+ 총 작업시간: + ${data.totalHours}시간 +
+
+ 근무 유형: + ${data.workLabel} +
+
+ 작업자 수: + ${data.workers.size}명 +
+
+ 검토 상태: + + ${data.reviewed ? '✅ 검토완료' : '⏳ 미검토'} + +
+
+ +
+

👥 작업자별 상세

+ ${workerDetailsHtml} +
+
+ `; +} + +// 검토 상태 토글 +function toggleReview() { + if (selectedDateData) { + selectedDateData.reviewed = !selectedDateData.reviewed; + renderDayInfo(); + + // TODO: 실제로는 여기서 API 호출해서 DB에 저장해야 함 + console.log(`검토 상태 변경: ${selectedDate} - ${selectedDateData.reviewed ? '검토완료' : '미검토'}`); + + showMessage(`검토 상태가 ${selectedDateData.reviewed ? '완료' : '미완료'}로 변경되었습니다.`, 'success'); + } +} + +// 현재 날짜 새로고침 +function refreshCurrentDay() { + if (selectedDate) { + loadDayData(selectedDate); + } +} + +// 🛠️ 작업 항목 수정 함수 (통합 API 사용) +async function editWorkItem(workId) { + try { + console.log('수정할 작업 ID:', workId); + + if (!selectedDateData) { + showMessage('작업 데이터를 찾을 수 없습니다.', 'error'); + return; + } + + const workData = selectedDateData.details.find(work => work.id == workId); + if (!workData) { + showMessage('수정할 작업 데이터를 찾을 수 없습니다.', 'error'); + return; + } + + // 기본 데이터가 없으면 로드 + if (basicData.workTypes.length === 0) { + showMessage('기본 데이터를 불러오는 중... (통합 API)', 'loading'); + await loadBasicData(); + } + + showEditModal(workData); + document.getElementById('message-container').innerHTML = ''; + + } catch (error) { + console.error('작업 정보 조회 오류:', error); + showMessage('작업 정보를 불러올 수 없습니다: ' + error.message, 'error'); + } +} + +// 🛠️ 수정 모달 표시 (개선된 버전) +function showEditModal(workData) { + const modalHtml = ` +
+
+
+

✏️ 작업 수정

+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ `; + + document.body.insertAdjacentHTML('beforeend', modalHtml); + + // 업무 상태 변경 이벤트 + document.getElementById('editWorkStatus').addEventListener('change', (e) => { + const errorTypeGroup = document.getElementById('editErrorTypeGroup'); + if (e.target.value === '2') { + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + } + }); +} + +// 🛠️ 수정 모달 닫기 +function closeEditModal() { + const modal = document.getElementById('editModal'); + if (modal) { + modal.remove(); + } +} + +// 🛠️ 수정된 작업 저장 (통합 API 사용) +async function saveEditedWork(workId) { + try { + // 입력값 검증 + const projectId = document.getElementById('editProject').value; + const workTypeId = document.getElementById('editWorkType').value; + const workStatusId = document.getElementById('editWorkStatus').value; + const errorTypeId = document.getElementById('editErrorType').value; + const workHours = document.getElementById('editWorkHours').value; + + // 필수값 체크 + if (!projectId) { + showMessage('프로젝트를 선택해주세요.', 'error'); + document.getElementById('editProject').focus(); + return; + } + + if (!workTypeId) { + showMessage('작업 유형을 선택해주세요.', 'error'); + document.getElementById('editWorkType').focus(); + return; + } + + if (!workStatusId) { + showMessage('업무 상태를 선택해주세요.', 'error'); + document.getElementById('editWorkStatus').focus(); + return; + } + + if (!workHours || workHours <= 0) { + showMessage('작업 시간을 올바르게 입력해주세요.', 'error'); + document.getElementById('editWorkHours').focus(); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showMessage('에러 상태인 경우 에러 유형을 선택해주세요.', 'error'); + document.getElementById('editErrorType').focus(); + return; + } + + const updateData = { + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: errorTypeId ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours) + }; + + showMessage('작업을 수정하는 중... (통합 API)', 'loading'); + + // 저장 버튼 비활성화 + const saveBtn = document.querySelector('.btn-success'); + const originalText = saveBtn.textContent; + saveBtn.textContent = '저장 중...'; + saveBtn.disabled = true; + + const result = await apiCall(`${API}/daily-work-reports/my-entry/${workId}`, { + method: 'PUT', + body: JSON.stringify(updateData) + }); + + console.log('✅ 수정 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); + + closeEditModal(); + refreshCurrentDay(); // 현재 날짜 데이터 새로고침 + + } catch (error) { + console.error('❌ 수정 실패:', error); + showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); + + // 버튼 복원 + const saveBtn = document.querySelector('.btn-success'); + if (saveBtn) { + saveBtn.textContent = '💾 저장'; + saveBtn.disabled = false; + } + } +} + +// 🗑️ 작업 항목 삭제 (통합 API 사용) +async function deleteWorkItem(workId) { + // 확인 대화상자 + const confirmDelete = await showConfirmDialog( + '작업 삭제 확인', + '정말로 이 작업을 삭제하시겠습니까?', + '삭제된 작업은 복구할 수 없습니다.' + ); + + if (!confirmDelete) return; + + try { + console.log('삭제할 작업 ID:', workId); + + showMessage('작업을 삭제하는 중... (통합 API)', 'loading'); + + const result = await apiCall(`${API}/daily-work-reports/my-entry/${workId}`, { + method: 'DELETE' + }); + + console.log('✅ 삭제 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); + + refreshCurrentDay(); // 현재 날짜 데이터 새로고침 + + } catch (error) { + console.error('❌ 삭제 실패:', error); + showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 🗑️ 작업자의 모든 작업 삭제 (통합 API 사용) +async function deleteWorkerAllWorks(date, workerName) { + // 확인 대화상자 + const confirmDelete = await showConfirmDialog( + '전체 작업 삭제 확인', + `정말로 ${workerName}님의 ${date} 모든 작업을 삭제하시겠습니까?`, + '삭제된 작업들은 복구할 수 없습니다.' + ); + + if (!confirmDelete) return; + + try { + if (!selectedDateData) return; + + const workerWorks = selectedDateData.details.filter(w => (w.worker_name || w.worker_id) === workerName); + + if (workerWorks.length === 0) { + showMessage('삭제할 작업이 없습니다.', 'error'); + return; + } + + showMessage(`${workerName}님의 작업들을 삭제하는 중... (통합 API)`, 'loading'); + + // 순차적으로 삭제 (병렬 처리하면 서버 부하 발생 가능) + let successCount = 0; + let failCount = 0; + + for (const work of workerWorks) { + try { + await apiCall(`${API}/daily-work-reports/my-entry/${work.id}`, { + method: 'DELETE' + }); + successCount++; + } catch (error) { + console.error(`작업 ${work.id} 삭제 실패:`, error); + failCount++; + } + } + + if (failCount === 0) { + showMessage(`✅ ${workerName}님의 모든 작업(${successCount}개)이 삭제되었습니다!`, 'success'); + } else { + showMessage(`⚠️ ${successCount}개 삭제 완료, ${failCount}개 삭제 실패`, 'warning'); + } + + refreshCurrentDay(); // 현재 날짜 데이터 새로고침 + + } catch (error) { + console.error('❌ 전체 삭제 실패:', error); + showMessage('작업 삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 확인 대화상자 표시 +function showConfirmDialog(title, message, warning) { + return new Promise((resolve) => { + const modalHtml = ` +
+
+
+

⚠️ ${title}

+
+
+

${message}

+

${warning}

+
+ +
+
+ `; + + document.body.insertAdjacentHTML('beforeend', modalHtml); + + // 전역 함수로 resolve 함수 노출 + window.resolveConfirm = (result) => { + const modal = document.getElementById('confirmModal'); + if (modal) modal.remove(); + delete window.resolveConfirm; + resolve(result); + }; + }); +} + +// 기본 데이터 로드 (통합 API 사용) +async function loadBasicData() { + try { + console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩...'); + + const promises = [ + // 프로젝트 로드 + apiCall(`${API}/projects`) + .then(data => Array.isArray(data) ? data : (data.projects || [])) + .catch(() => []), + + // 작업 유형 로드 + apiCall(`${API}/daily-work-reports/work-types`) + .then(data => Array.isArray(data) ? data : [ + {id: 1, name: 'Base'}, + {id: 2, name: 'Vessel'}, + {id: 3, name: 'Piping'} + ]) + .catch(() => [ + {id: 1, name: 'Base'}, + {id: 2, name: 'Vessel'}, + {id: 3, name: 'Piping'} + ]), + + // 업무 상태 유형 로드 + apiCall(`${API}/daily-work-reports/work-status-types`) + .then(data => Array.isArray(data) ? data : [ + {id: 1, name: '정규'}, + {id: 2, name: '에러'} + ]) + .catch(() => [ + {id: 1, name: '정규'}, + {id: 2, name: '에러'} + ]), + + // 에러 유형 로드 + apiCall(`${API}/daily-work-reports/error-types`) + .then(data => Array.isArray(data) ? data : [ + {id: 1, name: '설계미스'}, + {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, + {id: 4, name: '작업 불량'} + ]) + .catch(() => [ + {id: 1, name: '설계미스'}, + {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, + {id: 4, name: '작업 불량'} + ]) + ]; + + const [projects, workTypes, workStatusTypes, errorTypes] = await Promise.all(promises); + + basicData = { + projects, + workTypes, + workStatusTypes, + errorTypes + }; + + console.log('✅ 기본 데이터 로드 완료 (통합 API):', basicData); + } catch (error) { + console.error('기본 데이터 로드 실패:', error); + } +} + +// 이벤트 리스너 설정 +function setupEventListeners() { + document.getElementById('prevMonth').addEventListener('click', () => { + currentDate.setMonth(currentDate.getMonth() - 1); + updateMonthDisplay(); + selectedDate = null; + selectedDateData = null; + renderCalendar(); + renderDayInfo(); + }); + + document.getElementById('nextMonth').addEventListener('click', () => { + currentDate.setMonth(currentDate.getMonth() + 1); + updateMonthDisplay(); + selectedDate = null; + selectedDateData = null; + renderCalendar(); + renderDayInfo(); + }); + + // 오늘 날짜로 이동 버튼 추가 + document.getElementById('goToday')?.addEventListener('click', () => { + const today = new Date(); + currentDate = new Date(today); + updateMonthDisplay(); + renderCalendar(); + + // 오늘 날짜 자동 선택 + const todayStr = formatDate(today); + selectedDate = todayStr; + loadDayData(todayStr); + }); +} + +// 전역 함수로 노출 +window.toggleReview = toggleReview; +window.refreshCurrentDay = refreshCurrentDay; +window.editWorkItem = editWorkItem; +window.deleteWorkItem = deleteWorkItem; +window.deleteWorkerAllWorks = deleteWorkerAllWorks; +window.closeEditModal = closeEditModal; +window.saveEditedWork = saveEditedWork; + +// 초기화 +async function init() { + try { + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + showMessage('로그인이 필요합니다.', 'error'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + updateMonthDisplay(); + setupEventListeners(); + renderCalendar(); + renderDayInfo(); + + // 기본 데이터 미리 로드 + await loadBasicData(); + + console.log('✅ 검토 페이지 초기화 완료 (통합 API 설정 적용)'); + + } catch (error) { + console.error('초기화 오류:', error); + showMessage('초기화 중 오류가 발생했습니다.', 'error'); + } +} + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', init); \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/logo 2.png b/deploy/tkfb-package/fastapi-bridge/static/logo 2.png new file mode 100644 index 0000000..5bbd962 Binary files /dev/null and b/deploy/tkfb-package/fastapi-bridge/static/logo 2.png differ diff --git a/deploy/tkfb-package/fastapi-bridge/static/logo.png b/deploy/tkfb-package/fastapi-bridge/static/logo.png new file mode 100644 index 0000000..5bbd962 Binary files /dev/null and b/deploy/tkfb-package/fastapi-bridge/static/logo.png differ diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/admin dashboard.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/admin dashboard.html new file mode 100644 index 0000000..7eff9a0 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/admin dashboard.html @@ -0,0 +1,44 @@ +
+

📄 작업 보고서

+ +
+ +
+

📊 출근/공수 관리

+ +
+ +
+

🔧 관리콘솔

+ +
+ +
+

🏭 공장 정보

+ +
+ +
+

📊 이슈 리포트

+ +
\ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/attendance-validation.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/attendance-validation.html new file mode 100644 index 0000000..d80b4db --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/attendance-validation.html @@ -0,0 +1,181 @@ + + + + + + 근태 검증 관리 시스템 | (주)테크니컬코리아 + + + + + + + + + +
+ + + ← 뒤로가기 + + + + + + +
+ + + + + +
+ +
+ +
+ +

+ 2025년 6월 +

+ +
+ + +
+

이번 달 요약

+
+
+
0
+
✅ 정상
+
+
+
0
+
⚠️ 검토필요
+
+
+
0
+
❌ 미입력
+
+
+
+ + +
+
+
+
+
+
+
+
+
+ + +
+ +
+ + +
+
+
+ 정상 +
+
+
+ 검토필요 +
+
+
+ 미입력 +
+
+ + + +
+ + +
+
+
🔄
+

날짜를 클릭해주세요

+

+ 캘린더에서 날짜를 클릭하면 해당 날짜의 작업자 검증 내역을 확인할 수 있습니다.
+ 순차 호출 방식으로 안정적이지만 약 5초의 로딩 시간이 있습니다. +

+
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/dashboard.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/dashboard.html new file mode 100644 index 0000000..eb00cad --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/dashboard.html @@ -0,0 +1,35 @@ +
+

📄 작업 보고서

+ +
+ +
+

📊 출근/공수 관리

+ +
+ +
+

관리콘솔

+ +
+ +
+

🏭 공장 정보

+ +
+ +
+

🗂 기타 관리

+

프로젝트 및 작업자 관련 기능은 추후 확장 예정

+
\ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/factory-upload.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/factory-upload.html new file mode 100644 index 0000000..d35bea0 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/factory-upload.html @@ -0,0 +1,23 @@ + + + + + 공장 지도 등록 + + + + +
+

공장 지도 등록

+
+ + + + + +
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-daily-work.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-daily-work.html new file mode 100644 index 0000000..1279963 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-daily-work.html @@ -0,0 +1,667 @@ +import React, { useState, useEffect } from 'react'; +import { Calendar, Clock, Users, AlertTriangle, CheckCircle, Edit3, Filter } from 'lucide-react'; + +const AttendanceValidationPage = () => { + const [currentDate, setCurrentDate] = useState(new Date()); + const [selectedDate, setSelectedDate] = useState(null); + const [attendanceData, setAttendanceData] = useState({}); + const [selectedDateWorkers, setSelectedDateWorkers] = useState([]); + const [filter, setFilter] = useState('all'); // all, needsReview, normal, missing + const [monthlyData, setMonthlyData] = useState({ workReports: [], dailyReports: [] }); + const [loading, setLoading] = useState(false); + const [isAuthorized, setIsAuthorized] = useState(true); // TODO: 실제 권한 체크 + + // 월이 변경될 때마다 해당 월의 전체 데이터 로드 + useEffect(() => { + loadMonthlyData(); + }, [currentDate]); + + const loadMonthlyData = async () => { + setLoading(true); + try { + const year = currentDate.getFullYear(); + const month = currentDate.getMonth() + 1; + + console.log(`${year}년 ${month}월 데이터 로딩 중...`); + const data = await fetchMonthlyData(year, month); + setMonthlyData(data); + + } catch (error) { + console.error('월간 데이터 로딩 실패:', error); + // 실패 시 빈 데이터로 설정 + setMonthlyData({ workReports: [], dailyReports: [] }); + } finally { + setLoading(false); + } + }; + + // 실제 API 호출 함수들 + const fetchWorkReports = async (date) => { + try { + const response = await fetch(`/api/workreports/date/${date}`, { + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token')}` + } + }); + return await response.json(); + } catch (error) { + console.error('WorkReports API 호출 오류:', error); + return []; + } + }; + + const fetchDailyWorkReports = async (date) => { + try { + const response = await fetch(`/api/daily-work-reports/date/${date}`, { + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token')}` + } + }); + return await response.json(); + } catch (error) { + console.error('DailyWorkReports API 호출 오류:', error); + return []; + } + }; + + // 월간 데이터 가져오기 (캘린더용) + const fetchMonthlyData = async (year, month) => { + const start = `${year}-${month.toString().padStart(2, '0')}-01`; + const end = `${year}-${month.toString().padStart(2, '0')}-31`; + + try { + const [workReports, dailyReports] = await Promise.all([ + fetch(`/api/workreports?start=${start}&end=${end}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }).then(res => res.json()), + fetch(`/api/daily-work-reports/search?start_date=${start}&end_date=${end}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }).then(res => res.json()) + ]); + + return { workReports, dailyReports: dailyReports.reports || [] }; + } catch (error) { + console.error('월간 데이터 가져오기 오류:', error); + return { workReports: [], dailyReports: [] }; + } + }; + + // 목업 데이터 (개발/테스트용) + const mockWorkReports = { + '2025-06-16': [ + { worker_id: 1, worker_name: '김철수', overtime_hours: 1, status: 'normal' }, + { worker_id: 2, worker_name: '이영희', overtime_hours: 0, status: 'half_day' }, + { worker_id: 3, worker_name: '박민수', overtime_hours: 0, status: 'vacation' }, + ], + '2025-06-17': [ + { worker_id: 1, worker_name: '김철수', overtime_hours: 2, status: 'normal' }, + { worker_id: 2, worker_name: '이영희', overtime_hours: 0, status: 'normal' }, + { worker_id: 4, worker_name: '정수현', overtime_hours: 0, status: 'early_leave' }, + ], + '2025-06-19': [ + { worker_id: 1, worker_name: '김철수', overtime_hours: 1, status: 'normal' }, + { worker_id: 2, worker_name: '이영희', overtime_hours: 0, status: 'half_day' }, + { worker_id: 3, worker_name: '박민수', overtime_hours: 0, status: 'vacation' }, + { worker_id: 4, worker_name: '정수현', overtime_hours: 0, status: 'normal' }, + ] + }; + + const mockDailyReports = { + '2025-06-16': [ + { worker_id: 1, worker_name: '김철수', work_hours: 9 }, + { worker_id: 2, worker_name: '이영희', work_hours: 4 }, + { worker_id: 3, worker_name: '박민수', work_hours: 0 }, + ], + '2025-06-17': [ + { worker_id: 1, worker_name: '김철수', work_hours: 10 }, + { worker_id: 2, worker_name: '이영희', work_hours: 8 }, + { worker_id: 4, worker_name: '정수현', work_hours: 6 }, + ], + '2025-06-19': [ + { worker_id: 1, worker_name: '김철수', work_hours: 9 }, + { worker_id: 2, worker_name: '이영희', work_hours: 4 }, + { worker_id: 3, worker_name: '박민수', work_hours: 0 }, + // 정수현 데이터 누락 - 미입력 상태 + ] + }; + + // 시간 계산 함수 + const calculateExpectedHours = (status, overtime_hours = 0) => { + const baseHours = { + 'normal': 8, + 'half_day': 4, + 'early_leave': 6, + 'quarter_day': 2, + 'vacation': 0, + 'sick_leave': 0 + }; + return (baseHours[status] || 8) + (overtime_hours || 0); + }; + + // 날짜별 상태 계산 (월간 데이터 기반) + const calculateDateStatus = (dateStr) => { + const workReports = monthlyData.workReports.filter(wr => wr.date === dateStr); + const dailyReports = monthlyData.dailyReports.filter(dr => dr.report_date === dateStr); + + if (workReports.length === 0 && dailyReports.length === 0) { + return 'no-data'; + } + + if (workReports.length === 0 || dailyReports.length === 0) { + return 'missing'; + } + + // 작업자별 시간 집계 + const dailyGrouped = dailyReports.reduce((acc, dr) => { + if (!acc[dr.worker_id]) { + acc[dr.worker_id] = 0; + } + acc[dr.worker_id] += parseFloat(dr.work_hours || 0); + return acc; + }, {}); + + // 불일치 검사 + const hasDiscrepancy = workReports.some(wr => { + const reportedHours = dailyGrouped[wr.worker_id] || 0; + const expectedHours = calculateExpectedHours('normal', wr.overtime_hours || 0); + return Math.abs(reportedHours - expectedHours) > 0; + }); + + return hasDiscrepancy ? 'needs-review' : 'normal'; + }; + + // 권한 체크 (실제 구현 시) + const checkPermission = () => { + // TODO: 실제 권한 체크 로직 + const userRole = localStorage.getItem('userRole') || 'user'; + return userRole === 'admin' || userRole === 'manager'; + }; + + // 권한 없음 UI + if (!isAuthorized) { + return ( +
+
+
🔒
+

접근 권한이 없습니다

+

이 페이지는 관리자(Admin) 이상만 접근 가능합니다.

+
+
+ ); + } + + // 로딩 중 UI + if (loading) { + return ( +
+
+
+
+ 데이터를 불러오는 중... +
+
+
+ ); + } + + // 캘린더 생성 + const generateCalendar = () => { + const year = currentDate.getFullYear(); + const month = currentDate.getMonth(); + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + const startDate = new Date(firstDay); + startDate.setDate(startDate.getDate() - firstDay.getDay()); + + const calendar = []; + const current = new Date(startDate); + + for (let week = 0; week < 6; week++) { + const weekDays = []; + for (let day = 0; day < 7; day++) { + const dateStr = current.toISOString().split('T')[0]; + const isCurrentMonth = current.getMonth() === month; + const status = isCurrentMonth ? calculateDateStatus(dateStr) : 'no-data'; + + weekDays.push({ + date: new Date(current), + dateStr, + isCurrentMonth, + status + }); + current.setDate(current.getDate() + 1); + } + calendar.push(weekDays); + } + return calendar; + }; + + // 실제 API를 사용한 작업자 데이터 조합 + const getWorkersForDate = async (dateStr) => { + try { + // 실제 API 호출 + const [workReports, dailyReports] = await Promise.all([ + fetchWorkReports(dateStr), + fetchDailyWorkReports(dateStr) + ]); + + console.log('API 응답:', { workReports, dailyReports }); + + const workerMap = new Map(); + + // WorkReports 데이터 추가 (생산지원팀 입력) + workReports.forEach(wr => { + workerMap.set(wr.worker_id, { + worker_id: wr.worker_id, + worker_name: wr.worker_name, + overtime_hours: wr.overtime_hours || 0, + status: 'normal', // 실제 테이블 구조에 맞게 수정 필요 + expected_hours: calculateExpectedHours('normal', wr.overtime_hours), + reported_hours: null, + hasWorkReport: true, + hasDailyReport: false + }); + }); + + // DailyReports 데이터 추가 (그룹장 입력) - 작업자별 총 시간 집계 + const dailyGrouped = dailyReports.reduce((acc, dr) => { + if (!acc[dr.worker_id]) { + acc[dr.worker_id] = { + worker_id: dr.worker_id, + worker_name: dr.worker_name, + total_work_hours: 0 + }; + } + acc[dr.worker_id].total_work_hours += parseFloat(dr.work_hours || 0); + return acc; + }, {}); + + Object.values(dailyGrouped).forEach(dr => { + if (workerMap.has(dr.worker_id)) { + const worker = workerMap.get(dr.worker_id); + worker.reported_hours = dr.total_work_hours; + worker.hasDailyReport = true; + } else { + workerMap.set(dr.worker_id, { + worker_id: dr.worker_id, + worker_name: dr.worker_name, + overtime_hours: 0, + status: 'normal', + expected_hours: 8, + reported_hours: dr.total_work_hours, + hasWorkReport: false, + hasDailyReport: true + }); + } + }); + + return Array.from(workerMap.values()).map(worker => ({ + ...worker, + difference: worker.reported_hours !== null ? worker.reported_hours - worker.expected_hours : -worker.expected_hours, + validationStatus: getValidationStatus(worker) + })); + + } catch (error) { + console.error('데이터 조합 오류:', error); + // 오류 시 목업 데이터 사용 + return getWorkersForDateMock(dateStr); + } + }; + + // 목업 데이터용 함수 (개발/테스트) + const getWorkersForDateMock = (dateStr) => { + const workReports = mockWorkReports[dateStr] || []; + const dailyReports = mockDailyReports[dateStr] || []; + + const workerMap = new Map(); + + // WorkReports 데이터 추가 + workReports.forEach(wr => { + workerMap.set(wr.worker_id, { + worker_id: wr.worker_id, + worker_name: wr.worker_name, + overtime_hours: wr.overtime_hours, + status: wr.status, + expected_hours: calculateExpectedHours(wr.status, wr.overtime_hours), + reported_hours: null, + hasWorkReport: true, + hasDailyReport: false + }); + }); + + // DailyReports 데이터 추가 + dailyReports.forEach(dr => { + if (workerMap.has(dr.worker_id)) { + const worker = workerMap.get(dr.worker_id); + worker.reported_hours = dr.work_hours; + worker.hasDailyReport = true; + } else { + workerMap.set(dr.worker_id, { + worker_id: dr.worker_id, + worker_name: dr.worker_name, + overtime_hours: 0, + status: 'normal', + expected_hours: 8, + reported_hours: dr.work_hours, + hasWorkReport: false, + hasDailyReport: true + }); + } + }); + + return Array.from(workerMap.values()).map(worker => ({ + ...worker, + difference: worker.reported_hours !== null ? worker.reported_hours - worker.expected_hours : -worker.expected_hours, + validationStatus: getValidationStatus(worker) + })); + }; + + const getValidationStatus = (worker) => { + if (!worker.hasWorkReport || !worker.hasDailyReport) return 'missing'; + if (Math.abs(worker.difference) > 0) return 'needs-review'; + return 'normal'; + }; + + // 작업자 수정 핸들러 + const handleEditWorker = (worker) => { + // TODO: 수정 모달 또는 인라인 편집 구현 + const newHours = prompt( + `${worker.worker_name}의 근무시간을 수정하세요.\n현재: ${worker.reported_hours || 0}시간`, + worker.reported_hours || 0 + ); + + if (newHours !== null && !isNaN(newHours)) { + updateWorkerHours(worker.worker_id, parseFloat(newHours)); + } + }; + + // 작업자 시간 업데이트 (실제 API 호출) + const updateWorkerHours = async (workerId, newHours) => { + try { + // TODO: 실제 수정 API 호출 + console.log(`작업자 ${workerId}의 시간을 ${newHours}시간으로 수정`); + + // 임시: 로컬 상태 업데이트 + setSelectedDateWorkers(prev => + prev.map(worker => + worker.worker_id === workerId + ? { + ...worker, + reported_hours: newHours, + difference: newHours - worker.expected_hours, + validationStatus: Math.abs(newHours - worker.expected_hours) > 0 ? 'needs-review' : 'normal' + } + : worker + ) + ); + + alert('수정이 완료되었습니다.'); + + } catch (error) { + console.error('수정 실패:', error); + alert('수정 중 오류가 발생했습니다.'); + } + }; + + // 날짜 클릭 핸들러 (실제 API 호출) + const handleDateClick = async (dateInfo) => { + if (!dateInfo.isCurrentMonth) return; + + setSelectedDate(dateInfo.dateStr); + + try { + // 로딩 상태 표시 + setSelectedDateWorkers([]); + + // 실제 API에서 데이터 가져오기 + const workers = await getWorkersForDate(dateInfo.dateStr); + setSelectedDateWorkers(workers); + + } catch (error) { + console.error('날짜별 데이터 로딩 오류:', error); + // 오류 시 목업 데이터 사용 + const workers = getWorkersForDateMock(dateInfo.dateStr); + setSelectedDateWorkers(workers); + } + }; + + // 필터링된 작업자 목록 + const filteredWorkers = selectedDateWorkers.filter(worker => { + if (filter === 'all') return true; + if (filter === 'needsReview') return worker.validationStatus === 'needs-review'; + if (filter === 'normal') return worker.validationStatus === 'normal'; + if (filter === 'missing') return worker.validationStatus === 'missing'; + return true; + }); + + // 상태별 아이콘 및 색상 + const getStatusIcon = (status) => { + switch (status) { + case 'normal': return ; + case 'needs-review': return ; + case 'missing': return ; + default: return null; + } + }; + + const getStatusColor = (status) => { + switch (status) { + case 'normal': return 'bg-green-100 text-green-800'; + case 'needs-review': return 'bg-yellow-100 text-yellow-800'; + case 'missing': return 'bg-red-100 text-red-800'; + default: return 'bg-gray-100 text-gray-800'; + } + }; + + const calendar = generateCalendar(); + const monthNames = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월']; + const dayNames = ['일', '월', '화', '수', '목', '금', '토']; + + return ( +
+
+ {/* 헤더 */} +
+
+ +

근태 검증 관리

+
+
+ Admin 전용 페이지 +
+
+ +
+ {/* 캘린더 섹션 */} +
+
+ {/* 캘린더 헤더 */} +
+ +

+ {currentDate.getFullYear()}년 {monthNames[currentDate.getMonth()]} +

+ +
+ + {/* 월간 요약 정보 */} +
+
+
+
+ {calendar.flat().filter(d => d.isCurrentMonth && d.status === 'normal').length} +
+
정상
+
+
+
+ {calendar.flat().filter(d => d.isCurrentMonth && d.status === 'needs-review').length} +
+
검토필요
+
+
+
+ {calendar.flat().filter(d => d.isCurrentMonth && d.status === 'missing').length} +
+
미입력
+
+
+
+ + {/* 요일 헤더 */} +
+ {dayNames.map(day => ( +
+ {day} +
+ ))} +
+ + {/* 캘린더 본체 */} +
+ {calendar.flat().map((dateInfo, index) => ( + + ))} +
+ + {/* 범례 */} +
+
+
+ 정상 +
+
+
+ 검토필요 +
+
+
+ 미입력 +
+
+
+
+ + {/* 작업자 리스트 섹션 */} +
+ {selectedDate ? ( +
+
+

+ 📅 {selectedDate} +

+ +
+ +
+ {filteredWorkers.map(worker => ( +
+
+ {worker.worker_name} + {getStatusIcon(worker.validationStatus)} +
+ +
+
+ 그룹장 입력: + + {worker.reported_hours !== null ? `${worker.reported_hours}시간` : '미입력'} + +
+
+ 시스템 계산: + {worker.expected_hours}시간 +
+ {worker.difference !== 0 && ( +
+ 차이: + 0 ? 'text-red-600' : 'text-blue-600'}`}> + {worker.difference > 0 ? '+' : ''}{worker.difference}시간 + +
+ )} +
+ + {worker.validationStatus === 'needs-review' && ( + + )} +
+ ))} +
+ + {filteredWorkers.length === 0 && ( +
+ 해당 조건의 작업자가 없습니다. +
+ )} +
+ ) : ( +
+ +

날짜를 선택하면

+

작업자 검증 내역을 확인할 수 있습니다.

+
+ )} +
+
+
+
+ ); +}; + +export default AttendanceValidationPage; \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-issue.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-issue.html new file mode 100644 index 0000000..5fe1e95 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-issue.html @@ -0,0 +1,62 @@ + + + + + + 이슈 유형 관리 | (주)테크니컬코리아 + + + + + + +
+ + +
+ + +
+ + +
+

새 이슈 유형 등록

+
+
+ + + +
+
+
+ +
+

등록된 이슈 유형

+
+ + + + + + + + + + + + +
ID카테고리서브카테고리작업
불러오는 중...
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-pipespec.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-pipespec.html new file mode 100644 index 0000000..09c763d --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-pipespec.html @@ -0,0 +1,62 @@ + + + + + + 파이프 스펙 관리 | (주)테크니컬코리아 + + + + + + +
+ + +
+ + +
+ + +
+

새 파이프 스펙 등록

+
+
+ + + + +
+
+
+ +
+

등록된 파이프 스펙

+
+ + + + + + + + + + + +
ID스펙작업
불러오는 중...
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-project.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-project.html new file mode 100644 index 0000000..751424d --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-project.html @@ -0,0 +1,76 @@ + + + + + + 프로젝트 관리 | (주)테크니컬코리아 + + + + + + +
+ + +
+ + +
+ + +
+

새 프로젝트 등록

+
+
+ + +
+
+ + +
+
+ + + + +
+
+
+ +
+

등록된 프로젝트

+
+ + + + + + + + + + + + + + + + + +
ID공사번호프로젝트명계약일납기일납품방식현장PM작업
불러오는 중...
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-task.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-task.html new file mode 100644 index 0000000..f69d19f --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-task.html @@ -0,0 +1,68 @@ + + + + + + 작업 항목 관리 | (주)테크니컬코리아 + + + + + + +
+ + +
+ + +
+ + +
+

새 작업 항목 등록

+
+
+ + +
+
+ + + +
+
+
+ +
+

등록된 작업 항목

+
+ + + + + + + + + + + + + + +
ID카테고리서브카테고리작업명설명작업
불러오는 중...
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-user.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-user.html new file mode 100644 index 0000000..54c9998 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-user.html @@ -0,0 +1,106 @@ + + + + + + 👤 사용자 관리 | (주)테크니컬코리아 + + + + + +
+ + +
+ + +
+ + + +
+

🔐 내 비밀번호 변경

+
+
+ + + + +
+
+
+ + +
+

새 사용자 등록

+
+
+ + + +
+
+ + + +
+
+
+ + + + + +
+

등록된 사용자

+
+ + + + + + + + + + + + + + +
ID아이디이름권한연결 작업자작업
불러오는 중...
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-worker.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-worker.html new file mode 100644 index 0000000..b57e65a --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/manage-worker.html @@ -0,0 +1,62 @@ + + + + + + 작업자 관리 | (주)테크니컬코리아 + + + + + + +
+ + +
+ + +
+ + +
+

새 작업자 등록

+
+
+ + + +
+
+
+ +
+

등록된 작업자

+
+ + + + + + + + + + + + +
ID이름직책작업
불러오는 중...
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/admin/work-review.html b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/work-review.html new file mode 100644 index 0000000..bc12a16 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/admin/work-review.html @@ -0,0 +1,109 @@ + + + + + + 작업 검토 | (주)테크니컬코리아 + + + + + +
+ + + +
+
+ + + ← 뒤로가기 + + + + + + +
+ + +
+
+ +
2025년 6월
+ +
+
+ +
+
+ + +
+

📖 사용법

+
+
+
👆
+
+ 날짜 클릭
+ 캘린더에서 날짜를 클릭하면 해당 날짜의 작업 정보를 확인할 수 있습니다. +
+
+
+
✏️
+
+ 작업 수정
+ 각 작업 항목의 수정 버튼을 클릭하여 프로젝트, 작업 유형, 시간 등을 수정할 수 있습니다. +
+
+
+
🗑️
+
+ 작업 삭제
+ 개별 작업 또는 작업자의 모든 작업을 삭제할 수 있습니다. +
+
+
+
+
+ 검토 완료
+ 작업 검토가 완료되면 검토 완료 버튼을 클릭하여 상태를 변경할 수 있습니다. +
+
+
+
+ + +
+

📅 캘린더

+
+ +
+
+
+
+
+
+
+ +
+
+ + +
+
+ +
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/analysis/daily_work_analysis.html b/deploy/tkfb-package/fastapi-bridge/static/pages/analysis/daily_work_analysis.html new file mode 100644 index 0000000..91471be --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/analysis/daily_work_analysis.html @@ -0,0 +1,890 @@ + + + + + + 작업 현황 분석 + + + + +
+
+

📊 일일 작업 현황 분석

+

실시간 작업 현황과 주요 지표를 확인하세요

+
+ + + ~ + + + + + + +
+
+ +
+
+ +
+
+
0
+
총 작업시간
+
+0%
+
+
+
0
+
보고서 건수
+
+0%
+
+
+
0
+
진행 프로젝트
+
+0%
+
+
+
0%
+
에러율
+
+0%
+
+
+ +
+
+
📈 일별 작업시간 추이
+
+ +
+
+
+
👥 작업자별 작업량
+
+ +
+
+
+ +
+
+
🏗️ 프로젝트별 투입시간
+
+ +
+
+
+
⚙️ 작업 유형별 분포
+
+ +
+
+
+ +
+
🔍 최근 작업 현황
+ + + + + + + + + + + + + + + + +
날짜작업자프로젝트작업유형작업시간상태
데이터를 불러오는 중...
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/12.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/12.html new file mode 100644 index 0000000..3c6fe96 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/12.html @@ -0,0 +1,497 @@ + + + + + + Rate Limit 관리 + + + +
+
+

+ + + + Rate Limit 관리 +

+
권한 레벨: -
+
+ +
+ + + + +
+

+ + + + 현재 상태 +

+ +
+
+
클라이언트 IP
+
로딩 중...
+
+
+
API 제한
+
로딩 중...
+
+
+
로그인 제한
+
로딩 중...
+
+
+
시간 윈도우
+
15분
+
+
+
+ + +
+
+ + + + + + + +
+
+ + +
+ + +
+

💡 사용 가이드

+
    +
  • 초기화: 현재 IP의 요청 카운터를 0으로 리셋
  • +
  • 제한 해제: 지정된 시간 동안 Rate Limit 완전 비활성화
  • +
  • 권한 요구사항: 레벨 4-5 사용자만 접근 가능
  • +
  • 자동 해제: 임시 해제는 설정된 시간 후 자동으로 복구됨
  • +
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/123.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/123.html new file mode 100644 index 0000000..9820306 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/123.html @@ -0,0 +1,1044 @@ + + + + + + 📊 작업 분석 대시보드 | 개선된 버전 + + + + + + +
+ + + +
+
+ + + ← 뒤로가기 + + +
+

📊 작업 분석 대시보드

+

총 시간 분류 & 프로젝트별 상세 분석

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+

⏱️ 총 시간 분류

+
+
데이터를 불러오는 중...
+
+
+ + +
+

📋 프로젝트 분류

+
+
데이터를 불러오는 중...
+
+
+ + +
+

📈 일별 작업시간 추이

+
+
데이터를 불러오는 중...
+
+
+ + +
+

🔍 프로젝트별 작업 유형 & 에러 분석

+
+
데이터를 불러오는 중...
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/123456.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/123456.html new file mode 100644 index 0000000..7e194a8 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/123456.html @@ -0,0 +1,1019 @@ + + + + + + 📊 작업 분석 대시보드 | 개선된 버전 + + + + + + +
+ + + +
+
+ + + ← 뒤로가기 + + +
+

📊 작업 분석 대시보드

+

총 시간 분류 & 프로젝트별 상세 분석

+
+ +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+

⏱️ 총 시간 분류

+
+
데이터를 불러오는 중...
+
+
+ + +
+

📋 프로젝트 분류

+
+
데이터를 불러오는 중...
+
+
+ + +
+

📈 일별 작업시간 추이

+
+
데이터를 불러오는 중...
+
+
+ + +
+

🔍 프로젝트별 작업 유형 & 에러 분석

+
+
데이터를 불러오는 중...
+
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/attendance.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/attendance.html new file mode 100644 index 0000000..e906977 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/attendance.html @@ -0,0 +1,87 @@ + + + + + + 출근부 조회 | (주)테크니컬코리아 + + + + + + + +
+ + +
+ + +
+ + +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+

조회할 연도와 월을 선택하세요.

+
+
+
+
+ + +
+

범례

+
+ + 잔업 + + + 연차/반차 + + + 유급 + + + 휴무 + +
+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/daily-work-report-viewer.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/daily-work-report-viewer.html new file mode 100644 index 0000000..c125528 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/daily-work-report-viewer.html @@ -0,0 +1,100 @@ + + + + + + 일일 작업보고서 조회 + + + +
+ + +
+
+ + + + +
+
+ + + + + + + + + + + + +
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/daily-work-report.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/daily-work-report.html new file mode 100644 index 0000000..a8e0156 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/daily-work-report.html @@ -0,0 +1,1062 @@ + + + + + + 일일 작업보고서 작성 | (주)테크니컬코리아 + + + + + + +
+ + + +
+
+ + + ← 뒤로가기 + + + + + +
+ + +
+
+
1
+
작업 날짜 선택
+
+
+ +
+ +
+ + +
+
+
2
+
작업자 선택
+
+
+ +
+ +
+ + +
+
+
3
+
작업 내역 입력
+
+ + +
+ 총 작업시간: 0시간 +
+ + +
+ +
+ + + + + + +
+ + + + + +
+

📖 사용 가이드

+
+
+
📅
+ 1단계
+ 작업 날짜 선택 +
+
+
👤
+ 2단계
+ 작업자 선택 (터치) +
+
+
🔧
+ 3단계
+ 작업 내역 입력 +
+
+
💾
+ 완료
+ 저장하여 마무리 +
+
+
✏️
+ 관리
+ 입력한 작업 수정/삭제 +
+
+
+
+
+
+ + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/factory-upload.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/factory-upload.html new file mode 100644 index 0000000..66a27fb --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/factory-upload.html @@ -0,0 +1,47 @@ + + + + + + 공장 정보 등록 | (주)테크니컬코리아 + + + + + + +
+ + +
+ + +
+
+

공장 정보 등록

+
+ + + + + + + + + + + +
+ + +
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/factory-view.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/factory-view.html new file mode 100644 index 0000000..cdbbae0 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/factory-view.html @@ -0,0 +1,59 @@ + + + + + + 공장 정보 | (주)테크니컬코리아 + + + + + +
+ + +
+ + +
+
+ +
+ 공장 정보를 불러오는 중... +
+ + + + + + +
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/management-dashboard.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/management-dashboard.html new file mode 100644 index 0000000..a85de2f --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/management-dashboard.html @@ -0,0 +1,215 @@ + + + + + + 관리자 대시보드 - 일일 작업 입력 현황 | (주)테크니컬코리아 + + + + + + +
+ + + +
+
+ + + ← 뒤로가기 + + + + + + + + + +
+ + +
+
+

📅 조회 날짜 선택

+ +
+
+ + +
+
+ + + + + + + + + + + + + + + + + +
+

📖 사용 가이드

+
+
+
📅
+ 날짜 선택
+ 확인하고 싶은 날짜를 선택하세요 +
+
+
📊
+ 현황 확인
+ 팀 전체의 입력 현황을 확인하세요 +
+
+
🔍
+ 필터링
+ 미입력자만 따로 확인할 수 있습니다 +
+
+
📥
+ 내보내기
+ 엑셀로 데이터를 다운로드하세요 +
+
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/project-analysis.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/project-analysis.html new file mode 100644 index 0000000..93272af --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/project-analysis.html @@ -0,0 +1,304 @@ + + + + + + 프로젝트 투입 분석 | (주)테크니컬코리아 + + + + + + + + +
+ + +
+ + +
+ + +
+

📅 분석 기간 설정

+
+ + + + + + + + + +
+
+ + +
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/work-report-review.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/work-report-review.html new file mode 100644 index 0000000..9b2b824 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/work-report-review.html @@ -0,0 +1,723 @@ + + + + + + 작업보고서 검토 | (주)테크니컬코리아 + + + + + + + + +
+ + +
+ + +
+ + + +
+ +
+ +
+ +
+
+
-
+
총 보고서
+
+
+
-
+
에러 발생
+
+
+
-
+
주의 필요
+
+
+
-
+
미검토
+
+
+ + +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+ + +
+
+ 🚨 주의 필요 항목 +
+
+ +
+
+ + +
+
+
작업보고서 목록
+
+ + +
+
+
+ + + + + + + + + + + + + + + + + + + +
날짜작업자출근형태기대시간실제시간시간상태프로젝트작업유형상태검토상태액션
+
+
+
+ + +
+
+
빠른 수정
+
항목을 선택하여 수정하세요
+
+
+
+
📝
+
수정할 항목을 선택해주세요
+
+
+
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/common/work-report-validation.html b/deploy/tkfb-package/fastapi-bridge/static/pages/common/work-report-validation.html new file mode 100644 index 0000000..9ee59c7 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/common/work-report-validation.html @@ -0,0 +1,733 @@ + + + + + + 작업 보고서 입력 검증 + + + +
+
+

📊 작업 보고서 입력 검증

+

일일 작업 보고서의 데이터 품질을 확인하고 누락된 정보를 찾아보세요

+
+ +
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+ + + + + +
+ +
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/admin.html b/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/admin.html new file mode 100644 index 0000000..fb4e61f --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/admin.html @@ -0,0 +1,34 @@ + + + + + + 관리자 포털 | (주)테크니컬코리아 + + + + + + + +
+ + + +
+ + +
+
페이지를 불러오는 중...
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/group-leader.html b/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/group-leader.html new file mode 100644 index 0000000..5e5c9b7 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/group-leader.html @@ -0,0 +1,564 @@ + + + + + + 작업 현황판 | (주)테크니컬코리아 + + + + + +
+ + + + +
+
+
+
+
+

📊 작업 현황판

+

실시간 팀 현황 및 작업 모니터링

+
+
+
+ + 활성 상태 +
+
+
+
+ +
+ +
+

⚡ 빠른 메뉴

+
+
+
👥
+
+

팀 작업 관리

+

팀원 작업 현황 확인 및 관리

+
+
+
+ +
+
📊
+
+

관리 대시보드

+

종합 관리 및 모니터링 시스템

+
+
+
+ +
+
+
+ + +
+ +
+
+

👥 팀 현황

+
🔄
+
+
+
+
8
+
총 팀원
+
+
+
7
+
출근
+
+
+
1
+
결근
+
+
+
+
+ 김작업 + 출근 +
+
+ 이현장 + 출근 +
+
+ 박휴가 + 휴가 +
+
+
+ + +
+
+

📢 공지사항

+
+
+
+
안전 교육 실시 안내
+
2025.06.10
+
+
+
하절기 근무시간 변경
+
2025.06.05
+
+
+
+ + +
+
+

📅 근무 일지

+
준비중
+
+
+
🚧
+

근무 일지 기능을 준비중입니다.

+
+
+ + +
+
+

📈 통계

+
준비중
+
+
+
📊
+

통계 기능을 준비중입니다.

+
+
+
+
+
+
+
+ + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/user.html b/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/user.html new file mode 100644 index 0000000..0c14efd --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/dashboard/user.html @@ -0,0 +1,70 @@ + + + + + + 개인 페이지 | (주)테크니컬코리아 + + + + + + + +
+ + + +
+ + +
+
+

👷 내 작업 정보

+

환영합니다. 개인 작업 포털입니다.

+
+ +
+
+

📅 오늘의 작업 일정

+
+

작업 일정을 불러오는 중...

+
+
+ +
+

🔧 빠른 메뉴

+ +
+ +
+

📈 내 작업 현황

+
+

통계를 불러오는 중...

+
+
+
+
+
+
+ + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/issue-reports/daily-issue-report.html b/deploy/tkfb-package/fastapi-bridge/static/pages/issue-reports/daily-issue-report.html new file mode 100644 index 0000000..8d54856 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/issue-reports/daily-issue-report.html @@ -0,0 +1,76 @@ + + + + + + 일일 이슈 보고 | (주)테크니컬코리아 + + + + + + +
+ + +
+ + +
+ + +
+
+
+ + +
+ +
+ + +
+ +
+ +
+ 날짜를 먼저 선택하세요. +
+
+ +
+ + +
+ +
+ +
+ + ~ + +
+
+ +
+ + +
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/profile/change-password.html b/deploy/tkfb-package/fastapi-bridge/static/pages/profile/change-password.html new file mode 100644 index 0000000..6fbd273 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/profile/change-password.html @@ -0,0 +1,391 @@ + + + + + + 🔐 비밀번호 변경 | (주)테크니컬코리아 + + + + + + +
+ + +
+
+

🔐 비밀번호 변경

+

계정 보안을 위해 정기적으로 비밀번호를 변경해주세요

+
+ +
+
+

+ 🔑 + 새 비밀번호 설정 +

+
+ +
+ +
+ + +
+

+ ℹ️ + 비밀번호 요구사항 +

+
    +
  • 최소 6자 이상 입력해주세요
  • +
  • 영문 대/소문자, 숫자, 특수문자를 조합하면 더 안전합니다
  • +
  • 개인정보나 쉬운 단어는 피해주세요
  • +
  • 이전 비밀번호와 다르게 설정해주세요
  • +
+
+ + +
+
+ +
+ + +
+
+ +
+ +
+ + +
+
+
+ +
+ +
+ + +
+
+ +
+ + +
+
+ + +
+
+
+
+ + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/profile/my-profile.html b/deploy/tkfb-package/fastapi-bridge/static/pages/profile/my-profile.html new file mode 100644 index 0000000..dc7e6fd --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/profile/my-profile.html @@ -0,0 +1,317 @@ + + + + + + 👤 내 프로필 | (주)테크니컬코리아 + + + + + + +
+ + +
+
+
👤
+

사용자

+

역할

+
+ +
+ +
+

+ 📋 + 기본 정보 +

+
+
+ 사용자 ID + - +
+
+ 사용자명 + - +
+
+ 이름 + - +
+
+ 권한 레벨 + - +
+
+ 작업자 ID + - +
+
+ 가입일 + - +
+
+
+ + +
+

+ 📊 + 활동 정보 +

+
+
+ 마지막 로그인 + - +
+
+ 이메일 + - +
+
+ + +
+
+ - + 작업 보고서 +
+
+ - + 이번 달 활동 +
+
+ - + 팀 기여도 +
+
+
+ + +
+

+ + 빠른 작업 +

+
+ + 🔐 + 비밀번호 변경 + + + + + + 돌아가기 + +
+
+
+
+
+ + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/work-reports/work-report-create.html b/deploy/tkfb-package/fastapi-bridge/static/pages/work-reports/work-report-create.html new file mode 100644 index 0000000..35db0d3 --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/work-reports/work-report-create.html @@ -0,0 +1,65 @@ + + + + + + 작업보고서 입력 | (주)테크니컬코리아 + + + + + + + +
+ + +
+ + +
+ + +
+

📅 날짜 선택

+
+
+ +
+

📋 작업 내용

+
+ + + + + + + + + + + + + + + + +
No작업자프로젝트작업잔업근무형태메모삭제
날짜를 먼저 선택하세요
+
+ +
+ +
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/fastapi-bridge/static/pages/work-reports/work-report-manage.html b/deploy/tkfb-package/fastapi-bridge/static/pages/work-reports/work-report-manage.html new file mode 100644 index 0000000..0ec6f6a --- /dev/null +++ b/deploy/tkfb-package/fastapi-bridge/static/pages/work-reports/work-report-manage.html @@ -0,0 +1,61 @@ + + + + + + 작업보고서 관리 | (주)테크니컬코리아 + + + + + + + +
+ + +
+ + +
+ + +
+

📅 날짜 선택

+
+
+ +
+

📋 선택된 날짜 보고서

+
+ + + + + + + + + + + + + + + + +
No작업자프로젝트작업잔업근무형태메모작업
날짜를 선택하면 보고서가 나타납니다.
+
+
+
+
+
+ + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/init-db/README.txt b/deploy/tkfb-package/init-db/README.txt new file mode 100644 index 0000000..3ea87b7 --- /dev/null +++ b/deploy/tkfb-package/init-db/README.txt @@ -0,0 +1 @@ +-- 초기 데이터베이스 생성 완료 시 실행됨 diff --git a/deploy/tkfb-package/web-ui/Dockerfile b/deploy/tkfb-package/web-ui/Dockerfile new file mode 100644 index 0000000..d5f93d7 --- /dev/null +++ b/deploy/tkfb-package/web-ui/Dockerfile @@ -0,0 +1,11 @@ +FROM nginx:alpine + +# 정적 파일 복사 +COPY . /usr/share/nginx/html/ + +# Nginx 설정 파일 복사 (선택사항) +# COPY nginx.conf /etc/nginx/conf.d/default.conf + +EXPOSE 80 + +CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/Minutes/safety.html b/deploy/tkfb-package/web-ui/Minutes/safety.html new file mode 100644 index 0000000..677861e --- /dev/null +++ b/deploy/tkfb-package/web-ui/Minutes/safety.html @@ -0,0 +1,1635 @@ + + + + + + 안전회의록 작성 + + + +
+
+

🏭 월간 안전회의록

+

테크니컬코리아 안전회의록 작성 및 관리 시스템

+
+ +
+ +
+ + + + +
+ + +
+
+
+ 하주현 선임 → 업무 인수인계 + 출산/육아휴직 대비 +
+
+
+ + + + +
+
+ +
+
+
+
+ + +
+
+
기존 회의록 참조 (미완료 항목)
+
+
+ + + + + +
+ +
+ 미완료 항목 0 | + 0개 표시됨 | + 완료된 항목 0 +
+ +
+ + +
+ +
+ +
+
+
+
+ + +
+
+
정기점검 사항
+
+
+ + + + +
+
+ 정기점검 사항 | + 0개 긴급, + 0개 예정 +
+
+ + +
+
+ +
+
+
+
+ + +
+ +
+
회의 기본정보
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ + +
+
+ 논의사항 + +
+
+
+ +
+
+
+ +
+ + + +
+ + +
+
+
+ + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/Minutes/인수인계관련/안전회의록 2025년 5월.xlsx b/deploy/tkfb-package/web-ui/Minutes/인수인계관련/안전회의록 2025년 5월.xlsx new file mode 100644 index 0000000..7aac17c Binary files /dev/null and b/deploy/tkfb-package/web-ui/Minutes/인수인계관련/안전회의록 2025년 5월.xlsx differ diff --git a/deploy/tkfb-package/web-ui/components/navbar.html b/deploy/tkfb-package/web-ui/components/navbar.html new file mode 100644 index 0000000..28d8e85 --- /dev/null +++ b/deploy/tkfb-package/web-ui/components/navbar.html @@ -0,0 +1,638 @@ + + +
+
+
+
+ +
+

테크니컬코리아

+

생산팀 포털

+
+
+
+ +
+
+
+ --월 --일 (--) + --시 --분 --초 +
+
+ 🌤️ + --°C + 날씨 로딩중 +
+
+
+ +
+ +
+ +
+
+

알림

+ 모두 보기 +
+
+
새 알림이 없습니다.
+
+
+
+ + + 📊 + 대시보드 + + + + + 신고 + + + +
+
+
+ + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/components/sections/admin-sections.html b/deploy/tkfb-package/web-ui/components/sections/admin-sections.html new file mode 100644 index 0000000..7f7085b --- /dev/null +++ b/deploy/tkfb-package/web-ui/components/sections/admin-sections.html @@ -0,0 +1,49 @@ + + + +
+

📄 작업 보고서

+ +
+ +
+

📊 출근/공수 관리

+ +
+ +
+

🔧 시스템 관리

+ +
+ +
+

🏭 공장 정보

+ +
+ +
+

📊 이슈 리포트

+ +
\ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/components/sidebar-nav.html b/deploy/tkfb-package/web-ui/components/sidebar-nav.html new file mode 100644 index 0000000..39b5e99 --- /dev/null +++ b/deploy/tkfb-package/web-ui/components/sidebar-nav.html @@ -0,0 +1,379 @@ + + + + + diff --git a/deploy/tkfb-package/web-ui/components/sidebar.html b/deploy/tkfb-package/web-ui/components/sidebar.html new file mode 100644 index 0000000..532fd6a --- /dev/null +++ b/deploy/tkfb-package/web-ui/components/sidebar.html @@ -0,0 +1,136 @@ + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/css/admin-pages.css b/deploy/tkfb-package/web-ui/css/admin-pages.css new file mode 100644 index 0000000..fb42bc8 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/admin-pages.css @@ -0,0 +1,1555 @@ +/** + * 관리자 페이지 공통 스타일 + * 사무적이고 전문적인 디자인 시스템 + * + * 적용 페이지: + * - projects.html (프로젝트 관리) + * - workers.html (작업자 관리) + * - codes.html (코드 관리) + */ + +/* ============================================ + 1. 전역 변수 및 기본 설정 + ============================================ */ +:root { + /* 색상 시스템 - 사무적 느낌의 중성 색상 */ + --color-primary: #2563eb; + --color-primary-dark: #1e40af; + --color-primary-light: #dbeafe; + + --color-secondary: #64748b; + --color-secondary-dark: #475569; + --color-secondary-light: #f1f5f9; + + --color-success: #10b981; + --color-warning: #f59e0b; + --color-error: #ef4444; + --color-info: #3b82f6; + + /* 배경 색상 */ + --bg-body: #f8fafc; + --bg-card: #ffffff; + --bg-hover: #f1f5f9; + + /* 텍스트 색상 */ + --text-primary: #0f172a; + --text-secondary: #64748b; + --text-muted: #94a3b8; + + /* 테두리 색상 */ + --border-color: #e2e8f0; + --border-focus: #2563eb; + + /* 그림자 */ + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1); + + /* 간격 */ + --space-xs: 0.25rem; + --space-sm: 0.5rem; + --space-md: 1rem; + --space-lg: 1.5rem; + --space-xl: 2rem; + --space-2xl: 3rem; + + /* 폰트 크기 */ + --font-xs: 0.75rem; + --font-sm: 0.875rem; + --font-base: 1rem; + --font-lg: 1.125rem; + --font-xl: 1.25rem; + --font-2xl: 1.5rem; + --font-3xl: 1.875rem; + + /* Border Radius */ + --radius-sm: 0.25rem; + --radius-md: 0.5rem; + --radius-lg: 0.75rem; + --radius-xl: 1rem; +} + +/* ============================================ + 2. 레이아웃 구조 (2단 레이아웃: 사이드바 + 메인) + ============================================ */ +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', Roboto, sans-serif; + background: var(--bg-body); + color: var(--text-primary); + line-height: 1.6; + margin: 0; + padding: 0; +} + +/* 페이지 컨테이너: 사이드바 + 메인 콘텐츠 */ +.page-container { + display: flex; + min-height: calc(100vh - 80px); /* 네비바 높이 제외 */ + background: var(--bg-body); +} + +/* 사이드바 */ +.sidebar { + width: 240px; + min-width: 240px; + flex-shrink: 0; + background: #ffffff; + border-right: 1px solid var(--border-color); + box-shadow: 2px 0 4px rgba(0, 0, 0, 0.05); + overflow-y: auto; +} + +.sidebar-nav { + padding: var(--space-lg) 0; +} + +.sidebar-header { + padding: 0 var(--space-lg) var(--space-md); + border-bottom: 1px solid var(--border-color); + margin-bottom: var(--space-md); +} + +.sidebar-title { + font-size: var(--font-base); + font-weight: 700; + color: var(--text-primary); + margin: 0; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.sidebar-menu { + list-style: none; + padding: 0; + margin: 0; +} + +.menu-item a { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-sm) var(--space-lg); + color: var(--text-secondary); + text-decoration: none; + transition: all 0.2s ease; + white-space: nowrap; +} + +.menu-item a:hover { + background: var(--bg-hover); + color: var(--text-primary); +} + +.menu-item.active a { + background: var(--color-primary-light); + color: var(--color-primary); + font-weight: 600; + border-right: 3px solid var(--color-primary); +} + +.menu-icon { + font-size: var(--font-lg); + flex-shrink: 0; +} + +.menu-text { + font-size: var(--font-sm); +} + +.menu-divider { + height: 1px; + background: var(--border-color); + margin: var(--space-md) var(--space-lg); +} + +/* 메인 콘텐츠 영역 */ +.main-content { + flex: 1; + padding: var(--space-lg); + padding-left: var(--space-md); + overflow-x: hidden; + max-width: 100%; + box-sizing: border-box; +} + +.dashboard-main { + width: 100%; + max-width: 1400px; + margin: 0 auto; +} + +/* 뒤로가기 버튼 - 사이드바로 대체되어 숨김 */ +.back-button { + display: none; +} + +/* ============================================ + 3. 페이지 헤더 + ============================================ */ +.page-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + margin-bottom: var(--space-xl); + padding: var(--space-lg); + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-sm); +} + +.page-title-section { + flex: 1; +} + +.page-title { + display: flex; + align-items: center; + gap: var(--space-md); + font-size: var(--font-3xl); + font-weight: 700; + color: var(--text-primary); + margin: 0 0 var(--space-sm) 0; + white-space: nowrap; /* 텍스트 줄바꿈 방지 */ +} + +.title-icon { + font-size: var(--font-2xl); + filter: grayscale(30%); +} + +.page-description { + font-size: var(--font-sm); + color: var(--text-secondary); + margin: 0; + line-height: 1.5; + max-width: 100%; + word-wrap: break-word; +} + +.page-actions { + display: flex; + gap: var(--space-sm); + flex-shrink: 0; +} + +/* ============================================ + 4. 버튼 스타일 + ============================================ */ +.btn { + display: inline-flex; + align-items: center; + gap: var(--space-sm); + padding: 0.625rem 1.25rem; + font-size: var(--font-sm); + font-weight: 600; + border: none; + border-radius: var(--radius-md); + cursor: pointer; + transition: all 0.2s ease; + white-space: nowrap; +} + +.btn-primary { + background: var(--color-primary); + color: white; + box-shadow: var(--shadow-sm); +} + +.btn-primary:hover { + background: var(--color-primary-dark); + box-shadow: var(--shadow-md); + transform: translateY(-1px); +} + +.btn-secondary { + background: var(--bg-card); + color: var(--text-secondary); + border: 1px solid var(--border-color); +} + +.btn-secondary:hover { + background: var(--bg-hover); + color: var(--text-primary); + border-color: var(--color-secondary); +} + +.btn-icon { + font-size: var(--font-base); + filter: grayscale(20%); +} + +/* ============================================ + 5. 검색 섹션 + ============================================ */ +.search-section { + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: var(--space-lg); + margin-bottom: var(--space-xl); + box-shadow: var(--shadow-sm); +} + +.search-bar { + display: flex; + gap: var(--space-md); + margin-bottom: var(--space-md); +} + +.search-input { + flex: 1; + padding: 0.625rem 1rem; + font-size: var(--font-sm); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + background: var(--bg-body); + transition: all 0.2s ease; +} + +.search-input:focus { + outline: none; + border-color: var(--border-focus); + background: white; + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); +} + +.search-btn { + padding: 0.625rem 1.25rem; + background: var(--color-primary); + color: white; + border: none; + border-radius: var(--radius-md); + font-size: var(--font-sm); + font-weight: 600; + cursor: pointer; + white-space: nowrap; + transition: all 0.2s ease; +} + +.search-btn:hover { + background: var(--color-primary-dark); + transform: translateY(-1px); +} + +/* 필터 영역 */ +.filter-group { + display: flex; + flex-wrap: wrap; + gap: var(--space-md); + align-items: center; +} + +.filter-label { + font-size: var(--font-sm); + font-weight: 600; + color: var(--text-secondary); + margin-right: var(--space-sm); +} + +.filter-btn { + padding: 0.5rem 1rem; + font-size: var(--font-sm); + background: var(--bg-body); + color: var(--text-secondary); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + cursor: pointer; + transition: all 0.2s ease; +} + +.filter-btn:hover { + background: var(--bg-hover); + color: var(--text-primary); +} + +.filter-btn.active { + background: var(--color-primary); + color: white; + border-color: var(--color-primary); +} + +/* ============================================ + 6. 프로젝트 섹션 + ============================================ */ +.projects-section { + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: var(--space-lg); + box-shadow: var(--shadow-sm); + width: 100%; + max-width: 100%; + overflow: hidden; + box-sizing: border-box; +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + flex-wrap: wrap; + gap: var(--space-md); + margin-bottom: var(--space-lg); + padding-bottom: var(--space-md); + border-bottom: 1px solid var(--border-color); +} + +.section-title { + font-size: var(--font-xl); + font-weight: 700; + color: var(--text-primary); + margin: 0; +} + +/* 통계 카드 */ +.project-stats { + display: flex; + gap: var(--space-sm); + flex-wrap: wrap; +} + +.stat-item { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: 0.625rem 1rem; + background: var(--bg-card); + border: 2px solid var(--border-color); + border-radius: var(--radius-md); + font-size: var(--font-sm); + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + white-space: nowrap; +} + +.stat-item:hover { + transform: translateY(-2px); + box-shadow: var(--shadow-md); +} + +.stat-item.active { + border-width: 2px; + box-shadow: var(--shadow-md); + transform: scale(1.02); +} + +.stat-icon { + font-size: var(--font-lg); +} + +/* 상태별 통계 색상 */ +.active-stat { + background: rgba(16, 185, 129, 0.05); + color: var(--color-success); + border-color: var(--color-success); +} + +.inactive-stat { + background: rgba(239, 68, 68, 0.05); + color: var(--color-error); + border-color: var(--color-error); +} + +.total-stat { + background: rgba(37, 99, 235, 0.05); + color: var(--color-primary); + border-color: var(--color-primary); +} + +/* ============================================ + 7. 그리드 레이아웃 (중앙 정렬) + ============================================ */ +.projects-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-lg); + width: 100%; + max-width: 100%; +} + +/* ============================================ + 8. 카드 스타일 + ============================================ */ +.project-card, +.worker-card { + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: var(--space-lg); + transition: all 0.2s ease; + cursor: pointer; + position: relative; + display: flex; + flex-direction: column; + height: 420px; + min-height: 420px; + max-height: 420px; + max-width: 100%; + overflow: hidden; + box-sizing: border-box; + word-wrap: break-word; +} + +.project-card:hover, +.worker-card:hover { + border-color: var(--color-primary); + box-shadow: var(--shadow-lg); + transform: translateY(-4px); +} + +.project-card.inactive, +.worker-card.inactive { + opacity: 0.75; + background: var(--bg-body); +} + +/* 카드 헤더 */ +.project-header { + display: flex; + flex-direction: column; + flex: 1; + min-height: 0; +} + +.project-info { + flex: 1; + display: flex; + flex-direction: column; + gap: var(--space-sm); + margin-bottom: var(--space-md); +} + +.project-job-no { + font-size: var(--font-xs); + font-weight: 600; + color: var(--text-muted); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.project-name { + font-size: var(--font-lg); + font-weight: 700; + color: var(--text-primary); + margin: 0; + line-height: 1.3; +} + +.project-badge { + padding: 0.25rem 0.75rem; + font-size: var(--font-xs); + font-weight: 600; + border-radius: var(--radius-sm); + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.badge-active { + background: rgba(16, 185, 129, 0.1); + color: var(--color-success); +} + +.badge-inactive { + background: rgba(239, 68, 68, 0.1); + color: var(--color-error); +} + +/* 카드 메타 정보 */ +.project-meta { + display: grid; + grid-template-columns: 1fr; + gap: var(--space-xs); + font-size: var(--font-sm); + color: var(--text-secondary); + padding: var(--space-md); + background: var(--bg-body); + border-radius: var(--radius-md); + margin-bottom: var(--space-md); +} + +.project-meta > span { + display: flex; + align-items: center; + gap: var(--space-xs); + padding: var(--space-xs) 0; + line-height: 1.5; +} + +.project-meta > span:empty::after { + content: '정보 없음'; + color: var(--text-muted); + font-style: italic; +} + +.meta-row { + display: grid; + grid-template-columns: 100px 1fr; + align-items: center; + gap: var(--space-sm); + font-size: var(--font-sm); + padding: var(--space-xs) 0; +} + +.meta-label { + font-weight: 600; + color: var(--text-muted); + font-size: var(--font-xs); + text-transform: uppercase; + letter-spacing: 0.3px; +} + +.meta-value { + color: var(--text-primary); + font-weight: 500; +} + +.meta-value:empty::after { + content: '-'; + color: var(--text-muted); +} + +/* 카드 액션 */ +.project-actions, +.worker-actions { + display: flex; + gap: var(--space-sm); + margin-top: auto; + padding-top: var(--space-md); + border-top: 1px solid var(--border-color); +} + +.btn-edit, +.btn-delete, +.action-btn { + flex: 1; + padding: 0.5rem 1rem; + font-size: var(--font-sm); + font-weight: 600; + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + background: white; + color: var(--text-secondary); + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + gap: var(--space-xs); +} + +.btn-edit:hover { + background: var(--color-primary); + color: white; + border-color: var(--color-primary); + transform: translateY(-1px); +} + +.btn-delete:hover, +.action-btn.danger:hover { + background: var(--color-error); + color: white; + border-color: var(--color-error); + transform: translateY(-1px); +} + +/* 작업자 카드 특별 스타일 */ +.worker-card .project-info { + display: flex; + align-items: flex-start; + gap: var(--space-md); + margin-bottom: var(--space-md); +} + +.worker-avatar { + width: 60px; + height: 60px; + border-radius: 50%; + background: linear-gradient(135deg, var(--color-primary), var(--color-primary-dark)); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + box-shadow: var(--shadow-md); +} + +.avatar-initial { + color: white; + font-size: var(--font-xl); + font-weight: 700; +} + +.worker-card.inactive .worker-avatar { + background: linear-gradient(135deg, var(--color-secondary), var(--color-secondary-dark)); + opacity: 0.7; +} + +.worker-details { + flex: 1; + min-width: 0; +} + +/* 비활성화 오버레이 및 라벨 */ +.inactive-overlay { + position: absolute; + top: var(--space-md); + right: var(--space-md); + z-index: 10; +} + +.inactive-badge { + display: inline-flex; + align-items: center; + gap: var(--space-xs); + padding: 0.375rem 0.75rem; + background: rgba(239, 68, 68, 0.9); + color: white; + border-radius: var(--radius-md); + font-size: var(--font-xs); + font-weight: 700; + box-shadow: var(--shadow-md); +} + +.inactive-label { + color: var(--color-error); + font-size: var(--font-sm); + font-weight: 600; + margin-left: var(--space-xs); +} + +.inactive-notice { + color: var(--color-warning) !important; + font-weight: 600 !important; +} + +/* ============================================ + 9. 코드 관리 탭 + ============================================ */ +.code-tabs { + display: flex; + gap: var(--space-sm); + margin-bottom: var(--space-xl); + padding: var(--space-sm); + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + overflow-x: auto; +} + +.tab-btn { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: 0.75rem 1.25rem; + font-size: var(--font-sm); + font-weight: 600; + color: var(--text-secondary); + background: transparent; + border: none; + border-radius: var(--radius-md); + cursor: pointer; + transition: all 0.2s ease; + white-space: nowrap; +} + +.tab-btn:hover { + background: var(--bg-hover); + color: var(--text-primary); +} + +.tab-btn.active { + color: var(--color-primary); + background: var(--color-primary-light); + border-bottom: 3px solid var(--color-primary); + font-weight: 600; +} + +.tab-icon { + font-size: var(--font-base); +} + +/* ============================================ + 10. 테이블 스타일 + ============================================ */ +.table-container { + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + overflow: hidden; +} + +table { + width: 100%; + border-collapse: collapse; +} + +thead { + background: var(--bg-body); + border-bottom: 2px solid var(--border-color); +} + +th { + padding: 1rem; + font-size: var(--font-sm); + font-weight: 700; + color: var(--text-secondary); + text-align: left; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +td { + padding: 1rem; + font-size: var(--font-sm); + color: var(--text-primary); + border-bottom: 1px solid var(--border-color); +} + +tr:hover { + background: var(--bg-hover); +} + +tr:last-child td { + border-bottom: none; +} + +/* 테이블 내 버튼 스타일 */ +.data-table .btn-icon { + padding: 0.375rem 0.5rem; + background: transparent; + border: none; + cursor: pointer; + font-size: 1rem; + transition: all 0.2s ease; + border-radius: var(--radius-sm); +} + +.data-table .btn-icon:hover { + background: var(--bg-hover); + transform: scale(1.1); +} + +/* ============================================ + 11. 모달 + ============================================ */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + backdrop-filter: blur(4px); +} + +.modal-container { + background: var(--bg-card); + border-radius: var(--radius-xl); + width: 90%; + max-width: 600px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 20px 25px -5px rgba(0, 0, 0, 0.1); +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: var(--space-lg); + border-bottom: 1px solid var(--border-color); +} + +.modal-title { + font-size: var(--font-xl); + font-weight: 700; + color: var(--text-primary); + margin: 0; +} + +.modal-close { + padding: 0.5rem; + background: none; + border: none; + font-size: var(--font-xl); + color: var(--text-secondary); + cursor: pointer; + border-radius: var(--radius-md); + transition: all 0.2s ease; +} + +.modal-close:hover { + background: var(--bg-hover); + color: var(--text-primary); +} + +.modal-body { + padding: var(--space-lg); +} + +.modal-footer { + display: flex; + gap: var(--space-md); + justify-content: flex-end; + padding: var(--space-lg); + border-top: 1px solid var(--border-color); +} + +/* ============================================ + 12. 폼 요소 + ============================================ */ +.form-group { + margin-bottom: var(--space-lg); +} + +.form-label { + display: block; + margin-bottom: var(--space-sm); + font-size: var(--font-sm); + font-weight: 600; + color: var(--text-primary); +} + +.form-label.required::after { + content: '*'; + color: var(--color-error); + margin-left: var(--space-xs); +} + +.form-input, +.form-select, +.form-textarea { + width: 100%; + padding: 0.625rem 1rem; + font-size: var(--font-sm); + border: 1px solid var(--border-color); + border-radius: var(--radius-md); + background: white; + transition: all 0.2s ease; + box-sizing: border-box; +} + +.form-input:focus, +.form-select:focus, +.form-textarea:focus { + outline: none; + border-color: var(--border-focus); + box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.1); +} + +.form-textarea { + resize: vertical; + min-height: 100px; +} + +.form-help { + margin-top: var(--space-xs); + font-size: var(--font-xs); + color: var(--text-muted); +} + +/* ============================================ + 13. 반응형 디자인 + ============================================ */ + +/* 대형 데스크탑 (1400px 이상) */ +@media (min-width: 1400px) { + .projects-grid { + grid-template-columns: repeat(3, 1fr); + } +} + +/* 일반 데스크탑 (1200px ~ 1399px) */ +@media (max-width: 1399px) and (min-width: 1200px) { + .projects-grid { + grid-template-columns: repeat(3, 1fr); + } +} + +/* 중간 화면 (1024px ~ 1199px) - 2열 */ +@media (max-width: 1199px) and (min-width: 1024px) { + .projects-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +/* 태블릿 (768px ~ 1023px) */ +@media (max-width: 1023px) and (min-width: 768px) { + .sidebar { + width: 200px; + min-width: 200px; + } + + .main-content { + padding: var(--space-md); + } + + .page-header { + flex-direction: column; + align-items: flex-start; + gap: var(--space-md); + } + + .page-actions { + width: 100%; + justify-content: flex-start; + } + + .projects-grid { + grid-template-columns: repeat(2, 1fr); + } + + .search-bar { + flex-direction: column; + } + + .project-stats { + flex-wrap: wrap; + gap: var(--space-sm); + } + + .stat-item { + font-size: var(--font-xs); + padding: 0.375rem 0.625rem; + } +} + +/* 모바일 (767px 이하) */ +@media (max-width: 767px) { + .page-container { + flex-direction: column; + } + + .sidebar { + display: none; /* 모바일에서는 사이드바 숨김 */ + } + + .main-content { + padding: var(--space-sm); + } + + .page-title { + font-size: var(--font-xl); + flex-direction: column; + align-items: flex-start; + gap: var(--space-xs); + } + + .title-icon { + font-size: var(--font-xl); + } + + .page-actions { + width: 100%; + flex-direction: column; + } + + .btn { + width: 100%; + justify-content: center; + } + + .search-section, + .projects-section { + padding: var(--space-md); + } + + .search-bar { + flex-direction: column; + } + + .projects-grid { + grid-template-columns: 1fr; + gap: var(--space-md); + } + + .project-card { + min-height: auto; + } + + .project-stats { + flex-direction: column; + width: 100%; + } + + .stat-item { + width: 100%; + justify-content: space-between; + } + + .code-tabs { + flex-direction: column; + } + + .tab-btn { + justify-content: center; + } + + .meta-row { + grid-template-columns: 80px 1fr; + gap: var(--space-xs); + } + + .meta-label { + font-size: 0.625rem; + } + + .modal-container { + width: 95%; + margin: var(--space-sm); + max-height: 95vh; + } +} + +/* 초소형 모바일 (480px 이하) */ +@media (max-width: 480px) { + .work-report-main { + padding: var(--space-xs); + } + + .page-title { + font-size: var(--font-lg); + } + + .page-description { + font-size: var(--font-xs); + } + + .search-section, + .projects-section { + padding: var(--space-sm); + } + + .project-card { + padding: var(--space-md); + } + + .btn { + padding: 0.5rem 0.875rem; + font-size: var(--font-xs); + } +} + +/* ============================================ + 14. Empty State + ============================================ */ +.empty-state { + text-align: center; + padding: var(--space-2xl) var(--space-lg); + color: var(--text-secondary); +} + +.empty-icon { + font-size: 4rem; + margin-bottom: var(--space-lg); + opacity: 0.5; +} + +.empty-state h3 { + font-size: var(--font-xl); + font-weight: 600; + color: var(--text-primary); + margin: 0 0 var(--space-sm) 0; +} + +.empty-state p { + font-size: var(--font-sm); + color: var(--text-secondary); + margin-bottom: var(--space-lg); +} + +/* ============================================ + 15. 로딩 및 스켈레톤 + ============================================ */ +.skeleton { + background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%); + background-size: 200% 100%; + animation: skeleton-loading 1.5s ease-in-out infinite; + border-radius: var(--radius-md); +} + +@keyframes skeleton-loading { + 0% { + background-position: 200% 0; + } + 100% { + background-position: -200% 0; + } +} + +.skeleton-card { + height: 280px; +} + +.skeleton-text { + height: 1rem; + margin-bottom: var(--space-sm); +} + +/* ============================================ + 16. 유틸리티 클래스 + ============================================ */ +.text-center { + text-align: center; +} + +.text-muted { + color: var(--text-muted); +} + +.text-success { + color: var(--color-success); +} + +.text-error { + color: var(--color-error); +} + +.mt-0 { margin-top: 0; } +.mt-1 { margin-top: var(--space-sm); } +.mt-2 { margin-top: var(--space-md); } +.mt-3 { margin-top: var(--space-lg); } + +.mb-0 { margin-bottom: 0; } +.mb-1 { margin-bottom: var(--space-sm); } +.mb-2 { margin-bottom: var(--space-md); } +.mb-3 { margin-bottom: var(--space-lg); } + +.hidden { + display: none !important; +} + +.loading { + opacity: 0.6; + pointer-events: none; +} + +/* 코드 상세 정보 */ +.code-detail { + display: flex; + flex-direction: column; + gap: var(--space-xs); +} + +.code-name { + font-size: var(--font-base); + font-weight: 600; + color: var(--text-primary); +} + +.code-description { + font-size: var(--font-sm); + color: var(--text-secondary); + line-height: 1.5; +} + +/* ============================================ + 17. 코드 관리 페이지 전용 스타일 + ============================================ */ + +/* 코드 탭 스타일 */ +.code-tabs { + display: flex; + gap: var(--space-sm); + margin-bottom: var(--space-xl); + border-bottom: 2px solid var(--border-color); + padding-bottom: 0; +} + +.tab-btn { + display: flex; + align-items: center; + gap: var(--space-sm); + padding: var(--space-md) var(--space-lg); + background: transparent; + border: none; + border-bottom: 3px solid transparent; + color: var(--text-secondary); + font-size: var(--font-base); + font-weight: 600; + cursor: pointer; + transition: all 0.2s ease; + position: relative; + margin-bottom: -2px; +} + +.tab-btn:hover { + color: var(--color-primary); + background: var(--color-primary-light); +} + +.tab-btn.active { + color: var(--color-primary); + border-bottom-color: var(--color-primary); +} + +.tab-icon { + font-size: var(--font-lg); +} + +/* 탭 콘텐츠 */ +.code-tab-content { + display: none; +} + +.code-tab-content.active { + display: block; + animation: fadeIn 0.3s ease; +} + +@keyframes fadeIn { + from { + opacity: 0; + transform: translateY(10px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* 코드 섹션 */ +.code-section { + margin-bottom: var(--space-xl); +} + +/* 코드 통계 */ +.code-stats { + display: flex; + gap: var(--space-sm); + flex-wrap: wrap; + margin-bottom: var(--space-lg); +} + +.code-stats .stat-item { + padding: 0.5rem 1rem; + font-size: var(--font-sm); +} + +/* 코드 그리드 */ +.code-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-lg); + width: 100%; +} + +/* 코드 카드 */ +.code-card { + background: var(--bg-card); + border: 1px solid var(--border-color); + border-radius: var(--radius-lg); + padding: var(--space-lg); + transition: all 0.2s ease; + cursor: pointer; + position: relative; + display: flex; + flex-direction: column; + min-height: 200px; +} + +.code-card:hover { + border-color: var(--color-primary); + box-shadow: var(--shadow-lg); + transform: translateY(-2px); +} + +/* 코드 카드 헤더 */ +.code-header { + display: flex; + align-items: flex-start; + gap: var(--space-md); + margin-bottom: var(--space-md); +} + +.code-icon { + font-size: 2rem; + flex-shrink: 0; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + background: var(--bg-body); + border-radius: var(--radius-md); +} + +.code-info { + flex: 1; + min-width: 0; +} + +.code-name { + font-size: var(--font-lg); + font-weight: 700; + color: var(--text-primary); + margin: 0 0 var(--space-xs) 0; + word-break: break-word; +} + +.code-label { + display: inline-block; + padding: 0.25rem 0.75rem; + background: var(--bg-body); + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + font-size: var(--font-xs); + font-weight: 600; + color: var(--text-secondary); +} + +.code-actions { + display: flex; + gap: var(--space-xs); + flex-shrink: 0; +} + +.btn-small { + padding: 0.375rem 0.625rem; + font-size: var(--font-sm); + background: white; + border: 1px solid var(--border-color); + border-radius: var(--radius-sm); + cursor: pointer; + transition: all 0.2s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.btn-small:hover { + transform: scale(1.1); +} + +.btn-small.btn-edit:hover { + background: var(--color-primary); + border-color: var(--color-primary); + color: white; +} + +.btn-small.btn-delete:hover { + background: var(--color-error); + border-color: var(--color-error); + color: white; +} + +/* 코드 설명 */ +.code-description { + font-size: var(--font-sm); + color: var(--text-secondary); + line-height: 1.6; + margin-bottom: var(--space-md); + flex: 1; +} + +/* 해결 가이드 */ +.solution-guide { + background: #fef3c7; + border-left: 3px solid #f59e0b; + padding: var(--space-md); + border-radius: var(--radius-sm); + font-size: var(--font-sm); + margin-bottom: var(--space-md); + line-height: 1.6; +} + +.solution-guide strong { + color: #92400e; + display: block; + margin-bottom: var(--space-xs); +} + +/* 코드 메타 정보 */ +.code-meta { + display: flex; + flex-wrap: wrap; + gap: var(--space-md); + padding-top: var(--space-md); + border-top: 1px solid var(--border-color); + margin-top: auto; +} + +.code-date { + font-size: var(--font-xs); + color: var(--text-muted); +} + +/* 상태별 카드 스타일 */ +.normal-status { + border-left: 4px solid #10b981; +} + +.error-status { + border-left: 4px solid #ef4444; +} + +/* 심각도별 카드 스타일 */ +.severity-low { + border-left: 4px solid #10b981; +} + +.severity-low .code-icon { + background: #d1fae5; +} + +.severity-medium { + border-left: 4px solid #f59e0b; +} + +.severity-medium .code-icon { + background: #fef3c7; +} + +.severity-high { + border-left: 4px solid #f97316; +} + +.severity-high .code-icon { + background: #ffedd5; +} + +.severity-critical { + border-left: 4px solid #ef4444; +} + +.severity-critical .code-icon { + background: #fee2e2; +} + +/* 작업 유형 카드 */ +.work-type-card { + border-left: 4px solid #3b82f6; +} + +.work-type-card .code-icon { + background: #dbeafe; +} + +/* 반응형 - 코드 그리드 */ +@media (max-width: 1199px) { + .code-grid { + grid-template-columns: repeat(2, 1fr); + } +} + +@media (max-width: 767px) { + .code-grid { + grid-template-columns: 1fr; + } + + .code-tabs { + overflow-x: auto; + flex-wrap: nowrap; + } + + .tab-btn { + white-space: nowrap; + padding: var(--space-sm) var(--space-md); + font-size: var(--font-sm); + } +} diff --git a/deploy/tkfb-package/web-ui/css/admin-settings.css b/deploy/tkfb-package/web-ui/css/admin-settings.css new file mode 100644 index 0000000..8013870 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/admin-settings.css @@ -0,0 +1,1320 @@ +/* admin-settings.css */ + +/* 기본 레이아웃 */ +.work-report-container { + min-height: 100vh; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +.work-report-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + text-align: center; + padding: 3rem 2rem; + margin-bottom: 0; +} + +.work-report-header h1 { + font-size: 2.5rem; + font-weight: 700; + margin: 0 0 1rem 0; + text-shadow: 0 2px 4px rgba(0,0,0,0.3); +} + +.work-report-header .subtitle { + font-size: 1.1rem; + opacity: 0.9; + margin: 0; + font-weight: 300; +} + +.work-report-main { + background: #f8f9fa; + min-height: calc(100vh - 200px); + padding-top: 2rem; +} + +.back-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.5rem; + background: rgba(255, 255, 255, 0.9); + color: #495057; + text-decoration: none; + border-radius: 8px; + font-weight: 500; + margin: 0 2rem 2rem 2rem; + transition: all 0.3s ease; + box-shadow: 0 2px 4px rgba(0,0,0,0.1); +} + +.back-button:hover { + background: white; + color: #007bff; + transform: translateY(-1px); + box-shadow: 0 4px 8px rgba(0,0,0,0.15); +} + +.dashboard-main { + padding: 0 2rem 2rem 2rem; + max-width: 1400px; + margin: 0 auto; +} + +.page-header { + margin-bottom: 2rem; +} + +.page-title-section { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.page-title { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 2rem; + font-weight: 700; + color: #1a1a1a; + margin: 0; +} + +.title-icon { + font-size: 2.25rem; +} + +.page-description { + font-size: 1rem; + color: #666; + margin: 0; +} + +/* 설정 섹션 */ +.settings-section { + background: white; + border-radius: 12px; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05); + overflow: hidden; +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1.5rem 2rem; + background: #f8f9fa; + border-bottom: 1px solid #e9ecef; +} + +.section-title { + display: flex; + align-items: center; + gap: 0.75rem; + font-size: 1.25rem; + font-weight: 600; + color: #1a1a1a; + margin: 0; +} + +.section-icon { + font-size: 1.5rem; +} + +/* 사용자 컨테이너 */ +.users-container { + padding: 2rem; +} + +.users-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; + gap: 1rem; +} + +/* 검색 박스 */ +.search-box { + position: relative; + flex: 1; + max-width: 300px; +} + +.search-input { + width: 100%; + padding: 0.75rem 1rem 0.75rem 2.5rem; + border: 2px solid #e9ecef; + border-radius: 8px; + font-size: 0.9rem; + transition: all 0.2s ease; +} + +.search-input:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1); +} + +.search-icon { + position: absolute; + left: 0.75rem; + top: 50%; + transform: translateY(-50%); + font-size: 1rem; + color: #666; +} + +/* 필터 버튼 */ +.filter-buttons { + display: flex; + gap: 0.5rem; +} + +.filter-btn { + padding: 0.5rem 1rem; + border: 2px solid #e9ecef; + background: white; + border-radius: 6px; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.filter-btn:hover { + border-color: #007bff; + color: #007bff; +} + +.filter-btn.active { + background: #007bff; + border-color: #007bff; + color: white; +} + +/* 사용자 테이블 */ +.users-table-container { + border: 1px solid #e9ecef; + border-radius: 8px; + overflow: hidden; +} + +.users-table { + width: 100%; + border-collapse: collapse; + font-size: 0.9rem; +} + +.users-table th { + background: #f8f9fa; + padding: 1rem; + text-align: left; + font-weight: 600; + color: #495057; + border-bottom: 2px solid #e9ecef; +} + +.users-table td { + padding: 1rem; + border-bottom: 1px solid #e9ecef; + vertical-align: middle; +} + +.users-table tbody tr:hover { + background: #f8f9fa; +} + +/* 사용자 정보 */ +.user-info { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.user-avatar-small { + width: 36px; + height: 36px; + background: #007bff; + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 600; + font-size: 0.9rem; +} + +.user-details h4 { + margin: 0; + font-size: 0.9rem; + font-weight: 600; + color: #1a1a1a; +} + +.user-details p { + margin: 0; + font-size: 0.8rem; + color: #666; +} + +/* 역할 배지 */ +.role-badge { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.25rem 0.75rem; + border-radius: 12px; + font-size: 0.75rem; + font-weight: 600; +} + +.role-badge.admin { + background: #dc3545; + color: white; +} + +.role-badge.leader { + background: #fd7e14; + color: white; +} + +.role-badge.user { + background: #28a745; + color: white; +} + +/* 상태 배지 */ +.status-badge { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.25rem 0.75rem; + border-radius: 12px; + font-size: 0.75rem; + font-weight: 600; +} + +.status-badge.active { + background: #d4edda; + color: #155724; +} + +.status-badge.inactive { + background: #f8d7da; + color: #721c24; +} + +/* 액션 버튼 */ +.action-buttons { + display: flex; + gap: 0.5rem; +} + +.action-btn { + padding: 0.4rem 0.8rem; + border: none; + border-radius: 4px; + font-size: 0.8rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; +} + +.action-btn.edit { + background: #007bff; + color: white; +} + +.action-btn.edit:hover { + background: #0056b3; +} + +.action-btn.delete { + background: #dc3545; + color: white; +} + +.action-btn.delete:hover { + background: #c82333; +} + +.action-btn.toggle { + background: #6c757d; + color: white; +} + +.action-btn.toggle:hover { + background: #545b62; +} + +/* 빈 상태 */ +.empty-state { + text-align: center; + padding: 3rem 2rem; + color: #666; +} + +.empty-icon { + font-size: 4rem; + margin-bottom: 1rem; +} + +.empty-state h3 { + font-size: 1.25rem; + font-weight: 600; + margin-bottom: 0.5rem; + color: #1a1a1a; +} + +.empty-state p { + font-size: 0.9rem; + margin: 0; +} + +/* 모달 스타일 */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; +} + +.modal-container { + background: white; + border-radius: 12px; + box-shadow: 0 20px 25px rgba(0, 0, 0, 0.1); + width: 90%; + max-width: 500px; + max-height: 90vh; + overflow-y: auto; +} + +.modal-container.small { + max-width: 400px; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1.5rem 2rem; + border-bottom: 1px solid #e9ecef; +} + +.modal-header h2 { + margin: 0; + font-size: 1.25rem; + font-weight: 600; + color: #1a1a1a; +} + +.modal-close-btn { + background: none; + border: none; + font-size: 1.5rem; + color: #666; + cursor: pointer; + padding: 0; + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + transition: all 0.2s ease; +} + +.modal-close-btn:hover { + background: #f8f9fa; + color: #1a1a1a; +} + +.modal-body { + padding: 2rem; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 1rem; + padding: 1.5rem 2rem; + border-top: 1px solid #e9ecef; + background: #f8f9fa; +} + +/* 폼 스타일 */ +.form-group { + margin-bottom: 1.5rem; +} + +.form-label { + display: block; + margin-bottom: 0.5rem; + font-weight: 600; + color: #1a1a1a; + font-size: 0.9rem; +} + +.form-control { + width: 100%; + padding: 0.75rem; + border: 2px solid #e9ecef; + border-radius: 6px; + font-size: 0.9rem; + transition: all 0.2s ease; +} + +.form-control:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1); +} + +.form-help { + display: block; + margin-top: 0.25rem; + font-size: 0.8rem; + color: #666; +} + +/* 삭제 경고 */ +.delete-warning { + text-align: center; + padding: 1rem 0; +} + +.warning-icon { + font-size: 3rem; + margin-bottom: 1rem; +} + +.delete-warning p { + margin-bottom: 0.5rem; + font-size: 1rem; + color: #1a1a1a; +} + +.warning-text { + font-size: 0.9rem; + color: #dc3545; + font-weight: 500; +} + +/* 버튼 스타일 */ +.btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.5rem; + border: none; + border-radius: 6px; + font-size: 0.9rem; + font-weight: 500; + text-decoration: none; + cursor: pointer; + transition: all 0.2s ease; +} + +.btn-primary { + background: #007bff; + color: white; +} + +.btn-primary:hover { + background: #0056b3; + transform: translateY(-1px); +} + +.btn-secondary { + background: #6c757d; + color: white; +} + +.btn-secondary:hover { + background: #545b62; +} + +.btn-danger { + background: #dc3545; + color: white; +} + +.btn-danger:hover { + background: #c82333; +} + +.btn-icon { + font-size: 1rem; +} + +/* 토스트 알림 */ +.toast-container { + position: fixed; + top: 20px; + right: 20px; + z-index: 1100; +} + +.toast { + background: white; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + padding: 1rem 1.5rem; + margin-bottom: 0.5rem; + display: flex; + align-items: center; + gap: 0.75rem; + min-width: 300px; + animation: slideIn 0.3s ease; +} + +.toast.success { + border-left: 4px solid #28a745; +} + +.toast.error { + border-left: 4px solid #dc3545; +} + +.toast.warning { + border-left: 4px solid #ffc107; +} + +.toast-icon { + font-size: 1.25rem; +} + +.toast-message { + flex: 1; + font-size: 0.9rem; + color: #1a1a1a; +} + +.toast-close { + background: none; + border: none; + font-size: 1.25rem; + color: #666; + cursor: pointer; + padding: 0; +} + +@keyframes slideIn { + from { + transform: translateX(100%); + opacity: 0; + } + to { + transform: translateX(0); + opacity: 1; + } +} + +/* 반응형 */ +@media (max-width: 1024px) { + .dashboard-main { + padding: 1.5rem; + } + + .users-header { + flex-direction: column; + align-items: stretch; + gap: 1rem; + } + + .search-box { + max-width: none; + } +} + +@media (max-width: 768px) { + .dashboard-main { + padding: 1rem; + } + + .section-header { + flex-direction: column; + align-items: stretch; + gap: 1rem; + } + + .users-table-container { + overflow-x: auto; + } + + .users-table { + min-width: 600px; + } + + .modal-container { + width: 95%; + margin: 1rem; + } + + .modal-body { + padding: 1.5rem; + } +} + +@media (max-width: 480px) { + .filter-buttons { + flex-wrap: wrap; + } + + .action-buttons { + flex-direction: column; + } +} + +/* 페이지 권한 관리 스타일 */ +.page-access-list { + max-height: 300px; + overflow-y: auto; + border: 1px solid var(--border-light); + border-radius: var(--radius-md); + padding: var(--space-3); + background: var(--bg-secondary); +} + +.page-access-category { + margin-bottom: var(--space-4); +} + +.page-access-category:last-child { + margin-bottom: 0; +} + +.page-access-category-title { + font-size: var(--text-sm); + font-weight: var(--font-semibold); + color: var(--text-secondary); + margin-bottom: var(--space-2); + padding-bottom: var(--space-2); + border-bottom: 1px solid var(--border-light); + text-transform: uppercase; +} + +.page-access-item { + display: flex; + align-items: center; + padding: var(--space-2); + border-radius: var(--radius-sm); + transition: var(--transition-normal); +} + +.page-access-item:hover { + background: var(--bg-hover); +} + +.page-access-item label { + display: flex; + align-items: center; + cursor: pointer; + flex: 1; + margin: 0; +} + +.page-access-item input[type="checkbox"] { + margin-right: var(--space-2); + width: 18px; + height: 18px; + cursor: pointer; +} + +.page-access-item .page-name { + font-size: var(--text-sm); + color: var(--text-primary); + font-weight: var(--font-medium); +} + +/* 권한 관리 버튼 스타일 */ +.action-btn.permissions { + background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%); + color: white; +} + +.action-btn.permissions:hover { + background: linear-gradient(135deg, #7c3aed 0%, #6d28d9 100%); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3); +} + +/* 비밀번호 초기화 버튼 스타일 */ +.action-btn.reset-pw { + background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); + color: white; +} + +.action-btn.reset-pw:hover { + background: linear-gradient(135deg, #d97706 0%, #b45309 100%); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3); +} + +/* 페이지 권한 모달 사용자 정보 */ +.page-access-user-info { + display: flex; + align-items: center; + gap: var(--space-3); + padding: var(--space-4); + background: var(--bg-secondary); + border-radius: var(--radius-lg); + margin-bottom: var(--space-4); +} + +.page-access-user-info h3 { + margin: 0; + font-size: var(--text-lg); + font-weight: var(--font-semibold); + color: var(--text-primary); +} + +.page-access-user-info p { + margin: 0; + font-size: var(--text-sm); + color: var(--text-secondary); +} + +/* 폴더 트리 스타일 */ +.folder-tree { + padding: 0; +} + +.folder-group { + margin-bottom: 0.5rem; + border: 1px solid #e9ecef; + border-radius: 8px; + overflow: hidden; +} + +.folder-header { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1rem; + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + cursor: pointer; + transition: all 0.2s ease; + user-select: none; +} + +.folder-header:hover { + background: linear-gradient(135deg, #e9ecef 0%, #dee2e6 100%); +} + +.folder-icon { + font-size: 1.25rem; +} + +.folder-name { + font-weight: 600; + color: #1a1a1a; + flex: 1; +} + +.folder-count { + font-size: 0.75rem; + color: #6c757d; + background: white; + padding: 0.125rem 0.5rem; + border-radius: 10px; +} + +.folder-toggle { + font-size: 0.75rem; + color: #6c757d; + transition: transform 0.2s ease; +} + +.folder-content { + padding: 0.5rem; + background: white; +} + +.page-item { + padding: 0.5rem 0.75rem; + margin-left: 1rem; + border-radius: 6px; + transition: all 0.2s ease; +} + +.page-item:hover { + background: #f8f9fa; +} + +.page-label { + display: flex; + align-items: center; + gap: 0.5rem; + cursor: pointer; + margin: 0; + width: 100%; +} + +.page-label input[type="checkbox"] { + width: 18px; + height: 18px; + cursor: pointer; + accent-color: #007bff; +} + +.page-label input[type="checkbox"]:disabled { + cursor: not-allowed; + opacity: 0.6; +} + +.file-icon { + font-size: 1rem; + opacity: 0.7; +} + +.page-label .page-name { + flex: 1; + font-size: 0.875rem; + color: #495057; +} + +.always-access-badge { + font-size: 0.65rem; + background: linear-gradient(135deg, #28a745 0%, #20c997 100%); + color: white; + padding: 0.125rem 0.5rem; + border-radius: 10px; + font-weight: 500; +} + +/* 활성화/비활성화 버튼 스타일 */ +.action-btn.activate { + background: linear-gradient(135deg, #28a745 0%, #20c997 100%); + color: white; +} + +.action-btn.activate:hover { + background: linear-gradient(135deg, #20c997 0%, #17a2b8 100%); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(40, 167, 69, 0.3); +} + +.action-btn.deactivate { + background: linear-gradient(135deg, #6c757d 0%, #495057 100%); + color: white; +} + +.action-btn.deactivate:hover { + background: linear-gradient(135deg, #495057 0%, #343a40 100%); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(108, 117, 125, 0.3); +} + +.action-btn.danger { + background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); + color: white; +} + +.action-btn.danger:hover { + background: linear-gradient(135deg, #c82333 0%, #a71d2a 100%); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(220, 53, 69, 0.3); +} + +/* 작업자 연결 스타일 */ +.worker-link-container { + display: flex; + align-items: center; + gap: 1rem; + padding: 0.75rem; + background: #f8f9fa; + border-radius: 8px; + border: 1px solid #e9ecef; +} + +.linked-worker-info { + flex: 1; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.linked-worker-info .no-worker { + color: #6c757d; + font-style: italic; +} + +.linked-worker-info .worker-badge { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.375rem 0.75rem; + background: linear-gradient(135deg, #28a745 0%, #20c997 100%); + color: white; + border-radius: 20px; + font-size: 0.875rem; + font-weight: 500; +} + +.linked-worker-info .worker-badge .dept-name { + opacity: 0.9; + font-size: 0.75rem; +} + +/* 작업자 선택 모달 */ +.worker-select-layout { + display: grid; + grid-template-columns: 200px 1fr; + gap: 1rem; + min-height: 400px; +} + +.department-list-panel, +.worker-list-panel { + border: 1px solid #e9ecef; + border-radius: 8px; + overflow: hidden; +} + +.panel-title { + margin: 0; + padding: 0.75rem 1rem; + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + font-size: 0.875rem; + font-weight: 600; + color: #495057; + border-bottom: 1px solid #e9ecef; +} + +.department-list { + max-height: 350px; + overflow-y: auto; +} + +.department-item { + padding: 0.75rem 1rem; + cursor: pointer; + border-bottom: 1px solid #f0f0f0; + transition: all 0.2s ease; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.department-item:hover { + background: #f8f9fa; +} + +.department-item.active { + background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); + color: white; +} + +.department-item .dept-icon { + font-size: 1rem; +} + +.department-item .dept-name { + flex: 1; + font-size: 0.875rem; +} + +.department-item .dept-count { + font-size: 0.75rem; + background: rgba(0,0,0,0.1); + padding: 0.125rem 0.5rem; + border-radius: 10px; +} + +.department-item.active .dept-count { + background: rgba(255,255,255,0.2); +} + +.worker-list { + max-height: 350px; + overflow-y: auto; + padding: 0.5rem; +} + +.worker-list .empty-message { + text-align: center; + padding: 2rem; + color: #6c757d; + font-style: italic; +} + +.worker-select-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem; + border-radius: 8px; + cursor: pointer; + transition: all 0.2s ease; + border: 2px solid transparent; +} + +.worker-select-item:hover { + background: #f8f9fa; + border-color: #e9ecef; +} + +.worker-select-item.selected { + background: #e7f3ff; + border-color: #007bff; +} + +.worker-select-item .worker-avatar { + width: 40px; + height: 40px; + background: linear-gradient(135deg, #007bff 0%, #6610f2 100%); + color: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 600; + font-size: 1rem; +} + +.worker-select-item .worker-info { + flex: 1; +} + +.worker-select-item .worker-name { + font-weight: 600; + color: #1a1a1a; + font-size: 0.9rem; +} + +.worker-select-item .worker-role { + font-size: 0.75rem; + color: #6c757d; +} + +.worker-select-item .select-indicator { + width: 24px; + height: 24px; + border: 2px solid #dee2e6; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; +} + +.worker-select-item.selected .select-indicator { + background: #007bff; + border-color: #007bff; + color: white; +} + +.worker-select-item .already-linked { + font-size: 0.7rem; + background: #ffc107; + color: #000; + padding: 0.125rem 0.5rem; + border-radius: 10px; +} + +/* 버튼 크기 조정 */ +.btn-sm { + padding: 0.375rem 0.75rem; + font-size: 0.8rem; +} + +/* ======================================== + 알림 수신자 설정 섹션 + ======================================== */ +#notificationRecipientsSection { + margin-top: 2rem; +} + +#notificationRecipientsSection .section-header { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; +} + +.section-description { + font-size: 0.875rem; + color: #6c757d; + margin: 0; +} + +.notification-recipients-container { + padding: 1.5rem 2rem; +} + +.notification-type-cards { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: 1rem; +} + +.notification-type-card { + background: #f8f9fa; + border: 2px solid #e9ecef; + border-radius: 12px; + padding: 1.25rem; + transition: all 0.2s ease; +} + +.notification-type-card:hover { + border-color: #007bff; + box-shadow: 0 4px 12px rgba(0, 123, 255, 0.1); +} + +.notification-type-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.notification-type-title { + display: flex; + align-items: center; + gap: 0.5rem; + font-weight: 600; + font-size: 1rem; + color: #1a1a1a; +} + +.notification-type-icon { + font-size: 1.25rem; +} + +.notification-type-card.repair .notification-type-icon { color: #fd7e14; } +.notification-type-card.safety .notification-type-icon { color: #dc3545; } +.notification-type-card.nonconformity .notification-type-icon { color: #6f42c1; } +.notification-type-card.equipment .notification-type-icon { color: #17a2b8; } +.notification-type-card.maintenance .notification-type-icon { color: #28a745; } +.notification-type-card.system .notification-type-icon { color: #6c757d; } + +.edit-recipients-btn { + padding: 0.375rem 0.75rem; + background: white; + border: 1px solid #dee2e6; + border-radius: 6px; + font-size: 0.75rem; + color: #495057; + cursor: pointer; + transition: all 0.2s ease; +} + +.edit-recipients-btn:hover { + background: #007bff; + border-color: #007bff; + color: white; +} + +.recipient-list { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + min-height: 32px; +} + +.recipient-tag { + display: inline-flex; + align-items: center; + gap: 0.25rem; + padding: 0.25rem 0.625rem; + background: white; + border: 1px solid #dee2e6; + border-radius: 16px; + font-size: 0.75rem; + color: #495057; +} + +.recipient-tag .tag-icon { + font-size: 0.875rem; +} + +.no-recipients { + font-size: 0.8rem; + color: #adb5bd; + font-style: italic; +} + +/* 알림 수신자 편집 모달 */ +.modal-description { + font-size: 0.875rem; + color: #6c757d; + margin-bottom: 1rem; +} + +.recipient-search-box { + margin-bottom: 1rem; +} + +.recipient-user-list { + max-height: 350px; + overflow-y: auto; + border: 1px solid #e9ecef; + border-radius: 8px; + background: #f8f9fa; +} + +.recipient-user-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.75rem 1rem; + border-bottom: 1px solid #e9ecef; + cursor: pointer; + transition: all 0.15s ease; +} + +.recipient-user-item:last-child { + border-bottom: none; +} + +.recipient-user-item:hover { + background: #e9ecef; +} + +.recipient-user-item.selected { + background: #e7f3ff; +} + +.recipient-user-item input[type="checkbox"] { + width: 18px; + height: 18px; + cursor: pointer; + accent-color: #007bff; +} + +.recipient-user-item .user-avatar-small { + width: 32px; + height: 32px; + font-size: 0.8rem; +} + +.recipient-user-info { + flex: 1; +} + +.recipient-user-name { + font-weight: 500; + font-size: 0.875rem; + color: #1a1a1a; +} + +.recipient-user-role { + font-size: 0.75rem; + color: #6c757d; +} + +@media (max-width: 768px) { + .notification-type-cards { + grid-template-columns: 1fr; + } +} diff --git a/deploy/tkfb-package/web-ui/css/admin.css b/deploy/tkfb-package/web-ui/css/admin.css new file mode 100644 index 0000000..145f0a6 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/admin.css @@ -0,0 +1,50 @@ +body { + font-family: 'Malgun Gothic', sans-serif; + margin: 0; + background: #f0f2f5; +} +.main-layout { + display: flex; +} +#sidebar-container { + width: 250px; + background: #1a237e; + color: white; + min-height: 100vh; +} +#content-container { + flex: 1; + padding: 30px; +} +h1, h2 { + color: #1976d2; +} +a { + color: #1976d2; + text-decoration: none; +} + +/* Admin 권한 배지 스타일 */ +.admin-badge { + background: linear-gradient(135deg, #ff6b35 0%, #f7931e 100%); + color: white; + font-size: 0.7rem; + font-weight: bold; + padding: 2px 6px; + border-radius: 10px; + margin-left: 8px; + text-transform: uppercase; + letter-spacing: 0.5px; + box-shadow: 0 2px 4px rgba(255,107,53,0.3); + display: inline-block; + vertical-align: middle; +} + +.admin-only-link { + position: relative; +} + +.admin-only-link:hover .admin-badge { + background: linear-gradient(135deg, #ff5722 0%, #ff9800 100%); + box-shadow: 0 3px 6px rgba(255,107,53,0.4); +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/css/annual-vacation-overview.css b/deploy/tkfb-package/web-ui/css/annual-vacation-overview.css new file mode 100644 index 0000000..3d1730f --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/annual-vacation-overview.css @@ -0,0 +1,348 @@ +/** + * annual-vacation-overview.css + * 연간 연차 현황 페이지 스타일 + */ + +.page-container { + min-height: 100vh; + background: var(--color-bg-primary); +} + +.main-content { + padding: 2rem 0; +} + +.content-wrapper { + max-width: 1400px; + margin: 0 auto; + padding: 0 2rem; +} + +/* 페이지 헤더 */ +.page-header { + margin-bottom: 2rem; +} + +.page-title { + font-size: 2rem; + font-weight: 700; + color: var(--color-text-primary); + margin-bottom: 0.5rem; +} + +.page-description { + font-size: 1rem; + color: var(--color-text-secondary); + margin: 0; +} + +/* 필터 섹션 */ +.filter-section { + margin-bottom: 2rem; +} + +.filter-controls { + display: flex; + gap: 1rem; + align-items: flex-end; + flex-wrap: wrap; +} + +.form-group { + display: flex; + flex-direction: column; + gap: 0.5rem; + min-width: 200px; +} + +.form-group label { + font-size: 0.875rem; + font-weight: 600; + color: var(--color-text-primary); +} + +.form-select { + padding: 0.625rem 1rem; + border: 1px solid var(--color-border); + border-radius: 8px; + background: white; + font-size: 0.875rem; + color: var(--color-text-primary); + transition: all 0.2s; +} + +.form-select:focus { + outline: none; + border-color: var(--color-primary); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* 탭 네비게이션 */ +.tabs-section { + margin-bottom: 2rem; +} + +.tabs-nav { + display: flex; + gap: 0.5rem; + border-bottom: 2px solid var(--color-border); + padding: 0; + margin: 0; +} + +.tab-btn { + padding: 1rem 2rem; + border: none; + background: none; + color: var(--color-text-secondary); + font-size: 1rem; + font-weight: 600; + cursor: pointer; + position: relative; + transition: all 0.2s; + border-radius: 8px 8px 0 0; +} + +.tab-btn:hover { + color: var(--color-primary); + background: rgba(59, 130, 246, 0.05); +} + +.tab-btn.active { + color: var(--color-primary); + background: white; +} + +.tab-btn.active::after { + content: ''; + position: absolute; + bottom: -2px; + left: 0; + right: 0; + height: 2px; + background: var(--color-primary); +} + +/* 탭 컨텐츠 */ +.tab-content { + display: none; +} + +.tab-content.active { + display: block; +} + +/* 월 선택 컨트롤 */ +.month-controls { + display: flex; + gap: 1rem; + align-items: center; +} + +.month-controls .form-select { + min-width: 120px; +} + +/* 차트 섹션 */ +.chart-section { + margin-bottom: 2rem; +} + +.card-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1.5rem; + border-bottom: 1px solid var(--color-border); +} + +.card-title { + font-size: 1.25rem; + font-weight: 600; + color: var(--color-text-primary); + margin: 0; +} + +.chart-controls { + display: flex; + gap: 0.5rem; +} + +.btn-outline { + background: white; + border: 1px solid var(--color-border); + color: var(--color-text-secondary); +} + +.btn-outline:hover { + background: var(--color-bg-secondary); + border-color: var(--color-primary); + color: var(--color-primary); +} + +.btn-outline.active { + background: var(--color-primary); + border-color: var(--color-primary); + color: white; +} + +.chart-container { + position: relative; + height: 500px; + padding: 1.5rem; +} + +/* 테이블 섹션 */ +.table-section { + margin-bottom: 2rem; +} + +.table-responsive { + overflow-x: auto; +} + +.data-table { + width: 100%; + border-collapse: collapse; + font-size: 0.875rem; +} + +.data-table thead { + background: var(--color-bg-secondary); +} + +.data-table th { + padding: 1rem; + text-align: left; + font-weight: 600; + color: var(--color-text-primary); + border-bottom: 2px solid var(--color-border); + white-space: nowrap; +} + +.data-table tbody tr { + border-bottom: 1px solid var(--color-border); + transition: background 0.2s; +} + +.data-table tbody tr:hover { + background: var(--color-bg-secondary); +} + +.data-table td { + padding: 1rem; + color: var(--color-text-primary); +} + +.loading-state { + padding: 3rem 1rem !important; + text-align: center; +} + +.loading-state .spinner { + margin: 0 auto 1rem; + width: 40px; + height: 40px; + border: 4px solid var(--color-border); + border-top-color: var(--color-primary); + border-radius: 50%; + animation: spin 1s linear infinite; +} + +.loading-state p { + margin: 0; + color: var(--color-text-secondary); +} + +@keyframes spin { + to { + transform: rotate(360deg); + } +} + +/* 사용률 프로그레스 바 */ +.usage-rate-cell { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.progress-bar { + flex: 1; + height: 8px; + background: var(--color-bg-secondary); + border-radius: 4px; + overflow: hidden; +} + +.progress-fill { + height: 100%; + border-radius: 4px; + transition: width 0.3s ease; +} + +.progress-fill.low { + background: linear-gradient(90deg, #10b981 0%, #059669 100%); +} + +.progress-fill.medium { + background: linear-gradient(90deg, #f59e0b 0%, #d97706 100%); +} + +.progress-fill.high { + background: linear-gradient(90deg, #ef4444 0%, #dc2626 100%); +} + +.usage-rate-text { + font-weight: 600; + min-width: 45px; + text-align: right; +} + +/* 반응형 */ +@media (max-width: 768px) { + .content-wrapper { + padding: 0 1rem; + } + + .page-title { + font-size: 1.5rem; + } + + .tabs-nav { + flex-direction: column; + gap: 0; + } + + .tab-btn { + border-radius: 0; + } + + .filter-controls { + flex-direction: column; + align-items: stretch; + } + + .form-group { + width: 100%; + min-width: auto; + } + + .chart-container { + height: 400px; + } + + .card-header { + flex-direction: column; + gap: 1rem; + align-items: flex-start; + } + + .chart-controls { + width: 100%; + } + + .chart-controls button { + flex: 1; + } +} diff --git a/deploy/tkfb-package/web-ui/css/attendance-validation.css b/deploy/tkfb-package/web-ui/css/attendance-validation.css new file mode 100644 index 0000000..15184a3 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/attendance-validation.css @@ -0,0 +1,883 @@ +/* 근태 검증 관리 시스템 - 개선된 스타일 */ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; + background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%); + color: #333; + line-height: 1.6; + min-height: 100vh; +} + +/* 뒤로가기 버튼 */ +.back-btn { + background: rgba(255,255,255,0.95); + color: #667eea; + border: 3px solid #667eea; + padding: 12px 24px; + border-radius: 12px; + text-decoration: none; + font-weight: 700; + font-size: 16px; + display: inline-flex; + align-items: center; + gap: 8px; + margin-bottom: 24px; + transition: all 0.3s ease; + box-shadow: 0 3px 12px rgba(102, 126, 234, 0.2); +} + +.back-btn:hover { + background: #667eea; + color: white; + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3); +} + +/* 페이지 헤더 */ +.page-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + border-radius: 16px; + padding: 2.5rem; + margin-bottom: 2rem; + box-shadow: 0 8px 32px rgba(102, 126, 234, 0.3); + border: 1px solid rgba(255, 255, 255, 0.1); +} + +/* 메인 카드 */ +.main-card { + background: white; + border-radius: 16px; + padding: 2rem; + margin-bottom: 2rem; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + border: 1px solid rgba(255, 255, 255, 0.8); + backdrop-filter: blur(10px); + transition: all 0.3s ease; +} + +.main-card:hover { + transform: translateY(-2px); + box-shadow: 0 12px 40px rgba(0, 0, 0, 0.15); +} + +.loading-card { + background: white; + border-radius: 16px; + padding: 3rem; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1); + text-align: center; +} + +/* 캘린더 헤더 */ +.calendar-header { + display: flex; + align-items: center; + justify-content: between; + margin-bottom: 2rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f0f0f0; +} + +.nav-btn { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border: none; + border-radius: 12px; + width: 48px; + height: 48px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(102, 126, 234, 0.3); +} + +.nav-btn:hover { + transform: translateY(-2px) scale(1.05); + box-shadow: 0 6px 24px rgba(102, 126, 234, 0.4); +} + +/* 월간 요약 */ +.summary-section { + margin-bottom: 2rem; + padding: 1.5rem; + background: linear-gradient(135deg, rgba(102, 126, 234, 0.1) 0%, rgba(118, 75, 162, 0.1) 100%); + border-radius: 16px; + border: 1px solid rgba(102, 126, 234, 0.2); +} + +.summary-title { + text-align: center; + font-size: 1.25rem; + font-weight: 700; + color: #333; + margin-bottom: 1rem; +} + +.summary-grid { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: 1.5rem; +} + +.summary-card { + background: white; + border-radius: 12px; + padding: 1.5rem; + text-align: center; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); + border: 2px solid transparent; +} + +.summary-card:hover { + transform: translateY(-4px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.summary-card.normal { + border-color: #10b981; +} + +.summary-card.warning { + border-color: #f59e0b; +} + +.summary-card.error { + border-color: #ef4444; +} + +.summary-number { + font-size: 2rem; + font-weight: 800; + margin-bottom: 0.5rem; +} + +.summary-card.normal .summary-number { + color: #10b981; +} + +.summary-card.warning .summary-number { + color: #f59e0b; +} + +.summary-card.error .summary-number { + color: #ef4444; +} + +.summary-label { + font-size: 0.875rem; + font-weight: 600; + color: #666; +} + +/* 요일 헤더 */ +.weekday-header { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 0.5rem; + margin-bottom: 1rem; +} + +.weekday { + padding: 1rem; + text-align: center; + font-size: 0.875rem; + font-weight: 700; + color: #64748b; + background: #f8fafc; + border-radius: 8px; +} + +.weekday.sunday { + color: #ef4444; +} + +.weekday.saturday { + color: #3b82f6; +} + +/* 캘린더 그리드 */ +.calendar-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + gap: 0.5rem; + margin-bottom: 2rem; +} + +.calendar-day { + position: relative; + min-height: 80px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 12px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + background: white; + border: 2px solid #e2e8f0; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.calendar-day.hover-enabled:hover { + transform: translateY(-3px); + box-shadow: 0 6px 24px rgba(0, 0, 0, 0.15); + border-color: #3b82f6; +} + +.calendar-day.selected { + transform: scale(1.05); + z-index: 10; + border-color: #3b82f6; + box-shadow: 0 8px 32px rgba(59, 130, 246, 0.3); +} + +.calendar-day.loading-state { + background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%); + border-color: #3b82f6; + animation: loading-pulse 1.5s infinite; +} + +@keyframes loading-pulse { + 0%, 100% { opacity: 1; } + 50% { opacity: 0.7; } +} + +.calendar-day.error-state { + background: linear-gradient(135deg, #fecaca 0%, #fca5a5 100%); + border-color: #ef4444; + color: #991b1b; +} + +.calendar-day.normal { + background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%); + border-color: #10b981; + color: #064e3b; +} + +.calendar-day.needs-review { + background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); + border-color: #f59e0b; + color: #92400e; +} + +.calendar-day.missing { + background: linear-gradient(135deg, #fecaca 0%, #fca5a5 100%); + border-color: #ef4444; + color: #991b1b; +} + +.calendar-day.no-data { + background: #f9fafb; + border-color: #e5e7eb; + color: #9ca3af; + position: relative; +} + +.calendar-day.no-data::after { + content: "클릭하여 확인"; + position: absolute; + bottom: 4px; + font-size: 10px; + color: #6b7280; + opacity: 0; + transition: opacity 0.3s; +} + +.calendar-day.no-data.hover-enabled:hover::after { + opacity: 1; +} + +.status-dot { + position: absolute; + top: 8px; + right: 8px; + width: 12px; + height: 12px; + border-radius: 50%; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); + transition: all 0.3s ease; +} + +.status-dot.pulse { + animation: pulse 1s infinite; +} + +@keyframes pulse { + 0%, 100% { transform: scale(1); } + 50% { transform: scale(1.2); } +} + +.status-dot.normal { + background: #10b981; +} + +.status-dot.warning { + background: #f59e0b; +} + +.status-dot.error { + background: #ef4444; +} + +/* 범례 */ +.legend { + display: flex; + justify-content: center; + gap: 2rem; + flex-wrap: wrap; +} + +.legend-item { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.875rem; + font-weight: 600; + color: #64748b; +} + +.legend-dot { + width: 16px; + height: 16px; + border-radius: 50%; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); +} + +.legend-dot.normal { + background: #10b981; +} + +.legend-dot.warning { + background: #f59e0b; +} + +.legend-dot.error { + background: #ef4444; +} + +/* 빈 상태 */ +.empty-state { + text-align: center; + padding: 4rem 2rem; +} + +.empty-icon { + font-size: 4rem; + margin-bottom: 1.5rem; +} + +.empty-title { + font-size: 1.5rem; + font-weight: 700; + color: #374151; + margin-bottom: 1rem; +} + +.empty-description { + color: #6b7280; + font-size: 1rem; + max-width: 500px; + margin: 0 auto; +} + +/* 작업자 카드 */ +.worker-card { + background: white; + border-radius: 16px; + padding: 1.5rem; + margin-bottom: 1.5rem; + border: 2px solid transparent; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); +} + +.worker-card:hover { + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.15); +} + +.worker-card.normal { + background: linear-gradient(135deg, #ecfdf5 0%, #d1fae5 100%); + border-color: #10b981; +} + +.worker-card.needs-review { + background: linear-gradient(135deg, #fffbeb 0%, #fef3c7 100%); + border-color: #f59e0b; +} + +.worker-card.missing { + background: linear-gradient(135deg, #fef2f2 0%, #fecaca 100%); + border-color: #ef4444; +} + +.worker-header { + display: flex; + justify-content: between; + align-items: center; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid rgba(0, 0, 0, 0.1); +} + +.worker-info { + display: flex; + align-items: center; + gap: 1rem; +} + +.worker-avatar { + width: 48px; + height: 48px; + background: white; + border-radius: 50%; + display: flex; + align-items: center; + justify-content: center; + font-weight: 700; + font-size: 1.25rem; + color: #374151; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); +} + +.worker-name { + font-size: 1.25rem; + font-weight: 700; + color: #374151; +} + +.worker-id { + font-size: 0.875rem; + color: #6b7280; + margin-top: 0.25rem; +} + +.status-badge { + font-size: 1.5rem; + filter: drop-shadow(2px 2px 4px rgba(0, 0, 0, 0.1)); +} + +/* 데이터 행 */ +.data-section { + background: rgba(255, 255, 255, 0.7); + border-radius: 12px; + padding: 1.5rem; + margin-bottom: 1rem; +} + +.data-row { + display: flex; + justify-content: between; + align-items: center; + padding: 0.75rem 0; + border-bottom: 1px solid rgba(0, 0, 0, 0.05); +} + +.data-row:last-child { + border-bottom: none; +} + +.data-label { + font-weight: 600; + color: #4b5563; +} + +.data-value { + font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', monospace; + font-weight: 700; + font-size: 1rem; +} + +.difference-positive { + color: #dc2626; + background: rgba(220, 38, 38, 0.1); + padding: 0.25rem 0.75rem; + border-radius: 6px; + font-weight: 700; +} + +.difference-negative { + color: #2563eb; + background: rgba(37, 99, 235, 0.1); + padding: 0.25rem 0.75rem; + border-radius: 6px; + font-weight: 700; +} + +/* 버튼 */ +.btn-primary { + background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 12px; + font-weight: 700; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(59, 130, 246, 0.3); + display: inline-flex; + align-items: center; + gap: 0.5rem; +} + +.btn-primary:hover { + transform: translateY(-2px); + box-shadow: 0 6px 24px rgba(59, 130, 246, 0.4); +} + +.btn-secondary { + background: #6b7280; + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 12px; + font-weight: 700; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 16px rgba(107, 114, 128, 0.3); +} + +.btn-secondary:hover { + background: #4b5563; + transform: translateY(-2px); +} + +.edit-btn { + background: linear-gradient(135deg, #3b82f6 0%, #1d4ed8 100%); + color: white; + border: none; + padding: 0.75rem 1.5rem; + border-radius: 8px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + font-size: 0.875rem; + width: 100%; + margin-top: 1rem; +} + +.edit-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(59, 130, 246, 0.3); +} + +.delete-btn { + background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%); + color: white; + border: none; + padding: 0.5rem 1rem; + border-radius: 6px; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + font-size: 0.75rem; + margin-left: 0.5rem; +} + +.delete-btn:hover { + transform: translateY(-1px); + box-shadow: 0 4px 16px rgba(239, 68, 68, 0.3); +} + +/* 필터 */ +.filter-container { + display: flex; + justify-content: between; + align-items: center; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f0f0f0; +} + +.filter-select { + background: white; + border: 2px solid #e5e7eb; + border-radius: 8px; + padding: 0.75rem 1rem; + font-weight: 600; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05); +} + +.filter-select:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* 모달 */ +.modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.75); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + animation: fadeIn 0.3s ease; +} + +.modal.hidden { + display: none; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +.modal-content { + background: white; + border-radius: 20px; + width: 90%; + max-width: 500px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); + animation: slideIn 0.3s ease; +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-50px) scale(0.9); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.modal-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 1.5rem; + border-radius: 20px 20px 0 0; + display: flex; + justify-content: between; + align-items: center; +} + +.modal-header h3 { + margin: 0; + font-size: 1.25rem; + font-weight: 700; +} + +.close-btn { + background: rgba(255, 255, 255, 0.2); + color: white; + border: none; + border-radius: 50%; + width: 36px; + height: 36px; + cursor: pointer; + font-size: 1.25rem; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s ease; +} + +.close-btn:hover { + background: rgba(255, 255, 255, 0.3); + transform: rotate(90deg); +} + +.modal-body { + padding: 1.5rem; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 1rem; + padding: 1.5rem; + border-top: 2px solid #f0f0f0; + background: #f8fafc; + border-radius: 0 0 20px 20px; +} + +/* 폼 요소 */ +.form-group { + margin-bottom: 1.5rem; +} + +.form-group label { + display: block; + margin-bottom: 0.5rem; + font-weight: 700; + color: #374151; + font-size: 0.875rem; +} + +.form-input { + width: 100%; + padding: 0.75rem 1rem; + border: 2px solid #e5e7eb; + border-radius: 8px; + font-size: 1rem; + transition: all 0.3s ease; +} + +.form-input:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.form-textarea { + width: 100%; + padding: 0.75rem 1rem; + border: 2px solid #e5e7eb; + border-radius: 8px; + font-size: 1rem; + resize: vertical; + min-height: 80px; + transition: all 0.3s ease; +} + +.form-textarea:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* 메시지 */ +.message { + padding: 1rem 1.5rem; + border-radius: 12px; + margin-bottom: 1.5rem; + font-weight: 600; + border: 2px solid transparent; + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.1); +} + +.message.success { + background: linear-gradient(135deg, #d1fae5 0%, #a7f3d0 100%); + color: #065f46; + border-color: #10b981; +} + +.message.error { + background: linear-gradient(135deg, #fecaca 0%, #fca5a5 100%); + color: #991b1b; + border-color: #ef4444; +} + +.message.warning { + background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); + color: #92400e; + border-color: #f59e0b; +} + +.message.loading { + background: linear-gradient(135deg, #dbeafe 0%, #bfdbfe 100%); + color: #1e40af; + border-color: #3b82f6; +} + +/* 로딩 스피너 */ +.loading-spinner { + width: 32px; + height: 32px; + border: 3px solid #e5e7eb; + border-top: 3px solid #3b82f6; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + from { transform: rotate(0deg); } + to { transform: rotate(360deg); } +} + +/* 애니메이션 */ +.fade-in { + animation: fadeInUp 0.5s ease-out; +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* 반응형 디자인 */ +@media (max-width: 768px) { + .summary-grid { + grid-template-columns: 1fr; + gap: 1rem; + } + + .calendar-day { + min-height: 60px; + font-size: 0.875rem; + } + + .worker-header { + flex-direction: column; + gap: 1rem; + text-align: center; + } + + .legend { + flex-direction: column; + gap: 1rem; + } + + .modal-content { + width: 95%; + margin: 1rem; + } + + .main-card { + padding: 1.5rem; + } + + .page-header { + padding: 2rem; + } +} + +@media (max-width: 480px) { + .calendar-day { + min-height: 50px; + font-size: 0.75rem; + } + + .summary-card { + padding: 1rem; + } + + .summary-number { + font-size: 1.5rem; + } + + .worker-card { + padding: 1rem; + } + + .modal-body, .modal-footer { + padding: 1rem; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/css/attendance.css b/deploy/tkfb-package/web-ui/css/attendance.css new file mode 100644 index 0000000..0b77e15 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/attendance.css @@ -0,0 +1,72 @@ +body { + font-family: Arial, sans-serif; + margin: 20px; + background: #f8f9fa; +} +h2 { + text-align: center; + color: #343a40; +} +.controls { + display: flex; + flex-wrap: wrap; + gap: 12px; + justify-content: center; + align-items: center; + margin-bottom: 16px; +} +.controls label { + font-weight: bold; +} +.controls select, +.controls button { + padding: 6px 10px; + border-radius: 4px; + border: 1px solid #ccc; + font-weight: bold; + cursor: pointer; +} +button#loadAttendance { + background-color: #4CAF50; + color: white; + border: none; +} +button#downloadPdf { + background-color: #007BFF; + color: white; + border: none; +} +#attendanceTableContainer { + max-height: 600px; + overflow: auto; +} +table { + width: 100%; + border-collapse: collapse; + margin-top: 10px; + font-size: 14px; +} +th, td { + border: 1px solid #ddd; + padding: 6px; + text-align: center; + background: white; +} +th { + background: #f2f2f2; +} +.divider { + border-left: 3px solid #333 !important; +} +tr.separator td { + border-bottom: 2px solid #999; + padding: 0; + height: 4px; + background: transparent; +} +.overtime-cell { background: #e9e5ff !important; } +.leave { background: #f5e0d6 !important; } +.holiday { background: #ffd6d6 !important; } +.paid-leave { background: #d6f0ff !important; } +.no-data { background: #ddd !important; } +.overtime-sum { background: #e9e5ff !important; } \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/css/common.css b/deploy/tkfb-package/web-ui/css/common.css new file mode 100644 index 0000000..eb1a24c --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/common.css @@ -0,0 +1,300 @@ +/* Common CSS - 공통 스타일 */ + +/* ========== 통일된 헤더 스타일 ========== */ +.work-report-container { + min-height: 100vh; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; +} + +.work-report-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + text-align: center; + padding: 2rem 1.5rem; + margin-bottom: 0; +} + +.work-report-header h1 { + font-size: clamp(1.5rem, 4vw, 2.5rem); + font-weight: 700; + margin: 0 0 0.75rem 0; + text-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.3); + word-wrap: break-word; + overflow-wrap: break-word; +} + +.work-report-header .subtitle { + font-size: clamp(0.875rem, 2vw, 1.1rem); + opacity: 0.9; + margin: 0; + font-weight: 300; + word-wrap: break-word; + overflow-wrap: break-word; + max-width: 90%; + margin-left: auto; + margin-right: auto; +} + +.work-report-main { + background: #f8f9fa; + min-height: calc(100vh - 12rem); + padding-top: 2rem; +} + +.back-button { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.75rem 1.5rem; + background: rgba(255, 255, 255, 0.9); + color: #495057; + text-decoration: none; + border-radius: 0.5rem; + font-weight: 500; + margin: 0 1.5rem 1.5rem 1.5rem; + transition: all 0.3s ease; + box-shadow: 0 0.125rem 0.25rem rgba(0,0,0,0.1); + white-space: nowrap; +} + +.back-button:hover { + background: white; + color: #007bff; + transform: translateY(-0.0625rem); + box-shadow: 0 0.25rem 0.5rem rgba(0,0,0,0.15); +} + +/* 반응형 헤더 */ +@media (max-width: 768px) { + .work-report-header { + padding: 1.5rem 1rem; + } + + .work-report-header h1 { + margin-bottom: 0.5rem; + } + + .back-button { + margin: 0 1rem 1rem 1rem; + padding: 0.625rem 1.25rem; + font-size: 0.875rem; + } +} + +@media (max-width: 480px) { + .work-report-header { + padding: 1.25rem 0.75rem; + } + + .work-report-header .subtitle { + font-size: 0.8125rem; + } + + .back-button { + margin: 0 0.75rem 0.75rem 0.75rem; + padding: 0.5rem 1rem; + font-size: 0.8125rem; + } +} + +/* Reset and Base Styles */ +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif; + line-height: 1.6; + color: #333; + background-color: #f8fafc; +} + +/* Typography */ +h1, h2, h3, h4, h5, h6 { + font-weight: 600; + line-height: 1.25; + margin-bottom: 0.5rem; +} + +h1 { font-size: 2rem; } +h2 { font-size: 1.5rem; } +h3 { font-size: 1.25rem; } +h4 { font-size: 1.125rem; } +h5 { font-size: 1rem; } +h6 { font-size: 0.875rem; } + +/* ========== 헤더 액션 버튼 ========== */ +.header-actions { + display: flex; + align-items: center; + gap: 1rem; + margin-right: 1rem; +} + +.dashboard-btn { + display: inline-flex; + align-items: center; + gap: 0.5rem; + padding: 0.6rem 1.2rem; + background: rgba(255, 255, 255, 0.15); + color: white; + border: 1px solid rgba(255, 255, 255, 0.3); + border-radius: 8px; + font-size: 0.9rem; + font-weight: 500; + text-decoration: none; + cursor: pointer; + transition: all 0.3s ease; + backdrop-filter: blur(10px); +} + +.dashboard-btn:hover { + background: rgba(255, 255, 255, 0.25); + border-color: rgba(255, 255, 255, 0.5); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0,0,0,0.15); +} + +.dashboard-btn .btn-icon { + font-size: 1rem; +} + +/* Buttons */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + padding: 0.5rem 1rem; + border: none; + border-radius: 0.375rem; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: all 0.2s ease; + text-decoration: none; +} + +.btn-primary { + background-color: #3b82f6; + color: white; +} + +.btn-primary:hover { + background-color: #2563eb; +} + +.btn-secondary { + background-color: #6b7280; + color: white; +} + +.btn-secondary:hover { + background-color: #4b5563; +} + +/* Utilities */ +.text-center { text-align: center; } +.text-left { text-align: left; } +.text-right { text-align: right; } + +.mb-1 { margin-bottom: 0.25rem; } +.mb-2 { margin-bottom: 0.5rem; } +.mb-3 { margin-bottom: 0.75rem; } +.mb-4 { margin-bottom: 1rem; } +.mb-5 { margin-bottom: 1.25rem; } +.mb-6 { margin-bottom: 1.5rem; } + +.mt-1 { margin-top: 0.25rem; } +.mt-2 { margin-top: 0.5rem; } +.mt-3 { margin-top: 0.75rem; } +.mt-4 { margin-top: 1rem; } +.mt-5 { margin-top: 1.25rem; } +.mt-6 { margin-top: 1.5rem; } + +.p-1 { padding: 0.25rem; } +.p-2 { padding: 0.5rem; } +.p-3 { padding: 0.75rem; } +.p-4 { padding: 1rem; } +.p-5 { padding: 1.25rem; } +.p-6 { padding: 1.5rem; } + +/* Container */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 0 1rem; +} + +/* Cards */ +.card { + background: white; + border-radius: 0.5rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + border: 1px solid #e5e7eb; +} + +.card-header { + padding: 1rem; + border-bottom: 1px solid #e5e7eb; +} + +.card-body { + padding: 1rem; +} + +/* Forms */ +.form-group { + margin-bottom: 1rem; +} + +.form-label { + display: block; + font-weight: 500; + margin-bottom: 0.25rem; + color: #374151; +} + +.form-control { + width: 100%; + padding: 0.5rem 0.75rem; + border: 1px solid #d1d5db; + border-radius: 0.375rem; + font-size: 0.875rem; + transition: border-color 0.2s ease; +} + +.form-control:focus { + outline: none; + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* Loading */ +.loading { + display: inline-block; + width: 20px; + height: 20px; + border: 3px solid #f3f3f3; + border-top: 3px solid #3b82f6; + border-radius: 50%; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +/* Responsive */ +@media (max-width: 768px) { + .container { + padding: 0 0.5rem; + } + + h1 { font-size: 1.5rem; } + h2 { font-size: 1.25rem; } + h3 { font-size: 1.125rem; } +} diff --git a/deploy/tkfb-package/web-ui/css/daily-issue.css b/deploy/tkfb-package/web-ui/css/daily-issue.css new file mode 100644 index 0000000..827e7c7 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/daily-issue.css @@ -0,0 +1,90 @@ +/* /css/daily-issue.css */ + +body { + font-family: Arial, sans-serif; + background: #f5f7fa; + margin: 0; + padding: 40px 20px; +} + +.container { + max-width: 500px; + margin: auto; + background: #fff; + border-radius: 12px; + box-shadow: 0 0 10px rgba(0,0,0,0.05); + padding: 32px; +} + +h2 { + text-align: center; + color: #333; + margin-bottom: 24px; +} + +label { + display: block; + margin-top: 20px; + font-weight: bold; + color: #333; +} + +select, input[type="date"], button { + width: 100%; + padding: 10px; + margin-top: 6px; + border: 1px solid #ccc; + border-radius: 6px; + box-sizing: border-box; + font-size: 1rem; +} + +button#submitBtn { + margin-top: 30px; + background: #1976d2; + color: white; + border: none; + font-size: 1rem; + border-radius: 6px; + cursor: pointer; + transition: background 0.2s; +} + +button#submitBtn:hover { + background: #125cb1; +} + +.multi-select-box { + display: flex; + flex-wrap: wrap; + gap: 8px; + margin-top: 8px; +} + +.multi-select-box .btn { + flex: 1 0 30%; + padding: 8px; + border: 1px solid #1976d2; + border-radius: 4px; + background: white; + color: #1976d2; + text-align: center; + cursor: pointer; + transition: background 0.2s, color 0.2s; +} + +.multi-select-box .btn.selected { + background: #1976d2; + color: white; +} + +.time-range { + display: flex; + gap: 8px; + align-items: center; + margin-top: 6px; +} + +.time-range select { + flex: 1; +} diff --git a/deploy/tkfb-package/web-ui/css/daily-patrol.css b/deploy/tkfb-package/web-ui/css/daily-patrol.css new file mode 100644 index 0000000..c6ade28 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/daily-patrol.css @@ -0,0 +1,1303 @@ +/* daily-patrol.css - 일일순회점검 페이지 스타일 */ + +/* 점검 시작 영역 */ +.patrol-start-section { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 2rem; + padding: 3rem 1.5rem; + background: var(--surface-color, #fff); + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + margin-bottom: 1.5rem; +} + +.patrol-start-section .btn-lg { + padding: 1.25rem 3rem; + font-size: 1.25rem; + border-radius: 12px; + display: flex; + align-items: center; + gap: 0.75rem; +} + +.patrol-start-section .btn-icon { + font-size: 1.5rem; +} + +/* 공장 선택 영역 */ +.factory-selection-area { + padding: 2rem; + background: var(--surface-color, #fff); + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + margin-bottom: 1.5rem; +} + +.factory-selection-header { + text-align: center; + margin-bottom: 2rem; +} + +.factory-selection-header h3 { + font-size: 1.5rem; + font-weight: 600; + margin: 0 0 0.5rem; +} + +.factory-selection-subtitle { + color: var(--text-secondary, #64748b); + margin: 0; +} + +.factory-cards-container { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 1.5rem; + max-width: 800px; + margin: 0 auto; +} + +.factory-card { + display: flex; + flex-direction: column; + align-items: center; + padding: 2rem 1.5rem; + background: var(--bg-color, #f8fafc); + border: 2px solid var(--border-color, #e2e8f0); + border-radius: 16px; + cursor: pointer; + transition: all 0.2s; +} + +.factory-card:hover { + border-color: var(--primary-color, #3b82f6); + background: #eff6ff; + transform: translateY(-4px); + box-shadow: 0 8px 20px rgba(59, 130, 246, 0.15); +} + +.factory-card:active { + transform: translateY(-2px); +} + +.factory-card-icon { + width: 80px; + height: 80px; + border-radius: 12px; + background: var(--surface-color, #fff); + display: flex; + align-items: center; + justify-content: center; + margin-bottom: 1rem; + overflow: hidden; + font-size: 2.5rem; +} + +.factory-card-icon img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.factory-card-name { + font-size: 1.125rem; + font-weight: 600; + text-align: center; +} + +/* 오늘 점검 현황 요약 */ +.today-status-summary { + display: flex; + gap: 1.5rem; + align-items: center; + justify-content: center; + padding: 1rem 2rem; + background: var(--bg-color, #f8fafc); + border-radius: 12px; +} + +.status-card { + text-align: center; + padding: 1rem 1.5rem; + background: var(--surface-color, #fff); + border-radius: 8px; + min-width: 100px; +} + +.status-label { + font-size: 0.85rem; + color: var(--text-secondary, #64748b); + margin-bottom: 0.5rem; +} + +.status-value { + font-size: 1.5rem; + font-weight: 700; +} + +.status-value.completed { + color: var(--success-color, #16a34a); +} + +.status-value.pending { + color: var(--warning-color, #f59e0b); +} + +.status-sub { + font-size: 0.75rem; + color: var(--text-secondary, #64748b); + margin-top: 0.25rem; +} + +/* 점검 영역 */ +.patrol-area { + background: var(--surface-color, #fff); + border-radius: 12px; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); + overflow: hidden; +} + +/* 세션 정보 바 */ +.session-info-bar { + display: flex; + justify-content: space-between; + align-items: center; + padding: 1rem 1.5rem; + background: linear-gradient(135deg, var(--primary-color, #3b82f6), #2563eb); + color: #fff; +} + +.session-info { + display: flex; + gap: 2rem; +} + +.session-info-item { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.session-info-label { + font-size: 0.75rem; + opacity: 0.8; +} + +.session-info-value { + font-weight: 600; +} + +.session-progress { + display: flex; + align-items: center; + gap: 1rem; +} + +.progress-bar { + width: 150px; + height: 8px; + background: rgba(255, 255, 255, 0.3); + border-radius: 4px; + overflow: hidden; +} + +.progress-fill { + height: 100%; + background: #fff; + border-radius: 4px; + transition: width 0.3s ease; +} + +.progress-text { + font-weight: 600; + font-size: 0.9rem; +} + +/* 점검 콘텐츠 영역 */ +.patrol-content { + display: grid; + grid-template-columns: 1fr 400px; + min-height: 500px; +} + +@media (max-width: 1024px) { + .patrol-content { + grid-template-columns: 1fr; + } +} + +/* 지도 영역 */ +.patrol-map-section { + padding: 1.5rem; + border-right: 1px solid var(--border-color, #e2e8f0); +} + +.map-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.map-header h3 { + font-size: 1rem; + font-weight: 600; + margin: 0; +} + +.map-legend { + display: flex; + gap: 1rem; + font-size: 0.8rem; +} + +.legend-item { + display: flex; + align-items: center; + gap: 0.25rem; +} + +.legend-item .dot { + width: 10px; + height: 10px; + border-radius: 50%; +} + +.legend-item.completed .dot { + background: var(--success-color, #16a34a); +} + +.legend-item.in-progress .dot { + background: var(--primary-color, #3b82f6); +} + +.legend-item.pending .dot { + background: var(--border-color, #cbd5e1); +} + +/* 지도 컨테이너 */ +.patrol-map-container { + position: relative; + width: 100%; + aspect-ratio: 16/10; + background: var(--bg-color, #f8fafc); + border-radius: 8px; + overflow: hidden; + border: 1px solid var(--border-color, #e2e8f0); +} + +.patrol-map-container img { + width: 100%; + height: 100%; + object-fit: contain; +} + +/* 작업장 마커 */ +.workplace-marker { + position: absolute; + padding: 0.3rem 0.5rem; + background: var(--surface-color, #fff); + border: 2px solid var(--border-color, #cbd5e1); + border-radius: 6px; + cursor: pointer; + font-size: 0.7rem; + font-weight: 600; + box-shadow: 0 2px 6px rgba(0, 0, 0, 0.12); + transition: all 0.15s ease-out; + transform: translate(-50%, -50%); + white-space: nowrap; + /* z-index는 JS에서 y좌표 기반 설정 (아래에 있을수록 높음) */ +} + +.workplace-marker:hover { + transform: translate(-50%, -50%) scale(1.15); + box-shadow: 0 6px 16px rgba(0, 0, 0, 0.25); + z-index: 200 !important; + background: #f0f9ff; + border-color: var(--primary-color, #3b82f6); +} + +.workplace-marker.completed { + border-color: var(--success-color, #16a34a); + background: #dcfce7; +} + +.workplace-marker.in-progress { + border-color: var(--primary-color, #3b82f6); + background: #dbeafe; +} + +.workplace-marker.selected { + border-color: var(--primary-color, #3b82f6); + background: var(--primary-color, #3b82f6); + color: #fff; + z-index: 150 !important; + transform: translate(-50%, -50%) scale(1.1); +} + +/* 작은 마커 (밀집 구역용) */ +.workplace-marker.compact { + padding: 0.2rem 0.35rem; + font-size: 0.6rem; + border-radius: 4px; + border-width: 1.5px; +} + +/* 작업장 목록 */ +.workplace-list-container { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); + gap: 0.75rem; + margin-top: 1rem; + padding: 0.5rem; + background: var(--bg-color, #f8fafc); + border-radius: 8px; +} + +.workplace-card { + padding: 1rem; + background: var(--surface-color, #fff); + border: 2px solid var(--border-color, #e2e8f0); + border-radius: 8px; + cursor: pointer; + transition: all 0.2s; + text-align: center; +} + +.workplace-card:hover { + border-color: var(--primary-color, #3b82f6); +} + +.workplace-card.completed { + border-color: var(--success-color, #16a34a); + background: #f0fdf4; +} + +.workplace-card.in-progress { + border-color: var(--primary-color, #3b82f6); + background: #eff6ff; +} + +.workplace-card.selected { + border-color: var(--primary-color, #3b82f6); + background: var(--primary-color, #3b82f6); + color: #fff; +} + +.workplace-card.selected .workplace-card-status { + color: rgba(255, 255, 255, 0.8); +} + +.workplace-card-name { + font-weight: 600; + margin-bottom: 0.25rem; +} + +.workplace-card-status { + font-size: 0.75rem; + color: var(--text-secondary, #64748b); +} + +/* 체크리스트 영역 */ +.patrol-checklist-section { + display: flex; + flex-direction: column; + background: var(--bg-color, #f8fafc); +} + +.checklist-header { + padding: 1rem 1.5rem; + border-bottom: 1px solid var(--border-color, #e2e8f0); + background: var(--surface-color, #fff); +} + +.checklist-header h3 { + font-size: 1rem; + font-weight: 600; + margin: 0 0 0.25rem; +} + +.checklist-subtitle { + font-size: 0.8rem; + color: var(--text-secondary, #64748b); + margin: 0; +} + +.checklist-content { + flex: 1; + overflow-y: auto; + padding: 1rem; +} + +.checklist-placeholder { + display: flex; + align-items: center; + justify-content: center; + height: 200px; + color: var(--text-secondary, #64748b); +} + +/* 체크리스트 카테고리 */ +.checklist-category { + margin-bottom: 1.5rem; +} + +.checklist-category-title { + font-size: 0.85rem; + font-weight: 600; + color: var(--text-secondary, #64748b); + text-transform: uppercase; + margin-bottom: 0.75rem; + padding-bottom: 0.5rem; + border-bottom: 1px solid var(--border-color, #e2e8f0); +} + +/* 체크 항목 */ +.check-item { + display: flex; + align-items: flex-start; + gap: 0.75rem; + padding: 0.75rem; + background: var(--surface-color, #fff); + border-radius: 8px; + margin-bottom: 0.5rem; + cursor: pointer; + transition: background 0.2s; +} + +.check-item:hover { + background: #f1f5f9; +} + +.check-item.checked { + background: #f0fdf4; +} + +.check-item-checkbox { + width: 24px; + height: 24px; + border: 2px solid var(--border-color, #cbd5e1); + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; + transition: all 0.2s; +} + +.check-item.checked .check-item-checkbox { + background: var(--success-color, #16a34a); + border-color: var(--success-color, #16a34a); + color: #fff; +} + +.check-item-content { + flex: 1; +} + +.check-item-text { + font-size: 0.9rem; + margin-bottom: 0.25rem; +} + +.check-item-required { + color: var(--error-color, #dc2626); + margin-left: 0.25rem; +} + +.check-item-note { + font-size: 0.8rem; + color: var(--text-secondary, #64748b); +} + +/* 체크 결과 선택 */ +.check-result-selector { + display: flex; + gap: 0.5rem; + margin-top: 0.5rem; +} + +.check-result-btn { + padding: 0.25rem 0.75rem; + border: 1px solid var(--border-color, #e2e8f0); + border-radius: 4px; + font-size: 0.75rem; + background: var(--surface-color, #fff); + cursor: pointer; + transition: all 0.2s; +} + +.check-result-btn.good.active { + background: #dcfce7; + border-color: var(--success-color, #16a34a); + color: var(--success-color, #16a34a); +} + +.check-result-btn.warning.active { + background: #fef3c7; + border-color: var(--warning-color, #f59e0b); + color: var(--warning-color, #f59e0b); +} + +.check-result-btn.bad.active { + background: #fee2e2; + border-color: var(--error-color, #dc2626); + color: var(--error-color, #dc2626); +} + +/* 체크리스트 액션 */ +.checklist-actions { + padding: 1rem 1.5rem; + border-top: 1px solid var(--border-color, #e2e8f0); + background: var(--surface-color, #fff); + display: flex; + gap: 0.75rem; + justify-content: flex-end; +} + +/* 물품 현황 섹션 */ +.items-section { + padding: 1.5rem; + border-top: 1px solid var(--border-color, #e2e8f0); +} + +.items-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.items-header h3 { + font-size: 1rem; + font-weight: 600; + margin: 0; +} + +.items-map-container { + position: relative; + width: 100%; + aspect-ratio: 16/9; + background: var(--bg-color, #f8fafc); + border-radius: 8px; + border: 1px solid var(--border-color, #e2e8f0); + overflow: hidden; +} + +.items-map-container img { + width: 100%; + height: 100%; + object-fit: contain; +} + +/* 물품 마커 */ +.item-marker { + position: absolute; + border: 2px solid; + border-radius: 4px; + background: rgba(255, 255, 255, 0.8); + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + font-size: 1.2rem; + transition: all 0.2s; +} + +.item-marker:hover { + transform: scale(1.1); + z-index: 10; +} + +.item-marker.container { + border-color: #3b82f6; + background: rgba(59, 130, 246, 0.2); +} + +.item-marker.plate { + border-color: #10b981; + background: rgba(16, 185, 129, 0.2); +} + +.item-marker.material { + border-color: #f59e0b; + background: rgba(245, 158, 11, 0.2); +} + +.item-marker.tool { + border-color: #8b5cf6; + background: rgba(139, 92, 246, 0.2); +} + +.item-marker.other { + border-color: #6b7280; + background: rgba(107, 114, 128, 0.2); +} + +/* 물품 범례 */ +.items-legend { + display: flex; + flex-wrap: wrap; + gap: 1rem; + margin-top: 1rem; + padding-top: 1rem; + border-top: 1px solid var(--border-color, #e2e8f0); +} + +.item-legend-item { + display: flex; + align-items: center; + gap: 0.5rem; + font-size: 0.85rem; +} + +.item-legend-icon { + width: 24px; + height: 24px; + border-radius: 4px; + display: flex; + align-items: center; + justify-content: center; + font-size: 0.9rem; +} + +/* 순회점검 완료 섹션 */ +.patrol-complete-section { + padding: 1.5rem; + border-top: 1px solid var(--border-color, #e2e8f0); + display: flex; + gap: 1rem; + align-items: flex-end; +} + +.patrol-complete-section .form-group { + flex: 1; + margin-bottom: 0; +} + +/* ==================== 작업장 상세 정보 패널 ==================== */ +.workplace-detail-panel { + position: fixed; + top: 90px; + right: 20px; + width: 400px; + max-height: calc(100vh - 110px); + background: var(--surface-color, #fff); + border-radius: 16px; + box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15); + display: none; + flex-direction: column; + z-index: 100; + overflow: hidden; +} + +.detail-panel-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + padding: 1rem 1.25rem; + background: linear-gradient(135deg, var(--primary-color, #3b82f6), #2563eb); + color: #fff; +} + +.detail-panel-title h3 { + margin: 0; + font-size: 1.1rem; + font-weight: 600; +} + +.detail-panel-subtitle { + font-size: 0.8rem; + opacity: 0.9; +} + +.detail-panel-close { + background: rgba(255, 255, 255, 0.2); + border: none; + color: #fff; + width: 28px; + height: 28px; + border-radius: 6px; + font-size: 1.25rem; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s; +} + +.detail-panel-close:hover { + background: rgba(255, 255, 255, 0.3); +} + +/* 요약 정보 */ +.detail-panel-summary { + display: flex; + gap: 0.5rem; + padding: 0.75rem 1rem; + background: var(--bg-color, #f8fafc); + border-bottom: 1px solid var(--border-color, #e2e8f0); + flex-wrap: wrap; +} + +.summary-item { + flex: 1; + min-width: 60px; + text-align: center; + padding: 0.5rem; + background: var(--surface-color, #fff); + border-radius: 8px; +} + +.summary-item.warning { + background: #fef3c7; +} + +.summary-item.danger { + background: #fee2e2; +} + +.summary-item.info { + background: #dbeafe; +} + +.summary-value { + display: block; + font-size: 1.25rem; + font-weight: 700; + color: var(--text-primary, #1e293b); +} + +.summary-item.warning .summary-value { + color: #b45309; +} + +.summary-item.danger .summary-value { + color: #dc2626; +} + +.summary-item.info .summary-value { + color: #2563eb; +} + +.summary-label { + font-size: 0.7rem; + color: var(--text-secondary, #64748b); +} + +/* 탭 */ +.detail-panel-tabs { + display: flex; + border-bottom: 1px solid var(--border-color, #e2e8f0); + background: var(--surface-color, #fff); +} + +.detail-tab { + flex: 1; + padding: 0.6rem 0.5rem; + border: none; + background: none; + font-size: 0.75rem; + color: var(--text-secondary, #64748b); + cursor: pointer; + border-bottom: 2px solid transparent; + transition: all 0.2s; + position: relative; +} + +.detail-tab:hover { + color: var(--primary-color, #3b82f6); +} + +.detail-tab.active { + color: var(--primary-color, #3b82f6); + border-bottom-color: var(--primary-color, #3b82f6); + font-weight: 600; +} + +.tab-badge { + display: none; + min-width: 16px; + height: 16px; + padding: 0 4px; + background: var(--error-color, #dc2626); + color: #fff; + font-size: 0.65rem; + font-weight: 600; + border-radius: 8px; + margin-left: 4px; + vertical-align: middle; +} + +.tab-badge.show { + display: inline-flex; + align-items: center; + justify-content: center; +} + +.tab-badge.warning { + background: var(--warning-color, #f59e0b); +} + +/* 탭 콘텐츠 */ +.detail-panel-content { + flex: 1; + overflow-y: auto; + padding: 1rem; + background: var(--bg-color, #f8fafc); +} + +.detail-tab-content { + display: none; +} + +.detail-tab-content.active { + display: block; +} + +.detail-empty { + text-align: center; + padding: 2rem 1rem; + color: var(--text-secondary, #64748b); + font-size: 0.9rem; +} + +/* 신고/부적합 섹션 */ +.issue-section { + margin-bottom: 1.5rem; +} + +.issue-section-title { + font-size: 0.85rem; + font-weight: 600; + margin: 0 0 0.75rem; + color: var(--text-primary, #1e293b); +} + +.issue-item { + background: var(--surface-color, #fff); + border-radius: 8px; + padding: 0.75rem; + margin-bottom: 0.5rem; + border-left: 3px solid var(--border-color, #cbd5e1); +} + +.issue-item.pending { + border-left-color: #f59e0b; +} + +.issue-item.info { + border-left-color: #3b82f6; +} + +.issue-item.warning { + border-left-color: #f59e0b; +} + +.issue-item.success { + border-left-color: #16a34a; +} + +.issue-item-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 0.5rem; +} + +.issue-title { + font-weight: 600; + font-size: 0.9rem; +} + +.issue-status { + font-size: 0.7rem; + padding: 2px 8px; + border-radius: 10px; + background: var(--bg-color, #f1f5f9); +} + +.issue-status.pending { + background: #fef3c7; + color: #b45309; +} + +.issue-status.info { + background: #dbeafe; + color: #1d4ed8; +} + +.issue-status.warning { + background: #fed7aa; + color: #c2410c; +} + +.issue-status.success { + background: #dcfce7; + color: #166534; +} + +.issue-item-meta { + display: flex; + gap: 0.5rem; + flex-wrap: wrap; + margin-bottom: 0.5rem; + font-size: 0.75rem; +} + +.issue-category { + color: var(--text-secondary, #64748b); +} + +.issue-severity { + padding: 1px 6px; + border-radius: 4px; + font-size: 0.65rem; +} + +.issue-severity.critical { + background: #fee2e2; + color: #dc2626; +} + +.issue-severity.high { + background: #fed7aa; + color: #c2410c; +} + +.issue-severity.medium { + background: #fef3c7; + color: #b45309; +} + +.issue-severity.low { + background: #d1fae5; + color: #059669; +} + +.issue-date { + color: var(--text-tertiary, #94a3b8); +} + +.issue-desc { + font-size: 0.8rem; + color: var(--text-secondary, #64748b); + margin-bottom: 0.25rem; +} + +.issue-reporter { + font-size: 0.7rem; + color: var(--text-tertiary, #94a3b8); +} + +/* 설비 섹션 */ +.equipment-section { + margin-bottom: 1.5rem; +} + +.equipment-section-title { + font-size: 0.85rem; + font-weight: 600; + margin: 0 0 0.75rem; + color: var(--text-primary, #1e293b); +} + +.repair-item { + background: var(--surface-color, #fff); + border-radius: 8px; + padding: 0.75rem; + margin-bottom: 0.5rem; + border-left: 3px solid #f59e0b; +} + +.repair-item.emergency { + border-left-color: #dc2626; + background: #fef2f2; +} + +.repair-item.high { + border-left-color: #f97316; +} + +.repair-item-header { + display: flex; + justify-content: space-between; + margin-bottom: 0.25rem; +} + +.repair-equipment { + font-weight: 600; + font-size: 0.85rem; +} + +.repair-priority { + font-size: 0.7rem; + padding: 2px 6px; + border-radius: 4px; + background: #fef3c7; + color: #b45309; +} + +.repair-priority.emergency { + background: #fee2e2; + color: #dc2626; +} + +.repair-priority.high { + background: #fed7aa; + color: #c2410c; +} + +.repair-category, .repair-desc, .repair-date { + font-size: 0.75rem; + color: var(--text-secondary, #64748b); +} + +.equipment-list { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.equipment-item { + display: flex; + align-items: center; + gap: 0.5rem; + padding: 0.5rem 0.75rem; + background: var(--surface-color, #fff); + border-radius: 6px; + font-size: 0.8rem; +} + +.equipment-item.attention { + background: #fef2f2; +} + +.equipment-name { + flex: 1; + font-weight: 500; +} + +.equipment-code { + color: var(--text-tertiary, #94a3b8); + font-size: 0.7rem; +} + +.equipment-status { + font-size: 0.65rem; + padding: 2px 6px; + border-radius: 4px; + background: #dcfce7; + color: #166534; +} + +.equipment-status.repair_needed { + background: #fee2e2; + color: #dc2626; +} + +.equipment-status.under_repair { + background: #fef3c7; + color: #b45309; +} + +.equipment-status.inactive { + background: #f1f5f9; + color: #64748b; +} + +/* 출입 섹션 */ +.visits-list { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.visit-item { + background: var(--surface-color, #fff); + border-radius: 8px; + padding: 0.75rem; +} + +.visit-item-header { + display: flex; + justify-content: space-between; + margin-bottom: 0.25rem; +} + +.visit-name { + font-weight: 600; + font-size: 0.9rem; +} + +.visit-company { + font-size: 0.75rem; + color: var(--text-secondary, #64748b); +} + +.visit-purpose { + font-size: 0.8rem; + color: var(--primary-color, #3b82f6); + margin-bottom: 0.25rem; +} + +.visit-time, .visit-companion, .visit-vehicle { + font-size: 0.75rem; + color: var(--text-secondary, #64748b); +} + +/* TBM 섹션 */ +.tbm-list { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.tbm-item { + background: var(--surface-color, #fff); + border-radius: 8px; + padding: 0.75rem; +} + +.tbm-item-header { + display: flex; + justify-content: space-between; + margin-bottom: 0.5rem; +} + +.tbm-task { + font-weight: 600; + font-size: 0.9rem; +} + +.tbm-status { + font-size: 0.7rem; + padding: 2px 8px; + border-radius: 10px; + background: var(--bg-color, #f1f5f9); +} + +.tbm-status.completed { + background: #dcfce7; + color: #166534; +} + +.tbm-status.in_progress { + background: #dbeafe; + color: #1d4ed8; +} + +.tbm-location, .tbm-leader, .tbm-content, .tbm-safety { + font-size: 0.8rem; + color: var(--text-secondary, #64748b); + margin-bottom: 0.25rem; +} + +.tbm-team { + font-size: 0.75rem; + padding-top: 0.5rem; + border-top: 1px dashed var(--border-color, #e2e8f0); + margin-top: 0.5rem; +} + +.tbm-team-label { + font-weight: 500; + color: var(--text-primary, #1e293b); +} + +.tbm-team-names { + color: var(--text-secondary, #64748b); +} + +/* 반응형 */ +@media (max-width: 768px) { + .patrol-start-section { + padding: 2rem 1rem; + } + + .patrol-start-section .btn-lg { + width: 100%; + justify-content: center; + } + + .today-status-summary { + flex-direction: row; + width: 100%; + } + + .status-card { + flex: 1; + min-width: auto; + padding: 0.75rem; + } + + .factory-selection-area { + padding: 1.5rem 1rem; + } + + .factory-cards-container { + grid-template-columns: repeat(2, 1fr); + gap: 1rem; + } + + .factory-card { + padding: 1.5rem 1rem; + } + + .factory-card-icon { + width: 60px; + height: 60px; + font-size: 2rem; + } + + .factory-card-name { + font-size: 1rem; + } + + .patrol-content { + grid-template-columns: 1fr; + } + + .patrol-map-section { + border-right: none; + border-bottom: 1px solid var(--border-color, #e2e8f0); + } + + .patrol-complete-section { + flex-direction: column; + } + + .session-info-bar { + flex-direction: column; + gap: 1rem; + text-align: center; + } + + .session-info { + flex-wrap: wrap; + justify-content: center; + } + + /* 모바일 상세 패널 */ + .workplace-detail-panel { + position: fixed; + top: 0; + right: 0; + left: 0; + bottom: 0; + width: 100%; + max-height: 100vh; + border-radius: 0; + } + + .detail-panel-tabs { + overflow-x: auto; + } + + .detail-tab { + white-space: nowrap; + } +} diff --git a/deploy/tkfb-package/web-ui/css/daily-work-report.css b/deploy/tkfb-package/web-ui/css/daily-work-report.css new file mode 100644 index 0000000..3998af4 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/daily-work-report.css @@ -0,0 +1,2018 @@ +/* daily-work-report.css - 일일 작업보고서 스타일 */ + +/* 탭 메뉴 스타일 */ +.tab-menu { + display: flex; + gap: 0.5rem; + border-bottom: 2px solid var(--border-color, #e5e7eb); + margin-bottom: 1.5rem; +} + +/* 날짜 그룹 스타일 (접기/펼치기) */ +.date-group { + margin-bottom: 1.5rem; + border: 1px solid #e5e7eb; + border-radius: 12px; + overflow: hidden; + background: white; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08); +} + +.date-group-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem 1.25rem; + background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%); + border-bottom: 1px solid #e5e7eb; + cursor: pointer; + transition: background-color 0.2s; + user-select: none; +} + +.date-group-header:hover { + background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%); +} + +.date-group-header.has-issues { + background: linear-gradient(135deg, #fefce8 0%, #fef9c3 100%); + border-bottom-color: #fde047; +} + +.date-group-header.has-issues:hover { + background: linear-gradient(135deg, #fef9c3 0%, #fef08a 100%); +} + +.date-header-left { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.date-toggle-icon { + font-size: 0.75rem; + color: #64748b; + width: 1rem; + text-align: center; +} + +.date-title { + font-weight: 600; + font-size: 1.1rem; + color: #1e293b; +} + +.today-badge { + background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); + color: white; + padding: 0.2rem 0.6rem; + border-radius: 10px; + font-size: 0.7rem; + font-weight: 600; +} + +.date-header-center { + display: flex; + gap: 1rem; +} + +.date-stat { + font-size: 0.85rem; + color: #64748b; +} + +.date-header-right { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.date-issue-summary { + display: flex; + gap: 0.5rem; +} + +.issue-badge { + padding: 0.25rem 0.6rem; + border-radius: 12px; + font-size: 0.75rem; + font-weight: 600; +} + +.issue-badge.nonconformity { + background: #fef2f2; + color: #dc2626; + border: 1px solid #fecaca; +} + +.issue-badge.safety { + background: #fefce8; + color: #ca8a04; + border: 1px solid #fde047; +} + +.no-issues { + font-size: 0.8rem; + color: #94a3b8; +} + +.date-group-content { + padding: 1rem; + background: #fafafa; +} + +.date-group.collapsed .date-group-content { + display: none; +} + +/* 부적합 버튼 강조 (관련 이슈 있을 때) */ +.btn-defect-toggle.has-related-issue { + background: linear-gradient(135deg, #fef2f2 0%, #fee2e2 100%); + border-color: #f87171; + color: #dc2626; + animation: pulse-attention 2s infinite; +} + +.btn-defect-toggle.has-related-issue:hover { + background: linear-gradient(135deg, #fee2e2 0%, #fecaca 100%); +} + +@keyframes pulse-attention { + 0%, 100% { + box-shadow: 0 0 0 0 rgba(248, 113, 113, 0.4); + } + 50% { + box-shadow: 0 0 0 4px rgba(248, 113, 113, 0); + } +} + +/* TBM 세션 그룹 스타일 */ +.tbm-session-group { + margin-bottom: 2rem; +} + +.tbm-session-header { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + padding: 0.75rem 1.5rem; + border-radius: 8px 8px 0 0; + display: flex; + align-items: center; + gap: 1rem; + font-size: 0.875rem; +} + +.tbm-session-badge { + background-color: rgba(255, 255, 255, 0.3); + padding: 0.25rem 0.75rem; + border-radius: 12px; + font-weight: 600; + font-size: 0.75rem; +} + +.tbm-session-date { + font-weight: 600; + font-size: 1rem; +} + +.tbm-session-creator { + font-size: 0.8rem; + opacity: 0.9; +} + +.tbm-session-count { + background-color: rgba(255, 255, 255, 0.2); + padding: 0.25rem 0.625rem; + border-radius: 12px; + font-weight: 600; + margin-left: auto; +} + +.tbm-session-info { + opacity: 0.95; + font-size: 0.875rem; +} + +/* 당일 신고 리마인더 스타일 */ +.issue-reminder-section { + background: linear-gradient(135deg, #fef3c7 0%, #fde68a 100%); + border: 1px solid #f59e0b; + border-top: none; + padding: 1rem 1.5rem; +} + +.issue-reminder-header { + display: flex; + align-items: center; + gap: 0.5rem; + margin-bottom: 0.75rem; +} + +.issue-reminder-icon { + font-size: 1.25rem; +} + +.issue-reminder-title { + font-weight: 600; + color: #92400e; + font-size: 0.9375rem; +} + +.issue-reminder-count { + background: #f59e0b; + color: white; + padding: 0.125rem 0.5rem; + border-radius: 10px; + font-size: 0.75rem; + font-weight: 600; +} + +.issue-reminder-list { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-bottom: 0.75rem; +} + +.issue-reminder-item { + display: flex; + align-items: center; + gap: 0.75rem; + background: white; + padding: 0.5rem 0.75rem; + border-radius: 6px; + font-size: 0.8125rem; + box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05); +} + +.issue-reminder-item.nonconformity { + border-left: 3px solid #f59e0b; +} + +.issue-reminder-item.safety { + border-left: 3px solid #ef4444; +} + +.issue-type-badge { + padding: 0.125rem 0.5rem; + border-radius: 4px; + font-size: 0.6875rem; + font-weight: 600; + flex-shrink: 0; +} + +.issue-reminder-item.nonconformity .issue-type-badge { + background: #fef3c7; + color: #92400e; +} + +.issue-reminder-item.safety .issue-type-badge { + background: #fee2e2; + color: #b91c1c; +} + +.issue-category { + color: #6b7280; + font-size: 0.75rem; + flex-shrink: 0; +} + +.issue-item { + flex: 1; + color: #374151; + font-weight: 500; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.issue-location { + color: #6b7280; + font-size: 0.75rem; + flex-shrink: 0; +} + +.issue-status { + padding: 0.125rem 0.375rem; + border-radius: 4px; + font-size: 0.6875rem; + font-weight: 500; + flex-shrink: 0; +} + +.issue-status.status-reported { + background: #dbeafe; + color: #1d4ed8; +} + +.issue-status.status-received { + background: #fed7aa; + color: #c2410c; +} + +.issue-status.status-in_progress { + background: #e9d5ff; + color: #7c3aed; +} + +.issue-status.status-completed { + background: #d1fae5; + color: #047857; +} + +.issue-status.status-closed { + background: #f3f4f6; + color: #4b5563; +} + +.issue-reminder-more { + text-align: center; + color: #92400e; + font-size: 0.75rem; + font-style: italic; +} + +.issue-reminder-hint { + background: rgba(255, 255, 255, 0.7); + padding: 0.5rem 0.75rem; + border-radius: 6px; + font-size: 0.8125rem; + color: #78350f; +} + +/* TBM 작업 테이블 스타일 */ +.tbm-table-container { + overflow-x: auto; + border: 1px solid var(--border-color, #e5e7eb); + border-radius: 0 0 8px 8px; + background: white; +} + +.tbm-work-table { + width: 100%; + border-collapse: collapse; + font-size: 0.875rem; +} + +.tbm-work-table thead { + background-color: #f9fafb; + border-bottom: 2px solid var(--border-color, #e5e7eb); +} + +.tbm-work-table th { + padding: 0.75rem 0.5rem; + text-align: left; + font-weight: 600; + color: var(--text-secondary, #6b7280); + border-bottom: 2px solid var(--border-color, #e5e7eb); + white-space: nowrap; + font-size: 0.8rem; +} + +.tbm-work-table td { + padding: 0.75rem 0.5rem; + border-bottom: 1px solid var(--border-light, #f3f4f6); + vertical-align: middle; +} + +.tbm-work-table tbody tr:hover { + background-color: #f9fafb; +} + +.tbm-work-table tbody tr:last-child td { + border-bottom: none; +} + +.worker-cell { + min-width: 100px; +} + +.worker-cell strong { + display: block; + color: var(--text-primary, #111827); + margin-bottom: 0.25rem; +} + +.worker-job-type { + font-size: 0.75rem; + color: var(--text-secondary, #6b7280); + background-color: #f3f4f6; + padding: 0.125rem 0.5rem; + border-radius: 4px; + display: inline-block; +} + +.workplace-cell div { + font-size: 0.8rem; +} + +.workplace-cell div:first-child { + color: var(--text-secondary, #6b7280); + font-size: 0.75rem; +} + +.form-input-compact { + width: 70px; + padding: 0.375rem 0.5rem; + border: 1px solid var(--border-color, #d1d5db); + border-radius: 4px; + font-size: 0.875rem; + text-align: center; +} + +.form-input-compact:focus { + outline: none; + border-color: var(--primary, #3b82f6); + box-shadow: 0 0 0 2px rgba(59, 130, 246, 0.1); +} + +.form-input-compact[type="number"] { + -moz-appearance: textfield; +} + +.form-input-compact[type="number"]::-webkit-outer-spin-button, +.form-input-compact[type="number"]::-webkit-inner-spin-button { + -webkit-appearance: none; + margin: 0; +} + +.btn-submit-compact { + padding: 0.5rem 1rem; + background-color: var(--primary, #3b82f6); + color: white; + border: none; + border-radius: 4px; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s; + white-space: nowrap; +} + +.btn-submit-compact:hover { + background-color: var(--primary-dark, #2563eb); +} + +.btn-submit-compact:active { + transform: scale(0.98); +} + +.btn-add-work { + padding: 0.625rem 1.25rem; + background-color: #10b981; + color: white; + border: none; + border-radius: 6px; + font-size: 0.875rem; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s; +} + +.btn-add-work:hover { + background-color: #059669; +} + +.btn-delete-compact { + padding: 0.375rem 0.625rem; + background-color: #ef4444; + color: white; + border: none; + border-radius: 4px; + font-size: 0.875rem; + cursor: pointer; + transition: background-color 0.2s; +} + +.btn-delete-compact:hover { + background-color: #dc2626; +} + +.btn-map-select { + padding: 0.5rem 0.875rem; + background-color: #8b5cf6; + color: white; + border: none; + border-radius: 4px; + font-size: 0.8rem; + font-weight: 500; + cursor: pointer; + transition: background-color 0.2s; + white-space: nowrap; +} + +.btn-map-select:hover { + background-color: #7c3aed; +} + +/* 작업장소 선택 박스 hover 효과 */ +.workplace-select-box { + transition: all 0.2s ease; +} + +.workplace-select-box:hover { + background-color: #f3f4f6 !important; + border-color: #8b5cf6 !important; + transform: translateY(-1px); + box-shadow: 0 2px 4px rgba(139, 92, 246, 0.1); +} + +.workplace-category-btn, +.workplace-btn { + padding: 0.75rem 1rem; + background-color: #f3f4f6; + border: 2px solid #e5e7eb; + border-radius: 6px; + cursor: pointer; + transition: all 0.2s; + font-size: 0.875rem; + font-weight: 500; + text-align: center; +} + +.workplace-category-btn:hover, +.workplace-btn:hover { + background-color: #e0e7ff; + border-color: #818cf8; + color: #4338ca; +} + +.workplace-category-btn:active, +.workplace-btn:active { + transform: scale(0.98); +} + +/* 작업장소 선택 모달 */ +#workplaceModal.modal { + display: none; + position: fixed; + z-index: 1000; + left: 0; + top: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + align-items: center; + justify-content: center; +} + +#workplaceModal .modal-content { + background-color: white; + margin: auto; + padding: 0; + border-radius: 8px; + max-width: 600px; + width: 90%; + max-height: 80vh; + overflow: hidden; + display: flex; + flex-direction: column; +} + +#workplaceModal .modal-header { + padding: 1.5rem; + border-bottom: 1px solid #e5e7eb; + display: flex; + justify-content: space-between; + align-items: center; +} + +#workplaceModal .modal-header h3 { + margin: 0; + font-size: 1.25rem; + color: #111827; +} + +#workplaceModal .modal-close { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + color: #6b7280; + padding: 0; + width: 2rem; + height: 2rem; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; +} + +#workplaceModal .modal-close:hover { + background-color: #f3f4f6; + color: #111827; +} + +#workplaceModal .modal-body { + padding: 1.5rem; + overflow-y: auto; +} + +.tab-btn { + padding: 0.75rem 1.5rem; + background: none; + border: none; + border-bottom: 3px solid transparent; + cursor: pointer; + font-weight: 500; + color: var(--text-secondary, #6b7280); + transition: all 0.2s; +} + +.tab-btn:hover { + color: var(--primary, #3b82f6); +} + +.tab-btn.active { + color: var(--primary, #3b82f6); + border-bottom-color: var(--primary, #3b82f6); +} + +/* TBM 작업 카드 스타일 */ +.tbm-work-card { + background: white; + border: 1px solid var(--border-color, #e5e7eb); + border-radius: 8px; + padding: 1.5rem; + margin-bottom: 1.5rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.tbm-work-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 2px solid var(--border-color, #e5e7eb); +} + +.tbm-work-header h4 { + margin: 0; + font-size: 1.125rem; + color: var(--text-primary, #111827); +} + +.tbm-work-date { + font-size: 0.875rem; + color: var(--text-secondary, #6b7280); + background: var(--bg-secondary, #f3f4f6); + padding: 0.25rem 0.75rem; + border-radius: 4px; +} + +.tbm-work-info { + margin-bottom: 1.5rem; +} + +.info-row { + display: flex; + padding: 0.5rem 0; + border-bottom: 1px solid var(--border-light, #f3f4f6); +} + +.info-row:last-child { + border-bottom: none; +} + +.info-row .label { + font-weight: 600; + color: var(--text-secondary, #6b7280); + min-width: 100px; + font-size: 0.875rem; +} + +.info-row .value { + color: var(--text-primary, #111827); + flex: 1; +} + +.tbm-work-input { + background: var(--bg-secondary, #f9fafb); + padding: 1.5rem; + border-radius: 6px; + margin-bottom: 1rem; +} + +.tbm-work-input .form-group { + margin-bottom: 1rem; +} + +.tbm-work-input .form-group:last-child { + margin-bottom: 0; +} + +.tbm-work-input label { + display: block; + font-weight: 500; + font-size: 0.875rem; + color: var(--text-secondary, #6b7280); + margin-bottom: 0.5rem; +} + +.tbm-work-input .form-input { + width: 100%; + padding: 0.625rem; + border: 1px solid var(--border-color, #d1d5db); + border-radius: 4px; + font-size: 1rem; +} + +.tbm-work-input .form-input:focus { + outline: none; + border-color: var(--primary, #3b82f6); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.tbm-work-input .form-input[readonly] { + background-color: #f3f4f6; + cursor: not-allowed; +} + +/* 버튼 스타일 */ +.btn-block { + width: 100%; + padding: 0.875rem; + font-size: 1rem; + font-weight: 500; +} + +.btn-primary { + background-color: var(--primary, #3b82f6); + color: white; + border: none; + border-radius: 6px; + cursor: pointer; + transition: background-color 0.2s; +} + +.btn-primary:hover { + background-color: var(--primary-dark, #2563eb); +} + +.btn-primary:disabled { + background-color: #9ca3af; + cursor: not-allowed; +} + +/* 메시지 스타일 */ +.message { + padding: 1rem; + border-radius: 6px; + margin-bottom: 1rem; + font-size: 0.875rem; +} + +.message.error { + background-color: #fee2e2; + color: #991b1b; + border-left: 4px solid #dc2626; +} + +.message.success { + background-color: #dcfce7; + color: #166534; + border-left: 4px solid #16a34a; +} + +.message.info { + background-color: #dbeafe; + color: #1e40af; + border-left: 4px solid #3b82f6; +} + +/* 완료된 보고서 카드 스타일 */ +.completed-report-card { + background: white; + border: 1px solid var(--border-color, #e5e7eb); + border-radius: 8px; + padding: 1.5rem; + margin-bottom: 1.5rem; + box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1); +} + +.completed-report-card .report-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; + padding-bottom: 1rem; + border-bottom: 2px solid var(--border-color, #e5e7eb); +} + +.completed-report-card .report-header h4 { + margin: 0 0.5rem 0 0; + font-size: 1.125rem; + color: var(--text-primary, #111827); + display: inline-block; +} + +.completed-report-card .report-date { + font-size: 0.875rem; + color: var(--text-secondary, #6b7280); + background: var(--bg-secondary, #f3f4f6); + padding: 0.25rem 0.75rem; + border-radius: 4px; +} + +.completed-report-card .report-info { + margin-top: 1rem; +} + +.tbm-badge { + display: inline-block; + background-color: #dbeafe; + color: #1e40af; + padding: 0.25rem 0.75rem; + border-radius: 12px; + font-size: 0.75rem; + font-weight: 600; + margin-left: 0.5rem; +} + +.manual-badge { + display: inline-block; + background-color: #f3f4f6; + color: #6b7280; + padding: 0.25rem 0.75rem; + border-radius: 12px; + font-size: 0.75rem; + font-weight: 600; + margin-left: 0.5rem; +} + +.form-group { + margin-bottom: 1rem; +} + +.form-label { + display: block; + font-weight: 500; + font-size: 0.875rem; + color: var(--text-secondary, #6b7280); + margin-bottom: 0.5rem; +} + +.form-input { + width: 100%; + padding: 0.625rem; + border: 1px solid var(--border-color, #d1d5db); + border-radius: 4px; + font-size: 1rem; +} + +.form-input:focus { + outline: none; + border-color: var(--primary, #3b82f6); + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +/* 시간 입력 트리거 (클릭 가능한 영역) */ +.time-input-trigger { + padding: 0.5rem 0.75rem; + background: #f9fafb; + border: 2px solid #e5e7eb; + border-radius: 6px; + cursor: pointer; + text-align: center; + font-weight: 600; + color: #374151; + min-height: 44px; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + user-select: none; +} + +.time-input-trigger:hover { + background: #f3f4f6; + border-color: #3b82f6; + color: #3b82f6; +} + +.time-input-trigger.has-value { + background: #eff6ff; + border-color: #3b82f6; + color: #1e40af; +} + +.time-input-trigger.placeholder { + color: #9ca3af; + font-style: italic; + font-weight: 400; +} + +/* 시간 선택 팝오버 */ +.time-picker-overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background-color: rgba(0, 0, 0, 0.5); + z-index: 2000; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; +} + +.time-picker-popup { + background: white; + border-radius: 16px; + box-shadow: 0 20px 60px rgba(0, 0, 0, 0.3); + padding: 1.5rem; + max-width: 400px; + width: 100%; + animation: popupSlideIn 0.3s ease-out; +} + +@keyframes popupSlideIn { + from { + opacity: 0; + transform: translateY(20px) scale(0.95); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +.time-picker-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.25rem; +} + +.time-picker-header h3 { + margin: 0; + font-size: 1.125rem; + font-weight: 700; + color: #111827; +} + +.time-picker-close { + background: none; + border: none; + font-size: 1.75rem; + color: #6b7280; + cursor: pointer; + padding: 0; + width: 2rem; + height: 2rem; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + transition: all 0.2s; +} + +.time-picker-close:hover { + background: #f3f4f6; + color: #111827; +} + +/* 퀵 선택 버튼 그리드 */ +.quick-time-grid { + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: 0.5rem; + margin-bottom: 1.25rem; +} + +.time-btn { + padding: 1rem 0.5rem; + background: #3b82f6; + color: white; + border: none; + border-radius: 10px; + cursor: pointer; + font-weight: 700; + font-size: 0.875rem; + min-height: 64px; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(59, 130, 246, 0.2); +} + +.time-btn:hover { + background: #2563eb; + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(59, 130, 246, 0.3); +} + +.time-btn:active { + transform: translateY(0) scale(0.98); + box-shadow: 0 2px 4px rgba(59, 130, 246, 0.2); +} + +.time-btn .time-value { + font-size: 0.95rem; +} + +/* 미세 조정 영역 */ +.time-adjust-area { + background: #f9fafb; + border: 1px solid #e5e7eb; + border-radius: 10px; + padding: 1rem; + margin-bottom: 1rem; + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.current-time-label { + font-size: 0.875rem; + color: #6b7280; + font-weight: 500; +} + +.current-time-value { + font-size: 1.5rem; + color: #111827; + font-weight: 700; + display: block; + margin-bottom: 0.5rem; +} + +.adjust-buttons { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 0.5rem; +} + +.adjust-btn { + padding: 0.875rem 1rem; + background: #6b7280; + color: white; + border: none; + border-radius: 8px; + font-weight: 700; + font-size: 0.875rem; + cursor: pointer; + min-height: 48px; + transition: all 0.2s ease; +} + +.adjust-btn:hover { + background: #4b5563; + transform: translateY(-1px); +} + +.adjust-btn:active { + transform: translateY(0) scale(0.98); +} + +/* 확인 버튼 */ +.confirm-btn { + width: 100%; + padding: 1rem; + background: #10b981; + color: white; + border: none; + border-radius: 10px; + font-weight: 700; + font-size: 1rem; + cursor: pointer; + min-height: 52px; + transition: all 0.2s ease; + box-shadow: 0 2px 4px rgba(16, 185, 129, 0.2); +} + +.confirm-btn:hover { + background: #059669; + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(16, 185, 129, 0.3); +} + +.confirm-btn:active { + transform: translateY(0) scale(0.98); +} + +/* ================================================ + 저장 결과 모달 스타일 + ================================================ */ +.modal-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 10000; + padding: 1rem; +} + +.modal-container.result-modal { + background: white; + border-radius: 12px; + max-width: 500px; + width: 100%; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2); +} + +.modal-header { + padding: 1.5rem; + border-bottom: 1px solid #e5e7eb; + display: flex; + justify-content: space-between; + align-items: center; +} + +.modal-header h2 { + margin: 0; + font-size: 1.25rem; + font-weight: 600; +} + +.modal-close-btn { + background: none; + border: none; + font-size: 1.5rem; + cursor: pointer; + color: #6b7280; + padding: 0; + width: 2rem; + height: 2rem; + display: flex; + align-items: center; + justify-content: center; + border-radius: 4px; + transition: background 0.2s; +} + +.modal-close-btn:hover { + background: #f3f4f6; +} + +.modal-body { + padding: 2rem 1.5rem; +} + +.result-icon { + text-align: center; + font-size: 3rem; + margin-bottom: 1rem; +} + +.result-title { + text-align: center; + font-size: 1.5rem; + font-weight: 600; + margin-bottom: 0.5rem; +} + +.result-title.success { + color: #10b981; +} + +.result-title.error { + color: #ef4444; +} + +.result-title.warning { + color: #f59e0b; +} + +.result-message { + text-align: center; + color: #6b7280; + margin-bottom: 1rem; +} + +.result-details { + margin-top: 1.5rem; + padding: 1rem; + background: #f9fafb; + border-radius: 8px; +} + +.result-details h4 { + margin: 0 0 0.5rem 0; + font-size: 0.875rem; + font-weight: 600; + color: #374151; +} + +.result-details ul { + margin: 0; + padding-left: 1.5rem; +} + +.result-details li { + margin-bottom: 0.25rem; + color: #6b7280; +} + +.result-details p { + margin: 0; + color: #6b7280; +} + +.modal-footer { + padding: 1rem 1.5rem; + border-top: 1px solid #e5e7eb; + display: flex; + justify-content: flex-end; + gap: 0.5rem; +} + +/* ================================================================= + 일괄제출 버튼 스타일 + ================================================================= */ + +.batch-submit-container { + padding: 1rem; + background: #f9fafb; + border-top: 2px solid #e5e7eb; + display: flex; + justify-content: center; + align-items: center; +} + +.btn-batch-submit { + background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); + color: white; + border: none; + padding: 0.875rem 2rem; + font-size: 1rem; + font-weight: 600; + border-radius: 8px; + cursor: pointer; + transition: all 0.3s ease; + box-shadow: 0 4px 6px rgba(59, 130, 246, 0.3); + min-width: 280px; + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; +} + +.btn-batch-submit:hover { + background: linear-gradient(135deg, #2563eb 0%, #1d4ed8 100%); + box-shadow: 0 6px 12px rgba(59, 130, 246, 0.4); + transform: translateY(-2px); +} + +.btn-batch-submit:active { + transform: translateY(0); + box-shadow: 0 2px 4px rgba(59, 130, 246, 0.3); +} + +.btn-batch-submit:disabled { + background: #9ca3af; + cursor: not-allowed; + box-shadow: none; + transform: none; +} + +/* 수동입력 섹션 강조 */ +.manual-input-section { + border: 2px solid #f59e0b; + border-radius: 8px; + margin-bottom: 2rem; + box-shadow: 0 4px 6px rgba(245, 158, 11, 0.1); +} + +.manual-input-section .tbm-session-header { + background: linear-gradient(135deg, #f59e0b 0%, #d97706 100%); +} + +/* TBM 세션 그룹 간격 조정 */ +.tbm-session-group:not(.manual-input-section) { + margin-bottom: 1.5rem; +} + +/* 부적합 원인 관리 버튼 */ +.btn-defect-manage { + background: #f3f4f6; + border: 1px solid #d1d5db; + border-radius: 6px; + padding: 0.5rem 0.75rem; + cursor: pointer; + font-size: 0.875rem; + min-width: 80px; + text-align: center; + transition: all 0.2s ease; +} + +.btn-defect-manage:hover { + background: #e5e7eb; + border-color: #9ca3af; +} + +.btn-defect-manage span { + color: #9ca3af; +} + +.btn-defect-manage span[style*="color: #dc2626"] { + font-weight: 500; +} + +/* 부적합 토글 버튼 (인라인 방식) */ +.btn-defect-toggle { + background: #f9fafb; + border: 2px solid #e5e7eb; + border-radius: 6px; + padding: 0.5rem 0.75rem; + cursor: pointer; + font-size: 0.875rem; + min-width: 70px; + text-align: center; + transition: all 0.2s ease; + display: flex; + align-items: center; + justify-content: center; + min-height: 44px; +} + +.btn-defect-toggle:hover { + background: #f3f4f6; + border-color: #d97706; +} + +.btn-defect-toggle.has-defect { + background: #fef3c7; + border-color: #f59e0b; +} + +.btn-defect-toggle span { + color: #6b7280; + font-weight: 500; +} + +.btn-defect-toggle.has-defect span { + color: #dc2626; + font-weight: 600; +} + +/* 부적합 인라인 영역 */ +.defect-row td { + border-bottom: 1px solid #fcd34d !important; +} + +.defect-inline-area { + padding: 0.75rem 1rem; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.defect-list { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.defect-inline-item { + display: flex; + align-items: center; + gap: 0.5rem; + background: white; + padding: 0.5rem; + border-radius: 6px; + border: 1px solid #e5e7eb; +} + +.defect-select { + flex: 1; + min-width: 120px; + max-width: 200px; + padding: 0.5rem; + border: 1px solid #d1d5db; + border-radius: 6px; + font-size: 0.875rem; + background: white; +} + +.defect-select:focus { + outline: none; + border-color: #f59e0b; + box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.1); +} + +.defect-time-input { + display: flex; + align-items: center; + gap: 0.25rem; + padding: 0.5rem 0.75rem; + background: #f9fafb; + border: 2px solid #e5e7eb; + border-radius: 6px; + cursor: pointer; + min-width: 80px; + justify-content: center; + transition: all 0.2s ease; +} + +.defect-time-input:hover { + background: #f3f4f6; + border-color: #f59e0b; +} + +.defect-time-value { + font-weight: 600; + color: #374151; + font-size: 0.875rem; +} + +.defect-time-unit { + font-size: 0.75rem; + color: #6b7280; +} + +.btn-remove-defect { + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + background: #fee2e2; + color: #dc2626; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 1.25rem; + font-weight: bold; + transition: all 0.2s ease; +} + +.btn-remove-defect:hover { + background: #fecaca; +} + +.btn-add-defect-inline { + align-self: flex-start; + padding: 0.5rem 1rem; + background: #f59e0b; + color: white; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 0.875rem; + font-weight: 500; + transition: all 0.2s ease; +} + +.btn-add-defect-inline:hover { + background: #d97706; +} + +/* ================================================================= + 이슈 기반 부적합 선택 UI + ================================================================= */ + +/* 이슈 섹션 전체 */ +.defect-issue-section { + margin-bottom: 0.75rem; +} + +.defect-issue-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.5rem 0.75rem; + background: #fef3c7; + border-radius: 6px 6px 0 0; + border: 1px solid #fcd34d; + border-bottom: none; +} + +.defect-issue-title { + font-weight: 600; + color: #92400e; + font-size: 0.8125rem; +} + +.defect-issue-count { + background: #f59e0b; + color: white; + padding: 0.125rem 0.375rem; + border-radius: 8px; + font-size: 0.6875rem; + font-weight: 600; +} + +/* 이슈 목록 */ +.defect-issue-list { + border: 1px solid #e5e7eb; + border-top: none; + border-radius: 0 0 6px 6px; + overflow: hidden; +} + +/* 개별 이슈 아이템 - 가벼운 인라인 스타일 */ +.defect-issue-item { + display: flex; + align-items: center; + gap: 0.75rem; + padding: 0.5rem 0.75rem; + background: white; + border-bottom: 1px solid #f3f4f6; + transition: all 0.2s ease; + font-size: 0.8125rem; +} + +.defect-issue-item:last-child { + border-bottom: none; +} + +.defect-issue-item:hover { + background: #f9fafb; +} + +.defect-issue-item.selected { + background: #fef2f2; + border-left: 3px solid #ef4444; +} + +/* 체크박스 영역 */ +.defect-issue-checkbox { + flex-shrink: 0; +} + +.defect-issue-checkbox input[type="checkbox"] { + width: 16px; + height: 16px; + cursor: pointer; + accent-color: #ef4444; +} + +/* 이슈 정보 영역 - 인라인 */ +.defect-issue-info { + flex: 1; + min-width: 0; + display: flex; + align-items: center; + gap: 0.5rem; +} + +.defect-issue-category { + font-size: 0.75rem; + color: #6b7280; + flex-shrink: 0; +} + +.defect-issue-item-name { + font-weight: 500; + color: #374151; + font-size: 0.8125rem; + flex: 1; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.defect-issue-location { + font-size: 0.75rem; + color: #9ca3af; + flex-shrink: 0; +} + +/* 시간 입력 영역 */ +.defect-issue-time { + flex-shrink: 0; +} + +.defect-issue-time .defect-time-input { + background: #f3f4f6; + opacity: 0.5; + cursor: not-allowed; + padding: 0.375rem 0.625rem; + font-size: 0.75rem; +} + +.defect-issue-time.active .defect-time-input { + background: #fee2e2; + opacity: 1; + cursor: pointer; + border-color: #ef4444; +} + +.defect-issue-time.active .defect-time-input:hover { + background: #fecaca; +} + +/* 레거시 부적합 섹션 */ +.defect-legacy-section { + margin-top: 1rem; +} + +.btn-add-legacy-defect { + display: inline-flex; + align-items: center; + gap: 0.375rem; + padding: 0.5rem 0.875rem; + background: #f3f4f6; + color: #374151; + border: 1px dashed #d1d5db; + border-radius: 6px; + cursor: pointer; + font-size: 0.8rem; + font-weight: 500; + transition: all 0.2s ease; + margin-bottom: 0.5rem; +} + +.btn-add-legacy-defect:hover { + background: #e5e7eb; + border-color: #9ca3af; +} + +.defect-legacy-list { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +/* ================================================================= + 순차 입력 부적합 UI (대분류 → 소분류 → 추가내용) + ================================================================= */ + +.defect-cascading-item { + background: #fefce8; + border: 1px solid #fde047; + border-radius: 8px; + padding: 0.75rem; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.defect-cascading-row { + display: flex; + align-items: flex-end; + gap: 0.5rem; + flex-wrap: wrap; +} + +.defect-field { + display: flex; + flex-direction: column; + gap: 0.25rem; + min-width: 100px; +} + +.defect-field-label { + font-size: 0.7rem; + font-weight: 600; + color: #92400e; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.defect-select-wrapper { + position: relative; +} + +.defect-category-select, +.defect-item-select { + width: 100%; + min-width: 120px; + max-width: none; + padding: 0.5rem 0.75rem; + border: 1px solid #fde047; + border-radius: 6px; + font-size: 0.8125rem; + background: white; + cursor: pointer; +} + +.defect-category-select:focus, +.defect-item-select:focus { + outline: none; + border-color: #f59e0b; + box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.2); +} + +.defect-category-select:disabled, +.defect-item-select:disabled { + background: #f3f4f6; + color: #9ca3af; + cursor: not-allowed; +} + +.defect-field-time { + min-width: 70px; + flex-shrink: 0; +} + +.defect-field-time .defect-time-input { + background: white; + border-color: #fde047; +} + +.defect-note-row { + display: flex; + gap: 0.5rem; +} + +.defect-note-input { + flex: 1; + padding: 0.5rem 0.75rem; + border: 1px solid #e5e7eb; + border-radius: 6px; + font-size: 0.8125rem; + background: white; +} + +.defect-note-input:focus { + outline: none; + border-color: #f59e0b; + box-shadow: 0 0 0 2px rgba(245, 158, 11, 0.1); +} + +.defect-note-input::placeholder { + color: #9ca3af; +} + +.defect-preview { + padding: 0.375rem 0.625rem; + background: rgba(245, 158, 11, 0.1); + border-radius: 4px; +} + +.defect-preview-text { + font-size: 0.75rem; + color: #92400e; + font-weight: 500; +} + +/* 부적합 액션 버튼 영역 */ +.defect-action-buttons { + display: flex; + gap: 0.5rem; + margin-top: 0.75rem; + align-items: center; +} + +.btn-save-defects { + padding: 0.5rem 1.25rem; + background: #16a34a; + color: white; + border: none; + border-radius: 6px; + cursor: pointer; + font-size: 0.875rem; + font-weight: 600; + transition: all 0.2s ease; +} + +.btn-save-defects:hover { + background: #15803d; +} + +.btn-save-defects.saved { + background: #22c55e; + cursor: default; +} + +.btn-save-defects:disabled { + opacity: 0.8; +} + +/* 저장 완료 메시지 */ +.defect-save-message { + display: flex; + align-items: center; + gap: 0.5rem; + margin-top: 0.5rem; + padding: 0.5rem 0.75rem; + background: #dcfce7; + border: 1px solid #86efac; + border-radius: 6px; + animation: fadeIn 0.3s ease; +} + +.save-message-text { + font-size: 0.8125rem; + color: #166534; + font-weight: 500; +} + +.save-message-text::before { + content: '✓ '; +} + +/* 저장 하이라이트 애니메이션 */ +.defect-legacy-list.saved-highlight .defect-cascading-item { + animation: highlightPulse 0.5s ease; +} + +@keyframes highlightPulse { + 0% { background-color: #fefce8; } + 50% { background-color: #dcfce7; } + 100% { background-color: #fefce8; } +} + +@keyframes fadeIn { + from { opacity: 0; transform: translateY(-5px); } + to { opacity: 1; transform: translateY(0); } +} + +/* ================================================================= + 저장된 부적합 섹션 + ================================================================= */ + +.defect-saved-section { + background: #f0fdf4; + border: 1px solid #86efac; + border-radius: 8px; + margin-bottom: 1rem; + overflow: hidden; +} + +.defect-saved-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.625rem 1rem; + background: linear-gradient(135deg, #dcfce7 0%, #bbf7d0 100%); + border-bottom: 1px solid #86efac; +} + +.defect-saved-title { + font-size: 0.8125rem; + font-weight: 600; + color: #166534; +} + +.defect-saved-count { + font-size: 0.75rem; + font-weight: 600; + color: white; + background: #16a34a; + padding: 0.125rem 0.5rem; + border-radius: 10px; +} + +.defect-saved-list { + padding: 0.5rem; +} + +.defect-saved-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.625rem 0.75rem; + background: white; + border: 1px solid #d1fae5; + border-radius: 6px; + margin-bottom: 0.375rem; + gap: 0.75rem; +} + +.defect-saved-item:last-child { + margin-bottom: 0; +} + +.defect-saved-info { + flex: 1; + min-width: 0; + display: flex; + flex-direction: column; + gap: 0.125rem; +} + +.defect-saved-category { + font-size: 0.75rem; + font-weight: 600; + color: #16a34a; +} + +.defect-saved-detail { + font-size: 0.8125rem; + color: #374151; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; +} + +.defect-saved-actions { + display: flex; + align-items: center; + gap: 0.5rem; + flex-shrink: 0; +} + +.defect-saved-hours { + font-size: 0.8125rem; + font-weight: 600; + color: #dc2626; + background: #fee2e2; + padding: 0.25rem 0.625rem; + border-radius: 4px; + white-space: nowrap; +} + +.btn-edit-defect { + padding: 0.25rem 0.625rem; + background: #3b82f6; + color: white; + border: none; + border-radius: 4px; + font-size: 0.75rem; + font-weight: 500; + cursor: pointer; + transition: background 0.2s; +} + +.btn-edit-defect:hover { + background: #2563eb; +} + +.btn-delete-defect { + padding: 0.25rem 0.625rem; + background: #ef4444; + color: white; + border: none; + border-radius: 4px; + font-size: 0.75rem; + font-weight: 500; + cursor: pointer; + transition: background 0.2s; +} + +.btn-delete-defect:hover { + background: #dc2626; +} + +/* 입력 중 섹션 */ +.defect-editing-section { + margin-top: 0.5rem; +} + +/* 반응형 - 저장된 부적합 */ +@media (max-width: 640px) { + .defect-saved-item { + flex-direction: column; + align-items: flex-start; + gap: 0.5rem; + } + + .defect-saved-actions { + width: 100%; + justify-content: flex-end; + } +} + +/* 반응형 - 모바일 */ +@media (max-width: 640px) { + .defect-cascading-row { + flex-direction: column; + align-items: stretch; + } + + .defect-field { + width: 100%; + max-width: none; + } + + .defect-category-select, + .defect-item-select { + max-width: none; + } + + .defect-field-time { + flex-direction: row; + align-items: center; + gap: 0.5rem; + } + + .defect-field-time .defect-field-label { + min-width: 40px; + } + + .btn-remove-defect { + align-self: flex-end; + margin-top: 0.5rem; + } +} + +/* 이슈 없음 상태 */ +.defect-no-issues { + display: flex; + align-items: center; + justify-content: space-between; + padding: 1rem; + background: #f9fafb; + border: 1px dashed #d1d5db; + border-radius: 8px; + margin-bottom: 0.5rem; +} + +.no-issues-text { + color: #6b7280; + font-size: 0.875rem; +} diff --git a/deploy/tkfb-package/web-ui/css/design-system.css b/deploy/tkfb-package/web-ui/css/design-system.css new file mode 100644 index 0000000..ee1b15c --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/design-system.css @@ -0,0 +1,477 @@ +/* ✅ design-system.css - 한글 기반 모던 디자인 시스템 */ + +/* ========== 색상 시스템 ========== */ +:root { + /* 주요 브랜드 색상 (하늘색 계열) */ + --primary-50: #f0f9ff; + --primary-100: #e0f2fe; + --primary-200: #bae6fd; + --primary-300: #7dd3fc; + --primary-400: #38bdf8; + --primary-500: #0ea5e9; + --primary-600: #0284c7; + --primary-700: #0369a1; + --primary-800: #075985; + --primary-900: #0c4a6e; + + /* 헤더 그라디언트 */ + --header-gradient: linear-gradient(135deg, #0ea5e9 0%, #38bdf8 50%, #7dd3fc 100%); + + /* 보조 색상 */ + --secondary-50: #f3e5f5; + --secondary-100: #e1bee7; + --secondary-200: #ce93d8; + --secondary-300: #ba68c8; + --secondary-400: #ab47bc; + --secondary-500: #9c27b0; + --secondary-600: #8e24aa; + --secondary-700: #7b1fa2; + --secondary-800: #6a1b9a; + --secondary-900: #4a148c; + + /* 그레이 스케일 */ + --gray-50: #fafafa; + --gray-100: #f5f5f5; + --gray-200: #eeeeee; + --gray-300: #e0e0e0; + --gray-400: #bdbdbd; + --gray-500: #9e9e9e; + --gray-600: #757575; + --gray-700: #616161; + --gray-800: #424242; + --gray-900: #212121; + + /* 상태 색상 */ + --success-50: #e8f5e8; + --success-500: #4caf50; + --success-700: #388e3c; + + --warning-50: #fff8e1; + --warning-500: #ff9800; + --warning-700: #f57c00; + + --error-50: #ffebee; + --error-500: #f44336; + --error-700: #d32f2f; + + --info-50: #e1f5fe; + --info-500: #03a9f4; + --info-700: #0288d1; + + /* 따뜻한 중성 색상 (베이지/크림) */ + --warm-50: #fafaf9; /* 매우 밝은 크림 */ + --warm-100: #f5f5f4; /* 밝은 크림 */ + --warm-200: #e7e5e4; /* 베이지 */ + --warm-300: #d6d3d1; /* 중간 베이지 */ + --warm-400: #a8a29e; /* 진한 베이지 */ + --warm-500: #78716c; /* 그레이 베이지 */ + + /* 부드러운 작업 상태 색상 (눈이 편한 톤) */ + --status-success-bg: #dcfce7; /* 부드러운 초록 배경 */ + --status-success-text: #16a34a; /* 부드러운 초록 텍스트 */ + --status-info-bg: #e0f2fe; /* 부드러운 하늘색 배경 */ + --status-info-text: #0284c7; /* 부드러운 하늘색 텍스트 */ + --status-warning-bg: #fef3c7; /* 부드러운 노랑 배경 */ + --status-warning-text: #ca8a04; /* 부드러운 노랑 텍스트 */ + --status-error-bg: #fee2e2; /* 부드러운 빨강 배경 */ + --status-error-text: #dc2626; /* 부드러운 빨강 텍스트 */ + --status-critical-bg: #fecaca; /* 진한 빨강 배경 */ + --status-critical-text: #b91c1c; /* 진한 빨강 텍스트 */ + --status-vacation-bg: #fed7aa; /* 부드러운 주황 배경 */ + --status-vacation-text: #ea580c; /* 부드러운 주황 텍스트 */ + + /* 배경 색상 */ + --bg-primary: #ffffff; + --bg-secondary: #f8fafc; + --bg-tertiary: #f1f5f9; + --bg-overlay: rgba(0, 0, 0, 0.5); + + /* 텍스트 색상 */ + --text-primary: #1a202c; + --text-secondary: #4a5568; + --text-tertiary: #718096; + --text-inverse: #ffffff; + + /* 경계선 */ + --border-light: #e2e8f0; + --border-medium: #cbd5e0; + --border-dark: #a0aec0; + + /* 그림자 */ + --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05); + --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); + --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05); + --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04); + + /* 반경 */ + --radius-sm: 4px; + --radius-md: 8px; + --radius-lg: 12px; + --radius-xl: 16px; + --radius-full: 9999px; + + /* 간격 */ + --space-1: 4px; + --space-2: 8px; + --space-3: 12px; + --space-4: 16px; + --space-5: 20px; + --space-6: 24px; + --space-8: 32px; + --space-10: 40px; + --space-12: 48px; + --space-16: 64px; + --space-20: 80px; + --space-24: 96px; + + /* 폰트 크기 */ + --text-xs: 12px; + --text-sm: 14px; + --text-base: 16px; + --text-lg: 18px; + --text-xl: 20px; + --text-2xl: 24px; + --text-3xl: 30px; + --text-4xl: 36px; + --text-5xl: 48px; + + /* 폰트 두께 */ + --font-light: 300; + --font-normal: 400; + --font-medium: 500; + --font-semibold: 600; + --font-bold: 700; + --font-extrabold: 800; + + /* 애니메이션 */ + --transition-fast: 150ms ease-in-out; + --transition-normal: 250ms ease-in-out; + --transition-slow: 350ms ease-in-out; +} + +/* ========== 기본 리셋 ========== */ +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + font-family: 'Pretendard', 'Malgun Gothic', 'Apple SD Gothic Neo', system-ui, sans-serif; + font-size: var(--text-base); + line-height: 1.6; + color: var(--text-primary); + background-color: var(--bg-secondary); + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +/* ========== 타이포그래피 ========== */ +.text-xs { font-size: var(--text-xs); } +.text-sm { font-size: var(--text-sm); } +.text-base { font-size: var(--text-base); } +.text-lg { font-size: var(--text-lg); } +.text-xl { font-size: var(--text-xl); } +.text-2xl { font-size: var(--text-2xl); } +.text-3xl { font-size: var(--text-3xl); } +.text-4xl { font-size: var(--text-4xl); } +.text-5xl { font-size: var(--text-5xl); } + +.font-light { font-weight: var(--font-light); } +.font-normal { font-weight: var(--font-normal); } +.font-medium { font-weight: var(--font-medium); } +.font-semibold { font-weight: var(--font-semibold); } +.font-bold { font-weight: var(--font-bold); } +.font-extrabold { font-weight: var(--font-extrabold); } + +.text-primary { color: var(--text-primary); } +.text-secondary { color: var(--text-secondary); } +.text-tertiary { color: var(--text-tertiary); } +.text-inverse { color: var(--text-inverse); } + +/* ========== 카드 컴포넌트 ========== */ +.card { + background: var(--bg-primary); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-sm); + border: 1px solid var(--border-light); + transition: var(--transition-normal); +} + +.card:hover { + box-shadow: var(--shadow-md); + transform: translateY(-1px); +} + +.card-header { + padding: var(--space-6); + border-bottom: 1px solid var(--border-light); +} + +.card-body { + padding: var(--space-6); +} + +.card-footer { + padding: var(--space-6); + border-top: 1px solid var(--border-light); + background: var(--bg-tertiary); + border-radius: 0 0 var(--radius-lg) var(--radius-lg); +} + +/* ========== 버튼 컴포넌트 ========== */ +.btn { + display: inline-flex; + align-items: center; + justify-content: center; + gap: var(--space-2); + padding: var(--space-3) var(--space-4); + font-size: var(--text-sm); + font-weight: var(--font-medium); + border-radius: var(--radius-md); + border: none; + cursor: pointer; + transition: var(--transition-fast); + text-decoration: none; + white-space: nowrap; +} + +.btn:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +.btn-primary { + background: var(--primary-500); + color: var(--text-inverse); +} + +.btn-primary:hover:not(:disabled) { + background: var(--primary-600); + transform: translateY(-1px); + box-shadow: var(--shadow-md); +} + +.btn-secondary { + background: var(--gray-100); + color: var(--text-primary); + border: 1px solid var(--border-medium); +} + +.btn-secondary:hover:not(:disabled) { + background: var(--gray-200); +} + +.btn-success { + background: var(--success-500); + color: var(--text-inverse); +} + +.btn-success:hover:not(:disabled) { + background: var(--success-700); +} + +.btn-warning { + background: var(--warning-500); + color: var(--text-inverse); +} + +.btn-warning:hover:not(:disabled) { + background: var(--warning-700); +} + +.btn-error { + background: var(--error-500); + color: var(--text-inverse); +} + +.btn-error:hover:not(:disabled) { + background: var(--error-700); +} + +.btn-sm { + padding: var(--space-2) var(--space-3); + font-size: var(--text-xs); +} + +.btn-lg { + padding: var(--space-4) var(--space-6); + font-size: var(--text-lg); +} + +/* ========== 배지 컴포넌트 ========== */ +.badge { + display: inline-flex; + align-items: center; + gap: var(--space-1); + padding: var(--space-1) var(--space-2); + font-size: var(--text-xs); + font-weight: var(--font-medium); + border-radius: var(--radius-full); + white-space: nowrap; +} + +.badge-primary { + background: var(--primary-100); + color: var(--primary-800); +} + +.badge-success { + background: var(--success-50); + color: var(--success-700); +} + +.badge-warning { + background: var(--warning-50); + color: var(--warning-700); +} + +.badge-error { + background: var(--error-50); + color: var(--error-700); +} + +.badge-gray { + background: var(--gray-100); + color: var(--gray-700); +} + +/* ========== 상태 표시기 ========== */ +.status-dot { + display: inline-block; + width: 8px; + height: 8px; + border-radius: var(--radius-full); + margin-right: var(--space-2); +} + +.status-dot.active { + background: var(--success-500); + box-shadow: 0 0 0 2px var(--success-100); +} + +.status-dot.inactive { + background: var(--gray-400); +} + +.status-dot.warning { + background: var(--warning-500); + box-shadow: 0 0 0 2px var(--warning-100); +} + +.status-dot.error { + background: var(--error-500); + box-shadow: 0 0 0 2px var(--error-100); +} + +/* ========== 그리드 시스템 ========== */ +.grid { + display: grid; + gap: var(--space-6); +} + +.grid-cols-1 { grid-template-columns: repeat(1, 1fr); } +.grid-cols-2 { grid-template-columns: repeat(2, 1fr); } +.grid-cols-3 { grid-template-columns: repeat(3, 1fr); } +.grid-cols-4 { grid-template-columns: repeat(4, 1fr); } + +@media (max-width: 768px) { + .grid-cols-2, + .grid-cols-3, + .grid-cols-4 { + grid-template-columns: 1fr; + } +} + +/* ========== 플렉스 유틸리티 ========== */ +.flex { display: flex; } +.flex-col { flex-direction: column; } +.items-center { align-items: center; } +.items-start { align-items: flex-start; } +.items-end { align-items: flex-end; } +.justify-center { justify-content: center; } +.justify-between { justify-content: space-between; } +.justify-start { justify-content: flex-start; } +.justify-end { justify-content: flex-end; } +.gap-1 { gap: var(--space-1); } +.gap-2 { gap: var(--space-2); } +.gap-3 { gap: var(--space-3); } +.gap-4 { gap: var(--space-4); } +.gap-6 { gap: var(--space-6); } + +/* ========== 간격 유틸리티 ========== */ +.p-1 { padding: var(--space-1); } +.p-2 { padding: var(--space-2); } +.p-3 { padding: var(--space-3); } +.p-4 { padding: var(--space-4); } +.p-6 { padding: var(--space-6); } +.p-8 { padding: var(--space-8); } + +.m-1 { margin: var(--space-1); } +.m-2 { margin: var(--space-2); } +.m-3 { margin: var(--space-3); } +.m-4 { margin: var(--space-4); } +.m-6 { margin: var(--space-6); } +.m-8 { margin: var(--space-8); } + +.mb-2 { margin-bottom: var(--space-2); } +.mb-4 { margin-bottom: var(--space-4); } +.mb-6 { margin-bottom: var(--space-6); } +.mt-4 { margin-top: var(--space-4); } +.mt-6 { margin-top: var(--space-6); } + +/* ========== 반응형 유틸리티 ========== */ +@media (max-width: 640px) { + .sm\:hidden { display: none; } + .sm\:text-sm { font-size: var(--text-sm); } + .sm\:p-4 { padding: var(--space-4); } +} + +@media (max-width: 768px) { + .md\:hidden { display: none; } + .md\:flex-col { flex-direction: column; } +} + +@media (max-width: 1024px) { + .lg\:hidden { display: none; } +} + +/* ========== 애니메이션 ========== */ +.fade-in { + animation: fadeIn var(--transition-normal) ease-in-out; +} + +.slide-up { + animation: slideUp var(--transition-normal) ease-out; +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes slideUp { + from { + opacity: 0; + transform: translateY(20px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +/* ========== 로딩 스피너 ========== */ +.spinner { + width: 20px; + height: 20px; + border: 2px solid var(--gray-200); + border-top: 2px solid var(--primary-500); + border-radius: var(--radius-full); + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} diff --git a/deploy/tkfb-package/web-ui/css/equipment-detail.css b/deploy/tkfb-package/web-ui/css/equipment-detail.css new file mode 100644 index 0000000..c5cf94f --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/equipment-detail.css @@ -0,0 +1,509 @@ +/* equipment-detail.css - 설비 상세 페이지 스타일 */ + +/* 헤더 */ +.eq-detail-header { + display: flex; + justify-content: space-between; + align-items: flex-start; + gap: 1rem; +} + +.eq-detail-header .page-title-section { + display: flex; + align-items: flex-start; + gap: 1rem; +} + +.btn-back { + display: flex; + align-items: center; + gap: 0.25rem; + padding: 0.5rem 0.75rem; + background: #f3f4f6; + border: 1px solid #d1d5db; + border-radius: 6px; + cursor: pointer; + font-size: 0.875rem; + color: #374151; + transition: all 0.15s ease; +} + +.btn-back:hover { + background: #e5e7eb; +} + +.back-arrow { + font-size: 1.1rem; +} + +.eq-header-info { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.eq-header-meta { + font-size: 0.875rem; + color: #6b7280; +} + +.eq-status-badge { + padding: 0.375rem 0.75rem; + border-radius: 20px; + font-size: 0.75rem; + font-weight: 600; + white-space: nowrap; +} + +.eq-status-badge.active { background: #d1fae5; color: #065f46; } +.eq-status-badge.maintenance { background: #fef3c7; color: #92400e; } +.eq-status-badge.repair_needed { background: #fee2e2; color: #991b1b; } +.eq-status-badge.inactive { background: #e5e7eb; color: #374151; } +.eq-status-badge.external { background: #dbeafe; color: #1e40af; } +.eq-status-badge.repair_external { background: #ede9fe; color: #5b21b6; } + +/* 기본 정보 카드 */ +.eq-info-card { + background: white; + border-radius: 12px; + padding: 1.25rem; + margin-bottom: 1.5rem; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} + +.eq-info-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: 1rem; +} + +.eq-info-item { + display: flex; + flex-direction: column; + gap: 0.25rem; +} + +.eq-info-label { + font-size: 0.75rem; + color: #6b7280; + font-weight: 500; +} + +.eq-info-value { + font-size: 0.9375rem; + color: #111827; +} + +/* 섹션 */ +.eq-section { + background: white; + border-radius: 12px; + padding: 1.25rem; + margin-bottom: 1.5rem; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); +} + +.eq-section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1rem; +} + +.eq-section-title { + font-size: 1rem; + font-weight: 600; + color: #111827; + margin: 0; +} + +/* 사진 그리드 */ +.eq-photo-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); + gap: 0.75rem; +} + +.eq-photo-item { + position: relative; + aspect-ratio: 1; + border-radius: 8px; + overflow: hidden; + cursor: pointer; +} + +.eq-photo-item img { + width: 100%; + height: 100%; + object-fit: cover; + transition: transform 0.2s ease; +} + +.eq-photo-item:hover img { + transform: scale(1.05); +} + +.eq-photo-delete { + position: absolute; + top: 4px; + right: 4px; + width: 24px; + height: 24px; + background: rgba(239, 68, 68, 0.9); + border: none; + border-radius: 50%; + color: white; + font-size: 14px; + cursor: pointer; + opacity: 0; + transition: opacity 0.2s ease; + display: flex; + align-items: center; + justify-content: center; +} + +.eq-photo-item:hover .eq-photo-delete { + opacity: 1; +} + +.eq-photo-empty { + grid-column: 1 / -1; + text-align: center; + padding: 2rem; + color: #9ca3af; + font-size: 0.875rem; +} + +/* 위치 정보 */ +.eq-location-card { + display: flex; + gap: 1.5rem; + align-items: flex-start; +} + +.eq-location-info { + flex: 1; + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.eq-location-row { + display: flex; + gap: 0.5rem; +} + +.eq-location-label { + font-size: 0.875rem; + color: #6b7280; + min-width: 80px; +} + +.eq-location-value { + font-size: 0.875rem; + color: #111827; + font-weight: 500; +} + +.eq-location-value.eq-moved { + color: #dc2626; +} + +.eq-map-preview { + width: 200px; + height: 150px; + background: #f3f4f6; + border-radius: 8px; + overflow: hidden; + position: relative; +} + +.eq-map-preview img { + width: 100%; + height: 100%; + object-fit: cover; +} + +.eq-map-marker { + position: absolute; + width: 12px; + height: 12px; + background: #dc2626; + border: 2px solid white; + border-radius: 50%; + transform: translate(-50%, -50%); + box-shadow: 0 2px 4px rgba(0,0,0,0.3); +} + +/* 액션 버튼 */ +.eq-action-buttons { + display: flex; + gap: 0.75rem; + margin-bottom: 1.5rem; + flex-wrap: wrap; +} + +.btn-action { + flex: 1; + min-width: 140px; + display: flex; + align-items: center; + justify-content: center; + gap: 0.5rem; + padding: 0.875rem 1rem; + border-radius: 10px; + font-size: 0.9375rem; + font-weight: 600; + border: none; + cursor: pointer; + transition: all 0.15s ease; +} + +.btn-action .btn-icon { + font-size: 1.25rem; +} + +.btn-move { + background: #dbeafe; + color: #1e40af; +} +.btn-move:hover { background: #bfdbfe; } + +.btn-repair { + background: #fef3c7; + color: #92400e; +} +.btn-repair:hover { background: #fde68a; } + +.btn-export { + background: #ede9fe; + color: #5b21b6; +} +.btn-export:hover { background: #ddd6fe; } + +/* 이력 리스트 */ +.eq-history-list { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.eq-history-item { + display: flex; + gap: 1rem; + padding: 0.875rem; + background: #f9fafb; + border-radius: 8px; + align-items: flex-start; +} + +.eq-history-date { + font-size: 0.8125rem; + color: #6b7280; + white-space: nowrap; + min-width: 80px; +} + +.eq-history-content { + flex: 1; +} + +.eq-history-title { + font-size: 0.875rem; + font-weight: 500; + color: #111827; + margin-bottom: 0.25rem; +} + +.eq-history-detail { + font-size: 0.8125rem; + color: #6b7280; +} + +.eq-history-status { + font-size: 0.75rem; + padding: 0.25rem 0.5rem; + border-radius: 12px; + font-weight: 500; +} + +.eq-history-status.pending { background: #fef3c7; color: #92400e; } +.eq-history-status.in_progress { background: #dbeafe; color: #1e40af; } +.eq-history-status.completed { background: #d1fae5; color: #065f46; } +.eq-history-status.exported { background: #ede9fe; color: #5b21b6; } +.eq-history-status.returned { background: #d1fae5; color: #065f46; } + +.eq-history-empty { + text-align: center; + padding: 1.5rem; + color: #9ca3af; + font-size: 0.875rem; +} + +.eq-history-action { + padding: 0.375rem 0.75rem; + background: #10b981; + color: white; + border: none; + border-radius: 6px; + font-size: 0.75rem; + cursor: pointer; +} + +.eq-history-action:hover { + background: #059669; +} + +/* 모달 스타일 추가 */ +.photo-preview-container { + margin-top: 1rem; + text-align: center; +} + +.photo-preview { + max-width: 100%; + max-height: 300px; + border-radius: 8px; +} + +.move-step { + min-height: 200px; +} + +.move-instruction { + font-size: 0.875rem; + color: #6b7280; + margin-bottom: 1rem; + text-align: center; +} + +.move-map-container { + width: 100%; + height: 300px; + background: #f3f4f6; + border-radius: 8px; + margin-bottom: 1rem; + position: relative; + overflow: hidden; +} + +.move-map-container img { + width: 100%; + height: 100%; + object-fit: contain; + cursor: crosshair; +} + +.move-marker { + position: absolute; + width: 20px; + height: 20px; + background: #dc2626; + border: 3px solid white; + border-radius: 50%; + transform: translate(-50%, -50%); + box-shadow: 0 2px 8px rgba(0,0,0,0.3); + pointer-events: none; +} + +.checkbox-label { + display: flex; + align-items: center; + gap: 0.5rem; + cursor: pointer; +} + +.checkbox-label input[type="checkbox"] { + width: 18px; + height: 18px; +} + +.repair-photo-previews { + display: flex; + gap: 0.5rem; + flex-wrap: wrap; + margin-top: 0.5rem; +} + +.repair-photo-preview { + width: 60px; + height: 60px; + border-radius: 6px; + object-fit: cover; +} + +/* 사진 확대 보기 */ +.photo-view-container { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0,0,0,0.9); + display: flex; + align-items: center; + justify-content: center; + z-index: 1000; + cursor: pointer; +} + +.photo-view-close { + position: absolute; + top: 20px; + right: 20px; + background: none; + border: none; + color: white; + font-size: 2rem; + cursor: pointer; +} + +.photo-view-image { + max-width: 90%; + max-height: 90%; + object-fit: contain; +} + +/* 버튼 스타일 */ +.btn-sm { + padding: 0.375rem 0.75rem; + font-size: 0.8125rem; +} + +.btn-outline { + background: transparent; + border: 1px solid #d1d5db; + color: #374151; +} + +.btn-outline:hover { + background: #f3f4f6; +} + +/* 반응형 */ +@media (max-width: 768px) { + .eq-detail-header { + flex-direction: column; + } + + .eq-location-card { + flex-direction: column; + } + + .eq-map-preview { + width: 100%; + height: 200px; + } + + .eq-action-buttons { + flex-direction: column; + } + + .btn-action { + min-width: auto; + } + + .eq-info-grid { + grid-template-columns: repeat(2, 1fr); + } +} diff --git a/deploy/tkfb-package/web-ui/css/equipment-management.css b/deploy/tkfb-package/web-ui/css/equipment-management.css new file mode 100644 index 0000000..20f6d48 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/equipment-management.css @@ -0,0 +1,361 @@ +/* equipment-management.css */ +/* 설비 관리 페이지 전용 스타일 */ + +/* 통계 요약 섹션 */ +.eq-stats-section { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); + gap: 1rem; + margin-bottom: 1.5rem; +} + +.eq-stat-card { + background: linear-gradient(135deg, #ffffff 0%, #f8fafc 100%); + border-radius: 12px; + padding: 1.25rem; + border: 1px solid #e2e8f0; + transition: all 0.2s ease; +} + +.eq-stat-card:hover { + transform: translateY(-2px); + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08); +} + +.eq-stat-card.highlight { + background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%); + color: white; + border: none; +} + +.eq-stat-card.highlight .eq-stat-label { + color: rgba(255, 255, 255, 0.85); +} + +.eq-stat-label { + font-size: 0.8rem; + color: #64748b; + margin-bottom: 0.5rem; + font-weight: 500; +} + +.eq-stat-value { + font-size: 1.75rem; + font-weight: 700; + line-height: 1.2; +} + +.eq-stat-sub { + font-size: 0.75rem; + color: #94a3b8; + margin-top: 0.25rem; +} + +.eq-stat-card.highlight .eq-stat-sub { + color: rgba(255, 255, 255, 0.7); +} + +/* 필터 섹션 개선 */ +.eq-filter-section { + background: #f8fafc; + border-radius: 12px; + padding: 1rem 1.25rem; + margin-bottom: 1.5rem; + display: flex; + flex-wrap: wrap; + gap: 1rem; + align-items: flex-end; +} + +.eq-filter-group { + display: flex; + flex-direction: column; + gap: 0.35rem; + min-width: 140px; +} + +.eq-filter-group label { + font-size: 0.75rem; + font-weight: 600; + color: #64748b; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.eq-filter-group .form-control { + padding: 0.5rem 0.75rem; + font-size: 0.875rem; + border-radius: 8px; + border: 1px solid #e2e8f0; + background: white; +} + +.eq-filter-group .form-control:focus { + border-color: #3b82f6; + box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1); +} + +.eq-search-group { + flex: 1; + min-width: 200px; +} + +.eq-search-group .form-control { + width: 100%; +} + +/* 테이블 개선 */ +.eq-table-container { + background: white; + border-radius: 12px; + border: 1px solid #e2e8f0; + overflow: hidden; +} + +.eq-table { + width: 100%; + border-collapse: collapse; + font-size: 0.875rem; +} + +.eq-table thead { + background: #f1f5f9; + position: sticky; + top: 0; + z-index: 10; +} + +.eq-table th { + padding: 0.875rem 1rem; + text-align: left; + font-weight: 600; + color: #475569; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 0.5px; + border-bottom: 2px solid #e2e8f0; + white-space: nowrap; +} + +.eq-table td { + padding: 0.75rem 1rem; + border-bottom: 1px solid #f1f5f9; + vertical-align: middle; +} + +.eq-table tbody tr { + transition: background 0.15s ease; +} + +.eq-table tbody tr:hover { + background: #f8fafc; +} + +.eq-table tbody tr:last-child td { + border-bottom: none; +} + +/* 테이블 컬럼별 스타일 */ +.eq-col-code { + font-weight: 600; + color: #1e40af; + white-space: nowrap; +} + +.eq-col-name { + font-weight: 500; + color: #1e293b; + max-width: 200px; +} + +.eq-col-model, +.eq-col-spec { + color: #64748b; + font-size: 0.8125rem; + max-width: 150px; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +.eq-col-price { + font-weight: 600; + color: #059669; + text-align: right; + white-space: nowrap; +} + +.eq-col-date { + color: #64748b; + font-size: 0.8125rem; + white-space: nowrap; +} + +/* 상태 배지 */ +.eq-status { + display: inline-flex; + align-items: center; + padding: 0.25rem 0.625rem; + border-radius: 9999px; + font-size: 0.75rem; + font-weight: 600; + white-space: nowrap; +} + +.eq-status-active { + background: #dcfce7; + color: #166534; +} + +.eq-status-maintenance { + background: #fef3c7; + color: #92400e; +} + +.eq-status-inactive { + background: #fee2e2; + color: #991b1b; +} + +/* 액션 버튼 */ +.eq-actions { + display: flex; + gap: 0.5rem; +} + +.eq-btn-action { + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + border: none; + border-radius: 8px; + cursor: pointer; + transition: all 0.15s ease; + font-size: 0.875rem; +} + +.eq-btn-edit { + background: #eff6ff; + color: #3b82f6; +} + +.eq-btn-edit:hover { + background: #3b82f6; + color: white; +} + +.eq-btn-delete { + background: #fef2f2; + color: #ef4444; +} + +.eq-btn-delete:hover { + background: #ef4444; + color: white; +} + +/* 빈 상태 */ +.eq-empty-state { + text-align: center; + padding: 4rem 2rem; + color: #64748b; +} + +.eq-empty-state p { + margin-bottom: 1.5rem; + font-size: 1rem; +} + +/* 테이블 스크롤 래퍼 */ +.eq-table-wrapper { + overflow-x: auto; + max-height: calc(100vh - 380px); + overflow-y: auto; +} + +/* 결과 카운트 */ +.eq-result-count { + display: flex; + justify-content: space-between; + align-items: center; + padding: 0.75rem 1rem; + background: #f8fafc; + border-bottom: 1px solid #e2e8f0; + font-size: 0.8125rem; + color: #64748b; +} + +.eq-result-count strong { + color: #1e293b; +} + +/* 반응형 */ +@media (max-width: 1200px) { + .eq-stats-section { + grid-template-columns: repeat(3, 1fr); + } +} + +@media (max-width: 768px) { + .eq-stats-section { + grid-template-columns: repeat(2, 1fr); + } + + .eq-filter-section { + flex-direction: column; + } + + .eq-filter-group { + width: 100%; + } + + .eq-table th, + .eq-table td { + padding: 0.625rem 0.75rem; + } + + .eq-col-spec, + .eq-col-model { + display: none; + } +} + +/* 모달 개선 */ +.eq-modal-body { + padding: 1.5rem; +} + +.eq-form-section { + margin-bottom: 1.5rem; + padding-bottom: 1.5rem; + border-bottom: 1px solid #f1f5f9; +} + +.eq-form-section:last-child { + margin-bottom: 0; + padding-bottom: 0; + border-bottom: none; +} + +.eq-form-section-title { + font-size: 0.8rem; + font-weight: 600; + color: #3b82f6; + text-transform: uppercase; + letter-spacing: 0.5px; + margin-bottom: 1rem; +} + +.eq-form-row { + display: grid; + grid-template-columns: repeat(2, 1fr); + gap: 1rem; +} + +@media (max-width: 600px) { + .eq-form-row { + grid-template-columns: 1fr; + } +} diff --git a/deploy/tkfb-package/web-ui/css/factory.css b/deploy/tkfb-package/web-ui/css/factory.css new file mode 100644 index 0000000..e7dcd68 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/factory.css @@ -0,0 +1,61 @@ +body { + font-family: 'Segoe UI', sans-serif; + background-color: #f9f9f9; + margin: 0; + padding: 0; +} + +.container { + max-width: 600px; + margin: 50px auto; + background: #fff; + border-radius: 12px; + box-shadow: 0 4px 12px rgba(0,0,0,0.1); + padding: 30px; +} + +h2 { + text-align: center; + margin-bottom: 20px; + color: #333; +} + +form label { + display: block; + margin-bottom: 6px; + font-weight: bold; + color: #444; +} + +form input[type="text"], +form input[type="file"], +form textarea { + width: 100%; + padding: 10px; + margin-bottom: 16px; + border: 1px solid #ccc; + border-radius: 8px; + font-size: 14px; + box-sizing: border-box; +} + +form textarea { + resize: vertical; + min-height: 100px; +} + +button { + width: 100%; + background-color: #007bff; + color: white; + border: none; + padding: 12px; + font-size: 16px; + border-radius: 8px; + cursor: pointer; + transition: background-color 0.3s ease; +} + +button:hover { + background-color: #0056b3; +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/css/login.css b/deploy/tkfb-package/web-ui/css/login.css new file mode 100644 index 0000000..3f9061e --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/login.css @@ -0,0 +1,54 @@ +body { + margin: 0; + padding: 0; + background: url('/img/login-bg.jpeg') no-repeat center center fixed; + background-size: cover; + font-family: 'Malgun Gothic', sans-serif; +} + +.login-container { + background: rgba(0, 0, 0, 0.65); + width: 400px; + padding: 40px; + margin: 100px auto; + border-radius: 12px; + text-align: center; + color: white; + box-shadow: 0 0 20px rgba(0,0,0,0.3); +} + +.logo { + width: 200px; + margin-bottom: 20px; +} + +input { + display: block; + width: 100%; + margin: 15px 0; + padding: 12px; + font-size: 1rem; + border-radius: 6px; + border: none; +} + +button { + padding: 12px 20px; + font-size: 1rem; + cursor: pointer; + border: none; + background-color: #1976d2; + color: white; + border-radius: 6px; + transition: background-color 0.3s; +} + +button:hover { + background-color: #1565c0; +} + +.error-message { + margin-top: 10px; + color: #ff6b6b; + font-weight: bold; +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/css/main-layout.css b/deploy/tkfb-package/web-ui/css/main-layout.css new file mode 100644 index 0000000..6467328 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/main-layout.css @@ -0,0 +1,160 @@ +/* ✅ /css/main-layout.css - 공통 레이아웃 스타일 */ + +* { + box-sizing: border-box; +} + +body { + margin: 0; + padding: 0; + font-family: 'Malgun Gothic', 'Apple SD Gothic Neo', sans-serif; + background-color: #f5f5f5; +} + +/* 메인 레이아웃 구조 */ +.main-layout { + display: flex; + min-height: 100vh; + flex-direction: column; +} + +#navbar-container { + position: sticky; + top: 0; + z-index: 1000; +} + +.content-wrapper { + display: flex; + flex: 1; +} + +#sidebar-container { + flex-shrink: 0; +} + +#content-container, +#sections-container, +#admin-sections, +#user-sections { + flex: 1; + padding: 24px; + max-width: 1200px; + margin: 0 auto; + width: 100%; +} + +/* 카드 스타일 */ +.card { + background: white; + border-radius: 8px; + padding: 24px; + margin-bottom: 24px; + box-shadow: 0 2px 4px rgba(0,0,0,0.08); +} + +/* 섹션 스타일 */ +section { + background: white; + border-radius: 8px; + padding: 20px; + margin-bottom: 20px; + box-shadow: 0 2px 4px rgba(0,0,0,0.08); +} + +section h2 { + font-size: 18px; + margin: 0 0 16px 0; + color: #333; + border-bottom: 2px solid #1976d2; + padding-bottom: 8px; +} + +section ul { + list-style: none; + padding: 0; + margin: 0; +} + +section li { + padding: 8px 0; + border-bottom: 1px solid #f0f0f0; +} + +section li:last-child { + border-bottom: none; +} + +section a { + color: #1976d2; + text-decoration: none; + display: block; + padding: 4px 0; + transition: all 0.3s; +} + +section a:hover { + color: #0d47a1; + padding-left: 8px; +} + +/* 로딩 상태 */ +.loading { + text-align: center; + padding: 60px 20px; + color: #666; +} + +.loading::after { + content: '.'; + animation: dots 1.5s steps(3, end) infinite; +} + +@keyframes dots { + 0%, 20% { content: '.'; } + 40% { content: '..'; } + 60%, 100% { content: '...'; } +} + +/* 에러 상태 */ +.error-state { + text-align: center; + padding: 60px 20px; + color: #d32f2f; +} + +.error-state button { + margin-top: 16px; + padding: 8px 24px; + background: #1976d2; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.error-state button:hover { + background: #1565c0; +} + +/* 반응형 디자인 */ +@media (max-width: 1024px) { + #content-container, + #sections-container { + padding: 16px; + } +} + +@media (max-width: 768px) { + .content-wrapper { + flex-direction: column; + } + + #sidebar-container { + order: -1; + } + + section h2 { + font-size: 16px; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/css/management-dashboard.css b/deploy/tkfb-package/web-ui/css/management-dashboard.css new file mode 100644 index 0000000..08524ef --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/management-dashboard.css @@ -0,0 +1,1005 @@ +/* management-dashboard.css - 관리자 대시보드 전용 스타일 */ + +* { + margin: 0; + padding: 0; + box-sizing: border-box; +} + +body { + font-family: 'Segoe UI', 'Noto Sans KR', Tahoma, Geneva, Verdana, sans-serif; + background-color: #f5f7fa; + color: #333; + line-height: 1.6; +} + +/* 메인 레이아웃 */ +.main-layout-with-navbar { + display: flex; + flex-direction: column; + min-height: 100vh; +} + +.content-wrapper { + flex: 1; + padding: 20px; +} + +.dashboard-container { + max-width: 1400px; + margin: 0 auto; +} + +/* 페이지 헤더 */ +.page-header { + text-align: center; + margin-bottom: 2.5rem; + padding: 3rem 2rem; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 16px; + box-shadow: 0 6px 24px rgba(0,0,0,0.12); + position: relative; +} + +.page-header h1 { + font-size: 2.5rem; + margin-bottom: 0.8rem; + font-weight: 700; +} + +.subtitle { + font-size: 1.1rem; + opacity: 0.9; + margin-bottom: 1rem; +} + +.permission-badge { + display: inline-block; + background: rgba(255,255,255,0.2); + color: white; + padding: 8px 20px; + border-radius: 25px; + font-size: 14px; + font-weight: 600; + border: 2px solid rgba(255,255,255,0.3); +} + +/* 뒤로가기 버튼 */ +.back-btn { + background: rgba(255,255,255,0.95); + color: #667eea; + border: 3px solid #667eea; + padding: 16px 32px; + border-radius: 12px; + text-decoration: none; + font-weight: 700; + font-size: 18px; + display: inline-flex; + align-items: center; + gap: 12px; + margin-bottom: 24px; + transition: all 0.3s ease; + box-shadow: 0 3px 12px rgba(102, 126, 234, 0.2); +} + +.back-btn:hover { + background: #667eea; + color: white; + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(102, 126, 234, 0.3); +} + +/* 메시지 스타일 */ +.message { + padding: 20px 32px; + border-radius: 12px; + margin-bottom: 32px; + font-weight: 600; + font-size: 18px; + box-shadow: 0 3px 12px rgba(0,0,0,0.1); +} + +.message.warning { + background: #fff3cd; + color: #856404; + border: 2px solid #ffeaa7; +} + +.message.error { + background: #f8d7da; + color: #721c24; + border: 2px solid #f5c6cb; +} + +.message.success { + background: #d4edda; + color: #155724; + border: 2px solid #c3e6cb; +} + +.message.loading { + background: #cce5ff; + color: #0066cc; + border: 2px solid #99d6ff; +} + +/* 날짜 선택 카드 */ +.date-selection-card { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); + margin-bottom: 2rem; +} + +.date-selection-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f0f0f0; +} + +.date-selection-header h3 { + margin: 0; + color: #333; + font-size: 1.4rem; +} + +.refresh-btn { + background: #28a745; + color: white; + border: none; + border-radius: 8px; + padding: 12px 20px; + cursor: pointer; + font-size: 14px; + font-weight: 600; + transition: all 0.3s; + display: flex; + align-items: center; + gap: 8px; +} + +.refresh-btn:hover { + background: #1e7e34; + transform: translateY(-1px); +} + +.date-selection-body { + display: flex; + gap: 20px; + align-items: center; + justify-content: center; +} + +.date-input { + padding: 15px 20px; + font-size: 18px; + border: 3px solid #e1e5e9; + border-radius: 12px; + background: white; + transition: border-color 0.3s; + min-width: 200px; +} + +.date-input:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 4px rgba(0, 123, 255, 0.15); +} + +/* 버튼 스타일 */ +.btn { + padding: 15px 30px; + border: none; + border-radius: 12px; + font-size: 16px; + font-weight: 700; + cursor: pointer; + transition: all 0.3s; + display: inline-flex; + align-items: center; + justify-content: center; + gap: 8px; + text-decoration: none; + box-shadow: 0 3px 12px rgba(0,0,0,0.1); +} + +.btn-primary { + background: #007bff; + color: white; +} + +.btn-primary:hover { + background: #0056b3; + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(0, 123, 255, 0.3); +} + +.btn-secondary { + background: #6c757d; + color: white; +} + +.btn-secondary:hover { + background: #545b62; + transform: translateY(-2px); +} + +/* 요약 섹션 */ +.summary-section { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); + margin-bottom: 2rem; +} + +.summary-section h3 { + margin-bottom: 1.5rem; + color: #333; + font-size: 1.4rem; +} + +.summary-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 20px; +} + +.summary-card { + background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); + border-radius: 12px; + padding: 1.5rem; + display: flex; + align-items: center; + gap: 15px; + border: 2px solid #dee2e6; + transition: all 0.3s ease; +} + +.summary-card:hover { + transform: translateY(-3px); + box-shadow: 0 8px 25px rgba(0,0,0,0.1); +} + +.summary-icon { + font-size: 2rem; + width: 60px; + height: 60px; + display: flex; + align-items: center; + justify-content: center; + border-radius: 50%; + background: rgba(255,255,255,0.8); +} + +.summary-content { + flex: 1; +} + +.summary-number { + font-size: 2rem; + font-weight: 700; + color: #333; + line-height: 1; +} + +.summary-label { + font-size: 0.9rem; + color: #666; + margin-top: 4px; +} + +/* 개별 요약 카드 색상 */ +.summary-card.total-workers { + background: linear-gradient(135deg, #e3f2fd 0%, #bbdefb 100%); + border-color: #2196f3; +} + +.summary-card.completed-workers { + background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%); + border-color: #4caf50; +} + +.summary-card.missing-workers { + background: linear-gradient(135deg, #ffebee 0%, #ffcdd2 100%); + border-color: #f44336; +} + +.summary-card.total-hours { + background: linear-gradient(135deg, #f3e5f5 0%, #e1bee7 100%); + border-color: #9c27b0; +} + +.summary-card.total-entries { + background: linear-gradient(135deg, #fff3e0 0%, #ffcc02 100%); + border-color: #ff9800; +} + +.summary-card.error-count { + background: linear-gradient(135deg, #fce4ec 0%, #f8bbd9 100%); + border-color: #e91e63; +} + +/* 액션 바 */ +.action-bar { + background: white; + border-radius: 12px; + padding: 1.5rem; + box-shadow: 0 4px 16px rgba(0,0,0,0.06); + margin-bottom: 2rem; + display: flex; + justify-content: space-between; + align-items: center; +} + +.filter-section { + display: flex; + gap: 20px; + align-items: center; +} + +.filter-checkbox { + display: flex; + align-items: center; + gap: 10px; + cursor: pointer; + font-weight: 600; + font-size: 16px; + color: #333; +} + +.filter-checkbox input[type="checkbox"] { + display: none; +} + +.checkmark { + width: 20px; + height: 20px; + border: 2px solid #007bff; + border-radius: 4px; + position: relative; + transition: all 0.3s ease; +} + +.filter-checkbox input[type="checkbox"]:checked + .checkmark { + background: #007bff; +} + +.filter-checkbox input[type="checkbox"]:checked + .checkmark::after { + content: "✓"; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; + font-weight: bold; + font-size: 12px; +} + +/* 작업자 섹션 */ +.workers-section { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); + margin-bottom: 2rem; +} + +.section-header { + display: flex; + justify-content: space-between; + align-items: center; + margin-bottom: 1.5rem; + padding-bottom: 1rem; + border-bottom: 2px solid #f0f0f0; +} + +.section-header h3 { + margin: 0; + color: #333; + font-size: 1.4rem; +} + +.legend { + display: flex; + gap: 15px; +} + +.legend-item { + font-size: 14px; + font-weight: 600; + padding: 6px 12px; + border-radius: 20px; + border: 2px solid; +} + +.legend-item.completed { + color: #28a745; + border-color: #28a745; + background: rgba(40, 167, 69, 0.1); +} + +.legend-item.missing { + color: #dc3545; + border-color: #dc3545; + background: rgba(220, 53, 69, 0.1); +} + +.legend-item.partial { + color: #ffc107; + border-color: #ffc107; + background: rgba(255, 193, 7, 0.1); +} + +/* 작업자 테이블 스타일 */ +.table-container { + background: white; + border-radius: 12px; + overflow: hidden; + box-shadow: 0 4px 16px rgba(0,0,0,0.06); +} + +.workers-table { + width: 100%; + border-collapse: collapse; + font-size: 14px; +} + +.workers-table thead { + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; +} + +.workers-table th { + padding: 16px 12px; + text-align: left; + font-weight: 700; + font-size: 14px; + border-bottom: 2px solid rgba(255,255,255,0.2); +} + +.workers-table th:first-child { + padding-left: 20px; +} + +.workers-table th:last-child { + padding-right: 20px; +} + +.workers-table tbody tr { + border-bottom: 1px solid #e9ecef; + transition: all 0.3s ease; +} + +.workers-table tbody tr:hover { + background: #f8f9fa; + transform: scale(1.01); + box-shadow: 0 2px 8px rgba(0,0,0,0.1); +} + +.workers-table tbody tr:last-child { + border-bottom: none; +} + +.workers-table td { + padding: 16px 12px; + vertical-align: middle; + line-height: 1.4; +} + +.workers-table td:first-child { + padding-left: 20px; +} + +.workers-table td:last-child { + padding-right: 20px; +} + +/* 작업자 이름 스타일 */ +.worker-name-cell { + font-weight: 700; + color: #333; + display: flex; + align-items: center; + gap: 8px; +} + +/* 상태 배지 스타일 */ +.status-badge { + padding: 6px 12px; + border-radius: 20px; + font-size: 12px; + font-weight: 700; + color: white; + white-space: nowrap; + text-align: center; + min-width: 70px; +} + +.status-badge.completed { + background: linear-gradient(135deg, #28a745 0%, #20c997 100%); +} + +.status-badge.missing { + background: linear-gradient(135deg, #dc3545 0%, #c82333 100%); +} + +.status-badge.partial { + background: linear-gradient(135deg, #ffc107 0%, #e0a800 100%); + color: #333; +} + +/* 시간 표시 스타일 */ +.hours-cell { + font-weight: 700; + font-size: 16px; + color: #495057; +} + +.hours-cell.zero { + color: #dc3545; + opacity: 0.7; +} + +.hours-cell.partial { + color: #ffc107; +} + +.hours-cell.full { + color: #28a745; +} + +/* 작업 유형 태그 */ +.work-types-container { + display: flex; + flex-wrap: wrap; + gap: 4px; + max-width: 120px; +} + +.work-type-tag { + background: #e3f2fd; + color: #1565c0; + padding: 4px 8px; + border-radius: 12px; + font-size: 11px; + font-weight: 600; + white-space: nowrap; + border: 1px solid #bbdefb; +} + +/* 프로젝트 태그 */ +.projects-container { + display: flex; + flex-wrap: wrap; + gap: 4px; + max-width: 150px; +} + +.project-tag { + background: #f3e5f5; + color: #7b1fa2; + padding: 4px 8px; + border-radius: 12px; + font-size: 11px; + font-weight: 600; + white-space: nowrap; + border: 1px solid #e1bee7; +} + +/* 기여자 태그 */ +.contributors-container { + display: flex; + flex-wrap: wrap; + gap: 4px; + max-width: 120px; +} + +.contributor-tag { + background: #e8f5e8; + color: #2e7d32; + padding: 4px 8px; + border-radius: 12px; + font-size: 11px; + font-weight: 600; + white-space: nowrap; + border: 1px solid #c8e6c9; +} + +/* 업데이트 시간 스타일 */ +.update-time { + font-size: 12px; + color: #666; + white-space: nowrap; +} + +.update-time.recent { + color: #28a745; + font-weight: 600; +} + +.update-time.old { + color: #dc3545; +} + +/* 상세 버튼 */ +.detail-btn { + background: linear-gradient(135deg, #007bff 0%, #0056b3 100%); + color: white; + border: none; + border-radius: 20px; + padding: 8px 16px; + cursor: pointer; + font-size: 12px; + font-weight: 600; + transition: all 0.3s; + white-space: nowrap; +} + +.detail-btn:hover { + background: linear-gradient(135deg, #0056b3 0%, #004085 100%); + transform: translateY(-1px); + box-shadow: 0 4px 12px rgba(0, 123, 255, 0.3); +} + +/* 데이터 없음 행 */ +.no-data-row { + text-align: center; + padding: 40px 20px; + color: #666; + font-style: italic; +} + +/* 테이블 반응형 */ +@media (max-width: 1200px) { + .workers-table { + font-size: 13px; + } + + .workers-table th, + .workers-table td { + padding: 12px 8px; + } + + .work-types-container, + .projects-container, + .contributors-container { + max-width: 100px; + } +} + +@media (max-width: 992px) { + .table-container { + overflow-x: auto; + } + + .workers-table { + min-width: 800px; + font-size: 12px; + } + + .workers-table th, + .workers-table td { + padding: 10px 6px; + } + + .work-types-container, + .projects-container, + .contributors-container { + max-width: 80px; + } + + .work-type-tag, + .project-tag, + .contributor-tag { + font-size: 10px; + padding: 3px 6px; + } +} + +@media (max-width: 768px) { + .workers-table { + min-width: 700px; + font-size: 11px; + } + + .workers-table th, + .workers-table td { + padding: 8px 4px; + } + + .status-badge { + font-size: 10px; + padding: 4px 8px; + min-width: 60px; + } + + .detail-btn { + font-size: 10px; + padding: 6px 12px; + } +} + +/* 로딩 스피너 */ +.loading-spinner { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 4rem 2rem; + background: white; + border-radius: 16px; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); +} + +.spinner { + width: 50px; + height: 50px; + border: 4px solid #f3f3f3; + border-top: 4px solid #007bff; + border-radius: 50%; + animation: spin 1s linear infinite; + margin-bottom: 1rem; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} + +.loading-spinner p { + color: #666; + font-size: 1.1rem; + font-weight: 600; +} + +/* 데이터 없음 메시지 */ +.no-data-message { + text-align: center; + padding: 4rem 2rem; + background: white; + border-radius: 16px; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); +} + +.no-data-icon { + font-size: 4rem; + margin-bottom: 1rem; +} + +.no-data-message h3 { + color: #333; + margin-bottom: 1rem; + font-size: 1.5rem; +} + +.no-data-message p { + color: #666; + font-size: 1.1rem; + line-height: 1.6; +} + +/* 작업자 상세 모달 */ +.worker-detail-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.7); + display: flex; + justify-content: center; + align-items: center; + z-index: 1000; + animation: fadeIn 0.3s ease; +} + +.modal-content { + background: white; + border-radius: 16px; + width: 90%; + max-width: 800px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 10px 40px rgba(0,0,0,0.3); + animation: slideIn 0.3s ease; +} + +.modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 24px; + border-bottom: 2px solid #f0f0f0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 16px 16px 0 0; +} + +.modal-header h3 { + margin: 0; + font-size: 20px; + font-weight: 700; +} + +.close-modal-btn { + background: rgba(255,255,255,0.2); + color: white; + border: none; + border-radius: 50%; + width: 32px; + height: 32px; + cursor: pointer; + font-size: 18px; + font-weight: 700; + display: flex; + align-items: center; + justify-content: center; + transition: all 0.3s; +} + +.close-modal-btn:hover { + background: rgba(255,255,255,0.3); + transform: rotate(90deg); +} + +.modal-body { + padding: 24px; +} + +/* 사용법 안내 */ +.guide-section { + background: white; + border-radius: 16px; + padding: 2rem; + box-shadow: 0 6px 24px rgba(0,0,0,0.08); + margin-top: 2rem; +} + +.guide-section h3 { + margin-bottom: 1.5rem; + color: #333; + font-size: 1.4rem; + text-align: center; +} + +.guide-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: 20px; +} + +.guide-item { + text-align: center; + padding: 20px; + background: #f8f9fa; + border-radius: 12px; + border: 2px solid #e9ecef; + transition: all 0.3s ease; +} + +.guide-item:hover { + transform: translateY(-2px); + box-shadow: 0 6px 20px rgba(0,0,0,0.1); + border-color: #667eea; +} + +.guide-icon { + font-size: 28px; + margin-bottom: 12px; +} + +.guide-item strong { + display: block; + font-size: 16px; + font-weight: 700; + margin-bottom: 8px; + color: #333; +} + +/* 애니메이션 */ +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes slideIn { + from { + opacity: 0; + transform: translateY(-50px) scale(0.9); + } + to { + opacity: 1; + transform: translateY(0) scale(1); + } +} + +/* 수정 모달 스타일 */ +.edit-modal { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0,0,0,0.7); + display: flex; + justify-content: center; + align-items: center; + z-index: 1001; /* 상세 모달보다 위에 */ + animation: fadeIn 0.3s ease; +} + +.edit-modal-content { + background: white; + border-radius: 16px; + width: 90%; + max-width: 600px; + max-height: 90vh; + overflow-y: auto; + box-shadow: 0 10px 40px rgba(0,0,0,0.3); + animation: slideIn 0.3s ease; +} + +.edit-modal-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 24px; + border-bottom: 2px solid #f0f0f0; + background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); + color: white; + border-radius: 16px 16px 0 0; +} + +.edit-modal-header h3 { + margin: 0; + font-size: 20px; + font-weight: 700; +} + +.edit-modal-body { + padding: 24px; +} + +.edit-form-group { + margin-bottom: 20px; +} + +.edit-form-group label { + display: block; + margin-bottom: 8px; + font-weight: 700; + color: #555; + font-size: 14px; +} + +.edit-select, .edit-input { + width: 100%; + padding: 12px 16px; + border: 2px solid #e1e5e9; + border-radius: 8px; + font-size: 16px; + background: white; + transition: border-color 0.3s; +} + +.edit-select:focus, .edit-input:focus { + outline: none; + border-color: #007bff; + box-shadow: 0 0 0 3px rgba(0, 123, 255, 0.1); +} + +.edit-modal-footer { + display: flex; + justify-content: flex-end; + gap: 12px; + padding: 24px; + border-top: 2px solid #f0f0f0; + background: #f8f9fa; + border-radius: 0 0 16px 16px; +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/css/modern-dashboard.css b/deploy/tkfb-package/web-ui/css/modern-dashboard.css new file mode 100644 index 0000000..ff148b9 --- /dev/null +++ b/deploy/tkfb-package/web-ui/css/modern-dashboard.css @@ -0,0 +1,4009 @@ +/* ✅ modern-dashboard.css - 모던 대시보드 전용 스타일 */ + +/* ========== 대시보드 레이아웃 ========== */ +.dashboard-container { + min-height: 100vh; + display: flex; + flex-direction: column; + background: linear-gradient(135deg, #f8fafc 0%, #e2e8f0 100%); +} + +/* ========== 메인 레이아웃 ========== */ +.dashboard-main { + flex: 1; + padding: 2rem 0; + min-height: calc(100vh - 80px); +} + +/* ========== 헤더 ========== */ +/* Navbar 컴포넌트가 헤더 스타일을 관리하므로 여기서는 제거 */ +/* 필요한 경우 navbar.html의 + + +
+ + + + + + + +
+
+ +
+
+

HR-001 인사관리 규정

+

채용, 승진, 전보, 퇴직 등 인사관리 전반

+
+
+ + +
+
+

HR-002 급여관리 규정

+

급여체계, 수당, 상여금 지급 기준

+
+
+ + +
+
+

HR-003 근무시간 관리규정

+

근무시간, 휴게시간, 연장근무 규정

+
+
+ + +
+
+

HR-004 휴가 및 휴직규정

+

연차, 병가, 특별휴가, 휴직 관련 규정

+
+
+ + +
+
+

HR-005 복리후생 규정

+

건강보험, 퇴직금, 각종 지원금 규정

+
+
+ + +
+
+

HR-006 성과평가 관리규정

+

성과평가 기준, 절차, 결과 활용 방안

+
+
+ + +
+
+

HR-007 교육훈련 관리규정

+

신입사원 교육, 직무교육, 외부교육 지원

+
+
+ + +
+
+

HR-008 징계 관리규정

+

징계사유, 절차, 징계양정 기준

+
+
+ + +
+
+

HR-009 정보보안 및 기밀유지

+

회사 정보보안 및 기밀유지 의무

+
+
+ + +
+
+

HR-010 복무 및 행동강령

+

직원 복무 기준 및 윤리 행동강령

+
+
+
+ + +
+

인사규정 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

인사 문의: hr@technicalkorea.co.kr | 내선: 3456

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/hse.html b/deploy/tkfb-package/web-ui/docs/hse.html new file mode 100644 index 0000000..af4c9a2 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/hse.html @@ -0,0 +1,447 @@ + + + + + + HSE 관리시스템 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

TK-HSE-001 ISO 45001:2018 HSE 관리시스템 매뉴얼

+

ISO 45001:2018 기반 보건, 안전 및 환경 관리시스템 최상위 문서 (한/영 이중언어)

+
+
+ + +
+
+

TK-HSE-P-410 조직 상황 이해 및 HSE 관리시스템 운영 절차

+

조직의 내외부 상황 파악 및 HSE 관리시스템 전반 운영

+
+
+ + +
+
+

TK-HSE-P-510 리더십 및 정책 수립 절차

+

최고경영자 리더십 및 HSE 정책 수립·운영 절차

+
+
+ +
+
+

TK-HSE-P-520 조직 편성 및 직무 배정 절차

+

HSE 관련 조직 구성 및 역할·책임·권한 배정

+
+
+ + +
+
+

TK-HSE-P-610 기획 및 위험 관리 절차

+

HSE 관리시스템 기획 및 위험과 기회 관리

+
+
+ +
+
+

TK-HSE-P-620 위험 평가 절차

+

유해요인 식별 및 위험성 평가 실시 절차

+
+
+ +
+
+

TK-HSE-P-630 HSE 법적 요구사항 관리 절차

+

HSE 관련 법령 및 기타 요구사항 관리

+
+
+ +
+
+

TK-HSE-P-640 HSE 목표 관리 절차

+

HSE 목표 설정, 달성 계획 수립 및 관리

+
+
+ + +
+
+

TK-HSE-P-710 자원 관리 절차

+

HSE 관리시스템 운영에 필요한 자원 관리

+
+
+ +
+
+

TK-HSE-P-720 교육 및 훈련 관리 절차

+

HSE 관련 교육·훈련 계획 수립 및 실시

+
+
+ +
+
+

TK-HSE-P-730 인식 및 의사소통 절차

+

HSE 인식 제고 및 내외부 의사소통 관리

+
+
+ +
+
+

TK-HSE-P-740 문서화된 정보 관리 절차

+

HSE 문서 및 기록의 작성, 관리, 보관

+
+
+ + +
+
+

TK-HSE-P-810 운영 기획 및 관리 절차

+

HSE 운영 기획, 작업허가, 변경관리, 조달관리

+
+
+ +
+
+

TK-HSE-P-820 비상 대비 및 대응 절차

+

비상상황 대비, 대응 계획 및 훈련

+
+
+ + +
+
+

TK-HSE-P-910 프로세스 성과 관리 절차

+

HSE 관리시스템 프로세스 성과 관리

+
+
+ +
+
+

TK-HSE-P-920 HSE 모니터링 및 측정 관리 절차

+

HSE 성과 모니터링, 측정 및 분석

+
+
+ +
+
+

TK-HSE-P-930 내부 심사 절차

+

HSE 관리시스템 내부 심사 계획 및 실시

+
+
+ +
+
+

TK-HSE-P-940 경영 검토 절차

+

HSE 관리시스템 경영진 검토

+
+
+ + +
+
+

TK-HSE-P-1010 사건, 부적합 및 시정조치 절차

+

사건·사고 조사, 부적합 처리 및 시정조치

+
+
+ +
+
+

TK-HSE-P-1020 지속적 개선 절차

+

HSE 관리시스템 지속적 개선 활동

+
+
+ + +
+
+

TK-HSE-W-001 개인보호구 관리 지침

+

개인보호구 지급, 관리, 점검 실무 지침

+
+
+ +
+
+

TK-HSE-W-002 화학물질 관리 지침

+

화학물질 보관, 사용, 폐기 실무 지침

+
+
+ +
+
+

TK-HSE-W-003 응급처치 및 의료관리 지침

+

응급상황 대응 및 응급처치 실무 지침

+
+
+
+ + +
+

HSE 문서 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

HSE 문의: safety@technicalkorea.co.kr | 내선: 1234

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-410.html b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-410.html new file mode 100644 index 0000000..b6cd015 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-410.html @@ -0,0 +1,1208 @@ + + + + + + TK-HSE-P-410 조직 상황 이해 및 HSE 관리시스템 운영 절차 + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-410

+

조직 상황 이해 및 HSE 관리시스템 운영 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목조직 상황 이해 및 HSE 관리시스템 운영 절차
문서 번호TK-HSE-P-410
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 6
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+
+

1. 목적

+
+

본 절차의 목적은 다음과 같습니다:

+
    +
  • 조직의 내부 및 외부 상황을 체계적으로 파악하고 분석
  • +
  • 이해관계자의 요구사항과 기대사항을 식별하고 관리
  • +
  • HSE 관리시스템의 적용 범위를 명확히 정의
  • +
  • HSE 관리시스템의 효과적인 수립, 실행, 유지 및 개선
  • +
  • ISO 45001:2018 표준 4조 요구사항의 체계적 이행
  • +
+
+ + +
+
+

2. 적용 범위

+
+

본 절차는 테크니컬코리아의 다음 영역에 적용됩니다:

+
    +
  • 전 부서 및 모든 사업장
  • +
  • HSE 관리시스템 구축 및 운영 활동
  • +
  • 조직 상황 분석 및 이해관계자 관리 업무
  • +
  • HSE 관리시스템 적용 범위 설정 및 관리
  • +
  • 관련 계약업체 및 공급업체
  • +
+
+ + +
+
+

3. 인용 표준 및 관련 문서

+
+

3.1 인용 표준

+
    +
  • ISO 45001:2018 - 직장 보건안전 관리시스템 - 요구사항 및 사용 지침
  • +
  • 산업안전보건법 및 관련 법령
  • +
+ +

3.2 관련 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-510 - 리더십 및 정책 수립 절차
  • +
  • TK-HSE-P-610 - 기획 및 위험 관리 절차
  • +
  • TK-HSE-P-740 - 문서화된 정보 관리 절차
  • +
+
+ + +
+
+

4. 용어와 정의

+
+ +
+

4.1 조직의 상황 (Context of the organization)

+

목표를 달성하기 위한 조직의 접근 방식을 개발하는 데 영향을 줄 수 있는 내부 및 외부 이슈의 조합

+ +

4.2 이해관계자 (Interested party)

+

결정이나 활동에 영향을 주거나, 영향을 받거나, 영향을 받는다고 인식하는 개인이나 조직

+ +

4.3 요구사항 (Requirements)

+

명시되거나, 일반적으로 함축되거나, 의무적인 필요나 기대

+ +

4.4 적용 범위 (Scope)

+

관리시스템이 적용되는 조직의 활동, 제품 및 서비스의 범위와 경계

+
+
+ + +
+
+

5. 역할과 책임

+
+ + + + + + + + + + + + + + + + + + + + + + +
역할책임사항
최고경영자 + • 조직 상황 분석 결과 승인
+ • HSE 관리시스템 적용 범위 최종 결정
+ • 이해관계자 관리 전략 승인
+ • 필요 자원 제공 결정 +
HSE 관리책임자 + • 조직 상황 분석 총괄 관리
+ • 이해관계자 식별 및 분석 주관
+ • HSE 관리시스템 적용 범위 제안
+ • 관련 문서 작성 및 관리 +
각 부서장 + • 부서별 내외부 이슈 식별
+ • 부서 관련 이해관계자 정보 제공
+ • 조직 상황 분석 협조
+ • 관련 정보 업데이트 보고 +
HSE 담당자 + • 조직 상황 분석 실무 수행
+ • 이해관계자 정보 수집 및 정리
+ • 관련 문서 작성 지원
+ • 정기적 검토 및 업데이트 실시 +
+
+ + +
+
+

6. 프로세스 흐름도

+
+ +
+
조직 상황 분석 계획
+
+
내부/외부 이슈 식별
+
+
이해관계자 식별 및 분석
+
+
HSE 관리시스템 적용 범위 설정
+
+
문서화 및 승인
+
+
정기적 검토 및 업데이트
+
+
+ + +
+
+

7. 세부 절차

+
+ +
+

7.1 조직 상황 분석 계획 수립

+

7.1.1 절차

+
    +
  1. HSE 관리책임자는 연 1회 또는 필요시 조직 상황 분석 계획을 수립한다
  2. +
  3. 분석 범위, 방법, 일정, 담당자를 명확히 정의한다
  4. +
  5. 각 부서장에게 협조 요청을 공문으로 발송한다
  6. +
  7. 분석에 필요한 자료와 정보원을 사전에 확보한다
  8. +
+ +

7.1.2 고려사항

+
    +
  • 사업 환경의 변화 여부
  • +
  • 새로운 법규 및 규제 도입
  • +
  • 조직 구조 및 전략의 변경
  • +
  • 이전 분석 결과의 유효성
  • +
+
+ +
+

7.2 내부 및 외부 이슈 식별

+

7.2.1 외부 이슈 분석

+
    +
  1. 법적 환경 +
      +
    • 산업안전보건법 및 관련 법령 변화
    • +
    • 환경 관련 법규 동향
    • +
    • 국제 표준 및 규격 변화
    • +
    +
  2. +
  3. 경제적 환경 +
      +
    • 시장 경제 상황 및 전망
    • +
    • 업계 경기 동향
    • +
    • 경쟁업체 현황
    • +
    +
  4. +
  5. 기술적 환경 +
      +
    • 안전보건 기술 발전 동향
    • +
    • 새로운 위험요소 출현
    • +
    • 디지털 기술 적용 가능성
    • +
    +
  6. +
  7. 사회적 환경 +
      +
    • 사회적 안전 의식 변화
    • +
    • 근로자 권익 보호 요구
    • +
    • 지역사회 관심사항
    • +
    +
  8. +
+ +

7.2.2 내부 이슈 분석

+
    +
  1. 조직 구조 +
      +
    • 조직도 및 보고 체계
    • +
    • 역할 및 책임 분담
    • +
    • 의사결정 프로세스
    • +
    +
  2. +
  3. 인적 자원 +
      +
    • 인력 현황 및 역량
    • +
    • 교육훈련 수준
    • +
    • 근로자 참여도
    • +
    +
  4. +
  5. 물적 자원 +
      +
    • 시설 및 장비 현황
    • +
    • 안전보건 시설 수준
    • +
    • 기술적 능력
    • +
    +
  6. +
  7. 조직 문화 +
      +
    • 안전보건 문화 수준
    • +
    • 의사소통 체계
    • +
    • 학습 및 개선 의지
    • +
    +
  8. +
+
+ +
+

7.3 이해관계자 식별 및 분석

+

7.3.1 이해관계자 식별

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
구분이해관계자주요 관심사항
내부근로자안전한 작업환경, 건강보호, 참여 기회
경영진법적 준수, 비용 절감, 생산성 향상
주주기업 이미지, 재무 성과, 지속가능성
노동조합근로자 권익, 안전보건 조건 개선
외부고객제품 안전성, 기업 신뢰도
공급업체/계약업체안전한 작업 조건, 계약 이행
정부/규제기관법적 준수, 사고 예방
지역사회환경 영향, 사회적 책임
보험회사위험 관리, 사고율 감소
+ +

7.3.2 이해관계자 요구사항 분석

+
    +
  1. 각 이해관계자별 구체적 요구사항을 조사한다
  2. +
  3. 법적 요구사항과 자발적 요구사항을 구분한다
  4. +
  5. 요구사항의 우선순위와 중요도를 평가한다
  6. +
  7. 상충되는 요구사항에 대한 조정 방안을 마련한다
  8. +
  9. 요구사항 변화를 모니터링할 체계를 구축한다
  10. +
+
+ +
+

7.4 HSE 관리시스템 적용 범위 설정

+

7.4.1 적용 범위 결정 기준

+
    +
  • 조직의 통제 또는 영향 하에 있는 활동
  • +
  • HSE 성과에 영향을 줄 수 있는 활동
  • +
  • 법적 요구사항이 적용되는 영역
  • +
  • 이해관계자의 기대가 반영되는 영역
  • +
+ +

7.4.2 적용 범위 문서화

+
    +
  1. 물리적 위치 및 시설 명시
  2. +
  3. 포함되는 활동, 제품, 서비스 기술
  4. +
  5. 조직의 권한과 통제 범위 정의
  6. +
  7. 제외 사항 및 그 사유 명시
  8. +
  9. 적용 범위의 가용성 보장
  10. +
+
+ +
+

7.5 정기적 검토 및 업데이트

+

7.5.1 검토 주기

+
    +
  • 정기 검토: 매년 1회 이상
  • +
  • 임시 검토: 중대한 변화 발생 시
  • +
  • 경영 검토 시 함께 검토
  • +
+ +

7.5.2 업데이트 절차

+
    +
  1. 변화 요인 식별 및 영향 분석
  2. +
  3. 관련 부서와 협의
  4. +
  5. 업데이트 내용 문서화
  6. +
  7. 승인 및 공유
  8. +
  9. 관련 문서 연동 업데이트
  10. +
+
+
+ + +
+
+

8. 기록 관리

+
+ +

8.1 작성 기록

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
기록명작성자보관 기간보관 장소
조직 상황 분석 보고서HSE 관리책임자3년HSE 관리부서
이해관계자 등록부HSE 담당자3년HSE 관리부서
HSE 관리시스템 적용 범위서HSE 관리책임자영구HSE 관리부서
검토 및 업데이트 기록HSE 담당자3년HSE 관리부서
+ +

8.2 기록 관리 요구사항

+
    +
  • 모든 기록은 읽기 쉽고 식별 가능해야 함
  • +
  • 기록의 검색, 보관, 보호가 용이해야 함
  • +
  • 보관 기간 만료 시 적절히 처분
  • +
  • 전자 문서의 경우 백업 및 보안 조치
  • +
+
+ + +
+
+

9. 첨부 서식

+
+ +
    +
  • 첨부 1: 조직 상황 분석 체크리스트
  • +
  • 첨부 2: 이해관계자 등록 양식
  • +
  • 첨부 3: HSE 관리시스템 적용 범위 양식
  • +
  • 첨부 4: 검토 및 업데이트 기록 양식
  • +
+
+
+ + +
+ +
+

TK-HSE-P-410

+

Understanding Organizational Context and HSE Management System Operation Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleUnderstanding Organizational Context and HSE Management System Operation Procedure
Document NumberTK-HSE-P-410
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 6
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+
+

1. PURPOSE

+
+

The purpose of this procedure is to:

+
    +
  • Systematically identify and analyze the internal and external context of the organization
  • +
  • Identify and manage the needs and expectations of interested parties
  • +
  • Clearly define the scope of application of the HSE management system
  • +
  • Effectively establish, implement, maintain and improve the HSE management system
  • +
  • Systematically implement the requirements of ISO 45001:2018 Clause 4
  • +
+
+ + +
+
+

2. SCOPE

+
+

This procedure applies to the following areas of Technicalkorea:

+
    +
  • All departments and business sites
  • +
  • HSE management system establishment and operation activities
  • +
  • Organizational context analysis and stakeholder management tasks
  • +
  • Setting and managing the scope of HSE management system application
  • +
  • Related contractors and suppliers
  • +
+
+ + +
+
+

3. NORMATIVE REFERENCES AND RELATED DOCUMENTS

+
+

3.1 Normative References

+
    +
  • ISO 45001:2018 - Occupational health and safety management systems - Requirements with guidance for use
  • +
  • Occupational Safety and Health Act and related regulations
  • +
+ +

3.2 Related Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-510 - Leadership and Policy Establishment Procedure
  • +
  • TK-HSE-P-610 - Planning and Risk Management Procedure
  • +
  • TK-HSE-P-740 - Documented Information Management Procedure
  • +
+
+ + +
+
+

4. TERMS AND DEFINITIONS

+
+ +
+

4.1 Context of the organization

+

Combination of internal and external issues that can influence the organization's approach to developing and achieving its objectives

+ +

4.2 Interested party

+

Person or organization that can affect, be affected by, or perceive themselves to be affected by a decision or activity

+ +

4.3 Requirements

+

Need or expectation that is stated, generally implied or obligatory

+ +

4.4 Scope

+

Extent and boundaries of activities, products and services of an organization to which the management system applies

+
+
+ + +
+
+

5. ROLES AND RESPONSIBILITIES

+
+ + + + + + + + + + + + + + + + + + + + + + +
RoleResponsibilities
Top Management + • Approve organizational context analysis results
+ • Make final decisions on HSE management system scope
+ • Approve stakeholder management strategies
+ • Decide on provision of necessary resources +
HSE Management Representative + • Overall management of organizational context analysis
+ • Lead stakeholder identification and analysis
+ • Propose HSE management system scope
+ • Prepare and manage related documents +
Department Heads + • Identify internal and external issues by department
+ • Provide stakeholder information related to departments
+ • Cooperate in organizational context analysis
+ • Report updates on relevant information +
HSE Personnel + • Perform practical organizational context analysis
+ • Collect and organize stakeholder information
+ • Support preparation of related documents
+ • Conduct regular reviews and updates +
+
+ + +
+
+

6. PROCESS FLOW CHART

+
+ +
+
Organizational Context Analysis Planning
+
+
Internal/External Issues Identification
+
+
Stakeholder Identification and Analysis
+
+
HSE Management System Scope Setting
+
+
Documentation and Approval
+
+
Regular Review and Update
+
+
+ + +
+
+

7. DETAILED PROCEDURES

+
+ +
+

7.1 Establishing Organizational Context Analysis Plan

+

7.1.1 Procedure

+
    +
  1. The HSE Management Representative establishes an organizational context analysis plan annually or as needed
  2. +
  3. Clearly define the analysis scope, method, schedule, and responsible persons
  4. +
  5. Send cooperation requests to each department head via official document
  6. +
  7. Secure necessary data and information sources in advance for analysis
  8. +
+ +

7.1.2 Considerations

+
    +
  • Changes in business environment
  • +
  • Introduction of new laws and regulations
  • +
  • Changes in organizational structure and strategy
  • +
  • Validity of previous analysis results
  • +
+
+ +
+

7.2 Internal and External Issues Identification

+

7.2.1 External Issues Analysis

+
    +
  1. Legal Environment +
      +
    • Changes in Occupational Safety and Health Act and related laws
    • +
    • Environmental regulatory trends
    • +
    • Changes in international standards and specifications
    • +
    +
  2. +
  3. Economic Environment +
      +
    • Market economic conditions and prospects
    • +
    • Industry business trends
    • +
    • Competitor status
    • +
    +
  4. +
  5. Technological Environment +
      +
    • Safety and health technology development trends
    • +
    • Emergence of new risk factors
    • +
    • Digital technology application possibilities
    • +
    +
  6. +
  7. Social Environment +
      +
    • Changes in social safety awareness
    • +
    • Demands for worker rights protection
    • +
    • Local community concerns
    • +
    +
  8. +
+ +

7.2.2 Internal Issues Analysis

+
    +
  1. Organizational Structure +
      +
    • Organizational chart and reporting system
    • +
    • Role and responsibility distribution
    • +
    • Decision-making process
    • +
    +
  2. +
  3. Human Resources +
      +
    • Personnel status and capabilities
    • +
    • Education and training level
    • +
    • Worker participation level
    • +
    +
  4. +
  5. Physical Resources +
      +
    • Facilities and equipment status
    • +
    • Safety and health facility level
    • +
    • Technical capabilities
    • +
    +
  6. +
  7. Organizational Culture +
      +
    • Safety and health culture level
    • +
    • Communication system
    • +
    • Learning and improvement willingness
    • +
    +
  8. +
+
+ +
+

7.3 Stakeholder Identification and Analysis

+

7.3.1 Stakeholder Identification

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryStakeholderKey Concerns
InternalWorkersSafe working environment, health protection, participation opportunities
ManagementLegal compliance, cost reduction, productivity improvement
ShareholdersCorporate image, financial performance, sustainability
Labor UnionWorker rights, improvement of safety and health conditions
ExternalCustomersProduct safety, corporate reliability
Suppliers/ContractorsSafe working conditions, contract fulfillment
Government/Regulatory AgenciesLegal compliance, accident prevention
Local CommunityEnvironmental impact, social responsibility
Insurance CompaniesRisk management, accident rate reduction
+ +

7.3.2 Stakeholder Requirements Analysis

+
    +
  1. Investigate specific requirements for each stakeholder
  2. +
  3. Distinguish between legal requirements and voluntary requirements
  4. +
  5. Evaluate priority and importance of requirements
  6. +
  7. Establish coordination measures for conflicting requirements
  8. +
  9. Establish a system to monitor changes in requirements
  10. +
+
+ +
+

7.4 Setting HSE Management System Scope

+

7.4.1 Scope Determination Criteria

+
    +
  • Activities under the organization's control or influence
  • +
  • Activities that can affect HSE performance
  • +
  • Areas where legal requirements apply
  • +
  • Areas where stakeholder expectations are reflected
  • +
+ +

7.4.2 Scope Documentation

+
    +
  1. Specify physical locations and facilities
  2. +
  3. Describe included activities, products, and services
  4. +
  5. Define the organization's authority and control scope
  6. +
  7. Specify exclusions and their rationale
  8. +
  9. Ensure availability of the scope
  10. +
+
+ +
+

7.5 Regular Review and Update

+

7.5.1 Review Cycle

+
    +
  • Regular review: At least once a year
  • +
  • Ad-hoc review: When significant changes occur
  • +
  • Review together during management review
  • +
+ +

7.5.2 Update Procedure

+
    +
  1. Identify change factors and analyze impact
  2. +
  3. Consult with related departments
  4. +
  5. Document update contents
  6. +
  7. Approve and share
  8. +
  9. Update related linked documents
  10. +
+
+
+ + +
+
+

8. RECORDS MANAGEMENT

+
+ +

8.1 Records to be Maintained

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Record NamePrepared byRetention PeriodStorage Location
Organizational Context Analysis ReportHSE Management Representative3 yearsHSE Management Department
Stakeholder RegisterHSE Personnel3 yearsHSE Management Department
HSE Management System Scope DocumentHSE Management RepresentativePermanentHSE Management Department
Review and Update RecordsHSE Personnel3 yearsHSE Management Department
+ +

8.2 Records Management Requirements

+
    +
  • All records must be legible and identifiable
  • +
  • Records must be easily retrievable, stored, and protected
  • +
  • Appropriate disposal when retention period expires
  • +
  • Backup and security measures for electronic documents
  • +
+
+ + +
+
+

9. APPENDIX FORMS

+
+ +
    +
  • Appendix 1: Organizational Context Analysis Checklist
  • +
  • Appendix 2: Stakeholder Registration Form
  • +
  • Appendix 3: HSE Management System Scope Form
  • +
  • Appendix 4: Review and Update Record Form
  • +
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-510.html b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-510.html new file mode 100644 index 0000000..808a9f1 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-510.html @@ -0,0 +1,1529 @@ + + + + + + TK-HSE-P-510 리더십 및 정책 수립 절차 + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-510

+

리더십 및 정책 수립 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목리더십 및 정책 수립 절차
문서 번호TK-HSE-P-510
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 7
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+
+

1. 목적

+
+

본 절차의 목적은 다음과 같습니다:

+
    +
  • 최고경영자의 HSE 관리시스템에 대한 리더십과 의지 실증
  • +
  • HSE 정책의 체계적 수립, 실행, 유지 및 의사소통
  • +
  • 조직 내 HSE 역할, 책임 및 권한의 명확한 정의
  • +
  • 근로자의 협의와 참여를 위한 체계적 프레임워크 구축
  • +
  • ISO 45001:2018 표준 5조 요구사항의 효과적 이행
  • +
+
+ + +
+
+

2. 적용 범위

+
+

본 절차는 테크니컬코리아의 다음 영역에 적용됩니다:

+
    +
  • 최고경영자의 리더십 활동
  • +
  • HSE 정책 수립, 승인, 실행 및 유지 관리
  • +
  • 조직 내 HSE 관련 역할과 책임 배정
  • +
  • 근로자 협의 및 참여 프로세스
  • +
  • HSE 관리시스템 적용 범위 내 모든 활동
  • +
+
+ + +
+
+

3. 인용 표준 및 관련 문서

+
+

3.1 인용 표준

+
    +
  • ISO 45001:2018 - 직장 보건안전 관리시스템 - 요구사항 및 사용 지침
  • +
  • 산업안전보건법 및 관련 법령
  • +
  • 근로자참여 및 협력증진에 관한 법률
  • +
+ +

3.2 관련 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-410 - 조직 상황 이해 및 HSE 관리시스템 운영 절차
  • +
  • TK-HSE-P-520 - 조직 편성 및 직무 배정 절차
  • +
  • TK-HSE-P-730 - 인식 및 의사소통 절차
  • +
+
+ + +
+
+

4. 용어와 정의

+
+ +
+

4.1 최고경영자 (Top management)

+

최고 수준에서 조직을 지휘하고 통제하는 개인 또는 집단

+ +

4.2 정책 (Policy)

+

최고경영자가 공식적으로 표현한 조직의 의도와 방향

+ +

4.3 협의 (Consultation)

+

결정을 내리기 전에 견해를 구하는 것

+ +

4.4 참여 (Participation)

+

의사결정 과정에 관여하는 것

+ +

4.5 리더십 (Leadership)

+

목표를 달성하기 위해 다른 사람들에게 영향을 미치고 동기를 부여하는 능력

+
+
+ + +
+
+

5. 역할과 책임

+
+ + + + + + + + + + + + + + + + + + + + + + +
역할책임사항
최고경영자 + • HSE 관리시스템에 대한 리더십과 의지 실증
+ • HSE 정책 승인 및 대외 의사소통
+ • 조직 내 HSE 역할과 책임 최종 승인
+ • 근로자 협의 및 참여 프로세스 승인
+ • HSE 관리시스템 효과성 보장
+ • 필요 자원 제공 및 지원 +
HSE 관리책임자 + • HSE 정책 초안 작성 및 개정
+ • 조직 내 HSE 역할과 책임 체계 구축
+ • 근로자 협의 및 참여 프로그램 운영
+ • HSE 정책 교육 및 전파
+ • 정책 이행 상황 모니터링 +
각 부서장 + • 부서 내 HSE 정책 전파 및 실행
+ • 부서원의 HSE 역할과 책임 명확화
+ • 근로자 의견 수렴 및 상급자 보고
+ • 부서 HSE 성과 관리
+ • HSE 개선 활동 참여 +
근로자 + • HSE 정책 이해 및 준수
+ • 배정된 HSE 역할과 책임 수행
+ • HSE 협의 및 참여 활동 적극 참여
+ • HSE 개선 의견 제시
+ • 동료 근로자의 HSE 활동 지원 +
+
+ + +
+
+

6. 프로세스 흐름도

+
+ +
+
HSE 정책 수립 필요성 검토
+
+
정책 초안 작성
+
+
근로자 협의 및 의견 수렴
+
+
정책 검토 및 수정
+
+
최고경영자 승인
+
+
정책 공표 및 교육
+
+
역할과 책임 배정
+
+
이행 모니터링 및 검토
+
+
+ + +
+
+

7. HSE 정책

+
+ +
+
테크니컬코리아 HSE 정책
+ +

우리 테크니컬코리아는 모든 임직원과 이해관계자의 건강과 안전을 최우선 가치로 여기며, 환경보호를 통한 지속가능한 경영을 추구합니다.

+ +
+

우리의 약속 (Our Commitments)

+
    +
  1. 안전하고 건강한 작업환경 제공 +
      +
    • 무재해 사업장 구현을 위한 지속적 노력
    • +
    • 근로자의 신체적, 정신적 건강 보호
    • +
    • 안전한 작업 조건과 환경 조성
    • +
    +
  2. + +
  3. 법적 요구사항 및 기타 요구사항 준수 +
      +
    • 산업안전보건법 등 관련 법령 완전 준수
    • +
    • 국제 표준 및 모범 사례 적극 적용
    • +
    • 고객 및 이해관계자 요구사항 충족
    • +
    +
  4. + +
  5. 유해요인 제거 및 HSE 위험 감소 +
      +
    • 체계적인 위험 평가 및 관리
    • +
    • 사전 예방적 안전관리 시스템 운영
    • +
    • 최신 안전기술 도입 및 적용
    • +
    +
  6. + +
  7. 지속적 개선 +
      +
    • HSE 성과의 지속적 향상
    • +
    • 혁신적 개선 아이디어 발굴 및 적용
    • +
    • 학습하는 조직문화 구축
    • +
    +
  8. + +
  9. 근로자 협의 및 참여 +
      +
    • 모든 HSE 의사결정에 근로자 참여 보장
    • +
    • 열린 의사소통 문화 조성
    • +
    • 근로자 의견의 적극적 수렴 및 반영
    • +
    +
  10. + +
  11. 목표 설정 및 성과 관리 +
      +
    • 명확하고 측정 가능한 HSE 목표 설정
    • +
    • 정기적 성과 검토 및 평가
    • +
    • 목표 달성을 위한 체계적 실행
    • +
    +
  12. +
+
+ +

모든 임직원은 이 정책을 이해하고 실천하여 안전하고 건강한 일터를 만드는데 적극 참여해야 합니다.

+ +
+

2025년 1월 3일

+

테크니컬코리아 대표이사

+

________________

+

[서명]

+
+
+
+ + +
+
+

8. 세부 절차

+
+ +
+

8.1 HSE 정책 수립 절차

+

8.1.1 정책 수립 필요성 검토

+
    +
  1. 정기 검토: 매년 1회 정책의 적절성 검토
  2. +
  3. 임시 검토: 다음 상황 발생 시 즉시 검토 +
      +
    • 관련 법령의 개정
    • +
    • 조직 구조나 사업 영역의 변경
    • +
    • 중대한 사고나 사건 발생
    • +
    • 이해관계자의 요구사항 변화
    • +
    +
  4. +
  5. 검토 결과 문서화: 검토 내용과 결론을 기록
  6. +
+ +

8.1.2 정책 초안 작성

+
    +
  1. HSE 관리책임자가 초안 작성 주관
  2. +
  3. 다음 요소를 필수적으로 포함: +
      +
    • 안전하고 건강한 작업조건 제공 의지
    • +
    • HSE 목표 설정을 위한 프레임워크
    • +
    • 법적 요구사항 및 기타 요구사항 준수 의지
    • +
    • 유해요인 제거 및 HSE 위험 감소 의지
    • +
    • 지속적 개선 의지
    • +
    • 근로자 협의 및 참여 의지
    • +
    +
  4. +
  5. 조직의 특성과 사업 영역을 반영
  6. +
  7. 이해하기 쉽고 명확한 언어로 작성
  8. +
+ +

8.1.3 근로자 협의 및 의견 수렴

+
    +
  1. 정책 초안을 전 근로자에게 공개
  2. +
  3. 다양한 채널을 통한 의견 수렴: +
      +
    • 부서별 설명회 개최
    • +
    • 서면 의견서 접수
    • +
    • 온라인 의견 제출 시스템 활용
    • +
    • 근로자 대표와 개별 면담
    • +
    +
  4. +
  5. 수렴 기간: 최소 2주간
  6. +
  7. 의견 검토 및 반영 여부 결정
  8. +
+
+ +
+

8.2 조직 내 역할과 책임 체계

+

8.2.1 HSE 조직도 작성

+
    +
  1. 최고경영자를 정점으로 하는 HSE 조직 체계 구성
  2. +
  3. 각 계층별 역할과 책임 명확히 정의
  4. +
  5. 보고 체계와 의사소통 경로 명시
  6. +
  7. 의사결정 권한과 범위 규정
  8. +
+ +

8.2.2 역할과 책임 문서 작성

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
직급/역할주요 HSE 책임권한
최고경영자• HSE 관리시스템 총괄
• 정책 승인 및 자원 제공
• 리더십 실증
• 최종 의사결정
• 예산 승인
• 조직 변경
HSE 관리책임자• HSE 시스템 운영
• 법규 준수 관리
• 성과 모니터링
• 시스템 개선
• 교육 시행
• 점검 및 감사
부서장• 부서 HSE 관리
• 근로자 교육
• 사고 보고
• 부서 내 결정
• 시정조치
• 자원 요청
안전관리자• 기술적 지원
• 위험 평가
• 안전 점검
• 기술 지도
• 작업 중지
• 개선 권고
근로자• 안전 수칙 준수
• 위험 신고
• 교육 참여
• 작업 거부권
• 의견 제시
• 참여 권리
+
+ +
+

8.3 근로자 협의 및 참여 체계

+

8.3.1 협의 및 참여 체계 구축

+
    +
  1. HSE 위원회 구성 +
      +
    • 사용자 측 위원: 3명 (경영진, HSE 관리책임자 등)
    • +
    • 근로자 측 위원: 3명 (근로자 대표, 현장 대표 등)
    • +
    • 분기별 정기 회의 개최
    • +
    • 임시 회의: 필요시 수시 개최
    • +
    +
  2. + +
  3. 부서별 HSE 담당자 지정 +
      +
    • 각 부서에서 HSE 담당자 1명 지정
    • +
    • 월 1회 HSE 담당자 회의 개최
    • +
    • 부서 내 HSE 이슈 수집 및 전달
    • +
    +
  4. + +
  5. 의견 수렴 채널 운영 +
      +
    • HSE 제안함 설치 및 운영
    • +
    • 온라인 의견 제출 시스템
    • +
    • 익명 신고 시스템 운영
    • +
    • 정기적 간담회 개최
    • +
    +
  6. +
+ +

8.3.2 협의 및 참여 영역

+
    +
  • HSE 정책 수립 및 개정
  • +
  • HSE 목표 설정 및 계획 수립
  • +
  • 위험 평가 및 관리 방안
  • +
  • 안전보건 교육 프로그램
  • +
  • 사고 조사 및 재발 방지 대책
  • +
  • 작업 환경 개선 사항
  • +
  • 개인보호구 선정 및 지급
  • +
  • HSE 성과 평가 및 개선
  • +
+
+
+ + +
+
+

9. 리더십 실증 활동

+
+ +
+

9.1 최고경영자 리더십 활동

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
활동 영역구체적 활동실행 주기
정책 의사소통• 신년 HSE 메시지 발표
• 주요 회의에서 HSE 중요성 강조
• HSE 정책 서명 및 게시
연 1회 이상
월 1회
정책 수립 시
현장 방문• 정기적 현장 안전 순회
• 근로자와 직접 대화
• 안전 문제 즉석 해결
월 2회 이상
분기 1회
즉시
자원 제공• HSE 예산 승인
• 안전시설 투자 결정
• 교육 프로그램 지원
연간 예산
필요시
지속적
성과 검토• 월간 HSE 성과 보고 청취
• 경영 검토 회의 주관
• 개선 지시 및 확인
월 1회
분기 1회
수시
+
+ +
+

9.2 중간 관리자 리더십 활동

+
    +
  • 일일 안전 점검: 작업 시작 전 안전 상태 확인
  • +
  • 주간 안전 회의: 부서별 안전 이슈 논의
  • +
  • 즉석 교육: 위험 상황 발견 시 즉시 교육 실시
  • +
  • 모범 행동: 안전 수칙 준수의 모범 사례 제시
  • +
  • 격려와 인정: 우수 안전 활동에 대한 칭찬과 보상
  • +
+
+
+ + +
+
+

10. 성과 모니터링 및 검토

+
+ +
+

10.1 정책 이행 모니터링

+

10.1.1 모니터링 지표

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
영역지표측정 방법목표
정책 인식도정책 이해도 (%)설문조사90% 이상
근로자 참여HSE 위원회 참석률 (%)출석 체크95% 이상
리더십 활동현장 방문 횟수방문 기록월 2회 이상
의사소통의견 제출 건수접수 현황월 5건 이상
+ +

10.1.2 검토 및 개선

+
    +
  1. 월간 검토: HSE 관리책임자가 지표 현황 분석
  2. +
  3. 분기 검토: HSE 위원회에서 성과 평가
  4. +
  5. 연간 검토: 경영 검토 시 종합 평가
  6. +
  7. 개선 조치: 미달 지표에 대한 구체적 개선 계획 수립
  8. +
+
+
+ + +
+
+

11. 기록 관리

+
+ +

11.1 작성 기록

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
기록명작성자보관 기간보관 장소
HSE 정책서최고경영자영구HSE 관리부서
역할과 책임 매트릭스HSE 관리책임자3년HSE 관리부서
HSE 위원회 회의록HSE 담당자3년HSE 관리부서
리더십 활동 기록각 부서장3년각 부서
근로자 의견 수렴 기록HSE 담당자3년HSE 관리부서
정책 교육 기록교육 담당자3년교육 담당부서
+
+ + +
+
+

12. 첨부 서식

+
+ +
    +
  • 첨부 1: HSE 정책 승인 요청서
  • +
  • 첨부 2: 역할과 책임 매트릭스 양식
  • +
  • 첨부 3: HSE 위원회 회의록 양식
  • +
  • 첨부 4: 근로자 의견 제출서
  • +
  • 첨부 5: 리더십 활동 체크리스트
  • +
  • 첨부 6: 정책 이행 모니터링 표
  • +
+
+
+ + +
+ +
+

TK-HSE-P-510

+

Leadership and Policy Establishment Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleLeadership and Policy Establishment Procedure
Document NumberTK-HSE-P-510
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 7
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+
+

1. Purpose

+
+

The purpose of this procedure is as follows:

+
    +
  • Demonstrate top management's leadership and commitment to the HSE management system
  • +
  • Systematic establishment, implementation, maintenance, and communication of HSE policy
  • +
  • Clear definition of HSE roles, responsibilities, and authorities within the organization
  • +
  • Establish a systematic framework for worker consultation and participation
  • +
  • Effective implementation of ISO 45001:2018 standard clause 5 requirements
  • +
+
+ + +
+
+

2. Scope

+
+

This procedure applies to the following areas of Technicalkorea:

+
    +
  • Top management leadership activities
  • +
  • HSE policy establishment, approval, implementation, and maintenance
  • +
  • Assignment of HSE-related roles and responsibilities within the organization
  • +
  • Worker consultation and participation processes
  • +
  • All activities within the scope of the HSE management system
  • +
+
+ + +
+
+

3. Referenced Standards and Related Documents

+
+

3.1 Referenced Standards

+
    +
  • ISO 45001:2018 - Occupational health and safety management systems - Requirements with guidance for use
  • +
  • Occupational Safety and Health Act and related regulations
  • +
  • Act on the Promotion of Worker Participation and Cooperation
  • +
+ +

3.2 Related Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-410 - Understanding Organizational Context and HSE Management System Operation Procedure
  • +
  • TK-HSE-P-520 - Organizational Structure and Job Assignment Procedure
  • +
  • TK-HSE-P-730 - Awareness and Communication Procedure
  • +
+
+ + +
+
+

4. Terms and Definitions

+
+ +
+

4.1 Top management

+

Person or group of people who directs and controls an organization at the highest level

+ +

4.2 Policy

+

Intentions and direction of an organization as formally expressed by its top management

+ +

4.3 Consultation

+

Seeking views before making a decision

+ +

4.4 Participation

+

Involvement in decision-making

+ +

4.5 Leadership

+

Ability to influence and motivate others to achieve objectives

+
+
+ + +
+
+

5. Roles and Responsibilities

+
+ + + + + + + + + + + + + + + + + + + + + + +
RoleResponsibilities
Top Management + • Demonstrate leadership and commitment to the HSE management system
+ • Approve HSE policy and communicate externally
+ • Final approval of HSE roles and responsibilities within the organization
+ • Approve worker consultation and participation processes
+ • Ensure effectiveness of the HSE management system
+ • Provide necessary resources and support +
HSE Manager + • Draft and revise HSE policy
+ • Establish HSE roles and responsibility system within the organization
+ • Operate worker consultation and participation programs
+ • HSE policy training and dissemination
+ • Monitor policy implementation status +
Department Heads + • Disseminate and implement HSE policy within departments
+ • Clarify HSE roles and responsibilities of department members
+ • Collect worker opinions and report to superiors
+ • Manage department HSE performance
+ • Participate in HSE improvement activities +
Workers + • Understand and comply with HSE policy
+ • Perform assigned HSE roles and responsibilities
+ • Actively participate in HSE consultation and participation activities
+ • Submit HSE improvement suggestions
+ • Support fellow workers' HSE activities +
+
+ + +
+
+

6. Process Flow Chart

+
+ +
+
Review Need for HSE Policy Establishment
+
+
Draft Policy
+
+
Worker Consultation and Opinion Collection
+
+
Policy Review and Modification
+
+
Top Management Approval
+
+
Policy Announcement and Training
+
+
Assign Roles and Responsibilities
+
+
Implementation Monitoring and Review
+
+
+ + +
+
+

7. HSE Policy

+
+ +
+
Technicalkorea HSE Policy
+ +

We, Technicalkorea, regard the health and safety of all employees and stakeholders as our highest priority value and pursue sustainable management through environmental protection.

+ +
+

Our Commitments

+
    +
  1. Providing Safe and Healthy Work Environment +
      +
    • Continuous efforts to achieve zero-accident workplace
    • +
    • Protection of workers' physical and mental health
    • +
    • Creation of safe working conditions and environment
    • +
    +
  2. + +
  3. Compliance with Legal Requirements and Other Requirements +
      +
    • Full compliance with Occupational Safety and Health Act and related laws
    • +
    • Active application of international standards and best practices
    • +
    • Meeting customer and stakeholder requirements
    • +
    +
  4. + +
  5. Elimination of Hazards and Reduction of HSE Risks +
      +
    • Systematic risk assessment and management
    • +
    • Operation of proactive safety management system
    • +
    • Introduction and application of latest safety technologies
    • +
    +
  6. + +
  7. Continual Improvement +
      +
    • Continuous improvement of HSE performance
    • +
    • Discovery and application of innovative improvement ideas
    • +
    • Building a learning organizational culture
    • +
    +
  8. + +
  9. Worker Consultation and Participation +
      +
    • Ensuring worker participation in all HSE decision-making
    • +
    • Creating an open communication culture
    • +
    • Active collection and reflection of worker opinions
    • +
    +
  10. + +
  11. Goal Setting and Performance Management +
      +
    • Setting clear and measurable HSE objectives
    • +
    • Regular performance review and evaluation
    • +
    • Systematic implementation to achieve objectives
    • +
    +
  12. +
+
+ +

All employees must understand and practice this policy to actively participate in creating a safe and healthy workplace.

+ +
+

January 3, 2025

+

CEO, Technicalkorea

+

________________

+

[Signature]

+
+
+
+ + +
+
+

8. Detailed Procedures

+
+ +
+

8.1 HSE Policy Establishment Procedure

+

8.1.1 Review of Policy Establishment Need

+
    +
  1. Regular Review: Review policy adequacy once a year
  2. +
  3. Ad-hoc Review: Immediate review when the following situations occur: +
      +
    • Amendment of related laws and regulations
    • +
    • Changes in organizational structure or business areas
    • +
    • Occurrence of major accidents or incidents
    • +
    • Changes in stakeholder requirements
    • +
    +
  4. +
  5. Document Review Results: Record review contents and conclusions
  6. +
+ +

8.1.2 Policy Draft Preparation

+
    +
  1. HSE Manager leads draft preparation
  2. +
  3. Must include the following elements: +
      +
    • Commitment to provide safe and healthy working conditions
    • +
    • Framework for setting HSE objectives
    • +
    • Commitment to comply with legal requirements and other requirements
    • +
    • Commitment to eliminate hazards and reduce HSE risks
    • +
    • Commitment to continual improvement
    • +
    • Commitment to worker consultation and participation
    • +
    +
  4. +
  5. Reflect organizational characteristics and business areas
  6. +
  7. Write in clear and understandable language
  8. +
+ +

8.1.3 Worker Consultation and Opinion Collection

+
    +
  1. Disclose policy draft to all workers
  2. +
  3. Collect opinions through various channels: +
      +
    • Hold departmental briefings
    • +
    • Receive written opinion submissions
    • +
    • Utilize online opinion submission system
    • +
    • Individual interviews with worker representatives
    • +
    +
  4. +
  5. Collection period: Minimum 2 weeks
  6. +
  7. Review opinions and decide on reflection
  8. +
+
+ +
+

8.2 Organizational Roles and Responsibility System

+

8.2.1 HSE Organization Chart Preparation

+
    +
  1. Establish HSE organizational system with top management at the apex
  2. +
  3. Clearly define roles and responsibilities at each level
  4. +
  5. Specify reporting system and communication channels
  6. +
  7. Define decision-making authority and scope
  8. +
+ +

8.2.2 Roles and Responsibility Document Preparation

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Position/RoleMain HSE ResponsibilitiesAuthority
Top Management• Overall HSE management system
• Policy approval and resource provision
• Leadership demonstration
• Final decision-making
• Budget approval
• Organizational changes
HSE Manager• HSE system operation
• Legal compliance management
• Performance monitoring
• System improvement
• Training implementation
• Inspection and audit
Department Head• Department HSE management
• Worker training
• Accident reporting
• Departmental decisions
• Corrective actions
• Resource requests
Safety Manager• Technical support
• Risk assessment
• Safety inspection
• Technical guidance
• Work stoppage
• Improvement recommendations
Worker• Safety rule compliance
• Risk reporting
• Training participation
• Right to refuse work
• Opinion submission
• Participation rights
+
+ +
+

8.3 Worker Consultation and Participation System

+

8.3.1 Consultation and Participation System Establishment

+
    +
  1. HSE Committee Formation +
      +
    • Employer representatives: 3 members (management, HSE Manager, etc.)
    • +
    • Worker representatives: 3 members (worker representatives, field representatives, etc.)
    • +
    • Hold quarterly regular meetings
    • +
    • Ad-hoc meetings: Hold as needed
    • +
    +
  2. + +
  3. Departmental HSE Representative Designation +
      +
    • Designate 1 HSE representative from each department
    • +
    • Hold monthly HSE representative meetings
    • +
    • Collect and communicate HSE issues within departments
    • +
    +
  4. + +
  5. Opinion Collection Channel Operation +
      +
    • Install and operate HSE suggestion boxes
    • +
    • Online opinion submission system
    • +
    • Anonymous reporting system operation
    • +
    • Regular round-table meetings
    • +
    +
  6. +
+ +

8.3.2 Consultation and Participation Areas

+
    +
  • HSE policy establishment and revision
  • +
  • HSE objective setting and planning
  • +
  • Risk assessment and management measures
  • +
  • Occupational health and safety training programs
  • +
  • Accident investigation and recurrence prevention measures
  • +
  • Work environment improvement matters
  • +
  • Personal protective equipment selection and distribution
  • +
  • HSE performance evaluation and improvement
  • +
+
+
+ + +
+
+

9. Leadership Demonstration Activities

+
+ +
+

9.1 Top Management Leadership Activities

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
Activity AreaSpecific ActivitiesImplementation Frequency
Policy Communication• Announce New Year HSE message
• Emphasize HSE importance in major meetings
• Sign and post HSE policy
Once a year or more
Monthly
When policy is established
Field Visits• Regular field safety rounds
• Direct dialogue with workers
• Immediate resolution of safety issues
Twice a month or more
Quarterly
Immediately
Resource Provision• HSE budget approval
• Safety facility investment decisions
• Training program support
Annual budget
As needed
Continuously
Performance Review• Listen to monthly HSE performance reports
• Chair management review meetings
• Issue and confirm improvement directives
Monthly
Quarterly
As needed
+
+ +
+

9.2 Middle Management Leadership Activities

+
    +
  • Daily Safety Inspection: Check safety conditions before work starts
  • +
  • Weekly Safety Meetings: Discuss departmental safety issues
  • +
  • On-the-spot Training: Immediate training when hazardous situations are discovered
  • +
  • Model Behavior: Present best practice examples of safety rule compliance
  • +
  • Encouragement and Recognition: Praise and reward excellent safety activities
  • +
+
+
+ + +
+
+

10. Performance Monitoring and Review

+
+ +
+

10.1 Policy Implementation Monitoring

+

10.1.1 Monitoring Indicators

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AreaIndicatorMeasurement MethodTarget
Policy AwarenessPolicy Understanding (%)Survey90% or higher
Worker ParticipationHSE Committee Attendance Rate (%)Attendance Check95% or higher
Leadership ActivitiesNumber of Field VisitsVisit RecordsTwice a month or more
CommunicationNumber of Opinion SubmissionsReception Status5 or more per month
+ +

10.1.2 Review and Improvement

+
    +
  1. Monthly Review: HSE Manager analyzes indicator status
  2. +
  3. Quarterly Review: HSE Committee evaluates performance
  4. +
  5. Annual Review: Comprehensive evaluation during management review
  6. +
  7. Improvement Actions: Establish specific improvement plans for underperforming indicators
  8. +
+
+
+ + +
+
+

11. Records Management

+
+ +

11.1 Records to be Created

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Record NamePrepared byRetention PeriodStorage Location
HSE Policy DocumentTop ManagementPermanentHSE Management Department
Roles and Responsibility MatrixHSE Manager3 yearsHSE Management Department
HSE Committee Meeting MinutesHSE Officer3 yearsHSE Management Department
Leadership Activity RecordsEach Department Head3 yearsEach Department
Worker Opinion Collection RecordsHSE Officer3 yearsHSE Management Department
Policy Training RecordsTraining Officer3 yearsTraining Department
+
+ + +
+
+

12. Attached Forms

+
+ +
    +
  • Attachment 1: HSE Policy Approval Request Form
  • +
  • Attachment 2: Roles and Responsibility Matrix Form
  • +
  • Attachment 3: HSE Committee Meeting Minutes Form
  • +
  • Attachment 4: Worker Opinion Submission Form
  • +
  • Attachment 5: Leadership Activity Checklist
  • +
  • Attachment 6: Policy Implementation Monitoring Table
  • +
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-520.html b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-520.html new file mode 100644 index 0000000..ef7cc5f --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-520.html @@ -0,0 +1,1826 @@ + + + + + + TK-HSE-P-520 조직 편성 및 직무 배정 절차 + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-520

+

조직 편성 및 직무 배정 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목조직 편성 및 직무 배정 절차
문서 번호TK-HSE-P-520
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 8
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+
+

1. 목적

+
+

본 절차의 목적은 다음과 같습니다:

+
    +
  • HSE 관리시스템 운영을 위한 효과적인 조직 구조 설계
  • +
  • 각 역할과 책임의 명확한 정의 및 배정
  • +
  • 권한과 의사소통 체계의 체계적 구축
  • +
  • HSE 성과 향상을 위한 적절한 인력 배치
  • +
  • 조직 변화에 따른 유연한 조직 운영 체계 확립
  • +
+
+ + +
+
+

2. 적용 범위

+
+

본 절차는 테크니컬코리아의 다음 영역에 적용됩니다:

+
    +
  • HSE 관리시스템 관련 모든 조직 및 직책
  • +
  • 본사, 공장, 지사 등 모든 사업장
  • +
  • 정규직, 계약직, 파견직 등 모든 근로자
  • +
  • HSE 업무에 관련된 계약업체 및 협력업체
  • +
  • 조직 개편 및 인사 발령 업무
  • +
+
+ + +
+
+

3. 인용 표준 및 관련 문서

+
+

3.1 인용 표준

+
    +
  • ISO 45001:2018 - 직장 보건안전 관리시스템 - 요구사항 및 사용 지침
  • +
  • 산업안전보건법 및 시행령, 시행규칙
  • +
  • 안전보건관리책임자 등의 선임 및 직무에 관한 고시
  • +
+ +

3.2 관련 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-510 - 리더십 및 정책 수립 절차
  • +
  • TK-HSE-P-710 - 자원 관리 절차
  • +
  • TK-HSE-P-720 - 교육 및 훈련 관리 절차
  • +
+
+ + +
+
+

4. 용어와 정의

+
+ +
+

4.1 조직 (Organization)

+

목표를 달성하기 위해 책임, 권한 및 상호관계가 배치된 개인 또는 집단

+ +

4.2 역할 (Role)

+

특정 상황에서 개인이나 그룹에게 기대되는 행동이나 업무의 집합

+ +

4.3 책임 (Responsibility)

+

할당된 업무나 의무를 수행해야 하는 의무

+ +

4.4 권한 (Authority)

+

결정을 내리고 자원을 사용할 수 있는 권리와 권력

+ +

4.5 역량 (Competence)

+

의도된 결과를 달성하기 위해 지식과 기술을 적용하는 능력

+
+
+ + +
+
+

5. HSE 조직 구조

+
+ +
+
+
최고경영자 (CEO)
+
+
+
+
HSE 관리책임자
+
+
├──────┼──────┼──────┤
+
+
안전관리자
+
보건관리자
+
환경관리자
+
HSE 담당자
+
+
+
+
부서별 HSE 담당자
+
+
+
+
현장 작업자
+
+
+ +
+

5.1 조직 구조 설계 원칙

+
    +
  • 명확성: 역할과 책임의 명확한 구분
  • +
  • 효율성: 의사결정과 업무 수행의 효율성 추구
  • +
  • 유연성: 조직 변화에 대한 적응 능력
  • +
  • 소통성: 원활한 의사소통 체계 구축
  • +
  • 전문성: 각 분야별 전문 역량 확보
  • +
+
+
+ + +
+
+

6. 역할과 책임

+
+ +
+

6.1 최고경영자 (CEO)

+ + + + + + + + + + + + + + + + + + + + + +
책임 영역구체적 책임사항권한
전략 수립• HSE 비전 및 전략 수립
• HSE 정책 승인
• 중장기 HSE 목표 결정
• 최종 의사결정
• 예산 승인
• 조직 개편
자원 제공• HSE 예산 승인
• 인적 자원 배정
• 시설 및 장비 투자
• 예산 집행
• 인사 발령
• 투자 결정
성과 관리• HSE 성과 검토
• 경영 검토 주관
• 개선 지시
• 성과 평가
• 포상 및 징계
• 시정 명령
+
+ +
+

6.2 HSE 관리책임자

+ + + + + + + + + + + + + + + + + + + + + +
책임 영역구체적 책임사항권한
시스템 운영• HSE 관리시스템 총괄 운영
• 시스템 개선 및 발전
• 법규 준수 관리
• 시스템 변경
• 절차 승인
• 법규 해석
조직 관리• HSE 조직 운영
• 업무 분장 및 조정
• 성과 관리
• 업무 배정
• 성과 평가
• 교육 지시
대외 업무• 정부 기관 업무
• 감사 및 점검 대응
• 외부 기관 협력
• 대외 협상
• 공문 발송
• 계약 체결
+
+ +
+

6.3 안전관리자

+
+

📋 주요 업무

+
    +
  • 안전관리계획의 수립 및 시행
  • +
  • 근로자의 안전·보건교육
  • +
  • 작업환경의 점검 및 개선
  • +
  • 산업재해 원인조사 및 재발방지 대책 수립
  • +
  • 안전장치 및 보호구의 점검 및 관리
  • +
  • 기계·기구류의 안전성 검토
  • +
  • 안전보건 관리규정의 작성 및 변경
  • +
+ +

🎯 필요 자격

+
    +
  • 안전관리자 선임 자격 (산업안전보건법)
  • +
  • 관련 분야 학위 또는 경력
  • +
  • 안전관리 실무 경험 3년 이상
  • +
+
+
+ +
+

6.4 보건관리자

+
+

📋 주요 업무

+
    +
  • 작업환경의 측정 및 평가
  • +
  • 근로자의 건강진단 및 사후관리
  • +
  • 직업성질병 예방 및 관리
  • +
  • 작업환경 개선 및 보건교육
  • +
  • 유해·위험 요인의 발굴 및 개선
  • +
  • 보건 관련 통계의 유지·관리
  • +
  • 응급처치 및 구급처치
  • +
+ +

🎯 필요 자격

+
    +
  • 보건관리자 선임 자격 (산업안전보건법)
  • +
  • 간호사, 위생사 등 보건 관련 자격
  • +
  • 산업보건 실무 경험 2년 이상
  • +
+
+
+ +
+

6.5 환경관리자

+
+

📋 주요 업무

+
    +
  • 환경영향 평가 및 관리
  • +
  • 환경법규 준수 관리
  • +
  • 폐기물 관리 및 처리
  • +
  • 대기, 수질, 토양 오염 방지
  • +
  • 환경 모니터링 및 측정
  • +
  • 환경 개선 계획 수립 및 시행
  • +
  • 환경 사고 대응 및 복구
  • +
+ +

🎯 필요 자격

+
    +
  • 환경 관련 기사 이상 자격증
  • +
  • 환경공학 또는 관련 분야 학위
  • +
  • 환경관리 실무 경험 3년 이상
  • +
+
+
+ +
+

6.6 부서장

+ + + + + + + + + + + + + + + + + +
책임 영역구체적 책임사항
부서 HSE 관리• 부서 HSE 계획 수립
• 부서원 HSE 교육
• 일일 안전점검 실시
• 사고 예방 활동 주관
근로자 관리• 부서원 HSE 역할 배정
• 안전수칙 준수 지도
• HSE 성과 평가
• 위험 행동 시정
보고 및 소통• HSE 현황 상급자 보고
• 근로자 의견 수렴
• 개선사항 건의
• 사고 즉시 보고
+
+
+ + +
+
+

7. 조직 편성 절차

+
+ +
+

7.1 HSE 조직 설계

+

7.1.1 조직 설계 단계

+
    +
  1. 현황 분석 +
      +
    • 현재 조직 구조 분석
    • +
    • 업무량 및 업무 특성 파악
    • +
    • 인력 현황 및 역량 평가
    • +
    • 법적 요구사항 검토
    • +
    +
  2. + +
  3. 조직 설계 +
      +
    • 최적 조직 구조 설계
    • +
    • 역할과 책임 정의
    • +
    • 보고 체계 및 권한 설정
    • +
    • 의사소통 채널 구축
    • +
    +
  4. + +
  5. 승인 및 공표 +
      +
    • 최고경영자 승인
    • +
    • 조직도 및 업무분장 공표
    • +
    • 전 직원 교육 실시
    • +
    • 시행 및 모니터링
    • +
    +
  6. +
+ +

7.1.2 조직 설계 시 고려사항

+ + + + + + + + + + + + + + + + + + + + + +
고려 요소세부 사항
법적 요구사항• 산업안전보건법상 관리자 선임 의무
• 사업장 규모별 선임 기준
• 자격 요건 및 직무 범위
사업 특성• 업종 및 업무 위험도
• 사업장 위치 및 규모
• 작업 형태 및 근무 시간
인적 자원• 현재 인력 현황
• 필요 역량 및 자격
• 교육 및 개발 계획
예산 및 자원• 인건비 예산
• 교육 및 훈련 비용
• 시설 및 장비 투자
+
+ +
+

7.2 직무 배정 절차

+

7.2.1 직무 분석

+
    +
  1. 업무 내용 분석 +
      +
    • 주요 업무 및 세부 업무 파악
    • +
    • 업무의 중요도 및 난이도 평가
    • +
    • 업무량 및 소요 시간 산정
    • +
    • 다른 업무와의 연관성 분석
    • +
    +
  2. + +
  3. 필요 역량 정의 +
      +
    • 학력, 경력, 자격증 요건
    • +
    • 필요 지식 및 기술
    • +
    • 개인적 특성 및 능력
    • +
    • 의사소통 및 리더십 역량
    • +
    +
  4. + +
  5. 성과 지표 설정 +
      +
    • 정량적 성과 지표
    • +
    • 정성적 평가 기준
    • +
    • 목표 설정 및 평가 방법
    • +
    • 피드백 및 개선 체계
    • +
    +
  6. +
+ +

7.2.2 인력 배정

+
+
직무 요구사항 검토
+
+
후보자 선정
+
+
역량 평가
+
+
배정 결정
+
+
발령 및 교육
+
+
성과 모니터링
+
+
+
+ + +
+
+

8. 역량 관리

+
+ +
+

8.1 역량 요구사항

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
직책학력/경력자격증핵심 역량
HSE 관리책임자대졸 이상, 5년 이상 경력안전관리자 또는 관련 자격리더십, 의사소통, 문제해결
안전관리자관련 학과 졸업, 3년 이상 경력안전관리자 선임 자격위험 평가, 기술 지도, 교육
보건관리자보건 관련 학과, 2년 이상 경력간호사, 위생사 등건강 관리, 상담, 응급처치
환경관리자환경공학 관련, 3년 이상 경력환경 관련 기사 이상환경 분석, 법규 해석, 개선
HSE 담당자고졸 이상, 1년 이상 경력관련 자격 우대업무 수행, 협조, 학습
+
+ +
+

8.2 역량 개발 계획

+

8.2.1 교육 훈련 체계

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
교육 구분대상내용주기
신입 교육신규 배정자• 조직 소개
• 역할 및 책임
• 기본 업무 교육
배정 후 1개월 내
정기 교육전체 HSE 조직• 법규 변경사항
• 새로운 기술
• 모범 사례
분기별
전문 교육관리자급• 전문 기술
• 리더십
• 의사소통
연 2회
보수 교육자격 보유자• 법정 보수교육
• 자격 갱신
• 최신 동향
법정 기준
+ +

8.2.2 역량 평가

+
    +
  • 정기 평가: 연 2회 (상/하반기)
  • +
  • 평가 방법: 서면 평가, 실무 평가, 360도 평가
  • +
  • 평가 기준: 업무 성과, 전문 지식, 협업 능력
  • +
  • 개선 계획: 평가 결과에 따른 개인별 개발 계획 수립
  • +
+
+
+ + +
+
+

9. 의사소통 체계

+
+ +
+

9.1 의사소통 채널

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
채널 유형참여자주기내용
경영진 회의CEO, HSE 관리책임자월 1회• HSE 성과 보고
• 주요 이슈 논의
• 의사결정
HSE 관리자 회의HSE 조직 전체주 1회• 업무 현황 공유
• 협조 사항
• 개선 방안
부서별 간담회부서장, HSE 담당자월 1회• 부서 HSE 현황
• 애로사항
• 지원 요청
전사 HSE 회의전체 임직원분기 1회• 정책 전파
• 성과 공유
• 우수사례
+
+ +
+

9.2 보고 체계

+

9.2.1 정기 보고

+
    +
  • 일일 보고: 현장 → 부서장 → HSE 담당자
  • +
  • 주간 보고: HSE 담당자 → HSE 관리책임자
  • +
  • 월간 보고: HSE 관리책임자 → 최고경영자
  • +
  • 분기 보고: 전사 HSE 성과 종합 보고
  • +
+ +

9.2.2 비상 보고

+
    +
  • 사고 발생 시: 즉시 보고 (30분 내)
  • +
  • 중대 위험 발견 시: 즉시 보고 (1시간 내)
  • +
  • 법규 위반 시: 즉시 보고 (당일)
  • +
  • 외부 점검 시: 사전 보고 및 결과 보고
  • +
+
+
+ + +
+
+

10. 성과 관리

+
+ +
+

10.1 성과 지표

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
지표 구분세부 지표목표측정 방법
조직 효율성업무 처리 시간기준 대비 90% 이하업무 처리 기록
의사결정 속도3일 이내결재 시스템
업무 만족도4.0/5.0 이상만족도 조사
역량 수준교육 이수율100%교육 기록
자격 보유율100%자격 대장
역량 평가 점수80점 이상평가 결과
의사소통회의 참석률95% 이상참석 기록
정보 공유 속도24시간 내시스템 로그
+
+ +
+

10.2 개선 관리

+

10.2.1 정기 검토

+
    +
  1. 월간 검토: 각 부서별 성과 분석
  2. +
  3. 분기 검토: 전체 조직 효율성 평가
  4. +
  5. 연간 검토: 조직 구조 및 운영 체계 전면 검토
  6. +
  7. 수시 검토: 중대한 문제 발생 시 즉시 검토
  8. +
+ +

10.2.2 개선 조치

+
    +
  • 업무 프로세스 개선: 비효율적 절차 간소화
  • +
  • 조직 구조 조정: 필요시 조직 개편
  • +
  • 역량 강화: 교육 및 훈련 확대
  • +
  • 시스템 개선: IT 시스템 및 도구 개선
  • +
+
+
+ + +
+
+

11. 기록 관리

+
+ +

11.1 작성 기록

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
기록명작성자보관 기간보관 장소
HSE 조직도HSE 관리책임자영구HSE 관리부서
업무분장표HSE 관리책임자3년HSE 관리부서
인사발령장인사담당자영구인사부서
역량 평가서각 부서장5년각 부서
교육 기록교육담당자3년교육담당부서
회의록회의 간사3년HSE 관리부서
+
+ + +
+
+

12. 첨부 서식

+
+ +
    +
  • 첨부 1: HSE 조직도 양식
  • +
  • 첨부 2: 업무분장표 양식
  • +
  • 첨부 3: 역할 및 책임 매트릭스
  • +
  • 첨부 4: 역량 요구사항 체크리스트
  • +
  • 첨부 5: 역량 평가표
  • +
  • 첨부 6: 교육 계획서 양식
  • +
  • 첨부 7: 성과 평가표
  • +
  • 첨부 8: 의사소통 매트릭스
  • +
+
+
+ + +
+ +
+

TK-HSE-P-520

+

Organization and Job Assignment Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleOrganization and Job Assignment Procedure
Document NumberTK-HSE-P-520
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 8
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+
+

1. Purpose

+
+

The purpose of this procedure is as follows:

+
    +
  • Design effective organizational structure for HSE management system operation
  • +
  • Clear definition and assignment of roles and responsibilities
  • +
  • Systematic establishment of authority and communication systems
  • +
  • Appropriate personnel deployment for HSE performance improvement
  • +
  • Establishment of flexible organizational operation system according to organizational changes
  • +
+
+ + +
+
+

2. Scope

+
+

This procedure applies to the following areas of Technicalkorea:

+
    +
  • All organizations and positions related to HSE management system
  • +
  • All business sites including headquarters, factories, and branches
  • +
  • All workers including regular, contract, and temporary employees
  • +
  • Contractors and partners related to HSE work
  • +
  • Organizational restructuring and personnel assignment work
  • +
+
+ + +
+
+

3. Referenced Standards and Related Documents

+
+

3.1 Referenced Standards

+
    +
  • ISO 45001:2018 - Occupational health and safety management systems - Requirements with guidance for use
  • +
  • Occupational Safety and Health Act and its enforcement decree and rules
  • +
  • Notice on the appointment and duties of safety and health management supervisors
  • +
+ +

3.2 Related Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-510 - Leadership and Policy Development Procedure
  • +
  • TK-HSE-P-710 - Resource Management Procedure
  • +
  • TK-HSE-P-720 - Education and Training Management Procedure
  • +
+
+ + +
+
+

4. Terms and Definitions

+
+ +
+

4.1 Organization

+

Person or group of people that has its own functions with responsibilities, authorities and relationships to achieve its objectives

+ +

4.2 Role

+

Set of behaviors or tasks expected of a person or group in a specific situation

+ +

4.3 Responsibility

+

Obligation to perform assigned tasks or duties

+ +

4.4 Authority

+

Right and power to make decisions and use resources

+ +

4.5 Competence

+

Ability to apply knowledge and skills to achieve intended results

+
+
+ + +
+
+

5. HSE Organization Structure

+
+ +
+
+
Chief Executive Officer (CEO)
+
+
+
+
HSE Management Representative
+
+
├──────┼──────┼──────┤
+
+
Safety Manager
+
Health Manager
+
Environmental Manager
+
HSE Officer
+
+
+
+
Departmental HSE Officers
+
+
+
+
Field Workers
+
+
+ +
+

5.1 Organizational Structure Design Principles

+
    +
  • Clarity: Clear distinction of roles and responsibilities
  • +
  • Efficiency: Pursuit of efficiency in decision-making and task performance
  • +
  • Flexibility: Adaptability to organizational changes
  • +
  • Communication: Establishment of smooth communication system
  • +
  • Professionalism: Securing professional competency in each field
  • +
+
+
+ + +
+
+

6. Roles and Responsibilities

+
+ +
+

6.1 Chief Executive Officer (CEO)

+ + + + + + + + + + + + + + + + + + + + + +
Responsibility AreaSpecific ResponsibilitiesAuthority
Strategy Development• Establish HSE vision and strategy
• Approve HSE policy
• Determine medium-long term HSE objectives
• Final decision making
• Budget approval
• Organizational restructuring
Resource Provision• Approve HSE budget
• Allocate human resources
• Invest in facilities and equipment
• Budget execution
• Personnel appointment
• Investment decision
Performance Management• Review HSE performance
• Lead management review
• Direct improvements
• Performance evaluation
• Rewards and disciplinary actions
• Corrective orders
+
+ +
+

6.2 HSE Management Representative

+ + + + + + + + + + + + + + + + + + + + + +
Responsibility AreaSpecific ResponsibilitiesAuthority
System Operation• Overall operation of HSE management system
• System improvement and development
• Legal compliance management
• System modification
• Procedure approval
• Legal interpretation
Organization Management• HSE organization operation
• Work assignment and coordination
• Performance management
• Task assignment
• Performance evaluation
• Training direction
External Affairs• Government agency affairs
• Audit and inspection response
• External organization cooperation
• External negotiation
• Official document dispatch
• Contract conclusion
+
+ +
+

6.3 Safety Manager

+
+

📋 Main Duties

+
    +
  • Establishment and implementation of safety management plans
  • +
  • Safety and health education for workers
  • +
  • Inspection and improvement of work environment
  • +
  • Investigation of industrial accident causes and establishment of recurrence prevention measures
  • +
  • Inspection and management of safety devices and protective equipment
  • +
  • Safety review of machinery and equipment
  • +
  • Preparation and modification of safety and health management regulations
  • +
+ +

🎯 Required Qualifications

+
    +
  • Safety manager appointment qualification (Occupational Safety and Health Act)
  • +
  • Related field degree or experience
  • +
  • Safety management practical experience of 3 years or more
  • +
+
+
+ +
+

6.4 Health Manager

+
+

📋 Main Duties

+
    +
  • Measurement and evaluation of work environment
  • +
  • Health examination and follow-up management of workers
  • +
  • Prevention and management of occupational diseases
  • +
  • Work environment improvement and health education
  • +
  • Discovery and improvement of harmful and dangerous factors
  • +
  • Maintenance and management of health-related statistics
  • +
  • Emergency treatment and first aid
  • +
+ +

🎯 Required Qualifications

+
    +
  • Health manager appointment qualification (Occupational Safety and Health Act)
  • +
  • Health-related qualifications such as nurse, hygienist
  • +
  • Industrial health practical experience of 2 years or more
  • +
+
+
+ +
+

6.5 Environmental Manager

+
+

📋 Main Duties

+
    +
  • Environmental impact assessment and management
  • +
  • Environmental regulation compliance management
  • +
  • Waste management and treatment
  • +
  • Prevention of air, water, and soil pollution
  • +
  • Environmental monitoring and measurement
  • +
  • Establishment and implementation of environmental improvement plans
  • +
  • Environmental accident response and recovery
  • +
+ +

🎯 Required Qualifications

+
    +
  • Environmental-related engineer certification or higher
  • +
  • Environmental engineering or related field degree
  • +
  • Environmental management practical experience of 3 years or more
  • +
+
+
+ +
+

6.6 Department Manager

+ + + + + + + + + + + + + + + + + +
Responsibility AreaSpecific Responsibilities
Department HSE Management• Establish department HSE plans
• HSE education for department members
• Conduct daily safety inspections
• Lead accident prevention activities
Worker Management• Assign HSE roles to department members
• Guide compliance with safety rules
• Evaluate HSE performance
• Correct dangerous behaviors
Reporting and Communication• Report HSE status to superiors
• Collect worker opinions
• Suggest improvements
• Immediately report accidents
+
+
+ + +
+
+

7. Organization Procedures

+
+ +
+

7.1 HSE Organization Design

+

7.1.1 Organization Design Stages

+
    +
  1. Current Status Analysis +
      +
    • Analysis of current organizational structure
    • +
    • Identification of workload and work characteristics
    • +
    • Evaluation of personnel status and competency
    • +
    • Review of legal requirements
    • +
    +
  2. + +
  3. Organization Design +
      +
    • Design optimal organizational structure
    • +
    • Define roles and responsibilities
    • +
    • Set reporting system and authority
    • +
    • Establish communication channels
    • +
    +
  4. + +
  5. Approval and Announcement +
      +
    • CEO approval
    • +
    • Announcement of organization chart and job assignment
    • +
    • Training for all employees
    • +
    • Implementation and monitoring
    • +
    +
  6. +
+ +

7.1.2 Considerations in Organization Design

+ + + + + + + + + + + + + + + + + + + + + +
Consideration FactorDetails
Legal Requirements• Mandatory appointment of managers under Occupational Safety and Health Act
• Appointment criteria by workplace size
• Qualification requirements and job scope
Business Characteristics• Industry type and work risk level
• Workplace location and size
• Work type and working hours
Human Resources• Current personnel status
• Required competency and qualifications
• Education and development plans
Budget and Resources• Personnel cost budget
• Education and training costs
• Facility and equipment investment
+
+ +
+

7.2 Job Assignment Procedure

+

7.2.1 Job Analysis

+
    +
  1. Work Content Analysis +
      +
    • Identification of main tasks and detailed tasks
    • +
    • Evaluation of task importance and difficulty
    • +
    • Calculation of workload and required time
    • +
    • Analysis of relationships with other tasks
    • +
    +
  2. + +
  3. Required Competency Definition +
      +
    • Education, experience, certification requirements
    • +
    • Required knowledge and skills
    • +
    • Personal characteristics and abilities
    • +
    • Communication and leadership competency
    • +
    +
  4. + +
  5. Performance Indicator Setting +
      +
    • Quantitative performance indicators
    • +
    • Qualitative evaluation criteria
    • +
    • Goal setting and evaluation methods
    • +
    • Feedback and improvement system
    • +
    +
  6. +
+ +

7.2.2 Personnel Assignment

+
+
Review Job Requirements
+
+
Select Candidates
+
+
Competency Assessment
+
+
Assignment Decision
+
+
Appointment and Training
+
+
Performance Monitoring
+
+
+
+ + +
+
+

8. Competency Management

+
+ +
+

8.1 Competency Requirements

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
PositionEducation/ExperienceCertificationCore Competency
HSE Management RepresentativeBachelor's degree or higher, 5+ years experienceSafety manager or related qualificationLeadership, communication, problem-solving
Safety ManagerRelated field graduate, 3+ years experienceSafety manager appointment qualificationRisk assessment, technical guidance, education
Health ManagerHealth-related field, 2+ years experienceNurse, hygienist, etc.Health management, counseling, first aid
Environmental ManagerEnvironmental engineering related, 3+ years experienceEnvironmental engineer or higherEnvironmental analysis, regulation interpretation, improvement
HSE OfficerHigh school graduate or higher, 1+ years experienceRelated qualification preferredTask performance, cooperation, learning
+
+ +
+

8.2 Competency Development Plan

+

8.2.1 Education and Training System

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Education TypeTargetContentFrequency
New Employee TrainingNewly assigned personnel• Organization introduction
• Roles and responsibilities
• Basic job training
Within 1 month of assignment
Regular TrainingAll HSE organization• Regulatory changes
• New technologies
• Best practices
Quarterly
Professional TrainingManagement level• Professional skills
• Leadership
• Communication
Twice a year
Refresher TrainingCertificate holders• Legal refresher training
• Qualification renewal
• Latest trends
As per legal requirements
+ +

8.2.2 Competency Assessment

+
    +
  • Regular Assessment: Twice a year (first/second half)
  • +
  • Assessment Method: Written assessment, practical assessment, 360-degree assessment
  • +
  • Assessment Criteria: Job performance, professional knowledge, collaboration ability
  • +
  • Improvement Plan: Individual development plan based on assessment results
  • +
+
+
+ + +
+
+

9. Communication System

+
+ +
+

9.1 Communication Channels

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Channel TypeParticipantsFrequencyContent
Management MeetingCEO, HSE Management RepresentativeMonthly• HSE performance reporting
• Major issue discussion
• Decision making
HSE Manager MeetingEntire HSE organizationWeekly• Work status sharing
• Cooperation matters
• Improvement measures
Departmental MeetingDepartment managers, HSE officersMonthly• Department HSE status
• Difficulties
• Support requests
Company-wide HSE MeetingAll employeesQuarterly• Policy dissemination
• Performance sharing
• Best practices
+
+ +
+

9.2 Reporting System

+

9.2.1 Regular Reporting

+
    +
  • Daily Report: Field → Department Manager → HSE Officer
  • +
  • Weekly Report: HSE Officer → HSE Management Representative
  • +
  • Monthly Report: HSE Management Representative → CEO
  • +
  • Quarterly Report: Company-wide HSE performance comprehensive report
  • +
+ +

9.2.2 Emergency Reporting

+
    +
  • Accident Occurrence: Immediate report (within 30 minutes)
  • +
  • Major Risk Discovery: Immediate report (within 1 hour)
  • +
  • Regulatory Violation: Immediate report (same day)
  • +
  • External Inspection: Advance report and result report
  • +
+
+
+ + +
+
+

10. Performance Management

+
+ +
+

10.1 Performance Indicators

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Indicator CategoryDetailed IndicatorTargetMeasurement Method
Organizational EfficiencyTask processing time90% or less of standardTask processing records
Decision-making speedWithin 3 daysApproval system
Job satisfaction4.0/5.0 or higherSatisfaction survey
Competency LevelTraining completion rate100%Training records
Qualification holding rate100%Qualification register
Competency assessment score80 points or higherAssessment results
CommunicationMeeting attendance rate95% or higherAttendance records
Information sharing speedWithin 24 hoursSystem logs
+
+ +
+

10.2 Improvement Management

+

10.2.1 Regular Review

+
    +
  1. Monthly Review: Performance analysis by each department
  2. +
  3. Quarterly Review: Overall organizational efficiency evaluation
  4. +
  5. Annual Review: Comprehensive review of organizational structure and operation system
  6. +
  7. Ad-hoc Review: Immediate review when major problems occur
  8. +
+ +

10.2.2 Improvement Measures

+
    +
  • Work Process Improvement: Streamlining inefficient procedures
  • +
  • Organizational Structure Adjustment: Organizational restructuring when necessary
  • +
  • Competency Enhancement: Expansion of education and training
  • +
  • System Improvement: IT system and tool improvement
  • +
+
+
+ + +
+
+

11. Records Management

+
+ +

11.1 Prepared Records

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Record NamePreparerRetention PeriodStorage Location
HSE Organization ChartHSE Management RepresentativePermanentHSE Management Department
Job Assignment TableHSE Management Representative3 yearsHSE Management Department
Personnel Appointment OrderHR PersonnelPermanentHR Department
Competency Assessment ReportEach Department Manager5 yearsEach Department
Training RecordsTraining Officer3 yearsTraining Department
Meeting MinutesMeeting Secretary3 yearsHSE Management Department
+
+ + +
+
+

12. Appendix Forms

+
+ +
    +
  • Appendix 1: HSE Organization Chart Form
  • +
  • Appendix 2: Job Assignment Table Form
  • +
  • Appendix 3: Role and Responsibility Matrix
  • +
  • Appendix 4: Competency Requirements Checklist
  • +
  • Appendix 5: Competency Assessment Form
  • +
  • Appendix 6: Training Plan Form
  • +
  • Appendix 7: Performance Evaluation Form
  • +
  • Appendix 8: Communication Matrix
  • +
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-610.html b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-610.html new file mode 100644 index 0000000..af89870 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-610.html @@ -0,0 +1,1671 @@ + + + + + + TK-HSE-P-610 기획 및 위험 관리 절차 + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-610

+

기획 및 위험 관리 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목기획 및 위험 관리 절차
문서 번호TK-HSE-P-610
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 9
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+
+

1. 목적

+
+

본 절차의 목적은 다음과 같습니다:

+
    +
  • HSE 관리시스템의 체계적인 기획과 실행
  • +
  • 위험과 기회를 다루기 위한 효과적인 조치 수립
  • +
  • 유해요인 식별 및 HSE 위험 평가의 체계적 수행
  • +
  • 법적 요구사항 및 기타 요구사항의 체계적 관리
  • +
  • 측정 가능한 HSE 목표 설정 및 달성 계획 수립
  • +
  • ISO 45001:2018 표준 6조 요구사항의 효과적 이행
  • +
+
+ + +
+
+

2. 적용 범위

+
+

본 절차는 테크니컬코리아의 다음 영역에 적용됩니다:

+
    +
  • HSE 관리시스템 적용 범위 내 모든 활동
  • +
  • 본사, 공장, 지사 등 모든 사업장
  • +
  • 정규직, 비정규직, 계약업체 근로자
  • +
  • 제품 생산, 서비스 제공, 지원 활동
  • +
  • 일상 및 비일상 업무, 비상 상황
  • +
  • 과거, 현재, 계획된 미래 활동
  • +
+
+ + +
+
+

3. 인용 표준 및 관련 문서

+
+

3.1 인용 표준

+
    +
  • ISO 45001:2018 - 직장 보건안전 관리시스템 - 요구사항 및 사용 지침
  • +
  • ISO 31000:2018 - 리스크 관리 - 지침
  • +
  • 산업안전보건법 및 관련 법령
  • +
  • 환경정책기본법 및 관련 법령
  • +
+ +

3.2 관련 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-410 - 조직 상황 이해 및 HSE 관리시스템 운영 절차
  • +
  • TK-HSE-P-620 - 위험 평가 절차
  • +
  • TK-HSE-P-630 - HSE 법적 요구사항 관리 절차
  • +
  • TK-HSE-P-640 - HSE 목표 관리 절차
  • +
+
+ + +
+
+

4. 용어와 정의

+
+ +
+

4.1 위험 (Risk)

+

불확실성의 영향으로, 목표에 대한 긍정적 또는 부정적 편차

+ +

4.2 기회 (Opportunity)

+

HSE 성과 향상, 폐기물 감소, 사고 예방 등 긍정적 결과를 가져올 가능성

+ +

4.3 유해요인 (Hazard)

+

부상과 건강악화를 일으킬 잠재성을 가진 근원

+ +

4.4 위험 평가 (Risk Assessment)

+

위험을 식별, 분석, 평가하는 전체적인 과정

+ +

4.5 법적 요구사항 (Legal Requirements)

+

조직이 준수해야 하는 법률, 규정, 명령 등

+ +

4.6 목표 (Objective)

+

달성해야 할 결과나 성과

+
+
+ + +
+
+

5. 프로세스 흐름도

+
+ +
+
기획 프로세스 시작
+
+
위험과 기회 식별
+
+
유해요인 식별
+
+
위험 평가
+
+
법적 요구사항 파악
+
+
HSE 목표 설정
+
+
실행 계획 수립
+
+
승인 및 실행
+
+
모니터링 및 검토
+
+
+ + +
+
+

6. 위험과 기회 관리

+
+ +
+

6.1 위험과 기회 식별

+

6.1.1 식별 대상

+ + + + + + + + + + + + + + + + + + + + + +
구분식별 대상고려사항
내부 위험• 설비 고장
• 인적 오류
• 조직 변화
• 자원 부족
• 발생 가능성
• 영향 정도
• 통제 가능성
• 대응 시간
외부 위험• 자연재해
• 법규 변경
• 시장 변화
• 공급업체 문제
• 예측 가능성
• 대응 능력
• 회복 시간
• 비용 영향
기회• 기술 개선
• 비용 절감
• 효율성 향상
• 이미지 개선
• 실현 가능성
• 투자 대비 효과
• 경쟁 우위
• 지속 가능성
+ +

6.1.2 식별 방법

+
    +
  • 브레인스토밍: 다학제팀 구성하여 아이디어 도출
  • +
  • 체크리스트: 표준화된 체크리스트 활용
  • +
  • 시나리오 분석: 가상의 상황 설정하여 분석
  • +
  • 과거 사례 분석: 내외부 사고 사례 검토
  • +
  • 전문가 판단: 해당 분야 전문가 의견 수렴
  • +
  • 현장 관찰: 직접 현장을 관찰하여 위험 요소 파악
  • +
+
+ +
+

6.2 위험과 기회 평가

+
+

📊 위험 평가 매트릭스

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
발생가능성영향도
1 (경미)2 (보통)3 (중간)4 (심각)5 (치명적)
5 (매우 높음)510152025
4 (높음)48121620
3 (보통)3691215
2 (낮음)246810
1 (매우 낮음)12345
+ +

🎯 위험 수준별 대응 기준

+
    +
  • 고위험 (15-25): 즉시 조치 필요, 작업 중단 고려
  • +
  • 중위험 (8-12): 단기간 내 개선 조치 필요
  • +
  • 저위험 (3-6): 계획적 개선 조치
  • +
  • 수용 가능 (1-2): 현재 수준 유지, 정기 모니터링
  • +
+
+
+ +
+

6.3 조치 계획 수립

+

6.3.1 위험 대응 전략

+
+

🔺 위험 관리 우선순위

+
    +
  1. 제거 (Elimination): 위험 요소 자체를 제거
  2. +
  3. 대체 (Substitution): 더 안전한 대안으로 교체
  4. +
  5. 공학적 통제 (Engineering Controls): 기술적 방법으로 위험 감소
  6. +
  7. 관리적 통제 (Administrative Controls): 절차, 교육, 훈련을 통한 관리
  8. +
  9. 개인보호구 (PPE): 개인보호장비 착용으로 보호
  10. +
+
+ +

6.3.2 기회 활용 전략

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
전략설명예시
적극 추진기회 실현 가능성을 높이기 위한 적극적 투자• 신기술 도입
• 전문 인력 채용
• 시설 개선
공유다른 조직과 협력하여 기회 공유• 파트너십 구축
• 컨소시엄 참여
• 외부 협력
수용별도 조치 없이 자연스러운 기회 활용• 시장 변화 대응
• 법규 변경 활용
• 트렌드 추종
모니터링기회 발생을 지속적으로 관찰• 정기 검토
• 성과 추적
• 트렌드 분석
+
+
+ + +
+
+

7. 유해요인 식별 및 위험 평가

+
+ +
+

7.1 유해요인 분류

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
분류세부 유형주요 예시
물리적 유해요인기계적 위험• 회전체, 압착, 충돌
• 낙하, 전도, 추락
환경적 위험• 소음, 진동, 온도
• 조명, 방사선
전기적 위험• 감전, 화재, 폭발
• 정전기, 낙뢰
화학적 유해요인유독물질• 산, 알칼리, 용매
• 중금속, 발암물질
가스/증기• 독성가스, 질식가스
• 인화성 가스
생물학적 유해요인병원체• 세균, 바이러스, 곰팡이
• 기생충, 독소
알레르기원• 꽃가루, 먼지
• 동물털, 식품
인간공학적 유해요인작업 자세• 부적절한 자세
• 반복 작업, 중량물
작업 설계• 작업대 높이
• 도구 설계, 공간
심리사회적 유해요인업무 스트레스• 과도한 업무량
• 시간 압박, 책임
조직 문화• 괴롭힘, 폭력
• 의사소통 부족
+
+ +
+

7.2 식별 절차

+

7.2.1 체계적 접근

+
    +
  1. 작업 분석 +
      +
    • 작업 공정별 세부 단계 분석
    • +
    • 사용 장비 및 재료 파악
    • +
    • 작업 환경 조건 확인
    • +
    • 작업자 특성 고려
    • +
    +
  2. + +
  3. 현장 조사 +
      +
    • 직접 현장 관찰 및 측정
    • +
    • 작업자 인터뷰 실시
    • +
    • 과거 사고 사례 검토
    • +
    • 유사 업종 사례 조사
    • +
    +
  4. + +
  5. 문서 검토 +
      +
    • 물질안전보건자료(MSDS) 검토
    • +
    • 장비 매뉴얼 및 사양서 확인
    • +
    • 법규 및 기준 검토
    • +
    • 감사 및 점검 결과 분석
    • +
    +
  6. + +
  7. 전문가 자문 +
      +
    • 산업보건 전문가 의견
    • +
    • 안전 기술 전문가 자문
    • +
    • 의학 전문가 상담
    • +
    • 법무 전문가 검토
    • +
    +
  8. +
+
+ +
+

7.3 위험 평가 방법

+

7.3.1 정량적 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + +
방법적용 대상장점단점
확률론적 평가통계 데이터가 충분한 경우• 객관적 결과
• 정확한 수치
• 데이터 확보 어려움
• 복잡한 계산
노출 평가화학물질, 물리적 인자• 직접 측정
• 과학적 근거
• 비용 소요
• 시간 제약
모델링복잡한 시스템• 시나리오 분석
• 예측 가능
• 가정 의존
• 불확실성
+ +

7.3.2 정성적 평가

+
    +
  • 매트릭스 방법: 발생가능성 × 영향도
  • +
  • 순위 결정법: 상대적 중요도 비교
  • +
  • 시나리오 분석: 가정 상황 설정
  • +
  • 전문가 판단: 경험과 지식 활용
  • +
+
+
+ + +
+
+

8. 법적 요구사항 관리

+
+ +
+

8.1 법적 요구사항 식별

+

8.1.1 주요 법령

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
분야주요 법령핵심 요구사항
안전산업안전보건법• 안전보건관리체계 구축
• 위험성 평가 실시
• 안전보건교육 실시
건설기계관리법• 건설기계 검사
• 조종사 면허
• 안전운행
화학물질관리법• 화학물질 등록
• 취급기준 준수
• 사고 신고
보건산업안전보건법• 작업환경측정
• 건강진단 실시
• 직업병 예방
감염병예방법• 감염병 예방조치
• 신고 의무
• 방역 활동
환경환경정책기본법• 환경오염 방지
• 환경영향 최소화
• 지속가능 발전
대기환경보전법• 배출허용기준 준수
• 방지시설 설치
• 측정 및 보고
폐기물관리법• 폐기물 분리수거
• 위탁처리
• 처리 현황 보고
+ +

8.1.2 기타 요구사항

+
    +
  • 고객 요구사항: 계약서, 사양서상 안전보건 조건
  • +
  • 자발적 표준: ISO 표준, 업계 모범사례
  • +
  • 보험 요구사항: 보험회사 안전 기준
  • +
  • 사회적 기대: 지역사회, NGO 요구사항
  • +
+
+ +
+

8.2 준수 관리 체계

+

8.2.1 법령 모니터링

+
    +
  1. 정보 수집: 정부 공고, 전문 기관 정보
  2. +
  3. 변경 분석: 기존 대비 변경사항 파악
  4. +
  5. 영향 평가: 조직에 미치는 영향 분석
  6. +
  7. 대응 계획: 필요 조치사항 계획 수립
  8. +
  9. 실행 및 추적: 계획 실행 및 결과 확인
  10. +
+ +

8.2.2 준수 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
평가 방법주기담당자결과 조치
자체 점검월 1회각 부서 담당자즉시 개선
내부 감사분기 1회HSE 담당자시정조치 계획
외부 평가연 1회외부 전문기관종합 개선 계획
정부 점검수시관계 공무원행정조치 대응
+
+
+ + +
+
+

9. HSE 목표 설정 및 관리

+
+ +
+

9.1 목표 설정 원칙

+
+

🎯 SMART 원칙

+
    +
  • Specific (구체적): 명확하고 구체적인 목표
  • +
  • Measurable (측정가능): 정량적으로 측정 가능
  • +
  • Achievable (달성가능): 현실적으로 달성 가능
  • +
  • Relevant (관련성): HSE 정책과 연관성
  • +
  • Time-bound (시한설정): 명확한 달성 기한
  • +
+ +

📋 목표 설정 고려사항

+
    +
  • HSE 정책과의 일치성
  • +
  • 법적 요구사항 반영
  • +
  • 위험 평가 결과 반영
  • +
  • 기술적, 재정적 실현가능성
  • +
  • 이해관계자 기대사항
  • +
  • 지속적 개선 의지
  • +
+
+
+ +
+

9.2 목표 영역별 설정

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
영역목표 예시측정 지표목표값
안전재해율 감소재해율 (%)전년 대비 20% 감소
위험성 평가 완료평가 완료율 (%)100% 완료
안전교육 강화교육 이수율 (%)95% 이상
보건직업병 발생 Zero직업병 발생 건수0건
건강진단 실시수진율 (%)100%
환경폐기물 감량폐기물 발생량 (톤)전년 대비 10% 감소
에너지 절약에너지 사용량 (kWh)전년 대비 5% 감소
+
+ +
+

9.3 실행 계획 수립

+

9.3.1 계획 수립 절차

+
    +
  1. 세부 과제 도출: 목표 달성을 위한 구체적 과제
  2. +
  3. 일정 계획: 단계별 추진 일정 수립
  4. +
  5. 책임자 지정: 과제별 담당자 및 책임자 배정
  6. +
  7. 자원 배정: 필요 인력, 예산, 자원 확보
  8. +
  9. 성과 지표: 중간 및 최종 성과 측정 지표
  10. +
  11. 점검 체계: 정기적 진행상황 점검 방법
  12. +
+ +

9.3.2 모니터링 및 검토

+
    +
  • 월별 점검: 진행상황 및 성과 확인
  • +
  • 분기별 평가: 목표 달성도 종합 평가
  • +
  • 연간 검토: 목표 적절성 및 달성 결과 종합 분석
  • +
  • 개선 조치: 미달성 원인 분석 및 개선 방안 수립
  • +
+
+
+ + +
+
+

10. 기록 관리

+
+ +

10.1 작성 기록

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
기록명작성자보관 기간보관 장소
위험과 기회 등록부HSE 담당자3년HSE 관리부서
유해요인 식별표각 부서장3년각 부서
위험 평가서HSE 담당자5년HSE 관리부서
법적 요구사항 목록HSE 관리책임자영구HSE 관리부서
HSE 목표 및 계획서HSE 관리책임자5년HSE 관리부서
진행상황 점검표각 부서장3년각 부서
+
+ + +
+
+

11. 첨부 서식

+
+ +
    +
  • 첨부 1: 위험과 기회 식별 체크리스트
  • +
  • 첨부 2: 유해요인 식별표 양식
  • +
  • 첨부 3: 위험 평가 매트릭스
  • +
  • 첨부 4: 위험 평가서 양식
  • +
  • 첨부 5: 법적 요구사항 등록부
  • +
  • 첨부 6: HSE 목표 설정 템플릿
  • +
  • 첨부 7: 실행 계획서 양식
  • +
  • 첨부 8: 진행상황 점검표
  • +
+
+
+ + +
+ +
+

TK-HSE-P-610

+

Planning and Risk Management Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitlePlanning and Risk Management Procedure
Document NumberTK-HSE-P-610
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 9
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+
+

1. PURPOSE

+
+

The purpose of this procedure is to:

+
    +
  • Systematic planning and implementation of HSE management system
  • +
  • Establish effective actions to address risks and opportunities
  • +
  • Systematic performance of hazard identification and HSE risk assessment
  • +
  • Systematic management of legal requirements and other requirements
  • +
  • Establish measurable HSE objectives and achievement plans
  • +
  • Effective implementation of ISO 45001:2018 Clause 6 requirements
  • +
+
+ + +
+
+

2. SCOPE

+
+

This procedure applies to the following areas of Technicalkorea:

+
    +
  • All activities within the scope of HSE management system application
  • +
  • All business sites including head office, factories, and branches
  • +
  • Regular, irregular, and contractor workers
  • +
  • Product production, service provision, and support activities
  • +
  • Routine and non-routine work, emergency situations
  • +
  • Past, present, and planned future activities
  • +
+
+ + +
+
+

3. NORMATIVE REFERENCES AND RELATED DOCUMENTS

+
+

3.1 Normative References

+
    +
  • ISO 45001:2018 - Occupational health and safety management systems - Requirements with guidance for use
  • +
  • ISO 31000:2018 - Risk management - Guidelines
  • +
  • Occupational Safety and Health Act and related regulations
  • +
  • Framework Act on Environmental Policy and related regulations
  • +
+ +

3.2 Related Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-410 - Understanding Organizational Context and HSE Management System Operation Procedure
  • +
  • TK-HSE-P-620 - Risk Assessment Procedure
  • +
  • TK-HSE-P-630 - HSE Legal Requirements Management Procedure
  • +
  • TK-HSE-P-640 - HSE Objectives Management Procedure
  • +
+
+ + +
+
+

4. TERMS AND DEFINITIONS

+
+ +
+

4.1 Risk

+

Effect of uncertainty, positive or negative deviation from objectives

+ +

4.2 Opportunity

+

Possibility of bringing positive results such as HSE performance improvement, waste reduction, accident prevention

+ +

4.3 Hazard

+

Source with a potential to cause injury and ill health

+ +

4.4 Risk Assessment

+

Overall process of risk identification, analysis and evaluation

+ +

4.5 Legal Requirements

+

Laws, regulations, orders, etc. that the organization must comply with

+ +

4.6 Objective

+

Result or performance to be achieved

+
+
+ + +
+
+

5. PROCESS FLOW

+
+ +
+
Planning Process Start
+
+
Risk and Opportunity Identification
+
+
Hazard Identification
+
+
Risk Assessment
+
+
Legal Requirements Identification
+
+
HSE Objectives Setting
+
+
Implementation Plan Development
+
+
Approval and Implementation
+
+
Monitoring and Review
+
+
+ + +
+
+

6. RISK AND OPPORTUNITY MANAGEMENT

+
+ +
+

6.1 Risk and Opportunity Identification

+

6.1.1 Identification Targets

+ + + + + + + + + + + + + + + + + + + + + +
CategoryIdentification TargetsConsiderations
Internal Risks• Equipment failure
• Human error
• Organizational change
• Resource shortage
• Probability of occurrence
• Impact level
• Controllability
• Response time
External Risks• Natural disasters
• Regulatory changes
• Market changes
• Supplier issues
• Predictability
• Response capability
• Recovery time
• Cost impact
Opportunities• Technology improvement
• Cost reduction
• Efficiency enhancement
• Image improvement
• Feasibility
• Return on investment
• Competitive advantage
• Sustainability
+
+ +
+

6.2 Risk and Opportunity Assessment

+
+

📊 Risk Assessment Matrix

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LikelihoodConsequence
1 (Minor)2 (Moderate)3 (Major)4 (Severe)5 (Catastrophic)
5 (Very High)510152025
4 (High)48121620
3 (Moderate)3691215
2 (Low)246810
1 (Very Low)12345
+ +

🎯 Risk Level Response Criteria

+
    +
  • High Risk (15-25): Immediate action required, consider work stoppage
  • +
  • Medium Risk (8-12): Improvement measures required in short term
  • +
  • Low Risk (3-6): Planned improvement measures
  • +
  • Acceptable (1-2): Maintain current level, regular monitoring
  • +
+
+
+ +
+

6.3 Action Plan Development

+

6.3.1 Risk Response Strategy

+
+

🔺 Risk Management Hierarchy

+
    +
  1. Elimination: Remove the risk factor itself
  2. +
  3. Substitution: Replace with safer alternatives
  4. +
  5. Engineering Controls: Reduce risk through technical methods
  6. +
  7. Administrative Controls: Management through procedures, education, training
  8. +
  9. Personal Protective Equipment (PPE): Protection through personal protective equipment
  10. +
+
+
+
+ + +
+
+

7. HAZARD IDENTIFICATION AND RISK ASSESSMENT

+
+ +
+

7.1 Hazard Classification

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ClassificationSub-typesMain Examples
Physical HazardsMechanical risks• Rotating parts, crushing, collision
• Falling, overturning, falling from height
Environmental risks• Noise, vibration, temperature
• Lighting, radiation
Electrical risks• Electric shock, fire, explosion
• Static electricity, lightning
Chemical HazardsToxic substances• Acids, alkalis, solvents
• Heavy metals, carcinogens
Gases/vapors• Toxic gases, asphyxiant gases
• Flammable gases
Biological HazardsPathogens• Bacteria, viruses, fungi
• Parasites, toxins
Allergens• Pollen, dust
• Animal fur, food
Ergonomic HazardsWork posture• Inappropriate posture
• Repetitive work, heavy objects
Work design• Workbench height
• Tool design, space
Psychosocial HazardsWork stress• Excessive workload
• Time pressure, responsibility
Organizational culture• Harassment, violence
• Lack of communication
+
+
+ + +
+
+

8. LEGAL REQUIREMENTS MANAGEMENT

+
+ +
+

8.1 Legal Requirements Identification

+

8.1.1 Major Laws

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldMajor LawsKey Requirements
SafetyOccupational Safety and Health Act• Establish safety and health management system
• Conduct risk assessment
• Implement safety and health education
Construction Equipment Management Act• Construction equipment inspection
• Operator license
• Safe operation
Chemical Control Act• Chemical registration
• Comply with handling standards
• Accident reporting
HealthOccupational Safety and Health Act• Work environment measurement
• Health examination
• Occupational disease prevention
Infectious Disease Control and Prevention Act• Infectious disease prevention measures
• Reporting obligation
• Quarantine activities
EnvironmentFramework Act on Environmental Policy• Environmental pollution prevention
• Minimize environmental impact
• Sustainable development
Clean Air Conservation Act• Comply with emission standards
• Install prevention facilities
• Measurement and reporting
Waste Management Act• Waste separation
• Consignment treatment
• Treatment status reporting
+
+
+ + +
+
+

9. HSE OBJECTIVES SETTING AND MANAGEMENT

+
+ +
+

9.1 Objective Setting Principles

+
+

🎯 SMART Principles

+
    +
  • Specific: Clear and specific objectives
  • +
  • Measurable: Quantitatively measurable
  • +
  • Achievable: Realistically achievable
  • +
  • Relevant: Related to HSE policy
  • +
  • Time-bound: Clear achievement deadline
  • +
+ +

📋 Objective Setting Considerations

+
    +
  • Consistency with HSE policy
  • +
  • Reflection of legal requirements
  • +
  • Reflection of risk assessment results
  • +
  • Technical and financial feasibility
  • +
  • Stakeholder expectations
  • +
  • Commitment to continuous improvement
  • +
+
+
+ +
+

9.2 Objectives by Area

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
AreaObjective ExamplesMeasurement IndicatorsTarget Values
SafetyReduce accident rateAccident rate (%)20% reduction from previous year
Complete risk assessmentAssessment completion rate (%)100% completion
Strengthen safety educationEducation completion rate (%)95% or higher
HealthZero occupational disease occurrenceNumber of occupational disease cases0 cases
Conduct health examinationsExamination rate (%)100%
EnvironmentWaste reductionWaste generation (tons)10% reduction from previous year
Energy savingEnergy consumption (kWh)5% reduction from previous year
+
+
+ + +
+
+

10. RECORDS MANAGEMENT

+
+ +

10.1 Records to be Created

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Record NameCreatorRetention PeriodStorage Location
Risk and Opportunity RegisterHSE Staff3 yearsHSE Management Department
Hazard Identification TableEach Department Head3 yearsEach Department
Risk Assessment ReportHSE Staff5 yearsHSE Management Department
Legal Requirements ListHSE ManagerPermanentHSE Management Department
HSE Objectives and PlansHSE Manager5 yearsHSE Management Department
Progress Monitoring SheetEach Department Head3 yearsEach Department
+
+ + +
+
+

11. APPENDIX FORMS

+
+ +
    +
  • Appendix 1: Risk and Opportunity Identification Checklist
  • +
  • Appendix 2: Hazard Identification Table Form
  • +
  • Appendix 3: Risk Assessment Matrix
  • +
  • Appendix 4: Risk Assessment Report Form
  • +
  • Appendix 5: Legal Requirements Register
  • +
  • Appendix 6: HSE Objectives Setting Template
  • +
  • Appendix 7: Implementation Plan Form
  • +
  • Appendix 8: Progress Monitoring Sheet
  • +
+
+ +
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-620.html b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-620.html new file mode 100644 index 0000000..c552dcd --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-620.html @@ -0,0 +1,1784 @@ + + + + + + TK-HSE-P-620 위험 평가 절차 + + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-620

+

위험 평가 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목위험 평가 절차
문서 번호TK-HSE-P-620
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+

1. 목적

+
+

본 절차는 테크니컬코리아의 모든 사업장 및 활동에서 발생할 수 있는 보건, 안전 및 환경(HSE) 위험요소를 체계적으로 식별, 평가 및 관리하기 위한 표준화된 방법론을 제공함을 목적으로 합니다.

+

이를 통해 근로자의 안전과 건강을 보호하고, 환경 영향을 최소화하며, ISO 45001:2018 요구사항에 부합하는 위험 관리 체계를 구축합니다.

+ + +
+

2. 적용 범위

+
+

본 절차는 다음에 적용됩니다:

+
    +
  • 테크니컬코리아의 모든 사업장, 시설 및 작업 현장
  • +
  • 정규직, 계약직, 파견직, 협력업체 직원을 포함한 모든 근로자
  • +
  • 일상적 및 비일상적 작업 활동
  • +
  • 제품 및 서비스의 전체 생명주기
  • +
  • 계획된 변경사항 및 비상상황
  • +
  • 모든 방문자 및 외부 이해관계자
  • +
+ + +
+

3. 관련 문서

+
+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-610 - 기획 및 위험 관리 절차
  • +
  • TK-HSE-P-630 - HSE 법적 요구사항 관리 절차
  • +
  • TK-HSE-P-810 - 운영 기획 및 관리 절차
  • +
  • TK-HSE-P-1010 - 사건, 부적합 및 시정조치 절차
  • +
  • ISO 45001:2018 - 보건안전경영시스템 요구사항
  • +
  • 산업안전보건법 및 관련 시행령, 시행규칙
  • +
  • 환경정책기본법 및 관련 법령
  • +
+ + +
+

4. 용어의 정의

+
+
+

4.1 유해요인(Hazard)

+

부상과 건강악화를 일으킬 잠재성을 가진 근원으로, 물리적, 화학적, 생물학적, 인간공학적, 심리사회적 요인을 포함합니다.

+ +

4.2 위험(Risk)

+

유해요인에 노출될 확률과 그로 인한 부상이나 건강악화의 심각성을 조합한 개념입니다.

+ +

4.3 위험 평가(Risk Assessment)

+

유해요인을 식별하고, 관련 위험을 분석 및 평가하는 전체적인 과정입니다.

+ +

4.4 허용 가능한 위험(Acceptable Risk)

+

조직의 법적 의무와 HSE 정책에 따라 수용 가능한 수준까지 감소된 위험입니다.

+ +

4.5 잔류 위험(Residual Risk)

+

위험 대응 조치를 실행한 후에도 남아있는 위험입니다.

+
+ + +
+

5. 역할과 책임

+
+
+

5.1 최고경영자

+
    +
  • 위험 평가 프로세스에 대한 최종 책임
  • +
  • 위험 평가에 필요한 자원 배정
  • +
  • 중대한 위험에 대한 의사결정
  • +
+ +

5.2 HSE 관리책임자

+
    +
  • 위험 평가 절차의 수립 및 유지
  • +
  • 위험 평가 팀 구성 및 교육
  • +
  • 위험 평가 결과의 검토 및 승인
  • +
  • 위험 평가 현황 모니터링
  • +
+ +

5.3 부서장/현장 관리자

+
    +
  • 담당 영역의 위험 평가 실시
  • +
  • 위험 통제 조치의 실행
  • +
  • 근로자의 위험 평가 참여 보장
  • +
  • 위험 평가 결과의 현장 적용
  • +
+ +

5.4 근로자

+
    +
  • 위험 평가 과정에 적극 참여
  • +
  • 유해요인 및 위험 상황 보고
  • +
  • 위험 통제 조치 준수
  • +
  • 안전 교육 및 훈련 참석
  • +
+ +

5.5 위험 평가팀

+
    +
  • 체계적인 위험 평가 수행
  • +
  • 위험 평가 보고서 작성
  • +
  • 위험 통제 조치 제안
  • +
  • 위험 평가 결과의 지속적 모니터링
  • +
+
+ + +
+

6. 위험 평가 프로세스

+
+ +
+
준비 및 기획
+ +
유해요인 식별
+ +
위험 분석
+

+
위험 평가
+ +
위험 대응
+ +
모니터링 및 검토
+
+ +
+

6.1 준비 및 기획 단계

+

6.1.1 위험 평가 범위 설정

+
    +
  • 평가 대상 작업, 활동, 시설의 명확한 정의
  • +
  • 평가 기간 및 주기 결정
  • +
  • 관련 법규 및 표준 확인
  • +
  • 이전 평가 결과 및 사고 이력 검토
  • +
+ +

6.1.2 위험 평가팀 구성

+
    +
  • 팀장: HSE 관리책임자 또는 지정된 담당자
  • +
  • 팀원: 해당 분야 전문가, 현장 관리자, 근로자 대표
  • +
  • 필요시 외부 전문가 참여
  • +
  • 팀원에 대한 위험 평가 교육 실시
  • +
+ +

6.1.3 정보 수집

+
    +
  • 작업 절차서 및 매뉴얼
  • +
  • 물질안전보건자료(MSDS)
  • +
  • 장비 및 기계 사양서
  • +
  • 과거 사고 및 아차사고 기록
  • +
  • 건강 검진 결과 및 직업병 발생 현황
  • +
  • 환경 모니터링 데이터
  • +
+
+ +
+

6.2 유해요인 식별

+

6.2.1 식별 방법

+
    +
  • 현장 조사 및 관찰
  • +
  • 작업 분석 및 작업 조건 검토
  • +
  • 근로자 면담 및 설문조사
  • +
  • 과거 사고 및 질병 기록 분석
  • +
  • 체크리스트 활용
  • +
  • 브레인스토밍 세션
  • +
+ +

6.2.2 유해요인 분류

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
분류유해요인 예시
물리적 유해요인소음, 진동, 온도, 조명, 방사선, 전기
화학적 유해요인독성물질, 부식성물질, 가연성물질, 분진, 가스, 증기
생물학적 유해요인세균, 바이러스, 곰팡이, 기생충
인간공학적 유해요인반복작업, 과도한 힘, 부자연스러운 자세, 진동
심리사회적 유해요인업무 스트레스, 작업 강도, 인간관계, 직장 내 괴롭힘
환경적 유해요인대기오염, 수질오염, 토양오염, 폐기물
+ +

6.2.3 노출 상황 고려사항

+
    +
  • 일상적 작업과 비일상적 작업
  • +
  • 정상 운영 조건과 비정상 조건
  • +
  • 비상상황 및 잠재적 사고 시나리오
  • +
  • 모든 작업자 및 방문자의 노출
  • +
  • 작업장 접근 경로 및 주변 영향
  • +
+
+ +
+

6.3 위험 분석

+

6.3.1 발생가능성 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
등급설명기준
5 (매우 높음)거의 확실히 발생주 1회 이상 또는 연간 50회 이상
4 (높음)발생 가능성이 높음월 1회 이상 또는 연간 12-50회
3 (보통)가끔 발생 가능년 1회 이상 또는 연간 1-12회
2 (낮음)발생 가능성이 낮음수년에 1회 또는 10년에 1-10회
1 (매우 낮음)거의 발생하지 않음10년에 1회 미만
+ +

6.3.2 심각성 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
등급설명인명 피해환경 영향
5 (치명적)사망 또는 영구장애사망 또는 영구 전신장애심각한 환경오염, 복구 불가능
4 (심각)중대한 부상 또는 질병중상, 만성질환, 부분장애중대한 환경영향, 복구 어려움
3 (보통)의료처치 필요의료처치 필요한 부상보통의 환경영향, 복구 가능
2 (경미)응급처치 필요응급처치 수준의 부상경미한 환경영향
1 (무시)부상 없음부상이나 건강영향 없음환경영향 무시할 수준
+
+ +
+

6.4 위험 평가

+

6.4.1 위험도 계산

+

위험도 = 발생가능성 × 심각성

+ +

6.4.2 위험도 매트릭스

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
심각성발생가능성
12345
5510152025
448121620
33691215
2246810
112345
+ +

6.4.3 위험도 분류 및 대응방안

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
위험도분류대응방안대응시한
20-25매우 높음즉시 작업 중단, 긴급 대책 수립즉시
10-19높음상세한 대책 수립 및 즉시 실행1주 이내
5-9보통대책 수립 및 계획에 따라 실행1개월 이내
1-4낮음현재 수준 유지, 정기 모니터링3개월 이내
+
+ + +
+

7. 위험 통제

+
+
+

7.1 통제 위계 (Hierarchy of Controls)

+
    +
  1. 제거 (Elimination): 유해요인 자체를 제거
  2. +
  3. 대체 (Substitution): 덜 위험한 방법, 재료, 장비로 대체
  4. +
  5. 공학적 통제 (Engineering Controls): 환기시설, 차폐, 격리 등
  6. +
  7. 관리적 통제 (Administrative Controls): 절차, 교육, 훈련, 표지판 등
  8. +
  9. 개인보호구 (Personal Protective Equipment): 마지막 수단으로 사용
  10. +
+ +

7.2 통제 조치 선정 기준

+
    +
  • 효과성: 위험 감소 효과
  • +
  • 실현가능성: 기술적, 경제적 실현 가능성
  • +
  • 수용성: 근로자 및 조직의 수용도
  • +
  • 지속성: 장기간 유지 가능성
  • +
  • 법적 요구사항 부합성
  • +
+ +

7.3 통제 조치 실행

+
    +
  • 실행 계획 수립 (담당자, 일정, 예산)
  • +
  • 필요한 자원 확보
  • +
  • 관련 인원 교육 및 훈련
  • +
  • 실행 상황 모니터링
  • +
  • 효과성 검증
  • +
+
+ + +
+

8. 문서화

+
+
+

8.1 위험 평가 보고서

+

모든 위험 평가 결과는 다음 내용을 포함하여 문서화해야 합니다:

+
    +
  • 평가 대상 및 범위
  • +
  • 평가팀 구성 및 역할
  • +
  • 평가 방법론
  • +
  • 식별된 유해요인 목록
  • +
  • 위험 분석 및 평가 결과
  • +
  • 제안된 통제 조치
  • +
  • 실행 계획
  • +
  • 모니터링 계획
  • +
+ +

8.2 위험 등록부 (Risk Register)

+

조직 차원의 통합 위험 등록부를 유지하며 다음 정보를 포함합니다:

+
    +
  • 위험 식별번호
  • +
  • 위험 설명
  • +
  • 영향 범위
  • +
  • 현재 통제 조치
  • +
  • 잔류 위험도
  • +
  • 추가 조치 계획
  • +
  • 담당자 및 일정
  • +
  • 검토 일정
  • +
+
+ + +
+

9. 모니터링 및 검토

+
+
+

9.1 정기 검토

+
    +
  • 일상 점검: 현장 관리자의 일일 안전 점검
  • +
  • 월간 검토: 부서별 위험 평가 현황 검토
  • +
  • 분기 검토: HSE 위원회의 위험 관리 현황 검토
  • +
  • 연간 검토: 전사 위험 평가의 전면적 재검토
  • +
+ +

9.2 검토 트리거

+

다음 상황에서는 즉시 위험 평가를 재검토해야 합니다:

+
    +
  • 사고 또는 아차사고 발생
  • +
  • 새로운 법규 또는 표준 시행
  • +
  • 작업 방법 또는 절차 변경
  • +
  • 새로운 장비 또는 화학물질 도입
  • +
  • 조직 구조 또는 인원 변경
  • +
  • 통제 조치의 실패 또는 부적절함 확인
  • +
+ +

9.3 성과 지표

+
    +
  • 위험 평가 완료율
  • +
  • 고위험 요소 감소율
  • +
  • 통제 조치 실행율
  • +
  • 사고 발생률 감소
  • +
  • 근로자 참여도
  • +
+
+ + +
+

10. 교육 및 훈련

+
+
+

10.1 교육 대상 및 내용

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
대상교육 내용주기
위험 평가팀위험 평가 방법론, 기법, 도구 사용법연 1회
관리자위험 관리 원칙, 통제 조치 선정 및 실행연 1회
근로자유해요인 인식, 위험 보고, 안전 수칙분기 1회
신입사원HSE 정책, 위험 평가 개념, 참여 방법입사시
+ +

10.2 교육 방법

+
    +
  • 집합 교육 및 워크숍
  • +
  • 온라인 교육 프로그램
  • +
  • 현장 실습 및 사례 연구
  • +
  • 외부 전문 교육 과정
  • +
+
+ + +
+
+

11. 위험 평가 양식

+
+ +
+

위험 평가 기본 정보

+ + + + + + + + + + + + + + + + + + + + + + + +
평가 번호평가 일자
평가 대상평가 유형□ 정기 □ 수시 □ 변경
평가팀장부서/현장
참여자
+
+ +
+

유해요인 식별 및 위험 평가

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
작업/활동유해요인잠재적 결과현재 통제조치발생가능성심각성위험도위험 수준
+
+ +
+

위험 통제 조치

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
제안 조치우선순위담당자완료 예정일예상 효과잔류 위험도
+
+ +
+

승인

+ + + + + + + + + + + + + + + + + + + +
작성자성명:서명:일자:
검토자성명:서명:일자:
승인자성명:서명:일자:
+
+
+ + +
+

12. 문서 관리

+
+

이것은 통제 문서입니다

+

승인 없이 복사하지 마십시오

+

최신 버전은 회사 인트라넷에서 확인할 수 있습니다

+

이 문서에 대한 문의사항은 HSE 관리부서로 연락하십시오

+
+ + +
+ +
+

TK-HSE-P-620

+

Risk Assessment Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleRisk Assessment Procedure
Document NumberTK-HSE-P-620
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+

1. PURPOSE

+
+

This procedure aims to provide a standardized methodology for systematically identifying, assessing, and managing health, safety, and environmental (HSE) risk factors that may occur in all workplaces and activities of Technicalkorea.

+

Through this, we protect the safety and health of workers, minimize environmental impacts, and establish a risk management system that complies with ISO 45001:2018 requirements.

+ + +
+

2. SCOPE

+
+

This procedure applies to:

+
    +
  • All workplaces, facilities, and work sites of Technicalkorea
  • +
  • All workers including permanent, contract, temporary, and contractor personnel
  • +
  • Routine and non-routine work activities
  • +
  • Entire life cycle of products and services
  • +
  • Planned changes and emergency situations
  • +
  • All visitors and external stakeholders
  • +
+ + +
+

3. RELATED DOCUMENTS

+
+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-610 - Planning and Risk Management Procedure
  • +
  • TK-HSE-P-630 - HSE Legal Requirements Management Procedure
  • +
  • TK-HSE-P-810 - Operational Planning and Control Procedure
  • +
  • TK-HSE-P-1010 - Incident, Nonconformity and Corrective Action Procedure
  • +
  • ISO 45001:2018 - Occupational Health and Safety Management Systems Requirements
  • +
  • Occupational Safety and Health Act and related enforcement decrees and rules
  • +
  • Framework Act on Environmental Policy and related laws
  • +
+ + +
+

4. TERMS AND DEFINITIONS

+
+
+

4.1 Hazard

+

Source with a potential to cause injury and ill health, including physical, chemical, biological, ergonomic, and psychosocial factors.

+ +

4.2 Risk

+

A concept that combines the probability of exposure to hazards and the severity of resulting injury or ill health.

+ +

4.3 Risk Assessment

+

The overall process of identifying hazards and analyzing and evaluating related risks.

+ +

4.4 Acceptable Risk

+

Risk that has been reduced to a level that can be tolerated by the organization having regard to its legal obligations and HSE policy.

+ +

4.5 Residual Risk

+

Risk remaining after risk treatment measures have been implemented.

+
+ + +
+

5. ROLES AND RESPONSIBILITIES

+
+
+

5.1 Top Management

+
    +
  • Ultimate responsibility for risk assessment process
  • +
  • Allocation of resources required for risk assessment
  • +
  • Decision-making on significant risks
  • +
+ +

5.2 HSE Manager

+
    +
  • Establishment and maintenance of risk assessment procedures
  • +
  • Formation and training of risk assessment teams
  • +
  • Review and approval of risk assessment results
  • +
  • Monitoring risk assessment status
  • +
+ +

5.3 Department Heads/Site Managers

+
    +
  • Conducting risk assessments in their areas of responsibility
  • +
  • Implementation of risk control measures
  • +
  • Ensuring worker participation in risk assessment
  • +
  • Field application of risk assessment results
  • +
+ +

5.4 Workers

+
    +
  • Active participation in risk assessment process
  • +
  • Reporting hazards and risk situations
  • +
  • Compliance with risk control measures
  • +
  • Attendance at safety education and training
  • +
+ +

5.5 Risk Assessment Team

+
    +
  • Systematic risk assessment performance
  • +
  • Preparation of risk assessment reports
  • +
  • Proposal of risk control measures
  • +
  • Continuous monitoring of risk assessment results
  • +
+
+ + +
+

6. RISK ASSESSMENT PROCESS

+
+ +
+
Preparation & Planning
+ +
Hazard Identification
+ +
Risk Analysis
+

+
Risk Evaluation
+ +
Risk Treatment
+ +
Monitoring & Review
+
+ +
+

6.1 Preparation and Planning Phase

+

6.1.1 Risk Assessment Scope Setting

+
    +
  • Clear definition of work, activities, and facilities to be assessed
  • +
  • Determination of assessment period and cycle
  • +
  • Confirmation of relevant regulations and standards
  • +
  • Review of previous assessment results and incident history
  • +
+ +

6.1.2 Risk Assessment Team Formation

+
    +
  • Team Leader: HSE Manager or designated person
  • +
  • Team Members: Subject matter experts, site managers, worker representatives
  • +
  • External experts participation when necessary
  • +
  • Risk assessment training for team members
  • +
+ +

6.1.3 Information Collection

+
    +
  • Work procedures and manuals
  • +
  • Material Safety Data Sheets (MSDS)
  • +
  • Equipment and machinery specifications
  • +
  • Past accident and near-miss records
  • +
  • Health examination results and occupational disease status
  • +
  • Environmental monitoring data
  • +
+
+ +
+

6.2 Hazard Identification

+

6.2.1 Identification Methods

+
    +
  • Site inspection and observation
  • +
  • Work analysis and working condition review
  • +
  • Worker interviews and surveys
  • +
  • Analysis of past accident and disease records
  • +
  • Checklist utilization
  • +
  • Brainstorming sessions
  • +
+ +

6.2.2 Hazard Classification

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ClassificationHazard Examples
Physical HazardsNoise, vibration, temperature, lighting, radiation, electricity
Chemical HazardsToxic substances, corrosive substances, flammable substances, dust, gas, vapor
Biological HazardsBacteria, viruses, fungi, parasites
Ergonomic HazardsRepetitive work, excessive force, awkward postures, vibration
Psychosocial HazardsWork stress, work intensity, human relations, workplace harassment
Environmental HazardsAir pollution, water pollution, soil contamination, waste
+ +

6.2.3 Exposure Situation Considerations

+
    +
  • Routine and non-routine work
  • +
  • Normal and abnormal operating conditions
  • +
  • Emergency situations and potential accident scenarios
  • +
  • Exposure of all workers and visitors
  • +
  • Workplace access routes and surrounding impacts
  • +
+
+ +
+

6.3 Risk Analysis

+

6.3.1 Likelihood Assessment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LevelDescriptionCriteria
5 (Very High)Almost certain to occurMore than once a week or 50+ times per year
4 (High)Likely to occurMore than once a month or 12-50 times per year
3 (Medium)May occur occasionallyMore than once a year or 1-12 times per year
2 (Low)Unlikely to occurOnce in several years or 1-10 times in 10 years
1 (Very Low)Rare occurrenceLess than once in 10 years
+ +

6.3.2 Severity Assessment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
LevelDescriptionHuman ImpactEnvironmental Impact
5 (Fatal)Death or permanent disabilityDeath or permanent total disabilitySevere environmental pollution, irreversible
4 (Serious)Major injury or illnessSerious injury, chronic disease, partial disabilityMajor environmental impact, difficult to recover
3 (Moderate)Medical treatment requiredInjury requiring medical treatmentModerate environmental impact, recoverable
2 (Minor)First aid requiredFirst aid level injuryMinor environmental impact
1 (Negligible)No injuryNo injury or health impactNegligible environmental impact
+
+ +
+

6.4 Risk Evaluation

+

6.4.1 Risk Level Calculation

+

Risk Level = Likelihood × Severity

+ +

6.4.2 Risk Matrix

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
SeverityLikelihood
12345
5510152025
448121620
33691215
2246810
112345
+ +

6.4.3 Risk Level Classification and Response

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Risk LevelClassificationResponseTimeline
20-25Very HighImmediate work stoppage, emergency measuresImmediate
10-19HighDetailed measures development and immediate implementationWithin 1 week
5-9MediumMeasures development and planned implementationWithin 1 month
1-4LowMaintain current level, regular monitoringWithin 3 months
+
+ + +
+

7. RISK CONTROL

+
+
+

7.1 Hierarchy of Controls

+
    +
  1. Elimination: Remove the hazard entirely
  2. +
  3. Substitution: Replace with less hazardous methods, materials, or equipment
  4. +
  5. Engineering Controls: Ventilation, shielding, isolation, etc.
  6. +
  7. Administrative Controls: Procedures, training, education, signage, etc.
  8. +
  9. Personal Protective Equipment (PPE): Use as last resort
  10. +
+ +

7.2 Control Measure Selection Criteria

+
    +
  • Effectiveness: Risk reduction effect
  • +
  • Feasibility: Technical and economic feasibility
  • +
  • Acceptability: Worker and organizational acceptance
  • +
  • Sustainability: Long-term maintainability
  • +
  • Legal compliance
  • +
+ +

7.3 Control Measure Implementation

+
    +
  • Implementation plan development (responsible person, schedule, budget)
  • +
  • Securing necessary resources
  • +
  • Training and education of relevant personnel
  • +
  • Implementation status monitoring
  • +
  • Effectiveness verification
  • +
+
+ + +
+

8. DOCUMENTATION

+
+
+

8.1 Risk Assessment Report

+

All risk assessment results must be documented including the following content:

+
    +
  • Assessment target and scope
  • +
  • Assessment team composition and roles
  • +
  • Assessment methodology
  • +
  • List of identified hazards
  • +
  • Risk analysis and evaluation results
  • +
  • Proposed control measures
  • +
  • Implementation plan
  • +
  • Monitoring plan
  • +
+ +

8.2 Risk Register

+

Maintain an integrated organizational risk register including the following information:

+
    +
  • Risk identification number
  • +
  • Risk description
  • +
  • Impact scope
  • +
  • Current control measures
  • +
  • Residual risk level
  • +
  • Additional measure plans
  • +
  • Responsible person and schedule
  • +
  • Review schedule
  • +
+
+ + +
+

9. MONITORING AND REVIEW

+
+
+

9.1 Regular Review

+
    +
  • Daily Inspection: Daily safety inspections by site managers
  • +
  • Monthly Review: Departmental risk assessment status review
  • +
  • Quarterly Review: HSE committee risk management status review
  • +
  • Annual Review: Comprehensive review of company-wide risk assessments
  • +
+ +

9.2 Review Triggers

+

Risk assessments must be immediately re-reviewed in the following situations:

+
    +
  • Occurrence of accidents or near-misses
  • +
  • Implementation of new regulations or standards
  • +
  • Changes in work methods or procedures
  • +
  • Introduction of new equipment or chemicals
  • +
  • Changes in organizational structure or personnel
  • +
  • Identification of control measure failure or inadequacy
  • +
+ +

9.3 Performance Indicators

+
    +
  • Risk assessment completion rate
  • +
  • High-risk factor reduction rate
  • +
  • Control measure implementation rate
  • +
  • Accident occurrence rate reduction
  • +
  • Worker participation rate
  • +
+
+ + +
+

10. TRAINING AND EDUCATION

+
+
+

10.1 Training Target and Content

+ + + + + + + + + + + + + + + + + + + + + + + + + + +
TargetTraining ContentFrequency
Risk Assessment TeamRisk assessment methodology, techniques, tool usageAnnual
ManagersRisk management principles, control measure selection and implementationAnnual
WorkersHazard recognition, risk reporting, safety rulesQuarterly
New EmployeesHSE policy, risk assessment concepts, participation methodsUpon hiring
+ +

10.2 Training Methods

+
    +
  • Group training and workshops
  • +
  • Online training programs
  • +
  • Field practice and case studies
  • +
  • External professional training courses
  • +
+
+ + +
+
+

11. RISK ASSESSMENT FORM

+
+ +
+

Risk Assessment Basic Information

+ + + + + + + + + + + + + + + + + + + + + + + +
Assessment No.Assessment Date
Assessment TargetAssessment Type□ Regular □ Ad-hoc □ Change
Team LeaderDepartment/Site
Participants
+
+ +
+

Hazard Identification and Risk Assessment

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Work/ActivityHazardPotential ConsequenceCurrent ControlsLikelihoodSeverityRisk LevelRisk Rating
+
+ +
+

Risk Control Measures

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Proposed MeasuresPriorityResponsible PersonTarget DateExpected EffectResidual Risk
+
+ +
+

Approval

+ + + + + + + + + + + + + + + + + + + +
Prepared byName:Signature:Date:
Reviewed byName:Signature:Date:
Approved byName:Signature:Date:
+
+
+ + +
+

12. DOCUMENT CONTROL

+
+

This is a controlled document

+

Do not copy without authorization

+

The latest version can be found on the company intranet

+

For inquiries about this document, contact the HSE Management Department

+
+
+ + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-630.html b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-630.html new file mode 100644 index 0000000..1f3f431 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/hse/TK-HSE-P-630.html @@ -0,0 +1,1894 @@ + + + + + + TK-HSE-P-630 HSE 법적 요구사항 관리 절차 + + + + +
+ +
+ + +
+ + +
+ +
+

TK-HSE-P-630

+

HSE 법적 요구사항 관리 절차

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목HSE 법적 요구사항 관리 절차
문서 번호TK-HSE-P-630
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+

1. 목적

+
+

본 절차는 테크니컬코리아의 사업 활동과 관련된 보건, 안전 및 환경(HSE) 법적 요구사항을 체계적으로 식별, 접근, 평가 및 관리하기 위한 프레임워크를 제공함을 목적으로 합니다.

+

이를 통해 법적 요구사항의 준수를 보장하고, 법규 위반으로 인한 리스크를 최소화하며, 지속적인 개선을 통한 HSE 성과 향상을 달성합니다.

+ +
+ 중요: 법적 요구사항의 식별과 준수는 조직의 HSE 경영시스템의 핵심 요소이며, ISO 45001:2018 및 ISO 14001:2015의 필수 요구사항입니다. +
+ + +
+

2. 적용 범위

+
+

본 절차는 다음에 적용됩니다:

+
    +
  • 테크니컬코리아의 모든 사업장 및 운영 활동
  • +
  • 국내외 모든 자회사 및 관계회사
  • +
  • 협력업체 및 계약업체와의 HSE 관련 활동
  • +
  • 제품 및 서비스의 전체 생명주기
  • +
  • 다음 분야의 법적 요구사항: +
      +
    • 산업안전보건 관련 법규
    • +
    • 환경보호 관련 법규
    • +
    • 화학물질 관리 관련 법규
    • +
    • 건설안전 관련 법규
    • +
    • 소방안전 관련 법규
    • +
    • 기타 HSE 관련 규제 및 표준
    • +
    +
  • +
+ + +
+

3. 관련 문서

+
+
+

3.1 내부 문서

+
    +
  • TK-HSE-001 - HSE 관리시스템 매뉴얼
  • +
  • TK-HSE-P-610 - 기획 및 위험 관리 절차
  • +
  • TK-HSE-P-620 - 위험 평가 절차
  • +
  • TK-HSE-P-810 - 운영 기획 및 관리 절차
  • +
  • TK-HSE-P-1010 - 사건, 부적합 및 시정조치 절차
  • +
+ +

3.2 외부 참조 표준

+
    +
  • ISO 45001:2018 - 보건안전경영시스템 요구사항
  • +
  • ISO 14001:2015 - 환경경영시스템 요구사항
  • +
  • ISO 9001:2015 - 품질경영시스템 요구사항
  • +
+ +

3.3 주요 법적 요구사항

+
    +
  • 산업안전보건법 및 시행령, 시행규칙
  • +
  • 환경정책기본법 및 관련 법령
  • +
  • 대기환경보전법
  • +
  • 수질 및 수생태계 보전에 관한 법률
  • +
  • 폐기물관리법
  • +
  • 화학물질관리법
  • +
  • 소방기본법
  • +
  • 건설기술 진흥법
  • +
+
+ + +
+

4. 용어의 정의

+
+
+

4.1 법적 요구사항(Legal Requirements)

+

국가 또는 지역의 법률, 규정, 조례, 허가, 라이선스 및 기타 형태의 정부 인가에 따라 조직이 준수해야 하는 요구사항입니다.

+ +

4.2 기타 요구사항(Other Requirements)

+

조직이 준수하기로 선택하거나 채택한 기타 요구사항으로, 업계 표준, 고객 요구사항, 자발적 약속 등을 포함합니다.

+ +

4.3 준수 평가(Compliance Evaluation)

+

조직이 법적 요구사항 및 기타 요구사항에 얼마나 잘 부합하는지를 판단하는 과정입니다.

+ +

4.4 규제 감시(Regulatory Monitoring)

+

조직의 활동에 적용되는 법적 요구사항의 변경사항을 지속적으로 추적하고 식별하는 과정입니다.

+ +

4.5 법적 등록부(Legal Register)

+

조직에 적용되는 모든 법적 요구사항과 기타 요구사항을 체계적으로 문서화한 데이터베이스 또는 목록입니다.

+
+ + +
+

5. 역할과 책임

+
+
+

5.1 최고경영자

+
    +
  • 법적 요구사항 관리에 대한 최종 책임
  • +
  • 법적 요구사항 준수를 위한 자원 할당
  • +
  • 중대한 법적 이슈에 대한 의사결정
  • +
  • 법적 위반 사항에 대한 최종 승인 및 조치
  • +
+ +

5.2 HSE 관리책임자

+
    +
  • 법적 요구사항 관리 체계의 수립 및 운영
  • +
  • 법적 등록부의 구축 및 유지관리
  • +
  • 준수 평가 프로그램의 기획 및 실행
  • +
  • 법적 요구사항 변경에 대한 영향 평가
  • +
  • 관련 부서에 대한 교육 및 지원
  • +
+ +

5.3 법무팀

+
    +
  • 법적 요구사항의 해석 및 자문
  • +
  • 규제 변경사항의 법적 영향 분석
  • +
  • 허가 및 인가 절차 지원
  • +
  • 법적 분쟁 및 위반 사항 대응
  • +
+ +

5.4 부서장/현장 관리자

+
    +
  • 담당 영역의 법적 요구사항 식별 지원
  • +
  • 해당 법적 요구사항의 현장 적용 및 준수
  • +
  • 법적 요구사항 위반 가능성 보고
  • +
  • 개선 조치의 실행 및 모니터링
  • +
+ +

5.5 모든 근로자

+
    +
  • 적용 가능한 법적 요구사항의 숙지 및 준수
  • +
  • 법적 요구사항 위반 상황의 즉시 보고
  • +
  • 관련 교육 및 훈련 참여
  • +
+
+ + +
+

6. 법적 요구사항 관리 프로세스

+
+ +
+
식별
+ +
접근 및 확보
+ +
분석 및 평가
+

+
등록부 업데이트
+ +
의무사항 전파
+ +
준수 모니터링
+
+ +
+

6.1 법적 요구사항 식별

+

6.1.1 식별 방법

+
    +
  • 체계적 검토: 정기적인 법규 데이터베이스 검색
  • +
  • 전문 서비스 활용: 법률 자문 및 규제 모니터링 서비스
  • +
  • 업계 정보: 협회, 세미나, 컨퍼런스를 통한 정보 수집
  • +
  • 정부 기관: 관련 부처 및 지방자치단체 공지사항
  • +
  • 내부 제보: 직원, 고객, 협력업체로부터의 정보
  • +
+ +

6.1.2 식별 대상

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

6.2 법적 요구사항 접근 및 확보

+

6.2.1 정보 소스

+
    +
  • 공식 채널 +
      +
    • 국가법령정보센터 (www.law.go.kr)
    • +
    • 행정안전부 자치법규정보시스템
    • +
    • 관련 부처 공식 웹사이트
    • +
    +
  • +
  • 전문 서비스 +
      +
    • 법률 자문 서비스
    • +
    • 규제 모니터링 전문업체
    • +
    • 업계 전문 컨설팅
    • +
    +
  • +
  • 업계 네트워크 +
      +
    • 산업별 협회 및 단체
    • +
    • 전문 세미나 및 워크숍
    • +
    • 동종업계 정보 교류
    • +
    +
  • +
+ +

6.2.2 문서 관리

+
    +
  • 모든 법규 문서의 전자 파일 보관
  • +
  • 최신 버전 유지 및 이력 관리
  • +
  • 접근 권한 설정 및 보안 관리
  • +
  • 백업 및 복구 체계 구축
  • +
+
+ +
+

6.3 법적 요구사항 분석 및 평가

+

6.3.1 적용성 평가

+

다음 기준에 따라 각 법적 요구사항의 조직 적용성을 평가합니다:

+
    +
  • 지리적 범위: 사업장 위치에 따른 적용 법규
  • +
  • 업종별 적용: 사업 분야에 따른 특화 법규
  • +
  • 규모별 적용: 기업 규모, 시설 규모에 따른 차등 적용
  • +
  • 활동별 적용: 특정 활동 또는 공정에 대한 법규
  • +
+ +

6.3.2 영향 분석

+ + + + + + + + + + + + + + + + + + + + + + + +

6.3.3 갭 분석

+

현재 조직 상태와 법적 요구사항 간의 차이를 분석:

+
    +
  • 현재 준수 수준 평가
  • +
  • 필요한 개선사항 식별
  • +
  • 추가 자원 소요 분석
  • +
  • 이행 일정 수립
  • +
+
+ + +
+

7. 법적 등록부 관리

+
+
+

7.1 등록부 구조

+

법적 등록부는 다음 정보를 포함해야 합니다:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

7.2 등록부 유지관리

+
    +
  • 정기 업데이트: 월 1회 이상 내용 검토 및 업데이트
  • +
  • 버전 관리: 변경 이력 및 승인 기록 유지
  • +
  • 접근 관리: 부서별 차등 접근 권한 설정
  • +
  • 백업 관리: 정기적 백업 및 복구 테스트
  • +
+ +

7.3 등록부 품질 관리

+
    +
  • 데이터 정확성 검증
  • +
  • 중복 항목 제거
  • +
  • 폐지된 법규 아카이빙
  • +
  • 관련 문서 링크 유지
  • +
+
+ + +
+

8. 준수 평가

+
+
+

8.1 평가 계획

+

8.1.1 평가 주기

+ + + + + + + + + + + + + + + + + + + + + + + +

8.1.2 평가 방법

+
    +
  • 현장 점검: 직접 현장 방문을 통한 준수 상태 확인
  • +
  • 문서 검토: 관련 기록 및 보고서 분석
  • +
  • 인터뷰: 담당자 및 작업자 면담
  • +
  • 테스트: 필요시 측정 및 시험 실시
  • +
+ +

8.2 평가 실행

+

8.2.1 평가팀 구성

+
    +
  • 팀장: HSE 관리책임자 또는 지정된 담당자
  • +
  • 팀원: 관련 부서 전문가, 외부 전문가
  • +
  • 관찰자: 해당 부서 담당자
  • +
+ +

8.2.2 평가 절차

+
    +
  1. 평가 계획 수립 및 통보
  2. +
  3. 관련 자료 사전 검토
  4. +
  5. 현장 평가 실시
  6. +
  7. 발견사항 정리 및 확인
  8. +
  9. 평가 보고서 작성
  10. +
  11. 개선계획 수립
  12. +
+ +

8.3 준수 상태 분류

+ + + + + + + + + + + + + + + + + + + + + + +
+ + +
+

9. 의사소통 및 교육

+
+
+

9.1 내부 의사소통

+

9.1.1 의사소통 채널

+
    +
  • 정기 회의: HSE 위원회, 부서별 회의
  • +
  • 교육 및 훈련: 신입사원, 보수교육
  • +
  • 공지사항: 인트라넷, 게시판, 이메일
  • +
  • 보고서: 월간/분기별 HSE 보고서
  • +
+ +

9.1.2 의사소통 내용

+
    +
  • 새로운 법적 요구사항 및 변경사항
  • +
  • 준수 평가 결과 및 개선계획
  • +
  • 위반 사례 및 교훈사항
  • +
  • 모범 사례 및 성공 스토리
  • +
+ +

9.2 교육 및 훈련

+

9.2.1 교육 프로그램

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

9.2.2 교육 효과성 평가

+
    +
  • 교육 이해도 테스트
  • +
  • 현장 적용 상황 점검
  • +
  • 참가자 만족도 조사
  • +
  • 행동 변화 모니터링
  • +
+
+ + +
+

10. 모니터링 및 검토

+
+
+

10.1 규제 변화 모니터링

+

10.1.1 모니터링 시스템

+
    +
  • 자동 알림 서비스: 법규 변경 알림 시스템 구축
  • +
  • 정기 검색: 주간 단위 법규 데이터베이스 검색
  • +
  • 전문가 네트워크: 법률 자문사, 컨설턴트 활용
  • +
  • 업계 정보: 협회, 세미나 참여를 통한 정보 수집
  • +
+ +

10.1.2 변경사항 대응

+
    +
  1. 변경사항 식별 및 분석
  2. +
  3. 조직 영향도 평가
  4. +
  5. 대응 계획 수립
  6. +
  7. 관련 부서 통보
  8. +
  9. 필요시 절차 및 시스템 업데이트
  10. +
  11. 교육 및 훈련 실시
  12. +
+ +

10.2 성과 모니터링

+

10.2.1 핵심 성과 지표 (KPI)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

10.2.2 보고 체계

+
    +
  • 월간 보고: 부서별 준수 현황
  • +
  • 분기 보고: 전사 종합 현황
  • +
  • 연간 보고: 성과 평가 및 개선계획
  • +
  • 특별 보고: 중대 위반 또는 변경사항
  • +
+ +

10.3 시스템 검토

+

10.3.1 정기 검토

+
    +
  • 분기 검토: 절차 적정성 및 효과성
  • +
  • 연간 검토: 전체 시스템 종합 평가
  • +
  • 특별 검토: 중대 변경 또는 사고 발생시
  • +
+ +

10.3.2 개선 활동

+
    +
  • 검토 결과에 따른 개선계획 수립
  • +
  • 절차 및 시스템 업데이트
  • +
  • 교육 프로그램 개선
  • +
  • 모니터링 시스템 강화
  • +
+
+ + +
+
+

11. 양식 및 서식

+
+ +
+

11.1 법적 요구사항 등록 양식

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

11.2 준수 평가 체크리스트

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

11.3 법규 변경 통보서

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+

12. 문서 관리

+
+
+ 문서 통제
+ 이 문서는 통제 문서입니다. 승인 없이 복사하거나 배포하지 마십시오.
+ 최신 버전은 회사 인트라넷에서 확인할 수 있습니다.
+ 문의사항은 HSE 관리부서로 연락하십시오. +
+
+ + +
+ +
+

TK-HSE-P-630

+

HSE Legal Requirements Management Procedure

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleHSE Legal Requirements Management Procedure
Document NumberTK-HSE-P-630
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+

1. PURPOSE

+
+

This procedure aims to provide a framework for systematically identifying, accessing, evaluating, and managing health, safety, and environmental (HSE) legal requirements related to Technicalkorea's business activities.

+

Through this, we ensure compliance with legal requirements, minimize risks from regulatory violations, and achieve improved HSE performance through continuous improvement.

+ +
+ Important: Identification and compliance with legal requirements is a core element of the organization's HSE management system and a mandatory requirement of ISO 45001:2018 and ISO 14001:2015. +
+ + +
+

2. SCOPE

+
+

This procedure applies to:

+
    +
  • All workplaces and operational activities of Technicalkorea
  • +
  • All domestic and international subsidiaries and affiliates
  • +
  • HSE-related activities with contractors and subcontractors
  • +
  • Entire life cycle of products and services
  • +
  • Legal requirements in the following areas: +
      +
    • Occupational health and safety regulations
    • +
    • Environmental protection regulations
    • +
    • Chemical substance management regulations
    • +
    • Construction safety regulations
    • +
    • Fire safety regulations
    • +
    • Other HSE-related regulations and standards
    • +
    +
  • +
+ + + + +
+

3. RELATED DOCUMENTS

+
+
+

3.1 Internal Documents

+
    +
  • TK-HSE-001 - HSE Management System Manual
  • +
  • TK-HSE-P-610 - Planning and Risk Management Procedure
  • +
  • TK-HSE-P-620 - Risk Assessment Procedure
  • +
  • TK-HSE-P-810 - Operational Planning and Control Procedure
  • +
  • TK-HSE-P-1010 - Incident, Nonconformity and Corrective Action Procedure
  • +
+ +

3.2 External Reference Standards

+
    +
  • ISO 45001:2018 - Occupational Health and Safety Management Systems Requirements
  • +
  • ISO 14001:2015 - Environmental Management Systems Requirements
  • +
  • ISO 9001:2015 - Quality Management Systems Requirements
  • +
+ +

3.3 Key Legal Requirements

+
    +
  • Occupational Safety and Health Act and enforcement decrees and rules
  • +
  • Framework Act on Environmental Policy and related laws
  • +
  • Clean Air Conservation Act
  • +
  • Water Quality and Aquatic Ecosystem Conservation Act
  • +
  • Waste Management Act
  • +
  • Chemical Substances Control Act
  • +
  • Framework Act on Fire Services
  • +
  • Construction Technology Promotion Act
  • +
+
+ + +
+

4. TERMS AND DEFINITIONS

+
+
+

4.1 Legal Requirements

+

Requirements that an organization must comply with according to national or regional laws, regulations, ordinances, permits, licenses, and other forms of governmental authorization.

+ +

4.2 Other Requirements

+

Other requirements that the organization chooses to comply with or adopt, including industry standards, customer requirements, voluntary commitments, etc.

+ +

4.3 Compliance Evaluation

+

The process of determining how well an organization conforms to legal requirements and other requirements.

+ +

4.4 Regulatory Monitoring

+

The process of continuously tracking and identifying changes in legal requirements applicable to the organization's activities.

+ +

4.5 Legal Register

+

A database or list that systematically documents all legal requirements and other requirements applicable to the organization.

+
+ + +
+

5. ROLES AND RESPONSIBILITIES

+
+
+

5.1 Top Management

+
    +
  • Ultimate responsibility for legal requirements management
  • +
  • Resource allocation for legal requirements compliance
  • +
  • Decision-making on significant legal issues
  • +
  • Final approval and action on legal violations
  • +
+ +

5.2 HSE Manager

+
    +
  • Establishment and operation of legal requirements management system
  • +
  • Construction and maintenance of legal register
  • +
  • Planning and execution of compliance evaluation programs
  • +
  • Impact assessment of legal requirements changes
  • +
  • Training and support for related departments
  • +
+ +

5.3 Legal Team

+
    +
  • Interpretation and consultation on legal requirements
  • +
  • Legal impact analysis of regulatory changes
  • +
  • Support for permit and authorization procedures
  • +
  • Response to legal disputes and violations
  • +
+ +

5.4 Department Heads/Site Managers

+
    +
  • Support identification of legal requirements in their areas
  • +
  • Site application and compliance with applicable legal requirements
  • +
  • Report potential legal requirement violations
  • +
  • Implementation and monitoring of improvement measures
  • +
+ +

5.5 All Workers

+
    +
  • Understanding and compliance with applicable legal requirements
  • +
  • Immediate reporting of legal requirement violation situations
  • +
  • Participation in related education and training
  • +
+
+ + +
+

6. LEGAL REQUIREMENTS MANAGEMENT PROCESS

+
+ +
+
Identification
+ +
Access & Acquisition
+ +
Analysis & Evaluation
+

+
Register Update
+ +
Dissemination
+ +
Compliance Monitoring
+
+ +
+

6.1 Legal Requirements Identification

+

6.1.1 Identification Methods

+
    +
  • Systematic Review: Regular legal database searches
  • +
  • Professional Services: Legal consultation and regulatory monitoring services
  • +
  • Industry Information: Information gathering through associations, seminars, conferences
  • +
  • Government Agencies: Notices from relevant ministries and local governments
  • +
  • Internal Reports: Information from employees, customers, contractors
  • +
+ +

6.1.2 Identification Targets

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

6.2 Legal Requirements Access and Acquisition

+

6.2.1 Information Sources

+
    +
  • Official Channels +
      +
    • Korea Law Information Center (www.law.go.kr)
    • +
    • Local Regulations Information System
    • +
    • Official websites of relevant ministries
    • +
    +
  • +
  • Professional Services +
      +
    • Legal consultation services
    • +
    • Regulatory monitoring specialists
    • +
    • Industry-specific consulting
    • +
    +
  • +
  • Industry Networks +
      +
    • Industry associations and organizations
    • +
    • Professional seminars and workshops
    • +
    • Peer industry information exchange
    • +
    +
  • +
+ +

6.2.2 Document Management

+
    +
  • Electronic file storage of all regulatory documents
  • +
  • Latest version maintenance and history management
  • +
  • Access permission settings and security management
  • +
  • Backup and recovery system establishment
  • +
+
+ +
+

6.3 Legal Requirements Analysis and Evaluation

+

6.3.1 Applicability Assessment

+

Evaluate the organizational applicability of each legal requirement according to the following criteria:

+
    +
  • Geographic Scope: Applicable regulations by workplace location
  • +
  • Industry-specific Application: Specialized regulations by business sector
  • +
  • Scale-based Application: Differential application by company size, facility scale
  • +
  • Activity-specific Application: Regulations for specific activities or processes
  • +
+ +

6.3.2 Impact Analysis

+ + + + + + + + + + + + + + + + + + + + + + + +

6.3.3 Gap Analysis

+

Analyze differences between current organizational status and legal requirements:

+
    +
  • Current compliance level assessment
  • +
  • Identification of necessary improvements
  • +
  • Additional resource requirement analysis
  • +
  • Implementation schedule establishment
  • +
+
+ + +
+

7. LEGAL REGISTER MANAGEMENT

+
+
+

7.1 Register Structure

+

The legal register must include the following information:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

7.2 Register Maintenance

+
    +
  • Regular Updates: Content review and update at least monthly
  • +
  • Version Control: Maintain change history and approval records
  • +
  • Access Management: Set differential access permissions by department
  • +
  • Backup Management: Regular backup and recovery testing
  • +
+ +

7.3 Register Quality Management

+
    +
  • Data accuracy verification
  • +
  • Duplicate item removal
  • +
  • Archiving of repealed regulations
  • +
  • Maintenance of related document links
  • +
+
+ + +
+

8. COMPLIANCE EVALUATION

+
+
+

8.1 Evaluation Planning

+

8.1.1 Evaluation Frequency

+ + + + + + + + + + + + + + + + + + + + + + + +

8.1.2 Evaluation Methods

+
    +
  • Site Inspection: Direct site visits to verify compliance status
  • +
  • Document Review: Analysis of related records and reports
  • +
  • Interviews: Interviews with responsible persons and workers
  • +
  • Testing: Measurement and testing when necessary
  • +
+ +

8.2 Evaluation Implementation

+

8.2.1 Evaluation Team Composition

+
    +
  • Team Leader: HSE Manager or designated person
  • +
  • Team Members: Related department experts, external experts
  • +
  • Observers: Department representatives
  • +
+ +

8.2.2 Evaluation Procedure

+
    +
  1. Evaluation plan establishment and notification
  2. +
  3. Preliminary review of related materials
  4. +
  5. Site evaluation implementation
  6. +
  7. Findings compilation and confirmation
  8. +
  9. Evaluation report preparation
  10. +
  11. Improvement plan establishment
  12. +
+ +

8.3 Compliance Status Classification

+ + + + + + + + + + + + + + + + + + + + + + +
+ + +
+

9. COMMUNICATION AND TRAINING

+
+
+

9.1 Internal Communication

+

9.1.1 Communication Channels

+
    +
  • Regular Meetings: HSE committee, departmental meetings
  • +
  • Education and Training: New employee, refresher training
  • +
  • Announcements: Intranet, bulletin boards, email
  • +
  • Reports: Monthly/quarterly HSE reports
  • +
+ +

9.1.2 Communication Content

+
    +
  • New legal requirements and changes
  • +
  • Compliance evaluation results and improvement plans
  • +
  • Violation cases and lessons learned
  • +
  • Best practices and success stories
  • +
+ +

9.2 Education and Training

+

9.2.1 Training Programs

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

9.2.2 Training Effectiveness Evaluation

+
    +
  • Training comprehension tests
  • +
  • Field application situation checks
  • +
  • Participant satisfaction surveys
  • +
  • Behavioral change monitoring
  • +
+
+ + +
+

10. MONITORING AND REVIEW

+
+
+

10.1 Regulatory Change Monitoring

+

10.1.1 Monitoring System

+
    +
  • Automatic Alert Service: Regulatory change alert system establishment
  • +
  • Regular Search: Weekly regulatory database searches
  • +
  • Expert Network: Utilization of legal advisors, consultants
  • +
  • Industry Information: Information gathering through associations, seminars
  • +
+ +

10.1.2 Change Response

+
    +
  1. Change identification and analysis
  2. +
  3. Organizational impact assessment
  4. +
  5. Response plan establishment
  6. +
  7. Notification to related departments
  8. +
  9. Procedure and system updates when necessary
  10. +
  11. Education and training implementation
  12. +
+ +

10.2 Performance Monitoring

+

10.2.1 Key Performance Indicators (KPI)

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

10.2.2 Reporting Structure

+
    +
  • Monthly Report: Departmental compliance status
  • +
  • Quarterly Report: Company-wide comprehensive status
  • +
  • Annual Report: Performance evaluation and improvement plan
  • +
  • Special Report: Major violations or changes
  • +
+ +

10.3 System Review

+

10.3.1 Regular Review

+
    +
  • Quarterly Review: Procedure adequacy and effectiveness
  • +
  • Annual Review: Comprehensive evaluation of entire system
  • +
  • Special Review: Upon major changes or incident occurrence
  • +
+ +

10.3.2 Improvement Activities

+
    +
  • Improvement plan establishment based on review results
  • +
  • Procedure and system updates
  • +
  • Training program improvements
  • +
  • Monitoring system enhancement
  • +
+
+ + +
+
+

11. FORMS AND TEMPLATES

+
+ +
+

11.1 Legal Requirements Registration Form

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

11.2 Compliance Evaluation Checklist

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+

11.3 Regulatory Change Notification

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+

12. DOCUMENT CONTROL

+
+
+ Document Control
+ This is a controlled document. Do not copy or distribute without authorization.
+ The latest version can be found on the company intranet.
+ For inquiries, contact the HSE Management Department. +
+
+
+ + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/index.html b/deploy/tkfb-package/web-ui/docs/index.html new file mode 100644 index 0000000..7cec773 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/index.html @@ -0,0 +1,295 @@ + + + + + + 테크니컬코리아 문서 시스템 + + + +
+
+

테크니컬코리아 문서 시스템

+

회사 규정 및 절차서 열람 시스템

+
+ +
+
+ +
+

HSE 관리시스템

+

ISO 45001:2018 기반 안전보건환경 관련 절차서

+ 바로가기 +
+ + +
+

품질 관리시스템

+

ISO 9001 기반 품질관리 절차 및 매뉴얼

+ 바로가기 +
+ + +
+

인사 규정

+

인사관리 규정 및 지침서

+ 바로가기 +
+ + +
+

기술 문서

+

설계 표준, 용접절차, BOM 시스템 가이드라인

+ 바로가기 +
+ + +
+

경영 방침

+

회사 방침, 윤리강령 및 정책 문서

+ 바로가기 +
+ + +
+

문서 검색

+ +
+
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

http://192.168.0.3:10080/docs

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/iso45001_bilingual_manual.html b/deploy/tkfb-package/web-ui/docs/iso45001_bilingual_manual.html new file mode 100644 index 0000000..d187ab0 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/iso45001_bilingual_manual.html @@ -0,0 +1,1469 @@ + + + + + + ISO 45001:2018 HSE 관리시스템 매뉴얼 + + + +
+ +
+ + +
+ + +
+ +
+

ISO 45001:2018

+

보건, 안전 및 환경 관리시스템 매뉴얼

+
테크니컬코리아
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
문서 제목HSE 관리시스템 매뉴얼
문서 번호TK-HSE-001
제정 일자2025.01.03
개정 일자
개정 번호01
페이지1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
구분작성검토승인
날짜
성명
서명
+
+ + +
+

목차 및 개정 이력

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
번호제목개정 번호개정 일자
1목차 및 개정 이력
21. 적용 범위
32. 인용 표준
43. 용어와 정의
54. 조직의 상황
65. 리더십과 근로자 참여
76. 기획
87. 지원
98. 운영
109. 성과 평가
1110. 개선
+ +

문서 개정 이력

+ + + + + + + + + + + + + + + + + + + + + + + + + +
개정일자수정 문서개정 내용 및 사유
02025.01.03ISO 45001:2018 HSE 관리시스템 구현 - 초기 생성
1
2
+
+ + +
+
+

1. 적용 범위

+
+ +

본 보건, 안전 및 환경 관리시스템 매뉴얼은 테크니컬코리아(이하 "회사"라 함)의 HSE 관리시스템 문서 중 최상위 문서로서, 국제표준 ISO 45001:2018의 요구사항에 따라 작성, 운영 및 유지됩니다.

+ +

본 HSE 관리시스템 매뉴얼은 테크니컬코리아가 수행하는 사업 범위 내에서 조직 관리부터 기획, 영업, 계약, 자재 조달 및 제조, 공정 실행, 관련 제품 및 서비스 활동에 이르기까지 전체 사업 범위에 걸쳐 보건, 안전 및 환경 활동을 수행하는 임직원에게 적용되며, 모든 이해관계자로부터 지속적으로 신뢰를 확보하고 향상시키기 위해 작성, 운영 및 유지됩니다.

+
+ + +
+
+

2. 인용 표준

+
+ +

본 HSE 관리시스템 매뉴얼은 국제표준 "ISO 45001:2018"의 요구사항을 적용하여 작성되었습니다. 본 HSE 관리시스템 매뉴얼 및 관련 문서는 국제표준의 개정이나 업무 개선의 필요에 따라 수정되어야 합니다.

+
+ + +
+
+

3. 용어와 정의

+
+ +

본 매뉴얼에서 사용하는 모든 용어는 "ISO 45001:2018"의 정의를 따르며, 정의되지 않은 용어는 관련 법령 및 테크니컬코리아의 규정이나 규칙에서 정한 정의를 따릅니다. 다만, 하위 규정에서 필요한 용어의 정의는 별도로 정할 수 있습니다.

+ +
+
조직의 상황:
+
목표를 달성하기 위한 조직의 접근 방식을 개발하는 데 영향을 줄 수 있는 내부 및 외부 이슈의 조합
+ +
이해관계자:
+
결정이나 활동에 영향을 주거나, 영향을 받거나, 영향을 받는다고 인식하는 개인이나 조직
+ +
의사소통:
+
조직 구성원 간에 생각이나 감정을 교환하는 포괄적인 행위
+ +
위험:
+
불확실성의 영향
+ +
위험과 기회:
+
잠재적 부정적 영향(위협)과 잠재적 유익한 영향(기회)
+ +
문서화된 정보:
+
조직이 관리하고 유지해야 하는 정보와 이를 포함하는 매체
+ +
HSE 관리시스템:
+
HSE 정책을 달성하기 위해 사용되는 관리시스템 또는 관리시스템의 일부
+ +
준수 의무:
+
조직이 준수해야 하거나 준수하기로 선택한 법적 요구사항 및 기타 요구사항
+ +
근로자:
+
조직의 통제 하에서 일이나 일과 관련된 활동을 수행하는 사람
+ +
참여:
+
의사결정 과정에 관여하는 것
+ +
협의:
+
결정을 내리기 전에 견해를 구하는 것
+ +
작업장:
+
근로 목적으로 사람이 있어야 하거나 가야 하는 조직의 통제 하에 있는 장소
+ +
계약업체:
+
합의된 규격, 조건에 따라 조직에 서비스를 제공하는 외부 조직
+ +
부상과 건강악화:
+
사람의 신체적, 정신적 또는 인지적 상태에 대한 부정적 영향
+ +
유해요인:
+
부상과 건강악화를 일으킬 잠재성을 가진 근원
+ +
사건:
+
일로부터 발생하거나 일의 과정에서 발생하여 부상과 건강악화를 일으킬 수 있거나 일으키는 사건
+
+
+ + + + + +
+
+

4. 조직의 상황

+
+ +
+

4.1 조직과 조직의 상황 이해

+

조직은 조직의 목적과 관련이 있고 HSE 관리시스템의 의도된 결과를 달성하는 능력에 영향을 주는 외부 및 내부 이슈를 결정해야 합니다.

+ +

외부 이슈에는 다음이 포함됩니다:

+
    +
  • 문화적, 사회적, 정치적, 법적, 재정적, 기술적, 경제적 및 자연 환경
  • +
  • 새로운 경쟁업체, 계약업체, 공급업체, 파트너 및 제공업체
  • +
  • 제품 및 OH&S 영향에 대한 새로운 지식
  • +
  • 산업 또는 부문과 관련된 주요 동향 및 추진요인
  • +
  • 외부 이해관계자의 관계, 인식 및 가치
  • +
+ +

내부 이슈에는 다음이 포함됩니다:

+
    +
  • 거버넌스, 조직 구조, 역할 및 책임
  • +
  • 정책, 목표 및 이를 달성하기 위한 전략
  • +
  • 자원, 지식 및 역량 측면에서의 능력
  • +
  • 정보 시스템, 정보 흐름 및 의사결정 과정
  • +
  • 근로자와의 관계, 그들의 인식 및 가치
  • +
  • 조직 문화
  • +
+
+ +
+

4.2 근로자 및 기타 이해관계자의 필요와 기대 이해

+

조직은 다음을 결정해야 합니다:

+
    +
  • HSE 관리시스템과 관련된 근로자 및 기타 이해관계자
  • +
  • 이러한 근로자 및 기타 이해관계자의 필요와 기대
  • +
  • 이러한 필요와 기대 중 법적 요구사항 및 기타 요구사항인 것
  • +
+
+ +
+

4.3 HSE 관리시스템의 적용 범위 결정

+

조직은 적용 범위를 정하기 위해 HSE 관리시스템의 경계와 적용 가능성을 결정해야 합니다. 적용 범위는 조직의 HSE 성과에 영향을 줄 수 있는 조직의 통제 또는 영향 하에 있는 활동, 제품 및 서비스를 포함해야 합니다.

+
+ +
+

4.4 HSE 관리시스템

+

조직은 이 국제표준의 요구사항에 따라 필요한 프로세스와 그들의 상호작용을 포함하여 HSE 관리시스템을 수립, 실행, 유지 및 지속적으로 개선해야 합니다.

+
+
+ + +
+
+

5. 리더십과 근로자 참여

+
+ +
+

5.1 리더십과 의지

+

최고경영자는 다음을 통해 HSE 관리시스템에 대한 리더십과 의지를 실증해야 합니다:

+
    +
  • 업무 관련 부상과 건강악화 예방에 대한 전반적인 책임지기
  • +
  • HSE 정책과 목표가 수립되고 전략적 방향과 양립할 수 있도록 보장
  • +
  • HSE 관리시스템 요구사항의 사업 프로세스 통합 보장
  • +
  • 필요한 자원을 이용할 수 있도록 보장
  • +
  • 효과적인 HSE 관리의 중요성 의사소통
  • +
  • HSE 관리시스템이 의도된 결과를 달성하도록 보장
  • +
  • 지속적 개선 촉진
  • +
  • 사건, 유해요인, 위험 및 기회를 보고할 때 근로자를 보복으로부터 보호
  • +
+
+ +
+

5.2 HSE 정책

+

최고경영자는 다음과 같은 HSE 정책을 수립, 실행 및 유지해야 합니다:

+
    +
  • 안전하고 건강한 작업 조건을 제공하겠다는 의지 포함
  • +
  • HSE 목표 설정을 위한 프레임워크 제공
  • +
  • 법적 요구사항 및 기타 요구사항을 충족하겠다는 의지 포함
  • +
  • 유해요인을 제거하고 HSE 위험을 감소시키겠다는 의지 포함
  • +
  • 지속적 개선에 대한 의지 포함
  • +
  • 근로자의 협의와 참여에 대한 의지 포함
  • +
+
+ +
+

5.3 조직의 역할, 책임 및 권한

+

최고경영자는 관련 역할에 대한 책임과 권한이 조직 내에서 할당, 의사소통 및 이해되도록 보장해야 합니다. 모든 수준의 근로자는 자신이 통제하는 OH&S 관리시스템의 측면에 대해 책임을 져야 합니다.

+
+ +
+

5.4 근로자의 협의와 참여

+

조직은 OH&S 관리시스템의 개발, 기획, 실행, 성과 평가 및 개선을 위한 조치에서 근로자의 협의와 참여를 위한 프로세스를 수립해야 합니다.

+
+
+ + +
+
+

6. 기획

+
+ +
+

6.1 위험과 기회를 다루는 조치

+

6.1.1 일반

+

HSE 관리시스템을 기획할 때, 조직은 다음을 위해 다루어야 할 위험과 기회를 결정해야 합니다:

+
    +
  • HSE 관리시스템이 의도된 결과를 달성할 수 있다는 확신 제공
  • +
  • 바람직하지 않은 영향 예방 또는 감소
  • +
  • 지속적 개선 달성
  • +
+ +

6.1.2 유해요인 식별 및 위험과 기회의 평가

+

조직은 다음을 고려하여 지속적이고 사전 예방적인 유해요인 식별을 위한 프로세스를 수립해야 합니다:

+
    +
  • 업무가 조직되는 방법, 사회적 요인, 리더십 및 조직 문화
  • +
  • 일상적 및 비일상적 활동과 상황
  • +
  • 기반시설, 장비, 재료, 물질 및 물리적 조건
  • +
  • 과거의 관련 사건 및 잠재적 비상 상황
  • +
  • 작업장에 접근하는 사람들
  • +
+ +

6.1.3 법적 요구사항 및 기타 요구사항의 결정

+

조직은 유해요인, HSE 위험 및 HSE 관리시스템에 적용되는 최신 법적 요구사항 및 기타 요구사항을 결정하고 접근할 수 있는 프로세스를 수립해야 합니다.

+ +

6.1.4 조치 기획

+

조직은 위험과 기회, 법적 요구사항 및 비상 상황을 다루기 위한 조치를 기획해야 합니다.

+
+ +
+

6.2 HSE 목표 및 이를 달성하기 위한 기획

+

조직은 관련 기능과 수준에서 HSE 목표를 수립해야 합니다. HSE 목표는 다음과 같아야 합니다:

+
    +
  • HSE 정책과 일치
  • +
  • 측정 가능하거나 성과 평가가 가능
  • +
  • 적용 가능한 요구사항 고려
  • +
  • 모니터링되고 의사소통됨
  • +
  • 적절하게 갱신됨
  • +
+
+
+ + +
+
+

7. 지원

+
+ +
+

7.1 자원

+

조직은 HSE 관리시스템의 수립, 실행, 유지 및 지속적 개선에 필요한 자원을 결정하고 제공해야 합니다.

+
+ +
+

7.2 역량

+

조직은 다음을 해야 합니다:

+
    +
  • HSE 성과에 영향을 주는 근로자의 필요한 역량 결정
  • +
  • 적절한 교육, 훈련 또는 경험에 기반하여 근로자가 역량을 갖추도록 보장
  • +
  • 필요한 역량을 획득하고 유지하기 위한 조치 취하기
  • +
  • 역량의 증거로서 문서화된 정보 보존
  • +
+
+ +
+

7.3 인식

+

근로자는 다음에 대해 인식하도록 해야 합니다:

+
    +
  • HSE 정책과 HSE 목표
  • +
  • HSE 관리시스템의 효과성에 대한 자신의 기여
  • +
  • HSE 관리시스템 요구사항에 부합하지 않는 것의 의미
  • +
  • 자신과 관련된 사건 및 조사 결과
  • +
  • 자신과 관련된 유해요인, HSE 위험 및 결정된 조치
  • +
+
+ +
+

7.4 의사소통

+

조직은 HSE 관리시스템과 관련된 내부 및 외부 의사소통을 위한 프로세스를 수립하여 무엇을, 언제, 누구와, 어떻게 의사소통할지를 결정해야 합니다.

+
+ +
+

7.5 문서화된 정보

+

조직의 HSE 관리시스템은 이 표준에서 요구하는 문서화된 정보와 HSE 관리시스템의 효과성에 필요하다고 조직이 결정한 문서화된 정보를 포함해야 합니다.

+
+
+ + +
+
+

8. 운영

+
+ +
+

8.1 운영 기획 및 관리

+

조직은 프로세스에 대한 기준을 수립하고 기준에 따라 관리를 실행함으로써 HSE 관리시스템 요구사항을 충족하는 데 필요한 프로세스를 기획, 실행, 관리 및 유지해야 합니다.

+ +

8.1.2 유해요인 제거 및 HSE 위험 감소

+

조직은 다음 관리 체계를 사용하여 유해요인 제거 및 HSE 위험 감소를 위한 프로세스를 수립해야 합니다:

+
    +
  • 유해요인 제거
  • +
  • 덜 위험한 프로세스, 운영, 재료 또는 장비로 대체
  • +
  • 공학적 관리 및 업무 재조직 사용
  • +
  • 훈련을 포함한 관리적 관리 사용
  • +
  • 적절한 개인보호장비 사용
  • +
+ +

8.1.3 변경 관리

+

조직은 OH&S 성과에 영향을 주는 계획된 임시 및 영구 변경의 실행 및 관리를 위한 프로세스를 수립해야 합니다.

+ +

8.1.4 조달

+

조직은 제품 및 서비스의 조달을 관리하고 계약업체와 협력하여 유해요인을 식별하고 HSE 위험을 평가 및 관리하는 프로세스를 수립해야 합니다.

+
+ +
+

8.2 비상 대비 및 대응

+

조직은 다음을 통해 잠재적 비상 상황을 대비하고 대응하는 프로세스를 수립해야 합니다:

+
    +
  • 비상 상황에 대한 계획된 대응 수립
  • +
  • 계획된 대응을 위한 훈련 제공
  • +
  • 계획된 대응 능력을 주기적으로 시험 및 연습
  • +
  • 성과를 평가하고 필요시 계획된 대응 수정
  • +
  • 모든 관련 당사자에게 의무와 책임 의사소통
  • +
+
+
+ + +
+
+

9. 성과 평가

+
+ +
+

9.1 모니터링, 측정, 분석 및 성과 평가

+

조직은 모니터링과 측정이 필요한 것, 모니터링 방법, 평가 기준, 모니터링과 측정을 수행해야 하는 시기를 결정하기 위해 모니터링, 측정, 분석 및 성과 평가를 위한 프로세스를 수립해야 합니다.

+ +

9.1.2 준수 평가

+

조직은 법적 요구사항 및 기타 요구사항에 대한 준수를 평가하는 프로세스를 수립해야 합니다.

+
+ +
+

9.2 내부 심사

+

조직은 HSE 관리시스템이 조직의 요구사항과 이 국제표준에 적합한지, 효과적으로 실행되고 유지되는지에 대한 정보를 제공하기 위해 계획된 주기로 내부 심사를 실시해야 합니다.

+
+ +
+

9.3 경영 검토

+

최고경영자는 조직의 HSE 관리시스템이 지속적으로 적절하고, 충분하며, 효과적임을 보장하기 위해 계획된 주기로 검토해야 합니다. 경영 검토는 다음을 고려해야 합니다:

+
    +
  • 이전 경영 검토의 조치 상태
  • +
  • 외부 및 내부 이슈의 변화
  • +
  • HSE 성과에 대한 정보
  • +
  • 자원의 적절성
  • +
  • 지속적 개선 기회
  • +
+
+
+ + +
+
+

10. 개선

+
+ +
+

10.1 일반

+

조직은 HSE 관리시스템의 의도된 결과를 달성하기 위해 개선 기회를 결정하고 필요한 조치를 실행해야 합니다.

+
+ +
+

10.2 사건, 부적합 및 시정조치

+

사건이나 부적합이 발생할 때, 조직은 다음을 해야 합니다:

+
    +
  • 사건이나 부적합에 시기적절하게 대응
  • +
  • 근본 원인을 제거하기 위한 시정조치의 필요성 평가
  • +
  • 시정조치를 포함하여 필요한 모든 조치 실행
  • +
  • 취한 조치의 효과성 검토
  • +
  • 필요시 HSE 관리시스템 변경
  • +
+
+ +
+

10.3 지속적 개선

+

조직은 다음을 위해 HSE 관리시스템의 적절성, 충분성 및 효과성을 지속적으로 개선해야 합니다:

+
    +
  • HSE 성과 향상
  • +
  • HSE 관리시스템을 지원하는 문화 촉진
  • +
  • 지속적 개선을 위한 조치 실행에서 근로자 참여 촉진
  • +
  • 지속적 개선의 관련 결과를 근로자에게 의사소통
  • +
+
+
+ + +
+
+

관련 문서

+
+ +
    +
  1. TK-HSE-P-410 - 조직 상황 이해 및 HSE 관리시스템 운영 절차
  2. +
  3. TK-HSE-P-510 - 리더십 및 정책 수립 절차
  4. +
  5. TK-HSE-P-520 - 조직 편성 및 직무 배정 절차
  6. +
  7. TK-HSE-P-610 - 기획 및 위험 관리 절차
  8. +
  9. TK-HSE-P-620 - 위험 평가 절차
  10. +
  11. TK-HSE-P-630 - HSE 법적 요구사항 관리 절차
  12. +
  13. TK-HSE-P-640 - HSE 목표 관리 절차
  14. +
  15. TK-HSE-P-710 - 자원 관리 절차
  16. +
  17. TK-HSE-P-720 - 교육 및 훈련 관리 절차
  18. +
  19. TK-HSE-P-730 - 인식 및 의사소통 절차
  20. +
  21. TK-HSE-P-740 - 문서화된 정보 관리 절차
  22. +
  23. TK-HSE-P-810 - 운영 기획 및 관리 절차
  24. +
  25. TK-HSE-P-820 - 비상 대비 및 대응 절차
  26. +
  27. TK-HSE-P-910 - 프로세스 성과 관리 절차
  28. +
  29. TK-HSE-P-920 - HSE 모니터링 및 측정 관리 절차
  30. +
  31. TK-HSE-P-930 - 내부 심사 절차
  32. +
  33. TK-HSE-P-940 - 경영 검토 절차
  34. +
  35. TK-HSE-P-1010 - 사건, 부적합 및 시정조치 절차
  36. +
  37. TK-HSE-P-1020 - 지속적 개선 절차
  38. +
+
+ + +
+
+

문서 관리

+
+ +

이것은 통제 문서입니다

+

승인 없이 복사하지 마십시오

+

최신 버전은 회사 인트라넷에서 확인할 수 있습니다

+

이 문서에 대한 문의사항은 HSE 관리부서로 연락하십시오

+
+ +
+ + +
+ +
+

ISO 45001:2018

+

Health, Safety and Environment Management System Manual

+
Technicalkorea
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
Document TitleHSE Management System Manual
Document NumberTK-HSE-001
Established Date2025.01.03
Revision Date
Revision Number01
Page1 of 1
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
CategoryPreparedReviewedApproved
Date
Name
Signature
+
+ + +
+

TABLE OF CONTENTS AND REVISION HISTORY

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
No.TitleRevision No.Revision Date
1Table of Contents and Revision History
21. Scope
32. Normative References
43. Terms and Definitions
54. Context of the Organization
65. Leadership and Worker Participation
76. Planning
87. Support
98. Operation
109. Performance Evaluation
1110. Improvement
+ +

Document Revision History

+ + + + + + + + + + + + + + + + + + + + + + + + + +
RevisionDateModified DocumentContent and Reason for Revision
02025.01.03ISO 45001:2018 HSE Management System Implementation - Initial Creation
1
2
+
+ + +
+
+

1. SCOPE

+
+ +

This Health, Safety and Environment Management System Manual is the highest-level document among the HSE management system documents of Technicalkorea (hereinafter referred to as "the Company"). It is prepared, operated, and maintained in accordance with the requirements of the international standard ISO 45001:2018.

+ +

This HSE Management System Manual applies to employees who perform health, safety and environment activities throughout the entire business scope, from organizational management to planning, sales, contracting, procurement and manufacturing of materials, process execution, and related product and service activities within the business scope that Technicalkorea performs. It is prepared, operated, and maintained to continuously secure and improve trust from all stakeholders.

+
+ + +
+
+

2. NORMATIVE REFERENCES

+
+ +

This HSE Management System Manual is prepared by applying the requirements of the international standard "ISO 45001:2018". This HSE Management System Manual and related documents shall be revised when necessary for the revision of international standards or improvement of work.

+
+ + +
+
+

3. TERMS AND DEFINITIONS

+
+ +

All terms used in this manual follow the definitions in "ISO 45001:2018", and undefined terms shall follow the definitions prescribed in related laws and regulations and Technicalkorea's regulations or rules. However, definitions of necessary terms in subordinate regulations may be separately established.

+ +
+
Context of the organization:
+
Combination of internal and external issues that can influence the organization's approach to developing and achieving its objectives
+ +
Interested party:
+
Person or organization that can affect, be affected by, or perceive themselves to be affected by a decision or activity
+ +
Communication:
+
Comprehensive act of exchanging thoughts or feelings among organization members
+ +
Risk:
+
Effect of uncertainty
+ +
Risk and opportunities:
+
Potential adverse effects (threats) and potential beneficial effects (opportunities)
+ +
Documented information:
+
Information required to be controlled and maintained by the organization and the medium containing it
+ +
HSE management system:
+
Management system or part of a management system used to achieve the HSE policy
+ +
Compliance obligations:
+
Legal requirements and other requirements that an organization has to comply with or chooses to comply with
+ +
Worker:
+
Person performing work or work-related activities under the control of the organization
+ +
Participation:
+
Involvement in decision-making processes
+ +
Consultation:
+
Seeking views before making a decision
+ +
Workplace:
+
Place under the control of the organization where a person needs to be or to go for work purposes
+ +
Contractor:
+
External organization providing services to the organization according to agreed specifications, terms and conditions
+ +
Injury and ill health:
+
Adverse effect on the physical, mental or cognitive condition of a person
+ +
Hazard:
+
Source with a potential to cause injury and ill health
+ +
Incident:
+
Occurrence arising from or in the course of work that could or does result in injury and ill health
+
+
+ + +
+
+

4. CONTEXT OF THE ORGANIZATION

+
+ +
+

4.1 Understanding the organization and its context

+

The organization shall determine external and internal issues that are relevant to its purpose and that affect its ability to achieve the intended outcomes of its HSE management system.

+ +

External issues include:

+
    +
  • Cultural, social, political, legal, financial, technological, economic and natural environment
  • +
  • New competitors, contractors, suppliers, partners and providers
  • +
  • New knowledge about products and OH&S impacts
  • +
  • Key trends and drivers related to the industry or sector
  • +
  • Relationships, perceptions and values of external interested parties
  • +
+ +

Internal issues include:

+
    +
  • Governance, organizational structure, roles and accountabilities
  • +
  • Policies, objectives and strategies to achieve them
  • +
  • Capabilities in terms of resources, knowledge and competencies
  • +
  • Information systems, information flows and decision-making processes
  • +
  • Relationships with workers, their perceptions and values
  • +
  • Organizational culture
  • +
+
+ +
+

4.2 Understanding the needs and expectations of workers and other interested parties

+

The organization shall determine:

+
    +
  • Workers and other interested parties relevant to the HSE management system
  • +
  • The needs and expectations of these workers and other interested parties
  • +
  • Which of these needs and expectations are legal requirements and other requirements
  • +
+
+ +
+

4.3 Determining the scope of the HSE management system

+

The organization shall determine the boundaries and applicability of the HSE management system to establish its scope. The scope shall include activities, products and services within the organization's control or influence that can affect the organization's HSE performance.

+
+ +
+

4.4 HSE management system

+

The organization shall establish, implement, maintain and continually improve an HSE management system, including the processes needed and their interactions, in accordance with the requirements of this international standard.

+
+
+ + +
+
+

5. LEADERSHIP AND WORKER PARTICIPATION

+
+ +
+

5.1 Leadership and commitment

+

Top management shall demonstrate leadership and commitment with respect to the HSE management system by:

+
    +
  • Taking overall responsibility for the prevention of work-related injury and ill health
  • +
  • Ensuring that the HSE policy and objectives are established and compatible with strategic direction
  • +
  • Ensuring integration of HSE management system requirements into business processes
  • +
  • Ensuring that necessary resources are available
  • +
  • Communicating the importance of effective HSE management
  • +
  • Ensuring the HSE management system achieves its intended outcomes
  • +
  • Promoting continual improvement
  • +
  • Protecting workers from reprisals when reporting incidents, hazards, risks and opportunities
  • +
+
+ +
+

5.2 HSE policy

+

Top management shall establish, implement and maintain an HSE policy that:

+
    +
  • Includes a commitment to provide safe and healthy working conditions
  • +
  • Provides a framework for setting HSE objectives
  • +
  • Includes a commitment to fulfill legal requirements and other requirements
  • +
  • Includes a commitment to eliminate hazards and reduce HSE risks
  • +
  • Includes a commitment to continual improvement
  • +
  • Includes a commitment to consultation and participation of workers
  • +
+
+ +
+

5.3 Organizational roles, responsibilities and authorities

+

Top management shall ensure that responsibilities and authorities for relevant roles are assigned, communicated and understood within the organization. Workers at all levels shall take responsibility for those aspects of the OH&S management system over which they have control.

+
+ +
+

5.4 Consultation and participation of workers

+

The organization shall establish processes for consultation and participation of workers in the development, planning, implementation, performance evaluation and actions for improvement of the OH&S management system.

+
+
+ + +
+
+

6. PLANNING

+
+ +
+

6.1 Actions to address risks and opportunities

+

6.1.1 General

+

When planning for the HSE management system, the organization shall determine the risks and opportunities that need to be addressed to:

+
    +
  • Give assurance that the HSE management system can achieve its intended outcomes
  • +
  • Prevent, or reduce, undesired effects
  • +
  • Achieve continual improvement
  • +
+ +

6.1.2 Hazard identification and assessment of risks and opportunities

+

The organization shall establish processes for ongoing and proactive hazard identification considering:

+
    +
  • How work is organized, social factors, leadership, and organizational culture
  • +
  • Routine and non-routine activities and situations
  • +
  • Infrastructure, equipment, materials, substances and physical conditions
  • +
  • Past relevant incidents and potential emergency situations
  • +
  • People with access to the workplace
  • +
+ +

6.1.3 Determination of legal requirements and other requirements

+

The organization shall establish processes to determine and have access to up-to-date legal requirements and other requirements applicable to its hazards, HSE risks and HSE management system.

+ +

6.1.4 Planning action

+

The organization shall plan actions to address risks and opportunities, legal requirements, and emergency situations.

+
+ +
+

6.2 HSE objectives and planning to achieve them

+

The organization shall establish HSE objectives at relevant functions and levels. HSE objectives shall be:

+
    +
  • Consistent with the HSE policy
  • +
  • Measurable or capable of performance evaluation
  • +
  • Take into account applicable requirements
  • +
  • Be monitored and communicated
  • +
  • Be updated as appropriate
  • +
+
+
+ + +
+
+

7. SUPPORT

+
+ +
+

7.1 Resources

+

The organization shall determine and provide the resources needed for the establishment, implementation, maintenance and continual improvement of the HSE management system.

+
+ +
+

7.2 Competence

+

The organization shall:

+
    +
  • Determine necessary competence of workers that affects HSE performance
  • +
  • Ensure workers are competent based on appropriate education, training or experience
  • +
  • Take actions to acquire and maintain necessary competence
  • +
  • Retain documented information as evidence of competence
  • +
+
+ +
+

7.3 Awareness

+

Workers shall be made aware of:

+
    +
  • The HSE policy and HSE objectives
  • +
  • Their contribution to the effectiveness of the HSE management system
  • +
  • The implications of not conforming to HSE management system requirements
  • +
  • Incidents and investigation results relevant to them
  • +
  • Hazards, HSE risks and determined actions relevant to them
  • +
+
+ +
+

7.4 Communication

+

The organization shall establish processes for internal and external communications relevant to the HSE management system, determining what, when, with whom, and how to communicate.

+
+ +
+

7.5 Documented information

+

The organization's HSE management system shall include documented information required by this standard and determined by the organization as necessary for the effectiveness of the HSE management system.

+
+
+ + +
+
+

8. OPERATION

+
+ +
+

8.1 Operational planning and control

+

The organization shall plan, implement, control and maintain the processes needed to meet HSE management system requirements by establishing criteria for processes and implementing control in accordance with the criteria.

+ +

8.1.2 Eliminating hazards and reducing HSE risks

+

The organization shall establish processes for elimination of hazards and reduction of HSE risks using the following hierarchy of controls:

+
    +
  • Eliminate the hazard
  • +
  • Substitute with less hazardous processes, operations, materials or equipment
  • +
  • Use engineering controls and reorganization of work
  • +
  • Use administrative controls, including training
  • +
  • Use adequate personal protective equipment
  • +
+ +

8.1.3 Management of change

+

The organization shall establish processes for the implementation and control of planned temporary and permanent changes that impact OH&S performance.

+ +

8.1.4 Procurement

+

The organization shall establish processes to control the procurement of products and services and coordinate with contractors to identify hazards and assess and control HSE risks.

+
+ +
+

8.2 Emergency preparedness and response

+

The organization shall establish processes to prepare for and respond to potential emergency situations by:

+
    +
  • Establishing a planned response to emergency situations
  • +
  • Providing training for the planned response
  • +
  • Periodically testing and exercising the planned response capability
  • +
  • Evaluating performance and revising the planned response when necessary
  • +
  • Communicating duties and responsibilities to all relevant parties
  • +
+
+
+ + +
+
+

9. PERFORMANCE EVALUATION

+
+ +
+

9.1 Monitoring, measurement, analysis and performance evaluation

+

The organization shall establish processes for monitoring, measurement, analysis and performance evaluation to determine what needs to be monitored and measured, methods for monitoring, criteria for evaluation, and when monitoring and measurement shall be performed.

+ +

9.1.2 Evaluation of compliance

+

The organization shall establish processes for evaluating compliance with legal requirements and other requirements.

+
+ +
+

9.2 Internal audit

+

The organization shall conduct internal audits at planned intervals to provide information on whether the HSE management system conforms to the organization's requirements and this international standard, and is effectively implemented and maintained.

+
+ +
+

9.3 Management review

+

Top management shall review the organization's HSE management system at planned intervals to ensure its continuing suitability, adequacy and effectiveness. The management review shall consider:

+
    +
  • Status of actions from previous management reviews
  • +
  • Changes in external and internal issues
  • +
  • Information on HSE performance
  • +
  • Adequacy of resources
  • +
  • Opportunities for continual improvement
  • +
+
+
+ + +
+
+

10. IMPROVEMENT

+
+ +
+

10.1 General

+

The organization shall determine opportunities for improvement and implement necessary actions to achieve the intended outcomes of its HSE management system.

+
+ +
+

10.2 Incident, nonconformity and corrective action

+

When an incident or nonconformity occurs, the organization shall:

+
    +
  • React to the incident or nonconformity in a timely manner
  • +
  • Evaluate the need for corrective action to eliminate root causes
  • +
  • Implement any action needed, including corrective action
  • +
  • Review the effectiveness of any action taken
  • +
  • Make changes to the HSE management system, if necessary
  • +
+
+ +
+

10.3 Continual improvement

+

The organization shall continually improve the suitability, adequacy and effectiveness of the HSE management system to:

+
    +
  • Enhance HSE performance
  • +
  • Promote a culture that supports an HSE management system
  • +
  • Promote worker participation in implementing actions for continual improvement
  • +
  • Communicate relevant results of continual improvement to workers
  • +
+
+
+ + +
+
+

RELATED DOCUMENTS

+
+ +
    +
  1. TK-HSE-P-410 - Understanding Organizational Context and HSE Management System Operation Procedure
  2. +
  3. TK-HSE-P-510 - Leadership and Policy Establishment Procedure
  4. +
  5. TK-HSE-P-520 - Organization and Job Assignment Procedure
  6. +
  7. TK-HSE-P-610 - Planning and Risk Management Procedure
  8. +
  9. TK-HSE-P-620 - Risk Assessment Procedure
  10. +
  11. TK-HSE-P-630 - HSE Legal Requirements Management Procedure
  12. +
  13. TK-HSE-P-640 - HSE Objectives Management Procedure
  14. +
  15. TK-HSE-P-710 - Resource Management Procedure
  16. +
  17. TK-HSE-P-720 - Education and Training Management Procedure
  18. +
  19. TK-HSE-P-730 - Awareness and Communication Procedure
  20. +
  21. TK-HSE-P-740 - Documented Information Management Procedure
  22. +
  23. TK-HSE-P-810 - Operational Planning and Control Procedure
  24. +
  25. TK-HSE-P-820 - Emergency Preparedness and Response Procedure
  26. +
  27. TK-HSE-P-910 - Process Performance Management Procedure
  28. +
  29. TK-HSE-P-920 - HSE Monitoring and Measurement Management Procedure
  30. +
  31. TK-HSE-P-930 - Internal Audit Procedure
  32. +
  33. TK-HSE-P-940 - Management Review Procedure
  34. +
  35. TK-HSE-P-1010 - Incident, Nonconformity and Corrective Action Procedure
  36. +
  37. TK-HSE-P-1020 - Continual Improvement Procedure
  38. +
+
+ + +
+
+

DOCUMENT CONTROL

+
+ +

This is a controlled document

+

Do not copy without authorization

+

Latest version available on company intranet

+

For questions regarding this document, contact the HSE Management Department

+
+ +
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/policy.html b/deploy/tkfb-package/web-ui/docs/policy.html new file mode 100644 index 0000000..84e87cd --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/policy.html @@ -0,0 +1,317 @@ + + + + + + 경영방침 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

MP-001 경영방침서

+

테크니컬코리아 경영이념 및 기본방침

+
+
+ + +
+
+

MP-002 윤리강령

+

임직원 윤리행동 기준 및 가이드라인

+
+
+ + +
+
+

MP-003 정보보안 정책

+

회사 정보자산 보호 및 보안 정책

+
+
+ + +
+
+

MP-004 조직도

+

회사 조직도 및 부서별 역할

+
+
+ + +
+
+

MP-005 권한위임 규정

+

의사결정 권한 및 위임 규정

+
+
+
+ + +
+

경영방침 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

경영방침 문의: policy@technicalkorea.co.kr | 내선: 5678

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/quality.html b/deploy/tkfb-package/web-ui/docs/quality.html new file mode 100644 index 0000000..9ae8382 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/quality.html @@ -0,0 +1,373 @@ + + + + + + 품질 관리시스템 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

QM-001 품질매뉴얼

+

ISO 9001 기반 품질경영시스템 매뉴얼

+
+
+ + +
+
+

QP-001 문서 및 기록관리 절차

+

품질문서 작성, 승인, 배포, 보관 절차

+
+
+ + +
+
+

QP-002 고객만족 관리절차

+

고객 요구사항 파악 및 만족도 관리

+
+
+ + +
+
+

QP-003 설계 및 개발관리

+

설계입력, 검토, 검증, 타당성확인 절차

+
+
+ + +
+
+

QP-004 구매 및 외주관리

+

협력업체 평가, 구매품 검증 절차

+
+
+ + +
+
+

QP-005 생산 및 서비스 제공

+

생산공정 관리 및 제품 식별추적성

+
+
+ + +
+
+

QP-006 검사 및 시험관리

+

원자재, 중간품, 최종제품 검사 절차

+
+
+ + +
+
+

QP-007 부적합 및 시정조치

+

부적합품 관리 및 시정예방조치 절차

+
+
+ + +
+
+

QP-008 내부심사 절차

+

품질경영시스템 내부심사 실시 절차

+
+
+ + +
+
+

QP-009 경영검토 절차

+

품질경영시스템 경영검토 실시 절차

+
+
+ + +
+
+

QP-010 측정장비 관리절차

+

측정장비 교정, 점검, 관리 절차

+
+
+ + +
+
+

QP-011 교육훈련 관리절차

+

품질 관련 교육훈련 계획 및 실시

+
+
+
+ + +
+

품질문서 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

품질 문의: quality@technicalkorea.co.kr | 내선: 2345

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/docs/technical.html b/deploy/tkfb-package/web-ui/docs/technical.html new file mode 100644 index 0000000..7178527 --- /dev/null +++ b/deploy/tkfb-package/web-ui/docs/technical.html @@ -0,0 +1,333 @@ + + + + + + 기술문서 - 테크니컬코리아 + + + +
+ + + + + + + +
+
+ +
+
+

TD-001 배관설계 표준

+

배관 설계 기준 및 표준 사양서

+
+
+ + +
+
+

TD-002 용접절차서 (WPS)

+

배관 용접 절차 및 품질 기준

+
+
+ + +
+
+

TD-003 재료사양서

+

배관재료 규격 및 선정 기준

+
+
+ + +
+
+

TD-004 CAD 도면 표준

+

도면 작성 기준 및 CAD 표준

+
+
+ + +
+
+

TD-005 배관 검사기준서

+

배관 제작 및 설치 검사 기준

+
+
+ + +
+
+

TD-006 압력시험 절차서

+

배관계통 압력시험 절차 및 기준

+
+
+ + +
+
+

TD-007 BOM 시스템 사용자 매뉴얼

+

자재관리 시스템 사용 가이드

+
+
+
+ + +
+

기술문서 검색

+ +
+
+ +
+

테크니컬코리아 내부 전용 문서시스템

+

기술 문의: tech@technicalkorea.co.kr | 내선: 4567

+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/img/favicon.png b/deploy/tkfb-package/web-ui/img/favicon.png new file mode 100644 index 0000000..5bbd962 Binary files /dev/null and b/deploy/tkfb-package/web-ui/img/favicon.png differ diff --git a/deploy/tkfb-package/web-ui/img/login-bg.jpeg b/deploy/tkfb-package/web-ui/img/login-bg.jpeg new file mode 100644 index 0000000..1681fd4 Binary files /dev/null and b/deploy/tkfb-package/web-ui/img/login-bg.jpeg differ diff --git a/deploy/tkfb-package/web-ui/img/logo.png b/deploy/tkfb-package/web-ui/img/logo.png new file mode 100644 index 0000000..5bbd962 Binary files /dev/null and b/deploy/tkfb-package/web-ui/img/logo.png differ diff --git a/deploy/tkfb-package/web-ui/img/technicalkorea Logo.jpg b/deploy/tkfb-package/web-ui/img/technicalkorea Logo.jpg new file mode 100644 index 0000000..8ff1b35 Binary files /dev/null and b/deploy/tkfb-package/web-ui/img/technicalkorea Logo.jpg differ diff --git a/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.ai b/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.ai new file mode 100644 index 0000000..6eee406 --- /dev/null +++ b/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.ai @@ -0,0 +1,28071 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: Adobe Illustrator by AutoTrace version 0.31.1 +%%Title: /var/www/autotracer.org/temp_dir_m/e8c501b501b02912ca28ab93d5cd0777/technicalkorea_Logo.ai +%%CreationDate: Tue Jul 1 05:01:59 2025 +%%BoundingBox: 0 0 2094 600 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +/bd { bind def } bind def +/incompound false def +/m { moveto } bd +/l { lineto } bd +/c { curveto } bd +/F { incompound not {fill} if } bd +/f { closepath F } bd +/S { stroke } bd +/*u { /incompound true def } bd +/*U { /incompound false def f} bd +/k { setcmykcolor } bd +/K { k } bd +%%EndProlog +%%BeginSetup +%%EndSetup +0.000 0.000 0.000 0.000 k +*u +0 600 m +0 395 l +2.656 400.517 3 406.612 6.468 412 c +15.646 426.865 33.640 436.640 51 437 c +50 438.783 50 438.594 48 439 c +57.403 441.779 69.218 440 79 440 c +142 440 l +348 440 l +1023 440 l +1013.597 437.221 1001.782 439 992 439 c +929 439 l +724 439 l +53 439 l +59.678 436.198 69.784 438 77 438 c +130 438 l +313 438 l +802 438 l +953 438 l +1000 438 l +1006.746 438 1015.382 436.560 1021.910 438.318 c +1028.865 440.190 1035.484 451.822 1040.170 457 c +1051.647 469.684 1064.752 480.969 1078 491.739 c +1115.698 522.386 1162.655 542.211 1211 546.830 c +1270.668 552.532 1330.755 531 1377 493.540 c +1391.785 481.543 1405.287 468.291 1417.845 454 c +1422.293 448.938 1428.382 437 1435 435.318 c +1440.178 433.942 1446.752 435 1452 435 c +1488 435 l +1603 435 l +1975 435 l +1975 410 l +1598 410 l +1480 410 l +1443 410 l +1436.570 410 1429.295 409 1423 410.529 c +1414.316 412.540 1409.882 421.408 1404.870 428 c +1395.994 439.674 1385.879 450.987 1375 460.830 c +1339.790 492.687 1295.380 518.597 1247 521.911 c +1189.677 525.836 1137.711 505.369 1093 470.338 c +1078.487 458.967 1065.337 445.924 1053.289 432 c +1045.483 422.979 1040.211 412.343 1027 412 c +951.439 410 875.588 412 800 412 c +346 412 l +143 412 l +79 412 l +68.784 412 56.989 413.612 47 411.319 c +25.723 406.435 28 384.934 28 368 c +28 236 l +28 219.459 23.618 191.367 46 188 c +45.350 189.300 45.853 189 44 189 c +48 190 l +47.350 191.300 47.853 191 46 191 c +55.963 193.945 68.631 192 79 192 c +147 192 l +367 192 l +812 192 l +958 192 l +985 192 1013 193.925 1040 191 c +1029 186.711 1017.488 188 1006 188 c +949 188 l +746 188 l +513.345 188 280.567 188.358 48 189 c +48 187 l +708 187 l +925 187 l +997 187 l +1008.831 187 1021.229 188 1033 186.895 c +1043.211 185.875 1048.521 174.214 1054.211 167 c +1066 151.956 1079.889 138.204 1095 126.424 c +1137.864 93 1187.948 76.740 1242 77 c +1293.516 77.249 1341.887 99.730 1380 133.285 c +1392 143.903 1402.337 156.917 1411.576 170 c +1416 176.377 1419.345 185.301 1428 186.775 c +1434.378 187.862 1441.539 187 1448 187 c +1486 187 l +1605 187 l +1973 187 l +1973 228 l +1991.816 213.537 2013.250 202 2033 189 c +2040.776 183.821 2051.203 179.405 2057 172 c +2046.379 167.980 2036.523 159.845 2027 153.691 c +2009 142 1990.829 130.798 1973 119 c +1973 162 l +1607 162 l +1493 162 l +1458 162 l +1452.692 162 1446.176 163 1441 161.682 c +1434.719 160 1430 149.848 1426.338 145 c +1415.872 131.643 1403.990 119.341 1391 108.438 c +1351.307 75 1298.445 52.254 1246 52 c +1186.955 51.716 1132 66.518 1084 101.884 c +1068 113.547 1053.250 127.194 1040.286 142 c +1035.508 147.457 1029.281 159.806 1021.985 161.682 c +1016.820 163 1010.312 162 1005 162 c +970 162 l +859 162 l +502 162 l +118 162 l +94 162 l +63.275 162 22.657 155.452 5.493 188 c +3 192.609 1.452 197.822 1 203 c +-1.292 197.538 0 189.887 0 184 c +0 143 l +0 0 l +2094 0 l +2094 600 l +0 600 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1220.667 547.667 m +1220.222 547.222 1221.278 547.278 1221.333 547.333 c +1221.778 547.778 1220.722 547.722 1220.667 547.667 c +f +*U +0.000 0.000 0.000 0.408 k +*u +1222 548 m +1223.506 547.317 1224.315 547.174 1226 547 c +1224.494 547.683 1223.685 547.826 1222 548 c +f +*U +0.000 0.000 0.000 0.498 k +*u +1226 548 m +1228.890 546.787 1231.874 547 1235 547 c +1232 548.213 1229 547.998 1226 548 c +f +*U +0.000 0.000 0.000 0.259 k +*u +1235 548 m +1236.769 547.221 1238 547 1240 547 c +1238.231 547.779 1236.964 547.912 1235 548 c +f +*U +0.000 0.000 0.000 0.435 k +*u +1208 547 m +1209.249 546.315 1209.548 546.251 1211 546 c +1209.752 546.685 1209.451 546.749 1208 547 c +f +*U +0.000 0.000 0.000 0.706 k +*u +1211 547 m +1212 546 l +1211 547 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1097 505 m +1102.506 505.267 1106.507 504.498 1112 504 c +1111.402 505.195 1111.534 504.978 1110 506 c +1111.798 508.376 1112 511 1113 514 c +1117.498 511.951 1123 512.486 1128 512 c +1127 520 l +1133.353 520.383 1138 520.728 1144 523 c +1143.417 525.914 1144.588 524.930 1142 527 c +1144 527.529 1145.875 527.948 1148 528 c +1148.986 529.479 1149 529.203 1149 531 c +1152 529.921 1154.825 528.604 1158 528 c +1156 532 l +1164.214 535.235 1170 536.679 1179 536 c +1177.777 537.195 1177.580 537.317 1176 538 c +1192 536 l +1190.211 537.422 1189.294 537.697 1187 538 c +1189.974 539.754 1192.648 542 1196 543 c +1202.709 544.728 1209.612 543.318 1216 546 c +1218.673 542.941 1223.233 544.168 1227 544.305 c +1235.305 544.606 1243.588 544.364 1251.884 544.219 c +1256.600 544 1263.284 544.889 1264 539 c +1267 540 l +1265.564 538.550 1264.885 537.778 1264 536 c +1269 536 l +1270.582 538 1271 537.733 1273 536 c +1277 536 l +1278 540 l +1280 540 l +1281 536 l +1285 539 l +1285 537.203 1285 537.479 1286 536 c +1289.458 536.692 1293.276 537.234 1297 535 c +1296 534 l +1302 534 l +1299.979 533 1298 532.504 1296 532 c +1297.684 530.717 1299.572 529.475 1300 532 c +1305 529 l +1304 528 l +1307.472 528.329 1310.633 529 1314 530 c +1309.697 533.253 1304 534.641 1299 536.333 c +1286.644 540.449 1273.894 543.338 1261 545 c +1218.743 551 1176 544 1137 527.421 c +1123.816 521.779 1107.527 514.888 1097 505 c +f +*U +0.000 0.000 0.000 0.714 k +*u +1248.667 546.667 m +1248.223 546.223 1249.277 546.277 1249.333 546.333 c +1249.778 546.778 1248.722 546.722 1248.667 546.667 c +f +*U +0.000 0.000 0.000 0.471 k +*u +1250.667 546.667 m +1250.222 546.222 1251.278 546.278 1251.333 546.333 c +1251.778 546.778 1250.722 546.722 1250.667 546.667 c +f +*U +0.000 0.000 0.000 0.212 k +*u +1252.667 546.667 m +1252.222 546.222 1253.278 546.278 1253.333 546.333 c +1253.778 546.778 1252.722 546.722 1252.667 546.667 c +f +*U +0.000 0.000 0.000 0.333 k +*u +1199 546 m +1200 545 l +1199 546 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1200.667 545.667 m +1200.222 545.222 1201.278 545.278 1201.333 545.333 c +1201.778 545.778 1200.722 545.722 1200.667 545.667 c +f +*U +0.000 0.000 0.000 0.996 k +*u +1187 539 m +1188.648 538 1190.175 537.551 1192 537 c +1186.275 536.347 1181.495 537.749 1176 539 c +1177 537.985 1177.612 537.691 1179 537 c +1170.375 535.591 1164 536.497 1156 532 c +1156.406 529.907 1156.217 529.980 1158 529 c +1154.812 529 1152 530.303 1149 531 c +1148 528 l +1145.646 528 1144.232 527.791 1142 527 c +1144 523 l +1138.183 521.579 1132.916 520.993 1127 520 c +1128 512 l +1122.997 512.954 1117.879 512.549 1113 514 c +1111.862 511.207 1110 507.540 1112 505 c +1108 504.450 1104.859 506.945 1101 506 c +1094 504.285 1088.645 500 1083 495.846 c +1072.743 488.290 1063 479.954 1054 471 c +1048.283 465.376 1038.172 458.932 1040 450 c +1038.271 449 1037.406 448.392 1036 447 c +1036 449 l +1031.474 445.298 1030.846 441.527 1032 436 c +1030 437 l +1030.768 435.686 1030.686 435.768 1032 435 c +1030.723 433 1030.723 433.915 1032 432 c +1029 434 l +1026.227 431.732 1022.444 432.412 1019 432 c +1020 434 l +1008.634 430.453 995.831 432 984 432 c +921 432 l +710 432 l +271 432 l +127 432 l +101.328 432 74.463 429.782 49 433 c +53 434 l +51.542 435 50.752 435.436 49 436 c +48 432 l +43 434 l +44 432 l +39.342 432.898 35.518 432.375 31 431 c +30.695 424 23.491 425.482 20 421 c +24 421 l +22.469 419 20.951 417.532 19 416 c +19 420 l +16.912 418.828 15.321 411.481 13 414 c +11.275 412.723 10.221 412.314 12 411 c +10.316 410.776 9.687 410.782 8 411 c +8.980 409.217 8.908 409.406 11 409 c +8.299 407.261 7 406 6 403 c +7.267 401.457 7.489 400.952 8 399 c +4 400 l +6.466 394.711 7 390.778 8 385 c +6.814 386 6.396 386.339 5 387 c +6 384 l +4.373 385.717 4 385.899 5 388 c +4 393 l +-1.639 383.933 0 373.290 0 363 c +0 305 l +24 305 l +24 391 l +25 389 l +25.751 391 25.656 391.596 24 393 c +24.727 395.753 24.607 398.517 26 401 c +24 404 l +25.915 402.723 25 402.723 27 404 c +28 399 l +29.187 401.180 29.234 402.514 29 405 c +34.487 405.255 32.224 409 34.895 412.489 c +36.307 414.307 38.989 415 41 416 c +40.489 414 40.267 413.543 39 412 c +40 414 l +38.217 413 38.406 413 38 411 c +39.878 411.176 41.199 411.438 43 412 c +42 415 l +44.592 415 45.707 414.737 48 414 c +47 416 l +86.624 411 127.988 414 168 414 c +378 414 l +1024 414 l +1016.841 417 1005.744 415 998 415 c +941 415 l +743 415 l +56 415 l +64.280 417.448 74.393 416 83 416 c +137 416 l +312 416 l +886 416 l +995 416 l +1004.996 416 1015 416 1025 415.995 c +1030.506 415.905 1034.575 414.502 1039.826 417 c +1043.661 418.902 1046 422.759 1048.600 426 c +1052.525 430.910 1056.589 435.507 1060.985 439.999 c +1076.853 456.214 1093.284 471.210 1112 484 c +1126.948 494.423 1143 502.860 1160 509.550 c +1165.691 511.808 1175.917 512.565 1178 519 c +1179 517.466 1178.805 517.598 1180 517 c +1183.857 518.867 1189.271 518.625 1192 522 c +1195 521.472 1197 522 1200 523 c +1197.812 524.885 1195.713 526 1193 527 c +1196.767 526.871 1200.391 524.566 1203 528 c +1205.934 527.360 1208 527.360 1211 528 c +1209.952 526 1209.487 525 1209 523 c +1217 525 l +1214.761 525.811 1213.353 525.529 1211 525 c +1213 527 1214.000 528.429 1217 528 c +1219 527 l +1222.348 527.279 1226.657 528.965 1231 528 c +1232 527.747 1233.863 526.284 1235 526 c +1237.340 525.415 1239.191 526.397 1241 527 c +1242 526 l +1242 528 l +1243 526 l +1244.300 526.650 1244 526 1244 528 c +1244.986 526.521 1245 526.797 1245 525 c +1245.685 526.248 1245.749 526.549 1246 528 c +1248.855 527.294 1251 527.513 1254 528 c +1253 524 l +1255.378 524.181 1257.628 524.233 1260 524 c +1260 528 l +1261 525.538 1261.334 524.568 1264 524 c +1263 521 l +1271.274 520.324 1277.667 518.358 1286 520 c +1284.843 518.183 1284.855 518 1285 516 c +1286.528 517.474 1286.840 517.918 1287 520 c +1289.409 519.728 1291.581 519.799 1294 520 c +1294.307 517.877 1294.382 517.314 1296 516 c +1295 513 l +1298.604 512 1301.263 511.594 1304 509 c +1310.537 511.439 1311.791 507.453 1316 503 c +1318.992 503 1321.189 502.883 1324 504 c +1323 500 l +1325.420 501.382 1326 502.363 1327 505 c +1327.506 503 1327.686 502.268 1329 501 c +1327.744 499.263 1327.345 498 1327 496 c +1349.291 482.355 1368.859 466.798 1387 447.996 c +1396.451 438.263 1406.258 427.833 1413 416 c +1415.741 415.723 1417.586 414.291 1420 413 c +1420 414.797 1419.986 414.522 1419 416 c +1968 416 l +1968 432 l +1586 432 l +1480 432 l +1463.783 432 1443.713 428.891 1429 436 c +1427.990 434.831 1427.516 434.685 1426 434 c +1424 440 l +1418.649 440.829 1416.401 443.682 1416 449 c +1417 445 l +1418.739 448.573 1415.598 458.891 1411 455 c +1409.287 456.647 1408.306 456.631 1408 459 c +1409.478 458 1409.203 458 1411 458 c +1409.465 467.785 1397 476.545 1389.999 482.834 c +1374.955 496.309 1358.416 507.820 1341 517.988 c +1333.655 522.277 1323.626 528.946 1315 529.748 c +1311.380 530 1307.517 528.743 1304 528 c +1303.441 530.579 1302.466 530.972 1300 532 c +1300.000 529.312 1298.323 530.572 1296 531 c +1298 531.881 1299.854 532.496 1302 533 c +1299.948 533.874 1298.253 533.953 1296 534 c +1295.404 537.935 1289 536.731 1286 536 c +1285 539 l +1283 537.999 1282.901 537.923 1282 536 c +1280 540 l +1278 540 l +1277 536 l +1275.313 536.218 1274.684 536.224 1273 536 c +1271.722 538.898 1269.750 539.483 1269 536 c +1266.968 536.323 1266 536.340 1264 536 c +1267 539 l +1265.502 539.479 1265.650 539.400 1264 539 c +1263.720 545 1256.869 544.287 1252 544.487 c +1244 544.813 1235.971 544.989 1228 544.634 c +1223.594 544.438 1219.714 543.187 1216 546 c +1209.178 543.964 1201.981 544.830 1195 543 c +1192 542.248 1189.747 540.246 1187 539 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1258 546 m +1259 545 l +1258 546 l +f +*U +0.000 0.000 0.000 0.557 k +*u +1259 546 m +1260 545 l +1259 546 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1260 546 m +1261 545 l +1260 546 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1192 545 m +1193 544 l +1192 545 l +f +*U +0.000 0.000 0.000 0.424 k +*u +1193 545 m +1194 544 l +1193 545 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1194 545 m +1195 544 l +1194 545 l +f +*U +0.012 0.012 0.000 0.678 k +*u +1265 545 m +1266 544 l +1265 545 l +f +*U +0.008 0.008 0.000 0.435 k +*u +1266 545 m +1267 544 l +1266 545 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1267 545 m +1268 544 l +1267 545 l +f +*U +0.000 0.000 0.000 0.267 k +*u +1187 544 m +1188 543 l +1187 544 l +f +*U +0.000 0.000 0.000 0.553 k +*u +1188 544 m +1189 543 l +1188 544 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1189 544 m +1190 543 l +1189 544 l +f +*U +0.000 0.000 0.000 0.686 k +*u +1271 544 m +1272 543 l +1271 544 l +f +*U +0.000 0.000 0.000 0.314 k +*u +1272 544 m +1273 543 l +1272 544 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1182 543 m +1183 542 l +1182 543 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1183 543 m +1184 542 l +1183 543 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1276 543 m +1277 542 l +1276 543 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1277 543 m +1278 542 l +1277 543 l +f +*U +0.000 0.000 0.000 0.286 k +*u +1178 542 m +1179 541 l +1178 542 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1179 542 m +1180 541 l +1179 542 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1280 542 m +1281 541 l +1280 542 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1281 542 m +1282 541 l +1281 542 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1174 541 m +1175 540 l +1174 541 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1175 541 m +1176 540 l +1175 541 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1284 541 m +1285 540 l +1284 541 l +f +*U +0.000 0.000 0.000 0.424 k +*u +1285 541 m +1286 540 l +1285 541 l +f +*U +0.000 0.000 0.000 0.294 k +*u +1170 540 m +1171 539 l +1170 540 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1171 540 m +1172 539 l +1171 540 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1288 540 m +1289 539 l +1288 540 l +f +*U +0.000 0.000 0.000 0.302 k +*u +1289 540 m +1290 539 l +1289 540 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1166 539 m +1167 538 l +1166 539 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1167 539 m +1168 538 l +1167 539 l +f +*U +0.000 0.000 0.000 0.416 k +*u +1292 539 m +1293 538 l +1292 539 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1163 538 m +1164 537 l +1163 538 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1164 538 m +1165 537 l +1164 538 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1295 538 m +1296 537 l +1295 538 l +f +*U +0.000 0.000 0.000 0.376 k +*u +1160 537 m +1161 536 l +1160 537 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1161 537 m +1162 536 l +1161 537 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1298 537 m +1299 536 l +1298 537 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1299 537 m +1300 536 l +1299 537 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1157 536 m +1158 535 l +1157 536 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1158 536 m +1159 535 l +1158 536 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1301 536 m +1302 535 l +1301 536 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1302 536 m +1303 535 l +1302 536 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1154 535 m +1155 534 l +1154 535 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1304 535 m +1305 534 l +1304 535 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1151 534 m +1152 533 l +1151 534 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1152 534 m +1153 533 l +1152 534 l +f +*U +0.000 0.000 0.000 0.557 k +*u +1307 534 m +1308 533 l +1307 534 l +f +*U +0.000 0.000 0.000 0.576 k +*u +1149 533 m +1150 532 l +1149 533 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1309 533 m +1310 532 l +1309 533 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1310 533 m +1311 532 l +1310 533 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1146 532 m +1147 531 l +1146 532 l +f +*U +0.000 0.000 0.000 0.576 k +*u +1312 532 m +1313 531 l +1312 532 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1144 531 m +1145 530 l +1144 531 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1314 531 m +1315 530 l +1314 531 l +f +*U +0.000 0.000 0.000 0.278 k +*u +1141 530 m +1142 529 l +1141 530 l +f +*U +0.000 0.000 0.000 0.357 k +*u +1317 530 m +1318 529 l +1317 530 l +f +*U +0.000 0.000 0.000 0.392 k +*u +1139 529 m +1140 528 l +1139 529 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1319 529 m +1320 528 l +1319 529 l +f +*U +0.000 0.000 0.000 0.267 k +*u +1136 528 m +1137 527 l +1136 528 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1137 528 m +1138 527 l +1137 528 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1193 528 m +1195.187 525.968 1197 524.906 1200 524 c +1197.184 522.642 1195 521.920 1192 522 c +1189.177 519.689 1182.345 517 1179 519 c +1177.407 514.799 1183.789 517 1186 517.630 c +1194.832 519.818 1203.937 521.406 1213 522 c +1239.991 524 1266.293 521.434 1292 512.319 c +1303.849 508 1315 500.221 1327 497 c +1327.689 498.688 1327.676 499 1329 500 c +1327.825 501.879 1327.870 502.716 1328 505 c +1323 500 l +1324 504 l +1321.301 503.264 1318.766 503.253 1316 503 c +1312.638 508.242 1310.278 512.630 1304 509 c +1301.737 512 1298.686 512.301 1295 513 c +1295.986 514.479 1296 514.203 1296 516 c +1294.733 517.543 1294.511 518 1294 520 c +1287 520 l +1287 517.898 1286.455 517.629 1285 516 c +1284.930 517.952 1284.646 517.940 1286 519 c +1283 520 1280 518.908 1277 518.998 c +1272.265 519 1267.750 520.793 1263 521 c +1263.986 522.479 1264 522.203 1264 524 c +1261.965 525.226 1261.674 525.702 1261 528 c +1260.317 526.494 1260.174 525.685 1260 524 c +1257.353 524.578 1255.636 524.607 1253 524 c +1254 528 l +1250.641 527.802 1246.615 528.853 1246 525 c +1245 526.479 1245 526.203 1245 528 c +1243.804 527.402 1244 527.534 1243 526 c +1243 528 l +1241.700 527.350 1242 527.853 1242 526 c +1233.779 527 1217.519 531.663 1211 525 c +1217 526 l +1209 523 l +1211 528 l +1208.194 527.598 1205.806 527.598 1203 528 c +1199.774 525 1196.868 527.178 1193 528 c +f +*U +0.000 0.000 0.000 0.212 k +*u +1322 528 m +1323 527 l +1322 528 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1134 527 m +1135 526 l +1134 527 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1324 527 m +1325 526 l +1324 527 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1132 526 m +1133 525 l +1132 526 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1326 526 m +1327 525 l +1326 526 l +f +*U +0.000 0.000 0.000 0.341 k +*u +1130 525 m +1131 524 l +1130 525 l +f +*U +0.000 0.000 0.000 0.306 k +*u +1328 525 m +1329 524 l +1328 525 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1128 524 m +1129 523 l +1128 524 l +f +*U +0.000 0.000 0.000 0.427 k +*u +1330 524 m +1331 523 l +1330 524 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1126 523 m +1127 522 l +1126 523 l +f +*U +0.000 0.000 0.000 0.612 k +*u +1216.667 522.667 m +1216.223 522.223 1217.277 522.277 1217.333 522.333 c +1217.778 522.778 1216.722 522.722 1216.667 522.667 c +f +*U +0.000 0.000 0.000 0.478 k +*u +1218 523 m +1219.249 522.315 1219.548 522.251 1221 522 c +1219.752 522.685 1219.451 522.749 1218 523 c +f +*U +0.000 0.000 0.000 0.290 k +*u +1221 523 m +1222.248 522.315 1222.548 522.251 1224 522 c +1222.752 522.685 1222.451 522.749 1221 523 c +f +*U +0.024 0.000 0.020 0.125 k +*u +1224 523 m +1227.698 521.448 1232 522 1236 522 c +1232.303 523.552 1227.983 523 1224 523 c +f +*U +0.000 0.000 0.000 0.314 k +*u +1236 523 m +1237.769 522.221 1239 522 1241 522 c +1239.231 522.779 1237.964 522.912 1236 523 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1241.667 522.667 m +1241.222 522.222 1242.278 522.278 1242.333 522.333 c +1242.778 522.778 1241.722 522.722 1241.667 522.667 c +f +*U +0.000 0.000 0.000 0.867 k +*u +1243.667 522.667 m +1243.223 522.223 1244.277 522.277 1244.333 522.333 c +1244.778 522.778 1243.722 522.722 1243.667 522.667 c +f +*U +0.000 0.000 0.000 0.404 k +*u +1332 523 m +1333 522 l +1332 523 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1124 522 m +1125 521 l +1124 522 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1206 522 m +1207 521 l +1206 522 l +f +*U +0.000 0.000 0.000 0.427 k +*u +1207.667 521.667 m +1207.223 521.223 1208.277 521.277 1208.333 521.333 c +1208.778 521.778 1207.722 521.722 1207.667 521.667 c +f +*U +0.000 0.000 0.000 0.235 k +*u +1209 522 m +1210 521 l +1209 522 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1250 522 m +1251.248 521.315 1251.548 521.251 1253 521 c +1251.752 521.685 1251.451 521.749 1250 522 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1253 522 m +1254 521 l +1253 522 l +f +*U +0.000 0.000 0.000 0.459 k +*u +1334 522 m +1335 521 l +1334 522 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1122 521 m +1123 520 l +1122 521 l +f +*U +0.000 0.000 0.000 0.608 k +*u +1200 521 m +1201 520 l +1200 521 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1201 521 m +1202 520 l +1201 521 l +f +*U +0.000 0.000 0.000 0.310 k +*u +1258 521 m +1259 520 l +1258 521 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1259 521 m +1260 520 l +1259 521 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1260 521 m +1261 520 l +1260 521 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1336 521 m +1337 520 l +1336 521 l +f +*U +0.000 0.000 0.000 0.443 k +*u +1120 520 m +1121 519 l +1120 520 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1194 520 m +1195 519 l +1194 520 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1195 520 m +1196 519 l +1195 520 l +f +*U +0.012 0.012 0.000 0.341 k +*u +1264 520 m +1265 519 l +1264 520 l +f +*U +0.008 0.008 0.000 0.608 k +*u +1265 520 m +1266 519 l +1265 520 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1338 520 m +1339 519 l +1338 520 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1118 519 m +1119 518 l +1118 519 l +f +*U +0.000 0.000 0.008 0.733 k +*u +1189 519 m +1190 518 l +1189 519 l +f +*U +0.000 0.000 0.008 0.396 k +*u +1190 519 m +1191 518 l +1190 519 l +f +*U +0.000 0.000 0.008 0.310 k +*u +1269 519 m +1270 518 l +1269 519 l +f +*U +0.000 0.000 0.008 0.741 k +*u +1270 519 m +1271 518 l +1270 519 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1116 518 m +1117 517 l +1116 518 l +f +*U +0.008 0.008 0.000 0.627 k +*u +1185 518 m +1186 517 l +1185 518 l +f +*U +0.008 0.008 0.000 0.282 k +*u +1186 518 m +1187 517 l +1186 518 l +f +*U +0.008 0.008 0.000 0.224 k +*u +1273 518 m +1274 517 l +1273 518 l +f +*U +0.008 0.008 0.000 0.655 k +*u +1274 518 m +1275 517 l +1274 518 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1341 518 m +1342 517 l +1341 518 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1115 517 m +1116 516 l +1115 517 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1181 517 m +1182 516 l +1181 517 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1182 517 m +1183 516 l +1182 517 l +f +*U +0.012 0.012 0.000 0.184 k +*u +1277 517 m +1278 516 l +1277 517 l +f +*U +0.008 0.008 0.000 0.690 k +*u +1278 517 m +1279 516 l +1278 517 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1343 517 m +1344 516 l +1343 517 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1113 516 m +1114 515 l +1113 516 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1177 516 m +1178 515 l +1177 516 l +f +*U +0.000 0.000 0.000 0.384 k +*u +1178 516 m +1179 515 l +1178 516 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1281 516 m +1282 515 l +1281 516 l +f +*U +0.000 0.000 0.000 0.463 k +*u +1111 515 m +1112 514 l +1111 515 l +f +*U +0.000 0.000 0.000 0.510 k +*u +1174 515 m +1175 514 l +1174 515 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1284 515 m +1285 514 l +1284 515 l +f +*U +0.000 0.000 0.000 0.643 k +*u +1285 515 m +1286 514 l +1285 515 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1346 515 m +1347 514 l +1346 515 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1109 514 m +1110 513 l +1109 514 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1171 514 m +1172 513 l +1171 514 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1288 514 m +1289 513 l +1288 514 l +f +*U +0.000 0.000 0.000 0.412 k +*u +1348 514 m +1349 513 l +1348 514 l +f +*U +0.000 0.000 0.000 0.290 k +*u +1168 513 m +1169 512 l +1168 513 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1290 513 m +1291 512 l +1290 513 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1291 513 m +1292 512 l +1291 513 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1350 513 m +1351 512 l +1350 513 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1106 512 m +1107 511 l +1106 512 l +f +*U +0.000 0.000 0.000 0.502 k +*u +1165 512 m +1166 511 l +1165 512 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1294 512 m +1295 511 l +1294 512 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1351 512 m +1352 511 l +1351 512 l +f +*U +0.000 0.000 0.000 0.259 k +*u +1104 511 m +1105 510 l +1104 511 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1162 511 m +1163 510 l +1162 511 l +f +*U +0.000 0.000 0.000 0.380 k +*u +1296 511 m +1297 510 l +1296 511 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1353 511 m +1354 510 l +1353 511 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1103 510 m +1104 509 l +1103 510 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1159 510 m +1160 509 l +1159 510 l +f +*U +0.000 0.000 0.000 0.600 k +*u +1299 510 m +1300 509 l +1299 510 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1101 509 m +1102 508 l +1101 509 l +f +*U +0.000 0.000 0.000 0.455 k +*u +1157 509 m +1158 508 l +1157 509 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1301 509 m +1302 508 l +1301 509 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1302 509 m +1303 508 l +1302 509 l +f +*U +0.000 0.000 0.000 0.471 k +*u +1356 509 m +1357 508 l +1356 509 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1155 508 m +1156 507 l +1155 508 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1098 507 m +1099 506 l +1098 507 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1152 507 m +1153 506 l +1152 507 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1306 507 m +1307 506 l +1306 507 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1359 507 m +1360 506 l +1359 507 l +f +*U +0.000 0.000 0.000 0.420 k +*u +1150 506 m +1151 505 l +1150 506 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1308 506 m +1309 505 l +1308 506 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1360 506 m +1361 505 l +1360 506 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1095 505 m +1096 504 l +1095 505 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1148 505 m +1149 504 l +1148 505 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1310 505 m +1311 504 l +1310 505 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1362 505 m +1363 504 l +1362 505 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1145 504 m +1146 503 l +1145 504 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1146 504 m +1147 503 l +1146 504 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1313 504 m +1314 503 l +1313 504 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1363 504 m +1364 503 l +1363 504 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1092 503 m +1093 502 l +1092 503 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1143 503 m +1144 502 l +1143 503 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1314 503 m +1315 502 l +1314 503 l +f +*U +0.000 0.000 0.000 0.624 k +*u +1141 502 m +1142 501 l +1141 502 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1317 502 m +1318 501 l +1317 502 l +f +*U +0.000 0.000 0.000 0.310 k +*u +1366 502 m +1367 501 l +1366 502 l +f +*U +0.000 0.000 0.000 0.408 k +*u +1089 501 m +1090 500 l +1089 501 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1139 501 m +1140 500 l +1139 501 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1318 501 m +1319 500 l +1318 501 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1088 500 m +1089 499 l +1088 500 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1137 500 m +1138 499 l +1137 500 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1320 500 m +1321 499 l +1320 500 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1369 500 m +1370 499 l +1369 500 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1086 499 m +1087 498 l +1086 499 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1135 499 m +1136 498 l +1135 499 l +f +*U +0.000 0.000 0.000 0.235 k +*u +1322 499 m +1323 498 l +1322 499 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1370 499 m +1371 498 l +1370 499 l +f +*U +0.000 0.000 0.000 0.467 k +*u +1085 498 m +1086 497 l +1085 498 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1134 498 m +1135 497 l +1134 498 l +f +*U +0.000 0.000 0.000 0.353 k +*u +1324 498 m +1325 497 l +1324 498 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1326 497 m +1327 496 l +1326 497 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1373 497 m +1374 496 l +1373 497 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1082 496 m +1083 495 l +1082 496 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1130 496 m +1131 495 l +1130 496 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1374 496 m +1375 495 l +1374 496 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1081 495 m +1082 494 l +1081 495 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1128 495 m +1129 494 l +1128 495 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1126 494 m +1127 493 l +1126 494 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1331 494 m +1332 493 l +1331 494 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1377 494 m +1378 493 l +1377 494 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1078 493 m +1079 492 l +1078 493 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1125 493 m +1126 492 l +1125 493 l +f +*U +0.000 0.000 0.000 0.314 k +*u +1378 493 m +1379 492 l +1378 493 l +f +1077 492 m +1078 491 l +1077 492 l +f +*U +0.000 0.000 0.000 0.404 k +*u +1123 492 m +1124 491 l +1123 492 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1334 492 m +1335 491 l +1334 492 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1379 492 m +1380 491 l +1379 492 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1076 491 m +1077 490 l +1076 491 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1121 491 m +1122 490 l +1121 491 l +f +*U +0.000 0.000 0.000 0.627 k +*u +1336 491 m +1337 490 l +1336 491 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1380 491 m +1381 490 l +1380 491 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1120 490 m +1121 489 l +1120 490 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1337 490 m +1338 489 l +1337 490 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1118 489 m +1119 488 l +1118 489 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1339 489 m +1340 488 l +1339 489 l +f +*U +0.000 0.000 0.000 0.439 k +*u +1072 488 m +1073 487 l +1072 488 l +f +*U +0.000 0.000 0.000 0.525 k +*u +1384 488 m +1385 487 l +1384 488 l +f +*U +0.000 0.000 0.000 0.537 k +*u +1115 487 m +1116 486 l +1115 487 l +f +*U +0.000 0.000 0.000 0.490 k +*u +1342 487 m +1343 486 l +1342 487 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1385 487 m +1386 486 l +1385 487 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1113 486 m +1114 485 l +1113 486 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1386 486 m +1387 485 l +1386 486 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1112 485 m +1113 484 l +1112 485 l +f +*U +0.000 0.000 0.000 0.439 k +*u +1345 485 m +1346 484 l +1345 485 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1067 484 m +1068 483 l +1067 484 l +f +1346 484 m +1347 483 l +1346 484 l +f +*U +0.000 0.000 0.000 0.506 k +*u +1066 483 m +1067 482 l +1066 483 l +f +1109 483 m +1110 482 l +1109 483 l +f +*U +0.000 0.000 0.000 0.816 k +*u +1348 483 m +1349 482 l +1348 483 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1065 482 m +1066 481 l +1065 482 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1349 482 m +1350 481 l +1349 482 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1391 482 m +1392 481 l +1391 482 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1064 481 m +1065 480 l +1064 481 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1106 481 m +1107 480 l +1106 481 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1392 481 m +1393 480 l +1392 481 l +f +*U +0.000 0.000 0.000 0.816 k +*u +1063 480 m +1064 479 l +1063 480 l +f +*U +0.000 0.333 0.275 0.169 k +*u +1209 480 m +1210.769 479.221 1212 479 1214 479 c +1212.231 479.779 1210.964 479.912 1209 480 c +f +*U +0.000 0.310 0.216 0.306 k +*u +1214.667 479.667 m +1214.222 479.222 1215.278 479.278 1215.333 479.333 c +1215.778 479.778 1214.722 479.722 1214.667 479.667 c +f +*U +0.000 0.682 0.471 0.220 k +*u +1216.667 479.667 m +1216.222 479.222 1217.278 479.278 1217.333 479.333 c +1217.778 479.778 1216.722 479.722 1216.667 479.667 c +f +*U +0.000 0.584 0.416 0.416 k +*u +1218 480 m +1220.890 478.787 1223.874 479 1227 479 c +1224 480.213 1221 479.998 1218 480 c +f +*U +0.000 0.482 0.482 0.518 k +*u +1227 480 m +1228.769 479.221 1230 479 1232 479 c +1230.231 479.779 1228.964 479.912 1227 480 c +f +*U +0.000 0.549 0.522 0.380 k +*u +1232.667 479.667 m +1232.222 479.222 1233.278 479.278 1233.333 479.333 c +1233.778 479.778 1232.722 479.722 1232.667 479.667 c +f +*U +0.000 0.384 0.416 0.165 k +*u +1234 480 m +1235.249 479.315 1235.548 479.251 1237 479 c +1235.752 479.685 1235.452 479.749 1234 480 c +f +*U +0.000 0.145 0.255 0.161 k +*u +1237.667 479.667 m +1237.222 479.222 1238.278 479.278 1238.333 479.333 c +1238.778 479.777 1237.722 479.722 1237.667 479.667 c +f +*U +0.000 0.000 0.000 0.494 k +*u +1393 480 m +1394 479 l +1393 480 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1103 479 m +1104 478 l +1103 479 l +f +*U +0.000 0.239 0.208 0.008 k +*u +1201 479 m +1202 478 l +1201 479 l +f +*U +0.000 0.302 0.251 0.149 k +*u +1202 479 m +1203 478 l +1202 479 l +f +*U +0.000 0.392 0.310 0.290 k +*u +1203 479 m +1204 478 l +1203 479 l +f +*U +0.000 0.514 0.416 0.486 k +*u +1204 479 m +1205.506 478.317 1206.315 478.174 1208 478 c +1206.494 478.683 1205.685 478.826 1204 479 c +f +*U +0.000 0.851 0.698 0.149 k +*u +1208 477 m +1212 477.749 1215.899 477.997 1220 478 c +1216.479 479.478 1210.661 480 1208 477 c +f +*U +0.000 0.863 0.616 0.129 k +*u +1186 475 m +1187 472 l +1211.465 475.213 1236.492 471.285 1261 473 c +1258 477.519 1245.341 477.930 1240 478 c +1227.931 478.172 1216 478.866 1204 477.802 c +1197.857 477.262 1192.257 475 1186 475 c +f +*U +0.000 0.694 0.424 0.306 k +*u +1233 479 m +1235.332 478 1237.457 478 1240 478 c +1237.669 478.984 1235.543 478.981 1233 479 c +f +*U +0.000 0.451 0.435 0.549 k +*u +1240 479 m +1241.769 478.221 1243 478 1245 478 c +1243.231 478.779 1241.964 478.912 1240 479 c +f +*U +0.000 0.475 0.373 0.259 k +*u +1245 479 m +1246 478 l +1245 479 l +f +*U +0.000 0.435 0.325 0.000 k +*u +1246.667 478.667 m +1246.222 478.222 1247.278 478.278 1247.333 478.333 c +1247.778 478.778 1246.722 478.722 1246.667 478.667 c +f +*U +0.000 0.000 0.000 0.392 k +*u +1353 479 m +1354 478 l +1353 479 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1394 479 m +1395 478 l +1394 479 l +f +*U +0.000 0.000 0.000 0.494 k +*u +1102 478 m +1103 477 l +1102 478 l +f +*U +0.000 0.259 0.118 0.129 k +*u +1195 478 m +1196 477 l +1195 478 l +f +*U +0.000 0.388 0.204 0.286 k +*u +1196 478 m +1197 477 l +1196 478 l +f +*U +0.000 0.624 0.494 0.376 k +*u +1197 478 m +1198.769 477.221 1200 477 1202 477 c +1200.231 477.779 1198.964 477.912 1197 478 c +f +*U +0.000 0.518 0.349 0.482 k +*u +1248 478 m +1249.506 477.317 1250.315 477.174 1252 477 c +1250.494 477.683 1249.685 477.826 1248 478 c +f +*U +0.000 0.298 0.224 0.204 k +*u +1252.667 477.667 m +1252.222 477.222 1253.278 477.278 1253.333 477.333 c +1253.778 477.778 1252.722 477.722 1252.667 477.667 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1395 478 m +1396 477 l +1395 478 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1101 477 m +1102 476 l +1101 477 l +f +*U +0.000 0.341 0.263 0.141 k +*u +1190 477 m +1191 476 l +1190 477 l +f +*U +0.000 0.451 0.263 0.290 k +*u +1191 477 m +1192 476 l +1191 477 l +f +*U +0.000 0.741 0.659 0.259 k +*u +1192 477 m +1194 476 1195.747 476 1198 476 c +1195.948 476.874 1194.253 476.953 1192 477 c +f +*U +0.000 0.910 0.918 0.063 k +*u +1248 477 m +1249.769 476.221 1251 476 1253 476 c +1251.231 476.779 1249.964 476.912 1248 477 c +f +*U +0.000 0.718 0.667 0.282 k +*u +1253 477 m +1254.248 476.315 1254.548 476.251 1256 476 c +1254.752 476.685 1254.451 476.749 1253 477 c +f +*U +0.000 0.416 0.200 0.584 k +*u +1256 477 m +1257 476 l +1256 477 l +f +*U +0.000 0.373 0.267 0.337 k +*u +1257 477 m +1258 476 l +1257 477 l +f +*U +0.000 0.149 0.043 0.129 k +*u +1258.667 476.667 m +1258.222 476.222 1259.278 476.278 1259.333 476.333 c +1259.778 476.777 1258.722 476.722 1258.667 476.667 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1356 477 m +1357 476 l +1356 477 l +f +*U +0.000 0.043 0.204 0.290 k +*u +1184.667 475.667 m +1184.222 475.222 1185.278 475.278 1185.333 475.333 c +1185.778 475.778 1184.722 475.722 1184.667 475.667 c +f +*U +0.000 0.341 0.153 0.357 k +*u +1186 476 m +1187 475 l +1186 476 l +f +*U +0.000 0.675 0.412 0.325 k +*u +1187 476 m +1189.332 475 1191.457 475 1194 475 c +1191.668 475.984 1189.544 475.981 1187 476 c +f +*U +0.000 0.514 0.322 0.486 k +*u +1260 476 m +1261.249 475.315 1261.548 475.251 1263 475 c +1261.752 475.685 1261.451 475.749 1260 476 c +f +*U +0.000 0.412 0.137 0.078 k +*u +1263 476 m +1264 475 l +1263 476 l +f +*U +0.000 0.000 0.000 0.518 k +*u +1357 476 m +1358 475 l +1357 476 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1397 476 m +1398 475 l +1397 476 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1057 475 m +1058 474 l +1057 475 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1098 475 m +1099 474 l +1098 475 l +f +*U +0.000 0.275 0.231 0.059 k +*u +1181 475 m +1182 474 l +1181 475 l +f +*U +0.000 0.435 0.314 0.322 k +*u +1182 475 m +1183 474 l +1182 475 l +f +*U +0.000 0.635 0.655 0.345 k +*u +1183 475 m +1184.249 474.315 1184.548 474.251 1186 474 c +1184.752 474.685 1184.452 474.749 1183 475 c +f +*U +0.000 0.796 0.592 0.204 k +*u +1261 475 m +1262 473 l +1263.635 473.545 1263.455 473.365 1264 475 c +1261 475 l +f +*U +0.000 0.522 0.373 0.443 k +*u +1264.667 474.667 m +1264.222 474.222 1265.278 474.278 1265.333 474.333 c +1265.778 474.778 1264.722 474.722 1264.667 474.667 c +f +*U +0.000 0.435 0.278 0.227 k +*u +1266 475 m +1267 474 l +1266 475 l +f +*U +0.000 0.314 0.200 0.039 k +*u +1267 475 m +1268 474 l +1267 475 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1398 475 m +1399 474 l +1398 475 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1056 474 m +1057 473 l +1056 474 l +f +*U +0.000 0.000 0.000 0.231 k +*u +1097 474 m +1098 473 l +1097 474 l +f +*U +0.000 0.216 0.192 0.043 k +*u +1177 474 m +1178 473 l +1177 474 l +f +*U +0.000 0.333 0.239 0.337 k +*u +1178 474 m +1179 473 l +1178 474 l +f +*U +0.000 0.573 0.518 0.427 k +*u +1179.667 473.667 m +1179.222 473.222 1180.278 473.278 1180.333 473.333 c +1180.778 473.778 1179.722 473.722 1179.667 473.667 c +f +*U +0.000 0.859 0.694 0.141 k +*u +1181 474 m +1182.750 472.745 1183.857 472.386 1186 472 c +1184.460 473.803 1183.403 473.832 1181 474 c +f +*U +0.000 0.843 0.910 0.090 k +*u +1186.333 473.333 m +1186.278 473.278 1186.222 472.222 1186.667 472.667 c +1186.723 472.723 1186.777 473.778 1186.333 473.333 c +f +*U +0.000 0.910 0.788 0.090 k +*u +1258 473 m +1262.216 471.231 1267.459 472 1272 472 c +1267.693 474 1262.585 474.272 1258 473 c +f +*U +0.000 0.518 0.471 0.455 k +*u +1267 474 m +1268.248 473.315 1268.548 473.251 1270 473 c +1268.752 473.685 1268.452 473.749 1267 474 c +f +*U +0.000 0.263 0.263 0.341 k +*u +1270 474 m +1271 473 l +1270 474 l +f +*U +0.000 0.239 0.196 0.176 k +*u +1271 474 m +1272 473 l +1271 474 l +f +*U +0.000 0.000 0.000 0.745 k +*u +1399 474 m +1400 473 l +1399 474 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1055 473 m +1056 472 l +1055 473 l +f +*U +0.000 0.027 0.020 0.322 k +*u +1173 471 m +1176 471 l +1175 473 l +1173.365 472.455 1173.545 472.635 1173 471 c +f +*U +0.000 0.502 0.502 0.498 k +*u +1175 473 m +1176.248 472.315 1176.548 472.251 1178 472 c +1176.752 472.685 1176.451 472.749 1175 473 c +f +*U +0.000 0.973 0.914 0.027 k +*u +1178 473 m +1179.769 472.221 1181 472 1183 472 c +1181.231 472.779 1179.964 472.912 1178 473 c +f +*U +0.000 0.918 0.918 0.082 k +*u +1188.667 472.667 m +1188.222 472.222 1189.278 472.278 1189.333 472.333 c +1189.778 472.778 1188.722 472.722 1188.667 472.667 c +f +*U +0.000 1.000 1.000 0.000 k +*u +1191 473 m +1192.769 472.221 1194 472 1196 472 c +1194.231 472.779 1192.964 472.912 1191 473 c +f +*U +0.000 0.776 0.847 0.153 k +*u +1196 473 m +1198 472 1199.747 472 1202 472 c +1199.948 472.874 1198.253 472.953 1196 473 c +f +*U +0.000 1.000 1.000 0.000 k +*u +1202 473 m +1206.720 471 1212.920 472 1218 472 c +1251 472 l +1246.280 473.981 1240 473 1235 473 c +1202 473 l +f +*U +0.000 0.820 0.875 0.125 k +*u +1251 473 m +1252.769 472.221 1254 472 1256 472 c +1254.231 472.779 1252.964 472.912 1251 473 c +f +*U +0.000 0.467 0.333 0.506 k +*u +1272.667 472.667 m +1272.222 472.222 1273.278 472.278 1273.333 472.333 c +1273.778 472.778 1272.722 472.722 1272.667 472.667 c +f +*U +0.000 0.122 0.035 0.180 k +*u +1176 472 m +1184.358 468.493 1197.940 471 1207 471 c +1276 471 l +1273 472.638 1270.260 472 1267 472 c +1260.668 471.941 1254.332 472 1248 472 c +1176 472 l +f +*U +0.000 0.000 0.000 0.753 k +*u +1361 473 m +1362 472 l +1361 473 l +f +*U +0.000 0.000 0.004 0.827 k +*u +1400 473 m +1401 472 l +1400 473 l +f +*U +0.000 0.000 0.000 0.494 k +*u +1054 472 m +1055 471 l +1054 472 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1094 472 m +1095 471 l +1094 472 l +f +*U +0.000 0.000 0.000 0.471 k +*u +1362 472 m +1363 471 l +1362 472 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1053 471 m +1054 470 l +1053 471 l +f +*U +0.000 0.000 0.000 0.341 k +*u +1093 471 m +1094 470 l +1093 471 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1363 471 m +1364 470 l +1363 471 l +f +*U +0.008 0.008 0.000 0.745 k +*u +1402 471 m +1403 470 l +1402 471 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1052 470 m +1053 469 l +1052 470 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1051 469 m +1052 468 l +1051 469 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1050 468 m +1051 467 l +1050 468 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1089 468 m +1090 467 l +1089 468 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1049 467 m +1050 466 l +1049 467 l +f +*U +0.000 0.000 0.000 0.510 k +*u +1088 467 m +1089 466 l +1088 467 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1368 467 m +1369 466 l +1368 467 l +f +*U +0.000 0.000 0.008 0.765 k +*u +1406 467 m +1407 466 l +1406 467 l +f +*U +0.000 0.000 0.000 0.294 k +*u +1087 466 m +1088 465 l +1087 466 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1369 466 m +1370 465 l +1369 466 l +f +*U +0.000 0.000 0.008 0.639 k +*u +1407 466 m +1408 465 l +1407 466 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1047 465 m +1048 464 l +1047 465 l +f +*U +0.000 0.000 0.000 0.443 k +*u +1370 465 m +1371 464 l +1370 465 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1408 465 m +1409 464 l +1408 465 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1046 464 m +1047 463 l +1046 464 l +f +*U +0.000 0.000 0.000 0.251 k +*u +1371 464 m +1372 463 l +1371 464 l +f +*U +0.000 0.000 0.008 0.651 k +*u +1409 464 m +1410 463 l +1409 464 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1045 463 m +1046 462 l +1045 463 l +f +*U +0.000 0.000 0.008 0.663 k +*u +1410 463 m +1411 462 l +1410 463 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1044 462 m +1045 461 l +1044 462 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1082 462 m +1083 461 l +1082 462 l +f +*U +0.000 0.000 0.008 0.251 k +*u +1411 462 m +1412 461 l +1411 462 l +f +*U +0.000 0.000 0.000 0.729 k +*u +1043 461 m +1044 460 l +1043 461 l +f +*U +0.000 0.000 0.000 0.463 k +*u +1081 461 m +1082 460 l +1081 461 l +f +*U +0.000 0.271 0.192 0.224 k +*u +1145 461 m +1146 460 l +1145 461 l +f +*U +0.000 0.400 0.282 0.600 k +*u +1146 461 m +1152.202 458.397 1161.298 460 1168 460 c +1161.797 462.603 1152.702 461 1146 461 c +f +*U +0.000 0.569 0.451 0.431 k +*u +1168 461 m +1169.969 459.937 1171.798 459.468 1174 459 c +1171.943 460.582 1170.613 460.826 1168 461 c +f +*U +0.000 0.278 0.259 0.722 k +*u +1173 461 m +1174.249 460.315 1174.548 460.251 1176 460 c +1174.752 460.685 1174.452 460.749 1173 461 c +f +*U +0.004 0.000 0.000 0.741 k +*u +1176 461 m +1177 460 l +1176 461 l +f +*U +0.000 0.424 0.345 0.576 k +*u +1283 461 m +1288.469 458.705 1296 460 1302 460 c +1296.531 462.295 1288.901 461 1283 461 c +f +*U +0.000 0.286 0.200 0.333 k +*u +1302.667 460.667 m +1302.222 460.222 1303.278 460.278 1303.333 460.333 c +1303.778 460.778 1302.722 460.722 1302.667 460.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1411 461 m +1409.723 459 1409.723 459.915 1411 458 c +1408 459 l +1408.275 456.730 1409.181 456.721 1410 455 c +1415.614 458.509 1418 449.335 1418 445 c +1417 449 l +1414.756 443.432 1418.748 440.397 1424 440 c +1426 434 l +1428.670 434.534 1428.443 433.215 1429 436 c +1439.506 428.578 1458.445 432 1471 432 c +1574 432 l +1968 432 l +1968 415 l +1619 415 l +1552.427 415 1485.454 413 1419 416 c +1420 413 l +1418 414.486 1416 415.836 1414 417 c +1419 407 1438.511 411 1448 411 c +1549 411 l +1974 411 l +1974 435 l +1592 435 l +1481 435 l +1449 435 l +1444.596 435 1438.312 433.875 1434.184 435.603 c +1430.813 437 1428.585 441.253 1426.399 444 c +1421.695 449.910 1417 456.566 1411 461 c +f +*U +0.000 0.000 0.008 0.200 k +*u +1412 461 m +1413 460 l +1412 461 l +f +*U +0.000 0.000 0.000 0.682 k +*u +1042 460 m +1043 459 l +1042 460 l +f +*U +0.000 0.000 0.000 0.400 k +*u +1080 460 m +1081 459 l +1080 460 l +f +*U +0.000 0.153 0.137 0.180 k +*u +1143 460 m +1144 459 l +1143 460 l +f +*U +0.000 0.686 0.506 0.314 k +*u +1144 460 m +1145.248 459.315 1145.548 459.251 1147 459 c +1145.752 459.685 1145.451 459.749 1144 460 c +f +*U +0.000 0.875 0.620 0.125 k +*u +1133 452 m +1133 450 l +1143.965 447.389 1159.403 448.480 1166 459 c +1168 458.754 1169.874 458.769 1172 459 c +1168.565 460.441 1164.703 460 1161 460 c +1156 460 1150.724 460.623 1146 459.200 c +1141.257 457.771 1137.281 454.383 1133 452 c +f +*U +0.000 0.141 0.094 0.271 k +*u +1174 460 m +1175 459 l +1174 460 l +f +*U +0.000 0.671 0.498 0.329 k +*u +1283 460 m +1283.545 458.365 1283.365 458.545 1285 458 c +1285 460 l +1283 460 l +f +*U +0.000 0.863 0.624 0.133 k +*u +1284 457 m +1286 455 1287.676 452.259 1290.224 450.862 c +1297 447 1307.481 449 1315 449 c +1313.378 451.388 1312.428 453 1312 456 c +1309.291 455.352 1306.784 455 1304 455 c +1305.800 455.562 1307 455.824 1309 456 c +1304 460.863 1288.450 463.171 1284 457 c +f +*U +0.000 0.286 0.204 0.082 k +*u +1305 460 m +1306 459 l +1305 460 l +f +*U +0.000 0.000 0.000 0.612 k +*u +1041 459 m +1042 458 l +1041 459 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1079 459 m +1080 458 l +1079 459 l +f +*U +0.000 0.314 0.251 0.086 k +*u +1141 459 m +1142 458 l +1141 459 l +f +*U +0.000 0.663 0.506 0.337 k +*u +1142.667 458.667 m +1142.222 458.222 1143.278 458.278 1143.333 458.333 c +1143.778 458.778 1142.722 458.722 1142.667 458.667 c +f +*U +0.000 0.757 0.596 0.243 k +*u +1166 459 m +1165 458 l +1165 456 l +1167.364 456.482 1167.518 456.636 1168 459 c +1166 459 l +f +*U +0.000 0.545 0.431 0.455 k +*u +1169.667 458.667 m +1169.222 458.222 1170.278 458.278 1170.333 458.333 c +1170.778 458.778 1169.722 458.722 1169.667 458.667 c +f +*U +0.000 0.447 0.298 0.337 k +*u +1171 459 m +1172 458 l +1171 459 l +f +*U +0.000 0.243 0.161 0.082 k +*u +1172 459 m +1173 458 l +1172 459 l +f +*U +0.000 0.325 0.220 0.039 k +*u +1283 459 m +1284 458 l +1283 459 l +f +*U +0.000 0.549 0.380 0.329 k +*u +1305.667 458.667 m +1305.222 458.222 1306.278 458.278 1306.333 458.333 c +1306.778 458.778 1305.722 458.722 1305.667 458.667 c +f +*U +0.000 0.298 0.212 0.000 k +*u +1307 459 m +1308 458 l +1307 459 l +f +*U +0.000 0.000 0.000 0.361 k +*u +1040 458 m +1041 457 l +1040 458 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1078 458 m +1079 457 l +1078 458 l +f +*U +0.000 0.235 0.180 0.090 k +*u +1139 458 m +1140 457 l +1139 458 l +f +*U +0.000 0.749 0.565 0.251 k +*u +1139 456 m +1140.580 456.683 1140.777 456.805 1142 458 c +1140.420 457.316 1140.223 457.195 1139 456 c +f +*U +0.000 0.443 0.337 0.557 k +*u +1168 458 m +1169 457 l +1168 458 l +f +*U +0.000 0.404 0.267 0.192 k +*u +1169 458 m +1170 457 l +1169 458 l +f +*U +0.000 0.392 0.282 0.361 k +*u +1308 458 m +1309 457 l +1308 458 l +f +*U +0.000 0.000 0.000 0.722 k +*u +1378 458 m +1379 457 l +1378 458 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1039 457 m +1040 456 l +1039 457 l +f +*U +0.000 0.302 0.212 0.278 k +*u +1138 457 m +1139 456 l +1138 457 l +f +*U +0.000 0.278 0.271 0.122 k +*u +1284 457 m +1285 456 l +1284 457 l +f +*U +0.000 0.769 0.482 0.224 k +*u +1304 456 m +1306.332 455 1308.457 455 1311 455 c +1308.644 456.371 1306.743 456 1304 456 c +f +*U +0.000 0.298 0.208 0.306 k +*u +1310 457 m +1311 456 l +1310 457 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1038 456 m +1039 455 l +1038 456 l +f +*U +0.000 0.569 0.459 0.165 k +*u +1136 456 m +1137 455 l +1136 456 l +f +*U +0.000 0.741 0.506 0.259 k +*u +1136 454 m +1137.580 454.683 1137.778 454.805 1139 456 c +1137.420 455.316 1137.223 455.195 1136 454 c +f +*U +0.000 0.557 0.396 0.443 k +*u +1163.667 455.667 m +1163.222 455.222 1164.278 455.278 1164.333 455.333 c +1164.778 455.778 1163.722 455.722 1163.667 455.667 c +f +*U +0.000 0.278 0.212 0.212 k +*u +1165 456 m +1166 455 l +1165 456 l +f +*U +0.000 0.314 0.200 0.459 k +*u +1285 456 m +1286 455 l +1285 456 l +f +*U +0.000 0.596 0.396 0.404 k +*u +1286 456 m +1286 453 l +1286.696 454.554 1286.696 454.446 1286 456 c +f +*U +0.000 0.243 0.224 0.055 k +*u +1312 456 m +1313 455 l +1312 456 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1038 455 m +1033.585 449.946 1028.679 441.305 1022.826 438 c +1018.671 435.701 1011.614 437 1007 437 c +969 437 l +833 437 l +243 437 l +109 437 l +68 437 l +58.250 437 48.548 437.463 39 435 c +24.783 431.584 11 422.596 4.901 409 c +1.701 402 0.947 394.492 0 387 c +2 388.988 2.579 390 3 393 c +5 388 l +3 386.181 3.920 385.305 6 384 c +6 385.797 5.986 385.522 5 387 c +6.635 386.455 6.455 386.635 7 385 c +9 390.551 7 395.360 4 400 c +8 399 l +7.693 401 7.618 401.686 6 403 c +7.409 405.564 8.403 406.670 11 408 c +8 411 l +12 410 l +11.402 411.195 11.534 410.977 10 412 c +11.416 412.472 11.814 412.814 13 414 c +15.367 410.507 17.329 418.372 19 420 c +18.782 418.313 18.776 417.684 19 416 c +21.437 417.306 22.694 418.563 24 421 c +22.316 421.224 21.687 421.218 20 421 c +24 424.478 32 424.227 31 431 c +35.444 431.946 39.463 432.483 44 432 c +43 434 l +44.723 433 46 432.465 48 432 c +49 436 l +53 435 l +49 434 l +54.619 430.634 62.653 432 69 432 c +114 432 l +282 432 l +804 432 l +954 432 l +997 432 l +1004.677 432 1012.812 430.954 1020 434 c +1019 432 l +1022.312 432.552 1024 431.678 1028 433 c +1029 432 l +1029 434 l +1030.186 432.964 1030.604 432.661 1032 432 c +1031.548 433.863 1030.908 435.308 1030 437 c +1032 436 l +1031.454 441.569 1032.295 444.690 1036 449 c +1036 447 l +1040 450 l +1039.676 452.204 1039.433 453.328 1038 455 c +f +*U +0.000 0.192 0.114 0.153 k +*u +1134 455 m +1135 454 l +1134 455 l +f +*U +0.000 0.322 0.196 0.529 k +*u +1135 455 m +1136 454 l +1135 455 l +f +*U +0.000 0.482 0.388 0.518 k +*u +1161.667 454.667 m +1161.222 454.222 1162.278 454.278 1162.333 454.333 c +1162.778 454.777 1161.722 454.722 1161.667 454.667 c +f +*U +0.000 0.361 0.267 0.153 k +*u +1163 455 m +1164 454 l +1163 455 l +f +*U +0.000 0.369 0.357 0.475 k +*u +1312.667 454.667 m +1312.222 454.222 1313.278 454.278 1313.333 454.333 c +1313.778 454.778 1312.722 454.722 1312.667 454.667 c +f +*U +0.000 0.000 0.000 0.749 k +*u +1417 455 m +1418 454 l +1417 455 l +f +*U +0.000 0.349 0.220 0.263 k +*u +1133 454 m +1134 453 l +1133 454 l +f +*U +0.000 0.714 0.557 0.286 k +*u +1131 452 m +1133 451.590 1133.963 452 1136 453 c +1133.859 453.410 1133 452.968 1131 452 c +f +*U +0.000 0.369 0.318 0.631 k +*u +1160 454 m +1161 453 l +1160 454 l +f +*U +0.000 0.353 0.259 0.122 k +*u +1161 454 m +1162 453 l +1161 454 l +f +*U +0.000 0.812 0.600 0.188 k +*u +1312 454 m +1313.446 449.667 1316.885 449 1321 448 c +1318.952 451.731 1316 453.201 1312 454 c +f +*U +0.000 0.427 0.341 0.169 k +*u +1315 454 m +1316 453 l +1315 454 l +f +*U +0.020 0.024 0.000 0.753 k +*u +1382 454 m +1383 453 l +1382 454 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1418 454 m +1419 453 l +1418 454 l +f +*U +0.000 0.341 0.227 0.129 k +*u +1131 453 m +1132 452 l +1131 453 l +f +*U +0.000 0.533 0.388 0.345 k +*u +1157 453 m +1158.248 452.315 1158.548 452.251 1160 452 c +1158.752 452.685 1158.452 452.749 1157 453 c +f +*U +0.000 0.275 0.188 0.059 k +*u +1286 453 m +1287 452 l +1286 453 l +f +*U +0.000 0.529 0.357 0.471 k +*u +1287.333 452.333 m +1287.278 452.278 1287.222 451.222 1287.667 451.667 c +1287.723 451.723 1287.777 452.778 1287.333 452.333 c +f +*U +0.000 0.298 0.145 0.102 k +*u +1317 453 m +1318 452 l +1317 453 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1419 453 m +1420 452 l +1419 453 l +f +*U +0.000 0.282 0.188 0.310 k +*u +1130 452 m +1131 451 l +1130 452 l +f +*U +0.000 0.604 0.482 0.396 k +*u +1156 452 m +1157 451 l +1156 452 l +f +*U +0.000 0.396 0.286 0.220 k +*u +1157 452 m +1158 451 l +1157 452 l +f +*U +0.000 0.282 0.208 0.357 k +*u +1318 452 m +1319 451 l +1318 452 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1034 451 m +1035 450 l +1034 451 l +f +*U +0.000 0.435 0.239 0.094 k +*u +1128 451 m +1129 450 l +1128 451 l +f +*U +0.000 0.639 0.459 0.361 k +*u +1129.667 450.667 m +1129.222 450.222 1130.278 450.278 1130.333 450.333 c +1130.778 450.778 1129.722 450.722 1129.667 450.667 c +f +*U +0.000 0.867 0.675 0.133 k +*u +1129 450 m +1131 449 1132.747 449 1135 449 c +1132.787 450.393 1131.609 450.374 1129 450 c +f +*U +0.000 0.451 0.329 0.388 k +*u +1154.667 450.667 m +1154.222 450.222 1155.278 450.278 1155.333 450.333 c +1155.778 450.778 1154.722 450.722 1154.667 450.667 c +f +*U +0.000 0.251 0.188 0.122 k +*u +1156 451 m +1157 450 l +1156 451 l +f +*U +0.000 0.298 0.196 0.239 k +*u +1287 451 m +1288 450 l +1287 451 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1288 451 m +1289 450 l +1288 451 l +f +*U +0.000 0.608 0.443 0.341 k +*u +1289 451 m +1290.458 449.919 1291.248 449.564 1293 449 c +1291.457 450.267 1290.952 450.489 1289 451 c +f +*U +0.000 0.000 0.000 0.655 k +*u +1033 450 m +1034 449 l +1033 450 l +f +*U +0.000 0.275 0.196 0.396 k +*u +1127 450 m +1128 449 l +1127 450 l +f +*U +0.000 0.741 0.741 0.259 k +*u +1128 450 m +1131.989 445.435 1146 448 1152 448 c +1144.846 451 1135.658 448.177 1128 450 c +f +*U +0.000 0.510 0.416 0.490 k +*u +1153 450 m +1154 449 l +1153 450 l +f +*U +0.000 0.298 0.239 0.192 k +*u +1154 450 m +1155 449 l +1154 450 l +f +*U +0.000 0.208 0.169 0.141 k +*u +1290 450 m +1291 449 l +1290 450 l +f +*U +0.000 0.337 0.267 0.004 k +*u +1321 450 m +1322 449 l +1321 450 l +f +*U +0.000 0.000 0.000 0.361 k +*u +1032 449 m +1033 448 l +1032 449 l +f +*U +0.000 0.141 0.114 0.259 k +*u +1125 449 m +1126 448 l +1125 449 l +f +*U +0.000 0.271 0.271 0.729 k +*u +1126.667 448.667 m +1126.222 448.222 1127.278 448.278 1127.333 448.333 c +1127.778 448.778 1126.722 448.722 1126.667 448.667 c +f +*U +0.000 0.192 0.188 0.263 k +*u +1152 449 m +1153 448 l +1152 449 l +f +*U +0.000 0.573 0.514 0.427 k +*u +1292.667 448.667 m +1292.222 448.222 1293.278 448.278 1293.333 448.333 c +1293.778 448.778 1292.722 448.722 1292.667 448.667 c +f +*U +0.000 0.753 0.753 0.247 k +*u +1294 449 m +1301.169 445.992 1312.239 448 1320 448 c +1312.831 451 1301.761 449 1294 449 c +f +*U +0.000 0.373 0.282 0.549 k +*u +1321.667 448.667 m +1321.222 448.222 1322.278 448.278 1322.333 448.333 c +1322.778 448.778 1321.722 448.722 1321.667 448.667 c +f +*U +0.000 0.000 0.000 0.780 k +*u +1422 449 m +1423 448 l +1422 449 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1031 448 m +1032 447 l +1031 448 l +f +*U +0.094 0.000 0.027 0.216 k +*u +1294 448 m +1295.248 447.315 1295.548 447.251 1297 447 c +1295.752 447.685 1295.451 447.749 1294 448 c +f +*U +0.000 0.000 0.000 0.796 k +*u +1423 448 m +1424 447 l +1423 448 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1030 447 m +1031 446 l +1030 447 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1066 447 m +1067 446 l +1066 447 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1424 447 m +1425 446 l +1424 447 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1389 446 m +1390 445 l +1389 446 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1426 444 m +1427 443 l +1426 444 l +f +*U +0.000 0.000 0.000 0.541 k +*u +1027 443 m +1028 442 l +1027 443 l +f +*U +0.000 0.000 0.000 0.298 k +*u +1392 443 m +1393 442 l +1392 443 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1427 443 m +1428 442 l +1427 443 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1026 442 m +1027 441 l +1026 442 l +f +*U +0.000 0.000 0.000 0.545 k +*u +1393 442 m +1394 441 l +1393 442 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1428 442 m +1429 441 l +1428 442 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1025 441 m +1026 440 l +1025 441 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1394 441 m +1395 440 l +1394 441 l +f +*U +0.012 0.000 0.016 0.000 k +*u +48 440 m +52 437 l +58.834 440.647 68.400 439 76 439 c +129 439 l +322 439 l +1023 439 l +1015.841 442 1004.744 440 997 440 c +940 440 l +740 440 l +48 440 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1395 440 m +1396 439 l +1395 440 l +f +*U +0.000 0.000 0.000 0.729 k +*u +1024 439 m +1025 438 l +1024 439 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1059 439 m +1060 438 l +1059 439 l +f +*U +0.000 0.000 0.000 0.408 k +*u +1430 439 m +1431 438 l +1430 439 l +f +*U +0.000 0.000 0.000 0.004 k +*u +1439 436 m +1445.817 437.623 1453 437 1460 437 c +1495 437 l +1608 437 l +1969 437 l +1965.730 439.477 1962 439.000 1958 439 c +1939 439 l +1861 439 l +1558 439 l +1469 439 l +1448 439 l +1444.213 438.992 1441.171 439.349 1439 436 c +f +*U +0.024 0.000 0.027 0.102 k +*u +52 438 m +59 434.996 70.256 437 78 437 c +135 437 l +333 437 l +1022 437 l +1014.841 440 1003.744 438 996 438 c +939 438 l +740 438 l +52 438 l +f +*U +0.024 0.000 0.031 0.325 k +*u +1022.667 437.667 m +1022.222 437.222 1023.278 437.278 1023.333 437.333 c +1023.778 437.778 1022.722 437.722 1022.667 437.667 c +f +*U +0.000 0.000 0.000 0.200 k +*u +1058 438 m +1059 437 l +1058 438 l +f +*U +0.000 0.000 0.000 0.325 k +*u +1431 438 m +1432 437 l +1431 438 l +f +*U +0.000 0.000 0.000 0.420 k +*u +44 437 m +45 436 l +44 437 l +f +*U +0.000 0.000 0.000 0.588 k +*u +45 437 m +46 436 l +45 437 l +f +*U +0.000 0.000 0.000 0.824 k +*u +46 437 m +47 436 l +46 437 l +f +*U +0.000 0.000 0.000 0.263 k +*u +1057 437 m +1058 436 l +1057 437 l +f +*U +0.000 0.224 0.169 0.035 k +*u +1110 437 m +1111 436 l +1110 437 l +f +*U +0.000 0.529 0.408 0.471 k +*u +1111 437 m +1117.584 434.237 1125.949 436.679 1133 435 c +1129.196 439.354 1116.561 437 1111 437 c +f +*U +0.000 0.373 0.271 0.592 k +*u +1133.667 436.667 m +1133.222 436.222 1134.278 436.278 1134.333 436.333 c +1134.778 436.778 1133.722 436.722 1133.667 436.667 c +f +*U +0.000 0.514 0.420 0.486 k +*u +1298 435 m +1307.524 437.267 1318.247 436 1328 436 c +1321.814 438.596 1312.678 437 1306 437 c +1302.895 436.994 1300 437.407 1298 435 c +f +*U +0.000 0.604 0.486 0.396 k +*u +1328 437 m +1331.366 435.584 1335.373 435.673 1339 435 c +1335.734 437.474 1331.990 437.000 1328 437 c +f +*U +0.000 0.000 0.000 0.537 k +*u +40 436 m +41 435 l +40 436 l +f +*U +0.004 0.000 0.004 0.996 k +*u +57 436 m +63.919 433 74.520 435 82 435 c +139 435 l +335 435 l +1015 435 l +1008 437.903 997.480 436 990 436 c +933 436 l +737 436 l +57 436 l +f +*U +0.000 0.000 0.000 0.475 k +*u +1056 436 m +1057 435 l +1056 436 l +f +*U +0.000 0.263 0.204 0.357 k +*u +1109 436 m +1110 435 l +1109 436 l +f +*U +0.000 0.545 0.447 0.455 k +*u +1110 436 m +1111 435 l +1110 436 l +f +*U +0.000 0.863 0.604 0.137 k +*u +1106 427 m +1101 427 l +1101 425 l +1121 425 l +1123.329 429.352 1128.185 431.948 1132 435 c +1124.775 438 1104.947 438.189 1106 427 c +f +*U +0.000 0.353 0.259 0.176 k +*u +1133 436 m +1134 435 l +1133 436 l +f +*U +0.000 0.875 0.624 0.125 k +*u +1299 436 m +1298.808 431.871 1297.540 428.769 1296 425 c +1348 425 l +1338.944 441.346 1314.725 436 1299 436 c +f +*U +0.000 0.173 0.157 0.192 k +*u +1339 436 m +1340 435 l +1339 436 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1398 436 m +1399 435 l +1398 436 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1432 436 m +1433 435 l +1432 436 l +f +*U +0.000 0.000 0.000 0.451 k +*u +36 435 m +37 434 l +36 435 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1055 435 m +1056 434 l +1055 435 l +f +*U +0.000 0.282 0.239 0.176 k +*u +1108 435 m +1109 434 l +1108 435 l +f +*U +0.000 0.506 0.431 0.494 k +*u +1131 435 m +1132 434 l +1131 435 l +f +*U +0.000 0.227 0.176 0.122 k +*u +1132 435 m +1133 434 l +1132 435 l +f +*U +0.000 0.518 0.475 0.090 k +*u +1298.333 434.333 m +1298.278 434.278 1298.222 433.222 1298.667 433.667 c +1298.723 433.723 1298.777 434.777 1298.333 434.333 c +f +*U +0.000 0.725 0.549 0.275 k +*u +1339 435 m +1340.324 432.313 1341.313 431.324 1344 430 c +1342.451 432 1341 433.451 1339 435 c +f +*U +0.000 0.294 0.224 0.098 k +*u +1340 435 m +1341 434 l +1340 435 l +f +*U +0.000 0.000 0.000 0.475 k +*u +1399 435 m +1400 434 l +1399 435 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1974 435 m +1974 410 l +1976.413 415.750 1976.413 429.250 1974 435 c +f +*U +0.000 0.000 0.000 0.400 k +*u +33 434 m +34 433 l +33 434 l +f +*U +0.000 0.000 0.000 0.988 k +*u +55 434 m +61.919 431 72.520 433 80 433 c +137 433 l +334 433 l +1016 433 l +1009 435.903 998.480 434 991 434 c +934 434 l +737 434 l +55 434 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1054 434 m +1055 433 l +1054 434 l +f +*U +0.000 0.416 0.325 0.133 k +*u +1107 434 m +1108 433 l +1107 434 l +f +*U +0.000 0.529 0.392 0.318 k +*u +1129 434 m +1129 432 l +1130.635 432.545 1130.455 432.365 1131 434 c +1129 434 l +f +*U +0.000 0.294 0.235 0.220 k +*u +1341 434 m +1342 433 l +1341 434 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1400 434 m +1401 433 l +1400 434 l +f +*U +0.000 0.000 0.000 0.220 k +*u +30 433 m +31 432 l +30 433 l +f +*U +0.000 0.000 0.000 0.592 k +*u +31 433 m +32 432 l +31 433 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1053 433 m +1054 432 l +1053 433 l +f +*U +0.000 0.349 0.282 0.247 k +*u +1106 433 m +1107 432 l +1106 433 l +f +*U +0.000 0.514 0.369 0.427 k +*u +1298 433 m +1298 430 l +1298.696 431.554 1298.696 431.446 1298 433 c +f +*U +0.000 0.227 0.200 0.263 k +*u +1342 433 m +1343 432 l +1342 433 l +f +*U +0.000 0.000 0.000 0.384 k +*u +28 432 m +29 431 l +28 432 l +f +*U +0.000 0.412 0.314 0.208 k +*u +1105 432 m +1106 431 l +1105 432 l +f +*U +0.063 0.000 0.012 0.275 k +*u +1128 432 m +1129 431 l +1128 432 l +f +*U +0.000 0.624 0.522 0.067 k +*u +1343 432 m +1344 431 l +1343 432 l +f +*U +0.000 0.000 0.000 0.349 k +*u +26 431 m +27 430 l +26 431 l +f +*U +0.000 0.753 0.576 0.235 k +*u +1104 431 m +1102 427 l +1106 427 l +1106 431 l +1104 431 l +f +*U +0.000 0.478 0.349 0.416 k +*u +1124 428 m +1125.457 429 1125.897 429.543 1127 431 c +1124.876 430 1124.899 430 1124 428 c +f +*U +0.000 0.188 0.149 0.082 k +*u +1127 431 m +1128 430 l +1127 431 l +f +*U +0.000 0.137 0.145 0.412 k +*u +1344 431 m +1345 430 l +1344 431 l +f +*U +0.000 0.000 0.000 0.239 k +*u +24 430 m +25 429 l +24 430 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1051 430 m +1052 429 l +1051 430 l +f +*U +0.000 0.400 0.227 0.310 k +*u +1103 430 m +1104 429 l +1103 430 l +f +*U +0.000 0.263 0.216 0.090 k +*u +1297 430 m +1298 429 l +1297 430 l +f +*U +0.000 0.369 0.306 0.271 k +*u +1345 430 m +1346 429 l +1345 430 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1403 430 m +1404 429 l +1403 430 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1050 429 m +1051 428 l +1050 429 l +f +*U +0.000 0.553 0.455 0.447 k +*u +1297.333 428.333 m +1297.278 428.278 1297.222 427.222 1297.667 427.667 c +1297.722 427.722 1297.778 428.778 1297.333 428.333 c +f +*U +0.000 0.314 0.369 0.192 k +*u +1346 429 m +1347 428 l +1346 429 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1404 429 m +1405 428 l +1404 429 l +f +*U +0.000 0.000 0.000 0.451 k +*u +21 428 m +22 427 l +21 428 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1049 428 m +1050 427 l +1049 428 l +f +*U +0.000 0.325 0.267 0.298 k +*u +1101 428 m +1102 427 l +1101 428 l +f +*U +0.000 0.686 0.518 0.306 k +*u +1121 428 m +1121 426 l +1122.635 426.545 1122.455 426.365 1123 428 c +1121 428 l +f +*U +0.000 0.365 0.294 0.259 k +*u +1123 428 m +1124 427 l +1123 428 l +f +*U +0.000 0.227 0.192 0.086 k +*u +1296 428 m +1297 427 l +1296 428 l +f +*U +0.000 0.325 0.212 0.282 k +*u +1347 428 m +1348 427 l +1347 428 l +f +*U +0.000 0.412 0.325 0.341 k +*u +1100 427 m +1101 426 l +1100 427 l +f +*U +0.000 0.310 0.263 0.204 k +*u +1122 427 m +1123 426 l +1122 427 l +f +*U +0.000 0.420 0.392 0.580 k +*u +1347 427 m +1348 426 l +1347 427 l +f +*U +0.000 0.220 0.235 0.239 k +*u +1348 427 m +1349 426 l +1348 427 l +f +*U +0.000 0.000 0.000 0.188 k +*u +18 426 m +19 425 l +18 426 l +f +*U +0.000 0.349 0.263 0.290 k +*u +1099 426 m +1100 425 l +1099 426 l +f +*U +0.000 0.533 0.482 0.467 k +*u +1099 425 m +1100.769 424.221 1102 424 1104 424 c +1102 425 1101.229 425 1099 425 c +f +*U +0.000 0.357 0.255 0.192 k +*u +1121 426 m +1122 425 l +1121 426 l +f +*U +0.000 0.173 0.125 0.329 k +*u +1295 426 m +1296 425 l +1295 426 l +f +*U +0.000 0.592 0.471 0.408 k +*u +1303 425 m +1307.720 423 1313.920 424 1319 424 c +1350 424 l +1346.182 426.207 1340.402 425 1336 425 c +1303 425 l +f +*U +0.000 0.278 0.247 0.239 k +*u +1349 426 m +1350 425 l +1349 426 l +f +*U +0.000 0.000 0.000 0.275 k +*u +1406 426 m +1407 425 l +1406 426 l +f +*U +0.000 0.000 0.000 0.773 k +*u +17 425 m +18 424 l +17 425 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1047 425 m +1048 424 l +1047 425 l +f +*U +0.000 0.192 0.161 0.447 k +*u +1098 425 m +1099 424 l +1098 425 l +f +*U +0.000 0.616 0.518 0.384 k +*u +1104 425 m +1108.724 423 1114.910 424 1120 424 c +1115.276 425.982 1109 425 1104 425 c +f +*U +0.000 0.082 0.051 0.380 k +*u +1120 425 m +1121 424 l +1120 425 l +f +*U +0.000 0.239 0.180 0.576 k +*u +1294 425 m +1295 424 l +1294 425 l +f +*U +0.000 0.400 0.400 0.600 k +*u +1295 425 m +1297.613 423.902 1300 424 1303 424 c +1300.387 425 1297.836 424.993 1295 425 c +f +*U +0.000 0.239 0.129 0.278 k +*u +1350 425 m +1351 424 l +1350 425 l +f +*U +0.000 0.000 0.004 0.361 k +*u +1407 425 m +1408 424 l +1407 425 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1046 424 m +1047 423 l +1046 424 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1045 423 m +1046 422 l +1045 423 l +f +*U +0.008 0.008 0.000 0.200 k +*u +1409 422 m +1410 421 l +1409 422 l +f +*U +0.008 0.008 0.000 0.643 k +*u +1410 421 m +1411 420 l +1410 421 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1043 420 m +1044 419 l +1043 420 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1042 419 m +1043 418 l +1042 419 l +f +*U +0.000 0.000 0.000 0.792 k +*u +10 418 m +11 417 l +10 418 l +f +*U +0.008 0.008 0.000 0.494 k +*u +1412 418 m +1413 417 l +1412 418 l +f +*U +0.000 0.000 0.000 0.533 k +*u +9 417 m +10 416 l +9 417 l +f +*U +0.000 0.000 0.000 1.000 k +*u +56 416 m +63 412.996 74.256 415 82 415 c +139 415 l +337 415 l +1024 415 l +1014.317 412 1002 414 992 414 c +927 414 l +713 414 l +287 414 l +150 414 l +120.557 414 90.368 412 61 414 c +56.305 414.375 51.748 415.650 47 416 c +48 414 l +46.365 414.545 46.545 414.365 46 416 c +42 415 l +42 413.203 42 413.479 43 412 c +40.734 411.657 38.346 411.382 40 414 c +39 412 l +40.618 413.314 40.693 413.877 41 416 c +38.711 415.239 35.767 414.630 34.328 412.490 c +32 409.247 33.743 405.592 29 405 c +29 399 l +27 404 l +24 404 l +24.768 402.686 24.686 402.768 26 402 c +24 399 24.308 396.349 24 393 c +25.267 391.457 25.489 390.952 26 389 c +25 391 l +21.895 383.601 24 372 24 364 c +24 305 l +15.957 305 7.998 305.609 0 305 c +7.409 301.891 18.975 304 27 304 c +27 371 l +27 381.888 25.902 394 33.380 402.960 c +41.502 412.660 53.403 413 65 413 c +101 413 l +286 413 l +823 413 l +974 413 l +1015 413 l +1024 413 1032.654 412 1041 416 c +1038.167 416.926 1036.303 415.540 1033.424 415.394 c +1027 415 1020.376 416 1014 416 c +952 416 l +745 416 l +56 416 l +f +*U +0.000 0.000 0.000 0.212 k +*u +8 416 m +9 415 l +8 416 l +f +*U +0.024 0.024 0.000 0.976 k +*u +1424 416 m +1428.720 414 1434.920 415 1440 415 c +1472 415 l +1583 415 l +1968 415 l +1963.280 416.981 1957 416 1952 416 c +1921 416 l +1810 416 l +1424 416 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1037 415 m +1038 414 l +1037 415 l +f +*U +0.000 0.000 0.000 0.298 k +*u +1038 415 m +1039 414 l +1038 415 l +f +*U +0.008 0.000 0.012 0.988 k +*u +1422 415 m +1425.691 412.204 1430.515 413 1435 413 c +1461 413 l +1566 413 l +1969 413 l +1964.785 414.769 1959.536 414 1955 414 c +1926 414 l +1825 414 l +1555 414 l +1469 414 l +1453.686 414 1437 412.200 1422 415 c +f +*U +0.000 0.000 0.000 0.647 k +*u +7 414 m +8 413 l +7 414 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1035 414 m +1036 413 l +1035 414 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1036 414 m +1037 413 l +1036 414 l +f +*U +0.000 0.255 0.075 0.110 k +*u +1089 414 m +1093.471 412 1099.183 413 1104 413 c +1099.529 414.876 1093.817 414 1089 414 c +f +*U +0.000 0.361 0.220 0.047 k +*u +1104 414 m +1105.769 413.221 1107 413 1109 413 c +1107.231 413.779 1105.964 413.912 1104 414 c +f +*U +0.000 0.251 0.063 0.114 k +*u +1298 414 m +1303.217 411.811 1310.381 413 1316 413 c +1352 413 l +1346.784 415.189 1339.619 414 1334 414 c +1298 414 l +f +*U +0.000 0.231 0.161 0.118 k +*u +1352 414 m +1354.613 412.902 1357 413 1360 413 c +1357.387 414 1354.836 413.993 1352 414 c +f +*U +0.000 0.000 0.000 0.173 k +*u +1415 414 m +1416 413 l +1415 414 l +f +*U +0.000 0.000 0.000 0.239 k +*u +6 413 m +7 412 l +6 413 l +f +*U +0.000 0.000 0.000 0.812 k +*u +50 413 m +51 412 l +50 413 l +f +*U +0.000 0.000 0.000 0.490 k +*u +51 413 m +58 409.996 69.256 412 77 412 c +135 412 l +336 412 l +1033 412 l +1025.841 415 1014.744 413 1007 413 c +949 413 l +748 413 l +51 413 l +f +*U +0.000 0.690 0.486 0.310 k +*u +1088 413 m +1088 411 l +1090 411 l +1089.455 412.635 1089.635 412.455 1088 413 c +f +*U +0.000 0.733 0.722 0.267 k +*u +1089.667 412.667 m +1089.222 412.222 1090.278 412.278 1090.333 412.333 c +1090.778 412.778 1089.722 412.722 1089.667 412.667 c +f +*U +0.000 0.800 0.875 0.125 k +*u +1091 413 m +1095.724 411 1101.910 412 1107 412 c +1102.276 413.982 1096 413 1091 413 c +f +*U +0.000 0.475 0.525 0.475 k +*u +1107 413 m +1108 412 l +1107 413 l +f +*U +0.000 0.227 0.302 0.259 k +*u +1108 413 m +1109 412 l +1108 413 l +f +*U +0.000 0.565 0.420 0.396 k +*u +1298 413 m +1298 408 l +1298.830 410 1298.830 410.970 1298 413 c +f +*U +0.000 0.773 0.855 0.145 k +*u +1299 413 m +1303.969 410.915 1310.650 412 1316 412 c +1352 412 l +1347 414 1340.350 413 1335 413 c +1299 413 l +f +*U +0.000 0.859 0.612 0.137 k +*u +1352 413 m +1354 412 1355.747 412 1358 412 c +1358 410 l +1315 410 l +1306 410 1296.397 408.986 1291 401 c +1294.474 401.231 1297.560 402.704 1301 402.946 c +1314.869 403.916 1329 403 1343 403 c +1346.604 403 1358.640 401 1360.824 404.545 c +1363.322 408.491 1353.592 407.999 1352 408 c +1355.590 409 1358.703 408.815 1361 412 c +1357.959 412.900 1355.169 412.992 1352 413 c +f +*U +0.000 0.278 0.180 0.345 k +*u +1360 413 m +1361 412 l +1360 413 l +f +*U +0.000 0.000 0.000 0.525 k +*u +1417 413 m +1418 412 l +1417 413 l +f +*U +0.000 0.000 0.000 0.686 k +*u +46 412 m +47 411 l +46 412 l +f +*U +0.000 0.000 0.000 0.192 k +*u +47 412 m +48 411 l +47 412 l +f +*U +0.000 0.235 0.149 0.337 k +*u +1087 412 m +1088 411 l +1087 412 l +f +*U +0.000 0.851 0.596 0.141 k +*u +1082 401 m +1086.620 401 1093.403 399.742 1097.696 401.603 c +1100.704 402.908 1102.175 406.339 1105 408 c +1103.272 413.208 1093.657 413.509 1089.299 410.825 c +1086.243 408.943 1083.492 404 1082 401 c +f +*U +0.000 0.808 0.718 0.173 k +*u +1104 412 m +1105 410 l +1106.635 410.545 1106.455 410.365 1107 412 c +1104 412 l +f +*U +0.000 0.286 0.275 0.235 k +*u +1107 412 m +1108 411 l +1107 412 l +f +*U +0.000 0.925 0.663 0.075 k +*u +1299 412 m +1299 408 l +1318.474 410.576 1338.184 410 1358 410 c +1358 412 l +1338.254 411.592 1318.764 410.440 1299 412 c +f +*U +0.000 0.843 0.580 0.157 k +*u +1303 412 m +1307.720 410 1313.920 411 1319 411 c +1352 411 l +1347.280 412.981 1341 412 1336 412 c +1303 412 l +f +*U +0.000 0.263 0.173 0.157 k +*u +1361 412 m +1362 411 l +1361 412 l +f +*U +0.000 0.000 0.000 0.541 k +*u +1419 412 m +1420 411 l +1419 412 l +f +*U +0.000 0.000 0.000 0.341 k +*u +5 411 m +6 410 l +5 411 l +f +*U +0.000 0.000 0.000 0.624 k +*u +43 411 m +44 410 l +43 411 l +f +*U +0.000 0.365 0.243 0.173 k +*u +1086 411 m +1087 410 l +1086 411 l +f +*U +0.000 0.471 0.337 0.529 k +*u +1087 411 m +1088 410 l +1087 411 l +f +*U +0.000 0.333 0.310 0.275 k +*u +1106 411 m +1107 410 l +1106 411 l +f +*U +0.000 0.910 0.663 0.090 k +*u +1360 411 m +1357.440 409 1355.192 409 1352 409 c +1356.775 406.991 1359.915 407.950 1363 403 c +1296 403 l +1296 401 l +1367 401 l +1365 404.706 1362.922 408 1360 411 c +f +*U +0.000 0.702 0.498 0.298 k +*u +1361 411 m +1361.683 409.420 1361.805 409.223 1363 408 c +1362.316 409.580 1362.195 409.777 1361 411 c +f +*U +0.000 0.000 0.000 0.188 k +*u +1422 411 m +1423 410 l +1422 411 l +f +*U +0.055 0.063 0.000 0.580 k +*u +1423 411 m +1427.720 409 1433.920 410 1439 410 c +1471 410 l +1583 410 l +1974 410 l +1969.280 411.981 1963 411 1958 411 c +1926 411 l +1813 411 l +1423 411 l +f +*U +0.000 0.000 0.000 0.365 k +*u +41 410 m +42 409 l +41 410 l +f +*U +0.000 0.000 0.000 0.004 k +*u +56 410 m +56 408 l +1032 408 l +1023.793 411.476 1012.764 410 1004 410 c +947 410 l +748 410 l +56 410 l +f +*U +0.000 0.631 0.427 0.369 k +*u +1086 410 m +1085 408.521 1085 408.797 1085 407 c +1086.289 408.443 1086.401 408.234 1086 410 c +f +*U +0.000 0.506 0.247 0.275 k +*u +1105 410 m +1106 409 l +1105 410 l +f +*U +0.000 0.000 0.000 0.200 k +*u +4 409 m +5 408 l +4 409 l +f +*U +0.000 0.000 0.000 0.592 k +*u +39 409 m +40 408 l +39 409 l +f +*U +0.000 0.278 0.165 0.071 k +*u +1297 409 m +1298 408 l +1297 409 l +f +*U +0.000 0.325 0.208 0.306 k +*u +1363 409 m +1364 408 l +1363 409 l +f +*U +0.008 0.008 0.000 0.827 k +*u +35 408 m +36 407 l +35 408 l +f +*U +0.000 0.259 0.302 0.329 k +*u +1084 408 m +1085 407 l +1084 408 l +f +*U +0.000 0.776 0.627 0.071 k +*u +1086 408 m +1085 406 l +1087 406 l +1087 407.853 1087.300 407.350 1086 408 c +f +*U +0.000 0.565 0.439 0.435 k +*u +1102 408 m +1102 406 l +1103.635 406.545 1103.455 406.365 1104 408 c +1102 408 l +f +*U +0.000 0.635 0.486 0.051 k +*u +1296 408 m +1297 407 l +1296 408 l +f +*U +0.000 0.741 0.549 0.239 k +*u +1295 407 m +1297 406.249 1297.596 406.344 1299 408 c +1295 407 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1363.333 407.333 m +1363.278 407.278 1363.222 406.222 1363.667 406.667 c +1363.722 406.723 1363.777 407.778 1363.333 407.333 c +f +*U +0.000 0.204 0.180 0.145 k +*u +1364 408 m +1365 407 l +1364 408 l +f +*U +0.000 0.000 0.000 0.216 k +*u +3 407 m +4 406 l +3 407 l +f +*U +0.008 0.008 0.000 0.737 k +*u +36 407 m +37 406 l +36 407 l +f +*U +0.000 0.447 0.404 0.475 k +*u +1084 407 m +1085 406 l +1084 407 l +f +*U +0.000 0.341 0.224 0.145 k +*u +1294 407 m +1295 406 l +1294 407 l +f +*U +0.000 0.427 0.325 0.573 k +*u +1364 407 m +1365 406 l +1364 407 l +f +*U +0.000 0.000 0.000 0.678 k +*u +3 406 m +4 405 l +3 406 l +f +*U +0.008 0.008 0.000 0.192 k +*u +35 406 m +36 405 l +35 406 l +f +*U +0.000 0.733 0.557 0.267 k +*u +1083 406 m +1083 404 l +1084.635 404.545 1084.455 404.365 1085 406 c +1083 406 l +f +*U +0.000 0.278 0.204 0.063 k +*u +1102 406 m +1103 405 l +1102 406 l +f +*U +0.000 0.337 0.243 0.286 k +*u +1293 406 m +1294 405 l +1293 406 l +f +*U +0.000 0.584 0.451 0.416 k +*u +1365 406 m +1365.406 403.908 1365.217 403.980 1367 403 c +1366.309 404.388 1366 404.861 1365 406 c +f +*U +0.000 0.000 0.000 0.345 k +*u +34 405 m +35 404 l +34 405 l +f +*U +0.000 0.361 0.290 0.278 k +*u +1082 405 m +1083 404 l +1082 405 l +f +*U +0.000 0.325 0.235 0.184 k +*u +1101 405 m +1102 404 l +1101 405 l +f +*U +0.000 0.694 0.561 0.306 k +*u +1292 405 m +1292 403 l +1293.635 403.545 1293.455 403.365 1294 405 c +1292 405 l +f +*U +0.000 0.263 0.208 0.259 k +*u +1366 405 m +1367 404 l +1366 405 l +f +*U +0.000 0.000 0.000 0.173 k +*u +2 404 m +3 403 l +2 404 l +f +*U +0.000 0.000 0.000 0.314 k +*u +33 404 m +34 403 l +33 404 l +f +*U +0.000 0.255 0.220 0.094 k +*u +1081 404 m +1082 403 l +1081 404 l +f +*U +0.000 0.545 0.467 0.455 k +*u +1082 404 m +1083 403 l +1082 404 l +f +*U +0.000 0.353 0.255 0.227 k +*u +1100 404 m +1101 403 l +1100 404 l +f +*U +0.000 0.365 0.302 0.635 k +*u +1291 404 m +1292 403 l +1291 404 l +f +*U +0.000 0.733 0.573 0.267 k +*u +1361.667 403.667 m +1361.222 403.222 1362.278 403.278 1362.333 403.333 c +1362.778 403.778 1361.722 403.722 1361.667 403.667 c +f +*U +0.000 0.000 0.000 0.671 k +*u +2 403 m +3 402 l +2 403 l +f +*U +0.000 0.000 0.008 0.792 k +*u +32 403 m +33 402 l +32 403 l +f +*U +0.000 0.400 0.271 0.545 k +*u +1081 403 m +1080 400 l +1083 400 l +1082.309 401.388 1082 401.861 1081 403 c +f +*U +0.000 0.376 0.302 0.424 k +*u +1099 403 m +1100 402 l +1099 403 l +f +*U +0.000 0.612 0.490 0.388 k +*u +1289 400 m +1303 400 l +1300.722 402.278 1294.392 399.965 1291 402 c +1292 403 l +1289.876 402 1289.899 402 1289 400 c +f +*U +0.000 0.686 0.498 0.294 k +*u +1366 403 m +1366.000 400.649 1365.347 401 1363 401 c +1365.388 399.631 1369.689 400.928 1366 403 c +f +*U +0.000 0.412 0.247 0.239 k +*u +1080 402 m +1081 401 l +1080 402 l +f +*U +0.000 0.380 0.286 0.149 k +*u +1288 402 m +1289 401 l +1288 402 l +f +*U +0.000 0.137 0.086 0.369 k +*u +1368 402 m +1369 401 l +1368 402 l +f +*U +0.000 0.000 0.000 0.267 k +*u +31 401 m +32 400 l +31 401 l +f +*U +0.031 0.000 0.016 0.078 k +*u +1078.667 400.667 m +1078.222 400.222 1079.278 400.278 1079.333 400.333 c +1079.778 400.778 1078.722 400.722 1078.667 400.667 c +f +*U +0.000 0.596 0.439 0.400 k +*u +1083 401 m +1087.471 399 1093.183 400 1098 400 c +1093.529 401.876 1087.817 401 1083 401 c +f +*U +0.031 0.000 0.008 0.455 k +*u +1287 401 m +1288 400 l +1287 401 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1288 401 m +1289 400 l +1288 401 l +f +*U +0.000 0.522 0.400 0.447 k +*u +1303 401 m +1308.463 398.708 1316 400 1322 400 c +1363 400 l +1357.537 402.292 1349.887 401 1344 401 c +1303 401 l +f +*U +0.000 0.243 0.161 0.733 k +*u +1368 401 m +1369 400 l +1368 401 l +f +*U +0.000 0.000 0.000 0.545 k +*u +1 400 m +2 399 l +1 400 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1 399 m +2 398 l +1 399 l +f +*U +0.000 0.000 0.000 0.196 k +*u +30 399 m +31 398 l +30 399 l +f +*U +0.000 0.000 0.000 0.831 k +*u +29 398 m +30 397 l +29 398 l +f +*U +0.000 0.000 0.000 0.322 k +*u +29 397 m +30 396 l +29 397 l +f +*U +0.000 0.000 0.000 0.467 k +*u +0 395 m +0 392 l +0.696 393.554 0.696 393.446 0 395 c +f +*U +0.000 0.000 0.000 0.812 k +*u +28 395 m +29 394 l +28 395 l +f +*U +0.000 0.000 0.000 0.306 k +*u +28 394 m +29 393 l +28 394 l +f +*U +0.000 0.000 0.000 0.859 k +*u +0.333 391.333 m +0.278 391.278 0.222 390.222 0.667 390.667 c +0.722 390.722 0.778 391.778 0.333 391.333 c +f +*U +0.000 0.357 0.333 0.149 k +*u +1073 390 m +1077.974 387.913 1084.638 389 1090 389 c +1085 391 1078.362 390 1073 390 c +f +*U +0.000 0.329 0.247 0.192 k +*u +1285 390 m +1287.613 388.902 1290 389 1293 389 c +1290.387 390 1287.835 389.993 1285 390 c +f +*U +0.000 0.192 0.102 0.114 k +*u +1293.333 389.333 m +1293.278 389.278 1293.222 388.222 1293.667 388.667 c +1293.722 388.722 1293.778 389.778 1293.333 389.333 c +f +*U +0.000 0.369 0.329 0.137 k +*u +1295 388 m +1304.222 390.196 1314.559 389 1324 389 c +1376 389 l +1370.293 391.395 1362 390 1356 390 c +1314 390 l +1308.940 390 1298.508 392 1295 388 c +f +*U +0.000 0.000 0.000 0.812 k +*u +27 389 m +27 304 l +29.395 309.707 28 317.846 28 324 c +28 367 l +28 373.686 29.599 382.806 27 389 c +f +*U +0.000 0.875 0.612 0.125 k +*u +1072 389 m +1070 378 l +1083 378 l +1084 382 1086.260 385.235 1088 389 c +1072 389 l +f +*U +0.000 0.325 0.286 0.475 k +*u +1088 389 m +1088 387 l +1089.635 387.545 1089.455 387.365 1090 389 c +1088 389 l +f +*U +0.000 0.224 0.165 0.286 k +*u +1284 389 m +1285 388 l +1284 389 l +f +*U +0.000 0.635 0.514 0.365 k +*u +1285 389 m +1285 384 l +1285.830 386 1285.830 386.970 1285 389 c +f +*U +0.000 0.824 0.627 0.176 k +*u +1286 389 m +1287.506 388.317 1288.315 388.174 1290 388 c +1289.776 386.316 1289.782 385.687 1290 384 c +1291.255 385.751 1291.614 386.857 1292 389 c +1286 389 l +f +*U +0.000 0.490 0.478 0.510 k +*u +1292 389 m +1293 388 l +1292 389 l +f +*U +0.000 0.678 0.475 0.322 k +*u +1296 389 m +1296.477 385.223 1296 379.552 1299 377 c +1298 381 1298.405 385.480 1296 389 c +f +*U +0.000 0.831 0.643 0.169 k +*u +1297 387 m +1305.923 389 1315.866 388 1325 388 c +1376 388 l +1370.537 390.292 1362.887 389 1357 389 c +1316 389 l +1310.940 389 1300.508 391 1297 387 c +f +*U +0.000 0.165 0.114 0.204 k +*u +1376 389 m +1377 388 l +1376 389 l +f +*U +0.000 0.259 0.192 0.082 k +*u +1284 388 m +1285 387 l +1284 388 l +f +*U +0.000 0.882 0.620 0.118 k +*u +1286 388 m +1285 379 l +1283.814 380 1283.396 380.339 1282 381 c +1282.576 378.313 1284.968 376.798 1287.361 379.333 c +1289.461 381.558 1289.624 385 1290 388 c +1286 388 l +f +*U +0.000 0.341 0.302 0.243 k +*u +1292 388 m +1293 387 l +1292 388 l +f +*U +0.000 0.859 0.620 0.141 k +*u +1298 388 m +1299 382 l +1303 384 l +1303.640 378.907 1315.759 381 1320 381 c +1376 381 l +1369.564 383.701 1359.951 382 1353 382 c +1304 382 l +1311.717 384.281 1320.982 383 1329 383 c +1378 383 l +1374.413 390.540 1364.181 388 1357 388 c +1298 388 l +f +*U +0.000 0.565 0.427 0.435 k +*u +1376.333 387.333 m +1376.278 387.278 1376.222 386.222 1376.667 386.667 c +1376.722 386.722 1376.777 387.778 1376.333 387.333 c +f +*U +0.000 0.337 0.216 0.373 k +*u +1071 387 m +1072 386 l +1071 387 l +f +*U +0.000 0.588 0.451 0.412 k +*u +1086 387 m +1086 385 l +1087.635 385.545 1087.455 385.365 1088 387 c +1086 387 l +f +*U +0.000 0.388 0.290 0.122 k +*u +1377 387 m +1378 386 l +1377 387 l +f +*U +0.000 0.290 0.196 0.043 k +*u +1070 386 m +1071 385 l +1070 386 l +f +*U +0.000 0.667 0.447 0.333 k +*u +1071.333 385.333 m +1071.278 385.278 1071.222 384.222 1071.667 384.667 c +1071.722 384.723 1071.777 385.778 1071.333 385.333 c +f +*U +0.000 0.408 0.306 0.263 k +*u +1087 386 m +1088 385 l +1087 386 l +f +*U +0.000 0.278 0.188 0.106 k +*u +1291 386 m +1292 385 l +1291 386 l +f +*U +0.000 0.498 0.400 0.133 k +*u +1296 386 m +1297 385 l +1296 386 l +f +*U +0.000 0.620 0.459 0.380 k +*u +1377.333 385.333 m +1377.278 385.278 1377.222 384.222 1377.667 384.667 c +1377.722 384.723 1377.777 385.778 1377.333 385.333 c +f +*U +0.000 0.333 0.224 0.341 k +*u +1070 385 m +1071 384 l +1070 385 l +f +*U +0.000 0.435 0.333 0.420 k +*u +1085.667 384.667 m +1085.222 384.222 1086.278 384.278 1086.333 384.333 c +1086.778 384.778 1085.722 384.722 1085.667 384.667 c +f +*U +0.000 0.114 0.090 0.271 k +*u +1284 385 m +1285 384 l +1284 385 l +f +*U +0.000 0.404 0.369 0.004 k +*u +1296 385 m +1297 384 l +1296 385 l +f +*U +0.000 0.196 0.157 0.290 k +*u +1378 385 m +1379 384 l +1378 385 l +f +*U +0.000 0.396 0.263 0.000 k +*u +1069 384 m +1070 383 l +1069 384 l +f +*U +0.000 0.800 0.596 0.200 k +*u +1070 384 m +1069 381 1068.635 379 1071 377 c +1070 384 l +f +*U +0.000 0.698 0.522 0.302 k +*u +1084 384 m +1084 381 l +1084.696 382.554 1084.696 382.446 1084 384 c +f +*U +0.000 0.349 0.298 0.651 k +*u +1085 384 m +1086 383 l +1085 384 l +f +*U +0.000 0.086 0.075 0.169 k +*u +1086 384 m +1087 383 l +1086 384 l +f +*U +0.000 0.773 0.600 0.227 k +*u +1283 384 m +1281.511 381.696 1280 379.503 1279 377 c +1282.306 377 1285.727 376.399 1288 379 c +1284.966 378.476 1283.720 378.400 1282 381 c +1285 379 l +1285.481 381.201 1285.481 381.799 1285 384 c +1283 384 l +f +*U +0.000 0.620 0.522 0.345 k +*u +1289 384 m +1288 380 l +1289.303 381.668 1289.553 381.992 1289 384 c +f +*U +0.000 0.412 0.318 0.318 k +*u +1290 384 m +1291 383 l +1290 384 l +f +*U +0.000 0.890 0.627 0.106 k +*u +1298 384 m +1298 378 l +1378 378 l +1378 383 l +1304 383 l +1310.436 380.299 1320 382 1327 382 c +1376 382 l +1370.309 379.919 1363 381 1357 381 c +1320 381 l +1315.950 381 1303.743 378.929 1303 384 c +1300.987 383.499 1299.961 383.363 1298 384 c +f +*U +0.000 0.612 0.580 0.337 k +*u +1378.333 383.333 m +1378.278 383.278 1378.222 382.222 1378.667 382.667 c +1378.722 382.722 1378.778 383.778 1378.333 383.333 c +f +*U +0.000 0.353 0.255 0.247 k +*u +1085 383 m +1086 382 l +1085 383 l +f +*U +0.000 0.388 0.310 0.612 k +*u +1282 383 m +1283 382 l +1282 383 l +f +*U +0.000 0.329 0.271 0.051 k +*u +1290 383 m +1291 382 l +1290 383 l +f +*U +0.000 0.184 0.141 0.337 k +*u +1379 383 m +1380 382 l +1379 383 l +f +*U +0.000 0.286 0.216 0.051 k +*u +1068 382 m +1069 381 l +1068 382 l +f +*U +0.000 0.863 0.671 0.137 k +*u +1378 382 m +1378 378 l +1299 378 l +1305.436 375.299 1315 377 1322 377 c +1359 377 l +1365.834 377 1373.416 376 1380 378 c +1379.436 379.752 1379 380.542 1378 382 c +f +*U +0.000 0.678 0.518 0.322 k +*u +1379.333 381.333 m +1379.278 381.278 1379.222 380.222 1379.667 380.667 c +1379.722 380.722 1379.778 381.778 1379.333 381.333 c +f +*U +0.000 0.698 0.561 0.302 k +*u +1068 381 m +1068 377 l +1068.710 378.759 1068.710 379.241 1068 381 c +f +*U +0.000 0.443 0.318 0.431 k +*u +1083.333 380.333 m +1083.278 380.278 1083.222 379.222 1083.667 379.667 c +1083.722 379.723 1083.777 380.778 1083.333 380.333 c +f +*U +0.000 0.302 0.220 0.224 k +*u +1084 381 m +1085 380 l +1084 381 l +f +*U +0.000 0.396 0.263 0.192 k +*u +1280 381 m +1281 380 l +1280 381 l +f +*U +0.000 0.325 0.298 0.188 k +*u +1289 381 m +1290 380 l +1289 381 l +f +*U +0.000 0.239 0.145 0.051 k +*u +1296 381 m +1297 380 l +1296 381 l +f +*U +0.000 0.439 0.275 0.145 k +*u +1380 381 m +1381 380 l +1380 381 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1288 380 m +1289 379 l +1288 380 l +f +*U +0.000 0.294 0.192 0.290 k +*u +1296 380 m +1297 379 l +1296 380 l +f +*U +0.000 0.667 0.459 0.333 k +*u +1380 380 m +1379 377 l +1380.766 377.979 1380.956 378.222 1380 380 c +f +*U +0.000 0.361 0.278 0.373 k +*u +1067 379 m +1068 378 l +1067 379 l +f +*U +0.000 0.275 0.200 0.122 k +*u +1083 379 m +1084 378 l +1083 379 l +f +*U +0.000 0.227 0.243 0.400 k +*u +1279 379 m +1280 378 l +1279 379 l +f +*U +0.000 0.204 0.192 0.573 k +*u +1288 379 m +1289 378 l +1288 379 l +f +*U +0.000 0.365 0.325 0.635 k +*u +1296.333 378.333 m +1296.278 378.278 1296.222 377.222 1296.667 377.667 c +1296.723 377.723 1296.777 378.778 1296.333 378.333 c +f +*U +0.000 0.231 0.282 0.224 k +*u +1381 379 m +1382 378 l +1381 379 l +f +*U +0.000 0.396 0.369 0.604 k +*u +1067 378 m +1068 377 l +1067 378 l +f +*U +0.000 0.729 0.584 0.271 k +*u +1071 378 m +1074.698 376.448 1079 377 1083 377 c +1079.302 378.552 1074.983 378 1071 378 c +f +*U +0.000 0.227 0.231 0.173 k +*u +1278 378 m +1279 377 l +1278 378 l +f +*U +0.000 0.341 0.369 0.518 k +*u +1381.333 377.333 m +1381.278 377.278 1381.222 376.222 1381.667 376.667 c +1381.722 376.722 1381.777 377.778 1381.333 377.333 c +f +*U +0.008 0.000 0.039 0.235 k +*u +1066 377 m +1067 376 l +1066 377 l +f +*U +0.000 0.345 0.290 0.271 k +*u +1067 377 m +1068 376 l +1067 377 l +f +*U +0.000 0.345 0.337 0.141 k +*u +1068 377 m +1072.217 375.231 1077.459 376 1082 376 c +1077.783 377.769 1072.541 377 1068 377 c +f +*U +0.000 0.075 0.075 0.141 k +*u +1082 377 m +1083 376 l +1082 377 l +f +*U +0.000 0.078 0.098 0.200 k +*u +1277 377 m +1278 376 l +1277 377 l +f +*U +0.000 0.514 0.420 0.059 k +*u +1278 377 m +1280 376 1281.747 376 1284 376 c +1281.948 376.874 1280.253 376.953 1278 377 c +f +*U +0.000 0.224 0.251 0.192 k +*u +1284 377 m +1285.506 376.317 1286.315 376.174 1288 376 c +1286.494 376.683 1285.685 376.826 1284 377 c +f +*U +0.000 0.408 0.376 0.114 k +*u +1296 377 m +1303 373.996 1314.256 376 1322 376 c +1381 376 l +1373.841 379 1362.744 377 1355 377 c +1296 377 l +f +*U +0.000 0.051 0.055 0.212 k +*u +1061 366 m +1062 365 l +1061 366 l +f +*U +0.000 0.314 0.231 0.306 k +*u +1062 366 m +1063 365 l +1062 366 l +f +*U +0.000 0.388 0.278 0.451 k +*u +1063 366 m +1064 365 l +1063 366 l +f +*U +0.000 0.420 0.306 0.251 k +*u +1064 366 m +1067.432 364.560 1071.300 365 1075 365 c +1071.568 366.440 1067.700 366 1064 366 c +f +*U +0.000 0.204 0.157 0.592 k +*u +1075 366 m +1076 365 l +1075 366 l +f +*U +0.000 0.373 0.251 0.278 k +*u +1262 366 m +1269 362.998 1278.342 365.823 1286 364 c +1282 368.565 1267.868 366 1262 366 c +f +*U +0.000 0.169 0.122 0.188 k +*u +1292 366 m +1293 365 l +1292 366 l +f +*U +0.000 0.373 0.251 0.278 k +*u +1293 366 m +1300.879 362.694 1313.466 365 1322 365 c +1387 365 l +1379 368.306 1366.534 366 1358 366 c +1293 366 l +f +*U +0.000 0.333 0.239 0.298 k +*u +1061 365 m +1062 364 l +1061 365 l +f +*U +0.000 0.886 0.639 0.114 k +*u +1062 365 m +1060.848 361.339 1059.742 357.774 1059 354 c +1067.597 354 1073 355.555 1075 365 c +1062 365 l +f +*U +0.000 0.400 0.365 0.600 k +*u +1075 365 m +1076 364 l +1075 365 l +f +*U +0.000 0.267 0.208 0.145 k +*u +1261.333 364.333 m +1261.278 364.278 1261.222 363.222 1261.667 363.667 c +1261.723 363.723 1261.777 364.778 1261.333 364.333 c +f +*U +0.000 0.871 0.604 0.125 k +*u +1262 365 m +1259.401 357.925 1251.946 358.723 1246 361 c +1241 354 l +1256.413 352.714 1272.503 354 1288 354 c +1384 354 l +1379.785 355.769 1374.536 355 1370 355 c +1343 355 l +1248 355 l +1253.436 356.607 1259.360 356 1265 356 c +1292 356 l +1384 356 l +1379.785 357.769 1374.536 357 1370 357 c +1344 357 l +1252 357 l +1266.222 361.322 1283.269 359 1298 359 c +1384 359 l +1378.697 362.618 1369.285 360 1363 360 c +1310 360 l +1302.427 360 1289.233 357.173 1285 365 c +1262 365 l +f +*U +0.000 0.251 0.188 0.090 k +*u +1291 365 m +1292 364 l +1291 365 l +f +*U +0.000 0.714 0.510 0.286 k +*u +1291 363 m +1292.580 363.683 1292.777 363.805 1294 365 c +1292.420 364.316 1292.223 364.195 1291 363 c +f +*U +0.000 0.839 0.584 0.161 k +*u +1294 363 m +1308.271 366.398 1325.354 364 1340 364 c +1354.951 364 1372.432 366.468 1387 363 c +1383.394 367 1372.217 365 1367 365 c +1313 365 l +1307.940 365 1297.508 367 1294 363 c +f +*U +0.000 0.243 0.184 0.122 k +*u +1387 365 m +1388 364 l +1387 365 l +f +*U +0.000 0.498 0.396 0.502 k +*u +1061.333 363.333 m +1061.278 363.278 1061.222 362.222 1061.667 362.667 c +1061.722 362.722 1061.777 363.778 1061.333 363.333 c +f +*U +0.000 0.341 0.271 0.243 k +*u +1075 364 m +1076 363 l +1075 364 l +f +*U +0.000 0.067 0.067 0.176 k +*u +1088 364 m +1089 363 l +1088 364 l +f +*U +0.000 0.196 0.153 0.208 k +*u +1245 364 m +1246 363 l +1245 364 l +f +*U +0.000 0.694 0.561 0.306 k +*u +1285 364 m +1285.980 362.217 1285.908 362.406 1288 362 c +1286.861 363 1286.388 363.309 1285 364 c +f +*U +0.000 0.290 0.278 0.333 k +*u +1286 364 m +1287 363 l +1286 364 l +f +*U +0.000 0.318 0.227 0.149 k +*u +1290 364 m +1291 363 l +1290 364 l +f +*U +0.000 0.875 0.631 0.114 k +*u +1288 361 m +1295 357.996 1306.256 360 1314 360 c +1361 360 l +1368.555 360 1376.591 361.314 1384 360 c +1371.804 356.395 1355.711 359 1343 359 c +1259 359 l +1262.959 357.339 1267.740 358 1272 358 c +1297 358 l +1384 358 l +1384 354 l +1388 354 l +1386 357 l +1387.479 356 1387.203 356 1389 356 c +1386.575 367 1375 364 1366 364 c +1316 364 l +1306.514 364 1296.677 365.344 1288 361 c +f +*U +0.000 0.537 0.392 0.463 k +*u +1387.333 363.333 m +1387.278 363.278 1387.222 362.222 1387.667 362.667 c +1387.722 362.722 1387.777 363.778 1387.333 363.333 c +f +*U +0.000 0.200 0.141 0.067 k +*u +1060 363 m +1061 362 l +1060 363 l +f +*U +0.000 0.282 0.220 0.424 k +*u +1088 363 m +1089 362 l +1088 363 l +f +*U +0.000 0.204 0.169 0.133 k +*u +1089 363 m +1090 362 l +1089 363 l +f +*U +0.000 0.325 0.318 0.675 k +*u +1245 363 m +1246 362 l +1245 363 l +f +*U +0.000 0.706 0.533 0.294 k +*u +1246 363 m +1244.602 360.950 1243.749 359.354 1243 357 c +1244.867 358.548 1246.438 360 1248 362 c +1246 363 l +f +*U +0.000 0.349 0.271 0.322 k +*u +1261 363 m +1262 362 l +1261 363 l +f +*U +0.000 0.392 0.278 0.361 k +*u +1288 363 m +1289 362 l +1288 363 l +f +*U +0.000 0.753 0.569 0.247 k +*u +1288 361 m +1289.580 361.683 1289.777 361.805 1291 363 c +1289.420 362.316 1289.223 362.195 1288 361 c +f +*U +0.000 0.400 0.275 0.184 k +*u +1060 362 m +1061 361 l +1060 362 l +f +*U +0.000 0.420 0.286 0.251 k +*u +1074 362 m +1075 361 l +1074 362 l +f +*U +0.000 0.424 0.329 0.506 k +*u +1088 362 m +1088 360 l +1090 360 l +1090 362 l +1088 362 l +f +*U +0.000 0.255 0.192 0.149 k +*u +1244 362 m +1245 361 l +1244 362 l +f +*U +0.000 0.341 0.267 0.200 k +*u +1260 362 m +1261 361 l +1260 362 l +f +*U +0.000 0.306 0.224 0.047 k +*u +1388 362 m +1389 361 l +1388 362 l +f +*U +0.000 0.251 0.196 0.227 k +*u +1090 361 m +1091 360 l +1090 361 l +f +*U +0.000 0.365 0.235 0.604 k +*u +1248 361 m +1249 360 l +1248 361 l +f +*U +0.000 0.306 0.200 0.286 k +*u +1249 361 m +1250 360 l +1249 361 l +f +*U +0.000 0.169 0.110 0.098 k +*u +1250 361 m +1251 360 l +1250 361 l +f +*U +0.000 0.255 0.176 0.322 k +*u +1258 361 m +1259 360 l +1258 361 l +f +*U +0.000 0.714 0.580 0.286 k +*u +1259.667 360.667 m +1259.222 360.222 1260.278 360.278 1260.333 360.333 c +1260.778 360.778 1259.722 360.722 1259.667 360.667 c +f +*U +0.000 0.467 0.325 0.306 k +*u +1388 361 m +1389 360 l +1388 361 l +f +*U +0.000 0.290 0.216 0.055 k +*u +1059 360 m +1060 359 l +1059 360 l +f +*U +0.000 0.655 0.510 0.345 k +*u +1072 360 m +1069.176 353.787 1065.243 354 1059 354 c +1063.989 351.907 1074 352.287 1072 360 c +f +*U +0.000 0.247 0.176 0.310 k +*u +1073 360 m +1074 359 l +1073 360 l +f +*U +0.153 0.004 0.000 0.196 k +*u +1087 360 m +1088 359 l +1087 360 l +f +*U +0.000 0.843 0.647 0.157 k +*u +1088 360 m +1088 356 l +1092 356 l +1091 360 l +1088 360 l +f +*U +0.000 0.318 0.204 0.118 k +*u +1243 360 m +1244 359 l +1243 360 l +f +*U +0.000 0.671 0.537 0.329 k +*u +1248 360 m +1250.613 358.902 1253 359 1256 359 c +1253.387 360 1250.836 359.993 1248 360 c +f +*U +0.000 0.502 0.463 0.498 k +*u +1388.333 359.333 m +1388.278 359.278 1388.222 358.222 1388.667 358.667 c +1388.722 358.722 1388.778 359.778 1388.333 359.333 c +f +*U +0.000 0.420 0.294 0.278 k +*u +1059 359 m +1060 358 l +1059 359 l +f +*U +0.000 0.337 0.235 0.055 k +*u +1073 359 m +1074 358 l +1073 359 l +f +*U +0.000 0.220 0.259 0.239 k +*u +1087 359 m +1088 358 l +1087 359 l +f +*U +0.000 0.592 0.471 0.408 k +*u +1091.333 358.333 m +1091.278 358.278 1091.222 357.222 1091.667 357.667 c +1091.722 357.723 1091.777 358.778 1091.333 358.333 c +f +*U +0.000 0.192 0.188 0.278 k +*u +1389 359 m +1390 358 l +1389 359 l +f +*U +0.000 0.639 0.498 0.361 k +*u +1059.333 357.333 m +1059.278 357.278 1059.222 356.222 1059.667 356.667 c +1059.722 356.722 1059.777 357.778 1059.333 357.333 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1087.333 357.333 m +1087.278 357.278 1087.222 356.222 1087.667 356.667 c +1087.722 356.722 1087.777 357.778 1087.333 357.333 c +f +*U +0.000 0.443 0.294 0.004 k +*u +1092 358 m +1093 357 l +1092 358 l +f +*U +0.000 0.349 0.247 0.180 k +*u +1242 358 m +1243 357 l +1242 358 l +f +*U +0.000 0.824 0.620 0.153 k +*u +1252 358 m +1256.215 356.231 1261.465 357 1266 357 c +1292 357 l +1384 357 l +1379.785 358.769 1374.536 358 1370 358 c +1344 358 l +1252 358 l +f +*U +0.000 0.427 0.380 0.329 k +*u +1389 358 m +1390 357 l +1389 358 l +f +*U +0.000 0.337 0.204 0.000 k +*u +1058 357 m +1059 356 l +1058 357 l +f +*U +0.000 0.102 0.067 0.180 k +*u +1072 357 m +1073 356 l +1072 357 l +f +*U +0.000 0.478 0.384 0.224 k +*u +1086 357 m +1087 356 l +1086 357 l +f +*U +0.000 0.455 0.294 0.275 k +*u +1092 357 m +1093 356 l +1092 357 l +f +*U +0.000 0.035 0.067 0.153 k +*u +1210 357 m +1211 356 l +1210 357 l +f +*U +0.000 0.424 0.306 0.278 k +*u +1211.667 356.667 m +1211.222 356.222 1212.278 356.278 1212.333 356.333 c +1212.778 356.778 1211.722 356.722 1211.667 356.667 c +f +*U +0.000 0.592 0.592 0.408 k +*u +1213 357 m +1215 353 l +1215.683 354.506 1215.826 355.315 1216 357 c +1213 357 l +f +*U +0.012 0.149 0.000 0.208 k +*u +1239 357 m +1240 356 l +1239 357 l +f +*U +0.000 0.588 0.373 0.412 k +*u +1240 357 m +1241.249 356.315 1241.548 356.251 1243 356 c +1241.752 356.685 1241.452 356.749 1240 357 c +f +*U +0.000 0.898 0.537 0.102 k +*u +1386 357 m +1386.901 355 1387 355 1389 354 c +1388 355.923 1387.924 355.999 1386 357 c +f +*U +0.000 0.655 0.384 0.345 k +*u +1389 357 m +1389.406 354.908 1389.217 354.980 1391 354 c +1390.309 355.388 1390 355.861 1389 357 c +f +*U +0.000 0.255 0.094 0.118 k +*u +1390.333 356.333 m +1390.278 356.278 1390.222 355.222 1390.667 355.667 c +1390.722 355.722 1390.777 356.778 1390.333 356.333 c +f +*U +0.000 0.416 0.282 0.286 k +*u +1058 356 m +1059 355 l +1058 356 l +f +*U +0.000 0.122 0.176 0.220 k +*u +1082.667 355.667 m +1082.222 355.222 1083.278 355.278 1083.333 355.333 c +1083.778 355.778 1082.722 355.722 1082.667 355.667 c +f +*U +0.000 0.345 0.247 0.290 k +*u +1084 356 m +1085 355 l +1084 356 l +f +*U +0.000 0.686 0.514 0.314 k +*u +1085.667 355.667 m +1085.222 355.222 1086.278 355.278 1086.333 355.333 c +1086.778 355.778 1085.722 355.722 1085.667 355.667 c +f +*U +0.000 0.910 0.651 0.090 k +*u +1085 355 m +1086.506 354.317 1087.315 354.174 1089 354 c +1087.276 355 1087 355 1085 355 c +f +*U +0.000 0.678 0.482 0.216 k +*u +1088 356 m +1089.223 354.805 1089.420 354.684 1091 354 c +1090 355.783 1090 355.594 1088 356 c +f +*U +0.000 0.478 0.329 0.522 k +*u +1091 356 m +1091 353 l +1091.696 354.554 1091.696 354.446 1091 356 c +f +*U +0.000 0.263 0.153 0.067 k +*u +1092 356 m +1093 355 l +1092 356 l +f +*U +0.000 0.125 0.051 0.110 k +*u +1207 356 m +1208 355 l +1207 356 l +f +*U +0.000 0.898 0.643 0.102 k +*u +1208 356 m +1209.926 353.792 1212 354 1215 354 c +1215 356 l +1208 356 l +f +*U +0.000 0.620 0.518 0.380 k +*u +1209.667 355.667 m +1209.222 355.222 1210.278 355.278 1210.333 355.333 c +1210.778 355.778 1209.722 355.722 1209.667 355.667 c +f +*U +0.000 0.161 0.235 0.263 k +*u +1231 356 m +1232 355 l +1231 356 l +f +*U +0.000 0.475 0.380 0.478 k +*u +1232 356 m +1233 355 l +1232 356 l +f +*U +0.000 0.365 0.443 0.149 k +*u +1233 356 m +1234.248 355.315 1234.548 355.251 1236 355 c +1234.751 355.685 1234.452 355.749 1233 356 c +f +*U +0.000 0.467 0.302 0.059 k +*u +1236.667 355.667 m +1236.222 355.222 1237.278 355.278 1237.333 355.333 c +1237.778 355.778 1236.722 355.722 1236.667 355.667 c +f +*U +0.000 0.537 0.482 0.447 k +*u +1238.667 355.667 m +1238.222 355.222 1239.278 355.278 1239.333 355.333 c +1239.778 355.778 1238.722 355.722 1238.667 355.667 c +f +*U +0.000 0.714 0.502 0.286 k +*u +1240 356 m +1240.654 352.946 1242 353 1245 353 c +1241 355 l +1242 356 l +1240 356 l +f +*U +0.000 0.878 0.671 0.122 k +*u +1248 356 m +1252.215 354.231 1257.465 355 1262 355 c +1289 355 l +1384 355 l +1379.785 356.769 1374.536 356 1370 356 c +1343 356 l +1248 356 l +f +*U +0.000 0.361 0.361 0.639 k +*u +1058.333 354.333 m +1058.278 354.278 1058.222 353.222 1058.667 353.667 c +1058.722 353.722 1058.777 354.778 1058.333 354.333 c +f +*U +0.000 0.518 0.341 0.176 k +*u +1071 355 m +1072 354 l +1071 355 l +f +*U +0.000 0.208 0.165 0.027 k +*u +1079 355 m +1080 354 l +1079 355 l +f +*U +0.000 0.698 0.620 0.302 k +*u +1080 353 m +1091 353 l +1087.676 354.492 1082.641 355.976 1080 353 c +f +*U +0.000 0.208 0.137 0.067 k +*u +1204 355 m +1205 354 l +1204 355 l +f +*U +0.000 0.467 0.325 0.200 k +*u +1205 355 m +1206 354 l +1205 355 l +f +*U +0.000 0.780 0.635 0.220 k +*u +1206.667 354.667 m +1206.222 354.222 1207.278 354.278 1207.333 354.333 c +1207.778 354.778 1206.722 354.722 1206.667 354.667 c +f +*U +0.000 0.800 0.686 0.200 k +*u +1229 355 m +1230.223 353.805 1230.420 353.684 1232 353 c +1231 354.783 1231 354.594 1229 355 c +f +*U +0.000 0.741 0.784 0.196 k +*u +1232 353 m +1236 354 l +1233.954 354.751 1233.404 354.656 1232 353 c +f +*U +0.000 0.706 0.686 0.294 k +*u +1233 354 m +1235.332 353 1237.457 353 1240 353 c +1237.557 354.530 1235.855 354.392 1233 354 c +f +*U +0.000 0.831 0.776 0.149 k +*u +1238.667 354.667 m +1238.222 354.222 1239.278 354.278 1239.333 354.333 c +1239.778 354.778 1238.722 354.722 1238.667 354.667 c +f +*U +0.000 0.251 0.192 0.110 k +*u +1057 354 m +1058 353 l +1057 354 l +f +*U +0.000 0.357 0.216 0.102 k +*u +1071 354 m +1072 353 l +1071 354 l +f +*U +0.000 0.192 0.161 0.243 k +*u +1077 354 m +1078 353 l +1077 354 l +f +*U +0.000 0.400 0.361 0.600 k +*u +1078.667 353.667 m +1078.222 353.222 1079.278 353.278 1079.333 353.333 c +1079.778 353.778 1078.722 353.722 1078.667 353.667 c +f +*U +0.000 0.800 0.580 0.200 k +*u +1081.667 353.667 m +1081.222 353.222 1082.278 353.278 1082.333 353.333 c +1082.778 353.778 1081.722 353.722 1081.667 353.667 c +f +*U +0.000 0.047 0.031 0.192 k +*u +1092 354 m +1093 353 l +1092 354 l +f +*U +0.000 0.110 0.231 0.114 k +*u +1202 354 m +1203 353 l +1202 354 l +f +*U +0.000 0.365 0.365 0.635 k +*u +1203.667 353.667 m +1203.222 353.222 1204.278 353.278 1204.333 353.333 c +1204.778 353.778 1203.722 353.722 1203.667 353.667 c +f +*U +0.000 0.659 0.514 0.341 k +*u +1205 354 m +1208 352.673 1211.586 353 1215 353 c +1211.837 354.327 1208.415 354.000 1205 354 c +f +*U +0.000 0.145 0.114 0.263 k +*u +1227 354 m +1228 353 l +1227 354 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1228.667 353.667 m +1228.222 353.222 1229.278 353.278 1229.333 353.333 c +1229.778 353.778 1228.722 353.722 1228.667 353.667 c +f +*U +0.000 0.671 0.702 0.298 k +*u +1246 354 m +1250.215 352.231 1255.464 353 1260 353 c +1289 353 l +1390 353 l +1385.785 354.769 1380.536 354 1376 354 c +1347 354 l +1246 354 l +f +*U +0.000 0.345 0.345 0.655 k +*u +1390 354 m +1391 353 l +1390 354 l +f +*U +0.020 0.000 0.000 0.282 k +*u +1069.667 352.667 m +1069.222 352.222 1070.278 352.278 1070.333 352.333 c +1070.778 352.778 1069.722 352.722 1069.667 352.667 c +f +*U +0.082 0.000 0.082 0.129 k +*u +1081 353 m +1082 352 l +1081 353 l +f +*U +0.000 0.196 0.145 0.125 k +*u +1203.667 352.667 m +1203.222 352.222 1204.278 352.278 1204.333 352.333 c +1204.778 352.778 1203.722 352.722 1203.667 352.667 c +f +*U +0.000 0.271 0.153 0.094 k +*u +1213 353 m +1214.249 352.315 1214.548 352.251 1216 352 c +1214.752 352.685 1214.452 352.749 1213 353 c +f +*U +0.000 0.114 0.106 0.192 k +*u +1229.667 352.667 m +1229.222 352.222 1230.278 352.278 1230.333 352.333 c +1230.778 352.778 1229.722 352.722 1229.667 352.667 c +f +*U +0.000 0.302 0.125 0.067 k +*u +1388 353 m +1389.248 352.315 1389.548 352.251 1391 352 c +1389.752 352.685 1389.451 352.749 1388 353 c +f +*U +0.000 0.000 0.000 0.075 k +*u +38 344 m +38 342 l +248 342 l +248 328 l +169 328 l +169 308 l +171 308 l +171 326 l +221 326 l +228.998 326 238 324.805 245.941 326 c +251 327 252 340 248.397 342.972 c +245 345.544 236.929 344 233 344 c +193 344 l +38 344 l +f +*U +0.000 0.000 0.000 0.067 k +*u +283 344 m +283 342 l +303 342 324 340.473 344 343 c +338.293 345.395 330 344 324 344 c +283 344 l +f +*U +0.000 0.000 0.000 0.075 k +*u +381 344 m +381 342 l +402 342 l +402 317 l +402 313.346 400.779 308.904 405 308 c +403.315 310.695 404 313.738 404 317 c +404 334 l +404 336.397 405 341.905 402.833 343.500 c +401.413 344.522 398.639 344 397 344 c +381 344 l +f +*U +0.000 0.000 0.000 0.067 k +*u +476 344 m +476 342 l +498 342 l +498 344 l +476 344 l +f +*U +0.000 0.000 0.000 0.055 k +*u +523 344 m +525.431 341.218 529.491 342 533 342 c +533 344 l +523 344 l +f +*U +0.000 0.000 0.000 0.075 k +*u +613 343 m +619.202 340.397 628.298 342 635 342 c +635 344 l +627.863 344 619.871 345 613 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +658 256 m +661 263.399 659 274.993 659 283 c +659 342 l +663.930 342 673.587 340 677 344 c +672.386 343.703 661.217 346.237 658 342.258 c +656.459 340.299 657.287 337.229 657.576 335 c +658.219 330 658 324.999 658 320 c +658 256 l +f +*U +0.000 0.000 0.000 0.075 k +*u +723 344 m +728.261 340.406 736.835 342 743 342 c +791 342 l +783.828 345 774.666 344 767 344 c +723 344 l +f +855 339 m +861.361 343.592 871.617 342.758 879 341 c +878.203 344.720 875.390 344 872 344 c +866.888 344 855 346 855 339 c +f +*U +0.000 0.000 0.000 0.067 k +*u +937 344 m +937 342 l +958 342 l +958 271 l +960 271 l +960 325 l +960 329 961.939 340.167 958.397 342.972 c +956.719 344.301 953.992 343.986 952 343.999 c +937 344 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1424 343 m +1429.281 338.999 1439.557 341 1446 341 c +1446 305 l +1450 307 l +1445 318.691 1451.483 332.607 1446 344 c +1438.638 343 1431.415 343 1424 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1503 342 m +1509.638 339.215 1523 339.975 1530 342 c +1523.242 344.909 1509.979 344 1503 342 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1943 343 m +1948.750 338.644 1958 341.897 1965 339 c +1963 344 l +1956.487 342.449 1949.659 343 1943 343 c +f +*U +0.000 0.000 0.000 0.161 k +*u +268 341 m +272.467 339.644 278.216 341.960 283 342 c +278 344 272.854 342.539 268 341 c +f +*U +0.000 0.000 0.000 0.133 k +*u +340 343 m +343 341.673 346.586 342 350 342 c +346.837 343.327 343.414 343.000 340 343 c +f +*U +0.000 0.000 0.000 0.141 k +*u +380 343 m +380 254 l +402 254 l +396.639 256.249 386.863 252.344 382.603 256.603 c +378.748 260.459 381 272.899 381 278 c +381 324 l +381 329.509 382.740 338.261 380 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +519 343 m +520.934 332.581 520 321.567 520 311 c +520 256 l +522.802 262.678 521 272.785 521 280 c +521 320 l +521 327.591 520.233 335.578 522 343 c +519 343 l +f +*U +0.000 0.000 0.000 0.157 k +*u +533.667 342.667 m +533.222 342.222 534.278 342.278 534.333 342.333 c +534.778 342.778 533.722 342.722 533.667 342.667 c +f +*U +0.000 0.000 0.000 0.075 k +*u +678 343 m +680.338 333.181 679 322 679 312 c +679 256 l +681 256 l +681 321 l +681 327 683.405 339.182 678 343 c +f +*U +0.000 0.000 0.000 0.137 k +*u +716 343 m +718.890 341.787 721.874 342 725 342 c +722 343.213 719 342.998 716 343 c +f +*U +0.000 0.000 0.000 0.129 k +*u +936 343 m +936 277 l +936 271.319 933.549 257.889 938 254 c +936.473 262.226 937 270.661 937 279 c +937 318 l +937 322.989 936.823 328 937 333 c +937.204 336.798 938.331 339.800 936 343 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1541 333 m +1552.458 342.259 1563.919 341 1578 341 c +1632 341 l +1632 343 l +1609 343 1585.778 344.470 1563 342.910 c +1555.191 342.376 1543.470 341.855 1541 333 c +f +1678 342 m +1684.678 339.198 1694.784 341 1702 341 c +1740 341 l +1746.834 341 1754.416 340 1761 342 c +1754.322 344.802 1744.216 343 1737 343 c +1700 343 l +1692.719 343 1685 343.695 1678 342 c +f +1798 342 m +1805.639 338.794 1817.729 341 1826 341 c +1873 341 l +1880.722 341 1889.565 339.802 1897 342 c +1889 345.306 1876.534 343 1868 343 c +1823 343 l +1814.790 343 1806 343.910 1798 342 c +f +*U +0.000 0.000 0.000 0.149 k +*u +37 342 m +37 328 l +38.667 331.972 38.667 338 37 342 c +f +*U +0.000 0.000 0.000 0.843 k +*u +38 342 m +38 328 l +39.667 331.972 39.667 338 38 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +39 342 m +39 328 l +84 328 l +84 255 l +104 255 l +104 328 l +147 328 l +147 342 l +39 342 l +f +*U +0.000 0.000 0.000 0.502 k +*u +147 342 m +147 328 l +148.796 332.279 147.909 337.419 149 342 c +147 342 l +f +*U +0.000 0.000 0.000 1.000 k +*u +149 342 m +149 255 l +249 255 l +249 269 l +169 269 l +169 296 l +166.727 292.523 167.889 288.994 167.985 285 c +168 277.977 167.882 270.994 168 264 c +194.536 265.978 221.374 265 248 265 c +247.971 262.575 248.282 259.481 246.397 257.603 c +242.527 253.750 230 256 225 256 c +152 256 l +152 305 l +152 309.955 153.774 319.380 150 323 c +152.697 326.851 152 331.439 152 336 c +247 336 l +247 329 l +168 329 l +168 323.686 168.242 318.306 167.911 313 c +167.774 310.792 166.850 307.834 168.357 305.898 c +170.552 303 176.906 305 180 305 c +191.999 304.932 204 305 216 305 c +216 296 l +170 296 l +170 294 l +217 294 l +217 307 l +169 307 l +169 328 l +248 328 l +248 342 l +149 342 l +f +*U +0.000 0.000 0.000 0.565 k +*u +275 342 m +276 341 l +275 342 l +f +*U +0.000 0.000 0.000 0.835 k +*u +276.667 341.667 m +276.222 341.222 277.278 341.278 277.333 341.333 c +277.778 341.778 276.722 341.722 276.667 341.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +365 288 m +358.261 288 351.753 289.944 345 290 c +345 269 l +298 269 l +293.583 269 283.993 267.214 280.603 270.603 c +277.463 273.744 279 281.938 279 286 c +279 328 l +345 328 l +345 309 l +348.433 309.434 352.677 309.327 355 312 c +351 311 l +351 328 l +349.902 325.387 350 322.835 350 320 c +349.190 322.729 349 325 349 328 c +346.699 322.517 349.734 315.928 346 311 c +347.722 316.825 347 323 346 329 c +278 329 l +278 325 l +276.285 326.551 275.177 327.244 273 328 c +271.600 322 272.998 316 273 310 c +273 270 l +277 271 l +278 267 l +275 269 l +274.438 267.199 274.176 265.878 274 264 c +273.438 265.801 273.176 267 273 269 c +272 267 271.561 265 271 263 c +268.234 263.676 267.348 263.604 265 262 c +264 265.534 263.510 268.354 264 272 c +262 271 l +262.934 272.723 263.535 274 264 276 c +261 275 l +262 279 l +263 277 l +264.769 281.215 264 286.464 264 291 c +264 301.834 266.730 317 262 327 c +264 326 l +263.339 327.396 263 327.814 262 329 c +263.367 330.731 263.984 333 265.564 334.658 c +268.309 337.354 273.537 336.315 277 336 c +277.228 338 277 337.890 279 339 c +278 337.521 278 337.797 278 336 c +297.472 337.254 317.471 335.999 337 336 c +342.945 336 352.661 338.707 357.870 335 c +359.627 333.792 360.672 331.638 362 330 c +359 324.658 360 317.970 360 312 c +356 312 l +364.876 308.285 365 316.411 364.985 323 c +364.776 331.411 361.647 338.267 352.999 340.485 c +344.854 342.575 336.325 342 328 342 c +291 342 l +283 342 272.886 342.842 266 338 c +260.527 334 260 327.249 260 321 c +260 279 l +260 272 259.582 264.689 265.329 259.800 c +271.276 254.742 281.613 255 289 255 c +305.663 254.994 322.339 254.806 339 255 c +345.793 255 355.403 255.340 360.442 260.532 c +367 267.310 365 279.432 365 288 c +f +*U +0.000 0.000 0.000 0.784 k +*u +347.667 341.667 m +347.222 341.222 348.278 341.278 348.333 341.333 c +348.778 341.778 347.722 341.722 347.667 341.667 c +f +*U +0.000 0.000 0.000 0.514 k +*u +349 342 m +350 341 l +349 342 l +f +*U +0.000 0.000 0.000 0.196 k +*u +352.667 341.667 m +352.222 341.222 353.278 341.278 353.333 341.333 c +353.778 341.778 352.722 341.722 352.667 341.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +382 342 m +382 255 l +402 255 l +402 293 l +477 293 l +477 255 l +496 255 l +496 342 l +477 342 l +477 307 l +402 307 l +402 342 l +382 342 l +f +*U +0.000 0.000 0.000 0.145 k +*u +475 342 m +475 309 l +405 309 l +411.194 306.401 420.314 308 427 308 c +476 308 l +476 330 l +476 333.983 476.552 338.301 475 342 c +f +*U +0.000 0.000 0.000 0.635 k +*u +476 342 m +476 308 l +477.328 311 477.000 314.581 477 318 c +477 325.215 478.802 335.323 476 342 c +f +*U +0.000 0.000 0.000 0.855 k +*u +496 342 m +496 255 l +498.395 260.707 497 268.846 497 275 c +497 319 l +497 325.951 498.701 335.564 496 342 c +f +*U +0.000 0.000 0.000 0.161 k +*u +497 342 m +497 255 l +476 255 l +482.202 252.397 491.298 254 498 254 c +498 315 l +498 323 500 334.600 497 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +521 342 m +521 255 l +539 255 l +539 320 l +536.960 317.763 536.388 316.617 538 314 c +534.952 308.288 536 301.340 536 295 c +536 256 l +527 256 l +527 317 l +527 325 529.264 334.805 522 340 c +526 339.907 528.433 337.780 532 336 c +531 338 l +532.635 337.455 532.455 337.635 533 336 c +534.797 336 534.521 336 536 337 c +537 336 l +536.438 334.199 536.176 332.878 536 331 c +536.685 332.248 536.749 332.548 537 334 c +537.225 331.765 537 331 536 329 c +536.873 326.519 537 324.638 537 322 c +540.167 321.588 540.838 318.289 543 316 c +547 311.801 552.312 308.388 557 304.861 c +571 294.254 585 283.464 599 272.611 c +605.712 267.375 613.978 258.378 622 255.500 c +625.547 254.227 630.278 255 634 255 c +634 342 l +615 342 l +615 320.949 615 299.981 616 279 c +599.355 295.299 578.505 308 560 322.235 c +552 328.219 543.366 337.927 534 341.272 c +530 342.687 525 342 521 342 c +f +*U +0.000 0.000 0.000 0.725 k +*u +534 342 m +535 341 l +534 342 l +f +*U +0.000 0.000 0.000 0.145 k +*u +614 342 m +614 283 l +612.483 283.957 611.661 284.387 610 285 c +611.549 282.864 612.864 281.549 615 280 c +615 322 l +615 328 616.395 336.293 614 342 c +f +*U +0.000 0.000 0.000 0.153 k +*u +634 342 m +634 255 l +636.395 260.707 635 268.846 635 275 c +635 319 l +635 325.951 636.701 335.564 634 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +659 342 m +659 255 l +679 255 l +679 342 l +659 342 l +f +*U +0.000 0.000 0.000 0.200 k +*u +707 340 m +709.533 339.463 711.512 340.220 714 341 c +711.328 341.799 709.568 341 707 340 c +f +*U +0.000 0.000 0.000 0.569 k +*u +716 342 m +717 341 l +716 342 l +f +*U +0.000 0.000 0.000 0.882 k +*u +717.667 341.667 m +717.222 341.222 718.278 341.278 718.333 341.333 c +718.778 341.778 717.722 341.722 717.667 341.667 c +f +*U +0.000 0.000 0.000 0.996 k +*u +806 288 m +800.959 288.216 795.988 289.841 791 289 c +792.981 280.677 790.819 272.352 792 264 c +739 264 l +735 264 723.533 262.871 723 267 c +720 265 l +720.462 270 719 275.691 719 281 c +719 329 l +771 329 l +777 329 786.400 330.884 790 325 c +790.685 326.248 790.749 326.548 791 328 c +792.254 322.426 791.350 316.569 793 311 c +800 312 l +800 320.200 800.248 328.211 803 336 c +792 342.480 781.309 342 769 342 c +730 342 l +721.969 342 710.324 342.670 704.649 335.787 c +700.958 331.311 701 325.467 701 320 c +701 295 l +701 285.335 697.933 269.255 704.649 261.329 c +709.588 255.499 718.907 255 726 255 c +742.994 254.802 760 254.993 777 255 c +784.338 255 794.781 254.715 800.660 259.800 c +808 266.288 806 279.211 806 288 c +f +*U +0.000 0.000 0.000 0.788 k +*u +788.667 341.667 m +788.223 341.223 789.277 341.278 789.333 341.333 c +789.778 341.778 788.722 341.722 788.667 341.667 c +f +*U +0.000 0.000 0.000 0.525 k +*u +790 342 m +791 341 l +790 342 l +f +*U +0.000 0.000 0.000 0.098 k +*u +791 342 m +793.283 340.779 795.428 340.348 798 340 c +795.686 341.591 793.810 341.858 791 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +818 278 m +823 280 l +822 283 l +823.796 283.969 823.681 285.432 825.194 286.889 c +826.774 288.409 829 287.791 830.611 289.306 c +832.810 291.495 833 298.935 834 302 c +835.714 300.450 836.823 299.756 839 299 c +838 296 l +841 295 l +840.458 292.326 840.493 291.269 842 289 c +850 301.314 860.923 315 866 329 c +868 329 l +873.587 314.239 886.418 302.728 892 288 c +896 290 l +895 296 l +893.805 295.402 894 295.534 893 294 c +892 295.207 889.170 296.995 888 299 c +887.230 300.321 887.249 303.259 887 305 c +886.895 305.737 889 305.375 886 306 c +887.479 306.986 887.203 307 889 307 c +887.752 307.685 887.452 307.749 886 308 c +887 312 l +885.263 311.938 885.360 311.980 884 313 c +883 310 l +881.483 310.957 880.661 311.387 879 312 c +879.764 314.746 879.764 316.254 879 319 c +888 321 l +888.197 318.624 888.247 316.372 888 314 c +890.580 313 892.253 312.747 895 313 c +895.628 310 896.659 307.856 896 305 c +896.810 303.230 896.497 301.947 898 301 c +896.964 299.814 896.661 299.396 896 298 c +898.377 297.689 898.983 297.747 901 299 c +901 297.203 901 297.479 902 296 c +905 297 l +904 292.337 904.911 289.835 910 290 c +910.560 284.738 913.861 280.204 918 277 c +916.703 275.406 916.465 274.982 916 273 c +917.797 273 917.522 273 919 274 c +919.902 272 920 272 922 271 c +921.954 268.752 922 268 923 266 c +920.717 264.554 920.418 263.689 920 261 c +921 262.458 921.436 263.248 922 265 c +923.938 261.993 925.532 260 929 259 c +922.952 255.612 912.227 253.236 912 263 c +909.433 264.246 908.914 265 909 268 c +910 266.466 909.805 266.598 911 266 c +912 271.764 907.541 271.650 903 272 c +903.986 273.479 904 273.203 904 275 c +902.521 275.986 902.797 276 901 276 c +902 277.186 902.339 277.604 903 279 c +900.777 279.184 900.810 279.240 899 278 c +892.386 281.530 883.352 280 876 280 c +851 280 l +844.697 280 838.703 280.351 833.274 276.532 c +830.404 274.513 828.884 270.872 827 268 c +826 271 l +823 270 l +824.341 268.726 825.403 267.959 827 267 c +825.952 265 825.487 264 825 262 c +823 262 822.734 261.830 821 261 c +822 263 l +816 261 l +817 256 l +807 256 l +808.283 260.441 810.639 264 813 268 c +814 265 l +815.554 267.485 815.542 269 815 272 c +818 273 l +818 277 l +811.345 272.962 806.249 261.951 803 255 c +808.192 255 818.207 253 822.391 256.603 c +827.945 261.295 829.256 272.479 836.185 275.397 c +841 277.438 848.806 276 854 276 c +866.992 276 880 276.241 892.999 275.995 c +904 275.786 904.250 262.539 911.529 256.603 c +916 252.850 927.332 255 933 255 c +921.231 277 906 298 892.344 319 c +888.903 324.272 885.735 329.719 882.308 334.999 c +880.831 337.274 879.276 340.246 876.674 341.397 c +872.829 343 860.974 343.216 857.379 340.972 c +852.377 337.851 848.859 328.923 845.808 324 c +840 314.649 834.265 305.249 828.308 296 c +824.582 290.215 820 284.615 818 278 c +f +938 342 m +938 255 l +1033 255 l +1033 269 l +958 269 l +958 342 l +938 342 l +f +*U +0.000 0.427 0.302 0.239 k +*u +1054.333 341.333 m +1054.278 341.278 1054.222 340.222 1054.667 340.667 c +1054.723 340.723 1054.777 341.778 1054.333 341.333 c +f +*U +0.000 0.525 0.416 0.475 k +*u +1055 340 m +1066.604 342.763 1080 341 1092 341 c +1096.941 341 1102.923 342 1107 339 c +1108.703 343.519 1098.748 342 1096 342 c +1066 342 l +1062.385 342 1057.271 343 1055 340 c +f +*U +0.000 0.341 0.243 0.047 k +*u +1108.333 341.333 m +1108.278 341.278 1108.222 340.222 1108.667 340.667 c +1108.723 340.723 1108.777 341.778 1108.333 341.333 c +f +*U +0.000 0.420 0.369 0.282 k +*u +1191 342 m +1192 341 l +1191 342 l +f +*U +0.000 0.525 0.416 0.475 k +*u +1192 342 m +1197.462 339.708 1205 341 1211 341 c +1252 341 l +1394 341 l +1388.537 343.292 1380.887 342 1375 342 c +1334 342 l +1192 342 l +f +*U +0.000 0.388 0.267 0.031 k +*u +1394.333 341.333 m +1394.278 341.278 1394.222 340.222 1394.667 340.667 c +1394.723 340.723 1394.777 341.777 1394.333 341.333 c +f +*U +0.000 0.000 0.000 0.161 k +*u +1529 342 m +1530 340 l +1531.635 340.545 1531.455 340.365 1532 342 c +1529 342 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1632 342 m +1634.890 340.787 1637.874 341 1641 341 c +1638 342.213 1635 341.998 1632 342 c +f +*U +0.000 0.000 0.000 0.071 k +*u +1640 341 m +1641.769 340.221 1643 340 1645 340 c +1643 341.301 1642.372 341.330 1640 341 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1760 342 m +1762.332 341 1764.457 341 1767 341 c +1764.669 341.984 1762.543 341.981 1760 342 c +f +*U +0.000 0.000 0.000 0.133 k +*u +1896 342 m +1896 326 l +1897.812 330.319 1897.812 337.681 1896 342 c +f +*U +0.000 0.000 0.000 0.149 k +*u +1942 342 m +1940.286 339.376 1938.944 336.987 1938 334 c +1940.574 336.358 1942.298 338.952 1944 342 c +1942 342 l +f +*U +0.000 0.000 0.000 0.325 k +*u +148 341 m +148 328 l +149.591 331.791 149.591 337.209 148 341 c +f +*U +0.000 0.000 0.000 0.745 k +*u +353 341 m +354 340 l +353 341 l +f +*U +0.000 0.000 0.000 0.169 k +*u +355.667 340.667 m +355.222 340.222 356.278 340.278 356.333 340.333 c +356.778 340.778 355.722 340.722 355.667 340.667 c +f +*U +0.000 0.000 0.000 0.067 k +*u +381 341 m +381 256 l +383.395 261.707 382 269.846 382 276 c +382 319 l +382 325.686 383.599 334.806 381 341 c +f +*U +0.000 0.000 0.000 0.125 k +*u +519 341 m +519 256 l +521.395 261.707 520 269.846 520 276 c +520 319 l +520 325.686 521.599 334.806 519 341 c +f +*U +0.000 0.000 0.000 0.996 k +*u +522 340 m +528.915 333.235 527 324 527 315 c +527 256 l +536 256 l +536 294 l +536 300.340 534.952 307.288 538 313 c +537 316.780 538.349 318.645 540 322 c +538 323.277 538.915 323.277 537 322 c +537.284 324.853 537.557 326.603 536 329 c +537.336 330.826 537.690 331.753 538 334 c +537.315 332.752 537.251 332.452 537 331 c +536.660 333 536.677 333.968 537 336 c +536 337 l +531 338 l +532 336 l +528.566 338.505 526.390 340.606 522 340 c +f +*U +0.000 0.000 0.000 0.157 k +*u +536 341 m +537.223 339.805 537.420 339.684 539 339 c +537.777 340.195 537.580 340.316 536 341 c +f +*U +0.000 0.000 0.000 0.769 k +*u +794 341 m +795 340 l +794 341 l +f +*U +0.000 0.000 0.000 0.608 k +*u +878 341 m +879 340 l +878 341 l +f +*U +0.000 0.000 0.000 0.094 k +*u +879 341 m +879.564 339.248 879.919 338.458 881 337 c +880.689 339.291 880.634 339.320 879 341 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1053 336 m +1053.363 333.768 1053.363 332.232 1053 330 c +1112 330 l +1109.601 333.899 1107.435 336.220 1107 341 c +1072 341 l +1063.987 341 1058.563 342 1053 336 c +f +*U +0.000 0.341 0.318 0.008 k +*u +1190 341 m +1191 340 l +1190 341 l +f +*U +0.000 0.875 0.608 0.125 k +*u +1191 341 m +1191 339 l +1286 339 l +1276.597 336.221 1264.782 338 1255 338 c +1192 338 l +1199.639 334.794 1211.729 337 1220 337 c +1283 337 l +1283 333 l +1255.927 329.579 1227.296 332 1200 332 c +1207.400 328.895 1218.993 331 1227 331 c +1287 331 l +1288 338 l +1291.694 337 1295.214 337 1299 337 c +1297.752 337.685 1297.452 337.749 1296 338 c +1305.683 340.862 1317.924 339 1328 339 c +1392 339 l +1386.293 341.395 1378 340 1372 340 c +1331 340 l +1284.362 340 1237.700 341 1191 341 c +f +*U +0.000 0.882 0.635 0.118 k +*u +1296 341 m +1303.879 337.694 1316.466 340 1325 340 c +1392 340 l +1382.317 337 1370 339 1360 339 c +1296 339 l +1299.619 336.322 1300.850 334.591 1301 330 c +1395 330 l +1394.694 333.752 1393.759 337.320 1393 341 c +1296 341 l +f +*U +0.000 0.733 0.533 0.267 k +*u +1393 341 m +1393 338 l +1395 339 l +1394.455 340.635 1394.635 340.455 1393 341 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1425 341 m +1425 253 l +1446 253 l +1440.286 255.398 1432.169 254 1426 254 c +1426 314 l +1426 322 1428 333.601 1425 341 c +f +*U +0.000 0.000 0.000 0.855 k +*u +1426 341 m +1426 254 l +1428.701 260.436 1427 270 1427 277 c +1427 321 l +1427 327 1428.395 335.293 1426 341 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1427 341 m +1427 254 l +1446 254 l +1446 292 l +1459.982 283.441 1473.942 274.834 1488 266.400 c +1494.470 262.518 1501.682 256.505 1509 254.499 c +1517.380 252.203 1528.330 254 1537 254 c +1529.973 261 1518.663 265.461 1510 270.427 c +1493.561 279.852 1477.411 291.497 1460 299 c +1482.270 313.736 1506.223 326 1529 340 c +1525.565 341.441 1521.703 341 1518 341 c +1513.502 341 1508.356 341.663 1504 340.351 c +1496.680 338 1489.450 332 1483 328 c +1470.699 320.335 1458 313 1446 305 c +1446 341 l +1427 341 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1491 335 m +1495.302 333.994 1499.507 337.689 1503 340 c +1498.778 340.616 1494.663 336.949 1491 335 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1503 341 m +1504 340 l +1503 341 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1529 341 m +1530 340 l +1529 341 l +f +*U +0.000 0.000 0.000 0.506 k +*u +1554 341 m +1555 340 l +1554 341 l +f +*U +0.000 0.000 0.000 0.855 k +*u +1555.667 340.667 m +1555.222 340.222 1556.278 340.278 1556.333 340.333 c +1556.778 340.777 1555.722 340.722 1555.667 340.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1636 255 m +1630.194 257.303 1622.186 256 1616 256 c +1574 256 l +1563.575 256 1553.913 253.776 1548 264 c +1545 262 l +1543.393 267.482 1544.298 272.443 1543.826 278 c +1542.614 292.285 1543 306.647 1543 321 c +1541.231 316.785 1542 311.536 1542 307 c +1542 280 l +1540.304 284.639 1541 290 1541 295 c +1541 302.647 1539.780 311.446 1541 318.972 c +1541.455 320.915 1542.816 322.241 1543.361 324 c +1544 326.697 1542.720 330.297 1544 332.694 c +1547.265 338.455 1556.648 333.660 1558 340 c +1566.631 335.508 1576.540 336 1586 336 c +1628 336 l +1635.905 336 1643.682 337.177 1651 334 c +1650 330 l +1649 332 l +1647.833 328.992 1647.521 325.261 1650 323 c +1649 325 l +1653 324 l +1644.764 313.519 1650 295.666 1648.830 283 c +1648 275.920 1646.705 268 1651 262 c +1650 261 l +1648.483 261.957 1647.662 262.387 1646 263 c +1643.373 259.674 1641 257.375 1637 256 c +1644.933 252.766 1652.822 259.407 1654.481 267 c +1655.735 272.734 1655 279 1655 285 c +1655 319 l +1654.997 325.661 1654.998 333 1648.956 337.297 c +1642.231 342 1631.781 341 1624 341 c +1569 341 l +1561 341 1550.307 341.777 1544.214 335.775 c +1539.258 330.894 1539 322.545 1539 316 c +1538.933 302 1538.407 287.932 1539 274 c +1539.305 268 1540.919 261.234 1546 257.728 c +1549.735 255.202 1554.704 255 1559 254.425 c +1571.338 252.746 1584.555 254 1597 254 c +1609 254 1624.361 251.560 1636 255 c +f +*U +0.000 0.000 0.000 0.808 k +*u +1638.667 340.667 m +1638.222 340.222 1639.278 340.278 1639.333 340.333 c +1639.778 340.778 1638.722 340.722 1638.667 340.667 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1677 341 m +1677 254 l +1679.395 259.707 1678 267.846 1678 274 c +1678 318 l +1678 324.951 1679.701 334.564 1677 341 c +f +*U +0.000 0.000 0.000 0.851 k +*u +1678 341 m +1678 254 l +1680.395 259.707 1679 267.846 1679 274 c +1679 318 l +1679 324.951 1680.701 334.564 1678 341 c +f +*U +0.000 0.000 0.000 0.996 k +*u +1679 341 m +1679 338 l +1760 338 l +1760 336 l +1680 336 l +1680 256 l +1696 256 l +1696 266 1698 278.211 1696 288 c +1703.463 288.834 1711.460 288 1719 287.999 c +1723.253 287.979 1728.340 288.223 1732 286 c +1733.662 286.613 1734.483 287 1736 288 c +1735.522 286 1735.295 284.504 1734 283 c +1735.636 280.382 1735.730 278.558 1739 279 c +1739.777 277.298 1740.588 275.810 1741 274 c +1742.767 273 1743.608 272.434 1745 271 c +1747.502 271.402 1749.489 271.359 1752 271 c +1751 266.465 1753.520 264.181 1758 264 c +1759 262 1759 261.902 1761 261 c +1761.642 263.842 1763.253 265.681 1765 268 c +1762.460 269.693 1761.684 272.422 1761 269 c +1757 274 l +1752 272 l +1752 273.410 1752.851 279 1752 280 c +1750.303 281.980 1749.186 278.744 1750 282 c +1747.944 281.513 1746.856 281 1745 280 c +1744 281 l +1745.517 281.958 1746.338 282.387 1748 283 c +1746.494 283.683 1745.685 283.826 1744 284 c +1753.243 290.648 1766.731 283.345 1775.786 291.419 c +1778.777 294 1780 298 1780.699 302 c +1782.276 312.675 1783.853 333.465 1771.996 338.521 c +1762.259 342.672 1750.334 341 1740 341 c +1679 341 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1765 341 m +1766 340 l +1765 341 l +f +*U +0.000 0.000 0.000 0.502 k +*u +1766 341 m +1767 340 l +1766 341 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1767 341 m +1769 339.775 1770.658 339.355 1773 339 c +1770.958 340.416 1769.489 340.745 1767 341 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1797 341 m +1797 256 l +1799.395 261.707 1798 269.846 1798 276 c +1798 319 l +1798 325.686 1799.599 334.806 1797 341 c +f +*U +0.000 0.000 0.000 0.851 k +*u +1798 341 m +1798 254 l +1800.395 259.707 1799 267.846 1799 274 c +1799 318 l +1799 324.951 1800.701 334.564 1798 341 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1799 341 m +1799 254 l +1860 254 l +1878 254 l +1880.762 254 1884.206 253.505 1886.815 254.603 c +1891.372 256.523 1894.169 263.750 1896 268 c +1818 268 l +1818 276.954 1816.760 286.543 1820 295 c +1816 296 l +1816 285.911 1813.562 272.892 1819 264 c +1823 264 l +1827.782 267.623 1836.197 266 1842 266 c +1888 266 l +1881 263.970 1873 265 1866 265 c +1824 265 l +1828.720 263 1834.920 264 1840 264 c +1871 264 l +1877.237 264 1885 265.537 1890 261 c +1888 262 l +1887.835 253.173 1874 256 1868 256 c +1800 256 l +1800 336 l +1888 336 l +1888 328 l +1839 328 l +1831.722 328 1823 329.518 1816 328 c +1816.654 320 1816.359 311.882 1816 304 c +1831.677 305.519 1848.224 304 1864 304 c +1864 296 l +1832 296 l +1828 296 1822.666 297.177 1821 293 c +1865 293 l +1865 306 l +1818 306 l +1818 327 l +1896 327 l +1894.855 331.810 1894.855 336.190 1896 341 c +1799 341 l +f +1890 254 m +1894.853 254 1904.246 252.186 1908.366 255 c +1914.572 259.309 1914.958 269.959 1921.379 273.972 c +1925.246 276.389 1932.606 275 1937 275 c +1971 275 l +1977.708 275 1982.871 276 1987 270 c +1992 273 l +1991 278 l +1989.805 276.777 1989.684 276.580 1989 275 c +1987.328 275.338 1987.690 275.537 1987 274 c +1985.868 276.328 1985.484 276.978 1987 279 c +1975.641 282.358 1960.833 280 1949 280 c +1941.869 280 1933.868 281 1927 279 c +1928 277 l +1927 276 l +1923 278 l +1921.517 276 1916.355 277.250 1916 280 c +1911 276 l +1910.961 278.627 1910.839 280.664 1912 283 c +1912.532 287.842 1915.597 288.210 1920 288 c +1919.277 294 1920.394 299 1922 305 c +1923.672 304.662 1923.310 304.463 1924 306 c +1928 304 l +1927.805 306.424 1927.590 308.648 1927 311 c +1928.397 311.662 1928.813 311.964 1930 313 c +1930 311 l +1931.300 311.650 1931 311 1931 313 c +1932.944 312.598 1933 312.598 1935 313 c +1936 311 1936 310.902 1938 310 c +1935.182 306 1934.649 302.227 1929 302 c +1927 287 l +1944.985 287 1963 286.267 1981 288 c +1981 292 l +1982 288 l +1983.195 289.223 1983.316 289.420 1984 291 c +1986.877 288.691 1988.808 287.950 1992 290 c +1992.338 285.727 1993.331 283.397 1996 280 c +1997.797 280 1997.521 280 1999 281 c +1999.648 278.606 2000 277.464 2002 276 c +2000 269 l +2001.801 268.438 2003 268.176 2005 268 c +2003.521 267 2003.797 267 2002 267 c +2004.401 264.987 2005.890 264.657 2009 265 c +2010 262.229 2010.945 259.969 2011 257 c +2009 261 l +2006.749 256 2004.263 255.764 1999 257 c +1999.986 258.479 2000 258.203 2000 260 c +1998.584 259.528 1998.186 259.186 1997 258 c +1995 261.930 1992.625 266.562 1989 269 c +1990 264.302 1993.289 256.564 1998 254.603 c +2003.297 252.489 2011.444 254 2017 254 c +2014.701 260 2010.612 265.493 2007.192 271 c +2000.539 281.715 1993.696 292.313 1987 303 c +1984.198 300.326 1983 296.294 1981 293 c +1979.977 294.534 1980.196 294.402 1979 295 c +1977.701 294.350 1978 294.853 1978 293 c +1976 293 l +1976.175 296.585 1974.198 299.859 1976 303 c +1973.992 303.553 1973.667 303.303 1972 302 c +1970.343 303.664 1969 304.875 1967 306 c +1969.363 299.545 1973.778 294 1977 288 c +1929 288 l +1934 301.975 1945.877 313 1951 327 c +1944 328 l +1944.892 326 1945.402 325.481 1947 324 c +1944 324 l +1945 319 l +1942.622 318.617 1942.644 316.363 1942 314 c +1940.507 314.999 1940.734 314.968 1939 315 c +1937.741 317.498 1936.440 318.632 1934 320 c +1935 322.243 1935.182 322.577 1935 325 c +1936.822 325.990 1936.716 326.867 1937 329 c +1938.479 328 1938.203 328 1940 328 c +1939 330 l +1943 328 l +1943.494 331 1943 332.000 1940 333 c +1947 336.523 1953.786 334.868 1961 337 c +1960.636 335.505 1960.198 327.855 1962 332 c +1964.939 329 1969.397 327.339 1970 323 c +1978 314 l +1977 312.261 1976.308 310.445 1975 309 c +1977.799 307 1980.760 305.927 1984 305 c +1982.851 310.943 1978.871 315.940 1975.681 321 c +1972.297 326.370 1967.910 337.839 1961.816 340.397 c +1958.944 341.602 1955 341 1952 341 c +1949.243 340.999 1945.798 341.467 1943.329 339.972 c +1940.557 338.294 1939 334.672 1937.399 332 c +1927.600 316 l +1919.747 302.917 1911.642 289.953 1903.575 277 c +1898.951 269.576 1893 262.205 1890 254 c +f +*U +0.000 0.000 0.000 0.184 k +*u +266.667 339.667 m +266.222 339.222 267.278 339.278 267.333 339.333 c +267.778 339.778 266.722 339.722 266.667 339.667 c +f +*U +0.000 0.000 0.000 0.773 k +*u +268 340 m +269 339 l +268 340 l +f +*U +0.000 0.000 0.000 0.702 k +*u +356 340 m +357 339 l +356 340 l +f +*U +0.000 0.000 0.000 0.153 k +*u +357.667 339.667 m +357.222 339.222 358.278 339.278 358.333 339.333 c +358.778 339.778 357.722 339.722 357.667 339.667 c +f +*U +0.000 0.000 0.000 0.753 k +*u +709 340 m +710 339 l +709 340 l +f +*U +0.000 0.000 0.000 0.765 k +*u +797 340 m +798 339 l +797 340 l +f +*U +0.000 0.576 0.431 0.424 k +*u +1054 340 m +1054 336 l +1054.710 337.759 1054.710 338.241 1054 340 c +f +*U +0.000 0.408 0.357 0.114 k +*u +1108.333 339.333 m +1108.278 339.278 1108.222 338.222 1108.667 338.667 c +1108.722 338.722 1108.777 339.778 1108.333 339.333 c +f +*U +0.000 0.486 0.412 0.290 k +*u +1190 340 m +1191 339 l +1190 340 l +f +*U +0.000 0.000 0.000 0.075 k +*u +1525 338 m +1527.457 337.484 1528.502 338 1530 340 c +1528 339.453 1526.745 338.890 1525 338 c +f +*U +0.000 0.000 0.000 0.769 k +*u +1550 340 m +1551 339 l +1550 340 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1558 340 m +1554.752 334.808 1547.456 338.432 1544.169 333 c +1542.619 330.512 1543.697 327.184 1542.945 324.421 c +1539 310.450 1541 294.552 1541 280 c +1542.769 284.215 1542 289.465 1542 294 c +1542 321 l +1543.692 315.275 1543 308.940 1543 303 c +1543 294.265 1543.334 285.691 1543.791 277 c +1544 271.522 1542.600 267.230 1545 262 c +1546.396 262.661 1546.814 262.964 1548 264 c +1551.815 254.311 1560 256 1569 256 c +1624 256 l +1632.962 255.986 1640.944 253.814 1646 263 c +1650 261 l +1651 262 l +1647.318 269.250 1648.621 276.236 1648.961 284 c +1649.552 297.500 1646.300 311.964 1653 324 c +1649 325 l +1650 323 l +1648.348 325.719 1648.347 328.823 1648 332 c +1649 330.466 1648.805 330.598 1650 330 c +1651 334 l +1643.507 338.510 1632.561 336 1624 336 c +1602.813 336 1578 332.322 1558 340 c +f +*U +0.000 0.000 0.000 0.671 k +*u +1644 340 m +1645 339 l +1644 340 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1645 340 m +1646.458 338.919 1647.248 338.564 1649 338 c +1647.457 339.267 1646.952 339.489 1645 340 c +f +*U +0.000 0.000 0.000 0.827 k +*u +1769 340 m +1770 339 l +1769 340 l +f +*U +0.000 0.000 0.000 0.863 k +*u +1895 340 m +1895 328 l +1896.512 331.604 1896.512 336.396 1895 340 c +f +*U +0.000 0.000 0.000 0.114 k +*u +261 333 m +262.968 334.868 264.488 336.744 266 339 c +262.718 337.748 261.728 336.425 261 333 c +f +*U +0.000 0.000 0.000 0.725 k +*u +266 339 m +267 338 l +266 339 l +f +*U +0.000 0.000 0.000 0.996 k +*u +277 339 m +275.723 337 275.723 337.915 277 336 c +268.909 337.450 265.627 336.462 262 329 c +264 326 l +262 327 l +266.932 311.864 264 292.764 264 277 c +263 279 l +262 277.623 261.596 276.560 261 275 c +262.797 275 262.522 275 264 276 c +262 271 l +264 272 l +263.185 268.202 263.688 265.626 265 262 c +267.266 263 268.477 263.306 271 263 c +271.644 265 271.906 266.795 272 269 c +272.562 267.199 272.824 265.878 273 264 c +273.924 265.648 274.449 267.175 275 269 c +276.186 267.964 276.604 267.661 278 267 c +277 271 l +273 270 l +273 309 l +273 315.348 271.891 321.745 273 328 c +274.767 327 275.607 326.434 277 325 c +277.683 326.506 277.826 327.315 278 329 c +346 329 l +346.780 322.831 347.460 317 346 311 c +349.786 314.308 348 323.233 348 328 c +348.810 325.271 348.979 322.850 349 320 c +350 322.613 349.993 325 350 328 c +351.607 322.563 351 316.642 351 311 c +353.669 311.430 354.626 310.763 357 310 c +357 312.351 357.652 311.935 360 312 c +360 317.602 359.373 324 362 329 c +357.914 339.779 349.335 336 340 336 c +319.688 335.787 298 338.213 278 336 c +279 339 l +277 339 l +f +*U +0.000 0.000 0.000 0.675 k +*u +358 339 m +359 338 l +358 339 l +f +*U +0.000 0.000 0.000 0.212 k +*u +359 339 m +360 338 l +359 339 l +f +*U +0.000 0.000 0.000 0.682 k +*u +538 339 m +539 338 l +538 339 l +f +*U +0.000 0.000 0.000 0.118 k +*u +539 339 m +540.450 337.392 541 336.936 543 336 c +541.771 337.870 541 338.224 539 339 c +f +*U +0.000 0.000 0.000 0.133 k +*u +704 336 m +705.457 337 705.897 337.543 707 339 c +704.876 338 704.899 338 704 336 c +f +*U +0.000 0.000 0.000 0.733 k +*u +707 339 m +708 338 l +707 339 l +f +*U +0.000 0.000 0.000 0.765 k +*u +799 339 m +800 338 l +799 339 l +f +*U +0.000 0.000 0.000 0.267 k +*u +800 339 m +800.545 337.365 800.365 337.545 802 337 c +801.455 338.635 801.635 338.455 800 339 c +f +*U +0.000 0.000 0.000 0.235 k +*u +854 339 m +855 338 l +854 339 l +f +*U +0.000 0.690 0.631 0.251 k +*u +1107 339 m +1107 336 l +1107.696 337.554 1107.696 337.446 1107 339 c +f +*U +0.000 0.651 0.486 0.349 k +*u +1190 339 m +1190 336 1189.792 333.925 1192 332 c +1191.405 334.396 1191 336.767 1190 339 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1191 339 m +1191 335.922 1191.438 333 1192 330 c +1287 330 l +1279.600 333 1268 331 1260 331 c +1200 331 l +1207 333 1215.573 332 1223 332 c +1242.417 332 1263.893 329.453 1283 333 c +1283 337 l +1192 337 l +1201.403 339.779 1213.218 338 1223 338 c +1286 338 l +1278 341.306 1265.534 339 1257 339 c +1191 339 l +f +*U +0.000 0.580 0.392 0.416 k +*u +1394 339 m +1394 335.389 1395.207 332.211 1392 330 c +1393.506 329.317 1394.315 329.174 1396 329 c +1395.926 332.575 1395.692 335.818 1394 339 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1547 339 m +1548 338 l +1547 339 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1772 339 m +1773 338 l +1772 339 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1773.667 338.667 m +1773.222 338.222 1774.278 338.278 1774.333 338.333 c +1774.778 338.778 1773.722 338.722 1773.667 338.667 c +f +*U +0.000 0.000 0.000 0.651 k +*u +1964 339 m +1965 338 l +1964 339 l +f +*U +0.000 0.000 0.000 0.141 k +*u +1965 339 m +1965.547 337 1966 335.745 1967 334 c +1967.375 336.419 1966.693 337.218 1965 339 c +f +*U +0.000 0.000 0.000 0.220 k +*u +360 338 m +361 337 l +360 338 l +f +*U +0.000 0.000 0.000 0.831 k +*u +800 338 m +801 337 l +800 338 l +f +*U +0.000 0.000 0.000 0.075 k +*u +853 338 m +852 336.521 852 336.797 852 335 c +853.289 336.443 853.401 336.234 853 338 c +f +*U +0.000 0.000 0.000 0.655 k +*u +854 338 m +855 337 l +854 338 l +f +*U +0.000 0.000 0.000 0.071 k +*u +937 338 m +937 256 l +939.292 261.462 938 269 938 275 c +938 317 l +938 323.420 939.497 332 937 338 c +f +*U +0.000 0.259 0.192 0.090 k +*u +1053 338 m +1054 337 l +1053 338 l +f +*U +0.000 0.392 0.220 0.341 k +*u +1108.333 337.333 m +1108.278 337.278 1108.222 336.222 1108.667 336.667 c +1108.723 336.723 1108.777 337.778 1108.333 337.333 c +f +*U +0.000 0.388 0.306 0.286 k +*u +1288 338 m +1289 337 l +1288 338 l +f +*U +0.000 0.427 0.333 0.004 k +*u +1289 338 m +1290 337 l +1289 338 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1431 338 m +1427 330.610 1429 320 1429 312 c +1429 256 l +1440 256 l +1440 267 1441.209 279.000 1440 290 c +1442.979 290.596 1441.733 291.567 1444 291 c +1445 292 l +1444.466 294.670 1445.785 294.443 1443 295 c +1446.375 295.457 1448.391 295.223 1451 293 c +1455 294 l +1453.466 292.978 1453.598 293.195 1453 292 c +1456 291 l +1455 289 l +1458.629 286.899 1463 289 1466 287 c +1468 292 l +1464 290 l +1466 294 l +1463.851 295.236 1456.647 297 1458 300 c +1456.526 302.358 1455.440 306.306 1452 306.500 c +1448.447 306.700 1446.841 301 1443.333 304.167 c +1439.311 307.751 1441.765 309.947 1442 314 c +1442.422 321.278 1442 328.708 1442 336 c +1439.194 329.313 1441 319.233 1441 312 c +1438.801 319.438 1440 328.271 1440 336 c +1436.580 336 1434 336.325 1431 338 c +f +*U +0.000 0.000 0.000 0.584 k +*u +1524 338 m +1525 337 l +1524 338 l +f +*U +0.000 0.000 0.000 0.169 k +*u +1649 338 m +1650.330 336.248 1651.247 335.330 1653 334 c +1651.847 336.249 1651.249 336.847 1649 338 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1679 338 m +1679 254 l +1698 254 l +1698 287 l +1705.526 287 1717 289.170 1724 286 c +1727.728 284.311 1730.884 281 1734 278.414 c +1753 262.750 l +1756.344 259.987 1759.841 256 1764 254.600 c +1771.303 251.994 1782.278 254 1790 254 c +1781 263 1769 269.783 1759 277.373 c +1754.494 280.753 1749.901 285.603 1744 285 c +1745.506 284.317 1746.315 284.174 1748 284 c +1746.400 283 1745.337 282.280 1744 281 c +1745 280 l +1750 282 l +1749.613 279.910 1749.616 280.289 1752 280 c +1752 272 l +1757 274 l +1760 269 l +1761.195 269.598 1760.978 269.466 1762 271 c +1762.901 269 1763 269 1765 268 c +1762.665 265.716 1761.409 264.229 1761 261 c +1758 264 l +1753.965 264.429 1751.657 266.859 1752 271 c +1749.312 271.592 1747.659 271.675 1745 271 c +1743.771 272.870 1743 273.224 1741 274 c +1740.752 276 1740.213 277 1739 279 c +1737 278.622 1736.240 278 1735 281 c +1734.839 281.375 1737 281.377 1734 282 c +1735.333 284 1735.679 285.552 1736 288 c +1732 286 l +1729.777 288.437 1726.208 287.912 1723 287.975 c +1714.614 288 1704 289.749 1696 288 c +1696.876 277.482 1696 266.572 1696 256 c +1680 256 l +1680 336 l +1760 336 l +1760 338 l +1679 338 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1774 338 m +1775 337 l +1774 338 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1775 338 m +1776.755 335.287 1777.833 333.611 1781 333 c +1779.210 335.445 1777.895 337 1775 338 c +f +*U +0.000 0.000 0.000 0.812 k +*u +360 337 m +361 336 l +360 337 l +f +*U +0.000 0.000 0.000 0.224 k +*u +361 337 m +362 336 l +361 337 l +f +*U +0.000 0.000 0.000 0.996 k +*u +479 337 m +479 330 478.884 323 479 316 c +479 313 479.940 309.399 478 307 c +478.598 305.805 478.466 306 480 305 c +461.492 303 442.591 304 424 304 c +418.504 304 408.270 302 404 306 c +401 304 l +400 336 l +384 336 l +384 256 l +400 256 l +400 264.332 399.915 272.669 400 281 c +400 285.375 401.167 289.738 400 294 c +415.345 295 430.608 295 446 295 c +455.295 295 464.832 295.702 474 294 c +473 296 l +474.850 295.798 476 295.798 478 296 c +477.952 293.670 477.797 293.994 480 293 c +479.776 291.316 479.782 290.687 480 289 c +478 290 l +480 278.957 479 267.203 479 256 c +495 256 l +495 336 l +489.600 336 484.282 335.742 479 337 c +f +*U +0.000 0.000 0.000 0.827 k +*u +801 337 m +802 336 l +801 337 l +f +*U +0.000 0.000 0.000 0.227 k +*u +802 337 m +803 336 l +802 337 l +f +*U +0.000 0.000 0.000 0.216 k +*u +881 337 m +882 336 l +881 337 l +f +*U +0.000 0.271 0.196 0.255 k +*u +1053 337 m +1054 336 l +1053 337 l +f +*U +0.043 0.000 0.071 0.396 k +*u +1288 337 m +1289 336 l +1288 337 l +f +*U +0.000 0.451 0.353 0.180 k +*u +1292 337 m +1293 336 l +1292 337 l +f +*U +0.000 0.702 0.553 0.298 k +*u +1293 337 m +1294.248 336.315 1294.548 336.251 1296 336 c +1294.752 336.685 1294.451 336.749 1293 337 c +f +*U +0.000 0.584 0.584 0.416 k +*u +1296 337 m +1297.248 336.315 1297.548 336.251 1299 336 c +1297.752 336.685 1297.452 336.749 1296 337 c +f +*U +0.000 0.635 0.443 0.357 k +*u +1299 337 m +1300 333 l +1300.751 335 1300.656 335.596 1299 337 c +f +*U +0.000 0.106 0.067 0.122 k +*u +1395 337 m +1396 336 l +1395 337 l +f +*U +0.000 0.000 0.000 0.098 k +*u +1521 336 m +1522.809 335.426 1523 335.535 1525 336 c +1523.341 336.406 1522.758 336.309 1521 336 c +f +*U +0.000 0.000 0.000 0.788 k +*u +1544 337 m +1545 336 l +1544 337 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1960 337 m +1953.445 335 1946.674 336 1940 334 c +1942 331.998 1942.903 330.929 1943 328 c +1939 330 l +1940 328 l +1937 329 l +1936.501 327.201 1936.267 326.281 1935 325 c +1934.834 323 1934.555 321.804 1934 320 c +1942 314 l +1944 320 l +1945 319 l +1944 324 l +1945.915 322.723 1945 322.723 1947 324 c +1944 328 l +1946.590 327.435 1950.248 327.898 1952.572 326.601 c +1956 324.606 1958 319.366 1960 316 c +1963.171 310.633 1966.869 306.574 1971 302 c +1976 304 l +1973.470 300.177 1975.978 297.212 1976 293 c +1978 293.501 1979 293.637 1981 293 c +1984.465 297.246 1986.168 301.549 1985 307 c +1981.505 305.871 1978.520 307.387 1975 308 c +1978 313 l +1976 316.927 1973.812 320.679 1970 323 c +1969.776 327.728 1965.586 329.413 1962 332 c +1961.274 329.821 1961.561 330.220 1960 331 c +1960.452 333.241 1960.838 334.884 1960 337 c +f +40 336 m +40 329 l +55 329 74 332.196 88 326 c +87 318.526 88 310.551 88 303 c +88 256 l +103 256 l +103 329 l +144 329 l +144 336 l +40 336 l +f +152 336 m +152 331.354 152.313 327 150 323 c +153.524 318.323 152 309.597 152 304 c +152 256 l +225 256 l +230.330 256 235.670 255.904 240.999 256 c +242.984 256 245.590 255.865 246.972 257.603 c +248.468 259.484 247.992 262.768 248 265 c +199 265 l +188.695 265 178.210 265.561 168 264 c +169.301 274.446 166.876 285.466 168 296 c +169 294.466 168.805 294.598 170 294 c +173.701 296.622 179.518 295.979 184 295.999 c +194.666 296 205.334 296 216 296 c +216 305 l +204.357 305 192.635 304.604 181 305 c +178 305 171 303.824 168.983 305.948 c +167.236 307.701 167.906 310.802 167.965 313 c +168 318.328 168 323.671 168 329 c +247 329 l +247 336 l +152 336 l +f +*U +0.000 0.000 0.000 0.090 k +*u +362 336 m +364.278 327.651 365 320.686 365 312 c +367 312 l +367 319.634 367.930 330.355 362 336 c +f +*U +0.000 0.000 0.000 0.682 k +*u +542 336 m +543 335 l +542 336 l +f +*U +0.000 0.000 0.000 0.996 k +*u +616 336 m +616 299 l +616 291.661 615.447 283.624 619 277 c +623 280 l +622.976 276.554 622 274.713 620 272 c +619 275 l +616 274.700 614.652 274.995 614 272 c +610 282 l +609.315 280.752 609.251 280.452 609 279 c +606.715 280.588 604.754 280.700 602 281 c +603.186 282.186 603.584 282.528 605 283 c +602 285.478 599.167 287.871 596 290 c +594 288 l +593.658 290.602 593.459 291.946 595 294 c +590 296.451 586.648 300.786 582 303.667 c +580.295 304.723 578.583 304.813 577 306 c +576 303 l +574.814 304.186 574.416 304.528 573 305 c +573 301 l +576 301 l +576 296 l +580.731 295.471 583.468 293.995 582 289 c +584 289 583.724 289 584 287 c +591 288 l +591.195 283.869 591.189 280.197 596 280 c +597.222 278.267 598 277.849 600 277 c +600.796 272.450 604 271.911 607 269 c +612 271 l +612 267 l +612.683 268.506 612.826 269.315 613 271 c +616 263 l +619.199 263 620.875 262.386 620 259 c +624.291 257.179 627.247 256 632 256 c +632 336 l +616 336 l +f +*U +0.000 0.000 0.000 0.137 k +*u +657 336 m +657 254 l +662.715 254 676 251.540 680 256 c +675.303 254.882 663.409 252.798 659.603 256.603 c +655.862 260.345 658 272 658 277 c +658 317 l +658 322.887 659.292 330.538 657 336 c +f +*U +0.000 0.000 0.000 0.996 k +*u +664 336 m +664 256 l +673 256 l +673 336 l +664 336 l +f +*U +0.000 0.000 0.000 0.196 k +*u +703 336 m +704 335 l +703 336 l +f +*U +0.000 0.000 0.000 0.114 k +*u +803 336 m +804 332 l +804.751 334 804.656 334.596 803 336 c +f +*U +0.000 0.000 0.000 0.996 k +*u +944 336 m +944 256 l +1011 256 l +1015.400 256 1027.971 253.850 1030.972 257.602 c +1032.312 259.276 1031.976 262 1032 264 c +978 264 l +971 264 961 262.350 955 266 c +952 265 l +953.343 272.365 952 280.485 952 288 c +952 336 l +944 336 l +f +*U +0.000 0.561 0.463 0.318 k +*u +1108 336 m +1108 333 l +1108.696 334.554 1108.696 334.446 1108 336 c +f +*U +0.000 0.302 0.224 0.157 k +*u +1189 336 m +1189 333 l +1189.696 334.554 1189.696 334.446 1189 336 c +f +*U +0.000 0.698 0.537 0.302 k +*u +1287 336 m +1287 330 l +1287.951 332.285 1287.951 333.715 1287 336 c +f +*U +0.000 0.118 0.063 0.176 k +*u +1288 336 m +1288 329 l +1289 331.534 1289 333.466 1288 336 c +f +*U +0.000 0.431 0.310 0.090 k +*u +1395 336 m +1396 335 l +1395 336 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1495 336 m +1496 335 l +1495 336 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1543 336 m +1544 335 l +1543 336 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1800 336 m +1800 256 l +1868 256 l +1874.243 256 1888.339 252.975 1888 262 c +1890 261 l +1886.645 265.749 1878.243 264 1873 264 c +1824 264 l +1830.868 266 1838.869 265 1846 265 c +1888 265 l +1883.280 266.981 1877 266 1872 266 c +1839 266 l +1834.423 266 1826.197 267.658 1823 264 c +1821 264.402 1820.943 264.402 1819 264 c +1814.610 274.280 1816.439 285 1816 296 c +1821 293 l +1822 296 l +1835.586 294.506 1850.274 296 1864 296 c +1864 304 l +1853 304 1842.000 303.951 1831 304 c +1825.937 304 1820.979 305 1816 304 c +1816.761 311.353 1817.516 320.795 1816 328 c +1823.794 328.871 1832 328 1840 328 c +1888 328 l +1888 336 l +1800 336 l +f +*U +0.000 0.000 0.000 0.710 k +*u +262 335 m +263 334 l +262 335 l +f +*U +0.000 0.000 0.000 0.149 k +*u +544 335 m +545.223 333.805 545.420 333.684 547 333 c +545.777 334.195 545.580 334.316 544 335 c +f +*U +0.000 0.000 0.000 0.200 k +*u +702.333 334.333 m +702.278 334.278 702.222 333.222 702.667 333.667 c +702.722 333.722 702.778 334.778 702.333 334.333 c +f +*U +0.000 0.000 0.000 0.733 k +*u +703 335 m +704 334 l +703 335 l +f +*U +0.000 0.000 0.000 1.000 k +*u +802 335 m +799.654 327.528 800 319.764 800 312 c +797.558 311.891 795.377 311.572 793 311 c +791.660 316.627 791.872 322.254 792 328 c +791.315 326.752 791.251 326.451 791 325 c +786.553 330.882 777.644 329 771 329 c +719 329 l +719 307.660 718.430 286.235 720 265 c +721.314 265.768 721.232 265.686 722 267 c +724 264 l +731.213 265.221 739.599 264 747 264 c +761.998 264 777 264.185 792 264 c +791.510 272.494 791.417 281.523 792 290 c +786 291 l +786 269 l +740 269 l +735.281 269 726.390 267.311 722.318 270 c +718.716 272.431 720 279.309 720 283 c +720 315 l +720 318.565 719 324.610 722.434 326.972 c +726.403 329.704 735.362 328 740 328 c +786 328 l +786 309 l +790.704 309.371 800.650 308.986 804.397 312 c +806.351 313.608 805.985 316.769 805.999 319 c +806 324.758 806 330.621 802 335 c +f +*U +0.000 0.635 0.451 0.365 k +*u +1053 335 m +1053 331 l +1053.710 332.759 1053.710 333.241 1053 335 c +f +*U +0.000 0.000 0.000 0.675 k +*u +1519 335 m +1520 334 l +1519 335 l +f +*U +0.000 0.000 0.000 0.255 k +*u +1520 335 m +1521 334 l +1520 335 l +f +*U +0.000 0.000 0.000 0.133 k +*u +849 334 m +849 330 l +850.434 331.393 851 332.233 852 334 c +849 334 l +f +*U +0.000 0.424 0.325 0.098 k +*u +1109 334 m +1110 333 l +1109 334 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1517 334 m +1518 333 l +1517 334 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1653 334 m +1656.654 318 1656 302.349 1656 286 c +1656 278.680 1656.716 269.601 1652.911 263 c +1649.440 256.988 1642.787 257.507 1639 253 c +1644.525 253.748 1649.893 255.313 1653.347 260 c +1657 265 1656.998 272 1657 278 c +1657 309 l +1657 317 1658.856 327.485 1653 334 c +f +*U +0.000 0.000 0.000 0.180 k +*u +1937.333 333.333 m +1937.278 333.278 1937.222 332.222 1937.667 332.667 c +1937.722 332.722 1937.778 333.778 1937.333 333.333 c +f +*U +0.000 0.000 0.000 0.686 k +*u +1938 334 m +1939 333 l +1938 334 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1968 334 m +1968.899 331.876 1968.876 331.899 1971 331 c +1969.896 332.457 1969.457 332.897 1968 334 c +f +*U +0.000 0.000 0.000 0.129 k +*u +260 333 m +257.599 323.720 258 314.513 258 305 c +258 292.256 257.999 279.680 259 267 c +260.908 271.636 259 277 259 282 c +258.781 292.964 258.746 304 259 315 c +259 320.683 261.674 327.556 260 333 c +f +*U +0.000 0.000 0.000 0.710 k +*u +261 333 m +262 332 l +261 333 l +f +*U +0.000 0.000 0.000 0.600 k +*u +546 333 m +547 332 l +546 333 l +f +*U +0.000 0.000 0.000 0.110 k +*u +547 333 m +550.358 328.622 554.915 325 560 323 c +556.600 327.482 552.218 330.882 547 333 c +f +*U +0.000 0.000 0.000 0.118 k +*u +701 333 m +698 319 699 305 699 291 c +699 282 698 272.632 701 264 c +702.590 269.170 700.275 275.621 700 281 c +699.560 291.942 699.887 303 700 314 c +700 319.906 702.716 327.418 701 333 c +f +*U +0.000 0.000 0.000 0.671 k +*u +702 333 m +703 332 l +702 333 l +f +*U +0.000 0.000 0.000 0.114 k +*u +884 333 m +884.684 331.420 884.805 331.223 886 330 c +885.316 331.580 885.195 331.777 884 333 c +f +*U +0.000 0.243 0.180 0.259 k +*u +1052 333 m +1052 330 l +1052.696 331.554 1052.696 331.446 1052 333 c +f +*U +0.000 0.157 0.165 0.176 k +*u +1111 333 m +1112 332 l +1111 333 l +f +*U +0.000 0.506 0.392 0.494 k +*u +1300 333 m +1300 329 l +1304 329 l +1300 333 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1487 331 m +1488.580 331.683 1488.777 331.805 1490 333 c +1488.419 332.316 1488.223 332.196 1487 331 c +f +*U +0.000 0.000 0.000 0.718 k +*u +1490 333 m +1491 332 l +1490 333 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1513 331 m +1515.509 330.434 1516.220 331 1518 333 c +1516 332.453 1514.745 331.890 1513 331 c +f +1540 333 m +1538 326 l +1540.353 327.901 1540.877 330 1540 333 c +f +*U +0.000 0.000 0.000 0.765 k +*u +1541 333 m +1542 332 l +1541 333 l +f +*U +0.000 0.000 0.000 0.141 k +*u +805 332 m +806 324 l +807.232 327 806.825 329.328 805 332 c +f +*U +0.000 0.435 0.435 0.565 k +*u +1111 332 m +1112 331 l +1111 332 l +f +*U +0.000 0.184 0.137 0.361 k +*u +1112 332 m +1113 331 l +1112 332 l +f +*U +0.000 0.263 0.329 0.384 k +*u +1191 332 m +1192 331 l +1191 332 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1779 332 m +1780 331 l +1779 332 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1780.333 331.333 m +1780.278 331.278 1780.222 330.222 1780.667 330.667 c +1780.722 330.723 1780.777 331.778 1780.333 331.333 c +f +*U +0.000 0.549 0.490 0.451 k +*u +1105 330 m +1107.890 328.787 1110.874 329 1114 329 c +1111.184 330.629 1108.238 330 1105 330 c +f +*U +0.000 0.392 0.294 0.184 k +*u +1113 331 m +1114 330 l +1113 331 l +f +*U +0.000 0.220 0.153 0.102 k +*u +1396 331 m +1397 330 l +1396 331 l +f +*U +0.000 0.000 0.000 0.157 k +*u +1483 330 m +1484.809 329.426 1485 329.535 1487 330 c +1485.341 330.406 1484.758 330.309 1483 330 c +f +*U +0.000 0.000 0.000 0.753 k +*u +1512 331 m +1513 330 l +1512 331 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1969 331 m +1970 330 l +1969 331 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1970.333 330.333 m +1970.278 330.278 1970.222 329.222 1970.667 329.667 c +1970.722 329.722 1970.778 330.778 1970.333 330.333 c +f +*U +0.000 0.000 0.000 0.596 k +*u +260 330 m +261 329 l +260 330 l +f +*U +0.000 0.000 0.000 0.616 k +*u +701 330 m +702 329 l +701 330 l +f +*U +0.000 0.000 0.000 0.714 k +*u +849 330 m +850 329 l +849 330 l +f +*U +0.000 0.000 0.000 0.761 k +*u +885 330 m +886 329 l +885 330 l +f +*U +0.000 0.000 0.000 0.102 k +*u +886 330 m +886.944 327 888.286 324.624 890 322 c +890.962 325.672 888.789 327.790 886 330 c +f +*U +0.000 0.584 0.482 0.416 k +*u +1052 330 m +1053.506 329.317 1054.315 329.174 1056 329 c +1054.494 329.683 1053.685 329.826 1052 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1056 330 m +1060.720 328 1066.920 329 1072 329 c +1105 329 l +1100.280 330.981 1094 330 1089 330 c +1056 330 l +f +*U +0.000 0.169 0.149 0.224 k +*u +1114 330 m +1115 329 l +1114 330 l +f +*U +0.000 0.404 0.278 0.247 k +*u +1193 330 m +1194 329 l +1193 330 l +f +*U +0.000 0.541 0.431 0.459 k +*u +1194 330 m +1195.769 329.221 1197 329 1199 329 c +1197.231 329.779 1195.964 329.912 1194 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1199 330 m +1205.919 327 1216.520 329 1224 329 c +1280 329 l +1273 331.903 1262.480 330 1255 330 c +1199 330 l +f +*U +0.000 0.522 0.400 0.478 k +*u +1280 330 m +1282.613 328.902 1285 329 1288 329 c +1285.387 330 1282.835 329.993 1280 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1304 330 m +1311.399 326.895 1322.993 329 1331 329 c +1392 329 l +1384.600 332 1373 330 1365 330 c +1304 330 l +f +*U +0.000 0.216 0.141 0.404 k +*u +1396 330 m +1397 329 l +1396 330 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1508 328 m +1510 327.590 1510.963 328 1513 329 c +1510.860 329.410 1510 328.968 1508 328 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1780 330 m +1780 328 l +1782 328 l +1782 330 l +1780 330 l +f +*U +0.000 0.000 0.000 0.231 k +*u +1935 330 m +1936 329 l +1935 330 l +f +*U +0.000 0.000 0.000 0.655 k +*u +364 329 m +365 328 l +364 329 l +f +*U +0.000 0.000 0.000 0.808 k +*u +551 329 m +552 328 l +551 329 l +f +*U +0.000 0.000 0.000 0.612 k +*u +805 329 m +806 328 l +805 329 l +f +*U +0.000 0.000 0.000 0.000 k +*u +866.667 328.667 m +866.222 328.222 867.278 328.278 867.333 328.333 c +867.778 328.778 866.722 328.722 866.667 328.667 c +f +*U +0.000 0.169 0.114 0.063 k +*u +1195 329 m +1196 328 l +1195 329 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1558 327 m +1555.663 327.519 1554.360 327.480 1552 327 c +1558.248 321 1557 315 1557 307 c +1557 272 l +1555.308 277.725 1556 284 1556 290 c +1556 320 l +1554 315.531 1555 309.809 1555 305 c +1555 294 1552.890 280.522 1556 270 c +1552.911 274 1554 280 1554 285 c +1554 321 l +1552.231 316.785 1553 311.536 1553 307 c +1553 280 l +1552.994 276 1550.995 269.732 1554 267 c +1552.964 265.814 1552.661 265.396 1552 264 c +1555 264.614 1554.395 263.395 1557 266 c +1557 264 l +1562 268.917 1571.341 267 1578 267 c +1633 267 l +1631.723 265 1631.723 265.915 1633 264 c +1634 265 1634.308 265.611 1635 267 c +1636.757 265.267 1637.642 264.659 1640 264 c +1639.402 265.195 1639.534 264.978 1638 266 c +1641.511 269.368 1640 277.401 1640 282 c +1640 311 l +1640.000 315 1638.806 320.206 1640 324 c +1639 328 l +1619 327.290 1597.519 328 1577 328 c +1572.735 328 1568.242 327.588 1564 328 c +1561 328.277 1559.227 330 1558 327 c +f +*U +0.000 0.000 0.000 0.820 k +*u +1654 329 m +1655 328 l +1654 329 l +f +*U +0.000 0.000 0.000 0.243 k +*u +1934 329 m +1935 328 l +1934 329 l +f +*U +0.000 0.000 0.000 0.737 k +*u +1935 329 m +1936 328 l +1935 329 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1971 329 m +1972 328 l +1971 329 l +f +*U +0.000 0.000 0.000 0.000 k +*u +104 328 m +108.215 326.231 113.464 327 118 327 c +147 327 l +142.785 328.769 137.536 328 133 328 c +104 328 l +f +*U +0.000 0.000 0.000 0.133 k +*u +104 327 m +104 255 l +99.198 255 88.240 252.966 84.603 256.603 c +81 260 83 270.410 83 275 c +83 327 l +40 327 l +44.215 325.231 49.464 326 54 326 c +82 326 l +82 254 l +105 254 l +105 326 l +147 326 l +147 254 l +250 254 l +250 270 l +248 265.529 249 259.817 249 255 c +175 255 l +169 255 162.999 254.959 157 255 c +154.582 255 151.474 254.732 149.603 256.603 c +146 260 148 270.410 148 275 c +148 292.208 145.855 311 149 328 c +134.538 325.315 118.684 327 104 327 c +f +*U +0.000 0.000 0.000 0.867 k +*u +279 328 m +279 270 l +280.981 274.720 280 280.920 280 286 c +280 314 l +280 318.536 280.769 323.785 279 328 c +f +*U +0.000 0.000 0.000 0.000 k +*u +280 328 m +285.951 325.503 294.580 327 301 327 c +345 327 l +339 329.497 330.420 328 324 328 c +280 328 l +f +721 328 m +726.951 325.503 735.580 327 742 327 c +786 327 l +780 329.497 771.420 328 765 328 c +721 328 l +f +*U +0.000 0.000 0.000 0.082 k +*u +846 328 m +844.296 325 842.939 322.260 842 319 c +844.821 321.605 846.482 324.483 848 328 c +846 328 l +f +*U +0.000 0.000 0.000 0.102 k +*u +865 325 m +866.457 326 866.897 326.543 868 328 c +865.876 327 865.899 327 865 325 c +f +*U +0.000 0.000 0.000 0.125 k +*u +1472 321 m +1482 327 l +1477.705 327.702 1473.987 324.621 1472 321 c +f +*U +0.000 0.000 0.000 0.702 k +*u +1482 328 m +1483 327 l +1482 328 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1507 328 m +1508 327 l +1507 328 l +f +*U +0.000 0.000 0.000 0.890 k +*u +1780.333 327.333 m +1780.278 327.278 1780.222 326.222 1780.667 326.667 c +1780.722 326.723 1780.777 327.778 1780.333 327.333 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1781 328 m +1781 300 l +1783.604 306.207 1783.604 321.793 1781 328 c +f +*U +0.000 0.000 0.000 0.098 k +*u +1952 328 m +1952.684 326.420 1952.805 326.223 1954 325 c +1953.316 326.580 1953.195 326.777 1952 328 c +f +*U +0.000 0.000 0.000 0.686 k +*u +1971 328 m +1972 327 l +1971 328 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1972 328 m +1973.508 323.269 1976.410 319.216 1979 315 c +1980.187 319.889 1975.422 324.898 1972 328 c +f +*U +0.000 0.000 0.000 0.141 k +*u +280 327 m +280 272 l +282.189 277.217 281 284.381 281 290 c +281 326 l +344 326 l +338.293 328.395 330 327 324 327 c +280 327 l +f +*U +0.000 0.000 0.000 0.106 k +*u +344 327 m +342.423 321.665 341 310.732 346 307 c +344.820 313.355 346.459 321 344 327 c +f +*U +0.000 0.000 0.000 0.153 k +*u +721 327 m +721 270 l +786 270 l +780.293 272.395 772 271 766 271 c +722 271 l +722 326 l +784 326 l +784 319.757 783.222 313 785 307 c +787.709 307.648 790.216 307.942 793 308 c +791 308.871 788.187 308.991 786.603 310.603 c +783.338 313.925 785 322.689 785 327 c +721 327 l +f +*U +0.000 0.000 0.000 0.075 k +*u +785 327 m +785 310 l +786.883 314.486 786.883 322.514 785 327 c +f +*U +0.000 0.000 0.000 0.592 k +*u +847 327 m +848 326 l +847 327 l +f +*U +0.000 0.000 0.000 0.000 k +*u +867 327 m +863.441 323.609 861.755 319.216 858 316 c +857.516 312.696 856.536 311 854 309 c +852.926 302.808 847.781 296.667 845 291 c +889 291 l +886.655 296.373 883 300.984 880 305.996 c +875.946 312.991 872.250 320.731 867 327 c +f +*U +0.000 0.000 0.000 0.161 k +*u +868.333 326.333 m +868.278 326.278 868.222 325.222 868.667 325.667 c +868.722 325.722 868.778 326.778 868.333 326.333 c +f +*U +0.000 0.000 0.000 0.129 k +*u +1506.667 326.667 m +1506.222 326.222 1507.278 326.278 1507.333 326.333 c +1507.778 326.778 1506.722 326.722 1506.667 326.667 c +f +*U +0.000 0.000 0.000 0.012 k +*u +1559 325 m +1567.923 327 1577.866 326 1587 326 c +1636 326 l +1630.537 328.292 1622.887 327 1617 327 c +1577 327 l +1572 327 1562.407 328.899 1559 325 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1698 327 m +1703.217 324.811 1710.381 326 1716 326 c +1755 326 l +1749.783 328.189 1742.619 327 1737 327 c +1698 327 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1755 327 m +1756.717 325 1757.566 324.651 1760 324 c +1758.314 325.656 1757.254 326.251 1755 327 c +f +*U +0.000 0.000 0.000 0.761 k +*u +1757 327 m +1758 326 l +1757 327 l +f +*U +0.000 0.000 0.000 0.075 k +*u +1818 327 m +1818 320.654 1817.522 314.208 1819 308 c +1821 312.974 1820 319.638 1820 325 c +1897 325 l +1891.726 328.996 1881.423 327 1875 327 c +1818 327 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1951 327 m +1952 326 l +1951 327 l +f +*U +0.000 0.000 0.000 0.071 k +*u +148 326 m +148 256 l +150 260.969 149 267.650 149 273 c +149 307 l +149 312.887 150.292 320.538 148 326 c +f +*U +0.000 0.000 0.000 0.820 k +*u +555 326 m +556 325 l +555 326 l +f +*U +0.000 0.000 0.000 0.859 k +*u +720 326 m +720 270 l +721.769 274.215 721 279.465 721 284 c +721 311 l +721 315.809 721.875 321.531 720 326 c +f +*U +0.000 0.000 0.000 0.671 k +*u +864 326 m +865 325 l +864 326 l +f +*U +0.000 0.000 0.000 0.639 k +*u +869 326 m +870 325 l +869 326 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1503 324 m +1504.580 324.683 1504.777 324.805 1506 326 c +1504.420 325.316 1504.223 325.195 1503 324 c +f +*U +0.000 0.000 0.000 0.161 k +*u +1538 326 m +1538 268 l +1539.981 272.720 1539 278.920 1539 284 c +1539 312 l +1539 316.536 1539.769 321.785 1538 326 c +f +*U +0.000 0.000 0.000 0.600 k +*u +1539 326 m +1540 325 l +1539 326 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1559 269 m +1636 269 l +1636 326 l +1579 326 l +1574.766 326 1562.918 328 1560 324.397 c +1557.456 321 1559 312.929 1559 309 c +1559 269 l +f +*U +0.000 0.000 0.000 0.067 k +*u +1698 326 m +1698 302 l +1700.633 308.274 1699.858 319 1700 326 c +1698 326 l +f +*U +0.000 0.000 0.000 0.000 k +*u +1700 326 m +1700 302 l +1719 302 1740.201 299.510 1759 303 c +1759 308 1761.253 320.332 1757.397 324 c +1754 327.425 1746.315 326 1742 326 c +1700 326 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1932 326 m +1929 321.997 1926.230 317.784 1925 313 c +1928.309 316 1932.684 321.314 1932 326 c +f +*U +0.000 0.000 0.000 0.576 k +*u +1933 326 m +1934 325 l +1933 326 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1951 326 m +1949.286 323.376 1947.944 320.987 1947 318 c +1949.464 320.284 1951.502 322.551 1951 326 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1952 326 m +1950.218 322.226 1947.742 319.243 1948 315 c +1940 310.991 1935 297.600 1931 290 c +1945.210 290 1959.845 291 1974 290 c +1970.750 297.805 1965.749 304.792 1961.370 312 c +1958.365 316.945 1956.264 321.945 1952 326 c +f +*U +0.000 0.000 0.000 0.627 k +*u +1954 326 m +1955 325 l +1954 326 l +f +*U +0.000 0.000 0.000 0.141 k +*u +869 325 m +869.944 322 871.286 319.624 873 317 c +873.502 320.449 871.464 322.716 869 325 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1477 325 m +1478 324 l +1477 325 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1502 325 m +1503 324 l +1502 325 l +f +*U +0.000 0.000 0.000 0.882 k +*u +1539.333 324.333 m +1539.278 324.278 1539.222 323.222 1539.667 323.667 c +1539.723 323.723 1539.777 324.778 1539.333 324.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1560 325 m +1560 270 l +1635 270 l +1635 309 l +1635 312.731 1636.423 320.302 1633.972 323.397 c +1631 327 1619.234 325 1615 325 c +1560 325 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1954 325 m +1954.547 323 1955 321.744 1956 320 c +1956.375 322.419 1955.693 323.218 1954 325 c +f +*U +0.000 0.000 0.000 0.000 k +*u +700.333 323.333 m +700.277 323.278 700.222 322.222 700.667 322.667 c +700.722 322.722 700.778 323.778 700.333 323.333 c +f +*U +0.000 0.000 0.000 0.090 k +*u +806 324 m +806 311 l +808.794 314.688 808 319.519 808 324 c +806 324 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1496 321 m +1498.837 320.325 1500.522 321.495 1503 323 c +1500.311 323.405 1498.444 322.225 1496 321 c +f +*U +0.000 0.000 0.000 0.651 k +*u +1655.333 323.333 m +1655.278 323.278 1655.222 322.222 1655.667 322.667 c +1655.722 322.722 1655.777 323.778 1655.333 323.333 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1759 324 m +1759 303 l +1761.351 307.369 1761.449 319.711 1759 324 c +f +*U +0.000 0.000 0.000 0.780 k +*u +1949 324 m +1950 323 l +1949 324 l +f +*U +0.000 0.000 0.000 0.757 k +*u +559 323 m +560 322 l +559 323 l +f +*U +0.000 0.000 0.000 0.090 k +*u +560 323 m +562.319 320 564.622 318.432 568 317 c +565.709 320 563.641 321.761 560 323 c +f +*U +0.000 0.000 0.000 0.831 k +*u +871 323 m +872 322 l +871 323 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1474 323 m +1475 322 l +1474 323 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1760 323 m +1761 322 l +1760 323 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1956 323 m +1957 322 l +1956 323 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1974 323 m +1975 322 l +1974 323 l +f +*U +0.000 0.000 0.000 0.824 k +*u +560 322 m +561 321 l +560 322 l +f +*U +0.000 0.000 0.000 0.749 k +*u +844 322 m +845 321 l +844 322 l +f +*U +0.000 0.000 0.000 0.122 k +*u +862 322 m +861 320.255 860.547 318.875 860 317 c +861.693 318.782 862.375 319.581 862 322 c +f +*U +0.000 0.000 0.000 0.827 k +*u +890 322 m +891 321 l +890 322 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1471 322 m +1472 321 l +1471 322 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1497 322 m +1498 321 l +1497 322 l +f +*U +0.000 0.000 0.000 0.871 k +*u +1655 322 m +1655 274 l +1656.552 277.699 1656 282 1656 286 c +1656 309 l +1656 313.260 1656.661 318 1655 322 c +f +*U +0.000 0.000 0.000 0.616 k +*u +259 321 m +259 276 l +260.661 279.959 260 284.740 260 289 c +260 310 l +260 313.702 260.441 317.565 259 321 c +f +*U +0.000 0.000 0.000 0.635 k +*u +700 321 m +700 276 l +701.661 279.959 701 284.740 701 289 c +701 310 l +701 313.702 701.441 317.565 700 321 c +f +*U +0.000 0.000 0.000 0.996 k +*u +879 319 m +879.508 316.408 879.508 314.593 879 312 c +883 310 l +883.986 311.479 884 311.203 884 313 c +885.493 312 885.266 312 887 312 c +886.423 309.289 886.232 308.605 889 308 c +887.522 307 887.797 307 886 307 c +887.791 304 888.463 290.190 895 296 c +896 290 l +890.818 288.394 885.381 289 880 289 c +853 289 l +847.537 289 840.729 287.777 841 295 c +839.521 295.986 839.797 296 838 296 c +838.986 297.479 839 297.203 839 299 c +834 302 l +832.781 298.586 832.532 293.624 830.647 290.607 c +827.879 286.179 821.909 286.980 823 280 c +817 279 l +817.194 276.894 817.417 275 818 273 c +816.203 273 816.479 272.986 815 272 c +815.224 269.625 815.214 267.376 815 265 c +813 268 l +809.974 264.391 807.832 260.662 807 256 c +817 256 l +816 261 l +818.172 261.464 819.958 262 822 263 c +821 261 l +823.979 261.596 822.733 262.567 825 262 c +825.613 263.661 826 264.483 827 266 c +825.550 267.608 824.949 268 823 269 c +826 271 l +826 269.203 826 269.479 827 268 c +830.854 272 832.458 276 838 278.532 c +842.983 280.687 848.690 280 854 280 c +882 280 l +887.552 280 893 280.668 898 278 c +899.804 278.555 901 278.834 903 279 c +901 276 l +904 275 l +903 272 l +907.215 271.394 911.430 271.215 911 266 c +910 268 l +908.235 265.304 908.957 263.863 912 263 c +910.624 253 923 255.829 929 258 c +926.540 260.196 924.463 262 923 265 c +921.919 263.542 921.564 262.752 921 261 c +920.862 263.667 921 264 923 266 c +922.434 267.773 922 269 922 271 c +919 274 l +916 273 l +918 277 l +914.586 280.751 911 284.951 910 290 c +905.168 290 904.463 292.500 905 297 c +903.203 297 903.479 296.986 902 296 c +901 299 l +899.177 298.255 897.977 298 896 298 c +898 301 l +895.658 301.781 895.980 301.654 898 303 c +897.455 304.635 897.635 304.455 896 305 c +897.550 308 896.183 309.916 895 313 c +892.440 312.887 890.456 313.265 888 314 c +888.496 316.556 888.442 318.429 888 321 c +884.864 320.580 881.976 320 879 319 c +f +*U +0.000 0.000 0.000 0.157 k +*u +892.333 320.333 m +892.278 320.278 892.222 319.222 892.667 319.667 c +892.722 319.722 892.778 320.778 892.333 320.333 c +f +1464 318 m +1466.690 317.595 1468.556 318.775 1471 320 c +1468 320.675 1466.478 319.505 1464 318 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1760 321 m +1760 307 l +1761.667 310.972 1761.667 317 1760 321 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1930 321 m +1931 320 l +1930 321 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1957 321 m +1958 320 l +1957 321 l +f +*U +0.000 0.000 0.000 0.027 k +*u +539 320 m +539 317 l +539.696 318.554 539.696 318.446 539 320 c +f +*U +0.000 0.000 0.000 0.765 k +*u +563 320 m +564 319 l +563 320 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1469 320 m +1470 319 l +1469 320 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1699 320 m +1699 313.654 1699.478 307.208 1698 301 c +1701 301 l +1699.540 307 1701.403 314.274 1699 320 c +f +*U +0.000 0.000 0.000 0.647 k +*u +1976 320 m +1977 319 l +1976 320 l +f +*U +0.000 0.000 0.000 0.761 k +*u +540 319 m +541 318 l +540 319 l +f +*U +0.000 0.000 0.000 0.125 k +*u +841 319 m +840 317.255 839.547 315.875 839 314 c +840.693 315.782 841.375 316.581 841 319 c +f +*U +0.000 0.000 0.000 0.745 k +*u +842 319 m +843 318 l +842 319 l +f +*U +0.000 0.000 0.000 0.725 k +*u +892 319 m +893 318 l +892 319 l +f +*U +0.000 0.000 0.000 0.094 k +*u +893 319 m +893.684 317.420 893.805 317.223 895 316 c +894.316 317.580 894.195 317.777 893 319 c +f +*U +0.000 0.118 0.239 0.184 k +*u +1051 319 m +1052 318 l +1051 319 l +f +*U +0.000 0.216 0.047 0.082 k +*u +1052 319 m +1053 318 l +1052 319 l +f +*U +0.000 0.129 0.059 0.169 k +*u +1109 319 m +1110.506 318.317 1111.315 318.174 1113 318 c +1111.494 318.683 1110.685 318.826 1109 319 c +f +*U +0.000 0.169 0.122 0.137 k +*u +1126 319 m +1127.769 318.221 1129 318 1131 318 c +1129.231 318.779 1127.964 318.912 1126 319 c +f +*U +0.000 0.176 0.106 0.153 k +*u +1202 319 m +1203.249 318.315 1203.548 318.251 1205 318 c +1203.752 318.685 1203.451 318.749 1202 319 c +f +*U +0.000 0.251 0.184 0.110 k +*u +1281.667 318.667 m +1281.222 318.222 1282.278 318.278 1282.333 318.333 c +1282.778 318.778 1281.722 318.722 1281.667 318.667 c +f +*U +0.000 0.075 0.059 0.153 k +*u +1297.667 318.667 m +1297.222 318.222 1298.278 318.278 1298.333 318.333 c +1298.778 318.778 1297.722 318.722 1297.667 318.667 c +f +*U +0.000 0.098 0.078 0.227 k +*u +1396.667 318.667 m +1396.222 318.222 1397.278 318.278 1397.333 318.333 c +1397.778 318.778 1396.722 318.722 1396.667 318.667 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1492 319 m +1493 318 l +1492 319 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1946 319 m +1947 318 l +1946 319 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1958.333 318.333 m +1958.278 318.278 1958.222 317.222 1958.667 317.667 c +1958.723 317.723 1958.777 318.777 1958.333 318.333 c +f +540 318 m +540 255 l +542.395 260.707 541 268.846 541 275 c +541 316 l +543 314.242 544.581 313 547 312 c +544.951 314.832 543 316.520 540 318 c +f +*U +0.000 0.000 0.000 0.765 k +*u +859 318 m +860 317 l +859 318 l +f +*U +0.000 0.000 0.000 0.675 k +*u +874 318 m +875 317 l +874 318 l +f +*U +0.000 0.388 0.294 0.078 k +*u +1050 318 m +1050 315 l +1050.696 316.554 1050.696 316.446 1050 318 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1051 318 m +1056.707 315.605 1064.846 317 1071 317 c +1112 317 l +1106.293 319.395 1098 318 1092 318 c +1051 318 l +f +*U +0.000 0.235 0.204 0.765 k +*u +1112 318 m +1113 317 l +1112 318 l +f +*U +0.000 0.643 0.482 0.357 k +*u +1120 314 m +1124.336 312.848 1128 316.766 1133 316 c +1128.217 319.622 1124.585 316.330 1120 314 c +f +*U +0.000 0.263 0.180 0.149 k +*u +1132 318 m +1133 317 l +1132 318 l +f +*U +0.000 0.314 0.196 0.310 k +*u +1202 318 m +1203 317 l +1202 318 l +f +*U +0.000 0.580 0.467 0.420 k +*u +1203.667 317.667 m +1203.222 317.222 1204.278 317.278 1204.333 317.333 c +1204.778 317.778 1203.722 317.722 1203.667 317.667 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1204 317 m +1205.623 314.565 1208.716 314.819 1206 316 c +1213.999 318.364 1223.688 317 1232 317 c +1282 317 l +1281 312 l +1282.580 311.317 1282.777 311.195 1284 310 c +1284.985 312.806 1283.633 315 1283 318 c +1231 318 l +1222.393 318 1212.280 319.447 1204 317 c +f +*U +0.000 0.208 0.153 0.102 k +*u +1283 318 m +1283 315 l +1283.696 316.554 1283.696 316.446 1283 318 c +f +*U +0.000 0.878 0.627 0.122 k +*u +1296 318 m +1295.570 312.551 1295.260 311.437 1299 307.500 c +1298 307 l +1306 303.593 1319.203 306 1328 306 c +1397 306 l +1397 317 l +1331 317 l +1319.718 317 1307 315.379 1296 318 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1297 318 m +1305 314.593 1318.203 317 1327 317 c +1396 317 l +1387.882 320.407 1374.797 318 1366 318 c +1297 318 l +f +*U +0.000 0.600 0.616 0.376 k +*u +1396 318 m +1397 315 l +1397.685 316.248 1397.749 316.549 1398 318 c +1396 318 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1466 318 m +1467 317 l +1466 318 l +f +*U +0.000 0.000 0.000 0.792 k +*u +1490 318 m +1491 317 l +1490 318 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1946 318 m +1945 316.255 1944.547 314.875 1944 313 c +1948 315 l +1947.309 316.388 1947 316.861 1946 318 c +f +*U +0.000 0.000 0.000 0.576 k +*u +539.333 316.333 m +539.278 316.278 539.222 315.222 539.667 315.667 c +539.722 315.722 539.778 316.778 539.333 316.333 c +f +*U +0.000 0.000 0.000 0.659 k +*u +567 317 m +568 316 l +567 317 l +f +*U +0.000 0.000 0.000 0.051 k +*u +568 317 m +570 314.542 571.790 313.641 575 313 c +572.841 315 570.801 316 568 317 c +f +*U +0.000 0.000 0.000 0.114 k +*u +874 317 m +874.547 315 875 313.745 876 312 c +876.375 314.419 875.693 315.218 874 317 c +f +*U +0.000 0.682 0.776 0.188 k +*u +1051 317 m +1051 312 l +1051.830 314 1051.830 314.970 1051 317 c +f +*U +0.000 0.906 0.667 0.094 k +*u +1052 317 m +1051 306 l +1135 306 l +1133.239 309.561 1132.478 312 1133 316 c +1126.471 317.490 1123 311.750 1117 312.502 c +1113.762 312.910 1112.182 316.296 1108.896 316.852 c +1102.898 317.867 1096 317 1090 317 c +1052 317 l +f +*U +0.000 0.451 0.329 0.314 k +*u +1112.333 316.333 m +1112.278 316.278 1112.222 315.222 1112.667 315.667 c +1112.722 315.723 1112.777 316.778 1112.333 316.333 c +f +*U +0.000 0.235 0.176 0.110 k +*u +1124 317 m +1125 316 l +1124 317 l +f +*U +0.000 0.259 0.176 0.353 k +*u +1133 317 m +1134 316 l +1133 317 l +f +*U +0.000 0.380 0.247 0.129 k +*u +1203 317 m +1204 316 l +1203 317 l +f +*U +0.000 0.882 0.647 0.118 k +*u +1206 317 m +1207.364 315.181 1207.492 315.969 1207 314 c +1212 313 l +1210.952 311 1210.488 310 1210 308 c +1217.426 305 1226 307.997 1234 308 c +1252.180 308 1270 308.419 1288 306 c +1285.880 308.630 1284.237 310.917 1281 312 c +1281.562 313.801 1281.824 315 1282 317 c +1206 317 l +f +*U +0.000 0.310 0.224 0.200 k +*u +1295 317 m +1296 316 l +1295 317 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1457 314 m +1459.837 313.325 1461.522 314.495 1464 316 c +1461.311 316.405 1459.444 315.225 1457 314 c +f +*U +0.000 0.000 0.000 0.616 k +*u +1464 317 m +1465 316 l +1464 317 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1489.667 316.667 m +1489.222 316.222 1490.278 316.278 1490.333 316.333 c +1490.778 316.778 1489.722 316.722 1489.667 316.667 c +f +*U +0.000 0.000 0.000 0.118 k +*u +1959 317 m +1959.899 313.173 1961.819 310.249 1964 307 c +1964.572 310.923 1961.728 314.354 1959 317 c +f +*U +0.000 0.000 0.000 0.608 k +*u +894 316 m +895 315 l +894 316 l +f +*U +0.000 0.000 0.000 0.075 k +*u +895 316 m +895.547 314 896 312.745 897 311 c +897.710 313.531 897 314.516 895 316 c +f +*U +0.000 0.278 0.204 0.031 k +*u +1123 316 m +1124 315 l +1123 316 l +f +*U +0.000 0.569 0.404 0.431 k +*u +1133.333 315.333 m +1133.278 315.278 1133.222 314.222 1133.667 314.667 c +1133.722 314.722 1133.777 315.778 1133.333 315.333 c +f +*U +0.000 0.165 0.125 0.169 k +*u +1134 316 m +1135 315 l +1134 316 l +f +*U +0.000 0.275 0.200 0.145 k +*u +1294 316 m +1295 315 l +1294 316 l +f +*U +0.000 0.675 0.494 0.325 k +*u +1295 316 m +1294 314 l +1296 314 l +1296 315.853 1296.300 315.350 1295 316 c +f +*U +0.000 0.306 0.353 0.027 k +*u +1398.333 315.333 m +1398.278 315.278 1398.222 314.222 1398.667 314.667 c +1398.722 314.722 1398.777 315.778 1398.333 315.333 c +f +*U +0.000 0.000 0.000 0.106 k +*u +1481 312 m +1484.534 311.424 1486.762 313.397 1489 316 c +1486 314.955 1483.618 313.586 1481 312 c +f +*U +0.000 0.000 0.000 0.788 k +*u +1927 316 m +1928 315 l +1927 316 l +f +*U +0.000 0.000 0.000 0.859 k +*u +539 315 m +539 255 l +540.875 259.469 540 265.191 540 270 c +540 299 l +540 304 540.981 310.280 539 315 c +f +*U +0.000 0.000 0.000 0.125 k +*u +858 315 m +857 313.521 857 313.797 857 312 c +858.289 313.443 858.401 313.234 858 315 c +f +*U +0.000 0.459 0.424 0.192 k +*u +1050 315 m +1050 310 l +1050.830 312 1050.830 312.970 1050 315 c +f +*U +0.000 0.412 0.314 0.125 k +*u +1113 315 m +1114 314 l +1113 315 l +f +*U +0.000 0.286 0.208 0.231 k +*u +1121 315 m +1122 314 l +1121 315 l +f +*U +0.000 0.290 0.212 0.141 k +*u +1205 315 m +1206 314 l +1205 315 l +f +*U +0.000 0.396 0.286 0.176 k +*u +1283 315 m +1284 314 l +1283 315 l +f +*U +0.000 0.796 0.769 0.141 k +*u +1397 315 m +1397 306 l +1398.256 308.994 1398.256 312 1397 315 c +f +*U +0.000 0.000 0.000 0.816 k +*u +1461 315 m +1462 314 l +1461 315 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1485 315 m +1486 314 l +1485 315 l +f +1979 315 m +1980 314 l +1979 315 l +f +*U +0.000 0.000 0.000 0.710 k +*u +571 314 m +572 313 l +571 314 l +f +*U +0.000 0.000 0.000 0.094 k +*u +837 314 m +837 311 l +838.195 312.223 838.316 312.420 839 314 c +837 314 l +f +*U +0.000 0.000 0.000 0.816 k +*u +839 314 m +840 313 l +839 314 l +f +*U +0.000 0.533 0.424 0.467 k +*u +1113 314 m +1114.543 312.733 1115 312.511 1117 312 c +1115.542 313 1114.752 313.436 1113 314 c +f +*U +0.000 0.196 0.169 0.216 k +*u +1119 314 m +1120 313 l +1119 314 l +f +*U +0.000 0.427 0.376 0.573 k +*u +1132 314 m +1132 310 l +1132.710 311.759 1132.710 312.241 1132 314 c +f +*U +0.000 0.376 0.282 0.247 k +*u +1133 314 m +1134 313 l +1133 314 l +f +*U +0.000 0.188 0.165 0.110 k +*u +1206 314 m +1207 313 l +1206 314 l +f +*U +0.000 0.290 0.278 0.710 k +*u +1207 314 m +1208 313 l +1207 314 l +f +*U +0.000 0.710 0.490 0.290 k +*u +1208 314 m +1209 309 l +1210.274 310.341 1211 311.403 1212 313 c +1208 314 l +f +*U +0.000 0.467 0.373 0.533 k +*u +1294 314 m +1294 311 l +1294.696 312.554 1294.696 312.446 1294 314 c +f +*U +0.000 0.420 0.451 0.094 k +*u +1398 314 m +1398 309 l +1398.830 311 1398.830 311.970 1398 314 c +f +*U +0.000 0.000 0.000 0.733 k +*u +1943 314 m +1944 313 l +1943 314 l +f +*U +0.000 0.000 0.000 0.149 k +*u +1981 314 m +1982 310 l +1982.553 312 1982.303 312.332 1981 314 c +f +*U +0.000 0.000 0.000 0.792 k +*u +547 313 m +548 312 l +547 313 l +f +*U +0.000 0.000 0.000 0.137 k +*u +573 313 m +574.223 311.805 574.420 311.684 576 311 c +574.777 312.195 574.580 312.316 573 313 c +f +*U +0.000 0.000 0.000 0.663 k +*u +856 313 m +857 312 l +856 313 l +f +*U +0.000 0.000 0.000 0.620 k +*u +877 313 m +878 312 l +877 313 l +f +*U +0.000 0.341 0.271 0.118 k +*u +1117 313 m +1118 312 l +1117 313 l +f +*U +0.000 0.710 0.553 0.290 k +*u +1118.667 312.667 m +1118.222 312.222 1119.278 312.278 1119.333 312.333 c +1119.778 312.778 1118.722 312.722 1118.667 312.667 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1924 313 m +1923 311.255 1922.547 309.875 1922 308 c +1923.693 309.782 1924.375 310.581 1924 313 c +f +*U +0.000 0.000 0.000 0.631 k +*u +1925 313 m +1926 312 l +1925 313 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1929 313 m +1928.455 311.365 1928.635 311.545 1927 311 c +1928 304 l +1924 306 l +1923.274 303.821 1923.561 304.220 1922 305 c +1919.825 299.325 1918.419 294 1920 288 c +1915.576 288.690 1911.467 288.267 1912 283 c +1910 281 1910.814 278.697 1911 276 c +1916 280 l +1916.251 278.548 1916.315 278.248 1917 277 c +1919.259 277 1921.290 276.624 1923 278 c +1924.517 277 1925.339 276.613 1927 276 c +1928.276 277.915 1928.277 277 1927 279 c +1936.521 281.267 1947.251 280 1957 280 c +1966.749 280 1977.479 281.267 1987 279 c +1985.907 277 1985.838 276.265 1986 274 c +1987.819 275.365 1987 275.492 1989 275 c +1990 278 l +1992 273 l +1989.567 271.538 1988.823 270.712 1988 268 c +1992.365 267.405 1994.627 261.447 1997 258 c +1998.417 258.472 1998.814 258.814 2000 260 c +1999 257 l +2003.462 255.684 2008.227 255.219 2008 261 c +2008.957 259.483 2009.387 258.662 2010 257 c +2011.533 260 2010.509 262 2009 265 c +2006.539 265 2004.400 265.434 2002 266 c +2003.478 266.986 2003.204 267 2005 267 c +2003.352 267.924 2001.825 268.449 2000 269 c +2002 276 l +2000.488 277.653 1999.819 278.894 1999 281 c +1996 280 l +1994 283.445 1992.720 286 1992 290 c +1988.786 288.587 1986.946 289.231 1984 291 c +1983 288 l +1982 292 l +1981.317 290.494 1981.174 289.685 1981 288 c +1927 287 l +1927.931 292.260 1928.728 296.660 1929 302 c +1934.463 301.221 1935.407 305 1938 309 c +1935 313 l +1933 312.590 1932.298 312.465 1931 311 c +1929.977 312.534 1930.195 312.402 1929 313 c +f +*U +0.000 0.000 0.000 0.125 k +*u +1943 313 m +1942 311.255 1941.547 309.875 1941 308 c +1942.693 309.782 1943.375 310.581 1943 313 c +f +*U +0.000 0.000 0.000 0.627 k +*u +364 312 m +365 311 l +364 312 l +f +*U +0.000 0.000 0.000 0.259 k +*u +365 312 m +366 311 l +365 312 l +f +*U +0.000 0.000 0.000 0.106 k +*u +547 312 m +548.402 309.726 549.515 309 552 308 c +550.394 309.914 549.217 310.837 547 312 c +f +*U +0.000 0.000 0.000 0.600 k +*u +548 312 m +549 311 l +548 312 l +f +*U +0.000 0.000 0.000 0.624 k +*u +805 312 m +806 311 l +805 312 l +f +*U +0.000 0.000 0.000 0.137 k +*u +856 312 m +855 310.521 855 310.797 855 309 c +856.289 310.443 856.401 310.234 856 312 c +f +*U +0.000 0.522 0.341 0.000 k +*u +1208 312 m +1209 311 l +1208 312 l +f +*U +0.000 0.333 0.310 0.231 k +*u +1285 312 m +1286 311 l +1285 312 l +f +*U +0.000 0.612 0.420 0.373 k +*u +1295 312 m +1295 309 l +1295.696 310.554 1295.696 310.446 1295 312 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1453 312 m +1454 310 l +1455.635 310.545 1455.455 310.365 1456 312 c +1453 312 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1456 312 m +1457 311 l +1456 312 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1480 312 m +1481 311 l +1480 312 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1981 312 m +1982 311 l +1981 312 l +f +*U +0.000 0.000 0.000 0.537 k +*u +357 311 m +358 310 l +357 311 l +f +*U +0.000 0.000 0.000 0.129 k +*u +347 309 m +352.305 306.836 359.395 309.558 365 310 c +359.672 312.215 352.581 309.706 347 309 c +f +*U +0.000 0.000 0.000 0.671 k +*u +575 311 m +576 310 l +575 311 l +f +*U +0.000 0.000 0.000 0.098 k +*u +576 311 m +579.358 306.622 583.915 303 589 301 c +585.678 305.500 581 308.833 576 311 c +f +*U +0.000 0.000 0.000 0.545 k +*u +798 311 m +799 310 l +798 311 l +f +*U +0.000 0.000 0.000 0.141 k +*u +799 311 m +801.332 310 803.457 310 806 310 c +803.668 310.985 801.543 310.981 799 311 c +f +*U +0.000 0.000 0.000 0.110 k +*u +835 311 m +833 305 l +835.181 306.896 836 308.259 837 311 c +835 311 l +f +*U +0.000 0.000 0.000 0.620 k +*u +837 311 m +838 310 l +837 311 l +f +*U +0.000 0.000 0.000 0.078 k +*u +878 311 m +878.833 306.696 880.634 303.791 884 301 c +882.616 304.781 880.761 308 878 311 c +f +*U +0.000 0.000 0.000 0.224 k +*u +898 311 m +899 310 l +898 311 l +f +*U +0.000 0.251 0.208 0.102 k +*u +1133 311 m +1134 310 l +1133 311 l +f +*U +0.000 0.533 0.408 0.463 k +*u +1285 311 m +1285 308 l +1285.696 309.554 1285.696 309.446 1285 311 c +f +*U +0.000 0.329 0.239 0.224 k +*u +1294 311 m +1295 310 l +1294 311 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1449 309 m +1451.509 308.434 1452.220 309 1454 311 c +1449 309 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1476 309 m +1478 308.590 1478.962 309 1481 310 c +1478.860 310.410 1478 309.968 1476 309 c +f +*U +0.000 0.000 0.000 0.812 k +*u +1924 311 m +1925 310 l +1924 311 l +f +*U +0.000 0.000 0.000 0.878 k +*u +348.667 309.667 m +348.222 309.222 349.278 309.278 349.333 309.333 c +349.778 309.778 348.722 309.722 348.667 309.667 c +f +*U +0.000 0.000 0.000 0.569 k +*u +350 310 m +351 309 l +350 310 l +f +*U +0.000 0.000 0.000 0.643 k +*u +790.667 309.667 m +790.223 309.223 791.278 309.278 791.333 309.333 c +791.778 309.778 790.722 309.722 790.667 309.667 c +f +*U +0.000 0.000 0.000 0.188 k +*u +794 310 m +795.769 309.221 797 309 799 309 c +797.231 309.779 795.964 309.912 794 310 c +f +*U +0.000 0.000 0.000 0.749 k +*u +879 310 m +880 309 l +879 310 l +f +*U +0.000 0.000 0.000 0.129 k +*u +898 310 m +898.545 308.365 898.365 308.545 900 308 c +900 310 l +898 310 l +f +*U +0.000 0.471 0.400 0.412 k +*u +1050 310 m +1050 305 l +1050.830 307 1050.830 307.970 1050 310 c +f +*U +0.000 0.639 0.463 0.341 k +*u +1133 310 m +1133.684 308.420 1133.805 308.223 1135 307 c +1134.316 308.580 1134.195 308.777 1133 310 c +f +*U +0.000 0.294 0.243 0.118 k +*u +1134 310 m +1135 309 l +1134 310 l +f +*U +0.000 0.306 0.239 0.694 k +*u +1208 310 m +1209 309 l +1208 310 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1453 310 m +1454 309 l +1453 310 l +f +*U +0.000 0.000 0.000 0.000 k +*u +1818 310 m +1818 306 l +1865 306 l +1861.301 307.552 1856.983 307 1853 307 c +1832 307 l +1826.819 307 1821.973 306.207 1818 310 c +f +*U +0.000 0.000 0.000 0.090 k +*u +1983 310 m +1985 305 l +1985.710 307.530 1985 308.516 1983 310 c +f +*U +0.000 0.000 0.000 0.169 k +*u +171 309 m +174.699 307.448 179 308 183 308 c +203 308 l +206.567 308 211.649 308.869 214.852 306.972 c +219.877 303.997 219 294 212.956 293 c +199 290.846 183 293 169 293 c +172.699 291.448 177 292 181 292 c +204 292 l +207.652 292 213.326 290.952 216.682 292.603 c +220 294.282 220 304.700 217.972 307.397 c +215.739 310.216 209 309 206 309 c +171 309 l +f +*U +0.000 0.000 0.000 0.678 k +*u +552 309 m +553 308 l +552 309 l +f +*U +0.000 0.133 0.149 0.169 k +*u +1135 309 m +1136 308 l +1135 309 l +f +*U +0.000 0.294 0.239 0.051 k +*u +1286 309 m +1287 308 l +1286 309 l +f +*U +0.000 0.290 0.196 0.357 k +*u +1295 309 m +1296 308 l +1295 309 l +f +*U +0.000 0.478 0.478 0.522 k +*u +1296 309 m +1297 308 l +1296 309 l +f +*U +0.000 1.000 0.725 0.000 k +*u +1297 309 m +1298.223 307.805 1298.420 307.684 1300 307 c +1298.777 308.195 1298.580 308.316 1297 309 c +f +*U +0.000 0.463 0.361 0.443 k +*u +1398 309 m +1398 306 l +1398.696 307.554 1398.696 307.446 1398 309 c +f +*U +0.000 0.000 0.000 0.710 k +*u +1475 309 m +1476 308 l +1475 309 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1940 309 m +1941 308 l +1940 309 l +f +*U +0.000 0.000 0.000 0.000 k +*u +169 308 m +173.720 306 179.920 307 185 307 c +216 307 l +211.280 308.981 205 308 200 308 c +169 308 l +f +*U +0.000 0.000 0.000 0.859 k +*u +402 308 m +408.436 305.299 418 307 425 307 c +477 307 l +470.564 309.701 460.951 308 454 308 c +402 308 l +f +*U +0.000 0.000 0.000 0.149 k +*u +853 308 m +853 306 l +854.635 306.545 854.455 306.365 855 308 c +853 308 l +f +*U +0.000 0.000 0.000 0.765 k +*u +899 308 m +900 307 l +899 308 l +f +*U +0.000 0.000 0.000 0.122 k +*u +900 308 m +900.810 305.778 901.739 304 903 302 c +903.410 304.888 902 306 900 308 c +f +*U +0.000 0.537 0.416 0.463 k +*u +1135 308 m +1132.692 306.241 1130.908 306 1128 306 c +1130.278 304.900 1136.531 303.938 1135 308 c +f +*U +0.000 0.376 0.282 0.624 k +*u +1211 308 m +1212 307 l +1211 308 l +f +*U +0.000 0.882 0.592 0.118 k +*u +1216 307 m +1222.194 304.401 1231.314 306 1238 306 c +1285 306 l +1278.650 309.376 1269.998 308 1263 308 c +1247.304 308 1231.625 307 1216 307 c +f +*U +0.000 0.471 0.345 0.212 k +*u +1286 308 m +1287 307 l +1286 308 l +f +*U +0.000 0.392 0.322 0.267 k +*u +1296 308 m +1297 307 l +1296 308 l +f +*U +0.000 0.361 0.271 0.482 k +*u +1297.333 307.333 m +1297.278 307.278 1297.222 306.222 1297.667 306.667 c +1297.722 306.722 1297.778 307.778 1297.333 307.333 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1466 303 m +1470 302.321 1473.438 305 1476 308 c +1472.360 306.848 1469.252 304.988 1466 303 c +f +*U +0.000 0.000 0.000 0.173 k +*u +1819 308 m +1823.720 306 1829.920 307 1835 307 c +1845.467 307 1856.647 305.862 1867 307 c +1862.280 308.981 1856 308 1851 308 c +1819 308 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1922 308 m +1923 307 l +1922 308 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1940 308 m +1939 306.255 1938.547 304.875 1938 303 c +1939.693 304.782 1940.375 305.581 1940 308 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1965 308 m +1966 307 l +1965 308 l +f +*U +0.000 0.000 0.000 0.098 k +*u +553 307 m +554.223 305.805 554.420 305.684 556 305 c +554.777 306.195 554.580 306.316 553 307 c +f +*U +0.000 0.000 0.000 0.812 k +*u +881 307 m +882 306 l +881 307 l +f +*U +0.000 0.027 0.016 0.541 k +*u +1136 307 m +1137 306 l +1136 307 l +f +*U +0.000 0.302 0.208 0.086 k +*u +1211 307 m +1212 306 l +1211 307 l +f +*U +0.000 0.475 0.380 0.525 k +*u +1212 307 m +1214.718 303.890 1220 305 1224 305 c +1220.304 306.551 1215.951 306 1212 307 c +f +*U +0.000 0.518 0.404 0.482 k +*u +1280 306 m +1283.698 304.448 1288 305 1292 305 c +1288.552 307.402 1284 306 1280 306 c +f +*U +0.000 0.349 0.224 0.188 k +*u +1291 307 m +1292 306 l +1291 307 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1448 307 m +1449 306 l +1448 307 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1920.333 306.333 m +1920.278 306.278 1920.222 305.222 1920.667 305.667 c +1920.722 305.722 1920.778 306.778 1920.333 306.333 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1965 307 m +1965.526 304.457 1965.878 303.465 1968 302 c +1967.251 304.254 1966.656 305.313 1965 307 c +f +*U +0.000 0.000 0.000 0.000 k +*u +217 306 m +217 295 l +218.431 298.410 218.431 302.590 217 306 c +f +*U +0.000 0.000 0.000 0.765 k +*u +556 306 m +557 305 l +556 306 l +f +*U +0.000 0.000 0.000 0.816 k +*u +834 306 m +835 305 l +834 306 l +f +*U +0.000 0.000 0.000 0.145 k +*u +852.333 305.333 m +852.278 305.278 852.222 304.222 852.667 304.667 c +852.722 304.722 852.778 305.778 852.333 305.333 c +f +*U +0.000 0.392 0.298 0.608 k +*u +1051 306 m +1057.678 303.198 1067.784 305 1075 305 c +1128 305 l +1121.322 307.802 1111.216 306 1104 306 c +1051 306 l +f +*U +0.000 0.047 0.035 0.816 k +*u +1136 306 m +1137 305 l +1136 306 l +f +*U +0.000 0.392 0.298 0.608 k +*u +1224 306 m +1229.217 303.811 1236.381 305 1242 305 c +1280 305 l +1274.784 307.189 1267.619 306 1262 306 c +1224 306 l +f +*U +0.000 0.235 0.149 0.357 k +*u +1292 306 m +1293 305 l +1292 306 l +f +*U +0.000 0.333 0.227 0.435 k +*u +1298 306 m +1299 305 l +1298 306 l +f +*U +0.000 0.392 0.298 0.608 k +*u +1299 306 m +1307 302.593 1320.203 305 1329 305 c +1398 305 l +1389.882 308.407 1376.797 306 1368 306 c +1299 306 l +f +*U +0.000 0.247 0.216 0.349 k +*u +1398 306 m +1399 305 l +1398 306 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1470 306 m +1471 305 l +1470 306 l +f +*U +0.000 0.000 0.000 0.627 k +*u +1760 306 m +1761 305 l +1760 306 l +f +*U +0.000 0.000 0.000 0.851 k +*u +1865 306 m +1865 293 l +1866.591 296.791 1866.591 302.209 1865 306 c +f +*U +0.000 0.000 0.000 0.129 k +*u +1866 306 m +1866 292 l +1867.667 295.972 1867.667 302 1866 306 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1918 304 m +1921 304 l +1920 306 l +1918.365 305.455 1918.545 305.635 1918 304 c +f +*U +0.000 0.000 0.000 0.800 k +*u +1938 306 m +1939 305 l +1938 306 l +f +*U +0.000 0.000 0.000 0.718 k +*u +851 305 m +852 304 l +851 305 l +f +*U +0.000 0.000 0.000 0.690 k +*u +882 305 m +883 304 l +882 305 l +f +*U +0.000 0.000 0.000 0.682 k +*u +901 305 m +902 304 l +901 305 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1468 305 m +1469 304 l +1468 305 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1986 305 m +1987 304 l +1986 305 l +f +*U +0.000 0.875 0.624 0.125 k +*u +0 304 m +3.415 275.239 0.989 244.987 1 216 c +1 207 1.178 189 10 184 c +9 187 l +16 187 l +16 192 l +13.603 192 10.582 191.716 8.742 193.603 c +4.524 197.931 8 211.340 8 217 c +8 296 l +25 296 l +25 303 l +16.661 303 8.226 302.473 0 304 c +f +*U +0.000 0.745 0.553 0.137 k +*u +2 304 m +8.928 301 19.503 303 27 303 c +20 305.907 9.497 304 2 304 c +f +*U +0.000 0.529 0.424 0.471 k +*u +27 304 m +27 216 l +29.497 221.951 28 230.580 28 237 c +28 281 l +28 287.951 29.701 297.564 27 304 c +f +*U +0.000 0.000 0.000 0.827 k +*u +584 304 m +585 303 l +584 304 l +f +*U +0.000 0.000 0.000 0.212 k +*u +832 304 m +833 303 l +832 304 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1918 304 m +1917 300 l +1918.434 301.393 1919 302.233 1920 304 c +1918 304 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1937 304 m +1938 303 l +1937 304 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1986 304 m +1987 303 l +1986 304 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1987 304 m +1987.547 302 1988 300.745 1989 299 c +1989.566 301.509 1988.847 302.220 1987 304 c +f +*U +0.000 0.878 0.631 0.122 k +*u +25 303 m +25 296 l +8 296 l +8 217 l +8 211.280 7 205.681 7 200 c +6.995 197.774 6.812 194.596 8.742 193 c +10.581 191.534 13.806 192 16 192 c +16 187 l +9 187 l +14.729 166.871 38 164 56 164 c +53.463 166 51.218 166.670 48 167 c +58.732 170.394 70.870 169 82 169 c +143 169 l +347 169 l +573.316 169 799.773 168 1026 168 c +1023.904 166.957 1022.301 166.397 1020 166 c +1023.746 164.425 1028 164.434 1032 163 c +1026.917 159.292 1028.860 154.570 1034 152 c +1034.482 147.602 1037.710 144.720 1042 144 c +1043.302 137.874 1051.372 127.403 1058 127 c +1060 121 l +1065.645 117.731 1070.265 112.945 1075.455 108.999 c +1084.809 101.890 1094.383 95 1104.385 88.790 c +1134.840 69.853 1172.407 57.574 1208 53.835 c +1230.812 51.439 1255.294 52.482 1278 56.194 c +1287.576 57.760 1297.239 62.310 1307 62 c +1312.651 67 1322.939 65.752 1327 72 c +1332.257 72 1337.333 75 1342 77.400 c +1351.411 82 1360 86.993 1368.950 92.731 c +1372.926 95.325 1375.304 98.590 1380 100 c +1380 104 l +1387 103.403 1392.546 110.925 1397.458 115.326 c +1406 123 1415.699 131.761 1422.624 141 c +1426 145.676 1429.982 150.383 1433 155.286 c +1434.874 157.982 1436 161.339 1439 162.972 c +1441.710 164.417 1445 163.998 1448 164 c +1449.545 169 1453.191 168.990 1458 169 c +1478 169 l +1571 169 l +1827 169 l +1918 169 l +1932.570 169 1948.564 170.879 1962.985 168.856 c +1966.189 168.407 1968.792 166.496 1972 166 c +1971.613 163.910 1971.616 164.289 1974 164 c +1975 149.673 1975 135.396 1975 121 c +1982.528 124.210 1989 130.403 1996 134.640 c +2016 146.761 2035.364 160.180 2055 173 c +2051.417 177.778 2043.203 182.381 2037 186 c +2034 187.663 2030.666 188.867 2028 191 c +2029 192 l +2022.569 194 2017.566 198.699 2012 202.371 c +2005 206.960 1997.472 210.666 1990.434 215 c +1985.255 218.421 1981 222.529 1975 224 c +1975 212.795 1977.422 198.436 1973 188 c +1974.801 186.685 1974.833 186.277 1975 184 c +1973.814 185 1973.396 185.339 1972 186 c +1968.765 183.562 1963.922 184 1960 184 c +1933 184 l +1828 184 l +1560 184 l +1472 184 l +1457.950 184 1442.908 185.529 1429 184 c +1424.554 188.593 1420.781 180.451 1418.570 177.454 c +1414.841 172.400 1410.443 167.829 1406.669 162.831 c +1403.309 158.382 1400.831 152.978 1397 149 c +1397.661 147.603 1397.964 147.187 1399 146 c +1397 145.930 1397 145.646 1396 147 c +1388.668 143.421 1383.819 135.383 1378 130 c +1379.943 129.378 1380.949 129.564 1383 130 c +1379.505 128.242 1376 128.553 1374 125 c +1369.507 125 1366.900 121.701 1363.485 119 c +1359.730 116 1355.532 113.778 1351.579 111 c +1336.876 101.279 1321.828 93.423 1304.999 87.715 c +1298.627 85.554 1292.888 81.909 1286 83 c +1279.646 78 1268.692 78.522 1261 77.421 c +1240.338 74.461 1219.358 75.788 1199 79.625 c +1192.383 80.872 1185.525 80.815 1179 82.795 c +1170.709 85.311 1162 87.656 1154 91 c +1149.521 92.958 1146 96.249 1141 96 c +1137.817 100.206 1130 102.419 1125.428 105 c +1116.708 109.812 1108.985 116 1100.910 121.890 c +1098 123.857 1090.870 130.413 1088 128 c +1077.695 141 1064.620 151.726 1054.411 164.985 c +1049.525 171.332 1045.859 180.996 1037.780 184.219 c +1032.550 186.306 1022.720 184 1017 184 c +967 184 l +792 184 l +289 184 l +126 184 l +74 184 l +62.741 184 51 183.376 40 185 c +40.986 186.479 41 186.203 41 188 c +37 188 l +35.781 191.439 33.303 192.655 30 194 c +30.636 201.291 27 208.512 27 216 c +27 303 l +25 303 l +f +*U +0.000 0.000 0.000 0.220 k +*u +559 303 m +560 302 l +559 303 l +f +*U +0.000 0.000 0.000 0.800 k +*u +560 303 m +561 302 l +560 303 l +f +*U +0.000 0.000 0.000 0.090 k +*u +831 303 m +830 301.521 830 301.797 830 300 c +831.289 301.443 831.401 301.234 831 303 c +f +*U +0.000 0.000 0.000 0.733 k +*u +832 303 m +833 302 l +832 303 l +f +*U +0.000 0.000 0.000 0.133 k +*u +850 303 m +848.817 300.672 847.777 298.489 847 296 c +849.256 298 850.728 299.867 850 303 c +f +*U +0.000 0.000 0.000 0.624 k +*u +1465 303 m +1466 302 l +1465 303 l +f +*U +0.000 0.000 0.000 0.153 k +*u +1701 302 m +1706.217 299.811 1713.381 301 1719 301 c +1731.812 301 1746.506 299 1759 302 c +1753.902 303.568 1746.469 302 1741 302 c +1701 302 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1919 303 m +1920 302 l +1919 303 l +f +*U +0.000 0.000 0.000 0.275 k +*u +1937 303 m +1938 302 l +1937 303 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1968 303 m +1969 302 l +1968 303 l +f +*U +0.000 0.000 0.000 0.820 k +*u +849 302 m +850 301 l +849 302 l +f +*U +0.000 0.000 0.000 0.804 k +*u +884 302 m +885 301 l +884 302 l +f +*U +0.000 0.000 0.000 0.608 k +*u +903 302 m +904 301 l +903 302 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1463 302 m +1464 301 l +1463 302 l +f +*U +0.000 0.000 0.000 0.118 k +*u +1460 300 m +1462.187 297.968 1464 296.906 1467 296 c +1465.771 297.870 1465 298.224 1463 299 c +1466 301 l +1463.726 301.409 1462.219 300.788 1460 300 c +f +*U +0.000 0.000 0.000 0.596 k +*u +1757 302 m +1758 301 l +1757 302 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1936 302 m +1934.216 298.641 1932.268 295.810 1932 292 c +1934.509 294.996 1936.347 298.460 1938 302 c +1936 302 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1968 302 m +1968.683 300.420 1968.805 300.222 1970 299 c +1969.316 300.580 1969.195 300.777 1968 302 c +f +*U +0.000 0.631 0.420 0.365 k +*u +0 301 m +0 208 l +2.802 214.678 1 224.784 1 232 c +1 279 l +1 285.686 2.599 294.806 0 301 c +f +*U +0.000 0.000 0.000 0.106 k +*u +561 301 m +562.450 299.392 563 298.936 565 298 c +563.550 299.608 562.949 300 561 301 c +f +*U +0.000 0.000 0.000 0.796 k +*u +588 301 m +589 300 l +588 301 l +f +*U +0.000 0.000 0.000 0.133 k +*u +589 301 m +590.450 299.392 591 298.936 593 298 c +591.550 299.608 590.949 300 589 301 c +f +*U +0.000 0.000 0.000 0.106 k +*u +884 301 m +884.651 298.566 885 297.717 887 296 c +886.251 298.254 885.656 299.314 884 301 c +f +*U +0.000 0.000 0.000 0.137 k +*u +905 301 m +906 297 l +906.393 298.924 906 299.360 905 301 c +f +*U +0.000 0.000 0.000 0.843 k +*u +1698 301 m +1703.217 298.811 1710.381 300 1716 300 c +1753 300 l +1747.783 302.189 1740.619 301 1735 301 c +1698 301 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1780 301 m +1781 300 l +1780 301 l +f +*U +0.000 0.000 0.000 0.596 k +*u +830 300 m +831 299 l +830 300 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1916 300 m +1915 298.255 1914.547 296.875 1914 295 c +1915.693 296.782 1916.375 297.581 1916 300 c +f +*U +0.000 0.000 0.000 0.659 k +*u +1917 300 m +1918 299 l +1917 300 l +f +*U +0.000 0.000 0.000 0.671 k +*u +565 299 m +566 298 l +565 299 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1461 299 m +1462 298 l +1461 299 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1970.333 298.333 m +1970.278 298.278 1970.222 297.222 1970.667 297.667 c +1970.722 297.722 1970.778 298.778 1970.333 298.333 c +f +*U +0.000 0.000 0.000 0.729 k +*u +1989 299 m +1990 298 l +1989 299 l +f +*U +0.000 0.000 0.000 0.243 k +*u +1990 299 m +1991 298 l +1990 299 l +f +*U +0.000 0.000 0.000 0.129 k +*u +565 298 m +565.545 296.365 565.365 296.545 567 296 c +567 298 l +565 298 l +f +*U +0.000 0.000 0.000 0.643 k +*u +592 298 m +593 297 l +592 298 l +f +*U +0.000 0.000 0.000 0.322 k +*u +593 298 m +594 297 l +593 298 l +f +*U +0.000 0.000 0.000 0.831 k +*u +829 298 m +830 297 l +829 298 l +f +*U +0.000 0.000 0.000 0.596 k +*u +1971 298 m +1972 297 l +1971 298 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1990 298 m +1990.545 296.365 1990.365 296.545 1992 296 c +1992 298 l +1990 298 l +f +*U +0.000 0.000 0.000 0.812 k +*u +593 297 m +594 296 l +593 297 l +f +*U +0.000 0.000 0.000 0.090 k +*u +594 297 m +595.223 295.805 595.420 295.684 597 295 c +596 296.783 596 296.594 594 297 c +f +*U +0.000 0.000 0.000 0.173 k +*u +827.333 296.333 m +827.278 296.278 827.222 295.222 827.667 295.667 c +827.722 295.722 827.778 296.778 827.333 296.333 c +f +*U +0.000 0.000 0.000 0.776 k +*u +846 297 m +847 296 l +846 297 l +f +*U +0.000 0.000 0.000 0.690 k +*u +887 297 m +888 296 l +887 297 l +f +*U +0.000 0.000 0.000 0.114 k +*u +907 297 m +907.810 294.778 908.739 293 910 291 c +910.410 293.888 909 295 907 297 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1779 297 m +1780 296 l +1779 297 l +f +*U +0.000 0.000 0.000 0.063 k +*u +1971 297 m +1973 291 l +1973.744 293.735 1972.915 294.968 1971 297 c +f +*U +0.000 0.000 0.000 0.725 k +*u +569 296 m +570 295 l +569 296 l +f +*U +0.000 0.000 0.000 0.129 k +*u +846 296 m +843 290 l +891 290 l +890.190 292.222 889.261 293.990 888 296 c +887.590 293.860 888 293 889 291 c +845 291 l +846 293 846.577 293.769 846 296 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1466 296 m +1467 295 l +1466 296 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1467.667 295.667 m +1467.222 295.222 1468.278 295.278 1468.333 295.333 c +1468.778 295.778 1467.722 295.722 1467.667 295.667 c +f +*U +0.000 0.000 0.000 0.149 k +*u +1779.333 295.333 m +1779.278 295.278 1779.222 294.222 1779.667 294.667 c +1779.722 294.722 1779.778 295.778 1779.333 295.333 c +f +*U +0.000 0.000 0.000 0.773 k +*u +1932 296 m +1933 295 l +1932 296 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1992 296 m +1993 293 1994.415 290.618 1996 288 c +1996.576 291.534 1994.603 293.762 1992 296 c +f +*U +0.000 0.000 0.000 0.235 k +*u +569 295 m +570 294 l +569 295 l +f +*U +0.000 0.000 0.000 0.749 k +*u +596 295 m +597 294 l +596 295 l +f +*U +0.000 0.000 0.000 0.133 k +*u +597 295 m +599.319 292 601.622 290.432 605 289 c +602.701 291.971 600.505 293.641 597 295 c +f +*U +0.000 0.000 0.000 0.102 k +*u +826 295 m +825 293.521 825 293.797 825 292 c +826.289 293.443 826.401 293.234 826 295 c +f +*U +0.000 0.000 0.000 0.765 k +*u +827 295 m +828 294 l +827 295 l +f +*U +0.000 0.278 0.173 0.082 k +*u +1051 295 m +1058.399 291.895 1069.993 294 1078 294 c +1138 294 l +1130.600 297 1119 295 1111 295 c +1051 295 l +f +*U +0.000 0.263 0.196 0.192 k +*u +1138 295 m +1139.248 294.315 1139.548 294.251 1141 294 c +1139.752 294.685 1139.451 294.749 1138 295 c +f +*U +0.000 0.278 0.173 0.082 k +*u +1213 293 m +1221.624 295 1231.174 294 1240 294 c +1287 294 l +1281.784 296.189 1274.619 295 1269 295 c +1231 295 l +1226 295 1216.407 296.899 1213 293 c +f +*U +0.000 0.271 0.243 0.180 k +*u +1296 295 m +1297.248 294.315 1297.548 294.251 1299 294 c +1297.751 294.685 1297.452 294.749 1296 295 c +f +*U +0.000 0.267 0.196 0.063 k +*u +1299 295 m +1302 293.673 1305.586 294 1309 294 c +1305.837 295.327 1302.415 295.000 1299 295 c +f +*U +0.000 0.278 0.227 0.157 k +*u +1313 295 m +1314.248 294.315 1314.548 294.251 1316 294 c +1314.752 294.685 1314.451 294.749 1313 295 c +f +*U +0.000 0.353 0.286 0.043 k +*u +1316 295 m +1317.506 294.317 1318.315 294.174 1320 294 c +1318.494 294.683 1317.685 294.826 1316 295 c +f +*U +0.000 0.278 0.173 0.082 k +*u +1320 295 m +1326.919 292 1337.520 294 1345 294 c +1399 294 l +1392 296.903 1381.480 295 1374 295 c +1320 295 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1468 295 m +1469 294 l +1468 295 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1469 295 m +1470.223 293.805 1470.420 293.684 1472 293 c +1470.777 294.195 1470.580 294.316 1469 295 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1778 295 m +1779 294 l +1778 295 l +f +*U +0.000 0.000 0.000 0.090 k +*u +1913 295 m +1911.952 293 1911.487 292 1911 290 c +1912.693 291.782 1913.375 292.581 1913 295 c +f +*U +0.000 0.000 0.000 0.796 k +*u +1914 295 m +1915 294 l +1914 295 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1973 295 m +1974 294 l +1973 295 l +f +*U +0.000 0.000 0.000 0.843 k +*u +169 294 m +173.720 292 179.920 293 185 293 c +217 293 l +212.280 294.981 206 294 201 294 c +169 294 l +f +*U +0.000 0.000 0.000 0.824 k +*u +889 294 m +890 293 l +889 294 l +f +*U +0.000 0.000 0.000 0.792 k +*u +908 294 m +909 293 l +908 294 l +f +*U +0.000 0.506 0.506 0.494 k +*u +1050.333 293.333 m +1050.278 293.278 1050.222 292.222 1050.667 292.667 c +1050.722 292.722 1050.778 293.778 1050.333 293.333 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1051 294 m +1055 291 l +1062 294.980 1073 293 1081 293 c +1140 293 l +1140 289 l +1140.779 290.769 1140.912 292 1141 294 c +1051 294 l +f +*U +0.000 0.522 0.345 0.471 k +*u +1214.333 293.333 m +1214.278 293.278 1214.222 292.222 1214.667 292.667 c +1214.722 292.722 1214.778 293.778 1214.333 293.333 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1215 294 m +1221.194 291.401 1230.314 293 1237 293 c +1254.524 293 1273.751 295.202 1291 292 c +1285.726 295.996 1275.423 294 1269 294 c +1215 294 l +f +*U +0.149 0.000 0.008 0.133 k +*u +1295.333 293.333 m +1295.278 293.278 1295.222 292.222 1295.667 292.667 c +1295.722 292.723 1295.777 293.778 1295.333 293.333 c +f +*U +0.000 0.702 0.557 0.298 k +*u +1296 294 m +1296 289 l +1296.683 290.506 1296.826 291.315 1297 293 c +1305 293 l +1302 294.213 1299 293.998 1296 294 c +f +*U +0.000 0.882 0.624 0.118 k +*u +1297 293 m +1297 289 l +1284.958 293.668 1273.859 293 1261 293 c +1215 293 l +1216 287 l +1216.685 288.248 1216.749 288.549 1217 290 c +1224 290 l +1221.894 289.356 1220.205 289 1218 289 c +1218 283 l +1250.935 281.586 1284 282 1317 282 c +1315.600 285 1314 287.825 1313 291 c +1310.566 291.651 1309.717 292 1308 294 c +1304.305 293.533 1300.735 293 1297 293 c +f +*U +0.000 0.635 0.463 0.365 k +*u +1308 294 m +1308.899 291.876 1308.876 291.899 1311 291 c +1309.897 292.457 1309.457 292.897 1308 294 c +f +*U +0.000 0.392 0.310 0.580 k +*u +1313 294 m +1314 293 l +1313 294 l +f +*U +0.000 0.745 0.557 0.255 k +*u +1312 291 m +1313 290 l +1314.596 290.959 1315.659 291.726 1317 293 c +1314.333 293 1313.893 292.911 1312 291 c +f +*U +0.000 0.667 0.663 0.298 k +*u +1316 294 m +1319.448 291.598 1323.896 292.966 1328 293 c +1324.302 294.551 1319.983 294 1316 294 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1328 294 m +1334.194 291.401 1343.314 293 1350 293 c +1398 293 l +1391.806 295.599 1382.686 294 1376 294 c +1328 294 l +f +*U +0.000 0.420 0.424 0.176 k +*u +1398 294 m +1398 290 l +1398.710 291.759 1398.710 292.241 1398 294 c +f +*U +0.000 0.000 0.000 0.055 k +*u +1767 286 m +1772.368 286.838 1777.190 289.221 1780 294 c +1775.951 292.207 1769.735 289.435 1767 286 c +f +*U +0.000 0.000 0.000 0.137 k +*u +402 293 m +408.436 290.299 418 292 425 292 c +475 292 l +475 255 l +476.661 258.959 476 263.740 476 268 c +476 293 l +402 293 l +f +*U +0.000 0.000 0.000 0.635 k +*u +476 293 m +476 255 l +477.441 258.435 477 262.298 477 266 c +477 274 479 285.600 476 293 c +f +*U +0.000 0.000 0.000 0.086 k +*u +572 293 m +573.573 290.338 575 289.228 578 288 c +576.170 290.348 574.637 291.617 572 293 c +f +*U +0.000 0.000 0.000 0.816 k +*u +573 293 m +574 292 l +573 293 l +f +*U +0.000 0.859 0.608 0.137 k +*u +1051 293 m +1052 283 l +1079.394 279.538 1108.379 282 1136 282 c +1136 284 l +1056 284 l +1062.584 285.946 1070 285 1077 285 c +1117 285 l +1123.705 285 1132.831 286.880 1138 282 c +1140 282 l +1140.890 285.870 1140.490 289 1140 293 c +1078 293 l +1072.473 293 1059.796 295.344 1056 291 c +1054.175 292.336 1053.247 292.690 1051 293 c +f +*U +0.000 0.522 0.365 0.122 k +*u +1291 293 m +1292 292 l +1291 293 l +f +*U +0.000 0.267 0.212 0.039 k +*u +1312 293 m +1313 292 l +1312 293 l +f +*U +0.000 0.871 0.624 0.129 k +*u +1319 292 m +1320.249 291.315 1320.548 291.251 1322 291 c +1320.722 288 1319.830 285 1319 282 c +1397 282 l +1397 293 l +1346 293 l +1337.393 293 1327.280 294.448 1319 292 c +f +*U +0.000 0.898 0.851 0.047 k +*u +1397 293 m +1397 290 l +1397.696 291.554 1397.696 291.446 1397 293 c +f +*U +0.000 0.000 0.000 0.098 k +*u +1472 293 m +1473.458 291.919 1474.248 291.564 1476 291 c +1474.457 292.267 1473.952 292.489 1472 293 c +f +*U +0.000 0.000 0.000 0.839 k +*u +1818 293 m +1822.720 291 1828.920 292 1834 292 c +1865 292 l +1860.280 293.981 1854 293 1849 293 c +1818 293 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1865 293 m +1866 292 l +1865 293 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1931 293 m +1929 289 l +1976 289 l +1975 293 l +1974.315 291.752 1974.251 291.452 1974 290 c +1960 291.554 1945 290 1931 290 c +1931.400 291.650 1931.479 291.502 1931 293 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1993 293 m +1994 292 l +1993 293 l +f +*U +0.000 0.000 0.000 0.165 k +*u +344 290 m +348 291 l +345.954 291.751 345.404 291.656 344 290 c +f +*U +0.000 0.000 0.000 0.078 k +*u +348 292 m +348 290 l +350 290 l +350 292 l +348 292 l +f +*U +0.000 0.000 0.000 0.722 k +*u +600 292 m +601 291 l +600 292 l +f +*U +0.000 0.000 0.000 0.082 k +*u +784 292 m +784 271 l +786 271 l +786 277.541 786.862 284.699 785 291 c +792 290 798.934 288.303 806 288 c +806 272 l +807.797 272 807.521 272 809 273 c +808 277 809.393 284 806.972 287.486 c +805.447 289.622 802.364 289.842 800 290.245 c +794.702 291 789.378 291.955 784 292 c +f +*U +0.000 0.000 0.000 0.078 k +*u +823 292 m +821.770 289.365 820.766 286.804 820 284 c +822.573 286.383 823.933 288.660 825 292 c +823 292 l +f +*U +0.000 0.000 0.000 0.624 k +*u +825 292 m +826 291 l +825 292 l +f +*U +0.000 0.000 0.000 0.616 k +*u +843 292 m +844 291 l +843 292 l +f +*U +0.000 0.584 0.439 0.329 k +*u +1050 292 m +1050 289 l +1050.696 290.554 1050.696 290.446 1050 292 c +f +*U +0.000 0.259 0.153 0.408 k +*u +1153 292 m +1154 291 l +1153 292 l +f +*U +0.000 0.314 0.184 0.043 k +*u +1154 292 m +1155 291 l +1154 292 l +f +*U +0.000 0.427 0.282 0.098 k +*u +1214 292 m +1215 291 l +1214 292 l +f +*U +0.000 0.447 0.314 0.400 k +*u +1291.667 291.667 m +1291.222 291.222 1292.278 291.278 1292.333 291.333 c +1292.778 291.778 1291.722 291.722 1291.667 291.667 c +f +*U +0.000 0.102 0.059 0.082 k +*u +1295.333 291.333 m +1295.278 291.278 1295.222 290.222 1295.667 290.667 c +1295.722 290.723 1295.777 291.778 1295.333 291.333 c +f +*U +0.000 0.400 0.282 0.098 k +*u +1311 292 m +1312 291 l +1311 292 l +f +*U +0.000 0.318 0.388 0.267 k +*u +1315 292 m +1316.506 291.317 1317.315 291.174 1319 291 c +1317.494 291.683 1316.685 291.826 1315 292 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1446 292 m +1446 264 l +1446 260.293 1445 255.582 1448 253 c +1446.414 261.541 1447 270.342 1447 279 c +1447 283.260 1447.661 288 1446 292 c +f +*U +0.000 0.000 0.000 0.776 k +*u +1473 292 m +1474 291 l +1473 292 l +f +*U +0.000 0.000 0.000 0.161 k +*u +1818 292 m +1822.720 290 1828.920 291 1834 291 c +1866 291 l +1861.280 292.981 1855 292 1850 292 c +1818 292 l +f +*U +0.000 0.000 0.000 0.078 k +*u +169 291 m +169 271 l +171 271 l +171 291 l +169 291 l +f +*U +0.000 0.000 0.000 0.106 k +*u +343 291 m +343 272 l +345 272 l +345 277.819 346.627 286.213 343 291 c +f +*U +0.000 0.000 0.000 0.894 k +*u +345.667 290.667 m +345.222 290.222 346.278 290.278 346.333 290.333 c +346.778 290.778 345.722 290.722 345.667 290.667 c +f +*U +0.000 0.000 0.000 0.600 k +*u +347 291 m +348 290 l +347 291 l +f +*U +0.000 0.000 0.000 0.169 k +*u +350 291 m +351.506 290.317 352.315 290.174 354 290 c +352.494 290.683 351.685 290.826 350 291 c +f +*U +0.000 0.000 0.000 0.082 k +*u +402 291 m +402 254 l +406.630 260.777 403.860 274 404 282 c +404 285.548 405 288.710 402 291 c +f +*U +0.000 0.000 0.000 0.243 k +*u +785 291 m +786 290 l +785 291 l +f +*U +0.000 0.000 0.000 0.541 k +*u +788 291 m +789 290 l +788 291 l +f +*U +0.000 0.000 0.000 0.808 k +*u +891.333 290.333 m +891.278 290.278 891.222 289.222 891.667 289.667 c +891.722 289.722 891.778 290.778 891.333 290.333 c +f +*U +0.000 0.000 0.000 0.710 k +*u +910 291 m +911 290 l +910 291 l +f +*U +0.000 0.000 0.000 0.102 k +*u +911 291 m +912.305 286.905 914.607 283.550 917 280 c +917.717 284.411 914 288.208 911 291 c +f +*U +0.000 0.133 0.122 0.078 k +*u +1141 291 m +1142 290 l +1141 291 l +f +*U +0.000 0.408 0.275 0.004 k +*u +1152.333 290.333 m +1152.278 290.278 1152.222 289.222 1152.667 289.667 c +1152.722 289.722 1152.777 290.778 1152.333 290.333 c +f +*U +0.000 0.698 0.522 0.302 k +*u +1153 288 m +1154.560 288.596 1155.623 289 1157 290 c +1154.303 290.854 1153.614 290.851 1153 288 c +f +*U +0.000 0.263 0.129 0.310 k +*u +1156 291 m +1157 290 l +1156 291 l +f +*U +0.000 0.588 0.451 0.412 k +*u +1293 291 m +1294 290 l +1293 291 l +f +*U +0.000 0.439 0.298 0.086 k +*u +1294 291 m +1295 290 l +1294 291 l +f +*U +0.000 0.204 0.141 0.122 k +*u +1314.333 290.333 m +1314.278 290.278 1314.222 289.222 1314.667 289.667 c +1314.722 289.722 1314.778 290.778 1314.333 290.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1319 284 m +1319.464 286.172 1320 287.958 1321 290 c +1314.568 291.356 1313.905 287.344 1319 284 c +f +*U +0.000 0.318 0.188 0.063 k +*u +1319.667 290.667 m +1319.222 290.222 1320.278 290.278 1320.333 290.333 c +1320.778 290.778 1319.722 290.722 1319.667 290.667 c +f +*U +0.000 0.420 0.263 0.094 k +*u +1321.333 290.333 m +1321.278 290.278 1321.222 289.222 1321.667 289.667 c +1321.722 289.722 1321.777 290.778 1321.333 290.333 c +f +*U +0.000 0.000 0.000 0.110 k +*u +1447 291 m +1447 255 l +1448.552 258.698 1448 263 1448 267 c +1448 289 l +1450.360 287.687 1452.391 286.659 1455 286 c +1452.579 288.268 1450 289.685 1447 291 c +f +*U +0.000 0.000 0.000 0.725 k +*u +1448 291 m +1449 290 l +1448 291 l +f +*U +0.000 0.000 0.000 0.596 k +*u +1475 291 m +1476 290 l +1475 291 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1476 291 m +1478.383 288.549 1480.793 287.178 1484 286 c +1481.654 288.730 1479.449 289.975 1476 291 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1818 291 m +1818 270 l +1820.643 276.299 1818.394 284.254 1820 291 c +1818 291 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1929 291 m +1930 290 l +1929 291 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1994 291 m +1995 290 l +1994 291 l +f +*U +0.000 0.000 0.000 0.827 k +*u +352 290 m +353 289 l +352 290 l +f +*U +0.000 0.000 0.000 0.561 k +*u +353 290 m +354 289 l +353 290 l +f +*U +0.000 0.000 0.000 0.200 k +*u +357.667 289.667 m +357.222 289.222 358.278 289.278 358.333 289.333 c +358.778 289.778 357.722 289.722 357.667 289.667 c +f +*U +0.000 0.000 0.000 0.078 k +*u +359 290 m +361 288.418 362.388 288.174 365 288 c +365 280.237 364.973 272.702 364 265 c +367 269.401 369.457 282.706 365.972 287.436 c +364.435 289.522 361.327 289.677 359 290 c +f +*U +0.000 0.000 0.000 0.753 k +*u +577 290 m +578 289 l +577 290 l +f +*U +0.000 0.000 0.000 0.533 k +*u +794 290 m +795 289 l +794 290 l +f +*U +0.000 0.000 0.000 0.776 k +*u +842 290 m +843 289 l +842 290 l +f +*U +0.000 0.000 0.000 0.616 k +*u +843 290 m +847.720 288 853.920 289 859 289 c +891 289 l +886.280 290.981 880 290 875 290 c +843 290 l +f +*U +0.000 0.404 0.314 0.286 k +*u +1141.333 289.333 m +1141.278 289.278 1141.222 288.222 1141.667 288.667 c +1141.722 288.722 1141.777 289.778 1141.333 289.333 c +f +*U +0.000 0.341 0.392 0.239 k +*u +1157 290 m +1158 289 l +1157 290 l +f +*U +0.000 0.145 0.094 0.192 k +*u +1215 290 m +1216 289 l +1215 290 l +f +*U +0.000 0.780 0.553 0.220 k +*u +1217 290 m +1216.659 283.801 1217.589 282 1224 282 c +1221.948 282.874 1220.253 282.953 1218 283 c +1218 289 l +1224 289 l +1221.669 289.984 1219.543 289.981 1217 290 c +f +*U +0.000 0.604 0.486 0.396 k +*u +1294 290 m +1295 289 l +1294 290 l +f +*U +0.000 0.290 0.290 0.710 k +*u +1313.333 289.333 m +1313.278 289.278 1313.222 288.222 1313.667 288.667 c +1313.722 288.722 1313.777 289.778 1313.333 289.333 c +f +*U +0.000 0.663 0.698 0.267 k +*u +1397 290 m +1397 284 l +1397.951 286.285 1397.951 287.715 1397 290 c +f +*U +0.000 0.322 0.290 0.157 k +*u +1398 290 m +1398 285 l +1398.830 287 1398.830 287.970 1398 290 c +f +*U +0.000 0.000 0.000 0.804 k +*u +1450 290 m +1451 289 l +1450 290 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1819 290 m +1819 283 1819.623 275.818 1818 269 c +1873 269 l +1880.751 269 1891 270.863 1898 267 c +1899.183 269.328 1900.223 271.511 1901 274 c +1893.242 268.414 1884.246 270 1875 270 c +1820 270 l +1820 276.169 1821.398 284.285 1819 290 c +f +*U +0.000 0.000 0.000 0.110 k +*u +1910 290 m +1909 288.522 1909 288.797 1909 287 c +1910.290 288.443 1910.401 288.233 1910 290 c +f +*U +0.000 0.000 0.000 0.820 k +*u +1911 290 m +1912 289 l +1911 290 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1976 290 m +1977 289 l +1976 290 l +f +*U +0.000 0.000 0.000 0.827 k +*u +358 289 m +359 288 l +358 289 l +f +*U +0.000 0.000 0.000 0.659 k +*u +359 289 m +360 288 l +359 289 l +f +*U +0.000 0.000 0.000 0.690 k +*u +578 289 m +579 288 l +578 289 l +f +*U +0.000 0.000 0.000 0.667 k +*u +604 289 m +605 288 l +604 289 l +f +*U +0.000 0.000 0.000 0.125 k +*u +605 289 m +606.624 286.956 607.643 286 610 285 c +608.598 287.274 607.485 287.987 605 289 c +f +*U +0.000 0.000 0.000 0.541 k +*u +800 289 m +801 288 l +800 289 l +f +*U +0.000 0.455 0.322 0.188 k +*u +1050 289 m +1050 284 l +1050.830 286 1050.830 286.970 1050 289 c +f +*U +0.000 0.278 0.231 0.251 k +*u +1152 289 m +1153 288 l +1152 289 l +f +*U +0.000 0.784 0.565 0.188 k +*u +1153 284 m +1157 285 l +1155.752 285.685 1155.451 285.749 1154 286 c +1156.786 286.458 1157.455 286.369 1159 284 c +1159.683 285.506 1159.826 286.315 1160 288 c +1155.836 288.646 1153.747 288.465 1153 284 c +f +*U +0.000 0.639 0.655 0.345 k +*u +1157 289 m +1158 288 l +1157 289 l +f +*U +0.000 0.318 0.486 0.373 k +*u +1158 289 m +1159 288 l +1158 289 l +f +*U +0.000 0.325 0.239 0.294 k +*u +1320 289 m +1321 288 l +1320 289 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1478 289 m +1479 288 l +1478 289 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1770 289 m +1771 288 l +1770 289 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1929 289 m +1933.720 287 1939.920 288 1945 288 c +1977 288 l +1972.280 289.981 1966 289 1961 289 c +1929 289 l +f +*U +0.000 0.588 0.455 0.357 k +*u +1141 288 m +1141 284 l +1141.710 285.759 1141.710 286.241 1141 288 c +f +*U +0.000 0.655 0.545 0.345 k +*u +1152 288 m +1152 282 l +1152.951 284.285 1152.951 285.715 1152 288 c +f +*U +0.000 0.114 0.216 0.318 k +*u +1160 288 m +1161 287 l +1160 288 l +f +*U +0.000 0.404 0.298 0.137 k +*u +1314.333 287.333 m +1314.278 287.278 1314.222 286.222 1314.667 286.667 c +1314.722 286.722 1314.778 287.778 1314.333 287.333 c +f +*U +0.000 0.353 0.243 0.345 k +*u +1319 288 m +1320 287 l +1319 288 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1453 288 m +1454 287 l +1453 288 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1480 288 m +1481 287 l +1480 288 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1766 288 m +1767 287 l +1766 288 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1996 288 m +1997 287 l +1996 288 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1997 288 m +1997.683 286.420 1997.805 286.223 1999 285 c +1998.316 286.580 1998.195 286.777 1997 288 c +f +*U +0.000 0.000 0.000 0.188 k +*u +579.667 286.667 m +579.222 286.222 580.278 286.278 580.333 286.333 c +580.778 286.778 579.722 286.722 579.667 286.667 c +f +*U +0.000 0.741 0.478 0.259 k +*u +1051 287 m +1051 283 l +1051.710 284.759 1051.710 285.241 1051 287 c +f +*U +0.000 0.886 0.667 0.110 k +*u +1154 287 m +1157 285 l +1155 284 1154.222 283.733 1153 282 c +1160 282 l +1159 287 l +1154 287 l +f +*U +0.000 0.267 0.259 0.706 k +*u +1160 287 m +1161 286 l +1160 287 l +f +*U +0.000 0.553 0.388 0.196 k +*u +1216.333 286.333 m +1216.278 286.278 1216.222 285.222 1216.667 285.667 c +1216.722 285.722 1216.777 286.778 1216.333 286.333 c +f +*U +0.122 0.000 0.031 0.161 k +*u +1317 287 m +1318 286 l +1317 287 l +f +*U +0.000 0.451 0.271 0.133 k +*u +1319 287 m +1320 286 l +1319 287 l +f +*U +0.000 0.000 0.000 0.792 k +*u +1455 287 m +1456 286 l +1455 287 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1698 287 m +1698 253 l +1700 253 l +1700 285 l +1709.432 285 1719 286 1728 283 c +1721.767 290 1706.728 287 1698 287 c +f +*U +0.000 0.000 0.000 0.631 k +*u +1724 287 m +1725 286 l +1724 287 l +f +*U +0.000 0.000 0.000 0.043 k +*u +1746 287 m +1747.506 286.317 1748.315 286.174 1750 286 c +1750 283 l +1755 283 l +1754.402 284.196 1754.534 283.977 1753 285 c +1754.314 285.768 1754.232 285.686 1755 287 c +1746 287 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1755 287 m +1757.234 284 1759.750 284.856 1763 286 c +1760.387 287 1757.835 286.993 1755 287 c +f +*U +0.000 0.000 0.000 0.165 k +*u +1763 287 m +1764.506 286.317 1765.315 286.174 1767 286 c +1765.494 286.683 1764.685 286.826 1763 287 c +f +*U +0.000 0.000 0.000 0.078 k +*u +1907 287 m +1906 282 l +1907.656 283.686 1908.251 284.746 1909 287 c +1907 287 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1909 287 m +1910 286 l +1909 287 l +f +*U +0.000 0.000 0.000 0.075 k +*u +581 286 m +583 282.223 585.961 280.341 590 279 c +587.451 282 584.610 284.201 581 286 c +f +*U +0.000 0.000 0.000 0.710 k +*u +582 286 m +583 285 l +582 286 l +f +*U +0.000 0.000 0.000 0.831 k +*u +913 286 m +914 285 l +913 286 l +f +*U +0.000 0.451 0.357 0.506 k +*u +1160 286 m +1160 283 l +1160.696 284.554 1160.696 284.446 1160 286 c +f +*U +0.000 0.459 0.337 0.153 k +*u +1315 286 m +1316 285 l +1315 286 l +f +*U +0.000 0.310 0.216 0.055 k +*u +1316 286 m +1317 285 l +1316 286 l +f +*U +0.016 0.035 0.000 0.188 k +*u +1319.333 285.333 m +1319.278 285.278 1319.222 284.222 1319.667 284.667 c +1319.723 284.723 1319.777 285.777 1319.333 285.333 c +f +*U +0.000 0.000 0.000 0.094 k +*u +1455 286 m +1458.420 281.873 1462.878 279.478 1468 278 c +1464.458 281.653 1459.766 284.255 1455 286 c +f +*U +0.000 0.000 0.000 0.176 k +*u +1484.667 285.667 m +1484.222 285.222 1485.278 285.278 1485.333 285.333 c +1485.778 285.778 1484.722 285.722 1484.667 285.667 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1747 286 m +1748 285 l +1747 286 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1748 286 m +1748.545 284.365 1748.365 284.545 1750 284 c +1750 286 l +1748 286 l +f +*U +0.000 0.000 0.000 0.882 k +*u +615 285 m +615 281 l +615.710 282.760 615.710 283.240 615 285 c +f +*U +0.000 0.937 0.667 0.063 k +*u +1056 285 m +1062.194 282.401 1071.314 284 1078 284 c +1115 284 l +1122.281 284 1129.880 284.695 1137 283 c +1133.298 287.236 1121.373 285 1116 285 c +1056 285 l +f +*U +0.078 0.000 0.020 0.259 k +*u +1151 285 m +1151 282 l +1151.696 283.554 1151.696 283.446 1151 285 c +f +*U +0.000 0.239 0.196 0.141 k +*u +1161 285 m +1162 284 l +1161 285 l +f +*U +0.000 0.937 0.667 0.063 k +*u +1224 285 m +1230.436 282.299 1240 284 1247 284 c +1296 284 l +1289.564 286.701 1279.951 285 1273 285 c +1224 285 l +f +*U +0.000 0.671 0.529 0.329 k +*u +1316 285 m +1316.899 282.876 1316.876 282.899 1319 282 c +1317.897 283.457 1317.457 283.897 1316 285 c +f +*U +0.000 0.369 0.239 0.086 k +*u +1317 285 m +1318 284 l +1317 285 l +f +*U +0.000 0.937 0.667 0.063 k +*u +1328 285 m +1333.707 282.605 1341.846 284 1348 284 c +1392 284 l +1386.293 286.395 1378 285 1372 285 c +1328 285 l +f +*U +0.000 0.204 0.176 0.047 k +*u +1398 285 m +1399 284 l +1398 285 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1458 285 m +1459 284 l +1458 285 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1486.667 284.667 m +1486.222 284.222 1487.278 284.278 1487.333 284.333 c +1487.778 284.778 1486.722 284.722 1486.667 284.667 c +f +*U +0.000 0.000 0.000 0.627 k +*u +1998 285 m +1999 284 l +1998 285 l +f +*U +0.000 0.000 0.000 0.067 k +*u +1999 285 m +2000 281.826 2001.785 279.509 2004 277 c +2003.829 280.924 2002 282.680 1999 285 c +f +*U +0.000 0.000 0.000 0.718 k +*u +820 284 m +821 283 l +820 284 l +f +*U +0.000 0.212 0.141 0.106 k +*u +1050.333 283.333 m +1050.278 283.278 1050.222 282.222 1050.667 282.667 c +1050.722 282.722 1050.778 283.778 1050.333 283.333 c +f +*U +0.000 0.510 0.447 0.404 k +*u +1140 284 m +1141 283 l +1140 284 l +f +*U +0.000 0.290 0.255 0.329 k +*u +1141 284 m +1142 283 l +1141 284 l +f +*U +0.000 0.369 0.329 0.259 k +*u +1161 284 m +1162 283 l +1161 284 l +f +*U +0.000 0.506 0.486 0.494 k +*u +1216.333 283.333 m +1216.278 283.278 1216.222 282.222 1216.667 282.667 c +1216.722 282.722 1216.777 283.778 1216.333 283.333 c +f +*U +0.000 0.243 0.216 0.051 k +*u +1318.667 283.667 m +1318.222 283.222 1319.278 283.278 1319.333 283.333 c +1319.778 283.778 1318.722 283.722 1318.667 283.667 c +f +*U +0.000 0.416 0.416 0.584 k +*u +1397.333 283.333 m +1397.278 283.278 1397.222 282.222 1397.667 282.667 c +1397.722 282.722 1397.778 283.778 1397.333 283.333 c +f +*U +0.000 0.000 0.000 0.584 k +*u +1487 284 m +1488 283 l +1487 284 l +f +*U +0.000 0.000 0.000 0.773 k +*u +586 283 m +587 282 l +586 283 l +f +*U +0.000 0.000 0.000 0.184 k +*u +818.333 282.333 m +818.278 282.278 818.222 281.222 818.667 281.667 c +818.722 281.722 818.778 282.778 818.333 282.333 c +f +*U +0.000 0.000 0.000 0.788 k +*u +915 283 m +916 282 l +915 283 l +f +*U +0.000 0.733 0.624 0.251 k +*u +1051 283 m +1052.769 282.221 1054 282 1056 282 c +1054.231 282.779 1052.964 282.912 1051 283 c +f +*U +0.000 0.698 0.514 0.290 k +*u +1136.667 282.667 m +1136.222 282.222 1137.278 282.278 1137.333 282.333 c +1137.778 282.778 1136.722 282.722 1136.667 282.667 c +f +*U +0.000 0.216 0.216 0.318 k +*u +1140 283 m +1141 282 l +1140 283 l +f +*U +0.000 0.659 0.545 0.341 k +*u +1160 283 m +1161.506 282.317 1162.315 282.174 1164 282 c +1162.494 282.683 1161.685 282.826 1160 283 c +f +*U +0.000 0.200 0.125 0.494 k +*u +1164 283 m +1165 282 l +1164 283 l +f +*U +0.039 0.000 0.012 0.231 k +*u +1215.333 282.333 m +1215.278 282.278 1215.222 281.222 1215.667 281.667 c +1215.723 281.723 1215.777 282.777 1215.333 282.333 c +f +*U +0.000 0.655 0.455 0.173 k +*u +1299.667 282.667 m +1299.222 282.222 1300.278 282.278 1300.333 282.333 c +1300.778 282.778 1299.722 282.722 1299.667 282.667 c +f +*U +0.000 0.561 0.416 0.439 k +*u +1301 283 m +1302.248 282.315 1302.548 282.251 1304 282 c +1302.752 282.685 1302.451 282.749 1301 283 c +f +*U +0.000 0.714 0.533 0.286 k +*u +1304 283 m +1305.248 282.315 1305.548 282.251 1307 282 c +1305.752 282.685 1305.452 282.749 1304 283 c +f +*U +0.000 0.000 0.000 0.118 k +*u +1489 283 m +1493.467 279 1499.361 275.785 1505 274 c +1500.973 278.359 1494.838 281.874 1489 283 c +f +*U +0.000 0.000 0.000 0.200 k +*u +1728 283 m +1729 282 l +1728 283 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1729 283 m +1730 282 l +1729 283 l +f +*U +0.000 0.000 0.000 0.149 k +*u +1752 283 m +1753.223 281.805 1753.420 281.684 1755 281 c +1753.777 282.195 1753.580 282.316 1752 283 c +f +*U +0.000 0.361 0.282 0.275 k +*u +1051.667 281.667 m +1051.222 281.222 1052.278 281.278 1052.333 281.333 c +1052.778 281.778 1051.722 281.722 1051.667 281.667 c +f +*U +0.000 0.247 0.204 0.267 k +*u +1053 282 m +1060 278.996 1071.256 281 1079 281 c +1137 281 l +1129.841 284 1118.744 282 1111 282 c +1053 282 l +f +*U +0.000 0.498 0.380 0.286 k +*u +1137.667 281.667 m +1137.222 281.222 1138.278 281.278 1138.333 281.333 c +1138.778 281.778 1137.722 281.722 1137.667 281.667 c +f +*U +0.000 0.314 0.247 0.173 k +*u +1139 282 m +1140 281 l +1139 282 l +f +*U +0.000 0.451 0.310 0.282 k +*u +1152 282 m +1153.249 281.315 1153.548 281.251 1155 281 c +1153.752 281.685 1153.452 281.749 1152 282 c +f +*U +0.000 0.498 0.380 0.043 k +*u +1155 282 m +1157.332 281 1159.457 281 1162 281 c +1159.669 281.984 1157.543 281.981 1155 282 c +f +*U +0.000 0.443 0.314 0.227 k +*u +1162 282 m +1163.249 281.315 1163.548 281.251 1165 281 c +1163.752 281.685 1163.452 281.749 1162 282 c +f +*U +0.000 0.404 0.286 0.302 k +*u +1216.667 281.667 m +1216.222 281.222 1217.278 281.278 1217.333 281.333 c +1217.778 281.778 1216.722 281.722 1216.667 281.667 c +f +*U +0.000 0.392 0.298 0.208 k +*u +1218 282 m +1219.769 281.221 1221 281 1223 281 c +1221.231 281.779 1219.964 281.912 1218 282 c +f +*U +0.000 0.247 0.204 0.267 k +*u +1223 282 m +1229.678 279.198 1239.784 281 1247 281 c +1299 281 l +1292.322 283.802 1282.216 282 1275 282 c +1223 282 l +f +*U +0.000 0.294 0.239 0.165 k +*u +1304.667 281.667 m +1304.222 281.222 1305.278 281.278 1305.333 281.333 c +1305.778 281.778 1304.722 281.722 1304.667 281.667 c +f +*U +0.000 0.396 0.302 0.337 k +*u +1306.667 281.667 m +1306.222 281.222 1307.278 281.278 1307.333 281.333 c +1307.778 281.778 1306.722 281.722 1306.667 281.667 c +f +*U +0.000 0.380 0.294 0.149 k +*u +1308 282 m +1309.506 281.317 1310.315 281.174 1312 281 c +1310.494 281.683 1309.685 281.826 1308 282 c +f +*U +0.000 0.275 0.200 0.396 k +*u +1312 282 m +1313 281 l +1312 282 l +f +*U +0.000 0.247 0.204 0.267 k +*u +1313 282 m +1320 278.996 1331.256 281 1339 281 c +1398 281 l +1390.841 284 1379.744 282 1372 282 c +1313 282 l +f +*U +0.000 0.000 0.000 0.737 k +*u +1463 282 m +1464 281 l +1463 282 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1730 282 m +1731 281 l +1730 282 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1905 282 m +1904 280.521 1904 280.797 1904 279 c +1905.289 280.443 1905.401 280.234 1905 282 c +f +*U +0.000 0.000 0.000 0.749 k +*u +1906 282 m +1907 281 l +1906 282 l +f +*U +0.000 0.000 0.000 0.561 k +*u +615 281 m +616 280 l +615 281 l +f +*U +0.000 0.000 0.000 0.200 k +*u +817.333 280.333 m +817.278 280.278 817.222 279.222 817.667 279.667 c +817.722 279.722 817.778 280.778 817.333 280.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +818 281 m +819 280 l +818 281 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1492 281 m +1493 280 l +1492 281 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1730 281 m +1731.624 278.956 1732.643 278 1735 277 c +1733.376 279 1732.357 279.896 1730 281 c +f +*U +0.000 0.000 0.000 0.612 k +*u +1754 281 m +1755 280 l +1754 281 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1755 281 m +1756.450 279.392 1757 278.936 1759 278 c +1757.550 279.608 1756.949 280 1755 281 c +f +*U +0.000 0.000 0.000 0.729 k +*u +590 280 m +591 279 l +590 280 l +f +*U +0.000 0.000 0.000 0.000 k +*u +615 280 m +616 279 l +615 280 l +f +*U +0.000 0.000 0.000 0.776 k +*u +917 280 m +918 279 l +917 280 l +f +*U +0.000 0.000 0.000 0.125 k +*u +918 280 m +919 277 920.414 274.618 922 272 c +922.576 275.534 920.603 277.762 918 280 c +f +*U +0.000 0.000 0.000 0.796 k +*u +2001 280 m +2002 279 l +2001 280 l +f +*U +0.000 0.000 0.000 0.137 k +*u +2002.333 279.333 m +2002.278 279.278 2002.222 278.222 2002.667 278.667 c +2002.723 278.723 2002.777 279.777 2002.333 279.333 c +f +*U +0.000 0.000 0.000 0.341 k +*u +590 279 m +591 278 l +590 279 l +f +*U +0.000 0.000 0.000 0.576 k +*u +591 279 m +592 278 l +591 279 l +f +*U +0.000 0.000 0.000 0.133 k +*u +816 279 m +814.602 276.950 813.749 275.354 813 273 c +815 274.908 816.250 276.208 816 279 c +f +*U +0.000 0.000 0.000 0.773 k +*u +1468 279 m +1469 278 l +1468 279 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1904 279 m +1905 278 l +1904 279 l +f +*U +0.000 0.000 0.000 0.063 k +*u +591 278 m +594 273 l +599 272 l +596.681 274.841 594.378 276.568 591 278 c +f +*U +0.000 0.000 0.000 0.694 k +*u +616.333 277.333 m +616.278 277.278 616.222 276.222 616.667 276.667 c +616.722 276.722 616.778 277.778 616.333 277.333 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1468 278 m +1469.543 276.733 1470 276.511 1472 276 c +1470.542 277 1469.752 277.436 1468 278 c +f +*U +0.000 0.000 0.000 0.702 k +*u +1735 278 m +1736 277 l +1735 278 l +f +*U +0.000 0.000 0.000 0.639 k +*u +1758 278 m +1759 277 l +1758 278 l +f +*U +0.000 0.000 0.000 0.671 k +*u +919 277 m +920 276 l +919 277 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1499 277 m +1500 276 l +1499 277 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1760 277 m +1761.223 275.805 1761.420 275.684 1763 275 c +1761.777 276.195 1761.580 276.316 1760 277 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1903 277 m +1904 276 l +1903 277 l +f +*U +0.000 0.000 0.000 0.655 k +*u +2003 277 m +2004 276 l +2003 277 l +f +*U +0.000 0.000 0.000 0.051 k +*u +2004 277 m +2004.547 275 2005 273.745 2006 272 c +2006.710 274.531 2006 275.516 2004 277 c +f +*U +0.000 0.000 0.000 0.753 k +*u +595 276 m +596 275 l +595 276 l +f +*U +0.000 0.000 0.000 0.745 k +*u +815 276 m +816 275 l +815 276 l +f +*U +0.000 0.000 0.000 0.749 k +*u +834 276 m +835 275 l +834 276 l +f +*U +0.000 0.000 0.000 0.129 k +*u +833 272 m +840.188 275 848.323 274 856 274 c +898 274 l +893.280 275.981 887 275 882 275 c +849 275 l +843.679 275 835.945 277.210 833 272 c +f +*U +0.000 0.000 0.000 0.784 k +*u +899 276 m +900 275 l +899 276 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1471.667 275.667 m +1471.222 275.222 1472.278 275.278 1472.333 275.333 c +1472.778 275.778 1471.722 275.722 1471.667 275.667 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1473 276 m +1474 275 l +1473 276 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1736 276 m +1738.719 272.223 1741.644 269.688 1746 268 c +1743.264 271.575 1740 274 1736 276 c +f +*U +0.000 0.000 0.000 0.000 k +*u +259.333 274.333 m +259.278 274.278 259.222 273.222 259.667 273.667 c +259.722 273.722 259.778 274.778 259.333 274.333 c +f +*U +0.000 0.000 0.000 0.114 k +*u +899 275 m +899.684 273.420 899.805 273.223 901 272 c +900.316 273.580 900.195 273.777 899 275 c +f +1473 275 m +1474.717 273 1475.566 272.651 1478 272 c +1476.313 273.656 1475.254 274.251 1473 275 c +f +*U +0.000 0.000 0.000 0.737 k +*u +1762 275 m +1763 274 l +1762 275 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1763 275 m +1768.354 268.424 1778.192 261.301 1786 258 c +1780.827 264.785 1771 272.274 1763 275 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1920 275 m +1921 274 l +1920 275 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1920 272 m +1933.679 275.257 1949.965 273 1964 273 c +1969.259 273 1976.967 274.410 1981.895 272.397 c +1985.436 270.950 1987 266.437 1990 264 c +1989 267 1987.593 271 1984.621 272.972 c +1981 275 1974.935 274 1971 274 c +1939 274 l +1934 274 1923 276.201 1920 272 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1922 275 m +1927.708 272.605 1935.846 274 1942 274 c +1984 274 l +1978.293 276.395 1970 275 1964 275 c +1922 275 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1984 275 m +1985 274 l +1984 275 l +f +*U +0.000 0.000 0.000 0.698 k +*u +1504 274 m +1505 273 l +1504 274 l +f +*U +0.000 0.000 0.000 0.290 k +*u +1505 274 m +1506 273 l +1505 274 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1655.333 273.333 m +1655.278 273.278 1655.222 272.222 1655.667 272.667 c +1655.722 272.722 1655.777 273.778 1655.333 273.333 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1901 274 m +1902 273 l +1901 274 l +f +*U +0.000 0.000 0.000 0.784 k +*u +599 273 m +600 272 l +599 273 l +f +*U +0.000 0.000 0.000 0.063 k +*u +812 273 m +810.652 271.232 809.878 270 809 268 c +811.343 269.347 812.401 270.259 812 273 c +f +*U +0.000 0.000 0.000 0.631 k +*u +813 273 m +814 272 l +813 273 l +f +*U +0.000 0.000 0.000 0.808 k +*u +832 273 m +833 272 l +832 273 l +f +*U +0.000 0.000 0.000 0.604 k +*u +1506 273 m +1507 272 l +1506 273 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1507 273 m +1508.223 271.805 1508.420 271.684 1510 271 c +1508.777 272.195 1508.580 272.316 1507 273 c +f +*U +0.000 0.000 0.000 0.722 k +*u +1741 273 m +1742 272 l +1741 273 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1919 273 m +1920 272 l +1919 273 l +f +*U +0.000 0.000 0.000 0.161 k +*u +806 272 m +806 268 l +806.710 269.760 806.710 270.241 806 272 c +f +*U +0.000 0.000 0.000 0.114 k +*u +832 272 m +831 270.255 830.547 268.875 830 267 c +831.693 268.782 832.375 269.581 832 272 c +f +*U +0.000 0.000 0.000 0.196 k +*u +901.333 271.333 m +901.278 271.278 901.222 270.222 901.667 270.667 c +901.722 270.722 901.778 271.778 901.333 271.333 c +f +*U +0.000 0.000 0.000 0.753 k +*u +1766 272 m +1767 271 l +1766 272 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1919 272 m +1918 270.522 1918 270.797 1918 269 c +1919.290 270.443 1919.401 270.233 1919 272 c +f +*U +0.000 0.000 0.000 0.110 k +*u +2007 272 m +2008.460 268 2010.660 264.537 2013 261 c +2013.886 265.544 2010.329 269.281 2007 272 c +f +*U +0.000 0.000 0.000 0.141 k +*u +169 271 m +175.919 268 186.520 270 194 270 c +249 270 l +242 272.903 231.480 271 224 271 c +169 271 l +f +*U +0.000 0.000 0.000 0.153 k +*u +280 271 m +285.951 268.503 294.580 270 301 270 c +345 270 l +339 272.497 330.420 271 324 271 c +280 271 l +f +*U +0.000 0.000 0.000 0.161 k +*u +600 271 m +601.223 269.805 601.420 269.684 603 269 c +601.777 270.195 601.580 270.316 600 271 c +f +*U +0.000 0.000 0.000 0.710 k +*u +902 271 m +903 270 l +902 271 l +f +*U +0.000 0.000 0.000 0.102 k +*u +924 271 m +924.777 268.511 925.817 266.328 927 264 c +927.728 267 926.256 268.853 924 271 c +f +*U +0.000 0.000 0.000 0.153 k +*u +958 271 m +964.436 268.299 974 270 981 270 c +1032 270 l +1025.564 272.701 1015.951 271 1009 271 c +958 271 l +f +*U +0.000 0.000 0.000 0.325 k +*u +1032 271 m +1033 270 l +1032 271 l +f +*U +0.000 0.306 0.227 0.243 k +*u +1052 271 m +1052 268 l +1053 269 1053.309 269.612 1054 271 c +1052 271 l +f +*U +0.000 0.478 0.349 0.161 k +*u +1054 271 m +1061 267.996 1072.256 270 1080 270 c +1138 270 l +1130.841 273 1119.744 271 1112 271 c +1054 271 l +f +*U +0.000 0.051 0.043 0.286 k +*u +1141 271 m +1142 270 l +1141 271 l +f +*U +0.000 0.318 0.220 0.455 k +*u +1142 271 m +1143 270 l +1142 271 l +f +*U +0.000 0.263 0.184 0.153 k +*u +1143 271 m +1144 270 l +1143 271 l +f +*U +0.000 0.478 0.349 0.161 k +*u +1147 271 m +1154.649 267.790 1166.712 270 1175 270 c +1167.351 273.210 1155.288 271 1147 271 c +f +*U +0.000 0.435 0.314 0.361 k +*u +1175 271 m +1176 270 l +1175 271 l +f +*U +0.000 0.247 0.212 0.227 k +*u +1195 271 m +1196.248 270.315 1196.548 270.251 1198 270 c +1196.752 270.685 1196.451 270.749 1195 271 c +f +*U +0.000 0.478 0.349 0.161 k +*u +1198 271 m +1204.194 268.401 1213.314 270 1220 270 c +1268 270 l +1261.806 272.599 1252.686 271 1246 271 c +1198 271 l +f +*U +0.000 0.416 0.247 0.298 k +*u +1268 271 m +1269.769 270.221 1271 270 1273 270 c +1271.231 270.779 1269.964 270.912 1268 271 c +f +*U +0.000 0.192 0.114 0.188 k +*u +1273.333 270.333 m +1273.278 270.278 1273.222 269.222 1273.667 269.667 c +1273.723 269.723 1273.777 270.777 1273.333 270.333 c +f +*U +0.000 0.298 0.231 0.106 k +*u +1278 271 m +1279 270 l +1278 271 l +f +*U +0.000 0.471 0.341 0.169 k +*u +1279 271 m +1284.715 268.602 1292.831 270 1299 270 c +1293.285 272.398 1285.169 271 1279 271 c +f +*U +0.000 0.278 0.196 0.098 k +*u +1299 271 m +1300 270 l +1299 271 l +f +*U +0.000 0.282 0.192 0.075 k +*u +1307.667 270.667 m +1307.222 270.222 1308.278 270.278 1308.333 270.333 c +1308.778 270.778 1307.722 270.722 1307.667 270.667 c +f +*U +0.000 0.467 0.318 0.275 k +*u +1309 271 m +1310.249 270.315 1310.548 270.251 1312 270 c +1310.752 270.685 1310.452 270.749 1309 271 c +f +*U +0.000 0.153 0.098 0.106 k +*u +1312 271 m +1313 270 l +1312 271 l +f +*U +0.000 0.216 0.165 0.161 k +*u +1316 271 m +1317 270 l +1316 271 l +f +*U +0.000 0.310 0.235 0.286 k +*u +1317 271 m +1318.506 270.317 1319.315 270.174 1321 270 c +1319.494 270.683 1318.685 270.826 1317 271 c +f +*U +0.000 0.478 0.349 0.161 k +*u +1321 271 m +1327.436 268.299 1337 270 1344 270 c +1393 270 l +1386.564 272.701 1376.951 271 1370 271 c +1321 271 l +f +*U +0.000 0.408 0.314 0.129 k +*u +1393 271 m +1396 268 l +1396.951 270.507 1395.348 270.706 1393 271 c +f +*U +0.000 0.000 0.000 0.545 k +*u +1481 271 m +1482 270 l +1481 271 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1509 271 m +1510 270 l +1509 271 l +f +*U +0.000 0.000 0.000 0.141 k +*u +1510.667 270.667 m +1510.222 270.222 1511.278 270.278 1511.333 270.333 c +1511.778 270.778 1510.722 270.722 1510.667 270.667 c +f +*U +0.000 0.000 0.000 0.612 k +*u +169 270 m +175.919 267 186.520 269 194 269 c +249 269 l +242 271.903 231.480 270 224 270 c +169 270 l +f +*U +0.000 0.000 0.000 0.851 k +*u +280 270 m +285.951 267.503 294.580 269 301 269 c +345 269 l +339 271.497 330.420 270 324 270 c +280 270 l +f +721 270 m +726.951 267.503 735.580 269 742 269 c +786 269 l +780 271.497 771.420 270 765 270 c +721 270 l +f +*U +0.000 0.000 0.000 0.239 k +*u +902 270 m +903 269 l +902 270 l +f +*U +0.000 0.000 0.000 0.851 k +*u +958 270 m +964.678 267.198 974.784 269 982 269 c +1033 269 l +1026.564 271.701 1016.951 270 1010 270 c +958 270 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1033 270 m +1033 254 l +1036 258.484 1035 264.749 1035 270 c +1033 270 l +f +*U +0.000 0.859 0.616 0.133 k +*u +1053 270 m +1053.482 267.636 1053.636 267.482 1056 267 c +1055.198 263.829 1055.599 261.232 1056 258 c +1136 258 l +1135 262.609 1135.960 265.571 1137 270 c +1053 270 l +f +*U +0.000 0.459 0.345 0.541 k +*u +1137.333 269.333 m +1137.278 269.278 1137.222 268.222 1137.667 268.667 c +1137.722 268.722 1137.777 269.778 1137.333 269.333 c +f +*U +0.000 0.102 0.086 0.184 k +*u +1138 270 m +1139 269 l +1138 270 l +f +*U +0.000 0.271 0.176 0.196 k +*u +1141.333 269.333 m +1141.278 269.278 1141.222 268.222 1141.667 268.667 c +1141.722 268.722 1141.777 269.778 1141.333 269.333 c +f +*U +0.000 0.612 0.408 0.353 k +*u +1142 270 m +1142 266 l +1143 267.458 1143.436 268.248 1144 270 c +1142 270 l +f +*U +0.000 0.655 0.549 0.345 k +*u +1147 270 m +1147 263 l +1148 265.534 1148 267.466 1147 270 c +f +*U +0.000 0.878 0.620 0.122 k +*u +1148 270 m +1148 267 1147.474 263 1149.742 260.742 c +1151.802 258.683 1155.340 259 1158 258.715 c +1166.621 257.652 1175.319 258 1184 258 c +1180.970 262.517 1177 264.215 1176 270 c +1148 270 l +f +*U +0.000 0.122 0.086 0.188 k +*u +1176 270 m +1177 269 l +1176 270 l +f +*U +0.000 0.404 0.306 0.294 k +*u +1194 270 m +1195 269 l +1194 270 l +f +*U +0.000 0.812 0.655 0.188 k +*u +1194 266 m +1198 269 l +1195.251 269.603 1194.500 268.638 1194 266 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1192 258 m +1264 258 l +1261 263.656 1266.715 265 1270 269 c +1252.776 268 1235.258 269 1218 269 c +1212.485 269 1202 271 1197.228 268.651 c +1193.931 267 1192.774 261.285 1192 258 c +f +*U +0.000 0.839 0.616 0.161 k +*u +1199 270 m +1205.194 267.401 1214.314 269 1221 269 c +1255 269 l +1260.628 269.000 1266.457 268 1272 269 c +1265.564 271.701 1255.951 270 1249 270 c +1199 270 l +f +*U +0.000 0.451 0.294 0.549 k +*u +1272 270 m +1273 269 l +1272 270 l +f +*U +0.000 0.235 0.176 0.114 k +*u +1276 270 m +1277 269 l +1276 270 l +f +*U +0.000 0.718 0.518 0.282 k +*u +1271 260 m +1275.314 262 1276.665 265.876 1280 269 c +1275.894 269.917 1273 263 1271 260 c +f +*U +0.000 0.855 0.604 0.141 k +*u +1271 258 m +1278.564 258 1286.480 257.330 1294 258.174 c +1297.428 258.559 1300.468 260.538 1303.830 260.860 c +1306.956 261 1309.747 259.775 1312.986 260.484 c +1317.567 261.486 1319 267 1323 267.687 c +1329 268.499 1336.776 267 1343 267 c +1392 267 l +1386.293 269.395 1378 268 1372 268 c +1328 268 l +1335 270 1343.573 269 1351 269 c +1395 269 l +1389 271.497 1380.420 270 1374 270 c +1327 270 l +1321.541 270.000 1308.956 271.874 1307 266 c +1304.706 266.303 1303.788 266.579 1302 268 c +1299 267 l +1298 271.221 1293.654 270 1290 270 c +1286.941 270 1282.926 270.656 1280 269.500 c +1276.675 268 1272.924 261 1271 258 c +f +*U +0.000 0.647 0.443 0.333 k +*u +1299 270 m +1299.406 267.907 1299.216 267.980 1301 267 c +1300.309 268.388 1300 268.861 1299 270 c +f +*U +0.000 0.455 0.322 0.353 k +*u +1306.333 269.333 m +1306.278 269.278 1306.222 268.222 1306.667 268.667 c +1306.722 268.722 1306.777 269.778 1306.333 269.333 c +f +*U +0.000 0.361 0.337 0.639 k +*u +1307 270 m +1308 269 l +1307 270 l +f +*U +0.000 0.714 0.553 0.286 k +*u +1312 270 m +1313.769 269.221 1315 269 1317 269 c +1315.231 269.779 1313.964 269.912 1312 270 c +f +*U +0.000 0.702 0.525 0.298 k +*u +1395 270 m +1395 266 l +1395.710 267.759 1395.710 268.241 1395 270 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1511 270 m +1512 269 l +1511 270 l +f +*U +0.000 0.000 0.000 0.157 k +*u +1514.333 269.333 m +1514.278 269.278 1514.222 268.222 1514.667 268.667 c +1514.722 268.722 1514.777 269.778 1514.333 269.333 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1539 270 m +1540 269 l +1539 270 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1917 270 m +1918 269 l +1917 270 l +f +*U +0.000 0.000 0.000 0.698 k +*u +1987 270 m +1988 269 l +1987 270 l +f +*U +0.000 0.000 0.000 0.518 k +*u +364 269 m +365 268 l +364 269 l +f +*U +0.000 0.000 0.000 0.604 k +*u +604 269 m +605 268 l +604 269 l +f +*U +0.000 0.000 0.000 0.549 k +*u +805 269 m +806 268 l +805 269 l +f +*U +0.000 0.000 0.000 0.157 k +*u +903.333 268.333 m +903.278 268.278 903.222 267.222 903.667 267.667 c +903.722 267.722 903.778 268.778 903.333 268.333 c +f +*U +0.000 0.243 0.169 0.553 k +*u +1176 269 m +1177 268 l +1176 269 l +f +*U +0.000 0.361 0.271 0.239 k +*u +1193 269 m +1194 268 l +1193 269 l +f +*U +0.000 0.600 0.576 0.400 k +*u +1271 269 m +1272 268 l +1271 269 l +f +*U +0.000 0.294 0.169 0.071 k +*u +1272 269 m +1273 268 l +1272 269 l +f +*U +0.000 0.255 0.176 0.114 k +*u +1275.333 268.333 m +1275.278 268.278 1275.222 267.222 1275.667 267.667 c +1275.722 267.722 1275.778 268.778 1275.333 268.333 c +f +*U +0.000 0.302 0.224 0.153 k +*u +1300 269 m +1301 268 l +1300 269 l +f +*U +0.000 0.596 0.447 0.345 k +*u +1321 269 m +1322.248 268.315 1322.548 268.251 1324 268 c +1322.752 268.685 1322.451 268.749 1321 269 c +f +*U +0.000 0.859 0.616 0.133 k +*u +1328 269 m +1333.707 266.605 1341.846 268 1348 268 c +1392 268 l +1384.848 265.886 1376.427 267 1369 267 c +1327 267 l +1329 257.518 1336.680 258 1345 258 c +1361 257.994 1377 258.956 1393 259 c +1393.655 261.537 1394.276 263 1396 265 c +1395 269 l +1328 269 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1483 269 m +1484.223 267.805 1484.420 267.684 1486 267 c +1484.777 268.195 1484.580 268.316 1483 269 c +f +*U +0.000 0.000 0.000 0.839 k +*u +1559 269 m +1565.678 266.198 1575.784 268 1583 268 c +1636 268 l +1629.322 270.802 1619.216 269 1612 269 c +1559 269 l +f +*U +0.000 0.000 0.000 0.620 k +*u +1818 269 m +1824.678 266.198 1834.784 268 1842 268 c +1896 268 l +1889.322 270.802 1879.216 269 1872 269 c +1818 269 l +f +*U +0.000 0.000 0.000 0.259 k +*u +1896 269 m +1896 266 l +1896.696 267.554 1896.696 267.446 1896 269 c +f +*U +0.000 0.000 0.000 0.141 k +*u +1917.333 268.333 m +1917.278 268.278 1917.222 267.222 1917.667 267.667 c +1917.722 267.723 1917.777 268.778 1917.333 268.333 c +f +*U +0.000 0.000 0.000 0.702 k +*u +2008 269 m +2009 268 l +2008 269 l +f +*U +0.000 0.000 0.000 0.506 k +*u +260 268 m +261 267 l +260 268 l +f +*U +0.000 0.000 0.000 0.157 k +*u +604.667 267.667 m +604.222 267.222 605.278 267.278 605.333 267.333 c +605.778 267.778 604.722 267.722 604.667 267.667 c +f +*U +0.000 0.000 0.000 0.533 k +*u +701 268 m +702 267 l +701 268 l +f +*U +0.000 0.000 0.000 0.059 k +*u +805 268 m +804.719 264.256 803.789 262.510 801 260 c +801 258 l +802 257 l +804 257 l +806.226 260.710 806.484 263.797 807 268 c +805 268 l +f +*U +0.000 0.000 0.000 0.137 k +*u +809 268 m +808 266.521 808 266.797 808 265 c +809.289 266.443 809.401 266.234 809 268 c +f +*U +0.000 0.000 0.000 0.769 k +*u +810 268 m +811 267 l +810 268 l +f +*U +0.000 0.000 0.000 0.749 k +*u +829 268 m +830 267 l +829 268 l +f +*U +0.000 0.306 0.216 0.000 k +*u +1052 268 m +1053 267 l +1052 268 l +f +*U +0.000 0.275 0.200 0.243 k +*u +1137 268 m +1138 267 l +1137 268 l +f +*U +0.000 0.247 0.165 0.039 k +*u +1141 268 m +1142 267 l +1141 268 l +f +*U +0.000 0.059 0.031 0.592 k +*u +1143 268 m +1142 265 l +1143.766 265.979 1143.956 266.222 1143 268 c +f +*U +0.000 0.553 0.420 0.447 k +*u +1176.333 267.333 m +1176.278 267.278 1176.222 266.222 1176.667 266.667 c +1176.722 266.722 1176.777 267.778 1176.333 267.333 c +f +*U +0.000 0.380 0.314 0.463 k +*u +1268 266 m +1269.580 266.683 1269.777 266.805 1271 268 c +1269.420 267.316 1269.223 267.195 1268 266 c +f +*U +0.000 0.380 0.290 0.020 k +*u +1271 268 m +1272 267 l +1271 268 l +f +*U +0.000 0.302 0.231 0.149 k +*u +1305 268 m +1306 267 l +1305 268 l +f +*U +0.000 0.690 0.529 0.310 k +*u +1306 268 m +1305 266 l +1307 266 l +1307 267.853 1307.300 267.350 1306 268 c +f +*U +0.000 0.463 0.286 0.212 k +*u +1320 268 m +1321 267 l +1320 268 l +f +*U +0.000 0.133 0.141 0.267 k +*u +1321 268 m +1322.248 267.315 1322.548 267.251 1324 267 c +1322.752 267.685 1322.451 267.749 1321 268 c +f +*U +0.000 0.463 0.376 0.298 k +*u +1324 268 m +1325 267 l +1324 268 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1486 268 m +1487 267 l +1486 268 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1515 268 m +1517.487 265.868 1519.809 264.732 1523 264 c +1520.973 266.754 1518.313 267.426 1515 268 c +f +*U +0.000 0.000 0.000 0.714 k +*u +1747 268 m +1748 267 l +1747 268 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1916 268 m +1917 267 l +1916 268 l +f +*U +0.000 0.000 0.000 0.243 k +*u +829 267 m +830 266 l +829 267 l +f +*U +0.000 0.000 0.000 0.149 k +*u +904 267 m +904.547 265 905 263.745 906 262 c +906.375 264.419 905.693 265.218 904 267 c +f +*U +0.000 0.443 0.341 0.557 k +*u +1053 267 m +1053 264 l +1053.696 265.554 1053.696 265.446 1053 267 c +f +*U +0.000 0.671 0.482 0.329 k +*u +1054 267 m +1054 263.831 1054 261 1055 258 c +1056 260.847 1055.515 263.968 1056 267 c +1054 267 l +f +*U +0.000 0.722 0.557 0.278 k +*u +1135 267 m +1135 264 1135.190 261.729 1136 259 c +1136.668 261.787 1136.172 264.387 1135 267 c +f +*U +0.000 0.267 0.173 0.329 k +*u +1136 267 m +1137 266 l +1136 267 l +f +*U +0.000 0.345 0.235 0.055 k +*u +1177 267 m +1178 266 l +1177 267 l +f +*U +0.000 0.518 0.396 0.482 k +*u +1193.333 266.333 m +1193.278 266.278 1193.222 265.222 1193.667 265.667 c +1193.722 265.723 1193.777 266.778 1193.333 266.333 c +f +*U +0.000 0.365 0.267 0.549 k +*u +1302.667 266.667 m +1302.222 266.222 1303.278 266.278 1303.333 266.333 c +1303.778 266.778 1302.722 266.722 1302.667 266.667 c +f +*U +0.000 0.620 0.455 0.125 k +*u +1304 267 m +1305 266 l +1304 267 l +f +*U +0.000 0.329 0.271 0.212 k +*u +1325 267 m +1326 266 l +1325 267 l +f +*U +0.000 0.592 0.424 0.337 k +*u +1326 267 m +1326.406 264.908 1326.217 264.980 1328 264 c +1327.309 265.388 1327 265.861 1326 267 c +f +*U +0.000 0.000 0.000 0.133 k +*u +1486 267 m +1488.856 263.887 1491.878 261.969 1496 261 c +1493 263.952 1489.915 265.760 1486 267 c +f +*U +0.000 0.000 0.000 0.145 k +*u +1539 267 m +1540.965 254.625 1552.471 253 1563 253 c +1639 253 l +1633 255.497 1624.420 254 1618 254 c +1572 254 l +1564.251 254 1555 253 1548 257 c +1543.848 259.472 1541.841 263.404 1539 267 c +f +*U +0.000 0.000 0.000 0.682 k +*u +1654 267 m +1655 266 l +1654 267 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1747 267 m +1748.624 264.956 1749.643 264 1752 263 c +1750.376 265 1749.357 265.896 1747 267 c +f +*U +0.000 0.000 0.000 0.706 k +*u +1773 267 m +1774 266 l +1773 267 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1895 267 m +1896 266 l +1895 267 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1916 267 m +1915 265.521 1915 265.797 1915 264 c +1916.290 265.443 1916.401 265.233 1916 267 c +f +*U +0.000 0.000 0.000 0.996 k +*u +349 266 m +344.829 263.722 338.732 264.490 334 264.200 c +321 263.407 307.943 263.938 295 264 c +288.649 264 282.729 265.499 277 262 c +278.248 261.315 278.548 261.251 280 261 c +281.294 253.546 292.180 256 298 256 c +316.570 256 335.671 254.595 354 258 c +352.376 261.247 350.610 264.439 351 266 c +349 266 l +f +*U +0.000 0.000 0.000 0.741 k +*u +363 266 m +364 265 l +363 266 l +f +*U +0.000 0.000 0.000 0.706 k +*u +608 266 m +609 265 l +608 266 l +f +*U +0.000 0.000 0.000 0.737 k +*u +804 266 m +805 265 l +804 266 l +f +*U +0.000 0.000 0.000 0.675 k +*u +926 266 m +927 265 l +926 266 l +f +*U +0.000 0.455 0.310 0.365 k +*u +1177 266 m +1178 265 l +1177 266 l +f +*U +0.000 0.463 0.302 0.443 k +*u +1266.667 265.667 m +1266.222 265.222 1267.278 265.278 1267.333 265.333 c +1267.778 265.778 1266.722 265.722 1266.667 265.667 c +f +*U +0.000 0.275 0.224 0.247 k +*u +1268 266 m +1269 265 l +1268 266 l +f +*U +0.000 0.369 0.263 0.314 k +*u +1275 266 m +1276 265 l +1275 266 l +f +*U +0.000 0.000 0.000 0.745 k +*u +1518 266 m +1519 265 l +1518 266 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1540 266 m +1541 265 l +1540 266 l +f +*U +0.000 0.000 0.000 0.239 k +*u +1895.333 265.333 m +1895.278 265.278 1895.222 264.222 1895.667 264.667 c +1895.722 264.722 1895.777 265.778 1895.333 265.333 c +f +*U +0.000 0.000 0.000 0.643 k +*u +1896 266 m +1897 265 l +1896 266 l +f +*U +0.000 0.000 0.000 0.745 k +*u +261 265 m +262 264 l +261 265 l +f +*U +0.000 0.000 0.000 0.133 k +*u +608 265 m +609.223 263.805 609.420 263.684 611 263 c +609.777 264.195 609.580 264.316 608 265 c +f +*U +0.000 0.000 0.000 0.678 k +*u +702 265 m +703 264 l +702 265 l +f +*U +0.000 0.000 0.000 0.157 k +*u +804 265 m +803 261 l +804.303 262.668 804.553 262.992 804 265 c +f +*U +0.000 0.000 0.000 0.690 k +*u +808 265 m +809 264 l +808 265 l +f +*U +0.004 0.027 0.000 0.278 k +*u +1143 265 m +1144 264 l +1143 265 l +f +*U +0.000 0.447 0.337 0.553 k +*u +1177 265 m +1178 264 l +1177 265 l +f +*U +0.000 0.125 0.086 0.129 k +*u +1178 265 m +1179 264 l +1178 265 l +f +*U +0.000 0.702 0.494 0.298 k +*u +1193 265 m +1192 261 l +1193.656 262.404 1193.751 262.953 1193 265 c +f +*U +0.000 0.380 0.325 0.620 k +*u +1264.667 264.667 m +1264.222 264.222 1265.278 264.278 1265.333 264.333 c +1265.778 264.778 1264.722 264.722 1264.667 264.667 c +f +*U +0.000 0.282 0.153 0.063 k +*u +1266 265 m +1267 264 l +1266 265 l +f +*U +0.000 0.506 0.431 0.212 k +*u +1319 265 m +1320 264 l +1319 265 l +f +*U +0.000 0.675 0.475 0.325 k +*u +1394 265 m +1393 259 l +1394.654 261.177 1394.994 262.425 1394 265 c +f +*U +0.000 0.408 0.294 0.192 k +*u +1395 265 m +1396 264 l +1395 265 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1491 265 m +1492 264 l +1491 265 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1894 265 m +1895 264 l +1894 265 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1990 265 m +1991 264 l +1990 265 l +f +*U +0.000 0.000 0.000 0.125 k +*u +261.333 263.333 m +261.278 263.278 261.222 262.222 261.667 262.667 c +261.722 262.722 261.778 263.778 261.333 263.333 c +f +702.333 263.333 m +702.278 263.278 702.222 262.222 702.667 262.667 c +702.722 262.722 702.778 263.778 702.333 263.333 c +f +*U +0.000 0.306 0.224 0.055 k +*u +1053.333 263.333 m +1053.278 263.278 1053.222 262.222 1053.667 262.667 c +1053.722 262.722 1053.777 263.778 1053.333 263.333 c +f +*U +0.000 0.694 0.541 0.306 k +*u +1178.333 263.333 m +1178.278 263.278 1178.222 262.222 1178.667 262.667 c +1178.722 262.722 1178.777 263.778 1178.333 263.333 c +f +*U +0.000 0.494 0.341 0.000 k +*u +1192 264 m +1193 263 l +1192 264 l +f +*U +0.000 0.498 0.412 0.369 k +*u +1262 264 m +1262 260 l +1262.911 261.376 1263.404 262.440 1264 264 c +1262 264 l +f +*U +0.000 0.400 0.227 0.098 k +*u +1264 264 m +1265 263 l +1264 264 l +f +*U +0.000 0.451 0.412 0.549 k +*u +1318 264 m +1319 263 l +1318 264 l +f +*U +0.000 0.012 0.051 0.220 k +*u +1319 264 m +1320 263 l +1319 264 l +f +*U +0.000 0.196 0.129 0.094 k +*u +1326 264 m +1327 263 l +1326 264 l +f +*U +0.000 0.471 0.310 0.529 k +*u +1327.333 263.333 m +1327.278 263.278 1327.222 262.222 1327.667 262.667 c +1327.722 262.722 1327.777 263.778 1327.333 263.333 c +f +*U +0.000 0.125 0.078 0.176 k +*u +1395 264 m +1396 263 l +1395 264 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1522 264 m +1524.187 261.968 1526 260.906 1529 260 c +1526.826 262.295 1525 263.273 1522 264 c +f +*U +0.000 0.000 0.000 0.804 k +*u +1653 264 m +1654 263 l +1653 264 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1752 264 m +1753 263 l +1752 264 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1777 264 m +1778 263 l +1777 264 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1894 264 m +1895 263 l +1894 264 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1914.333 263.333 m +1914.278 263.278 1914.222 262.222 1914.667 262.667 c +1914.722 262.722 1914.777 263.778 1914.333 263.333 c +f +*U +0.000 0.000 0.000 0.102 k +*u +1990 264 m +1990.651 261.566 1991 260.717 1993 259 c +1992.251 261.254 1991.656 262.314 1990 264 c +f +*U +0.000 0.000 0.000 0.631 k +*u +262 263 m +263 262 l +262 263 l +f +*U +0.000 0.000 0.000 0.137 k +*u +611 263 m +612.402 260.726 613.515 260 616 259 c +614.394 260.914 613.217 261.837 611 263 c +f +*U +0.000 0.000 0.000 0.710 k +*u +612 263 m +613 262 l +612 263 l +f +*U +0.000 0.000 0.000 0.616 k +*u +703 263 m +704 262 l +703 263 l +f +*U +0.000 0.000 0.000 0.608 k +*u +826 263 m +827 262 l +826 263 l +f +*U +0.000 0.000 0.000 0.831 k +*u +907 263 m +908 262 l +907 263 l +f +*U +0.000 0.000 0.000 0.588 k +*u +928 263 m +929 262 l +928 263 l +f +*U +0.000 0.000 0.000 0.114 k +*u +929 263 m +929 261 l +930.635 261.545 930.455 261.365 931 263 c +929 263 l +f +*U +0.000 0.263 0.165 0.086 k +*u +1147 263 m +1148 262 l +1147 263 l +f +*U +0.000 0.424 0.325 0.463 k +*u +1179 263 m +1180.248 262.315 1180.548 262.251 1182 262 c +1180.752 262.685 1180.451 262.749 1179 263 c +f +*U +0.000 0.478 0.396 0.522 k +*u +1182.333 262.333 m +1182.278 262.278 1182.222 261.222 1182.667 261.667 c +1182.722 261.722 1182.777 262.778 1182.333 262.333 c +f +*U +0.000 0.463 0.329 0.271 k +*u +1192 263 m +1193 262 l +1192 263 l +f +*U +0.000 0.333 0.259 0.431 k +*u +1318 263 m +1319 262 l +1318 263 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1523 263 m +1524 262 l +1523 263 l +f +*U +0.000 0.000 0.000 0.529 k +*u +1541 263 m +1542 262 l +1541 263 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1753 263 m +1754 262 l +1753 263 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1893.333 262.333 m +1893.278 262.278 1893.222 261.222 1893.667 261.667 c +1893.722 261.722 1893.777 262.778 1893.333 262.333 c +f +*U +0.000 0.000 0.000 0.553 k +*u +1894 263 m +1895 262 l +1894 263 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1913 263 m +1914 262 l +1913 263 l +f +*U +0.000 0.000 0.000 0.224 k +*u +262 262 m +263 261 l +262 262 l +f +*U +0.000 0.000 0.000 0.800 k +*u +263 262 m +264 261 l +263 262 l +f +*U +0.000 0.000 0.000 0.671 k +*u +361 262 m +362 261 l +361 262 l +f +*U +0.000 0.000 0.000 0.216 k +*u +703 262 m +704 261 l +703 262 l +f +*U +0.000 0.000 0.000 0.604 k +*u +802 262 m +803 261 l +802 262 l +f +*U +0.000 0.000 0.000 0.204 k +*u +826 262 m +827 261 l +826 262 l +f +*U +0.000 0.000 0.000 0.125 k +*u +907 262 m +907.651 259.566 908 258.717 910 257 c +909.251 259.254 908.656 260.314 907 262 c +f +*U +0.000 0.157 0.106 0.173 k +*u +1136 262 m +1137 261 l +1136 262 l +f +*U +0.000 0.388 0.247 0.353 k +*u +1148 262 m +1149 261 l +1148 262 l +f +*U +0.000 0.310 0.196 0.000 k +*u +1191 262 m +1192 261 l +1191 262 l +f +*U +0.000 0.114 0.184 0.243 k +*u +1271 262 m +1272 261 l +1271 262 l +f +*U +0.000 0.573 0.408 0.392 k +*u +1303 262 m +1304.249 261.315 1304.548 261.251 1306 261 c +1304.751 261.685 1304.452 261.749 1303 262 c +f +*U +0.000 0.333 0.251 0.282 k +*u +1317 262 m +1318 261 l +1317 262 l +f +*U +0.000 0.318 0.204 0.361 k +*u +1327 262 m +1328 261 l +1327 262 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1496 262 m +1497 261 l +1496 262 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1753 262 m +1755.719 258.222 1758.644 255.688 1763 254 c +1760.264 257.575 1757 260 1753 262 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1892 262 m +1893 261 l +1892 262 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1913 262 m +1914 261 l +1913 262 l +f +*U +0.000 0.000 0.000 0.243 k +*u +263 261 m +264 260 l +263 261 l +f +*U +0.000 0.000 0.000 0.090 k +*u +825 261 m +822 255 l +824.640 256.536 825.818 257.939 825 261 c +f +*U +0.000 0.000 0.000 0.118 k +*u +930 261 m +931 258.515 931.726 257.402 934 256 c +932.906 258.357 932 259.599 930 261 c +f +*U +0.000 0.165 0.106 0.141 k +*u +1148 261 m +1149 260 l +1148 261 l +f +*U +0.000 0.545 0.416 0.357 k +*u +1182 261 m +1182.545 259.365 1182.365 259.545 1184 259 c +1184 261 l +1182 261 l +f +*U +0.000 0.125 0.110 0.204 k +*u +1190 261 m +1191 260 l +1190 261 l +f +*U +0.000 0.522 0.341 0.400 k +*u +1191 261 m +1189 260 l +1190.482 259.209 1191.796 259 1191 261 c +f +*U +0.000 0.118 0.184 0.141 k +*u +1263 261 m +1264 260 l +1263 261 l +f +*U +0.000 0.188 0.063 0.204 k +*u +1268 261 m +1269 260 l +1268 261 l +f +*U +0.000 0.549 0.325 0.451 k +*u +1269.667 260.667 m +1269.222 260.222 1270.278 260.278 1270.333 260.333 c +1270.778 260.778 1269.722 260.722 1269.667 260.667 c +f +*U +0.000 0.608 0.518 0.392 k +*u +1300 259 m +1301.580 259.683 1301.777 259.805 1303 261 c +1301.420 260.316 1301.223 260.195 1300 259 c +f +*U +0.000 0.220 0.161 0.133 k +*u +1303.667 260.667 m +1303.222 260.222 1304.278 260.278 1304.333 260.333 c +1304.778 260.778 1303.722 260.722 1303.667 260.667 c +f +*U +0.000 0.404 0.290 0.251 k +*u +1305 261 m +1306 260 l +1305 261 l +f +*U +0.000 0.639 0.451 0.275 k +*u +1313 261 m +1314.506 260.317 1315.315 260.174 1317 260 c +1315.494 260.683 1314.686 260.826 1313 261 c +f +*U +0.000 0.667 0.533 0.333 k +*u +1328 261 m +1329.450 259.392 1330 258.936 1332 258 c +1330.550 259.608 1329.948 260 1328 261 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1781 261 m +1782 260 l +1781 261 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1892 261 m +1893 260 l +1892 261 l +f +*U +0.000 0.000 0.000 0.733 k +*u +1893 261 m +1894 260 l +1893 261 l +f +*U +0.000 0.000 0.000 0.063 k +*u +1912 261 m +1911 257 l +1912.753 258.330 1913.670 259.247 1915 261 c +1912 261 l +f +*U +0.000 0.000 0.000 0.722 k +*u +2013 261 m +2014 260 l +2013 261 l +f +*U +0.000 0.000 0.000 0.098 k +*u +2014 261 m +2014.683 259.420 2014.805 259.222 2016 258 c +2015.316 259.580 2015.195 259.777 2014 261 c +f +*U +0.000 0.000 0.000 0.196 k +*u +264 260 m +265 259 l +264 260 l +f +*U +0.000 0.000 0.000 0.792 k +*u +265 260 m +266 259 l +265 260 l +f +*U +0.000 0.000 0.000 0.812 k +*u +359 260 m +360 259 l +359 260 l +f +*U +0.000 0.000 0.000 0.804 k +*u +616 260 m +617 259 l +616 260 l +f +*U +0.000 0.000 0.000 0.255 k +*u +705 260 m +706 259 l +705 260 l +f +*U +0.000 0.000 0.000 0.824 k +*u +706 260 m +707 259 l +706 260 l +f +800 260 m +801 259 l +800 260 l +f +*U +0.000 0.000 0.000 0.820 k +*u +805 260 m +806 259 l +805 260 l +f +*U +0.000 0.000 0.000 0.804 k +*u +824 260 m +825 259 l +824 260 l +f +*U +0.000 0.439 0.294 0.094 k +*u +1137 260 m +1138 259 l +1137 260 l +f +*U +0.000 0.161 0.153 0.275 k +*u +1149 260 m +1150 259 l +1149 260 l +f +*U +0.000 0.498 0.431 0.502 k +*u +1150 260 m +1151 259 l +1150 260 l +f +*U +0.000 0.494 0.329 0.094 k +*u +1184 260 m +1185 259 l +1184 260 l +f +*U +0.000 0.455 0.298 0.118 k +*u +1188 260 m +1189 259 l +1188 260 l +f +*U +0.000 0.718 0.580 0.282 k +*u +1262 260 m +1263.249 259.315 1263.548 259.251 1265 259 c +1263.752 259.685 1263.452 259.749 1262 260 c +f +*U +0.000 0.392 0.416 0.357 k +*u +1265.667 259.667 m +1265.222 259.222 1266.278 259.278 1266.333 259.333 c +1266.778 259.778 1265.722 259.722 1265.667 259.667 c +f +*U +0.000 0.729 0.671 0.271 k +*u +1266 258 m +1267.580 258.683 1267.777 258.805 1269 260 c +1267.420 259.316 1267.223 259.195 1266 258 c +f +*U +0.000 0.875 0.835 0.098 k +*u +1268 259 m +1269.809 258.426 1270 258.535 1272 259 c +1270.191 259.574 1269.931 259.465 1268 259 c +f +*U +0.000 0.455 0.314 0.196 k +*u +1307 260 m +1308 259 l +1307 260 l +f +*U +0.000 0.690 0.478 0.310 k +*u +1308 260 m +1309.249 259.315 1309.548 259.251 1311 259 c +1309.752 259.685 1309.452 259.749 1308 260 c +f +*U +0.000 0.447 0.325 0.553 k +*u +1311 260 m +1312.248 259.315 1312.548 259.251 1314 259 c +1312.752 259.685 1312.451 259.749 1311 260 c +f +*U +0.000 0.396 0.286 0.208 k +*u +1314 260 m +1315 259 l +1314 260 l +f +*U +0.000 0.329 0.239 0.055 k +*u +1315 260 m +1316 259 l +1315 260 l +f +*U +0.000 0.278 0.239 0.063 k +*u +1394.333 259.333 m +1394.278 259.278 1394.222 258.222 1394.667 258.667 c +1394.723 258.723 1394.777 259.777 1394.333 259.333 c +f +*U +0.000 0.000 0.000 0.106 k +*u +1497 260 m +1499.633 257.340 1502.414 256 1506 255 c +1503.356 257.717 1500.694 259 1497 260 c +f +*U +0.000 0.000 0.000 0.176 k +*u +1529.667 259.667 m +1529.222 259.222 1530.278 259.278 1530.333 259.333 c +1530.778 259.778 1529.722 259.722 1529.667 259.667 c +f +*U +0.000 0.000 0.000 0.310 k +*u +1891.667 259.667 m +1891.222 259.222 1892.278 259.278 1892.333 259.333 c +1892.778 259.778 1891.722 259.722 1891.667 259.667 c +f +*U +0.000 0.000 0.000 0.824 k +*u +1911 260 m +1912 259 l +1911 260 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1993 260 m +1994 259 l +1993 260 l +f +*U +0.000 0.000 0.000 0.263 k +*u +265 259 m +266 258 l +265 259 l +f +*U +0.000 0.000 0.000 0.639 k +*u +266 259 m +267 258 l +266 259 l +f +*U +0.000 0.000 0.000 0.106 k +*u +348 254 m +352.391 254.594 356 255.826 360 258 c +356.543 258.579 350.301 256.677 348 254 c +f +*U +0.000 0.000 0.000 0.110 k +*u +616 259 m +617.624 256.956 618.643 256 621 255 c +619.376 257 618.357 257.896 616 259 c +f +*U +0.000 0.000 0.000 0.094 k +*u +706 259 m +707.465 256.878 708.457 256.526 711 256 c +709.369 257.366 707.962 258 706 259 c +f +*U +0.000 0.000 0.000 0.651 k +*u +707 259 m +708 258 l +707 259 l +f +*U +0.000 0.000 0.000 0.153 k +*u +797 257 m +799.291 257.311 799.320 257.366 801 259 c +799.248 258.436 798.458 258 797 257 c +f +*U +0.000 0.310 0.224 0.247 k +*u +1054 259 m +1055 258 l +1054 259 l +f +*U +0.000 0.400 0.278 0.600 k +*u +1136.667 258.667 m +1136.222 258.222 1137.278 258.278 1137.333 258.333 c +1137.778 258.778 1136.722 258.722 1136.667 258.667 c +f +*U +0.000 0.196 0.125 0.141 k +*u +1138 259 m +1129.439 256.469 1118.901 258 1110 258 c +1055 258 l +1059.609 255.344 1068.602 257 1074 257 c +1119 257 l +1123.999 257 1129 256.941 1134 257 c +1135.998 257 1138.953 256.691 1138 259 c +f +*U +0.000 0.235 0.243 0.282 k +*u +1150 259 m +1151 258 l +1150 259 l +f +*U +0.000 0.714 0.506 0.286 k +*u +1151 259 m +1153.890 257.787 1156.874 258 1160 258 c +1157 259.213 1154 258.998 1151 259 c +f +*U +0.000 0.498 0.498 0.502 k +*u +1184 259 m +1185.506 258.317 1186.315 258.174 1188 258 c +1186.494 258.683 1185.685 258.826 1184 259 c +f +*U +0.000 0.706 0.753 0.196 k +*u +1188 259 m +1189.506 258.317 1190.315 258.174 1192 258 c +1190.494 258.683 1189.685 258.826 1188 259 c +f +*U +0.000 0.804 0.812 0.114 k +*u +1264.667 258.667 m +1264.222 258.222 1265.278 258.278 1265.333 258.333 c +1265.778 258.778 1264.722 258.722 1264.667 258.667 c +f +*U +0.000 0.667 0.451 0.333 k +*u +1296 259 m +1297.506 258.317 1298.315 258.174 1300 258 c +1298.494 258.683 1297.685 258.826 1296 259 c +f +*U +0.000 0.325 0.212 0.251 k +*u +1300 259 m +1301 258 l +1300 259 l +f +*U +0.000 0.271 0.176 0.153 k +*u +1308.667 258.667 m +1308.222 258.222 1309.278 258.278 1309.333 258.333 c +1309.778 258.778 1308.722 258.722 1308.667 258.667 c +f +*U +0.000 0.710 0.486 0.286 k +*u +1333 259 m +1334.249 258.315 1334.548 258.251 1336 258 c +1334.752 258.685 1334.451 258.749 1333 259 c +f +*U +0.000 0.808 0.627 0.192 k +*u +1384 259 m +1386.890 257.787 1389.874 258 1393 258 c +1390 259.213 1387 258.998 1384 259 c +f +*U +0.000 0.349 0.322 0.651 k +*u +1393 259 m +1394 258 l +1393 259 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1501 259 m +1502 258 l +1501 259 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1530 259 m +1531 258 l +1530 259 l +f +*U +0.000 0.000 0.000 0.169 k +*u +1531 259 m +1532.687 257.344 1533.746 256.749 1536 256 c +1534.314 257.656 1533.254 258.251 1531 259 c +f +*U +0.000 0.000 0.000 0.812 k +*u +1758 259 m +1759 258 l +1758 259 l +f +*U +0.000 0.000 0.000 0.090 k +*u +1787 259 m +1786.952 256.670 1786.796 256.994 1789 256 c +1788.308 257.389 1788 257.860 1787 259 c +f +*U +0.000 0.000 0.000 0.078 k +*u +1891 259 m +1892 258 l +1891 259 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1993 259 m +1993.684 257.420 1993.805 257.223 1995 256 c +1994.316 257.580 1994.195 257.777 1993 259 c +f +*U +0.000 0.000 0.000 0.212 k +*u +267 258 m +268 257 l +267 258 l +f +*U +0.000 0.000 0.000 0.608 k +*u +268 258 m +269 257 l +268 258 l +f +*U +0.000 0.000 0.000 0.639 k +*u +709 258 m +710 257 l +709 258 l +f +*U +0.000 0.000 0.000 0.635 k +*u +910 258 m +911 257 l +910 258 l +f +*U +0.000 0.000 0.000 0.824 k +*u +931 258 m +932 257 l +931 258 l +f +*U +0.000 0.196 0.125 0.141 k +*u +1151 258 m +1154.699 256.448 1159 257 1163 257 c +1183 257 l +1179.301 258.552 1174.983 258 1171 258 c +1151 258 l +f +*U +0.000 0.325 0.212 0.063 k +*u +1183 258 m +1185.890 256.787 1188.874 257 1192 257 c +1189 258.213 1186 257.998 1183 258 c +f +*U +0.000 0.196 0.125 0.141 k +*u +1192 258 m +1195.699 256.448 1200 257 1204 257 c +1225 257 l +1299 257 l +1295.301 258.552 1290.983 258 1287 258 c +1266 258 l +1192 258 l +f +1330 258 m +1335.707 255.605 1343.846 257 1350 257 c +1394 257 l +1388.293 259.395 1380 258 1374 258 c +1330 258 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1890.333 257.333 m +1890.278 257.278 1890.222 256.222 1890.667 256.667 c +1890.723 256.723 1890.777 257.777 1890.333 257.333 c +f +*U +0.000 0.000 0.000 0.553 k +*u +1891 258 m +1892 257 l +1891 258 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1910 258 m +1911 257 l +1910 258 l +f +*U +0.000 0.000 0.000 0.647 k +*u +2015 258 m +2016 257 l +2015 258 l +f +*U +0.000 0.000 0.000 0.055 k +*u +268 257 m +270.516 255 272.903 254.465 276 254 c +273.954 256.433 271 256.597 268 257 c +f +*U +0.000 0.000 0.000 0.678 k +*u +271 257 m +272 256 l +271 257 l +f +*U +0.000 0.000 0.000 0.671 k +*u +353 257 m +354 256 l +353 257 l +f +*U +0.000 0.000 0.000 0.639 k +*u +794 257 m +795 256 l +794 257 l +f +*U +0.000 0.000 0.000 0.082 k +*u +795 257 m +792.600 256.197 790.628 255.907 789 254 c +791 254.226 796 254.330 795 257 c +f +*U +0.000 0.000 0.000 0.251 k +*u +796 257 m +797 256 l +796 257 l +f +*U +0.000 0.000 0.000 0.161 k +*u +802 257 m +801 255.522 801 255.797 801 254 c +822 254 l +815.592 256.689 808.348 253.470 802 257 c +f +*U +0.000 0.000 0.000 0.663 k +*u +803 257 m +804 256 l +803 257 l +f +*U +0.000 0.000 0.000 0.078 k +*u +910 257 m +910.406 254.908 910.217 254.980 912 254 c +911.316 255.580 911.195 255.777 910 257 c +f +*U +0.000 0.000 0.000 0.757 k +*u +1646 257 m +1647 256 l +1646 257 l +f +*U +0.000 0.000 0.000 0.569 k +*u +1889 257 m +1890 256 l +1889 257 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1910 257 m +1909 255.521 1909 255.797 1909 254 c +1910.766 254.979 1910.956 255.222 1910 257 c +f +*U +0.000 0.000 0.000 0.565 k +*u +276 256 m +277 255 l +276 256 l +f +*U +0.000 0.000 0.000 0.827 k +*u +277 256 m +278.248 255.315 278.548 255.251 280 255 c +278.752 255.685 278.452 255.749 277 256 c +f +*U +0.000 0.000 0.000 0.847 k +*u +345 256 m +346.248 255.315 346.548 255.251 348 255 c +346.752 255.685 346.452 255.749 345 256 c +f +*U +0.000 0.000 0.000 0.157 k +*u +520 256 m +523.613 251.865 534.751 254 540 254 c +533.987 256.523 526.440 254.467 520 256 c +f +*U +0.000 0.000 0.000 0.659 k +*u +621 256 m +622 255 l +621 256 l +f +*U +0.000 0.000 0.000 0.169 k +*u +712 256 m +713.248 255.315 713.549 255.251 715 255 c +713.751 255.685 713.452 255.749 712 256 c +f +*U +0.000 0.000 0.000 0.553 k +*u +717 256 m +718 255 l +717 256 l +f +*U +0.000 0.000 0.000 0.839 k +*u +718.667 255.667 m +718.222 255.222 719.278 255.278 719.333 255.333 c +719.778 255.778 718.722 255.722 718.667 255.667 c +f +*U +0.000 0.000 0.000 0.890 k +*u +786.667 255.667 m +786.222 255.222 787.278 255.278 787.333 255.333 c +787.778 255.778 786.722 255.722 786.667 255.667 c +f +*U +0.000 0.000 0.000 0.639 k +*u +788 256 m +789 255 l +788 256 l +f +*U +0.000 0.000 0.000 0.345 k +*u +933 256 m +934 255 l +933 256 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1506 256 m +1507 255 l +1506 256 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1536.667 255.667 m +1536.222 255.222 1537.278 255.278 1537.333 255.333 c +1537.778 255.778 1536.722 255.722 1536.667 255.667 c +f +*U +0.000 0.000 0.000 0.776 k +*u +1551 256 m +1552 255 l +1551 256 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1643 256 m +1644 255 l +1643 256 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1788 256 m +1789 255 l +1788 256 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1789 256 m +1790 255 l +1789 256 l +f +1797.333 255.333 m +1797.278 255.278 1797.222 254.222 1797.667 254.667 c +1797.722 254.722 1797.778 255.778 1797.333 255.333 c +f +*U +0.000 0.000 0.000 0.208 k +*u +1889 256 m +1890 255 l +1889 256 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1995.333 255.333 m +1995.278 255.278 1995.222 254.222 1995.667 254.667 c +1995.722 254.722 1995.778 255.778 1995.333 255.333 c +f +*U +0.000 0.000 0.000 0.153 k +*u +2017 256 m +2011.881 252 2002.237 254 1996 254 c +2002.445 251.296 2012 253 2019 253 c +2018.309 254.388 2018 254.861 2017 256 c +f +*U +0.000 0.000 0.000 0.157 k +*u +276 255 m +282.436 252.299 292 254 299 254 c +348 254 l +341.564 256.701 331.951 255 325 255 c +276 255 l +f +621 255 m +624.959 253.339 629.737 254 634 254 c +630 255.661 625.263 255 621 255 c +f +717 255 m +723.436 252.299 733 254 740 254 c +789 254 l +782.564 256.701 772.951 255 766 255 c +717 255 l +f +*U +0.000 0.000 0.000 0.161 k +*u +912 255 m +918.202 252.397 927.298 254 934 254 c +927.798 256.603 918.702 255 912 255 c +f +938 255 m +945.879 251.694 958.466 254 967 254 c +1033 254 l +1025 257.306 1012.534 255 1004 255 c +938 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1506 255 m +1508.435 252.214 1512.484 253 1516 253 c +1540 253 l +1536.753 254.877 1532.729 254 1529 254 c +1521.304 253.988 1513.592 253.591 1506 255 c +f +*U +0.000 0.000 0.000 0.733 k +*u +1537 255 m +1538 254 l +1537 255 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1556 255 m +1557 254 l +1556 255 l +f +*U +0.000 0.000 0.000 0.855 k +*u +1557.667 254.667 m +1557.222 254.222 1558.278 254.278 1558.333 254.333 c +1558.778 254.778 1557.722 254.722 1557.667 254.667 c +f +*U +0.000 0.000 0.000 0.878 k +*u +1635 255 m +1636.248 254.315 1636.549 254.251 1638 254 c +1636.751 254.685 1636.452 254.749 1635 255 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1638 255 m +1639 254 l +1638 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1790 255 m +1781.715 252.551 1771.615 254 1763 254 c +1767.994 251 1778 253 1784 253 c +1786 253 1791 252.226 1790 255 c +f +*U +0.000 0.000 0.000 0.447 k +*u +1888.667 254.667 m +1888.222 254.222 1889.278 254.278 1889.333 254.333 c +1889.778 254.778 1888.722 254.722 1888.667 254.667 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1996 255 m +1997 254 l +1996 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1678 254 m +1683.715 251.602 1691.831 253 1698 253 c +1692.285 255.398 1684.169 254 1678 254 c +f +1798 254 m +1801.699 252.448 1806 253 1810 253 c +1832 253 l +1909 253 l +1905.301 254.552 1900.983 254 1897 254 c +1875 254 l +1798 254 l +f +*U +0.000 0.106 0.086 0.180 k +*u +1057 247 m +1058 246 l +1057 247 l +f +*U +0.000 0.341 0.341 0.659 k +*u +1058.333 246.333 m +1058.278 246.278 1058.222 245.222 1058.667 245.667 c +1058.722 245.722 1058.778 246.778 1058.333 246.333 c +f +*U +0.000 0.498 0.396 0.502 k +*u +1059 247 m +1061.613 245.902 1064 246 1067 246 c +1064.387 247 1061.836 246.993 1059 247 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1067 247 m +1073.678 244.198 1083.784 246 1091 246 c +1144 246 l +1137.322 248.802 1127.216 247 1120 247 c +1067 247 l +f +*U +0.000 0.498 0.380 0.502 k +*u +1144 247 m +1146 246 1147.747 246 1150 246 c +1147.948 246.874 1146.253 246.953 1144 247 c +f +*U +0.000 0.561 0.408 0.267 k +*u +1150.333 246.333 m +1150.278 246.278 1150.222 245.222 1150.667 245.667 c +1150.722 245.722 1150.778 246.778 1150.333 246.333 c +f +*U +0.000 0.263 0.184 0.424 k +*u +1161 247 m +1162 246 l +1161 247 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1162 247 m +1170 243.593 1183.203 246 1192 246 c +1258 246 l +1250 249.306 1237.534 247 1229 247 c +1162 247 l +f +*U +0.000 0.247 0.184 0.753 k +*u +1258.667 246.667 m +1258.222 246.222 1259.278 246.278 1259.333 246.333 c +1259.778 246.778 1258.722 246.722 1258.667 246.667 c +f +*U +0.000 0.035 0.024 0.267 k +*u +1260 247 m +1261 246 l +1260 247 l +f +*U +0.000 0.082 0.047 0.369 k +*u +1268 247 m +1269 246 l +1268 247 l +f +*U +0.000 0.494 0.357 0.506 k +*u +1269 247 m +1270 244 l +1274 246 l +1272.231 246.779 1270.964 246.912 1269 247 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1274 247 m +1277.958 245.339 1282.740 246 1287 246 c +1310 246 l +1306 247.661 1301.260 247 1297 247 c +1274 247 l +f +*U +0.000 0.424 0.322 0.196 k +*u +1310.333 246.333 m +1310.278 246.278 1310.222 245.222 1310.667 245.667 c +1310.722 245.722 1310.778 246.778 1310.333 246.333 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1324 247 m +1329.951 244.503 1338.580 246 1345 246 c +1391 246 l +1385 248.497 1376.420 247 1370 247 c +1324 247 l +f +*U +0.000 0.082 0.114 0.212 k +*u +1391 247 m +1392 246 l +1391 247 l +f +*U +0.000 0.882 0.639 0.118 k +*u +1059 246 m +1059.836 242.935 1060.738 237.971 1063.510 236 c +1066.366 234 1071.701 235 1075 235 c +1105 235 l +1106 240 l +1072 240 l +1079.434 242.197 1088.278 241 1096 241 c +1100.539 241 1105.529 241.903 1110 241.375 c +1116 240.662 1121.966 238.401 1128 238 c +1128 235 l +1152 235 l +1151.825 238.819 1150.848 242.292 1150 246 c +1059 246 l +f +*U +0.000 0.878 0.627 0.122 k +*u +1162 246 m +1164.772 242 1168.415 237.292 1173 235.588 c +1179.519 233.244 1189.201 235 1196 235 c +1252 235 l +1252 239 l +1250.804 238.402 1251 238.534 1250 237 c +1246.447 242 1236.560 240 1231 240 c +1176 240 l +1176 242 l +1248 242 l +1248 244 l +1168 244 l +1170.729 244.810 1173 244.979 1176 245 c +1171.783 246.769 1166.541 246 1162 246 c +f +*U +0.000 0.910 0.627 0.090 k +*u +1168 245 m +1173.951 242.503 1182.580 244 1189 244 c +1227 244 l +1234.810 244 1242.620 244.828 1250 242 c +1242.283 239.719 1233 241 1225 241 c +1176 241 l +1181.217 238.811 1188.381 240 1194 240 c +1230 240 l +1237.251 240 1244.709 241 1251 237 c +1253 243 l +1249 243 l +1249 245 l +1252.419 244.377 1254.691 243.810 1258 245 c +1250.600 248 1239 246 1231 246 c +1209.980 246 1188.944 245.173 1168 245 c +f +*U +0.000 0.525 0.388 0.475 k +*u +1258 246 m +1259 245 l +1258 246 l +f +*U +0.000 0.263 0.176 0.278 k +*u +1259 246 m +1260 245 l +1259 246 l +f +*U +0.000 0.314 0.196 0.322 k +*u +1269 246 m +1270 245 l +1269 246 l +f +*U +0.000 0.878 0.643 0.122 k +*u +1271 246 m +1272.314 241.402 1276.667 239.579 1278 235 c +1362 235 l +1370.177 235 1386.780 231.173 1388 242 c +1385.915 242 1386.276 241.862 1386 244 c +1385.317 242.494 1385.174 241.685 1385 240 c +1344 240 l +1338.621 240 1331.439 238.637 1327 242 c +1325 242 l +1323.777 240.805 1323.580 240.684 1322 240 c +1322 236 l +1318.590 238 1315.720 241 1311.985 242.441 c +1303.438 245.641 1294.926 244.796 1286 245 c +1280.970 245 1276 245.997 1271 246 c +f +*U +0.000 0.922 0.639 0.078 k +*u +1280 246 m +1285.860 243.541 1293.705 245.268 1300 244.960 c +1304.225 244.753 1307.973 243 1312 242 c +1309.645 246.492 1305.605 245.998 1301 246 c +1280 246 l +f +*U +0.000 0.275 0.200 0.027 k +*u +1323 246 m +1324 245 l +1323 246 l +f +*U +0.000 0.910 0.627 0.090 k +*u +1324 246 m +1326.236 238.589 1333.630 240 1340 240 c +1385 240 l +1385 244 l +1385.986 242.521 1386 242.797 1386 241 c +1388.179 242.539 1388.573 243.355 1389 246 c +1324 246 l +f +*U +0.000 0.710 0.510 0.290 k +*u +1389 246 m +1389 242 l +1389.911 243.377 1390.404 244.440 1391 246 c +1389 246 l +f +*U +0.000 0.569 0.396 0.431 k +*u +1058 245 m +1059 244 l +1058 245 l +f +*U +0.000 0.620 0.482 0.380 k +*u +1150 245 m +1151 240 l +1151.791 242.307 1151.475 243 1150 245 c +f +*U +0.000 0.325 0.275 0.078 k +*u +1151 245 m +1152 244 l +1151 245 l +f +*U +0.000 0.710 0.565 0.290 k +*u +1162 245 m +1164 241 l +1164.369 243.223 1163.859 243.735 1162 245 c +f +*U +0.000 0.808 0.596 0.184 k +*u +1249 245 m +1249 243 l +1251.873 242.656 1254.175 242.385 1257 243 c +1254.444 244.190 1251.805 244.702 1249 245 c +f +*U +0.000 0.541 0.416 0.459 k +*u +1257 245 m +1258 244 l +1257 245 l +f +*U +0.000 0.231 0.153 0.329 k +*u +1258 245 m +1259 244 l +1258 245 l +f +*U +0.000 0.592 0.435 0.345 k +*u +1310.667 244.667 m +1310.222 244.222 1311.278 244.278 1311.333 244.333 c +1311.778 244.778 1310.722 244.722 1310.667 244.667 c +f +*U +0.000 0.224 0.173 0.125 k +*u +1312 245 m +1313 244 l +1312 245 l +f +*U +0.000 0.310 0.310 0.690 k +*u +1322 245 m +1322.545 243.365 1322.365 243.545 1324 243 c +1324 245 l +1322 245 l +f +*U +0.000 0.318 0.231 0.333 k +*u +1390 245 m +1391 244 l +1390 245 l +f +*U +0.000 0.443 0.306 0.035 k +*u +1058 244 m +1059 243 l +1058 244 l +f +*U +0.000 0.733 0.541 0.267 k +*u +1059 244 m +1060 239 l +1060.651 241.234 1060.318 242 1059 244 c +f +*U +0.000 0.239 0.188 0.137 k +*u +1162 244 m +1163 243 l +1162 244 l +f +*U +0.000 0.361 0.239 0.318 k +*u +1270 244 m +1271 243 l +1270 244 l +f +*U +0.000 0.431 0.376 0.569 k +*u +1312 244 m +1313 243 l +1312 244 l +f +*U +0.000 0.329 0.263 0.216 k +*u +1313 244 m +1314 243 l +1313 244 l +f +*U +0.000 0.153 0.133 0.259 k +*u +1322 244 m +1323 243 l +1322 244 l +f +*U +0.000 0.878 0.675 0.114 k +*u +1326 244 m +1331.463 241.708 1339 243 1345 243 c +1384 243 l +1378.537 245.292 1370.887 244 1365 244 c +1326 244 l +f +*U +0.000 0.290 0.216 0.031 k +*u +1390 244 m +1391 243 l +1390 244 l +f +*U +0.000 0.251 0.176 0.733 k +*u +1271.333 242.333 m +1271.278 242.278 1271.222 241.222 1271.667 241.667 c +1271.722 241.722 1271.778 242.778 1271.333 242.333 c +f +*U +0.000 0.514 0.439 0.486 k +*u +1313 243 m +1314 242 l +1313 243 l +f +*U +0.000 0.322 0.251 0.180 k +*u +1314 243 m +1315 242 l +1314 243 l +f +*U +0.000 0.561 0.404 0.137 k +*u +1323 243 m +1324 242 l +1323 243 l +f +*U +0.000 0.780 0.541 0.220 k +*u +1324 243 m +1324 240 l +1325 241 1325.309 241.612 1326 243 c +1324 243 l +f +*U +0.000 0.541 0.514 0.459 k +*u +1107 242 m +1108.769 241.221 1110 241 1112 241 c +1110.231 241.779 1108.964 241.912 1107 242 c +f +*U +0.000 0.020 0.004 0.282 k +*u +1152.333 241.333 m +1152.278 241.278 1152.222 240.222 1152.667 240.667 c +1152.722 240.722 1152.778 241.778 1152.333 241.333 c +f +*U +0.000 0.827 0.627 0.157 k +*u +1176 242 m +1182.436 239.299 1192 241 1199 241 c +1250 241 l +1243.564 243.701 1233.951 242 1227 242 c +1176 242 l +f +*U +0.000 0.612 0.482 0.388 k +*u +1253 242 m +1252.278 239.582 1252 237.528 1252 235 c +1240 235 l +1243.958 233.339 1248.737 234 1253 234 c +1253.190 236.971 1253.834 239.260 1255 242 c +1253 242 l +f +*U +0.000 0.663 0.490 0.337 k +*u +1272.667 241.667 m +1272.222 241.222 1273.278 241.278 1273.333 241.333 c +1273.778 241.778 1272.722 241.722 1272.667 241.667 c +f +*U +0.000 0.482 0.459 0.518 k +*u +1314 242 m +1315 241 l +1314 242 l +f +*U +0.000 0.396 0.306 0.122 k +*u +1315 242 m +1316 241 l +1315 242 l +f +*U +0.000 0.612 0.459 0.388 k +*u +1323.333 241.333 m +1323.278 241.278 1323.223 240.222 1323.667 240.667 c +1323.722 240.722 1323.778 241.778 1323.333 241.333 c +f +*U +0.000 0.827 0.627 0.157 k +*u +1328 242 m +1333.216 239.811 1340.381 241 1346 241 c +1384 241 l +1378.783 243.189 1371.619 242 1366 242 c +1328 242 l +f +*U +0.000 0.580 0.451 0.349 k +*u +1388 242 m +1388 239 l +1388.696 240.554 1388.696 240.446 1388 242 c +f +*U +0.000 0.267 0.220 0.318 k +*u +1389 242 m +1390 241 l +1389 242 l +f +*U +0.000 0.251 0.188 0.298 k +*u +1059 241 m +1060 240 l +1059 241 l +f +*U +0.000 0.910 0.627 0.090 k +*u +1072 241 m +1075.959 239.339 1080.740 240 1085 240 c +1108 240 l +1104 241.661 1099.260 241 1095 241 c +1072 241 l +f +*U +0.000 0.310 0.169 0.075 k +*u +1108 241 m +1109 240 l +1108 241 l +f +*U +0.000 0.506 0.380 0.000 k +*u +1112 241 m +1113 240 l +1112 241 l +f +*U +0.000 0.255 0.188 0.149 k +*u +1164 241 m +1165 240 l +1164 241 l +f +*U +0.000 0.549 0.459 0.451 k +*u +1165 241 m +1166 240 l +1165 241 l +f +*U +0.000 0.427 0.322 0.122 k +*u +1273 241 m +1274 240 l +1273 241 l +f +*U +0.000 0.275 0.204 0.376 k +*u +1316 241 m +1317 240 l +1316 241 l +f +*U +0.000 0.153 0.145 0.118 k +*u +1389 241 m +1390 240 l +1389 241 l +f +*U +0.000 0.392 0.325 0.443 k +*u +1106.333 239.333 m +1106.278 239.278 1106.222 238.222 1106.667 238.667 c +1106.722 238.722 1106.778 239.778 1106.333 239.333 c +f +*U +0.000 0.290 0.247 0.102 k +*u +1107 240 m +1108 239 l +1107 240 l +f +*U +0.000 0.227 0.188 0.212 k +*u +1115 240 m +1116 239 l +1115 240 l +f +*U +0.000 0.686 0.486 0.310 k +*u +1116 240 m +1118.432 238.683 1120.248 238.723 1123 239 c +1120.668 239.985 1118.543 239.981 1116 240 c +f +*U +0.000 0.494 0.424 0.478 k +*u +1152 240 m +1152 234 l +1152.951 236.285 1152.951 237.715 1152 240 c +f +*U +0.000 0.180 0.118 0.420 k +*u +1166 240 m +1167 239 l +1166 240 l +f +*U +0.000 0.263 0.165 0.714 k +*u +1167 240 m +1168 239 l +1167 240 l +f +*U +0.000 0.231 0.137 0.035 k +*u +1253 240 m +1254 239 l +1253 240 l +f +*U +0.000 0.576 0.447 0.424 k +*u +1275.667 239.667 m +1275.222 239.222 1276.278 239.278 1276.333 239.333 c +1276.778 239.778 1275.722 239.722 1275.667 239.667 c +f +*U +0.000 0.722 0.553 0.278 k +*u +1317 240 m +1317.684 238.420 1317.804 238.223 1319 237 c +1318.316 238.580 1318.195 238.777 1317 240 c +f +*U +0.000 0.431 0.310 0.322 k +*u +1060 239 m +1061 238 l +1060 239 l +f +*U +0.000 0.561 0.478 0.439 k +*u +1061 239 m +1061 236 l +1061.696 237.554 1061.696 237.446 1061 239 c +f +*U +0.000 0.471 0.349 0.506 k +*u +1105 239 m +1105 234 l +1105.830 236 1105.830 236.970 1105 239 c +f +*U +0.000 0.329 0.282 0.165 k +*u +1118 239 m +1119 238 l +1118 239 l +f +*U +0.000 0.506 0.424 0.494 k +*u +1120 239 m +1121.248 238.315 1121.549 238.251 1123 238 c +1121.752 238.685 1121.452 238.749 1120 239 c +f +*U +0.000 0.216 0.141 0.059 k +*u +1167 239 m +1168 238 l +1167 239 l +f +*U +0.000 0.698 0.537 0.302 k +*u +1168.667 238.667 m +1168.222 238.222 1169.278 238.278 1169.333 238.333 c +1169.778 238.778 1168.722 238.722 1168.667 238.667 c +f +*U +0.000 0.369 0.267 0.212 k +*u +1276 239 m +1277 238 l +1276 239 l +f +*U +0.000 0.384 0.278 0.525 k +*u +1277.333 238.333 m +1277.278 238.278 1277.222 237.222 1277.667 237.667 c +1277.722 237.722 1277.778 238.778 1277.333 238.333 c +f +*U +0.000 0.286 0.192 0.133 k +*u +1321 239 m +1322 238 l +1321 239 l +f +*U +0.000 0.698 0.478 0.302 k +*u +1322 239 m +1321 237.521 1321 237.797 1321 236 c +1322.290 237.443 1322.401 237.234 1322 239 c +f +*U +0.000 0.271 0.204 0.059 k +*u +1388.333 238.333 m +1388.278 238.278 1388.222 237.222 1388.667 237.667 c +1388.722 237.722 1388.778 238.778 1388.333 238.333 c +f +*U +0.000 0.247 0.208 0.059 k +*u +1060 238 m +1061 237 l +1060 238 l +f +*U +0.000 0.200 0.188 0.122 k +*u +1106 238 m +1107 237 l +1106 238 l +f +*U +0.000 0.176 0.137 0.086 k +*u +1125 238 m +1126 237 l +1125 238 l +f +*U +0.000 0.635 0.471 0.365 k +*u +1126 238 m +1126.545 236.365 1126.365 236.545 1128 236 c +1128 238 l +1126 238 l +f +*U +0.000 0.325 0.271 0.318 k +*u +1169 238 m +1170 237 l +1169 238 l +f +*U +0.000 0.243 0.180 0.012 k +*u +1253 238 m +1254 237 l +1253 238 l +f +*U +0.000 0.498 0.388 0.000 k +*u +1319 238 m +1320 237 l +1319 238 l +f +*U +0.000 0.420 0.298 0.404 k +*u +1387.333 237.333 m +1387.278 237.278 1387.222 236.222 1387.667 236.667 c +1387.722 236.722 1387.778 237.778 1387.333 237.333 c +f +*U +0.000 0.373 0.282 0.012 k +*u +1126 237 m +1127 236 l +1126 237 l +f +*U +0.000 0.204 0.176 0.110 k +*u +1153 237 m +1153 234 l +1153.696 235.554 1153.696 235.446 1153 237 c +f +*U +0.000 0.318 0.286 0.227 k +*u +1170 237 m +1171 236 l +1170 237 l +f +*U +0.000 0.263 0.196 0.298 k +*u +1253 237 m +1253 234 l +1253.696 235.554 1253.696 235.446 1253 237 c +f +*U +0.000 0.482 0.478 0.518 k +*u +1277 237 m +1276 234 l +1277.766 234.979 1277.956 235.222 1277 237 c +f +*U +0.000 0.129 0.122 0.337 k +*u +1061.333 235.333 m +1061.278 235.278 1061.222 234.222 1061.667 234.667 c +1061.722 234.722 1061.778 235.778 1061.333 235.333 c +f +*U +0.000 0.420 0.325 0.580 k +*u +1062.333 235.333 m +1062.278 235.278 1062.222 234.222 1062.667 234.667 c +1062.722 234.722 1062.778 235.778 1062.333 235.333 c +f +*U +0.000 0.306 0.239 0.580 k +*u +1127.333 235.333 m +1127.278 235.278 1127.222 234.222 1127.667 234.667 c +1127.722 234.722 1127.778 235.778 1127.333 235.333 c +f +*U +0.000 0.365 0.318 0.102 k +*u +1171 236 m +1172 235 l +1171 236 l +f +*U +0.000 0.420 0.298 0.561 k +*u +1386.333 235.333 m +1386.278 235.278 1386.223 234.222 1386.667 234.667 c +1386.722 234.722 1386.778 235.778 1386.333 235.333 c +f +*U +0.000 0.227 0.173 0.227 k +*u +1387 236 m +1388 235 l +1387 236 l +f +*U +0.000 0.729 0.580 0.271 k +*u +1063 235 m +1067.215 233.231 1072.464 234 1077 234 c +1105 234 l +1100.785 235.769 1095.536 235 1091 235 c +1063 235 l +f +1128 235 m +1134.687 232.194 1144.767 234 1152 234 c +1145.313 236.806 1135.233 235 1128 235 c +f +*U +0.000 0.341 0.282 0.149 k +*u +1172 235 m +1173 234 l +1172 235 l +f +*U +0.000 0.471 0.447 0.529 k +*u +1173.667 234.667 m +1173.222 234.222 1174.278 234.278 1174.333 234.333 c +1174.778 234.778 1173.722 234.722 1173.667 234.667 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1175 235 m +1180.951 232.503 1189.580 234 1196 234 c +1240 234 l +1234 236.497 1225.420 235 1219 235 c +1175 235 l +f +*U +0.000 0.255 0.180 0.157 k +*u +1275 235 m +1276 234 l +1275 235 l +f +*U +0.000 0.729 0.580 0.271 k +*u +1278 235 m +1281.699 233.448 1286 234 1290 234 c +1311 234 l +1386 234 l +1382.301 235.552 1377.983 235 1374 235 c +1353 235 l +1278 235 l +f +*U +0.004 0.000 0.000 0.000 k +*u +1971 228 m +1969.647 227 1969.645 227.177 1968 227 c +1968 190 l +1432 190 l +1436.215 188.231 1441.464 189 1446 189 c +1473 189 l +1567 189 l +1840 189 l +1925 189 l +1939 189 1955.321 191.257 1969 188 c +1969 224 l +1969.810 221.271 1969.979 218.850 1970 216 c +1971.452 219.427 1972.263 224.480 1971 228 c +f +*U +0.000 0.204 0.137 0.133 k +*u +1973 228 m +1974 227 l +1973 228 l +f +*U +0.000 0.333 0.259 0.667 k +*u +1973 227 m +1974 226 l +1973 227 l +f +*U +0.000 0.694 0.478 0.282 k +*u +1974 227 m +1971.938 214.812 1974.578 201.484 1973 189 c +1975.477 192.270 1975.000 195.999 1975 200 c +1975 207.751 1973 218 1977 225 c +1975.814 226.186 1975.416 226.528 1974 227 c +f +*U +0.000 0.306 0.224 0.176 k +*u +1976 226 m +1977 225 l +1976 226 l +f +*U +0.000 0.318 0.227 0.337 k +*u +1977 225 m +1978 224 l +1977 225 l +f +*U +0.000 0.184 0.188 0.102 k +*u +1136 224 m +1137 223 l +1136 224 l +f +*U +0.031 0.000 0.039 0.169 k +*u +1176 224 m +1177 223 l +1176 224 l +f +*U +0.000 0.733 0.588 0.267 k +*u +1973 224 m +1973 192 l +1974.328 195 1974.000 198.581 1974 202 c +1974 208.686 1975.599 217.806 1973 224 c +f +*U +0.000 0.698 0.541 0.302 k +*u +1978.333 223.333 m +1978.278 223.278 1978.222 222.222 1978.667 222.667 c +1978.722 222.722 1978.778 223.778 1978.333 223.333 c +f +*U +0.000 0.373 0.298 0.208 k +*u +1979 224 m +1980 223 l +1979 224 l +f +*U +0.000 0.133 0.090 0.208 k +*u +1066 223 m +1067 222 l +1066 223 l +f +*U +0.000 0.329 0.298 0.671 k +*u +1067 223 m +1068 222 l +1067 223 l +f +*U +0.000 0.525 0.412 0.475 k +*u +1068 223 m +1072.969 220.915 1079.650 222 1085 222 c +1120 222 l +1115 224 1108.350 223 1103 223 c +1068 223 l +f +*U +0.000 0.141 0.078 0.224 k +*u +1120 223 m +1121 222 l +1120 223 l +f +*U +0.000 0.063 0.031 0.686 k +*u +1135 223 m +1136 222 l +1135 223 l +f +*U +0.000 0.588 0.588 0.412 k +*u +1136 223 m +1137.458 221.919 1138.248 221.564 1140 221 c +1138.457 222.267 1137.952 222.489 1136 223 c +f +*U +0.000 0.529 0.400 0.471 k +*u +1139 223 m +1143.724 221 1149.910 222 1155 222 c +1150.276 223.982 1144 223 1139 223 c +f +*U +0.000 0.224 0.192 0.337 k +*u +1155 223 m +1156 222 l +1155 223 l +f +*U +0.000 0.278 0.180 0.094 k +*u +1175.333 222.333 m +1175.278 222.278 1175.222 221.222 1175.667 221.667 c +1175.722 221.722 1175.778 222.778 1175.333 222.333 c +f +*U +0.000 0.525 0.412 0.475 k +*u +1176 223 m +1180.969 220.915 1187.650 222 1193 222 c +1207 222 1223.321 224.257 1237 221 c +1233.803 224.658 1225.577 223 1221 223 c +1176 223 l +f +*U +0.000 0.298 0.259 0.702 k +*u +1237.667 222.667 m +1237.222 222.222 1238.278 222.278 1238.333 222.333 c +1238.778 222.778 1237.722 222.722 1237.667 222.667 c +f +*U +0.000 0.118 0.122 0.196 k +*u +1239 223 m +1240 222 l +1239 223 l +f +*U +0.000 0.341 0.247 0.204 k +*u +1266 223 m +1266 220 l +1266.696 221.554 1266.696 221.446 1266 223 c +f +*U +0.000 0.525 0.412 0.475 k +*u +1267 220 m +1274.573 224.212 1286.527 222 1295 222 c +1355 222 l +1362.993 222 1373.844 223.980 1381 220 c +1382 223 l +1294 223 l +1274 223 l +1270.610 223 1267.797 223.720 1267 220 c +f +*U +0.000 0.239 0.180 0.176 k +*u +1382 223 m +1383 222 l +1382 223 l +f +*U +0.000 0.431 0.431 0.569 k +*u +1979 223 m +1980 222 l +1979 223 l +f +*U +0.000 0.416 0.325 0.329 k +*u +1980 223 m +1981 222 l +1980 223 l +f +*U +0.000 0.875 0.627 0.125 k +*u +1067 222 m +1069.303 218.837 1071.658 213.242 1075.329 211.603 c +1079.551 209.719 1086.451 211 1091 211 c +1126 211 l +1124.811 214.701 1122.757 218.979 1118.816 220.436 c +1114 222.214 1107 221 1102 221 c +1090.306 221 1078.604 220.533 1067 222 c +f +*U +0.000 0.941 0.659 0.059 k +*u +1070 222 m +1074.720 220 1080.920 221 1086 221 c +1120 221 l +1115.280 222.981 1109 222 1104 222 c +1070 222 l +f +*U +0.000 0.647 0.529 0.341 k +*u +1120.333 221.333 m +1120.278 221.278 1120.222 220.222 1120.667 220.667 c +1120.722 220.722 1120.778 221.778 1120.333 221.333 c +f +*U +0.000 0.478 0.365 0.173 k +*u +1136.667 221.667 m +1136.222 221.222 1137.278 221.278 1137.333 221.333 c +1137.778 221.778 1136.722 221.722 1136.667 221.667 c +f +*U +0.000 0.886 0.647 0.114 k +*u +1140 222 m +1141.657 220 1143.887 218.760 1145.326 216.742 c +1146.630 214.912 1146.943 212.610 1149.183 211.603 c +1152.475 210 1157.459 211 1161 211 c +1159.231 211.779 1157.964 211.912 1156 212 c +1161.382 223 1146.695 222 1140 222 c +f +*U +0.000 0.643 0.522 0.357 k +*u +1155.333 221.333 m +1155.278 221.278 1155.222 220.222 1155.667 220.667 c +1155.722 220.722 1155.778 221.778 1155.333 221.333 c +f +*U +0.000 0.875 0.627 0.125 k +*u +1176 222 m +1176 218.577 1176 214.938 1178.920 212.514 c +1181 210.636 1184.292 211 1187 211 c +1193.292 210.987 1199.722 210.628 1206 211 c +1209.773 211.310 1212.695 213.205 1216 211 c +1218.709 211.648 1221.215 211.942 1224 212 c +1224.272 220.344 1229.279 219.399 1236 221 c +1230 223.464 1223 221 1217 221 c +1203.284 220.841 1189.644 221.962 1176 222 c +f +*U +0.000 0.941 0.659 0.059 k +*u +1184 222 m +1188.215 220.231 1193.464 221 1198 221 c +1224 221 l +1219.785 222.769 1214.536 222 1210 222 c +1184 222 l +f +*U +0.000 0.416 0.298 0.361 k +*u +1237 222 m +1238 221 l +1237 222 l +f +*U +0.000 0.941 0.659 0.059 k +*u +1268 222 m +1271 218 l +1276.837 223.572 1289.407 221 1297 221 c +1368 221 l +1359.642 224.507 1346 222 1337 222 c +1268 222 l +f +*U +0.000 0.875 0.620 0.125 k +*u +1272 218 m +1271 220 l +1269.787 217 1270 214 1270 211 c +1288.808 211 1308.257 209.555 1327 211 c +1331.214 211.396 1334.743 213.694 1339 214 c +1339 211 l +1363 211 l +1366.417 211 1370.579 210.351 1373.917 211 c +1376.340 211.663 1381.961 219 1379.472 221.278 c +1378.196 222.430 1375.553 222 1374 222 c +1369.277 222 1364.736 221 1360 221 c +1301 221 l +1280 221 l +1276.470 221 1272.855 221.992 1272 218 c +f +*U +0.000 0.345 0.235 0.325 k +*u +1381 222 m +1382 221 l +1381 222 l +f +*U +0.000 0.388 0.302 0.141 k +*u +1982 222 m +1983 221 l +1982 222 l +f +*U +0.000 0.255 0.180 0.039 k +*u +1067 221 m +1068 220 l +1067 221 l +f +*U +0.000 0.482 0.329 0.416 k +*u +1068.333 220.333 m +1068.278 220.278 1068.222 219.222 1068.667 219.667 c +1068.722 219.722 1068.778 220.778 1068.333 220.333 c +f +*U +0.000 0.282 0.259 0.216 k +*u +1121 221 m +1122 220 l +1121 221 l +f +*U +0.000 0.235 0.208 0.239 k +*u +1139 221 m +1140 220 l +1139 221 l +f +*U +0.000 0.647 0.431 0.353 k +*u +1140.667 220.667 m +1140.222 220.222 1141.278 220.278 1141.333 220.333 c +1141.778 220.778 1140.722 220.722 1140.667 220.667 c +f +*U +0.000 0.365 0.298 0.153 k +*u +1156 221 m +1157 220 l +1156 221 l +f +*U +0.000 0.427 0.282 0.188 k +*u +1175 221 m +1176 220 l +1175 221 l +f +*U +0.000 0.506 0.388 0.494 k +*u +1234.667 220.667 m +1234.222 220.222 1235.278 220.278 1235.333 220.333 c +1235.778 220.778 1234.722 220.722 1234.667 220.667 c +f +*U +0.000 0.298 0.220 0.212 k +*u +1236 221 m +1237 220 l +1236 221 l +f +*U +0.000 0.259 0.180 0.067 k +*u +1381 221 m +1382 220 l +1381 221 l +f +*U +0.000 0.529 0.443 0.471 k +*u +1982.667 220.667 m +1982.222 220.222 1983.278 220.278 1983.333 220.333 c +1983.778 220.778 1982.722 220.722 1982.667 220.667 c +f +*U +0.000 0.584 0.525 0.416 k +*u +1121.333 219.333 m +1121.278 219.278 1121.222 218.222 1121.667 218.667 c +1121.722 218.722 1121.778 219.778 1121.333 219.333 c +f +*U +0.000 0.463 0.353 0.255 k +*u +1141 220 m +1142 219 l +1141 220 l +f +*U +0.000 0.678 0.635 0.267 k +*u +1156 220 m +1156.684 218.420 1156.805 218.223 1158 217 c +1157.316 218.580 1157.195 218.777 1156 220 c +f +*U +0.000 0.184 0.118 0.180 k +*u +1157 220 m +1158 219 l +1157 220 l +f +*U +0.000 0.573 0.388 0.427 k +*u +1175 220 m +1175 216 l +1175.710 217.760 1175.710 218.240 1175 220 c +f +*U +0.000 0.624 0.443 0.376 k +*u +1224 217 m +1227.412 218.446 1230.304 218.959 1234 219 c +1230.302 220.551 1226.279 220.515 1224 217 c +f +*U +0.000 0.216 0.165 0.133 k +*u +1234 220 m +1235 219 l +1234 220 l +f +*U +0.000 0.741 0.537 0.259 k +*u +1267 220 m +1269 216 l +1269.558 218.308 1268.996 218.756 1267 220 c +f +*U +0.000 0.349 0.282 0.278 k +*u +1985 220 m +1986 219 l +1985 220 l +f +*U +0.000 0.306 0.216 0.008 k +*u +1068 219 m +1069 218 l +1068 219 l +f +*U +0.000 0.431 0.302 0.443 k +*u +1069.333 218.333 m +1069.278 218.278 1069.222 217.222 1069.667 217.667 c +1069.722 217.722 1069.778 218.778 1069.333 218.333 c +f +*U +0.000 0.345 0.282 0.145 k +*u +1122 219 m +1123 218 l +1122 219 l +f +*U +0.000 0.333 0.176 0.090 k +*u +1142 219 m +1143 218 l +1142 219 l +f +*U +0.000 0.631 0.482 0.369 k +*u +1143 219 m +1146 214 l +1146.611 216.816 1145.444 217.675 1143 219 c +f +*U +0.000 0.271 0.200 0.071 k +*u +1226 219 m +1227.506 218.317 1228.314 218.174 1230 218 c +1228.494 218.683 1227.685 218.826 1226 219 c +f +*U +0.000 0.337 0.243 0.086 k +*u +1267 219 m +1268 218 l +1267 219 l +f +*U +0.000 0.722 0.592 0.278 k +*u +1986 219 m +1987.229 217 1987.868 216.777 1990 216 c +1988.607 217.434 1987.767 218 1986 219 c +f +*U +0.000 0.341 0.239 0.000 k +*u +1987 219 m +1988 218 l +1987 219 l +f +*U +0.000 0.718 0.514 0.282 k +*u +1070.333 217.333 m +1070.278 217.278 1070.222 216.222 1070.667 216.667 c +1070.722 216.722 1070.778 217.778 1070.333 217.333 c +f +*U +0.000 0.290 0.271 0.106 k +*u +1158 218 m +1159 217 l +1158 218 l +f +*U +0.000 0.239 0.216 0.141 k +*u +1225.333 217.333 m +1225.278 217.278 1225.222 216.222 1225.667 216.667 c +1225.722 216.722 1225.778 217.778 1225.333 217.333 c +f +*U +0.000 0.404 0.286 0.369 k +*u +1268 218 m +1269 217 l +1268 218 l +f +*U +0.000 0.357 0.282 0.384 k +*u +1379 218 m +1380 217 l +1379 218 l +f +*U +0.000 0.357 0.255 0.027 k +*u +1069 217 m +1070 216 l +1069 217 l +f +*U +0.000 0.118 0.165 0.325 k +*u +1123 217 m +1124 216 l +1123 217 l +f +*U +0.000 0.714 0.514 0.243 k +*u +1158 217 m +1156 212 l +1161 212 l +1160 213.962 1159.366 215.369 1158 217 c +f +*U +0.000 0.459 0.333 0.541 k +*u +1224 217 m +1224 214 l +1224.696 215.554 1224.696 215.446 1224 217 c +f +*U +0.000 0.204 0.153 0.161 k +*u +1268 217 m +1269 216 l +1268 217 l +f +*U +0.000 0.251 0.188 0.153 k +*u +1990 217 m +1991 216 l +1990 217 l +f +*U +0.000 0.616 0.475 0.384 k +*u +27 216 m +27 206 l +28.346 209.207 28.346 212.793 27 216 c +f +*U +0.000 0.271 0.176 0.612 k +*u +1070 216 m +1071 215 l +1070 216 l +f +*U +0.000 0.761 0.553 0.239 k +*u +1071 216 m +1071.526 213.457 1071.878 212.465 1074 211 c +1073.199 213 1072.503 214.337 1071 216 c +f +*U +0.000 0.227 0.145 0.133 k +*u +1124 216 m +1125 215 l +1124 216 l +f +*U +0.000 0.373 0.271 0.227 k +*u +1145 216 m +1146 215 l +1145 216 l +f +*U +0.000 0.063 0.035 0.706 k +*u +1175 216 m +1176 215 l +1175 216 l +f +*U +0.000 0.616 0.455 0.384 k +*u +1269 216 m +1269 211 l +1269.830 213 1269.830 213.970 1269 216 c +f +*U +0.000 0.494 0.369 0.506 k +*u +1377.333 215.333 m +1377.278 215.278 1377.222 214.222 1377.667 214.667 c +1377.722 214.722 1377.778 215.778 1377.333 215.333 c +f +*U +0.000 0.208 0.137 0.475 k +*u +1378 216 m +1379 215 l +1378 216 l +f +*U +0.000 0.745 0.545 0.247 k +*u +1990 216 m +1990 214 l +1992 214 l +1992 216 l +1990 216 l +f +*U +0.000 0.263 0.176 0.141 k +*u +1070 215 m +1071 214 l +1070 215 l +f +*U +0.000 0.855 0.541 0.145 k +*u +1080 215 m +1084.215 213.231 1089.465 214 1094 214 c +1120 214 l +1115.785 215.769 1110.536 215 1106 215 c +1080 215 l +f +*U +0.000 0.067 0.047 0.267 k +*u +1175 215 m +1176 214 l +1175 215 l +f +*U +0.000 0.678 0.510 0.322 k +*u +1176.667 214.667 m +1176.222 214.222 1177.278 214.278 1177.333 214.333 c +1177.778 214.778 1176.722 214.722 1176.667 214.667 c +f +*U +0.000 0.855 0.541 0.145 k +*u +1184 215 m +1190.687 212.194 1200.767 214 1208 214 c +1201.313 216.806 1191.233 215 1184 215 c +f +1272 215 m +1276.720 213 1282.920 214 1288 214 c +1320 214 l +1315.280 215.980 1309 215 1304 215 c +1272 215 l +f +*U +0.000 0.388 0.302 0.612 k +*u +1992 215 m +1993 214 l +1992 215 l +f +*U +0.000 0.333 0.263 0.149 k +*u +1993 215 m +1994 214 l +1993 215 l +f +*U +0.000 0.918 0.694 0.082 k +*u +1080 214 m +1084.215 212.231 1089.465 213 1094 213 c +1121 213 l +1116.785 214.769 1111.535 214 1107 214 c +1080 214 l +f +*U +0.000 0.400 0.275 0.231 k +*u +1125 214 m +1126 213 l +1125 214 l +f +*U +0.000 0.263 0.188 0.149 k +*u +1160 214 m +1161 213 l +1160 214 l +f +*U +0.000 0.392 0.294 0.298 k +*u +1177 214 m +1178 213 l +1177 214 l +f +*U +0.000 0.271 0.169 0.282 k +*u +1224.333 213.333 m +1224.278 213.278 1224.222 212.222 1224.667 212.667 c +1224.722 212.722 1224.778 213.778 1224.333 213.333 c +f +*U +0.000 0.678 0.510 0.322 k +*u +1333 214 m +1335 213 1336.747 213 1339 213 c +1336.948 213.874 1335.253 213.953 1333 214 c +f +*U +0.000 0.369 0.247 0.353 k +*u +1377 214 m +1378 213 l +1377 214 l +f +*U +0.000 0.459 0.333 0.384 k +*u +1993.667 213.667 m +1993.222 213.223 1994.277 213.277 1994.333 213.333 c +1994.778 213.778 1993.722 213.722 1993.667 213.667 c +f +*U +0.000 0.275 0.176 0.180 k +*u +1071 213 m +1072 212 l +1071 213 l +f +*U +0.000 0.302 0.220 0.357 k +*u +1126 213 m +1127 212 l +1126 213 l +f +*U +0.000 0.361 0.263 0.000 k +*u +1146 213 m +1147 212 l +1146 213 l +f +*U +0.000 0.306 0.224 0.396 k +*u +1161 213 m +1162 212 l +1161 213 l +f +*U +0.000 0.518 0.388 0.408 k +*u +1178.333 212.333 m +1178.278 212.278 1178.222 211.222 1178.667 211.667 c +1178.722 211.722 1178.778 212.778 1178.333 212.333 c +f +*U +0.000 0.525 0.329 0.380 k +*u +1210 211 m +1211.580 211.684 1211.777 211.805 1213 213 c +1211.420 212.316 1211.223 212.195 1210 211 c +f +*U +0.000 0.545 0.435 0.455 k +*u +1213 213 m +1214.248 212.315 1214.548 212.251 1216 212 c +1214.751 212.685 1214.452 212.749 1213 213 c +f +*U +0.000 0.502 0.357 0.345 k +*u +1332 210 m +1333 211 1333.309 211.612 1334 213 c +1331.797 212 1331.952 212.330 1332 210 c +f +*U +0.000 0.165 0.141 0.129 k +*u +1334 213 m +1335 212 l +1334 213 l +f +*U +0.000 0.439 0.310 0.165 k +*u +1338 213 m +1338 210 l +1338.696 211.554 1338.696 211.446 1338 213 c +f +*U +0.000 0.506 0.337 0.494 k +*u +1376 213 m +1377 212 l +1376 213 l +f +*U +0.000 0.380 0.275 0.306 k +*u +1996 213 m +1997 212 l +1996 213 l +f +*U +0.000 0.592 0.427 0.408 k +*u +1124 211 m +1126 210.249 1126.596 210.344 1128 212 c +1124 211 l +f +*U +0.000 0.349 0.239 0.329 k +*u +1147 212 m +1148 211 l +1147 212 l +f +*U +0.000 0.588 0.467 0.412 k +*u +1159 211 m +1161 210.249 1161.596 210.344 1163 212 c +1159 211 l +f +*U +0.000 0.416 0.298 0.294 k +*u +1163 212 m +1164 211 l +1163 212 l +f +*U +0.000 0.325 0.192 0.098 k +*u +1212 212 m +1213 211 l +1212 212 l +f +*U +0.106 0.000 0.110 0.184 k +*u +1215 212 m +1216 211 l +1215 212 l +f +*U +0.000 0.416 0.341 0.584 k +*u +1217.667 211.667 m +1217.222 211.222 1218.278 211.278 1218.333 211.333 c +1218.778 211.778 1217.722 211.722 1217.667 211.667 c +f +*U +0.000 0.659 0.443 0.341 k +*u +1219 212 m +1220.769 211.221 1222 211 1224 211 c +1222.231 211.779 1220.964 211.912 1219 212 c +f +*U +0.000 0.173 0.106 0.137 k +*u +1224 212 m +1225 211 l +1224 212 l +f +*U +0.000 0.322 0.208 0.341 k +*u +1376 212 m +1377 211 l +1376 212 l +f +*U +0.000 0.706 0.490 0.259 k +*u +1996 212 m +1997.222 210.267 1998 209.849 2000 209 c +1998.771 210.870 1998 211.224 1996 212 c +f +*U +0.000 0.251 0.188 0.153 k +*u +1998 212 m +1999 211 l +1998 212 l +f +*U +0.000 0.459 0.376 0.090 k +*u +1072 211 m +1073 210 l +1072 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1073 211 m +1077.969 208.915 1084.650 210 1090 210 c +1124 210 l +1119 212 1112.350 211 1107 211 c +1073 211 l +f +*U +0.020 0.000 0.008 0.898 k +*u +1128 211 m +1129 210 l +1128 211 l +f +*U +0.000 0.027 0.020 0.627 k +*u +1129 211 m +1130 210 l +1129 211 l +f +*U +0.000 0.020 0.016 0.255 k +*u +1130 211 m +1131 210 l +1130 211 l +f +*U +0.000 0.259 0.180 0.443 k +*u +1148 211 m +1149 210 l +1148 211 l +f +*U +0.000 0.576 0.388 0.416 k +*u +1149 211 m +1150.248 210.315 1150.548 210.251 1152 210 c +1150.752 210.685 1150.452 210.749 1149 211 c +f +*U +0.000 0.345 0.345 0.655 k +*u +1152 211 m +1154.332 210 1156.457 210 1159 210 c +1156.668 210.984 1154.543 210.981 1152 211 c +f +*U +0.000 0.161 0.153 0.839 k +*u +1163.667 210.667 m +1163.222 210.222 1164.278 210.278 1164.333 210.333 c +1164.778 210.778 1163.722 210.722 1163.667 210.667 c +f +*U +0.000 0.047 0.047 0.631 k +*u +1165 211 m +1166 210 l +1165 211 l +f +*U +0.000 0.243 0.184 0.165 k +*u +1178 211 m +1179 210 l +1178 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1179 211 m +1187.367 207.489 1200.924 210 1210 210 c +1201.633 213.511 1188 211 1179 211 c +f +*U +0.000 0.329 0.227 0.275 k +*u +1210 211 m +1211 210 l +1210 211 l +f +*U +0.000 0.145 0.129 0.267 k +*u +1221 211 m +1222.248 210.315 1222.549 210.251 1224 210 c +1222.752 210.685 1222.451 210.749 1221 211 c +f +*U +0.000 0.333 0.243 0.361 k +*u +1269 211 m +1270 210 l +1269 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1270 211 m +1275.707 208.605 1283.846 210 1290 210 c +1332 210 l +1326.293 212.395 1318 211 1312 211 c +1270 211 l +f +*U +0.000 0.533 0.435 0.467 k +*u +1339 211 m +1340.506 210.317 1341.315 210.174 1343 210 c +1341.494 210.683 1340.686 210.826 1339 211 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1343 211 m +1346.699 209.448 1351 210 1355 210 c +1376 210 l +1372.301 211.552 1367.983 211 1364 211 c +1343 211 l +f +*U +0.000 0.431 0.282 0.545 k +*u +2000 210 m +2001 209 l +2000 210 l +f +*U +0.000 0.361 0.239 0.027 k +*u +2001 210 m +2002 209 l +2001 210 l +f +*U +0.000 0.416 0.267 0.310 k +*u +2002 209 m +2003 208 l +2002 209 l +f +*U +0.000 0.455 0.333 0.349 k +*u +0.333 207.333 m +0.278 207.278 0.222 206.222 0.667 206.667 c +0.722 206.722 0.778 207.778 0.333 207.333 c +f +*U +0.000 0.651 0.482 0.349 k +*u +1 208 m +1 200 l +2 202.770 2 205.230 1 208 c +f +*U +0.000 0.537 0.498 0.388 k +*u +2002.667 207.667 m +2002.222 207.223 2003.277 207.277 2003.333 207.333 c +2003.778 207.778 2002.722 207.722 2002.667 207.667 c +f +*U +0.000 0.310 0.345 0.047 k +*u +2004 208 m +2005 207 l +2004 208 l +f +*U +0.000 0.184 0.137 0.047 k +*u +28 207 m +29 206 l +28 207 l +f +*U +0.000 0.357 0.322 0.310 k +*u +2005 207 m +2006 206 l +2005 207 l +f +*U +0.000 0.286 0.220 0.165 k +*u +0.333 205.333 m +0.278 205.278 0.222 204.222 0.667 204.667 c +0.722 204.722 0.778 205.778 0.333 205.333 c +f +*U +0.000 0.271 0.200 0.212 k +*u +28 206 m +29 205 l +28 206 l +f +*U +0.000 0.553 0.420 0.357 k +*u +2005.667 205.667 m +2005.222 205.223 2006.277 205.277 2006.333 205.333 c +2006.778 205.778 2005.722 205.722 2005.667 205.667 c +f +*U +0.000 0.510 0.396 0.180 k +*u +2007 206 m +2008 205 l +2007 206 l +f +*U +0.000 0.192 0.161 0.055 k +*u +0 204 m +1 203 l +0 204 l +f +*U +0.000 0.604 0.471 0.396 k +*u +28.333 203.333 m +28.278 203.278 28.222 202.222 28.667 202.667 c +28.722 202.722 28.778 203.778 28.333 203.333 c +f +*U +0.000 0.325 0.239 0.231 k +*u +2010 204 m +2011 203 l +2010 204 l +f +*U +0.000 0.282 0.196 0.024 k +*u +29 203 m +30 202 l +29 203 l +f +*U +0.000 0.443 0.373 0.557 k +*u +2011 203 m +2012 202 l +2011 203 l +f +*U +0.000 0.400 0.275 0.255 k +*u +29 202 m +30 201 l +29 202 l +f +*U +0.000 0.337 0.239 0.310 k +*u +2013 202 m +2014 201 l +2013 202 l +f +*U +0.000 0.435 0.290 0.439 k +*u +29 201 m +30 200 l +29 201 l +f +*U +0.000 0.376 0.267 0.482 k +*u +2014 201 m +2015 200 l +2014 201 l +f +*U +0.000 0.106 0.086 0.224 k +*u +2015 201 m +2016 200 l +2015 201 l +f +*U +0.000 0.349 0.235 0.165 k +*u +1 200 m +2 199 l +1 200 l +f +*U +0.000 0.408 0.337 0.094 k +*u +30 200 m +31 199 l +30 200 l +f +*U +0.000 0.220 0.125 0.122 k +*u +1080 200 m +1081.506 199.317 1082.315 199.174 1084 199 c +1082.494 199.683 1081.685 199.826 1080 200 c +f +*U +0.000 0.063 0.051 0.216 k +*u +1086 200 m +1087 199 l +1086 200 l +f +*U +0.000 0.208 0.078 0.118 k +*u +1088 200 m +1089.248 199.315 1089.549 199.251 1091 199 c +1089.751 199.685 1089.452 199.749 1088 200 c +f +*U +0.000 0.286 0.169 0.071 k +*u +1095 200 m +1098.699 198.448 1103 199 1107 199 c +1127 199 l +1123.301 200.552 1118.983 200 1115 200 c +1095 200 l +f +*U +0.016 0.000 0.024 0.204 k +*u +1163 200 m +1163 198 l +1164.635 198.545 1164.455 198.365 1165 200 c +1163 200 l +f +*U +0.000 0.286 0.169 0.071 k +*u +1175 200 m +1181.687 197.194 1191.767 199 1199 199 c +1192.313 201.806 1182.233 200 1175 200 c +f +*U +0.000 0.165 0.165 0.204 k +*u +1204 200 m +1205.248 199.315 1205.548 199.251 1207 199 c +1205.751 199.685 1205.452 199.749 1204 200 c +f +*U +0.004 0.000 0.024 0.212 k +*u +1266 200 m +1267 199 l +1266 200 l +f +*U +0.000 0.106 0.314 0.196 k +*u +1267 200 m +1268 199 l +1267 200 l +f +*U +0.000 0.094 0.082 0.153 k +*u +1274 200 m +1275 199 l +1274 200 l +f +*U +0.000 0.306 0.275 0.110 k +*u +1279.667 199.667 m +1279.222 199.222 1280.278 199.278 1280.333 199.333 c +1280.778 199.778 1279.722 199.722 1279.667 199.667 c +f +*U +0.000 0.063 0.016 0.200 k +*u +1298 200 m +1299.248 199.315 1299.549 199.251 1301 199 c +1299.751 199.685 1299.452 199.749 1298 200 c +f +*U +0.000 0.286 0.169 0.071 k +*u +1315 200 m +1319.724 198 1325.910 199 1331 199 c +1326.276 200.982 1320 200 1315 200 c +f +*U +0.000 0.039 0.035 0.169 k +*u +1333 200 m +1334 199 l +1333 200 l +f +*U +0.000 0.286 0.169 0.071 k +*u +1346 200 m +1350.217 198.231 1355.459 199 1360 199 c +1355.783 200.769 1350.541 200 1346 200 c +f +*U +0.000 0.125 0.122 0.157 k +*u +1365 200 m +1366.506 199.317 1367.315 199.174 1369 199 c +1367.494 199.683 1366.685 199.826 1365 200 c +f +*U +0.000 0.333 0.239 0.271 k +*u +2016 200 m +2017 199 l +2016 200 l +f +*U +0.000 0.271 0.188 0.000 k +*u +1 199 m +2 198 l +1 199 l +f +*U +0.000 0.533 0.435 0.467 k +*u +2 199 m +2 196 l +2.696 197.554 2.696 197.446 2 199 c +f +*U +0.000 0.569 0.435 0.412 k +*u +30 199 m +31 195 l +31.393 196.924 31 197.360 30 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1080 199 m +1084.188 196.579 1091 198 1096 198 c +1108.785 198 1122.402 199.339 1135 197 c +1131.914 200.531 1124.411 199 1120 199 c +1080 199 l +f +*U +0.000 0.318 0.255 0.682 k +*u +1164 199 m +1165 198 l +1164 199 l +f +*U +0.000 0.769 0.616 0.212 k +*u +1165 199 m +1166 195 l +1169 197 1171.302 197.882 1175 198 c +1171.837 199.327 1168.415 199.000 1165 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1175 199 m +1184.696 194.931 1197.633 199.468 1208 197 c +1205.565 199.786 1201.516 199.000 1198 199 c +1175 199 l +f +*U +0.000 0.310 0.263 0.180 k +*u +1266 199 m +1266 196 l +1266.696 197.554 1266.696 197.446 1266 199 c +f +*U +0.000 0.639 0.725 0.275 k +*u +1267 199 m +1267 192 l +1268 194.534 1268 196.466 1267 199 c +f +*U +0.000 0.682 0.553 0.318 k +*u +1268 199 m +1271.697 197.449 1276 198 1280 198 c +1276.303 199.551 1271.983 199 1268 199 c +f +*U +0.000 0.639 0.541 0.149 k +*u +1280 199 m +1279 197 l +1281 197 l +1281 198.853 1281.300 198.350 1280 199 c +f +*U +0.000 0.471 0.353 0.035 k +*u +1288 199 m +1289 198 l +1288 199 l +f +*U +0.000 0.514 0.380 0.239 k +*u +1289 199 m +1290 198 l +1289 199 l +f +*U +0.000 0.651 0.533 0.349 k +*u +1290 199 m +1297.409 195.891 1308.975 198 1317 198 c +1309.591 201 1298 199 1290 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1317 199 m +1321.469 197 1327.192 198 1332 198 c +1363 198 l +1358.531 199.875 1352.809 199 1348 199 c +1317 199 l +f +*U +0.000 0.812 0.592 0.188 k +*u +1361 196 m +1362.872 196 1363.612 196 1365 195 c +1366.459 196.312 1367 197.231 1368 199 c +1364.830 198.827 1362.864 198.644 1361 196 c +f +*U +0.000 0.047 0.024 0.686 k +*u +1368 199 m +1369 198 l +1368 199 l +f +*U +0.000 0.424 0.361 0.576 k +*u +2017 199 m +2018 198 l +2017 199 l +f +*U +0.000 0.251 0.184 0.220 k +*u +2018 199 m +2019 198 l +2018 199 l +f +*U +0.000 0.263 0.243 0.125 k +*u +31 198 m +32 197 l +31 198 l +f +*U +0.000 0.353 0.216 0.047 k +*u +1080 198 m +1081 197 l +1080 198 l +f +*U +0.000 0.878 0.631 0.118 k +*u +1082 198 m +1083.523 194.843 1086 189 1089.415 187.600 c +1093.757 185.574 1101.283 187 1106 187 c +1144 187 l +1144 192 l +1138.978 192.912 1135.892 197 1130.981 197.811 c +1115 200 1097.886 197.672 1082 198 c +f +*U +0.000 0.776 0.796 0.125 k +*u +1088 198 m +1090.613 196.902 1093 197 1096 197 c +1093.387 198 1090.836 197.993 1088 198 c +f +*U +0.000 0.494 0.361 0.000 k +*u +1135 198 m +1136 197 l +1135 198 l +f +*U +0.000 0.231 0.192 0.149 k +*u +1164 198 m +1165 197 l +1164 198 l +f +*U +0.000 0.875 0.627 0.125 k +*u +1167 189 m +1169.811 188.837 1172.227 187.623 1175 187.212 c +1181.456 186.259 1188.485 187 1195 187 c +1200.940 187 1207.275 186.308 1213 188 c +1211.205 191 1209.833 195 1206.695 196.972 c +1203.965 198.594 1200 198.000 1197 198 c +1178 198 l +1175.348 198.000 1170.968 198.771 1168.742 196.972 c +1166.565 195.212 1167 191.470 1167 189 c +f +*U +0.000 0.255 0.227 0.357 k +*u +1208 198 m +1209 197 l +1208 198 l +f +*U +0.000 0.867 0.624 0.133 k +*u +1268 198 m +1267.822 193.920 1267.630 190.287 1264 188 c +1267.958 186.339 1272.737 187 1277 187 c +1277.794 188.871 1279.375 191 1279.568 193 c +1280 199 1271.684 198.000 1268 198 c +f +*U +0.000 0.792 0.678 0.208 k +*u +1278 198 m +1278.901 196 1279 196 1281 195 c +1280 196.923 1279.924 196.999 1278 198 c +f +*U +0.000 0.306 0.325 0.196 k +*u +1287 198 m +1288 197 l +1287 198 l +f +*U +0.000 0.624 0.600 0.337 k +*u +1288 198 m +1287.438 196.199 1287.176 194.878 1287 193 c +1290 198 l +1288 198 l +f +*U +0.000 0.882 0.631 0.118 k +*u +1288 193 m +1307 193 l +1306.582 190.311 1306.283 189.446 1304 188 c +1308.720 186 1314.920 187 1320 187 c +1330.816 187 1344.307 184.811 1354.830 187.299 c +1359.709 188.453 1363.982 192.189 1365 197 c +1361.308 196.869 1357.750 197.975 1353.999 197.999 c +1338.334 198 1322.665 198 1307 198 c +1300.721 198 1290.249 200.410 1288 193 c +f +*U +0.000 0.020 0.008 0.278 k +*u +1368 198 m +1369 197 l +1368 198 l +f +*U +0.000 0.533 0.439 0.467 k +*u +2018 198 m +2019 197 l +2018 198 l +f +*U +0.000 0.337 0.247 0.263 k +*u +2019 198 m +2020 197 l +2019 198 l +f +*U +0.000 0.361 0.251 0.243 k +*u +1081 197 m +1082 196 l +1081 197 l +f +*U +0.000 0.502 0.353 0.478 k +*u +1082.333 196.333 m +1082.278 196.278 1082.222 195.222 1082.667 195.667 c +1082.722 195.722 1082.778 196.778 1082.333 196.333 c +f +*U +0.000 0.580 0.475 0.420 k +*u +1208 197 m +1208.684 195.420 1208.805 195.223 1210 194 c +1209.316 195.580 1209.195 195.777 1208 197 c +f +*U +0.000 0.435 0.286 0.427 k +*u +1366.333 196.333 m +1366.278 196.278 1366.222 195.222 1366.667 195.667 c +1366.722 195.722 1366.778 196.778 1366.333 196.333 c +f +*U +0.000 0.404 0.345 0.235 k +*u +1367 197 m +1368 196 l +1367 197 l +f +*U +0.000 0.514 0.388 0.486 k +*u +2020 197 m +2021 196 l +2020 197 l +f +*U +0.000 0.306 0.231 0.231 k +*u +2021 197 m +2022 196 l +2021 197 l +f +*U +0.000 0.224 0.169 0.098 k +*u +2 196 m +3 195 l +2 196 l +f +*U +0.000 0.580 0.459 0.420 k +*u +3 196 m +3 193 l +3.696 194.554 3.696 194.446 3 196 c +f +*U +0.000 0.251 0.157 0.216 k +*u +32 196 m +33 195 l +32 196 l +f +*U +0.000 0.310 0.220 0.588 k +*u +1136 196 m +1137 195 l +1136 196 l +f +*U +0.000 0.337 0.255 0.047 k +*u +1165 196 m +1166 195 l +1165 196 l +f +*U +0.000 0.412 0.329 0.204 k +*u +1266.333 195.333 m +1266.278 195.278 1266.222 194.222 1266.667 194.667 c +1266.722 194.722 1266.778 195.778 1266.333 195.333 c +f +*U +0.000 0.937 0.671 0.063 k +*u +1274 196 m +1275 193.867 1275.882 193.217 1278 192 c +1277 196 l +1274 196 l +f +*U +0.000 0.165 0.137 0.145 k +*u +1286.333 195.333 m +1286.278 195.278 1286.222 194.222 1286.667 194.667 c +1286.722 194.722 1286.777 195.778 1286.333 195.333 c +f +*U +0.000 0.404 0.310 0.514 k +*u +2021.667 195.667 m +2021.222 195.222 2022.278 195.278 2022.333 195.333 c +2022.778 195.778 2021.722 195.722 2021.667 195.667 c +f +*U +0.000 0.671 0.486 0.329 k +*u +30 195 m +31.904 193 33.534 192 36 191 c +34 193.323 32.892 194.194 30 195 c +f +*U +0.000 0.263 0.173 0.094 k +*u +33 195 m +34 194 l +33 195 l +f +*U +0.000 0.220 0.157 0.118 k +*u +1082 195 m +1083 194 l +1082 195 l +f +*U +0.000 0.553 0.427 0.447 k +*u +1083 195 m +1084 194 l +1083 195 l +f +*U +0.000 0.612 0.443 0.388 k +*u +1136.667 194.667 m +1136.222 194.222 1137.278 194.278 1137.333 194.333 c +1137.778 194.778 1136.722 194.722 1136.667 194.667 c +f +*U +0.000 0.400 0.286 0.247 k +*u +1138 195 m +1139 194 l +1138 195 l +f +*U +0.000 0.659 0.478 0.325 k +*u +1166 195 m +1165 190 l +1166.879 191.623 1166.916 192.700 1166 195 c +f +*U +0.000 0.314 0.243 0.306 k +*u +1210 195 m +1211 194 l +1210 195 l +f +*U +0.000 0.522 0.541 0.459 k +*u +1280 195 m +1280 192 l +1280.696 193.554 1280.696 193.446 1280 195 c +f +*U +0.000 0.463 0.325 0.537 k +*u +1365 195 m +1366 194 l +1365 195 l +f +*U +0.000 0.455 0.435 0.545 k +*u +2023 195 m +2024 194 l +2023 195 l +f +*U +0.000 0.212 0.137 0.267 k +*u +2024 195 m +2025 194 l +2024 195 l +f +*U +0.000 0.333 0.216 0.000 k +*u +1083 194 m +1084 193 l +1083 194 l +f +*U +0.000 0.447 0.314 0.451 k +*u +1084.333 193.333 m +1084.278 193.278 1084.222 192.222 1084.667 192.667 c +1084.722 192.722 1084.778 193.778 1084.333 193.333 c +f +*U +0.000 0.471 0.380 0.529 k +*u +1138.667 193.667 m +1138.222 193.222 1139.278 193.278 1139.333 193.333 c +1139.778 193.778 1138.722 193.722 1138.667 193.667 c +f +*U +0.000 0.361 0.259 0.200 k +*u +1140 194 m +1141 193 l +1140 194 l +f +*U +0.000 0.498 0.388 0.502 k +*u +1210 194 m +1211 193 l +1210 194 l +f +*U +0.000 0.616 0.420 0.353 k +*u +1266 194 m +1265.697 191.706 1265.421 190.788 1264 189 c +1267.458 187.697 1267 191.778 1266 194 c +f +*U +0.000 0.412 0.412 0.588 k +*u +1364 194 m +1365 193 l +1364 194 l +f +*U +0.000 0.243 0.176 0.071 k +*u +1365 194 m +1366 193 l +1365 194 l +f +*U +0.000 0.522 0.345 0.333 k +*u +2024.667 193.667 m +2024.222 193.222 2025.278 193.278 2025.333 193.333 c +2025.778 193.778 2024.722 193.722 2024.667 193.667 c +f +*U +0.000 0.349 0.231 0.078 k +*u +2026 194 m +2027 193 l +2026 194 l +f +*U +0.000 0.486 0.345 0.106 k +*u +3 193 m +4 192 l +3 193 l +f +*U +0.000 0.533 0.361 0.392 k +*u +1140 193 m +1141.248 192.315 1141.549 192.251 1143 192 c +1141.752 192.685 1141.452 192.749 1140 193 c +f +*U +0.000 0.282 0.196 0.165 k +*u +1143 193 m +1144 192 l +1143 193 l +f +*U +0.000 0.129 0.102 0.196 k +*u +1211 193 m +1212 192 l +1211 193 l +f +*U +0.000 0.208 0.161 0.227 k +*u +1287 193 m +1288 192 l +1287 193 l +f +*U +0.000 0.714 0.714 0.286 k +*u +1288 193 m +1290.332 192 1292.457 192 1295 192 c +1292.668 192.985 1290.543 192.981 1288 193 c +f +*U +0.000 0.694 0.537 0.306 k +*u +1295 193 m +1296.506 192.317 1297.315 192.174 1299 192 c +1297.494 192.683 1296.685 192.826 1295 193 c +f +*U +0.000 0.537 0.392 0.463 k +*u +1299 193 m +1300.769 192.221 1302 192 1304 192 c +1302.231 192.779 1300.964 192.912 1299 193 c +f +*U +0.000 0.769 0.561 0.231 k +*u +1304 193 m +1304.457 191 1304.581 190.792 1304 189 c +1306.905 187.905 1306.880 190.550 1307 193 c +1304 193 l +f +*U +0.000 0.306 0.345 0.271 k +*u +1364 193 m +1365 192 l +1364 193 l +f +*U +0.000 0.475 0.325 0.525 k +*u +2026 193 m +2027 192 l +2026 193 l +f +*U +0.000 0.224 0.145 0.333 k +*u +2027 193 m +2028 192 l +2027 193 l +f +*U +0.000 0.490 0.337 0.384 k +*u +4.333 191.333 m +4.278 191.278 4.222 190.222 4.667 190.667 c +4.722 190.722 4.778 191.778 4.333 191.333 c +f +*U +0.000 0.290 0.216 0.149 k +*u +36 192 m +37 191 l +36 192 l +f +*U +0.020 0.000 0.020 0.000 k +*u +46 192 m +53 188.996 64.256 191 72 191 c +130 191 l +332 191 l +1032 191 l +1024.841 194 1013.744 192 1006 192 c +948 192 l +746 192 l +46 192 l +f +*U +0.008 0.012 0.000 0.000 k +*u +56 189 m +62.919 186 73.520 188 81 188 c +138 188 l +335 188 l +804 188 l +955 188 l +982.955 188 1012.512 185.346 1040 190 c +1034.725 193 1028 189 1022 189 c +969 189 l +775 189 l +56 189 l +f +*U +0.000 0.369 0.239 0.612 k +*u +1085 192 m +1086 191 l +1085 192 l +f +*U +0.000 0.580 0.396 0.420 k +*u +1086.333 191.333 m +1086.278 191.278 1086.222 190.222 1086.667 190.667 c +1086.722 190.722 1086.778 191.778 1086.333 191.333 c +f +*U +0.000 0.325 0.325 0.675 k +*u +1144.333 191.333 m +1144.278 191.278 1144.222 190.222 1144.667 190.667 c +1144.722 190.722 1144.778 191.778 1144.333 191.333 c +f +*U +0.000 0.365 0.267 0.090 k +*u +1165 192 m +1166 191 l +1165 192 l +f +*U +0.000 0.369 0.337 0.224 k +*u +1211 192 m +1212 191 l +1211 192 l +f +*U +0.000 0.443 0.302 0.239 k +*u +1304 192 m +1305 191 l +1304 192 l +f +*U +0.000 0.384 0.259 0.518 k +*u +1361 190 m +1362.580 190.684 1362.777 190.805 1364 192 c +1362.420 191.316 1362.223 191.195 1361 190 c +f +*U +0.020 0.000 0.020 0.000 k +*u +1432 192 m +1436.720 190 1442.920 191 1448 191 c +1479 191 l +1588 191 l +1968 191 l +1963.280 192.981 1957 192 1952 192 c +1921 192 l +1812 192 l +1432 192 l +f +*U +0.000 0.349 0.255 0.031 k +*u +2029 192 m +2030 191 l +2029 192 l +f +*U +0.000 0.365 0.263 0.286 k +*u +37 191 m +38 190 l +37 191 l +f +*U +0.000 0.020 0.012 0.000 k +*u +48 191 m +55 187.996 66.256 190 74 190 c +132 190 l +333 190 l +1032 190 l +1024.841 193 1013.744 191 1006 191 c +948 191 l +747 191 l +48 191 l +f +*U +0.000 0.251 0.169 0.157 k +*u +1085 191 m +1086 190 l +1085 191 l +f +*U +0.000 0.153 0.118 0.114 k +*u +1145 191 m +1146 190 l +1145 191 l +f +*U +0.000 0.565 0.459 0.435 k +*u +1211.333 190.333 m +1211.278 190.278 1211.222 189.222 1211.667 189.667 c +1211.722 189.722 1211.778 190.778 1211.333 190.333 c +f +*U +0.000 0.388 0.290 0.039 k +*u +1278 191 m +1279 190 l +1278 191 l +f +*U +0.000 0.318 0.235 0.129 k +*u +1305 191 m +1306 190 l +1305 191 l +f +*U +0.000 0.020 0.012 0.000 k +*u +1432 191 m +1436.720 189 1442.920 190 1448 190 c +1479 190 l +1588 190 l +1968 190 l +1963.280 191.981 1957 191 1952 191 c +1921 191 l +1812 191 l +1432 191 l +f +*U +0.000 0.506 0.369 0.490 k +*u +2028.667 190.667 m +2028.222 190.223 2029.277 190.277 2029.333 190.333 c +2029.778 190.778 2028.722 190.722 2028.667 190.667 c +f +*U +0.000 0.322 0.235 0.239 k +*u +2030 191 m +2031 190 l +2030 191 l +f +*U +0.000 0.282 0.200 0.016 k +*u +4 190 m +5 189 l +4 190 l +f +*U +0.000 0.569 0.388 0.431 k +*u +5.333 189.333 m +5.278 189.278 5.222 188.222 5.667 188.667 c +5.722 188.722 5.778 189.778 5.333 189.333 c +f +*U +0.000 0.780 0.537 0.220 k +*u +37 190 m +37.980 188.217 37.908 188.406 40 188 c +38.777 189.195 38.580 189.316 37 190 c +f +*U +0.000 0.322 0.235 0.004 k +*u +39 190 m +40 189 l +39 190 l +f +*U +0.004 0.000 0.000 0.000 k +*u +44 190 m +48.869 186.970 58.251 189 64 189 c +116 189 l +310 189 l +1032 189 l +1024.841 192 1013.744 190 1006 190 c +948 190 l +745 190 l +44 190 l +f +*U +0.000 0.408 0.275 0.173 k +*u +1086 190 m +1087 189 l +1086 190 l +f +*U +0.000 0.329 0.235 0.341 k +*u +1144.333 189.333 m +1144.278 189.278 1144.222 188.222 1144.667 188.667 c +1144.722 188.722 1144.778 189.778 1144.333 189.333 c +f +*U +0.000 0.467 0.333 0.114 k +*u +1165.667 189.667 m +1165.222 189.222 1166.278 189.278 1166.333 189.333 c +1166.778 189.778 1165.722 189.722 1165.667 189.667 c +f +*U +0.000 0.384 0.384 0.616 k +*u +1168 190 m +1169 189 l +1168 190 l +f +*U +0.000 0.278 0.204 0.145 k +*u +1212 190 m +1213 189 l +1212 190 l +f +*U +0.000 0.353 0.255 0.184 k +*u +1265 190 m +1266 189 l +1265 190 l +f +*U +0.000 0.561 0.396 0.416 k +*u +1277 190 m +1275.554 187.717 1274.689 187.418 1272 187 c +1274 186 1275.747 186 1278 186 c +1277.826 187.685 1277.683 188.494 1277 190 c +f +*U +0.000 0.267 0.208 0.082 k +*u +1304 190 m +1305 189 l +1304 190 l +f +*U +0.000 0.443 0.325 0.306 k +*u +1305 190 m +1306 189 l +1305 190 l +f +*U +0.000 0.525 0.412 0.471 k +*u +1358.667 189.667 m +1358.222 189.222 1359.278 189.278 1359.333 189.333 c +1359.778 189.778 1358.722 189.722 1358.667 189.667 c +f +*U +0.000 0.318 0.204 0.294 k +*u +1360 190 m +1361 189 l +1360 190 l +f +*U +0.000 0.263 0.176 0.114 k +*u +1361 190 m +1362 189 l +1361 190 l +f +*U +0.000 0.600 0.455 0.400 k +*u +2030.667 189.667 m +2030.222 189.222 2031.278 189.278 2031.333 189.333 c +2031.778 189.778 2030.722 189.722 2030.667 189.667 c +f +*U +0.000 0.137 0.090 0.180 k +*u +2032 190 m +2033 189 l +2032 190 l +f +*U +0.000 0.439 0.298 0.553 k +*u +40 189 m +41 188 l +40 189 l +f +*U +0.000 0.400 0.275 0.314 k +*u +41 189 m +42 188 l +41 189 l +f +*U +0.000 0.290 0.204 0.027 k +*u +42 189 m +43 188 l +42 189 l +f +*U +0.000 0.376 0.243 0.408 k +*u +1087 189 m +1088 188 l +1087 189 l +f +*U +0.000 0.173 0.200 0.118 k +*u +1169 189 m +1170 188 l +1169 189 l +f +*U +0.000 0.404 0.345 0.243 k +*u +1170 189 m +1171 188 l +1170 189 l +f +*U +0.000 0.224 0.149 0.298 k +*u +1263 189 m +1264 188 l +1263 189 l +f +*U +0.000 0.141 0.145 0.392 k +*u +1303 189 m +1304 188 l +1303 189 l +f +*U +0.000 0.596 0.486 0.404 k +*u +1357.333 188.333 m +1357.278 188.278 1357.222 187.222 1357.667 187.667 c +1357.722 187.722 1357.778 188.778 1357.333 188.333 c +f +*U +0.000 0.482 0.373 0.322 k +*u +1358 189 m +1359 188 l +1358 189 l +f +*U +0.008 0.012 0.000 0.000 k +*u +1430 189 m +1434.720 187 1440.920 188 1446 188 c +1477 188 l +1587 188 l +1968 188 l +1963.280 189.981 1957 189 1952 189 c +1921 189 l +1811 189 l +1430 189 l +f +*U +0.000 0.561 0.388 0.439 k +*u +2032 189 m +2033 188 l +2032 189 l +f +*U +0.000 0.420 0.286 0.235 k +*u +2033 189 m +2034 188 l +2033 189 l +f +*U +0.000 0.365 0.239 0.035 k +*u +5 188 m +6 187 l +5 188 l +f +*U +0.000 0.604 0.467 0.396 k +*u +41 188 m +42.248 187.315 42.549 187.251 44 187 c +42.752 187.685 42.452 187.749 41 188 c +f +*U +0.000 0.392 0.278 0.353 k +*u +44 188 m +45 187 l +44 188 l +f +*U +0.000 0.216 0.161 0.110 k +*u +45 188 m +46.248 187.315 46.549 187.251 48 187 c +46.752 187.685 46.452 187.749 45 188 c +f +*U +0.000 0.192 0.149 0.671 k +*u +1144.333 187.333 m +1144.278 187.278 1144.222 186.222 1144.667 186.667 c +1144.722 186.722 1144.778 187.778 1144.333 187.333 c +f +*U +0.000 0.341 0.278 0.384 k +*u +1172 188 m +1173 187 l +1172 188 l +f +*U +0.000 0.373 0.271 0.557 k +*u +1212 188 m +1212 186 l +1214 186 l +1213.455 187.635 1213.635 187.455 1212 188 c +f +*U +0.000 0.373 0.263 0.318 k +*u +1213 188 m +1214 187 l +1213 188 l +f +*U +0.000 0.490 0.349 0.467 k +*u +1261 188 m +1262.926 185.792 1265 186 1268 186 c +1265.717 187.222 1263.572 187.652 1261 188 c +f +*U +0.000 0.365 0.278 0.047 k +*u +1301 188 m +1302 187 l +1301 188 l +f +*U +0.000 0.498 0.365 0.502 k +*u +1302 188 m +1301 186 l +1303 186 l +1303 187.853 1303.300 187.350 1302 188 c +f +*U +0.000 0.663 0.475 0.275 k +*u +1303.333 187.333 m +1303.278 187.278 1303.222 186.222 1303.667 186.667 c +1303.722 186.722 1303.778 187.778 1303.333 187.333 c +f +*U +0.000 0.341 0.278 0.204 k +*u +1358 188 m +1359 187 l +1358 188 l +f +*U +0.000 0.753 0.514 0.227 k +*u +1973 188 m +1974 184 l +1975 185.458 1975.436 186.248 1976 188 c +1973 188 l +f +*U +0.000 0.573 0.396 0.376 k +*u +2033.667 187.667 m +2033.222 187.222 2034.278 187.278 2034.333 187.333 c +2034.778 187.778 2033.722 187.722 2033.667 187.667 c +f +*U +0.000 0.271 0.200 0.200 k +*u +2035 188 m +2036 187 l +2035 188 l +f +*U +0.000 0.455 0.298 0.247 k +*u +6 187 m +7 186 l +6 187 l +f +*U +0.000 0.506 0.337 0.494 k +*u +7.333 186.333 m +7.278 186.278 7.222 185.222 7.667 185.667 c +7.722 185.722 7.778 186.778 7.333 186.333 c +f +*U +0.000 0.914 0.635 0.086 k +*u +40 186 m +44.917 182.699 54 185 60 185 c +111 185 l +303 185 l +795 185 l +953 185 l +1004 185 l +1014.283 185 1024.836 185.752 1035 184 c +1031.803 187.658 1023.577 186 1019 186 c +975 186 l +796 186 l +279 186 l +116 186 l +64 186 l +56.424 186 47.290 187.580 40 186 c +f +*U +0.000 0.655 0.494 0.345 k +*u +44 187 m +45.506 186.317 46.315 186.174 48 186 c +46.494 186.683 45.685 186.826 44 187 c +f +*U +0.000 0.525 0.424 0.475 k +*u +48 187 m +55 183.996 66.256 186 74 186 c +132 186 l +334 186 l +1035 186 l +1027.841 189 1016.744 187 1009 187 c +951 187 l +749 187 l +48 187 l +f +*U +0.000 0.325 0.239 0.475 k +*u +1035 187 m +1036 186 l +1035 187 l +f +*U +0.000 0.247 0.184 0.118 k +*u +1036 187 m +1037 186 l +1036 187 l +f +*U +0.000 0.459 0.349 0.122 k +*u +1088 187 m +1089 186 l +1088 187 l +f +*U +0.000 0.443 0.329 0.494 k +*u +1089 187 m +1094.216 184.811 1101.381 186 1107 186 c +1144 186 l +1138.783 188.189 1131.619 187 1126 187 c +1089 187 l +f +*U +0.024 0.000 0.027 0.227 k +*u +1145 187 m +1146 186 l +1145 187 l +f +*U +0.000 0.259 0.224 0.278 k +*u +1173 187 m +1174 186 l +1173 187 l +f +*U +0.000 0.443 0.329 0.494 k +*u +1174 187 m +1177.699 185.448 1182 186 1186 186 c +1209 186 l +1205.301 187.552 1200.983 187 1197 187 c +1174 187 l +f +*U +0.000 0.478 0.314 0.373 k +*u +1209 187 m +1210.248 186.315 1210.549 186.251 1212 186 c +1210.752 186.685 1210.452 186.749 1209 187 c +f +*U +0.000 0.380 0.275 0.306 k +*u +1268 187 m +1269.506 186.317 1270.315 186.174 1272 186 c +1270.494 186.683 1269.685 186.826 1268 187 c +f +*U +0.000 0.443 0.329 0.494 k +*u +1304 187 m +1308.969 184.915 1315.650 186 1321 186 c +1357 186 l +1352 188 1345.350 187 1340 187 c +1304 187 l +f +*U +0.000 0.271 0.212 0.275 k +*u +1357 187 m +1358 186 l +1357 187 l +f +*U +0.000 0.216 0.192 0.039 k +*u +1425 187 m +1426 186 l +1425 187 l +f +*U +0.000 0.306 0.243 0.271 k +*u +1426 187 m +1427 186 l +1426 187 l +f +*U +0.000 0.416 0.345 0.584 k +*u +1427 187 m +1428.506 186.317 1429.314 186.174 1431 186 c +1429.494 186.683 1428.685 186.826 1427 187 c +f +*U +0.000 0.525 0.424 0.475 k +*u +1431 187 m +1435.720 185 1441.920 186 1447 186 c +1478 186 l +1589 186 l +1973 186 l +1968.280 187.980 1962 187 1957 187 c +1926 187 l +1815 187 l +1431 187 l +f +*U +0.000 0.384 0.278 0.412 k +*u +2035.667 186.667 m +2035.222 186.222 2036.278 186.278 2036.333 186.333 c +2036.778 186.778 2035.722 186.722 2035.667 186.667 c +f +*U +0.000 0.694 0.514 0.306 k +*u +1035 186 m +1036.693 184.938 1038 184.480 1040 184 c +1038.211 185.422 1037.294 185.697 1035 186 c +f +*U +0.000 0.314 0.200 0.145 k +*u +1423 186 m +1424 185 l +1423 186 l +f +*U +0.000 0.643 0.510 0.337 k +*u +1424.667 185.667 m +1424.222 185.222 1425.278 185.278 1425.333 185.333 c +1425.778 185.778 1424.722 185.722 1424.667 185.667 c +f +*U +0.000 0.914 0.635 0.086 k +*u +1429 184 m +1436.724 185.839 1445 185 1453 185 c +1493 185 l +1623 185 l +1853 185 l +1927 185 l +1941.930 185 1957.180 185.947 1972 184 c +1969.897 186.407 1967 185.994 1964 186 c +1945 186 l +1866 186 l +1547 186 l +1459 186 l +1438 186 l +1434.683 185.999 1431.276 186.604 1429 184 c +f +*U +0.000 0.459 0.392 0.541 k +*u +2037 186 m +2038 185 l +2037 186 l +f +*U +0.000 0.349 0.263 0.082 k +*u +2038 186 m +2039 185 l +2038 186 l +f +*U +0.000 0.478 0.314 0.251 k +*u +7 185 m +8 184 l +7 185 l +f +*U +0.000 0.878 0.616 0.122 k +*u +48 185 m +55 181.996 66.256 184 74 184 c +132 184 l +333 184 l +1032 184 l +1024.841 187 1013.744 185 1006 185 c +948 185 l +747 185 l +48 185 l +f +*U +0.000 0.094 0.047 0.463 k +*u +1040 185 m +1041 184 l +1040 185 l +f +*U +0.000 0.482 0.306 0.510 k +*u +1422.667 184.667 m +1422.222 184.222 1423.278 184.278 1423.333 184.333 c +1423.778 184.778 1422.722 184.722 1422.667 184.667 c +f +*U +0.000 0.878 0.616 0.122 k +*u +1431 185 m +1435.720 183 1441.920 184 1447 184 c +1478 184 l +1587 184 l +1968 184 l +1963.280 185.981 1957 185 1952 185 c +1921 185 l +1812 185 l +1431 185 l +f +*U +0.000 0.545 0.388 0.431 k +*u +2038.667 184.667 m +2038.222 184.223 2039.277 184.277 2039.333 184.333 c +2039.778 184.778 2038.722 184.722 2038.667 184.667 c +f +*U +0.000 0.686 0.435 0.302 k +*u +8 184 m +9 181.783 10 180.606 12 179 c +11 184 l +8 184 l +f +*U +0.000 0.800 0.686 0.161 k +*u +1040 184 m +1040.684 181.791 1041 181.297 1043 180 c +1042 181.769 1041.459 182.688 1040 184 c +f +*U +0.000 0.561 0.482 0.388 k +*u +1041 184 m +1041 182 l +1043 182 l +1042.455 183.635 1042.635 183.455 1041 184 c +f +*U +0.000 0.365 0.333 0.012 k +*u +1420 184 m +1421 183 l +1420 184 l +f +*U +0.000 0.463 0.463 0.537 k +*u +1421 184 m +1422 183 l +1421 184 l +f +*U +0.000 0.502 0.498 0.475 k +*u +2040 184 m +2041 183 l +2040 184 l +f +*U +0.000 0.365 0.380 0.239 k +*u +2041 184 m +2042 183 l +2041 184 l +f +*U +0.000 0.349 0.212 0.086 k +*u +8 183 m +9 182 l +8 183 l +f +*U +0.000 0.259 0.247 0.188 k +*u +1419 183 m +1420 182 l +1419 183 l +f +*U +0.000 0.435 0.412 0.565 k +*u +1420 183 m +1421 182 l +1420 183 l +f +*U +0.000 0.439 0.365 0.459 k +*u +2041.667 182.667 m +2041.222 182.222 2042.278 182.278 2042.333 182.333 c +2042.778 182.778 2041.722 182.722 2041.667 182.667 c +f +*U +0.000 0.180 0.157 0.169 k +*u +2043 183 m +2044 182 l +2043 183 l +f +*U +0.000 0.651 0.537 0.349 k +*u +1043.333 181.333 m +1043.278 181.278 1043.222 180.222 1043.667 180.667 c +1043.722 180.722 1043.778 181.778 1043.333 181.333 c +f +*U +0.000 0.282 0.220 0.098 k +*u +1418 182 m +1419 181 l +1418 182 l +f +*U +0.000 0.686 0.529 0.314 k +*u +1419 182 m +1417.738 179.990 1416.810 178.222 1416 176 c +1418.583 177.570 1419.675 179.282 1421 182 c +1419 182 l +f +*U +0.000 0.537 0.420 0.416 k +*u +2043 182 m +2044 181 l +2043 182 l +f +*U +0.000 0.259 0.216 0.251 k +*u +2044 182 m +2045 181 l +2044 182 l +f +*U +0.000 0.235 0.212 0.176 k +*u +1044 181 m +1045 180 l +1044 181 l +f +*U +0.000 0.212 0.137 0.169 k +*u +2046 181 m +2047 180 l +2046 181 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1044 180 m +1045 179 l +1044 180 l +f +*U +0.000 0.235 0.173 0.129 k +*u +1417 180 m +1418 179 l +1417 180 l +f +*U +0.000 0.471 0.388 0.529 k +*u +2046 180 m +2047 179 l +2046 180 l +f +*U +0.000 0.376 0.231 0.318 k +*u +2047 180 m +2048 179 l +2047 180 l +f +*U +0.000 0.635 0.498 0.365 k +*u +1045.333 178.333 m +1045.278 178.278 1045.222 177.222 1045.667 177.667 c +1045.722 177.722 1045.778 178.778 1045.333 178.333 c +f +*U +0.000 0.988 0.671 0.012 k +*u +1419 179 m +1418 177.521 1418 177.797 1418 176 c +1419.290 177.443 1419.401 177.233 1419 179 c +f +*U +0.000 0.376 0.290 0.600 k +*u +2048 179 m +2049 178 l +2048 179 l +f +*U +0.000 0.322 0.259 0.075 k +*u +2049 179 m +2050 178 l +2049 179 l +f +*U +0.000 0.106 0.059 0.118 k +*u +12 178 m +13 177 l +12 178 l +f +*U +0.000 0.227 0.173 0.341 k +*u +1046 178 m +1047 177 l +1046 178 l +f +*U +0.000 0.627 0.502 0.373 k +*u +2049 178 m +2050 177 l +2049 178 l +f +*U +0.000 0.455 0.341 0.290 k +*u +2050 178 m +2051 177 l +2050 178 l +f +*U +0.000 0.290 0.188 0.078 k +*u +13 177 m +14 176 l +13 177 l +f +*U +0.000 0.447 0.329 0.553 k +*u +2050.667 176.667 m +2050.223 176.223 2051.278 176.278 2051.333 176.333 c +2051.778 176.778 2050.722 176.722 2050.667 176.667 c +f +*U +0.000 0.212 0.157 0.251 k +*u +2052 177 m +2053 176 l +2052 177 l +f +*U +0.000 0.247 0.157 0.145 k +*u +14 176 m +15 175 l +14 176 l +f +*U +0.000 0.349 0.224 0.510 k +*u +15 176 m +16 175 l +15 176 l +f +*U +0.000 0.078 0.051 0.169 k +*u +1098.333 175.333 m +1098.278 175.278 1098.222 174.222 1098.667 174.667 c +1098.722 174.722 1098.778 175.778 1098.333 175.333 c +f +*U +0.000 0.384 0.412 0.133 k +*u +1099 176 m +1103.720 174 1109.920 175 1115 175 c +1149 175 l +1144.280 176.980 1138 176 1133 176 c +1099 176 l +f +*U +0.000 0.361 0.333 0.306 k +*u +1149 176 m +1150 175 l +1149 176 l +f +*U +0.000 0.102 0.133 0.204 k +*u +1150 176 m +1151 175 l +1150 176 l +f +*U +0.000 0.384 0.412 0.133 k +*u +1185 176 m +1189.215 174.231 1194.465 175 1199 175 c +1227 175 l +1222.785 176.769 1217.536 176 1213 176 c +1185 176 l +f +*U +0.000 0.235 0.282 0.039 k +*u +1227 176 m +1228 175 l +1227 176 l +f +*U +0.000 0.318 0.251 0.141 k +*u +1256 176 m +1257.506 175.317 1258.315 175.174 1260 175 c +1258.494 175.683 1257.685 175.826 1256 176 c +f +*U +0.000 0.392 0.373 0.129 k +*u +1260 176 m +1264.217 174.231 1269.459 175 1274 175 c +1269.783 176.769 1264.541 176 1260 176 c +f +*U +0.000 0.008 0.004 0.243 k +*u +1296 176 m +1297 175 l +1296 176 l +f +*U +0.000 0.055 0.098 0.490 k +*u +1297 176 m +1298 174 l +1299.635 174.545 1299.455 174.365 1300 176 c +1297 176 l +f +*U +0.000 0.231 0.224 0.098 k +*u +1300.667 175.667 m +1300.222 175.222 1301.278 175.278 1301.333 175.333 c +1301.778 175.778 1300.722 175.722 1300.667 175.667 c +f +*U +0.000 0.384 0.412 0.133 k +*u +1302 176 m +1306.469 174 1312.191 175 1317 175 c +1348 175 l +1343.531 176.875 1337.809 176 1333 176 c +1302 176 l +f +*U +0.000 0.039 0.165 0.431 k +*u +1348.667 175.667 m +1348.222 175.222 1349.278 175.278 1349.333 175.333 c +1349.778 175.778 1348.722 175.722 1348.667 175.667 c +f +*U +0.000 0.161 0.141 0.176 k +*u +1350 176 m +1351 175 l +1350 176 l +f +*U +0.000 0.694 0.545 0.306 k +*u +1415 176 m +1413.545 173.344 1412 170.832 1411 168 c +1413.665 170.231 1415.825 172.419 1415 176 c +f +*U +0.000 0.690 0.494 0.310 k +*u +2053 176 m +2053 174 l +2055 174 l +2054.455 175.635 2054.635 175.455 2053 176 c +f +*U +0.000 0.286 0.176 0.047 k +*u +2054 176 m +2055 175 l +2054 176 l +f +*U +0.000 0.263 0.173 0.063 k +*u +15 175 m +16 174 l +15 175 l +f +*U +0.000 0.271 0.176 0.400 k +*u +1048 175 m +1049 174 l +1048 175 l +f +*U +0.000 0.510 0.384 0.490 k +*u +1099 175 m +1099.545 173.365 1099.365 173.545 1101 173 c +1101 175 l +1099 175 l +f +*U +0.000 0.910 0.663 0.082 k +*u +1101 175 m +1102 173 1103 172.260 1105 171 c +1105 175 l +1101 175 l +f +*U +0.000 0.867 0.753 0.075 k +*u +1105 175 m +1105 170 l +1107 170 l +1107 175 l +1105 175 l +f +*U +0.000 0.871 0.616 0.125 k +*u +1107 175 m +1106 169 l +1108 167 1109.547 165.421 1111 163 c +1124.682 166.257 1140.961 164 1155 164 c +1154 167.322 1153 169.275 1150 171 c +1149.461 175.291 1143.577 174 1140 174 c +1128.929 174 1118 174.657 1107 175 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1112 175 m +1115.699 173.448 1120 174 1124 174 c +1145 174 l +1141.301 175.552 1136.983 175 1133 175 c +1112 175 l +f +*U +0.000 0.678 0.525 0.286 k +*u +1145 175 m +1146.940 174 1148.898 173.561 1151 173 c +1149.266 175 1147.645 174.923 1145 175 c +f +*U +0.000 0.522 0.365 0.298 k +*u +1185.333 174.333 m +1185.278 174.278 1185.222 173.222 1185.667 173.667 c +1185.722 173.722 1185.778 174.778 1185.333 174.333 c +f +*U +0.000 0.690 0.541 0.306 k +*u +1186 173 m +1192 174 l +1189.471 175 1187.824 175 1186 173 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1192 175 m +1195.699 173.448 1200 174 1204 174 c +1225 174 l +1221.301 175.552 1216.983 175 1213 175 c +1192 175 l +f +*U +0.000 0.831 0.600 0.149 k +*u +1225 175 m +1221.309 172.204 1216.485 173 1212 173 c +1202.898 173 1194 172.648 1185 172 c +1181 165 l +1191.522 168.283 1203 167 1214 167 c +1272 167 l +1267 169 1260.362 168 1255 168 c +1258 168.900 1260.831 168.992 1264 169 c +1260.881 170.312 1257.782 169.891 1255 172 c +1252.280 170.967 1249.813 170.278 1248 168 c +1244.336 170.567 1239.395 170.445 1235 171 c +1235.980 169.217 1235.907 169.406 1238 169 c +1234.414 168.319 1230.664 168.259 1227 168 c +1228.479 168.986 1228.203 169 1230 169 c +1226 170.661 1221.260 170 1217 170 c +1192 170 l +1192 172 l +1216 172 l +1220.296 172 1224.302 171.260 1227 175 c +1225 175 l +f +*U +0.000 0.392 0.392 0.608 k +*u +1227 175 m +1228 174 l +1227 175 l +f +*U +0.000 0.655 0.518 0.322 k +*u +1228 175 m +1228.980 173.217 1228.907 173.406 1231 173 c +1229.860 174 1229.389 174.309 1228 175 c +f +*U +0.000 0.259 0.192 0.106 k +*u +1237 175 m +1238 174 l +1237 175 l +f +*U +0.000 0.757 0.588 0.243 k +*u +1238.333 174.333 m +1238.278 174.278 1238.222 173.222 1238.667 173.667 c +1238.722 173.722 1238.778 174.778 1238.333 174.333 c +f +*U +0.000 0.573 0.447 0.427 k +*u +1239 175 m +1241.836 173.693 1244.998 172.939 1248 172 c +1245.271 174.787 1242.827 174.956 1239 175 c +f +*U +0.000 0.251 0.188 0.157 k +*u +1246 175 m +1247 174 l +1246 175 l +f +*U +0.000 0.251 0.196 0.133 k +*u +1253 175 m +1254 174 l +1253 175 l +f +*U +0.000 0.486 0.380 0.365 k +*u +1254.667 174.667 m +1254.222 174.222 1255.278 174.278 1255.333 174.333 c +1255.778 174.778 1254.722 174.722 1254.667 174.667 c +f +*U +0.000 0.690 0.749 0.251 k +*u +1256 175 m +1258.613 173.902 1261 174 1264 174 c +1261.387 175 1258.835 174.993 1256 175 c +f +*U +0.000 0.749 0.847 0.145 k +*u +1264 175 m +1266.613 173.902 1269 174 1272 174 c +1269.387 175 1266.836 174.993 1264 175 c +f +*U +0.000 0.882 0.627 0.118 k +*u +1254 173 m +1256.529 169.493 1259.940 170 1264 170 c +1260.959 169 1258.169 169 1255 169 c +1259.974 166.913 1266.638 168 1272 168 c +1264.848 165.886 1256.427 167 1249 167 c +1206 167 l +1199.931 167 1186.617 169.579 1183 164 c +1250 164 l +1267 164 l +1269.301 164 1272.496 163.564 1274.471 165 c +1277.520 167.286 1276.363 172.889 1272.856 173.972 c +1267.975 175.480 1258.816 174.424 1254 173 c +f +*U +0.000 0.384 0.384 0.616 k +*u +1273 175 m +1274 174 l +1273 175 l +f +*U +0.000 0.263 0.224 0.322 k +*u +1274 175 m +1275 174 l +1274 175 l +f +*U +0.075 0.216 0.000 0.192 k +*u +1297 175 m +1298 174 l +1297 175 l +f +*U +0.000 0.631 0.639 0.361 k +*u +1299 175 m +1300.223 173.805 1300.420 173.684 1302 173 c +1300.777 174.195 1300.580 174.316 1299 175 c +f +*U +0.000 0.773 0.631 0.212 k +*u +1301.667 174.667 m +1301.222 174.222 1302.278 174.278 1302.333 174.333 c +1302.778 174.778 1301.722 174.722 1301.667 174.667 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1302 174 m +1305.985 173 1310.830 174.000 1315 174 c +1344 174 l +1340 175.661 1335.260 175 1331 175 c +1321.805 175 1310.842 176.614 1302 174 c +f +*U +0.000 0.918 0.659 0.082 k +*u +1312 174 m +1318.965 171 1329.475 173 1337 172.996 c +1340.593 172.961 1343.614 172 1346 175 c +1334.957 172.950 1323.203 174 1312 174 c +f +*U +0.000 0.788 0.616 0.212 k +*u +1346 175 m +1345 172.896 1344.954 172.248 1345 170 c +1346.840 171.717 1347.349 172.566 1348 175 c +1346 175 l +f +*U +0.000 0.580 0.522 0.306 k +*u +1348 175 m +1348 173 l +1349.635 173.545 1349.455 173.365 1350 175 c +1348 175 l +f +*U +0.000 0.408 0.325 0.224 k +*u +1414 175 m +1415 174 l +1414 175 l +f +*U +0.000 0.475 0.349 0.098 k +*u +2055 175 m +2056 174 l +2055 175 l +f +*U +0.000 0.204 0.145 0.102 k +*u +1049 174 m +1050 173 l +1049 174 l +f +*U +0.000 0.533 0.475 0.035 k +*u +1151 174 m +1152 173 l +1151 174 l +f +*U +0.000 0.918 0.659 0.082 k +*u +1186 171 m +1197.524 175.489 1212.781 173 1225 173 c +1217 176.305 1204.531 174 1196 174 c +1191.995 173.998 1188.334 174.600 1186 171 c +f +*U +0.000 0.894 0.643 0.106 k +*u +1226 174 m +1222.730 171.523 1219 172 1215 172 c +1192 172 l +1192 170 l +1230 170 l +1228.521 169 1228.797 169 1227 169 c +1230.382 167.640 1234.352 168 1238 168 c +1235 171 l +1239 170.240 1243.650 170.538 1247 168 c +1248 171 1246.257 173 1242.981 173.682 c +1237.459 174.621 1231.755 172.932 1226 174 c +f +*U +0.000 0.357 0.298 0.020 k +*u +1231 174 m +1232.769 173.221 1234 173 1236 173 c +1234.231 173.779 1232.964 173.912 1231 174 c +f +*U +0.000 0.608 0.490 0.392 k +*u +1236.667 173.667 m +1236.222 173.222 1237.278 173.278 1237.333 173.333 c +1237.778 173.778 1236.722 173.722 1236.667 173.667 c +f +*U +0.000 0.329 0.275 0.137 k +*u +1247 174 m +1248 173 l +1247 174 l +f +*U +0.000 0.388 0.314 0.125 k +*u +1252.333 173.333 m +1252.278 173.278 1252.222 172.222 1252.667 172.667 c +1252.722 172.722 1252.778 173.778 1252.333 173.333 c +f +*U +0.000 0.714 0.588 0.286 k +*u +1252 171 m +1253.923 171.902 1253.999 172 1255 174 c +1253 173 1253 172.924 1252 171 c +f +*U +0.000 0.318 0.294 0.216 k +*u +1275 174 m +1276 173 l +1275 174 l +f +*U +0.000 0.859 0.604 0.137 k +*u +1301 173 m +1302 170.237 1307.468 166.678 1304 165 c +1308 162.843 1312.478 163.944 1317 163.996 c +1327.786 164 1335.368 163.682 1345 169 c +1343 173.893 1338.660 173.000 1334 173 c +1323.230 173 1311.529 174.955 1301 173 c +f +*U +0.000 0.710 0.537 0.290 k +*u +2055 174 m +2053.964 172.813 2053.662 172.397 2053 171 c +2054.849 171.967 2055.722 172 2055 174 c +f +*U +0.016 0.008 0.000 0.741 k +*u +2056 174 m +2057 173 l +2056 174 l +f +*U +0.000 0.408 0.286 0.329 k +*u +18 173 m +19 172 l +18 173 l +f +*U +0.000 0.627 0.471 0.373 k +*u +19 173 m +20 171.543 20.543 171 22 170 c +21 172 21 172 19 173 c +f +*U +0.000 0.365 0.306 0.635 k +*u +1049 173 m +1050 172 l +1049 173 l +f +*U +0.000 0.267 0.196 0.082 k +*u +1100 173 m +1101 172 l +1100 173 l +f +*U +0.000 0.698 0.553 0.302 k +*u +1101 173 m +1103.732 169 1106.678 166 1111 164 c +1108.464 168 1105.345 171 1101 173 c +f +*U +0.000 0.651 0.471 0.349 k +*u +1150 172 m +1151.551 170 1152.855 168.218 1154 166 c +1154.785 168.916 1153.644 170.511 1152 173 c +1150 172 l +f +*U +0.000 0.208 0.188 0.302 k +*u +1182 173 m +1183 172 l +1182 173 l +f +*U +0.000 0.714 0.514 0.286 k +*u +1183 171 m +1184.580 171.684 1184.777 171.805 1186 173 c +1183.907 172.594 1183.980 172.783 1183 171 c +f +*U +0.000 0.357 0.337 0.392 k +*u +1276 173 m +1277 172 l +1276 173 l +f +*U +0.000 0.141 0.114 0.145 k +*u +1289 173 m +1290 172 l +1289 173 l +f +*U +0.000 0.384 0.310 0.106 k +*u +1300 173 m +1301 172 l +1300 173 l +f +*U +0.000 0.004 0.000 0.298 k +*u +2056 173 m +2057 172 l +2056 173 l +f +*U +0.000 0.094 0.071 0.184 k +*u +19 172 m +20 171 l +19 172 l +f +*U +0.000 0.761 0.522 0.239 k +*u +22 172 m +23.382 169.580 24.363 168.939 27 168 c +25.410 169.752 24 170.794 22 172 c +f +*U +0.000 0.655 0.525 0.345 k +*u +1050.333 171.333 m +1050.278 171.278 1050.222 170.222 1050.667 170.667 c +1050.722 170.722 1050.778 171.778 1050.333 171.333 c +f +*U +0.000 0.106 0.110 0.278 k +*u +1181 172 m +1182 171 l +1181 172 l +f +*U +0.000 0.333 0.333 0.667 k +*u +1182 172 m +1183 171 l +1182 172 l +f +*U +0.000 0.294 0.184 0.165 k +*u +1248 172 m +1249 171 l +1248 172 l +f +*U +0.000 0.271 0.243 0.188 k +*u +1251 172 m +1252 171 l +1251 172 l +f +*U +0.000 0.514 0.408 0.478 k +*u +1276 172 m +1276 169 l +1276.696 170.554 1276.696 170.446 1276 172 c +f +*U +0.000 0.322 0.271 0.424 k +*u +1287 172 m +1288 171 l +1287 172 l +f +*U +0.000 0.631 0.475 0.369 k +*u +1288 172 m +1289.248 171.315 1289.548 171.251 1291 171 c +1289.751 171.685 1289.452 171.749 1288 172 c +f +*U +0.000 0.361 0.267 0.220 k +*u +1291 172 m +1292 171 l +1291 172 l +f +*U +0.000 0.118 0.176 0.267 k +*u +1299 172 m +1300 171 l +1299 172 l +f +*U +0.000 0.275 0.275 0.725 k +*u +1300 172 m +1301 171 l +1300 172 l +f +*U +0.000 0.392 0.298 0.239 k +*u +1412 172 m +1413 171 l +1412 172 l +f +*U +0.000 0.341 0.231 0.314 k +*u +2054 172 m +2055 171 l +2054 172 l +f +*U +0.000 0.412 0.306 0.235 k +*u +1051 171 m +1052 170 l +1051 171 l +f +*U +0.000 0.800 0.784 0.122 k +*u +1182 171 m +1183 168 l +1183.685 169.249 1183.749 169.548 1184 171 c +1182 171 l +f +*U +0.000 0.557 0.435 0.443 k +*u +1248 171 m +1249.506 170.317 1250.315 170.174 1252 170 c +1250.494 170.683 1249.685 170.826 1248 171 c +f +*U +0.000 0.212 0.196 0.137 k +*u +1286 171 m +1287 170 l +1286 171 l +f +*U +0.000 0.478 0.408 0.498 k +*u +1287 171 m +1288 170 l +1287 171 l +f +*U +0.000 0.937 0.678 0.063 k +*u +1288 171 m +1287 164 l +1291 164 l +1291.262 166.428 1291.262 168.572 1291 171 c +1288 171 l +f +*U +0.000 0.627 0.475 0.373 k +*u +1291 171 m +1291 168 l +1291.696 169.554 1291.696 169.446 1291 171 c +f +*U +0.000 0.294 0.220 0.271 k +*u +1292 171 m +1293 170 l +1292 171 l +f +*U +0.000 0.294 0.208 0.314 k +*u +1300 171 m +1301 170 l +1300 171 l +f +*U +0.000 0.478 0.427 0.522 k +*u +1301 171 m +1302 170 l +1301 171 l +f +*U +0.000 0.475 0.349 0.412 k +*u +2051.667 170.667 m +2051.223 170.223 2052.278 170.278 2052.333 170.333 c +2052.778 170.778 2051.722 170.722 2051.667 170.667 c +f +*U +0.000 0.275 0.176 0.102 k +*u +2053 171 m +2054 170 l +2053 171 l +f +*U +0.000 0.114 0.090 0.173 k +*u +22 170 m +23 169 l +22 170 l +f +*U +0.000 0.337 0.247 0.027 k +*u +1052 170 m +1053 169 l +1052 170 l +f +*U +0.000 0.184 0.157 0.078 k +*u +1103 170 m +1104 169 l +1103 170 l +f +*U +0.000 0.353 0.255 0.204 k +*u +1154 170 m +1155 169 l +1154 170 l +f +*U +0.000 0.396 0.412 0.075 k +*u +1182.333 169.333 m +1182.278 169.278 1182.222 168.222 1182.667 168.667 c +1182.722 168.722 1182.778 169.778 1182.333 169.333 c +f +*U +0.000 0.322 0.208 0.059 k +*u +1277 170 m +1277 167 l +1277.696 168.554 1277.696 168.446 1277 170 c +f +*U +0.000 0.314 0.275 0.290 k +*u +1286 170 m +1287 169 l +1286 170 l +f +*U +0.000 0.722 0.596 0.278 k +*u +1287.333 169.333 m +1287.278 169.278 1287.222 168.222 1287.667 168.667 c +1287.722 168.722 1287.778 169.778 1287.333 169.333 c +f +*U +0.000 0.522 0.376 0.400 k +*u +1292 170 m +1292 165 l +1292.830 167 1292.830 167.969 1292 170 c +f +*U +0.000 0.667 0.592 0.333 k +*u +1302.667 169.667 m +1302.222 169.222 1303.278 169.278 1303.333 169.333 c +1303.778 169.778 1302.722 169.722 1302.667 169.667 c +f +*U +0.000 0.584 0.427 0.349 k +*u +2049 170 m +2048 168 l +2050 168 l +2050 169.853 2050.300 169.350 2049 170 c +f +*U +0.000 0.396 0.380 0.604 k +*u +2050 170 m +2051 169 l +2050 170 l +f +*U +0.000 0.310 0.255 0.290 k +*u +2051 170 m +2052 169 l +2051 170 l +f +*U +0.000 0.686 0.506 0.031 k +*u +24 169 m +25 168 l +24 169 l +f +*U +0.000 0.882 0.635 0.118 k +*u +54 169 m +60.919 166 71.520 168 79 168 c +136 168 l +333 168 l +1016 168 l +1009 170.903 998.480 169 991 169 c +934 169 l +737 169 l +54 169 l +f +*U +0.000 0.655 0.455 0.314 k +*u +1052 169 m +1053.523 164.519 1056.174 161.720 1060 159 c +1058 163 1055.451 166.215 1052 169 c +f +*U +0.000 0.584 0.337 0.000 k +*u +1104 169 m +1105 168 l +1104 169 l +f +*U +0.000 0.478 0.380 0.522 k +*u +1286 169 m +1286 163 l +1286.951 165.285 1286.951 166.715 1286 169 c +f +*U +0.000 0.361 0.282 0.243 k +*u +1303 169 m +1304 168 l +1303 169 l +f +*U +0.431 0.000 0.184 0.000 k +*u +1344 169 m +1345 168 l +1344 169 l +f +*U +0.000 0.263 0.212 0.220 k +*u +1410 169 m +1411 168 l +1410 169 l +f +*U +0.000 0.882 0.635 0.118 k +*u +1449 169 m +1453.469 167 1459.191 168 1464 168 c +1494 168 l +1600 168 l +1967 168 l +1962.531 169.875 1956.809 169 1952 169 c +1922 169 l +1816 169 l +1449 169 l +f +*U +0.000 0.282 0.220 0.082 k +*u +2050 169 m +2051 168 l +2050 169 l +f +*U +0.000 0.204 0.133 0.118 k +*u +26 168 m +27 167 l +26 168 l +f +*U +0.000 0.510 0.431 0.490 k +*u +27.667 167.667 m +27.222 167.222 28.278 167.278 28.333 167.333 c +28.778 167.778 27.722 167.722 27.667 167.667 c +f +*U +0.000 0.882 0.627 0.118 k +*u +48 168 m +55.782 163.635 65.383 165 74 165 c +125 165 l +317 165 l +1020 165 l +1012.841 168 1001.744 166 994 166 c +937 166 l +737 166 l +512.682 166 288.312 164.556 64 166 c +58.486 166 53.541 167.981 48 168 c +f +*U +0.000 0.831 0.600 0.149 k +*u +56 168 m +63 164.996 74.256 167 82 167 c +139 167 l +337 167 l +1026 167 l +1018.841 170 1007.744 168 1000 168 c +943 168 l +744 168 l +56 168 l +f +*U +0.000 0.478 0.373 0.502 k +*u +1276 168 m +1276 165 l +1276.696 166.554 1276.696 166.446 1276 168 c +f +*U +0.000 0.078 0.047 0.184 k +*u +1285 168 m +1286 167 l +1285 168 l +f +*U +0.000 0.388 0.243 0.188 k +*u +1304 168 m +1305 167 l +1304 168 l +f +*U +0.000 0.467 0.467 0.533 k +*u +1341 168 m +1342 167 l +1341 168 l +f +*U +0.000 0.251 0.259 0.435 k +*u +1342 168 m +1343 167 l +1342 168 l +f +*U +0.000 0.310 0.267 0.129 k +*u +1409 168 m +1410 167 l +1409 168 l +f +*U +0.000 0.561 0.427 0.357 k +*u +1410 168 m +1409 166.521 1409 166.797 1409 165 c +1410.289 166.443 1410.401 166.234 1410 168 c +f +*U +0.000 0.831 0.600 0.149 k +*u +1448 168 m +1452.469 166 1458.191 167 1463 167 c +1494 167 l +1600 167 l +1968 167 l +1963.531 168.875 1957.809 168 1953 168 c +1922 168 l +1816 168 l +1448 168 l +f +*U +0.000 0.737 0.561 0.263 k +*u +2042 164 m +2044.222 164.810 2045.990 165.739 2048 167 c +2045 167.698 2043.578 166.511 2042 164 c +f +*U +0.063 0.000 0.012 0.278 k +*u +2048 168 m +2049 167 l +2048 168 l +f +*U +0.000 0.259 0.196 0.106 k +*u +28 167 m +29 166 l +28 167 l +f +*U +0.000 0.502 0.420 0.498 k +*u +29.667 166.667 m +29.222 166.222 30.278 166.278 30.333 166.333 c +30.778 166.778 29.722 166.722 29.667 166.667 c +f +*U +0.000 0.906 0.655 0.094 k +*u +56 167 m +63 163.996 74.256 166 82 166 c +139 166 l +337 166 l +1024 166 l +1016.841 169 1005.744 167 998 167 c +941 167 l +743 167 l +56 167 l +f +*U +0.000 0.208 0.247 0.267 k +*u +1155 167 m +1156 166 l +1155 167 l +f +*U +0.000 0.345 0.263 0.212 k +*u +1180.667 166.667 m +1180.222 166.222 1181.278 166.278 1181.333 166.333 c +1181.778 166.778 1180.722 166.722 1180.667 166.667 c +f +*U +0.000 0.667 0.494 0.333 k +*u +1291 167 m +1289.774 164.965 1289.298 164.674 1287 164 c +1288.769 163.221 1290 163 1292 163 c +1291.826 164.685 1291.683 165.494 1291 167 c +f +*U +0.000 0.482 0.447 0.118 k +*u +1306 167 m +1307 166 l +1306 167 l +f +*U +0.000 0.412 0.345 0.412 k +*u +1340.667 166.667 m +1340.222 166.222 1341.278 166.278 1341.333 166.333 c +1341.778 166.778 1340.722 166.722 1340.667 166.667 c +f +*U +0.000 0.906 0.655 0.094 k +*u +1448 167 m +1452.469 165 1458.191 166 1463 166 c +1494 166 l +1600 166 l +1968 166 l +1963.531 167.875 1957.809 167 1953 167 c +1922 167 l +1816 167 l +1448 167 l +f +*U +0.000 0.220 0.176 0.102 k +*u +31 166 m +32 165 l +31 166 l +f +*U +0.000 0.584 0.424 0.400 k +*u +32 166 m +33.248 165.315 33.548 165.251 35 165 c +33.752 165.685 33.452 165.749 32 166 c +f +*U +0.000 0.400 0.286 0.212 k +*u +1055 166 m +1056 165 l +1055 166 l +f +*U +0.000 0.580 0.459 0.349 k +*u +1155.333 165.333 m +1155.278 165.278 1155.222 164.222 1155.667 164.667 c +1155.722 164.722 1155.778 165.778 1155.333 165.333 c +f +*U +0.000 0.553 0.467 0.447 k +*u +1178 163 m +1181 165 l +1178.860 166 1178.473 165.251 1178 163 c +f +*U +0.000 0.290 0.345 0.243 k +*u +1304 166 m +1305 165 l +1304 166 l +f +*U +0.000 0.592 0.490 0.333 k +*u +1305.667 165.667 m +1305.222 165.222 1306.278 165.278 1306.333 165.333 c +1306.778 165.778 1305.722 165.722 1305.667 165.667 c +f +*U +0.000 0.573 0.482 0.427 k +*u +1339 166 m +1340 165 l +1339 166 l +f +*U +0.000 0.318 0.271 0.259 k +*u +1340 166 m +1341 165 l +1340 166 l +f +*U +0.000 0.408 0.329 0.247 k +*u +1408 166 m +1409 165 l +1408 166 l +f +*U +0.000 0.882 0.627 0.118 k +*u +1448 166 m +1452.469 164 1458.191 165 1463 165 c +1493 165 l +1597 165 l +1851 165 l +1933 165 l +1945.430 165 1959.861 162.946 1972 165 c +1967.531 166.875 1961.809 166 1957 166 c +1926 166 l +1819 166 l +1448 166 l +f +*U +0.000 0.357 0.278 0.125 k +*u +2045 166 m +2046 165 l +2045 166 l +f +*U +0.000 0.216 0.161 0.176 k +*u +34 165 m +35 164 l +34 165 l +f +*U +0.000 0.667 0.525 0.333 k +*u +35 165 m +36.769 164.221 38 164 40 164 c +38.231 164.779 36.964 164.912 35 165 c +f +*U +0.000 0.871 0.616 0.125 k +*u +56 165 m +61.707 162.605 69.846 164 76 164 c +120 164 l +273 164 l +803 164 l +974 164 l +988.325 164 1002.677 164.265 1016.999 163.995 c +1022.983 163.883 1026.670 158.761 1032 163 c +1024.402 166.657 1014.282 165 1006 165 c +951 165 l +755 165 l +56 165 l +f +*U +0.000 0.094 0.086 0.192 k +*u +1056 165 m +1057 164 l +1056 165 l +f +*U +0.000 0.255 0.176 0.118 k +*u +1177.333 164.333 m +1177.278 164.278 1177.222 163.222 1177.667 163.667 c +1177.722 163.722 1177.778 164.778 1177.333 164.333 c +f +*U +0.000 0.992 0.753 0.000 k +*u +1179 165 m +1180.506 164.317 1181.315 164.174 1183 164 c +1181.494 164.683 1180.685 164.826 1179 165 c +f +*U +0.000 0.490 0.345 0.490 k +*u +1275.333 164.333 m +1275.278 164.278 1275.222 163.222 1275.667 163.667 c +1275.722 163.722 1275.778 164.778 1275.333 164.333 c +f +*U +0.000 0.369 0.267 0.231 k +*u +1276 165 m +1277 164 l +1276 165 l +f +*U +0.000 0.302 0.231 0.267 k +*u +1292.333 164.333 m +1292.278 164.278 1292.222 163.222 1292.667 163.667 c +1292.722 163.722 1292.778 164.778 1292.333 164.333 c +f +*U +0.000 0.329 0.267 0.196 k +*u +1301 165 m +1302 164 l +1301 165 l +f +*U +0.000 0.706 0.678 0.251 k +*u +1299 164 m +1301 163 1302.747 163 1305 163 c +1302.817 164.430 1301.625 164.328 1299 164 c +f +*U +0.000 0.729 0.549 0.271 k +*u +1310 164 m +1316.988 161 1331.781 161.866 1339 164 c +1330.505 166 1318.899 164 1310 164 c +f +*U +0.000 0.325 0.278 0.384 k +*u +1339 165 m +1340 164 l +1339 165 l +f +*U +0.000 0.192 0.125 0.129 k +*u +1407 165 m +1408 164 l +1407 165 l +f +*U +0.000 0.871 0.616 0.125 k +*u +1448 165 m +1452.469 163 1458.191 164 1463 164 c +1494 164 l +1600 164 l +1969 164 l +1964.531 165.875 1958.809 165 1954 165 c +1923 165 l +1817 165 l +1448 165 l +f +*U +0.000 0.259 0.188 0.224 k +*u +38.667 163.667 m +38.222 163.222 39.278 163.278 39.333 163.333 c +39.778 163.778 38.722 163.722 38.667 163.667 c +f +*U +0.000 0.608 0.478 0.392 k +*u +40 164 m +41.769 163.221 43 163 45 163 c +43.231 163.779 41.964 163.912 40 164 c +f +*U +0.000 0.729 0.549 0.271 k +*u +45 164 m +52 160.996 63.256 163 71 163 c +129 163 l +329 163 l +1024 163 l +1016.841 166 1005.744 164 998 164 c +940 164 l +740 164 l +45 164 l +f +*U +0.000 0.408 0.294 0.306 k +*u +1110 164 m +1111 163 l +1110 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1112 164 m +1116.215 162.231 1121.464 163 1126 163 c +1155 163 l +1150.785 164.769 1145.536 164 1141 164 c +1112 164 l +f +*U +0.000 0.408 0.408 0.592 k +*u +1155 164 m +1156 163 l +1155 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1179 164 m +1186.879 160.694 1199.466 163 1208 163 c +1275 163 l +1267 166.306 1254.534 164 1246 164 c +1179 164 l +f +*U +0.000 0.161 0.180 0.192 k +*u +1298.333 163.333 m +1298.278 163.278 1298.222 162.222 1298.667 162.667 c +1298.722 162.722 1298.778 163.778 1298.333 163.333 c +f +*U +0.000 0.749 0.804 0.118 k +*u +1305 164 m +1306.248 163.315 1306.548 163.251 1308 163 c +1306.752 163.685 1306.452 163.749 1305 164 c +f +*U +0.000 0.275 0.235 0.216 k +*u +1338 164 m +1339 163 l +1338 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1438 162 m +1445 163.695 1452.719 163 1460 163 c +1495 163 l +1609 163 l +1973 163 l +1973 120 l +1974.875 124.469 1974 130.191 1974 135 c +1974 164 l +1571 164 l +1472 164 l +1448 164 l +1444.483 164.000 1440.435 164.786 1438 162 c +f +*U +0.000 0.596 0.471 0.404 k +*u +2040 164 m +2040 162 l +2041.635 162.545 2041.455 162.365 2042 164 c +2040 164 l +f +*U +0.000 0.318 0.227 0.051 k +*u +2042 164 m +2043 163 l +2042 164 l +f +*U +0.000 0.176 0.125 0.157 k +*u +45.667 162.667 m +45.222 162.222 46.278 162.278 46.333 162.333 c +46.778 162.778 45.722 162.722 45.667 162.667 c +f +*U +0.000 0.384 0.290 0.129 k +*u +47 163 m +54 159.996 65.256 162 73 162 c +130 162 l +329 162 l +1020 162 l +1012.841 165 1001.744 163 994 163 c +937 163 l +738 163 l +47 163 l +f +*U +0.000 0.361 0.271 0.227 k +*u +1020 163 m +1021.506 162.317 1022.315 162.174 1024 162 c +1022.494 162.683 1021.685 162.826 1020 163 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1111 163 m +1115.469 161 1121.192 162 1126 162 c +1155 162 l +1150.531 163.875 1144.809 163 1140 163 c +1111 163 l +f +*U +0.000 0.263 0.204 0.361 k +*u +1155 163 m +1156 162 l +1155 163 l +f +*U +0.000 0.384 0.290 0.129 k +*u +1178 163 m +1186 159.593 1199.203 162 1208 162 c +1276 162 l +1267.882 165.407 1254.797 163 1246 163 c +1178 163 l +f +*U +0.000 0.271 0.231 0.255 k +*u +1286 163 m +1288 162 1289.747 162 1292 162 c +1289.948 162.874 1288.253 162.953 1286 163 c +f +*U +0.000 0.106 0.090 0.208 k +*u +1292 163 m +1293 162 l +1292 163 l +f +*U +0.000 0.412 0.455 0.141 k +*u +1299 163 m +1300.506 162.317 1301.315 162.174 1303 162 c +1301.494 162.683 1300.685 162.826 1299 163 c +f +*U +0.000 0.290 0.325 0.184 k +*u +1303 163 m +1305.890 161.787 1308.874 162 1312 162 c +1309 163.213 1306 162.998 1303 163 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1312 163 m +1319.169 159.992 1330.239 162 1338 162 c +1330.831 165 1319.761 163 1312 163 c +f +*U +0.000 0.522 0.380 0.431 k +*u +1437.333 162.333 m +1437.278 162.278 1437.222 161.222 1437.667 161.667 c +1437.722 161.722 1437.778 162.778 1437.333 162.333 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1439 163 m +1443.720 161 1449.920 162 1455 162 c +1486 162 l +1595 162 l +1973 162 l +1968.280 163.980 1962 163 1957 163 c +1926 163 l +1817 163 l +1439 163 l +f +*U +0.000 0.286 0.212 0.118 k +*u +1024 162 m +1025 161 l +1024 162 l +f +*U +0.000 0.424 0.282 0.251 k +*u +1405 162 m +1406 161 l +1405 162 l +f +*U +0.000 0.725 0.518 0.275 k +*u +1436.333 161.333 m +1436.278 161.278 1436.223 160.222 1436.667 160.667 c +1436.722 160.722 1436.778 161.778 1436.333 161.333 c +f +*U +0.000 0.275 0.200 0.102 k +*u +1438 162 m +1439 161 l +1438 162 l +f +*U +0.000 0.435 0.329 0.380 k +*u +2037 162 m +2037 160 l +2038.635 160.545 2038.455 160.365 2039 162 c +2037 162 l +f +*U +0.000 0.353 0.282 0.043 k +*u +2039 162 m +2040 161 l +2039 162 l +f +*U +0.020 0.000 0.027 0.000 k +*u +56 161 m +63 157.996 74.256 160 82 160 c +139 160 l +337 160 l +1023 160 l +1015.841 163 1004.744 161 997 161 c +940 161 l +742 161 l +56 161 l +f +*U +0.000 0.333 0.243 0.376 k +*u +1025 161 m +1026 160 l +1025 161 l +f +*U +0.000 0.243 0.157 0.122 k +*u +1404 161 m +1405 160 l +1404 161 l +f +*U +0.000 0.408 0.294 0.247 k +*u +1437 161 m +1438 160 l +1437 161 l +f +*U +0.020 0.000 0.027 0.000 k +*u +1440 161 m +1444.469 159 1450.191 160 1455 160 c +1486 160 l +1595 160 l +1971 160 l +1971 128 l +1972.552 131.699 1972 136 1972 140 c +1972 161 l +1440 161 l +f +*U +0.000 0.514 0.463 0.486 k +*u +2036 161 m +2037 160 l +2036 161 l +f +*U +0.000 0.290 0.235 0.439 k +*u +1026 160 m +1027 159 l +1026 160 l +f +*U +0.000 0.498 0.373 0.408 k +*u +1027.333 159.333 m +1027.278 159.278 1027.222 158.222 1027.667 158.667 c +1027.722 158.722 1027.778 159.778 1027.333 159.333 c +f +*U +0.000 0.400 0.333 0.220 k +*u +1060 160 m +1061 159 l +1060 160 l +f +*U +0.000 0.600 0.486 0.400 k +*u +1404 160 m +1403 158.521 1403 158.797 1403 157 c +1404.289 158.443 1404.401 158.234 1404 160 c +f +*U +0.000 0.400 0.325 0.447 k +*u +1435.667 159.667 m +1435.222 159.222 1436.278 159.278 1436.333 159.333 c +1436.778 159.778 1435.722 159.722 1435.667 159.667 c +f +*U +0.000 0.694 0.478 0.282 k +*u +1974 160 m +1974 122 l +1977 129.399 1975 140.993 1975 149 c +1975 152.702 1975.441 156.566 1974 160 c +f +*U +0.000 0.259 0.165 0.565 k +*u +2034.667 159.667 m +2034.222 159.222 2035.278 159.278 2035.333 159.333 c +2035.778 159.778 2034.722 159.722 2034.667 159.667 c +f +*U +0.000 0.051 0.031 0.192 k +*u +2036 160 m +2037 159 l +2036 160 l +f +*U +0.000 0.749 0.553 0.251 k +*u +1060 159 m +1061 155 l +1061.553 157 1061.303 157.332 1060 159 c +f +*U +0.000 0.314 0.243 0.271 k +*u +1061 159 m +1062 158 l +1061 159 l +f +*U +0.000 0.420 0.416 0.580 k +*u +1435 159 m +1436 158 l +1435 159 l +f +*U +0.000 0.510 0.373 0.490 k +*u +2032 159 m +2032 157 l +2033.635 157.545 2033.455 157.365 2034 159 c +2032 159 l +f +*U +0.000 0.376 0.255 0.267 k +*u +2034 159 m +2035 158 l +2034 159 l +f +*U +0.000 0.157 0.133 0.188 k +*u +1027 158 m +1028 157 l +1027 158 l +f +*U +0.000 0.420 0.384 0.580 k +*u +1028 158 m +1029 157 l +1028 158 l +f +*U +0.000 0.251 0.184 0.133 k +*u +1062 158 m +1063 157 l +1062 158 l +f +*U +0.000 0.392 0.302 0.357 k +*u +1402 158 m +1403 157 l +1402 158 l +f +*U +0.000 0.533 0.396 0.384 k +*u +1434.333 157.333 m +1434.278 157.278 1434.222 156.222 1434.667 156.667 c +1434.722 156.722 1434.778 157.778 1434.333 157.333 c +f +*U +0.000 0.325 0.267 0.263 k +*u +1435 158 m +1436 157 l +1435 158 l +f +*U +0.000 0.227 0.180 0.357 k +*u +1028 157 m +1029 156 l +1028 157 l +f +*U +0.000 0.624 0.490 0.376 k +*u +1062 157 m +1063.324 154.313 1064.313 153.324 1067 152 c +1065.451 154 1064 155.451 1062 157 c +f +*U +0.000 0.267 0.200 0.165 k +*u +1063 157 m +1064 156 l +1063 157 l +f +*U +0.000 0.290 0.235 0.227 k +*u +1401 157 m +1402 156 l +1401 157 l +f +*U +0.000 0.569 0.467 0.431 k +*u +1402 157 m +1403 156 l +1402 157 l +f +*U +0.000 0.471 0.420 0.529 k +*u +2030 157 m +2031 156 l +2030 157 l +f +*U +0.000 0.388 0.329 0.110 k +*u +2031 157 m +2032 156 l +2031 157 l +f +*U +0.000 0.427 0.345 0.114 k +*u +1400 156 m +1401 155 l +1400 156 l +f +*U +0.000 0.537 0.420 0.463 k +*u +1433 156 m +1434 155 l +1433 156 l +f +*U +0.000 0.200 0.165 0.129 k +*u +1434 156 m +1435 155 l +1434 156 l +f +*U +0.000 0.361 0.294 0.357 k +*u +2029 156 m +2030 155 l +2029 156 l +f +*U +0.000 0.216 0.141 0.173 k +*u +1399 155 m +1400 154 l +1399 155 l +f +*U +0.000 0.298 0.251 0.243 k +*u +1433 155 m +1434 154 l +1433 155 l +f +*U +0.000 0.494 0.376 0.498 k +*u +2027 155 m +2028 154 l +2027 155 l +f +*U +0.000 0.192 0.169 0.157 k +*u +2028 155 m +2029 154 l +2028 155 l +f +*U +0.000 0.267 0.196 0.110 k +*u +1030 154 m +1031 153 l +1030 154 l +f +*U +0.000 0.620 0.431 0.380 k +*u +1399.333 153.333 m +1399.278 153.278 1399.222 152.222 1399.667 152.667 c +1399.722 152.722 1399.778 153.778 1399.333 153.333 c +f +*U +0.000 0.612 0.561 0.388 k +*u +1431.333 153.333 m +1431.278 153.278 1431.222 152.222 1431.667 152.667 c +1431.722 152.722 1431.778 153.778 1431.333 153.333 c +f +*U +0.000 0.306 0.267 0.435 k +*u +1432 154 m +1433 153 l +1432 154 l +f +*U +0.000 0.396 0.306 0.365 k +*u +2026 154 m +2027 153 l +2026 154 l +f +*U +0.000 0.259 0.196 0.231 k +*u +1031 153 m +1032 152 l +1031 153 l +f +*U +0.000 0.427 0.271 0.349 k +*u +1398 153 m +1399 152 l +1398 153 l +f +*U +0.000 0.467 0.420 0.533 k +*u +2024 153 m +2025 152 l +2024 153 l +f +*U +0.000 0.392 0.294 0.012 k +*u +2025 153 m +2026 152 l +2025 153 l +f +*U +0.000 0.322 0.224 0.255 k +*u +1032 152 m +1033 151 l +1032 152 l +f +*U +0.000 0.384 0.365 0.616 k +*u +1033 152 m +1034 151 l +1033 152 l +f +*U +0.000 0.710 0.498 0.282 k +*u +1067 152 m +1067.684 149.791 1068 149.297 1070 148 c +1069 149.948 1068.607 150.550 1067 152 c +f +*U +0.000 0.180 0.129 0.188 k +*u +1125 152 m +1126 151 l +1125 152 l +f +*U +0.000 0.616 0.455 0.373 k +*u +1126 152 m +1130.564 149.361 1138.689 151 1144 151 c +1138.777 153.191 1131.632 152 1126 152 c +f +*U +0.000 0.522 0.400 0.447 k +*u +1144 152 m +1147.959 150.339 1152.740 151 1157 151 c +1180 151 l +1176 152.661 1171.260 152 1167 152 c +1144 152 l +f +*U +0.000 0.718 0.545 0.282 k +*u +1180 152 m +1181.458 150.919 1182.248 150.564 1184 150 c +1182.686 151.618 1182 151.693 1180 152 c +f +*U +0.000 0.000 0.000 0.298 k +*u +1214.667 151.667 m +1214.222 151.222 1215.278 151.278 1215.333 151.333 c +1215.778 151.778 1214.722 151.722 1214.667 151.667 c +f +*U +0.000 0.145 0.114 0.180 k +*u +1233 152 m +1234 151 l +1233 152 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1234 152 m +1235 151 l +1234 152 l +f +*U +0.000 0.529 0.384 0.467 k +*u +1235.333 151.333 m +1235.278 151.278 1235.222 150.222 1235.667 150.667 c +1235.722 150.722 1235.778 151.778 1235.333 151.333 c +f +*U +0.000 0.741 0.529 0.251 k +*u +1236 152 m +1236.307 149.877 1236.382 149.314 1238 148 c +1237.404 149.560 1236.911 150.623 1236 152 c +f +*U +0.000 0.616 0.463 0.376 k +*u +1237 152 m +1242.469 149.705 1250 151 1256 151 c +1250.531 153.295 1242.901 152 1237 152 c +f +*U +0.000 0.522 0.400 0.447 k +*u +1256 152 m +1261.707 149.605 1269.846 151 1276 151 c +1290.998 151 1307.230 152.742 1322 150 c +1318.696 153.781 1309.740 152 1305 152 c +1256 152 l +f +*U +0.000 0.278 0.251 0.722 k +*u +1322 152 m +1323 151 l +1322 152 l +f +*U +0.000 0.145 0.094 0.333 k +*u +1323 152 m +1324 151 l +1323 152 l +f +*U +0.000 0.804 0.600 0.196 k +*u +1397 152 m +1395.998 149.386 1395.678 147.773 1396 145 c +1399 146 l +1397 149 l +1398.924 150 1399 150 1400 152 c +1397 152 l +f +*U +0.000 0.455 0.463 0.490 k +*u +1430 152 m +1431 151 l +1430 152 l +f +*U +0.110 0.000 0.071 0.133 k +*u +1431 152 m +1432 151 l +1431 152 l +f +*U +0.000 0.514 0.337 0.486 k +*u +2022 152 m +2023 151 l +2022 152 l +f +*U +0.000 0.349 0.204 0.290 k +*u +2023 152 m +2024 151 l +2023 152 l +f +*U +0.000 0.263 0.184 0.325 k +*u +1126 151 m +1127 150 l +1126 151 l +f +*U +0.000 0.894 0.651 0.106 k +*u +1128 151 m +1131.547 146.985 1139.689 140.968 1145 139.938 c +1151 138.752 1158.724 140 1165 140 c +1205 140 l +1205 142 l +1202.214 142.355 1199.684 143.535 1196.911 143.871 c +1193.952 144.229 1190.807 143.588 1188 145 c +1184.936 146.650 1183.611 150 1179.946 150.772 c +1174.300 151.876 1167.742 151 1162 151 c +1128 151 l +f +*U +0.000 0.243 0.176 0.090 k +*u +1234 151 m +1235 150 l +1234 151 l +f +*U +0.000 0.882 0.635 0.118 k +*u +1237 151 m +1238.959 144.618 1244.912 145.185 1248 140 c +1265.500 140 1284.675 137.762 1302 140 c +1307.844 140.959 1317 145.842 1320 151 c +1237 151 l +f +*U +0.000 0.263 0.176 0.133 k +*u +1322 151 m +1323 150 l +1322 151 l +f +*U +0.000 0.341 0.282 0.286 k +*u +1396 151 m +1397 150 l +1396 151 l +f +*U +0.000 0.306 0.345 0.365 k +*u +1430 151 m +1431 150 l +1430 151 l +f +*U +0.000 0.545 0.451 0.455 k +*u +1034 150 m +1035 149 l +1034 150 l +f +*U +0.000 0.698 0.510 0.278 k +*u +1128.667 149.667 m +1128.222 149.222 1129.278 149.278 1129.333 149.333 c +1129.778 149.778 1128.722 149.722 1128.667 149.667 c +f +*U +0.000 0.282 0.208 0.224 k +*u +1235 150 m +1236 149 l +1235 150 l +f +*U +0.000 0.275 0.180 0.329 k +*u +1320 150 m +1321 149 l +1320 150 l +f +*U +0.000 0.286 0.208 0.369 k +*u +1395 150 m +1396 149 l +1395 150 l +f +*U +0.000 0.310 0.231 0.396 k +*u +1429 150 m +1430 149 l +1429 150 l +f +*U +0.000 0.384 0.267 0.259 k +*u +2020 150 m +2021 149 l +2020 150 l +f +*U +0.000 0.294 0.212 0.176 k +*u +1034 149 m +1035 148 l +1034 149 l +f +*U +0.000 0.349 0.271 0.243 k +*u +1070 149 m +1071 148 l +1070 149 l +f +*U +0.000 0.282 0.220 0.204 k +*u +1129 149 m +1130 148 l +1129 149 l +f +*U +0.000 0.224 0.169 0.443 k +*u +1184 149 m +1185 148 l +1184 149 l +f +*U +0.000 0.459 0.302 0.525 k +*u +1317.667 148.667 m +1317.222 148.222 1318.278 148.278 1318.333 148.333 c +1318.778 148.778 1317.722 148.722 1317.667 148.667 c +f +*U +0.000 0.278 0.141 0.086 k +*u +1319 149 m +1320 148 l +1319 149 l +f +*U +0.000 0.271 0.180 0.204 k +*u +1394 149 m +1395 148 l +1394 149 l +f +*U +0.000 0.651 0.494 0.349 k +*u +1427 149 m +1427 147 l +1428.635 147.545 1428.455 147.365 1429 149 c +1427 149 l +f +*U +0.000 0.553 0.384 0.380 k +*u +2017.667 148.667 m +2017.222 148.222 2018.278 148.278 2018.333 148.333 c +2018.778 148.778 2017.722 148.722 2017.667 148.667 c +f +*U +0.000 0.247 0.169 0.110 k +*u +2019 149 m +2020 148 l +2019 149 l +f +*U +0.000 0.306 0.224 0.259 k +*u +1035 148 m +1036 147 l +1035 148 l +f +*U +0.000 0.486 0.365 0.125 k +*u +1071 148 m +1072 147 l +1071 148 l +f +*U +0.000 0.420 0.314 0.275 k +*u +1131 148 m +1132 147 l +1131 148 l +f +*U +0.000 0.553 0.361 0.412 k +*u +1184 148 m +1188 143.180 1193.174 144 1199 144 c +1194.338 145.956 1188.933 146 1184 148 c +f +*U +0.000 0.200 0.165 0.165 k +*u +1236 148 m +1237 147 l +1236 148 l +f +*U +0.000 0.431 0.325 0.424 k +*u +1237 148 m +1237.684 146.420 1237.805 146.223 1239 145 c +1238.316 146.580 1238.195 146.777 1237 148 c +f +*U +0.000 0.318 0.251 0.431 k +*u +1317 148 m +1318 147 l +1317 148 l +f +*U +0.000 0.306 0.204 0.188 k +*u +1393 148 m +1394 147 l +1393 148 l +f +*U +0.000 0.522 0.404 0.478 k +*u +1394 148 m +1395 147 l +1394 148 l +f +*U +0.000 0.278 0.231 0.102 k +*u +1428 148 m +1429 147 l +1428 148 l +f +*U +0.000 0.380 0.259 0.290 k +*u +2017 148 m +2018 147 l +2017 148 l +f +*U +0.000 0.208 0.161 0.306 k +*u +1036 147 m +1037 146 l +1036 147 l +f +*U +0.000 0.243 0.212 0.416 k +*u +1072 147 m +1073 146 l +1072 147 l +f +*U +0.000 0.255 0.204 0.133 k +*u +1132 147 m +1133 146 l +1132 147 l +f +*U +0.000 0.714 0.537 0.286 k +*u +1133.667 146.667 m +1133.222 146.222 1134.278 146.278 1134.333 146.333 c +1134.778 146.778 1133.722 146.722 1133.667 146.667 c +f +*U +0.000 0.196 0.184 0.153 k +*u +1316 147 m +1317 146 l +1316 147 l +f +*U +0.000 0.400 0.290 0.035 k +*u +1392 147 m +1393 146 l +1392 147 l +f +*U +0.000 0.718 0.545 0.282 k +*u +1393 147 m +1392 145 l +1394 145 l +1394 146.853 1394.300 146.350 1393 147 c +f +*U +0.000 0.667 0.424 0.333 k +*u +1425 147 m +1425 144 l +1426.195 145.223 1426.316 145.420 1427 147 c +1425 147 l +f +*U +0.000 0.361 0.275 0.184 k +*u +1427 147 m +1428 146 l +1427 147 l +f +*U +0.000 0.204 0.133 0.122 k +*u +2016 147 m +2017 146 l +2016 147 l +f +*U +0.000 0.412 0.306 0.282 k +*u +1037 146 m +1038 145 l +1037 146 l +f +*U +0.000 0.565 0.467 0.435 k +*u +1072 146 m +1073 145 l +1072 146 l +f +*U +0.000 0.412 0.341 0.141 k +*u +1073 146 m +1074 145 l +1073 146 l +f +*U +0.000 0.306 0.243 0.216 k +*u +1134 146 m +1135 145 l +1134 146 l +f +*U +0.000 0.475 0.392 0.525 k +*u +1135 146 m +1136 145 l +1135 146 l +f +*U +0.000 0.102 0.067 0.227 k +*u +1195 146 m +1196.248 145.315 1196.549 145.251 1198 145 c +1196.751 145.685 1196.452 145.749 1195 146 c +f +*U +0.000 0.200 0.173 0.329 k +*u +1237 146 m +1238 145 l +1237 146 l +f +*U +0.000 0.592 0.498 0.408 k +*u +1313 146 m +1314 145 l +1313 146 l +f +*U +0.000 0.471 0.353 0.208 k +*u +1314 146 m +1315 145 l +1314 146 l +f +*U +0.000 0.506 0.396 0.451 k +*u +2012.667 145.667 m +2012.222 145.222 2013.278 145.278 2013.333 145.333 c +2013.778 145.778 2012.722 145.722 2012.667 145.667 c +f +*U +0.000 0.345 0.259 0.220 k +*u +2014 146 m +2015 145 l +2014 146 l +f +*U +0.000 0.569 0.467 0.431 k +*u +1073 145 m +1074 144 l +1073 145 l +f +*U +0.000 0.247 0.212 0.341 k +*u +1074 145 m +1075 144 l +1074 145 l +f +*U +0.000 0.114 0.129 0.125 k +*u +1135 145 m +1136 144 l +1135 145 l +f +*U +0.000 0.647 0.420 0.133 k +*u +1199 145 m +1200 144 l +1199 145 l +f +*U +0.000 0.180 0.169 0.153 k +*u +1238 145 m +1239 144 l +1238 145 l +f +*U +0.000 0.459 0.361 0.125 k +*u +1239 145 m +1240 144 l +1239 145 l +f +*U +0.000 0.580 0.486 0.420 k +*u +1240 145 m +1241.506 144.317 1242.315 144.174 1244 144 c +1242.494 144.683 1241.686 144.826 1240 145 c +f +*U +0.000 0.329 0.282 0.580 k +*u +1312 145 m +1313 144 l +1312 145 l +f +*U +0.000 0.224 0.141 0.584 k +*u +1391 145 m +1392 144 l +1391 145 l +f +*U +0.000 0.482 0.427 0.231 k +*u +2012 145 m +2013 144 l +2012 145 l +f +*U +0.000 0.188 0.118 0.671 k +*u +1039 144 m +1040 143 l +1039 144 l +f +*U +0.000 0.741 0.463 0.259 k +*u +1040 144 m +1040.684 142.420 1040.805 142.223 1042 141 c +1042 144 l +1040 144 l +f +*U +0.000 0.463 0.443 0.173 k +*u +1075 144 m +1076 143 l +1075 144 l +f +*U +0.000 0.192 0.137 0.294 k +*u +1137 144 m +1138 143 l +1137 144 l +f +*U +0.000 0.698 0.533 0.302 k +*u +1138.667 143.667 m +1138.222 143.222 1139.278 143.278 1139.333 143.333 c +1139.778 143.778 1138.722 143.722 1138.667 143.667 c +f +*U +0.000 0.067 0.114 0.302 k +*u +1200 144 m +1201 143 l +1200 144 l +f +*U +0.000 0.086 0.012 0.192 k +*u +1243 144 m +1244 143 l +1243 144 l +f +*U +0.000 0.290 0.161 0.376 k +*u +1244 144 m +1245 143 l +1244 144 l +f +*U +0.000 0.416 0.259 0.573 k +*u +1309.667 143.667 m +1309.222 143.222 1310.278 143.278 1310.333 143.333 c +1310.778 143.778 1309.722 143.722 1309.667 143.667 c +f +*U +0.000 0.337 0.180 0.039 k +*u +1311 144 m +1312 143 l +1311 144 l +f +*U +0.000 0.682 0.498 0.282 k +*u +1390 144 m +1387.794 141.748 1385.807 139.576 1384 137 c +1387 138.489 1390 140.283 1390 144 c +f +*U +0.000 0.243 0.149 0.686 k +*u +1424 144 m +1425 143 l +1424 144 l +f +*U +0.000 0.180 0.114 0.125 k +*u +1425 144 m +1426 143 l +1425 144 l +f +*U +0.000 0.443 0.286 0.463 k +*u +2009.667 143.667 m +2009.222 143.223 2010.277 143.277 2010.333 143.333 c +2010.778 143.778 2009.722 143.722 2009.667 143.667 c +f +*U +0.000 0.169 0.102 0.173 k +*u +2011 144 m +2012 143 l +2011 144 l +f +*U +0.000 0.180 0.118 0.176 k +*u +1039 143 m +1040 142 l +1039 143 l +f +*U +0.000 0.502 0.400 0.341 k +*u +1075 143 m +1076.223 141.805 1076.420 141.684 1078 141 c +1076.777 142.195 1076.580 142.316 1075 143 c +f +*U +0.000 0.365 0.263 0.247 k +*u +1139 143 m +1140 142 l +1139 143 l +f +*U +0.000 0.471 0.365 0.486 k +*u +1200 143 m +1201 142 l +1200 143 l +f +*U +0.000 0.420 0.329 0.259 k +*u +1201 143 m +1202 142 l +1201 143 l +f +*U +0.000 0.275 0.235 0.067 k +*u +1202 143 m +1203 142 l +1202 143 l +f +*U +0.000 0.137 0.110 0.122 k +*u +1210 143 m +1211 142 l +1210 143 l +f +*U +0.000 0.290 0.216 0.306 k +*u +1211 143 m +1212 142 l +1211 143 l +f +*U +0.000 0.537 0.467 0.431 k +*u +1212 143 m +1214 142 1215.747 142 1218 142 c +1215.948 142.874 1214.253 142.953 1212 143 c +f +*U +0.000 0.267 0.216 0.259 k +*u +1218 143 m +1219 142 l +1218 143 l +f +*U +0.000 0.349 0.224 0.000 k +*u +1245 143 m +1246 142 l +1245 143 l +f +*U +0.000 0.471 0.345 0.306 k +*u +1246 143 m +1246 140 l +1246.696 141.554 1246.696 141.446 1246 143 c +f +*U +0.000 0.576 0.435 0.353 k +*u +1247 143 m +1246 139 l +1247.656 140.404 1247.751 140.954 1247 143 c +f +*U +0.000 0.357 0.259 0.310 k +*u +1309 143 m +1310 142 l +1309 143 l +f +*U +0.000 0.161 0.098 0.263 k +*u +1424 143 m +1425 142 l +1424 143 l +f +*U +0.000 0.557 0.361 0.427 k +*u +2008 143 m +2009 142 l +2008 143 l +f +*U +0.000 0.478 0.322 0.098 k +*u +2009 143 m +2010 142 l +2009 143 l +f +*U +0.000 0.282 0.212 0.075 k +*u +1040 142 m +1041 141 l +1040 142 l +f +*U +0.000 0.329 0.239 0.055 k +*u +1140 142 m +1141 141 l +1140 142 l +f +*U +0.000 0.580 0.455 0.420 k +*u +1205 142 m +1206.769 141.221 1208 141 1210 141 c +1208.231 141.779 1206.964 141.912 1205 142 c +f +*U +0.000 0.945 0.667 0.055 k +*u +1205 141 m +1208.959 139.339 1213.737 140 1218 140 c +1218 142 l +1205 141 l +f +*U +0.000 0.667 0.522 0.333 k +*u +1218 142 m +1212.887 138 1203.218 140 1197 140 c +1146 140 l +1152.436 137.299 1162 139 1169 139 c +1220 139 l +1219.316 140.580 1219.195 140.777 1218 142 c +f +*U +0.000 0.329 0.251 0.075 k +*u +1219 142 m +1220 141 l +1219 142 l +f +*U +0.000 0.604 0.459 0.396 k +*u +1306 142 m +1307 141 l +1306 142 l +f +*U +0.000 0.361 0.298 0.396 k +*u +1307 142 m +1308 141 l +1307 142 l +f +*U +0.000 0.369 0.306 0.353 k +*u +1423 142 m +1424 141 l +1423 142 l +f +*U +0.000 0.659 0.471 0.341 k +*u +2006.667 141.667 m +2006.222 141.222 2007.278 141.278 2007.333 141.333 c +2007.778 141.778 2006.722 141.722 2006.667 141.667 c +f +*U +0.000 0.184 0.125 0.133 k +*u +2008 142 m +2009 141 l +2008 142 l +f +*U +0.000 0.361 0.337 0.086 k +*u +1041 141 m +1042 140 l +1041 141 l +f +*U +0.000 0.620 0.475 0.380 k +*u +1042 141 m +1043 140 l +1042 141 l +f +*U +0.000 0.706 0.490 0.294 k +*u +1077 141 m +1078.573 138.338 1080 137.228 1083 136 c +1081 138.447 1079.763 139.700 1077 141 c +f +*U +0.000 0.325 0.235 0.082 k +*u +1142 141 m +1143 140 l +1142 141 l +f +*U +0.000 0.443 0.337 0.188 k +*u +1220 141 m +1221 140 l +1220 141 l +f +*U +0.000 0.412 0.388 0.588 k +*u +1304 141 m +1305 140 l +1304 141 l +f +*U +0.000 0.420 0.318 0.380 k +*u +1305 141 m +1306 140 l +1305 141 l +f +*U +0.000 0.427 0.325 0.341 k +*u +1422 141 m +1423 140 l +1422 141 l +f +*U +0.000 0.439 0.431 0.561 k +*u +2005 141 m +2006 140 l +2005 141 l +f +*U +0.000 0.329 0.227 0.325 k +*u +2006 141 m +2007 140 l +2006 141 l +f +*U +0.000 0.267 0.220 0.235 k +*u +1042 140 m +1043 139 l +1042 140 l +f +*U +0.000 0.604 0.412 0.000 k +*u +1144 140 m +1145 139 l +1144 140 l +f +*U +0.000 0.400 0.388 0.600 k +*u +1220.667 139.667 m +1220.222 139.222 1221.278 139.278 1221.333 139.333 c +1221.778 139.778 1220.722 139.722 1220.667 139.667 c +f +*U +0.000 0.416 0.267 0.325 k +*u +1222 140 m +1223 139 l +1222 140 l +f +*U +0.000 0.145 0.075 0.220 k +*u +1222 138 m +1223.580 138.684 1223.777 138.805 1225 140 c +1223.420 139.316 1223.223 139.195 1222 138 c +f +*U +0.000 0.204 0.137 0.169 k +*u +1227 139 m +1230.607 137.487 1234.260 138 1238 139 c +1234.672 140 1230.479 139.411 1227 139 c +f +*U +0.000 0.259 0.165 0.396 k +*u +1229 140 m +1230.248 139.315 1230.548 139.251 1232 139 c +1230.751 139.685 1230.452 139.749 1229 140 c +f +*U +0.000 0.227 0.153 0.286 k +*u +1232 140 m +1233.248 139.315 1233.548 139.251 1235 139 c +1233.751 139.685 1233.452 139.749 1232 140 c +f +*U +0.000 0.067 0.078 0.518 k +*u +1239.667 139.667 m +1239.222 139.222 1240.278 139.278 1240.333 139.333 c +1240.778 139.778 1239.722 139.722 1239.667 139.667 c +f +*U +0.000 0.667 0.522 0.333 k +*u +1248 140 m +1253.216 137.811 1260.381 139 1266 139 c +1304 139 l +1298.783 141.189 1291.619 140 1286 140 c +1248 140 l +f +*U +0.000 0.404 0.314 0.596 k +*u +1421 140 m +1422 139 l +1421 140 l +f +*U +0.000 0.498 0.384 0.427 k +*u +2003.667 139.667 m +2003.222 139.222 2004.278 139.278 2004.333 139.333 c +2004.778 139.778 2003.722 139.722 2003.667 139.667 c +f +*U +0.000 0.373 0.298 0.259 k +*u +1043 139 m +1044 138 l +1043 139 l +f +*U +0.000 0.675 0.533 0.294 k +*u +1044 139 m +1045 136.643 1045.956 135.624 1048 134 c +1046.987 136.485 1046.274 137.598 1044 139 c +f +*U +0.012 0.000 0.024 0.145 k +*u +1145.667 138.667 m +1145.222 138.222 1146.278 138.278 1146.333 138.333 c +1146.778 138.778 1145.722 138.722 1145.667 138.667 c +f +*U +0.000 0.035 0.024 0.251 k +*u +1238 139 m +1239 138 l +1238 139 l +f +*U +0.000 0.310 0.251 0.071 k +*u +1247 139 m +1248 138 l +1247 139 l +f +*U +0.000 0.039 0.035 0.220 k +*u +1299.667 138.667 m +1299.222 138.222 1300.278 138.278 1300.333 138.333 c +1300.778 138.778 1299.722 138.722 1299.667 138.667 c +f +*U +0.000 0.424 0.365 0.576 k +*u +1420 139 m +1421 138 l +1420 139 l +f +*U +0.000 0.455 0.357 0.102 k +*u +2003 139 m +2004 138 l +2003 139 l +f +*U +0.000 0.420 0.388 0.580 k +*u +1419 138 m +1420 137 l +1419 138 l +f +*U +0.000 0.235 0.173 0.110 k +*u +1420 138 m +1421 137 l +1420 138 l +f +*U +0.000 0.561 0.424 0.192 k +*u +2001 138 m +2002 137 l +2001 138 l +f +*U +0.000 0.337 0.255 0.071 k +*u +2002 138 m +2003 137 l +2002 138 l +f +*U +0.000 0.145 0.086 0.169 k +*u +1083 137 m +1084 136 l +1083 137 l +f +*U +0.000 0.110 0.047 0.729 k +*u +1383 137 m +1384 136 l +1383 137 l +f +*U +0.000 0.318 0.251 0.110 k +*u +1419 137 m +1420 136 l +1419 137 l +f +*U +0.000 0.333 0.302 0.153 k +*u +2000 137 m +2001 136 l +2000 137 l +f +*U +0.000 0.796 0.576 0.204 k +*u +1083 136 m +1084 132.767 1085.455 130.310 1088 128 c +1089.198 129.245 1089 129 1091 129 c +1088.615 131.749 1086 133.943 1083 136 c +f +*U +0.000 0.271 0.290 0.102 k +*u +1084 136 m +1085 135 l +1084 136 l +f +*U +0.000 0.490 0.365 0.510 k +*u +1417 136 m +1418 135 l +1417 136 l +f +*U +0.000 0.231 0.149 0.318 k +*u +1418 136 m +1419 135 l +1418 136 l +f +*U +0.000 0.463 0.345 0.431 k +*u +1995 134 m +1996.580 134.684 1996.777 134.805 1998 136 c +1996.420 135.316 1996.223 135.195 1995 134 c +f +*U +0.000 0.129 0.102 0.475 k +*u +1998 136 m +1999 135 l +1998 136 l +f +*U +0.000 0.267 0.196 0.251 k +*u +1085 135 m +1086 134 l +1085 135 l +f +*U +0.000 0.545 0.361 0.455 k +*u +1416 135 m +1417 134 l +1416 135 l +f +*U +0.000 0.384 0.255 0.157 k +*u +1417 135 m +1418 134 l +1417 135 l +f +*U +0.000 0.275 0.216 0.082 k +*u +1997 135 m +1998 134 l +1997 135 l +f +*U +0.000 0.341 0.239 0.271 k +*u +1086 134 m +1087 133 l +1086 134 l +f +*U +0.000 0.514 0.380 0.486 k +*u +1380 134 m +1381 133 l +1380 134 l +f +*U +0.000 0.616 0.431 0.380 k +*u +1415 134 m +1413.242 131.988 1412 130.419 1411 128 c +1413.348 129.773 1415 131 1415 134 c +f +*U +0.000 0.224 0.137 0.314 k +*u +1416 134 m +1417 133 l +1416 134 l +f +*U +0.000 0.525 0.408 0.475 k +*u +1994 134 m +1995 133 l +1994 134 l +f +*U +0.000 0.337 0.243 0.306 k +*u +1995 134 m +1996 133 l +1995 134 l +f +*U +0.000 0.204 0.157 0.125 k +*u +1048 133 m +1049 132 l +1048 133 l +f +*U +0.000 0.494 0.420 0.227 k +*u +1087 133 m +1088 132 l +1087 133 l +f +*U +0.000 0.510 0.510 0.459 k +*u +1379 133 m +1380 132 l +1379 133 l +f +*U +0.000 0.796 0.600 0.196 k +*u +1380 133 m +1378.390 131.672 1377.299 130.617 1376 129 c +1380 128 l +1379.402 129.196 1379.534 128.977 1378 130 c +1379.994 130.847 1380.699 131 1380 133 c +f +*U +0.000 0.533 0.400 0.455 k +*u +1992.667 132.667 m +1992.222 132.222 1993.278 132.278 1993.333 132.333 c +1993.778 132.778 1992.722 132.722 1992.667 132.667 c +f +*U +0.000 0.318 0.220 0.051 k +*u +1994 133 m +1995 132 l +1994 133 l +f +*U +0.000 0.341 0.235 0.439 k +*u +1088 132 m +1089 131 l +1088 132 l +f +*U +0.000 0.251 0.271 0.157 k +*u +1377 132 m +1378 131 l +1377 132 l +f +*U +0.000 0.212 0.188 0.373 k +*u +1992 132 m +1993 131 l +1992 132 l +f +*U +0.000 0.525 0.424 0.475 k +*u +1051 131 m +1052 130 l +1051 131 l +f +*U +0.000 0.286 0.263 0.180 k +*u +1376 131 m +1377 130 l +1376 131 l +f +*U +0.000 0.439 0.341 0.349 k +*u +1989 131 m +1989 129 l +1990.635 129.545 1990.455 129.365 1991 131 c +1989 131 l +f +*U +0.000 0.337 0.275 0.059 k +*u +1991 131 m +1992 130 l +1991 131 l +f +*U +0.000 0.486 0.431 0.514 k +*u +1052 130 m +1053 129 l +1052 130 l +f +*U +0.000 0.275 0.200 0.286 k +*u +1091 130 m +1092 129 l +1091 130 l +f +*U +0.000 0.325 0.204 0.204 k +*u +1375 130 m +1376 129 l +1375 130 l +f +*U +0.000 0.953 0.620 0.047 k +*u +1380 128 m +1381.580 128.684 1381.777 128.805 1383 130 c +1381.420 129.317 1381.223 129.195 1380 128 c +f +*U +0.000 0.525 0.396 0.475 k +*u +1988 130 m +1989 129 l +1988 130 l +f +*U +0.000 0.251 0.180 0.349 k +*u +1092 129 m +1093 128 l +1092 129 l +f +*U +0.000 0.306 0.200 0.302 k +*u +1374 129 m +1375 128 l +1374 129 l +f +*U +0.000 0.486 0.310 0.514 k +*u +1375 129 m +1376 128 l +1375 129 l +f +*U +0.000 0.180 0.141 0.059 k +*u +1412 129 m +1413 128 l +1412 129 l +f +*U +0.000 0.408 0.333 0.424 k +*u +1986.667 128.667 m +1986.222 128.223 1987.277 128.277 1987.333 128.333 c +1987.778 128.778 1986.722 128.722 1986.667 128.667 c +f +*U +0.000 0.192 0.173 0.149 k +*u +1988 129 m +1989 128 l +1988 129 l +f +*U +0.000 0.506 0.561 0.427 k +*u +1054 128 m +1054.545 126.365 1054.365 126.545 1056 126 c +1056 128 l +1054 128 l +f +*U +0.000 0.588 0.443 0.329 k +*u +1092 128 m +1093.624 125.956 1094.643 125 1097 124 c +1095.376 126 1094.357 126.896 1092 128 c +f +*U +0.000 0.192 0.129 0.506 k +*u +1173 128 m +1174 127 l +1173 128 l +f +*U +0.000 0.220 0.220 0.780 k +*u +1174.667 127.667 m +1174.222 127.223 1175.278 127.278 1175.333 127.333 c +1175.778 127.778 1174.722 127.722 1174.667 127.667 c +f +*U +0.000 0.580 0.420 0.420 k +*u +1176 128 m +1180.271 125 1188.772 127 1194 127 c +1240 127 l +1234.293 129.395 1226 128 1220 128 c +1176 128 l +f +*U +0.000 0.529 0.412 0.471 k +*u +1240 128 m +1247.409 124.891 1258.975 127 1267 127 c +1259.591 130 1248 128 1240 128 c +f +*U +0.000 0.620 0.467 0.380 k +*u +1264 126 m +1266.698 125 1269 125.647 1272 126 c +1269 128 1267.224 127 1264 126 c +f +*U +0.000 0.247 0.247 0.753 k +*u +1271 128 m +1272.506 127.317 1273.315 127.174 1275 127 c +1273.494 127.683 1272.685 127.826 1271 128 c +f +*U +0.000 0.192 0.192 0.478 k +*u +1275 128 m +1276 127 l +1275 128 l +f +*U +0.000 0.098 0.102 0.200 k +*u +1276 128 m +1277 127 l +1276 128 l +f +*U +0.000 0.675 0.482 0.325 k +*u +1373 125 m +1374 126 1374.309 126.612 1375 128 c +1372.797 127 1372.952 127.330 1373 125 c +f +*U +0.000 0.545 0.435 0.384 k +*u +1409 128 m +1408 126.522 1408 126.797 1408 125 c +1409.289 126.443 1409.401 126.234 1409 128 c +f +*U +0.000 0.322 0.298 0.678 k +*u +1410 128 m +1411 127 l +1410 128 l +f +*U +0.000 0.443 0.282 0.475 k +*u +1984 128 m +1984 126 l +1985.635 126.545 1985.455 126.365 1986 128 c +1984 128 l +f +*U +0.000 0.212 0.133 0.169 k +*u +1986 128 m +1987 127 l +1986 128 l +f +*U +0.000 0.792 0.620 0.208 k +*u +1057 127 m +1057.514 124 1058.289 123.366 1061 122 c +1059.774 123.922 1058.627 125.412 1057 127 c +f +*U +0.000 0.478 0.365 0.161 k +*u +1176 127 m +1177 126 l +1176 127 l +f +*U +0.000 0.878 0.620 0.122 k +*u +1180 127 m +1184 124 l +1192.981 124.818 1202.873 121.439 1212 121 c +1230.863 120.213 1248.573 122.424 1267 126 c +1259.601 129 1248 127 1240 127 c +1180 127 l +f +*U +0.000 0.259 0.224 0.122 k +*u +1410 127 m +1411 126 l +1410 127 l +f +*U +0.000 0.192 0.145 0.125 k +*u +1096 126 m +1097 125 l +1096 126 l +f +*U +0.000 0.220 0.188 0.318 k +*u +1180 126 m +1181 125 l +1180 126 l +f +*U +0.000 0.604 0.451 0.392 k +*u +1181 126 m +1182.249 125.315 1182.548 125.251 1184 125 c +1182.752 125.685 1182.451 125.749 1181 126 c +f +*U +0.000 0.263 0.263 0.220 k +*u +1268 126 m +1269 125 l +1268 126 l +f +*U +0.000 0.224 0.173 0.051 k +*u +1370 126 m +1371 125 l +1370 126 l +f +*U +0.000 0.353 0.290 0.173 k +*u +1409 126 m +1410 125 l +1409 126 l +f +*U +0.000 0.443 0.357 0.373 k +*u +1981 126 m +1981 124 l +1982.635 124.545 1982.455 124.365 1983 126 c +1981 126 l +f +*U +0.000 0.243 0.243 0.278 k +*u +1983 126 m +1984 125 l +1983 126 l +f +*U +0.000 0.325 0.231 0.275 k +*u +1097 125 m +1098 124 l +1097 125 l +f +*U +0.000 0.294 0.239 0.027 k +*u +1183 125 m +1184 124 l +1183 125 l +f +*U +0.000 0.620 0.463 0.361 k +*u +1185 125 m +1186.249 124.315 1186.548 124.251 1188 124 c +1186.752 124.685 1186.451 124.749 1185 125 c +f +*U +0.000 0.600 0.459 0.400 k +*u +1256 124 m +1258.698 123 1261 123.647 1264 124 c +1261.244 125 1258.893 124.532 1256 124 c +f +*U +0.000 0.173 0.141 0.380 k +*u +1264 125 m +1265 124 l +1264 125 l +f +*U +0.000 0.149 0.129 0.110 k +*u +1265 125 m +1266 124 l +1265 125 l +f +*U +0.000 0.216 0.165 0.263 k +*u +1369 125 m +1370 124 l +1369 125 l +f +*U +0.000 0.643 0.475 0.341 k +*u +1404 121 m +1405.753 122.330 1406.670 123.247 1408 125 c +1405.751 123.847 1405 123.249 1404 121 c +f +*U +0.000 0.298 0.255 0.176 k +*u +1408 125 m +1409 124 l +1408 125 l +f +*U +0.000 0.247 0.220 0.094 k +*u +1187 124 m +1188 123 l +1187 124 l +f +*U +0.000 0.412 0.325 0.231 k +*u +1188 124 m +1189 123 l +1188 124 l +f +*U +0.000 0.600 0.506 0.400 k +*u +1189.667 123.667 m +1189.223 123.223 1190.278 123.278 1190.333 123.333 c +1190.778 123.778 1189.722 123.722 1189.667 123.667 c +f +*U +0.000 0.306 0.208 0.204 k +*u +1260 124 m +1261 123 l +1260 124 l +f +*U +0.000 0.290 0.204 0.341 k +*u +1368 124 m +1369 123 l +1368 124 l +f +*U +0.000 0.376 0.298 0.118 k +*u +1407 124 m +1408 123 l +1407 124 l +f +*U +0.000 0.220 0.153 0.118 k +*u +1980 124 m +1981 123 l +1980 124 l +f +*U +0.000 0.302 0.220 0.071 k +*u +1100 123 m +1101 122 l +1100 123 l +f +*U +0.000 0.310 0.224 0.059 k +*u +1192 123 m +1193 122 l +1192 123 l +f +*U +0.000 0.333 0.243 0.212 k +*u +1193 123 m +1194 122 l +1193 123 l +f +*U +0.000 0.510 0.357 0.475 k +*u +1194 123 m +1195.249 122.315 1195.548 122.251 1197 122 c +1195.752 122.685 1195.451 122.749 1194 123 c +f +*U +0.000 0.753 0.569 0.247 k +*u +1248 123 m +1249.249 122.315 1249.548 122.251 1251 122 c +1249.752 122.685 1249.452 122.749 1248 123 c +f +*U +0.000 0.549 0.455 0.451 k +*u +1251 123 m +1252.249 122.315 1252.548 122.251 1254 122 c +1252.752 122.685 1252.451 122.749 1251 123 c +f +*U +0.000 0.498 0.369 0.200 k +*u +1254 123 m +1255 122 l +1254 123 l +f +*U +0.000 0.502 0.376 0.031 k +*u +1255 123 m +1256 122 l +1255 123 l +f +*U +0.000 0.086 0.027 0.153 k +*u +1256 123 m +1257 122 l +1256 123 l +f +*U +0.000 0.271 0.275 0.388 k +*u +1367 123 m +1368 122 l +1367 123 l +f +*U +0.000 0.459 0.416 0.541 k +*u +1368 123 m +1369 122 l +1368 123 l +f +*U +0.000 0.380 0.298 0.094 k +*u +1406 123 m +1407 122 l +1406 123 l +f +*U +0.000 0.553 0.478 0.447 k +*u +1977 123 m +1978 122 l +1977 123 l +f +*U +0.000 0.325 0.224 0.310 k +*u +1978 123 m +1979 122 l +1978 123 l +f +*U +0.000 0.365 0.263 0.224 k +*u +1101 122 m +1102 121 l +1101 122 l +f +*U +0.000 0.176 0.137 0.125 k +*u +1198 122 m +1199 121 l +1198 122 l +f +*U +0.000 0.176 0.137 0.298 k +*u +1199 122 m +1200 121 l +1199 122 l +f +*U +0.000 0.643 0.498 0.357 k +*u +1200 122 m +1202.613 120.902 1205 121 1208 121 c +1205.387 122 1202.835 121.993 1200 122 c +f +*U +0.000 0.706 0.518 0.294 k +*u +1240 122 m +1241.769 121.221 1243 121 1245 121 c +1243.231 121.779 1241.964 121.912 1240 122 c +f +*U +0.000 0.545 0.424 0.455 k +*u +1245 122 m +1246.249 121.315 1246.548 121.251 1248 121 c +1246.752 121.685 1246.451 121.749 1245 122 c +f +*U +0.000 0.235 0.176 0.278 k +*u +1248.667 121.667 m +1248.222 121.222 1249.278 121.278 1249.333 121.333 c +1249.778 121.778 1248.722 121.722 1248.667 121.667 c +f +*U +0.000 0.200 0.149 0.071 k +*u +1250 122 m +1251 121 l +1250 122 l +f +*U +0.000 0.294 0.243 0.204 k +*u +1405 122 m +1406 121 l +1405 122 l +f +*U +0.000 0.471 0.380 0.529 k +*u +1974.333 121.333 m +1974.278 121.278 1974.222 120.222 1974.667 120.667 c +1974.722 120.722 1974.778 121.778 1974.333 121.333 c +f +*U +0.000 0.408 0.294 0.424 k +*u +1102 121 m +1103 120 l +1102 121 l +f +*U +0.000 0.173 0.161 0.247 k +*u +1205 121 m +1206.249 120.315 1206.548 120.251 1208 120 c +1206.752 120.685 1206.451 120.749 1205 121 c +f +*U +0.000 0.502 0.357 0.192 k +*u +1208 121 m +1209 120 l +1208 121 l +f +*U +0.000 0.604 0.514 0.396 k +*u +1209 121 m +1211.331 120 1213.457 120 1216 120 c +1213.668 120.985 1211.543 120.981 1209 121 c +f +*U +0.000 0.843 0.851 0.149 k +*u +1216 121 m +1221.469 118.705 1229 120 1235 120 c +1229.531 122.295 1221.901 121 1216 121 c +f +*U +0.000 0.553 0.541 0.447 k +*u +1235 121 m +1236.249 120.315 1236.548 120.251 1238 120 c +1236.752 120.685 1236.452 120.749 1235 121 c +f +*U +0.000 0.675 0.400 0.243 k +*u +1238.667 120.667 m +1238.222 120.223 1239.278 120.278 1239.333 120.333 c +1239.778 120.778 1238.722 120.722 1238.667 120.667 c +f +*U +0.000 0.337 0.255 0.204 k +*u +1240 121 m +1241.249 120.315 1241.548 120.251 1243 120 c +1241.752 120.685 1241.451 120.749 1240 121 c +f +*U +0.000 0.169 0.137 0.082 k +*u +1243 121 m +1244 120 l +1243 121 l +f +*U +0.000 0.122 0.055 0.204 k +*u +1364 121 m +1365 120 l +1364 121 l +f +*U +0.000 0.400 0.298 0.600 k +*u +1365 121 m +1366 120 l +1365 121 l +f +*U +0.000 0.510 0.392 0.059 k +*u +1404 121 m +1405 120 l +1404 121 l +f +*U +0.000 0.671 0.463 0.094 k +*u +1975 121 m +1976 120 l +1975 121 l +f +*U +0.000 0.322 0.204 0.298 k +*u +1062 120 m +1063 119 l +1062 120 l +f +*U +0.000 0.427 0.286 0.573 k +*u +1063 120 m +1064 119 l +1063 120 l +f +*U +0.000 0.133 0.114 0.161 k +*u +1104 120 m +1105 119 l +1104 120 l +f +*U +0.000 0.090 0.020 0.224 k +*u +1218 120 m +1220.890 118.787 1223.874 119 1227 119 c +1224 120.213 1221 119.998 1218 120 c +f +*U +0.000 0.384 0.416 0.263 k +*u +1363 120 m +1364 119 l +1363 120 l +f +*U +0.000 0.506 0.329 0.443 k +*u +1402 120 m +1403 119 l +1402 120 l +f +*U +0.000 0.200 0.125 0.176 k +*u +1403 120 m +1404 119 l +1403 120 l +f +*U +0.031 0.000 0.012 0.588 k +*u +1973 120 m +1974 119 l +1973 120 l +f +*U +0.000 0.290 0.184 0.235 k +*u +1063 119 m +1064 118 l +1063 119 l +f +*U +0.000 0.494 0.357 0.455 k +*u +1104 119 m +1105 118 l +1104 119 l +f +*U +0.000 0.424 0.302 0.290 k +*u +1105 119 m +1106 118 l +1105 119 l +f +*U +0.000 0.627 0.506 0.373 k +*u +1362.667 118.667 m +1362.222 118.223 1363.278 118.278 1363.333 118.333 c +1363.778 118.778 1362.722 118.722 1362.667 118.667 c +f +*U +0.000 0.537 0.408 0.463 k +*u +1401 119 m +1402 118 l +1401 119 l +f +*U +0.000 0.329 0.220 0.075 k +*u +1402 119 m +1403 118 l +1402 119 l +f +*U +0.000 0.376 0.294 0.188 k +*u +1064 118 m +1065 117 l +1064 118 l +f +*U +0.000 0.522 0.424 0.478 k +*u +1065 118 m +1066 117 l +1065 118 l +f +*U +0.000 0.235 0.180 0.090 k +*u +1107 118 m +1108 117 l +1107 118 l +f +*U +0.000 0.318 0.388 0.086 k +*u +1360 118 m +1361 117 l +1360 118 l +f +*U +0.000 0.459 0.451 0.541 k +*u +1361 118 m +1362 117 l +1361 118 l +f +*U +0.000 0.522 0.341 0.431 k +*u +1400 118 m +1401 117 l +1400 118 l +f +*U +0.000 0.329 0.224 0.067 k +*u +1401 118 m +1402 117 l +1401 118 l +f +*U +0.000 0.404 0.325 0.561 k +*u +1066 117 m +1067 116 l +1066 117 l +f +*U +0.000 0.541 0.424 0.459 k +*u +1107 117 m +1108 116 l +1107 117 l +f +*U +0.000 0.322 0.247 0.310 k +*u +1108 117 m +1109 116 l +1108 117 l +f +*U +0.000 0.278 0.192 0.322 k +*u +1359 117 m +1360 116 l +1359 117 l +f +*U +0.000 0.553 0.404 0.447 k +*u +1399 117 m +1400 116 l +1399 117 l +f +*U +0.000 0.224 0.145 0.180 k +*u +1400 117 m +1401 116 l +1400 117 l +f +*U +0.055 0.000 0.059 0.157 k +*u +1066 116 m +1067 115 l +1066 116 l +f +*U +0.000 0.329 0.329 0.671 k +*u +1067 116 m +1068 115 l +1067 116 l +f +*U +0.000 0.486 0.353 0.404 k +*u +1108.667 115.667 m +1108.222 115.222 1109.278 115.278 1109.333 115.333 c +1109.778 115.778 1108.722 115.722 1108.667 115.667 c +f +*U +0.000 0.235 0.196 0.114 k +*u +1357 116 m +1358 115 l +1357 116 l +f +*U +0.000 0.490 0.388 0.510 k +*u +1358 116 m +1359 115 l +1358 116 l +f +*U +0.000 0.706 0.525 0.239 k +*u +1396 116 m +1396 113 l +1397.196 114.223 1397.316 114.420 1398 116 c +1396 116 l +f +*U +0.000 0.365 0.310 0.635 k +*u +1398 116 m +1399 115 l +1398 116 l +f +*U +0.000 0.212 0.157 0.075 k +*u +1399 116 m +1400 115 l +1399 116 l +f +*U +0.000 0.455 0.380 0.545 k +*u +1068 115 m +1069 114 l +1068 115 l +f +*U +0.000 0.443 0.341 0.196 k +*u +1111 115 m +1112 114 l +1111 115 l +f +*U +0.000 0.373 0.302 0.231 k +*u +1356 115 m +1357 114 l +1356 115 l +f +*U +0.000 0.451 0.451 0.549 k +*u +1357 115 m +1358 114 l +1357 115 l +f +*U +0.000 0.659 0.451 0.341 k +*u +1112 114 m +1112 112 l +1114 112 l +1113.455 113.635 1113.635 113.455 1112 114 c +f +*U +0.000 0.380 0.255 0.063 k +*u +1113 114 m +1114 113 l +1113 114 l +f +*U +0.000 0.490 0.408 0.263 k +*u +1070 113 m +1071 112 l +1070 113 l +f +*U +0.000 0.310 0.192 0.196 k +*u +1114 113 m +1115 112 l +1114 113 l +f +*U +0.000 0.106 0.102 0.404 k +*u +1353 113 m +1354 112 l +1353 113 l +f +*U +0.000 0.514 0.431 0.239 k +*u +1395 113 m +1396 112 l +1395 113 l +f +*U +0.000 0.094 0.055 0.329 k +*u +1071 112 m +1072 111 l +1071 112 l +f +*U +0.000 0.643 0.431 0.357 k +*u +1072 112 m +1072.545 110.365 1072.365 110.545 1074 110 c +1074 112 l +1072 112 l +f +*U +0.000 0.467 0.467 0.533 k +*u +1115 112 m +1116 111 l +1115 112 l +f +*U +0.000 0.302 0.318 0.110 k +*u +1116 112 m +1117 111 l +1116 112 l +f +*U +0.000 0.549 0.384 0.451 k +*u +1393 112 m +1394 111 l +1393 112 l +f +*U +0.000 0.220 0.137 0.333 k +*u +1394 112 m +1395 111 l +1394 112 l +f +*U +0.000 0.267 0.165 0.082 k +*u +1072 111 m +1073 110 l +1072 111 l +f +*U +0.000 0.384 0.318 0.251 k +*u +1117 111 m +1118 110 l +1117 111 l +f +*U +0.000 0.310 0.263 0.196 k +*u +1350 111 m +1351 110 l +1350 111 l +f +*U +0.000 0.471 0.369 0.478 k +*u +1351 111 m +1352 110 l +1351 111 l +f +*U +0.000 0.412 0.275 0.141 k +*u +1393 111 m +1394 110 l +1393 111 l +f +*U +0.000 0.361 0.243 0.016 k +*u +1119 110 m +1120 109 l +1119 110 l +f +*U +0.000 0.278 0.216 0.075 k +*u +1348 110 m +1349 109 l +1348 110 l +f +*U +0.000 0.475 0.333 0.463 k +*u +1388 107 m +1389.949 107.936 1390.550 108.392 1392 110 c +1390 109 1389.450 108.608 1388 107 c +f +*U +0.000 0.235 0.153 0.098 k +*u +1392 110 m +1393 109 l +1392 110 l +f +*U +0.000 0.663 0.537 0.337 k +*u +1075.667 108.667 m +1075.222 108.222 1076.278 108.278 1076.333 108.333 c +1076.778 108.778 1075.722 108.722 1075.667 108.667 c +f +*U +0.000 0.627 0.506 0.373 k +*u +1120 109 m +1120 107 l +1122 107 l +1121.455 108.635 1121.635 108.455 1120 109 c +f +*U +0.000 0.216 0.192 0.125 k +*u +1121 109 m +1122 108 l +1121 109 l +f +*U +0.000 0.369 0.263 0.341 k +*u +1347 109 m +1348 108 l +1347 109 l +f +*U +0.000 0.310 0.235 0.071 k +*u +1391 109 m +1392 108 l +1391 109 l +f +*U +0.000 0.227 0.220 0.212 k +*u +1076 108 m +1077 107 l +1076 108 l +f +*U +0.000 0.584 0.471 0.416 k +*u +1077 108 m +1078 107 l +1077 108 l +f +*U +0.000 0.341 0.275 0.290 k +*u +1122 108 m +1123 107 l +1122 108 l +f +*U +0.000 0.282 0.204 0.133 k +*u +1345 108 m +1346 107 l +1345 108 l +f +*U +0.000 0.184 0.169 0.176 k +*u +1077 107 m +1078 106 l +1077 107 l +f +*U +0.000 0.486 0.408 0.514 k +*u +1078 107 m +1079 106 l +1078 107 l +f +*U +0.000 0.592 0.431 0.392 k +*u +1122.667 106.667 m +1122.222 106.222 1123.278 106.278 1123.333 106.333 c +1123.778 106.778 1122.722 106.722 1122.667 106.667 c +f +*U +0.000 0.380 0.282 0.082 k +*u +1124 107 m +1125 106 l +1124 107 l +f +*U +0.000 0.620 0.447 0.353 k +*u +1344.667 106.667 m +1344.223 106.223 1345.278 106.278 1345.333 106.333 c +1345.778 106.778 1344.722 106.722 1344.667 106.667 c +f +*U +0.000 0.561 0.455 0.439 k +*u +1387 107 m +1388 106 l +1387 107 l +f +*U +0.000 0.322 0.243 0.267 k +*u +1388 107 m +1389 106 l +1388 107 l +f +*U +0.000 0.663 0.518 0.271 k +*u +1079 106 m +1080.543 104.733 1081 104.511 1083 104 c +1081.457 105.267 1080.952 105.489 1079 106 c +f +*U +0.000 0.761 0.576 0.239 k +*u +1125 106 m +1125.980 104.217 1125.908 104.406 1128 104 c +1126.861 105 1126.388 105.309 1125 106 c +f +*U +0.000 0.275 0.235 0.161 k +*u +1126 106 m +1127 105 l +1126 106 l +f +*U +0.000 0.373 0.255 0.208 k +*u +1342 106 m +1343 105 l +1342 106 l +f +*U +0.000 0.365 0.290 0.635 k +*u +1343 106 m +1344 105 l +1343 106 l +f +*U +0.000 0.455 0.404 0.545 k +*u +1386 106 m +1387 105 l +1386 106 l +f +*U +0.000 0.298 0.239 0.278 k +*u +1387 106 m +1388 105 l +1387 106 l +f +*U +0.102 0.000 0.027 0.137 k +*u +1128 105 m +1129 104 l +1128 105 l +f +*U +0.000 0.251 0.161 0.129 k +*u +1340 105 m +1341 104 l +1340 105 l +f +*U +0.000 0.655 0.506 0.345 k +*u +1341.667 104.667 m +1341.222 104.223 1342.278 104.278 1342.333 104.333 c +1342.778 104.778 1341.722 104.722 1341.667 104.667 c +f +*U +0.000 0.490 0.471 0.510 k +*u +1385 105 m +1386 104 l +1385 105 l +f +*U +0.000 0.286 0.251 0.141 k +*u +1386 105 m +1387 104 l +1386 105 l +f +*U +0.000 0.098 0.067 0.231 k +*u +1081 104 m +1082 103 l +1081 104 l +f +*U +0.000 0.455 0.322 0.545 k +*u +1082 104 m +1083 103 l +1082 104 l +f +*U +0.000 0.510 0.384 0.490 k +*u +1128 104 m +1129 103 l +1128 104 l +f +*U +0.000 0.439 0.310 0.278 k +*u +1129 104 m +1130 103 l +1129 104 l +f +*U +0.000 0.580 0.490 0.420 k +*u +1338 102 m +1339.581 102.684 1339.777 102.804 1341 104 c +1339.420 103.317 1339.223 103.195 1338 102 c +f +*U +0.000 0.753 0.686 0.192 k +*u +1380 104 m +1380 100 l +1384 102 l +1382.542 103 1381.752 103.436 1380 104 c +f +*U +0.000 0.075 0.039 0.651 k +*u +1384 104 m +1385 103 l +1384 104 l +f +*U +0.000 0.678 0.486 0.322 k +*u +1083.667 102.667 m +1083.222 102.222 1084.278 102.278 1084.333 102.333 c +1084.778 102.778 1083.722 102.722 1083.667 102.667 c +f +*U +0.000 0.463 0.361 0.537 k +*u +1130 103 m +1131 102 l +1130 103 l +f +*U +0.000 0.325 0.235 0.329 k +*u +1131 103 m +1132 102 l +1131 103 l +f +*U +0.000 0.322 0.267 0.361 k +*u +1337 103 m +1338 102 l +1337 103 l +f +*U +0.000 0.365 0.259 0.322 k +*u +1084 102 m +1085 101 l +1084 102 l +f +*U +0.000 0.561 0.451 0.439 k +*u +1085 102 m +1086 101 l +1085 102 l +f +*U +0.000 0.522 0.388 0.478 k +*u +1132 102 m +1133 101 l +1132 102 l +f +*U +0.000 0.325 0.224 0.337 k +*u +1133 102 m +1134 101 l +1133 102 l +f +*U +0.000 0.294 0.247 0.306 k +*u +1335 102 m +1336 101 l +1335 102 l +f +*U +0.000 0.620 0.514 0.380 k +*u +1336.667 101.667 m +1336.222 101.223 1337.278 101.278 1337.333 101.333 c +1337.778 101.778 1336.722 101.722 1336.667 101.667 c +f +*U +0.000 0.306 0.337 0.243 k +*u +1382 102 m +1383 101 l +1382 102 l +f +*U +0.000 0.255 0.188 0.098 k +*u +1085 101 m +1086 100 l +1085 101 l +f +*U +0.000 0.651 0.514 0.349 k +*u +1133 101 m +1134.543 99.733 1135 99.511 1137 99 c +1135.542 100 1134.752 100.436 1133 101 c +f +*U +0.000 0.388 0.282 0.212 k +*u +1135 101 m +1136 100 l +1135 101 l +f +*U +0.000 0.286 0.267 0.306 k +*u +1333 101 m +1334 100 l +1333 101 l +f +*U +0.000 0.494 0.471 0.506 k +*u +1334 101 m +1335 100 l +1334 101 l +f +*U +0.000 0.224 0.216 0.235 k +*u +1381 101 m +1382 100 l +1381 101 l +f +*U +0.000 0.329 0.235 0.525 k +*u +1087 100 m +1088 99 l +1087 100 l +f +*U +0.000 0.392 0.247 0.267 k +*u +1137 100 m +1138 99 l +1137 100 l +f +*U +0.000 0.278 0.231 0.239 k +*u +1331 100 m +1332 99 l +1331 100 l +f +*U +0.000 0.631 0.502 0.369 k +*u +1332.667 99.667 m +1332.222 99.222 1333.278 99.278 1333.333 99.333 c +1333.778 99.778 1332.722 99.722 1332.667 99.667 c +f +*U +0.000 0.722 0.600 0.204 k +*u +1373 96 m +1375.403 96.628 1376.958 97.562 1379 99 c +1376 99.483 1374.593 98.410 1373 96 c +f +*U +0.000 0.392 0.235 0.275 k +*u +1379 100 m +1380 99 l +1379 100 l +f +*U +0.000 0.533 0.361 0.165 k +*u +1088 99 m +1089 98 l +1088 99 l +f +*U +0.000 0.584 0.471 0.416 k +*u +1089 99 m +1090.223 97.805 1090.420 97.684 1092 97 c +1090.777 98.195 1090.580 98.316 1089 99 c +f +*U +0.000 0.478 0.392 0.522 k +*u +1138 99 m +1139 98 l +1138 99 l +f +*U +0.000 0.294 0.239 0.318 k +*u +1139 99 m +1140 98 l +1139 99 l +f +*U +0.000 0.251 0.208 0.165 k +*u +1329 99 m +1330 98 l +1329 99 l +f +*U +0.000 0.647 0.533 0.353 k +*u +1330.667 98.667 m +1330.222 98.223 1331.278 98.278 1331.333 98.333 c +1331.778 98.778 1330.722 98.722 1330.667 98.667 c +f +*U +0.000 0.243 0.235 0.357 k +*u +1378 99 m +1379 98 l +1378 99 l +f +*U +0.000 0.396 0.318 0.220 k +*u +1141 98 m +1142 97 l +1141 98 l +f +*U +0.000 0.278 0.235 0.239 k +*u +1327 98 m +1328 97 l +1327 98 l +f +*U +0.000 0.635 0.475 0.329 k +*u +1328.667 97.667 m +1328.222 97.222 1329.278 97.278 1329.333 97.333 c +1329.778 97.778 1328.722 97.722 1328.667 97.667 c +f +*U +0.000 0.349 0.271 0.506 k +*u +1376 98 m +1377 97 l +1376 98 l +f +*U +0.000 0.247 0.161 0.118 k +*u +1377 98 m +1378 97 l +1377 98 l +f +*U +0.000 0.482 0.420 0.114 k +*u +1091 97 m +1092 96 l +1091 97 l +f +*U +0.000 0.541 0.541 0.459 k +*u +1092 97 m +1093 96 l +1092 97 l +f +*U +0.000 0.588 0.459 0.412 k +*u +1141.667 96.667 m +1141.222 96.222 1142.278 96.278 1142.333 96.333 c +1142.778 96.778 1141.722 96.722 1141.667 96.667 c +f +*U +0.000 0.263 0.204 0.145 k +*u +1325 97 m +1326 96 l +1325 97 l +f +*U +0.000 0.522 0.396 0.392 k +*u +1326.667 96.667 m +1326.222 96.223 1327.278 96.278 1327.333 96.333 c +1327.778 96.778 1326.722 96.722 1326.667 96.667 c +f +*U +0.000 0.725 0.518 0.275 k +*u +1333.667 96.667 m +1333.222 96.222 1334.278 96.278 1334.333 96.333 c +1334.778 96.778 1333.722 96.722 1333.667 96.667 c +f +*U +0.000 0.514 0.337 0.435 k +*u +1093 96 m +1094 94.985 1094.611 94.691 1096 94 c +1095 95.783 1095 95.594 1093 96 c +f +*U +0.000 0.365 0.267 0.031 k +*u +1146 96 m +1147 95 l +1146 96 l +f +*U +0.000 0.416 0.322 0.243 k +*u +1323 96 m +1324 95 l +1323 96 l +f +*U +0.000 0.482 0.376 0.518 k +*u +1373 96 m +1374 95 l +1373 96 l +f +*U +0.000 0.224 0.169 0.196 k +*u +1374 96 m +1375 95 l +1374 96 l +f +*U +0.000 0.427 0.286 0.114 k +*u +1094 95 m +1095 94 l +1094 95 l +f +*U +0.000 0.522 0.369 0.475 k +*u +1146.667 94.667 m +1146.222 94.222 1147.278 94.278 1147.333 94.333 c +1147.778 94.778 1146.722 94.722 1146.667 94.667 c +f +*U +0.000 0.349 0.251 0.094 k +*u +1148 95 m +1149 94 l +1148 95 l +f +*U +0.000 0.353 0.267 0.082 k +*u +1320 95 m +1321 94 l +1320 95 l +f +*U +0.000 0.627 0.455 0.310 k +*u +1321.667 94.667 m +1321.222 94.222 1322.278 94.278 1322.333 94.333 c +1322.778 94.778 1321.722 94.722 1321.667 94.667 c +f +*U +0.000 0.690 0.506 0.294 k +*u +1326 95 m +1326.545 93.365 1326.365 93.545 1328 93 c +1328 95 l +1326 95 l +f +*U +0.000 0.412 0.318 0.451 k +*u +1372 95 m +1373 94 l +1372 95 l +f +*U +0.000 0.204 0.133 0.133 k +*u +1095 94 m +1096 93 l +1095 94 l +f +*U +0.000 0.471 0.392 0.529 k +*u +1096 94 m +1097 93 l +1096 94 l +f +*U +0.000 0.471 0.349 0.529 k +*u +1149 94 m +1150 93 l +1149 94 l +f +*U +0.000 0.278 0.204 0.329 k +*u +1150 94 m +1151 93 l +1150 94 l +f +*U +0.000 0.357 0.255 0.016 k +*u +1318 94 m +1319 93 l +1318 94 l +f +*U +0.000 0.565 0.475 0.435 k +*u +1370 94 m +1371 93 l +1370 94 l +f +*U +0.000 0.353 0.275 0.047 k +*u +1371 94 m +1372 93 l +1371 94 l +f +*U +0.000 0.349 0.251 0.322 k +*u +1097 93 m +1098 92 l +1097 93 l +f +*U +0.000 0.427 0.302 0.478 k +*u +1151.667 92.667 m +1151.222 92.222 1152.278 92.278 1152.333 92.333 c +1152.778 92.778 1151.722 92.722 1151.667 92.667 c +f +*U +0.000 0.212 0.161 0.153 k +*u +1153 93 m +1154 92 l +1153 93 l +f +*U +0.000 0.282 0.227 0.263 k +*u +1316 93 m +1317 92 l +1316 93 l +f +*U +0.000 0.431 0.431 0.569 k +*u +1368 93 m +1369 92 l +1368 93 l +f +*U +0.000 0.431 0.325 0.361 k +*u +1369 93 m +1370 92 l +1369 93 l +f +*U +0.000 0.125 0.102 0.129 k +*u +1098 92 m +1099 91 l +1098 92 l +f +*U +0.000 0.682 0.545 0.318 k +*u +1099.667 91.667 m +1099.222 91.222 1100.278 91.278 1100.333 91.333 c +1100.778 91.778 1099.722 91.722 1099.667 91.667 c +f +*U +0.000 0.737 0.545 0.263 k +*u +1152 92 m +1153.458 90.919 1154.248 90.564 1156 90 c +1154.457 91.267 1153.952 91.489 1152 92 c +f +*U +0.000 0.431 0.306 0.275 k +*u +1155 92 m +1156 91 l +1155 92 l +f +*U +0.000 0.051 0.055 0.149 k +*u +1156 92 m +1157 91 l +1156 92 l +f +*U +0.000 0.243 0.184 0.149 k +*u +1313 92 m +1314 91 l +1313 92 l +f +*U +0.000 0.624 0.478 0.333 k +*u +1314.667 91.667 m +1314.222 91.223 1315.278 91.278 1315.333 91.333 c +1315.778 91.778 1314.722 91.722 1314.667 91.667 c +f +*U +0.000 0.639 0.475 0.361 k +*u +1366.667 91.667 m +1366.223 91.223 1367.278 91.278 1367.333 91.333 c +1367.778 91.778 1366.722 91.722 1366.667 91.667 c +f +*U +0.000 0.184 0.153 0.263 k +*u +1368 92 m +1369 91 l +1368 92 l +f +*U +0.000 0.341 0.247 0.271 k +*u +1100 91 m +1101 90 l +1100 91 l +f +*U +0.000 0.737 0.573 0.263 k +*u +1101.667 90.667 m +1101.222 90.222 1102.278 90.278 1102.333 90.333 c +1102.778 90.778 1101.722 90.722 1101.667 90.667 c +f +*U +0.000 0.443 0.333 0.486 k +*u +1156.667 90.667 m +1156.222 90.222 1157.278 90.278 1157.333 90.333 c +1157.778 90.778 1156.722 90.722 1156.667 90.667 c +f +*U +0.000 0.227 0.196 0.204 k +*u +1158 91 m +1159 90 l +1158 91 l +f +*U +0.000 0.259 0.231 0.192 k +*u +1311 91 m +1312 90 l +1311 91 l +f +*U +0.000 0.392 0.282 0.435 k +*u +1365.667 90.667 m +1365.222 90.222 1366.278 90.278 1366.333 90.333 c +1366.778 90.778 1365.722 90.722 1365.667 90.667 c +f +*U +0.000 0.435 0.365 0.565 k +*u +1102.667 89.667 m +1102.222 89.222 1103.278 89.278 1103.333 89.333 c +1103.778 89.778 1102.722 89.722 1102.667 89.667 c +f +*U +0.000 0.451 0.451 0.549 k +*u +1159 90 m +1160 89 l +1159 90 l +f +*U +0.000 0.286 0.184 0.475 k +*u +1160 90 m +1161 89 l +1160 90 l +f +*U +0.000 0.263 0.173 0.118 k +*u +1161 90 m +1162 89 l +1161 90 l +f +*U +0.000 0.298 0.243 0.204 k +*u +1308 90 m +1309 89 l +1308 90 l +f +*U +0.000 0.580 0.447 0.408 k +*u +1309 90 m +1310.249 89.315 1310.548 89.251 1312 89 c +1310.752 89.685 1310.452 89.749 1309 90 c +f +*U +0.000 0.541 0.408 0.459 k +*u +1363 90 m +1363 88 l +1364.635 88.545 1364.455 88.365 1365 90 c +1363 90 l +f +*U +0.000 0.322 0.235 0.035 k +*u +1365 90 m +1366 89 l +1365 90 l +f +*U +0.067 0.000 0.067 0.176 k +*u +1103 89 m +1104 88 l +1103 89 l +f +*U +0.000 0.475 0.329 0.525 k +*u +1161.667 88.667 m +1161.222 88.222 1162.278 88.278 1162.333 88.333 c +1162.778 88.778 1161.722 88.722 1161.667 88.667 c +f +*U +0.000 0.278 0.176 0.412 k +*u +1163 89 m +1164 88 l +1163 89 l +f +*U +0.000 0.094 0.059 0.137 k +*u +1164 89 m +1165 88 l +1164 89 l +f +*U +0.000 0.094 0.055 0.208 k +*u +1305 89 m +1306 88 l +1305 89 l +f +*U +0.000 0.580 0.447 0.420 k +*u +1306.667 88.667 m +1306.222 88.222 1307.278 88.278 1307.333 88.333 c +1307.778 88.778 1306.722 88.722 1306.667 88.667 c +f +*U +0.000 0.271 0.200 0.349 k +*u +1105 88 m +1106 87 l +1105 88 l +f +*U +0.000 0.690 0.557 0.310 k +*u +1106.667 87.667 m +1106.222 87.222 1107.278 87.278 1107.333 87.333 c +1107.778 87.778 1106.722 87.722 1106.667 87.667 c +f +*U +0.000 0.588 0.447 0.412 k +*u +1164.667 87.667 m +1164.222 87.222 1165.278 87.278 1165.333 87.333 c +1165.778 87.778 1164.722 87.722 1164.667 87.667 c +f +*U +0.000 0.710 0.522 0.255 k +*u +1165 87 m +1166.506 86.317 1167.315 86.174 1169 86 c +1167.265 87 1167 87 1165 87 c +f +*U +0.000 0.486 0.365 0.000 k +*u +1167 88 m +1168 87 l +1167 88 l +f +*U +0.000 0.235 0.263 0.090 k +*u +1302 88 m +1303 87 l +1302 88 l +f +*U +0.000 0.298 0.314 0.455 k +*u +1303 88 m +1304 87 l +1303 88 l +f +*U +0.000 0.400 0.255 0.498 k +*u +1360.667 87.667 m +1360.222 87.222 1361.278 87.278 1361.333 87.333 c +1361.778 87.778 1360.722 87.722 1360.667 87.667 c +f +*U +0.000 0.220 0.141 0.165 k +*u +1362 88 m +1363 87 l +1362 88 l +f +*U +0.000 0.329 0.251 0.416 k +*u +1107 87 m +1108 86 l +1107 87 l +f +*U +0.000 0.494 0.345 0.235 k +*u +1169 87 m +1170 86 l +1169 87 l +f +*U +0.000 0.263 0.192 0.000 k +*u +1170 87 m +1171 86 l +1170 87 l +f +*U +0.000 0.271 0.227 0.118 k +*u +1299 87 m +1300 86 l +1299 87 l +f +*U +0.000 0.431 0.349 0.404 k +*u +1300 87 m +1301 86 l +1300 87 l +f +*U +0.000 0.612 0.545 0.388 k +*u +1301.667 86.667 m +1301.222 86.222 1302.278 86.278 1302.333 86.333 c +1302.778 86.778 1301.722 86.722 1301.667 86.667 c +f +*U +0.000 0.329 0.216 0.224 k +*u +1360 87 m +1361 86 l +1360 87 l +f +*U +0.000 0.263 0.192 0.078 k +*u +1108 86 m +1109 85 l +1108 86 l +f +*U +0.000 0.612 0.498 0.388 k +*u +1109.667 85.667 m +1109.222 85.222 1110.278 85.278 1110.333 85.333 c +1110.778 85.778 1109.722 85.722 1109.667 85.667 c +f +*U +0.000 0.616 0.486 0.384 k +*u +1170.667 85.667 m +1170.222 85.222 1171.278 85.278 1171.333 85.333 c +1171.778 85.778 1170.722 85.722 1170.667 85.667 c +f +*U +0.000 0.322 0.220 0.106 k +*u +1173 86 m +1174 85 l +1173 86 l +f +*U +0.000 0.369 0.314 0.224 k +*u +1296 86 m +1297 85 l +1296 86 l +f +*U +0.000 0.565 0.447 0.435 k +*u +1297.667 85.667 m +1297.223 85.223 1298.278 85.278 1298.333 85.333 c +1298.778 85.778 1297.722 85.722 1297.667 85.667 c +f +*U +0.000 0.416 0.294 0.502 k +*u +1358 86 m +1359 85 l +1358 86 l +f +*U +0.000 0.294 0.220 0.016 k +*u +1110 85 m +1111 84 l +1110 85 l +f +*U +0.000 0.737 0.561 0.263 k +*u +1111.667 84.667 m +1111.222 84.222 1112.278 84.278 1112.333 84.333 c +1112.778 84.778 1111.722 84.722 1111.667 84.667 c +f +*U +0.000 0.439 0.349 0.561 k +*u +1174.667 84.667 m +1174.222 84.223 1175.278 84.278 1175.333 84.333 c +1175.778 84.778 1174.722 84.722 1174.667 84.667 c +f +*U +0.000 0.259 0.192 0.306 k +*u +1176 85 m +1177 84 l +1176 85 l +f +*U +0.000 0.208 0.169 0.098 k +*u +1177 85 m +1178 84 l +1177 85 l +f +*U +0.000 0.110 0.090 0.192 k +*u +1292 85 m +1293 84 l +1292 85 l +f +*U +0.000 0.753 0.588 0.247 k +*u +1288 83 m +1291 82 1293.942 82.554 1296 85 c +1293.225 84.590 1290.673 83.851 1288 83 c +f +*U +0.000 0.545 0.388 0.455 k +*u +1356 85 m +1357 84 l +1356 85 l +f +*U +0.000 0.243 0.180 0.141 k +*u +1357 85 m +1358 84 l +1357 85 l +f +*U +0.000 0.447 0.322 0.239 k +*u +1112 84 m +1113 83 l +1112 84 l +f +*U +0.000 0.533 0.380 0.467 k +*u +1113 84 m +1114 83 l +1113 84 l +f +*U +0.000 0.663 0.565 0.271 k +*u +1176 84 m +1177.377 83 1178.440 82.596 1180 82 c +1178.686 83.618 1178 83.693 1176 84 c +f +*U +0.000 0.373 0.357 0.239 k +*u +1180 84 m +1181 83 l +1180 84 l +f +*U +0.000 0.208 0.227 0.055 k +*u +1181 84 m +1182 83 l +1181 84 l +f +*U +0.000 0.173 0.137 0.153 k +*u +1288 84 m +1289 83 l +1288 84 l +f +*U +0.000 0.310 0.224 0.290 k +*u +1289 84 m +1290 83 l +1289 84 l +f +*U +0.000 0.557 0.427 0.443 k +*u +1354 84 m +1355 83 l +1354 84 l +f +*U +0.000 0.294 0.216 0.349 k +*u +1355 84 m +1356 83 l +1355 84 l +f +*U +0.000 0.549 0.420 0.451 k +*u +1114.667 82.667 m +1114.222 82.222 1115.278 82.278 1115.333 82.333 c +1115.778 82.778 1114.722 82.722 1114.667 82.667 c +f +*U +0.000 0.612 0.514 0.388 k +*u +1180 83 m +1181.506 82.317 1182.315 82.174 1184 82 c +1182.494 82.683 1181.685 82.826 1180 83 c +f +*U +0.000 0.196 0.141 0.314 k +*u +1184 83 m +1185 82 l +1184 83 l +f +*U +0.000 0.188 0.141 0.137 k +*u +1185 83 m +1186 82 l +1185 83 l +f +*U +0.000 0.255 0.188 0.051 k +*u +1284 83 m +1285 82 l +1284 83 l +f +*U +0.000 0.333 0.239 0.255 k +*u +1285 83 m +1286 82 l +1285 83 l +f +*U +0.000 0.424 0.302 0.569 k +*u +1287 83 m +1288 82 l +1287 83 l +f +*U +0.000 0.565 0.431 0.373 k +*u +1348 81 m +1350.274 80.591 1351.781 81.212 1354 82 c +1351.538 82.697 1350.335 82 1348 81 c +f +*U +0.000 0.184 0.141 0.086 k +*u +1115 82 m +1116 81 l +1115 82 l +f +*U +0.000 0.584 0.408 0.365 k +*u +1116 82 m +1117.458 80.919 1118.248 80.564 1120 80 c +1118.457 81.267 1117.952 81.489 1116 82 c +f +*U +0.000 0.678 0.498 0.322 k +*u +1185 82 m +1186.249 81.315 1186.548 81.251 1188 81 c +1186.752 81.685 1186.451 81.749 1185 82 c +f +*U +0.000 0.388 0.275 0.322 k +*u +1188 82 m +1189 81 l +1188 82 l +f +*U +0.000 0.212 0.161 0.212 k +*u +1189 82 m +1190 81 l +1189 82 l +f +*U +0.000 0.416 0.286 0.078 k +*u +1280 82 m +1281 81 l +1280 82 l +f +*U +0.000 0.600 0.451 0.400 k +*u +1281 82 m +1282.769 81.221 1284 81 1286 81 c +1284.231 81.779 1282.964 81.912 1281 82 c +f +*U +0.000 0.059 0.043 0.149 k +*u +1352 82 m +1353 81 l +1352 82 l +f +*U +0.000 0.278 0.212 0.090 k +*u +1117 81 m +1118 80 l +1117 81 l +f +*U +0.000 0.667 0.537 0.333 k +*u +1190.667 80.667 m +1190.222 80.222 1191.278 80.278 1191.333 80.333 c +1191.778 80.778 1190.722 80.722 1190.667 80.667 c +f +*U +0.000 0.361 0.243 0.639 k +*u +1192 81 m +1193 80 l +1192 81 l +f +*U +0.000 0.345 0.224 0.439 k +*u +1193 81 m +1194 80 l +1193 81 l +f +*U +0.000 0.263 0.173 0.255 k +*u +1194 81 m +1195 80 l +1194 81 l +f +*U +0.000 0.153 0.098 0.129 k +*u +1195 81 m +1196 80 l +1195 81 l +f +*U +0.000 0.157 0.098 0.255 k +*u +1275 81 m +1276 80 l +1275 81 l +f +*U +0.000 0.349 0.227 0.322 k +*u +1276 81 m +1277 80 l +1276 81 l +f +*U +0.000 0.612 0.435 0.388 k +*u +1277 81 m +1278.249 80.315 1278.548 80.251 1280 80 c +1278.752 80.685 1278.452 80.749 1277 81 c +f +*U +0.000 0.310 0.267 0.129 k +*u +1350 81 m +1351 80 l +1350 81 l +f +*U +0.000 0.416 0.345 0.584 k +*u +1120.667 79.667 m +1120.222 79.222 1121.278 79.278 1121.333 79.333 c +1121.778 79.778 1120.722 79.722 1120.667 79.667 c +f +*U +0.000 0.278 0.227 0.098 k +*u +1268 80 m +1269.249 79.315 1269.548 79.251 1271 79 c +1269.752 79.685 1269.452 79.749 1268 80 c +f +*U +0.000 0.737 0.541 0.263 k +*u +1268 79 m +1270.698 78 1273 78.647 1276 79 c +1273.244 80 1270.893 79.532 1268 79 c +f +*U +0.000 0.302 0.196 0.569 k +*u +1346.667 79.667 m +1346.223 79.223 1347.278 79.278 1347.333 79.333 c +1347.778 79.778 1346.722 79.722 1346.667 79.667 c +f +*U +0.000 0.102 0.063 0.220 k +*u +1348 80 m +1349 79 l +1348 80 l +f +*U +0.000 0.176 0.141 0.110 k +*u +1121 79 m +1122 78 l +1121 79 l +f +*U +0.000 0.616 0.478 0.384 k +*u +1122.667 78.667 m +1122.222 78.222 1123.278 78.278 1123.333 78.333 c +1123.778 78.778 1122.722 78.722 1122.667 78.667 c +f +*U +0.000 0.514 0.392 0.486 k +*u +1202 79 m +1203.249 78.315 1203.548 78.251 1205 78 c +1203.752 78.685 1203.452 78.749 1202 79 c +f +*U +0.000 0.259 0.180 0.251 k +*u +1205.667 78.667 m +1205.222 78.222 1206.278 78.278 1206.333 78.333 c +1206.778 78.778 1205.722 78.722 1205.667 78.667 c +f +*U +0.000 0.063 0.039 0.149 k +*u +1207.667 78.667 m +1207.222 78.222 1208.278 78.278 1208.333 78.333 c +1208.778 78.778 1207.722 78.722 1207.667 78.667 c +f +*U +0.000 0.188 0.133 0.184 k +*u +1260.667 78.667 m +1260.222 78.223 1261.278 78.278 1261.333 78.333 c +1261.778 78.778 1260.722 78.722 1260.667 78.667 c +f +*U +0.000 0.239 0.161 0.322 k +*u +1262.667 78.667 m +1262.222 78.222 1263.278 78.278 1263.333 78.333 c +1263.778 78.778 1262.722 78.722 1262.667 78.667 c +f +*U +0.000 0.569 0.392 0.384 k +*u +1264 79 m +1265.506 78.317 1266.315 78.174 1268 78 c +1266.494 78.683 1265.685 78.826 1264 79 c +f +*U +0.000 0.561 0.369 0.439 k +*u +1344.667 78.667 m +1344.223 78.223 1345.278 78.278 1345.333 78.333 c +1345.778 78.778 1344.722 78.722 1344.667 78.667 c +f +*U +0.000 0.373 0.247 0.118 k +*u +1346 79 m +1347 78 l +1346 79 l +f +*U +0.000 0.627 0.463 0.373 k +*u +1124.667 77.667 m +1124.222 77.222 1125.278 77.278 1125.333 77.333 c +1125.778 77.778 1124.722 77.722 1124.667 77.667 c +f +*U +0.000 0.627 0.439 0.373 k +*u +1208 78 m +1209.249 77.315 1209.548 77.251 1211 77 c +1209.752 77.685 1209.452 77.749 1208 78 c +f +*U +0.000 0.482 0.416 0.518 k +*u +1211 78 m +1212.249 77.315 1212.548 77.251 1214 77 c +1212.752 77.685 1212.452 77.749 1211 78 c +f +*U +0.000 0.278 0.231 0.224 k +*u +1215.667 77.667 m +1215.222 77.222 1216.278 77.278 1216.333 77.333 c +1216.778 77.778 1215.722 77.722 1215.667 77.667 c +f +*U +0.000 0.231 0.192 0.137 k +*u +1217 78 m +1218.506 77.317 1219.315 77.174 1221 77 c +1219.494 77.683 1218.685 77.826 1217 78 c +f +*U +0.000 0.212 0.082 0.129 k +*u +1249 78 m +1250.506 77.317 1251.315 77.174 1253 77 c +1251.494 77.683 1250.685 77.826 1249 78 c +f +*U +0.000 0.349 0.251 0.216 k +*u +1253 78 m +1254.249 77.315 1254.548 77.251 1256 77 c +1254.752 77.685 1254.451 77.749 1253 78 c +f +*U +0.000 0.506 0.416 0.494 k +*u +1256 78 m +1257.249 77.315 1257.548 77.251 1259 77 c +1257.752 77.685 1257.451 77.749 1256 78 c +f +*U +0.000 0.702 0.537 0.298 k +*u +1259 78 m +1260.249 77.315 1260.548 77.251 1262 77 c +1260.752 77.685 1260.452 77.749 1259 78 c +f +*U +0.000 0.631 0.471 0.325 k +*u +1341 78 m +1342.249 77.315 1342.548 77.251 1344 77 c +1342.752 77.685 1342.451 77.749 1341 78 c +f +*U +0.000 0.204 0.129 0.286 k +*u +1344 78 m +1345 77 l +1344 78 l +f +*U +0.000 0.255 0.188 0.047 k +*u +1125 77 m +1126 76 l +1125 77 l +f +*U +0.000 0.659 0.455 0.314 k +*u +1126 77 m +1127.750 75.745 1128.857 75.386 1131 75 c +1129.249 76.255 1128 76.614 1126 77 c +f +*U +0.000 0.729 0.596 0.271 k +*u +1219 77 m +1220.769 76.221 1222 76 1224 76 c +1222.231 76.779 1220.964 76.912 1219 77 c +f +*U +0.000 0.447 0.353 0.553 k +*u +1224 77 m +1226.613 75.902 1229 76 1232 76 c +1229.387 77 1226.836 76.993 1224 77 c +f +*U +0.000 0.541 0.380 0.447 k +*u +1232 77 m +1234.613 75.902 1237 76 1240 76 c +1237.387 77 1234.835 76.993 1232 77 c +f +*U +0.000 0.478 0.373 0.522 k +*u +1240 77 m +1242.613 75.902 1245 76 1248 76 c +1245.387 77 1242.836 76.993 1240 77 c +f +*U +0.000 0.753 0.690 0.247 k +*u +1248 77 m +1249.249 76.315 1249.548 76.251 1251 76 c +1249.752 76.685 1249.452 76.749 1248 77 c +f +*U +0.000 0.894 0.922 0.078 k +*u +1251 77 m +1252.506 76.317 1253.315 76.174 1255 76 c +1253.494 76.683 1252.685 76.826 1251 77 c +f +*U +0.000 0.427 0.400 0.573 k +*u +1340.667 76.667 m +1340.222 76.222 1341.278 76.278 1341.333 76.333 c +1341.778 76.778 1340.722 76.722 1340.667 76.667 c +f +*U +0.000 0.294 0.247 0.184 k +*u +1342 77 m +1343 76 l +1342 77 l +f +*U +0.000 0.043 0.047 0.216 k +*u +1127 76 m +1128 75 l +1127 76 l +f +*U +0.000 0.533 0.443 0.467 k +*u +1338.667 75.667 m +1338.222 75.222 1339.278 75.278 1339.333 75.333 c +1339.778 75.778 1338.722 75.722 1338.667 75.667 c +f +*U +0.000 0.404 0.322 0.141 k +*u +1340 76 m +1341 75 l +1340 76 l +f +*U +0.000 0.365 0.263 0.231 k +*u +1130 75 m +1131 74 l +1130 75 l +f +*U +0.000 0.733 0.529 0.267 k +*u +1131.667 74.667 m +1131.222 74.222 1132.278 74.278 1132.333 74.333 c +1132.778 74.778 1131.722 74.722 1131.667 74.667 c +f +*U +0.000 0.510 0.400 0.447 k +*u +1336.667 74.667 m +1336.222 74.223 1337.278 74.278 1337.333 74.333 c +1337.778 74.778 1336.722 74.722 1336.667 74.667 c +f +*U +0.000 0.325 0.271 0.063 k +*u +1338 75 m +1339 74 l +1338 75 l +f +*U +0.000 0.349 0.243 0.271 k +*u +1132 74 m +1133 73 l +1132 74 l +f +*U +0.000 0.722 0.486 0.278 k +*u +1133 74 m +1134 72.985 1134.611 72.691 1136 72 c +1135 73.783 1135 73.594 1133 74 c +f +*U +0.000 0.565 0.549 0.357 k +*u +1331 73 m +1332.846 72.533 1334 72.699 1336 73 c +1333.955 73.775 1333 73.592 1331 73 c +f +*U +0.000 0.208 0.196 0.208 k +*u +1336 74 m +1337 73 l +1336 74 l +f +*U +0.000 0.427 0.278 0.000 k +*u +1134 73 m +1135 72 l +1134 73 l +f +*U +0.000 0.341 0.369 0.298 k +*u +1333 73 m +1334 72 l +1333 73 l +f +*U +0.000 0.137 0.173 0.098 k +*u +1334 73 m +1335 72 l +1334 73 l +f +*U +0.000 0.239 0.110 0.118 k +*u +1136 72 m +1137 71 l +1136 72 l +f +*U +0.000 0.345 0.200 0.396 k +*u +1137 72 m +1138 71 l +1137 72 l +f +*U +0.000 0.757 0.545 0.243 k +*u +1138 72 m +1139.750 70.745 1140.857 70.386 1143 70 c +1141.212 71.421 1140.294 71.697 1138 72 c +f +*U +0.000 0.788 0.620 0.212 k +*u +1326 70 m +1329 70 l +1328 72 l +1326.365 71.455 1326.545 71.635 1326 70 c +f +*U +0.000 0.486 0.314 0.514 k +*u +1329.667 71.667 m +1329.222 71.222 1330.278 71.278 1330.333 71.333 c +1330.778 71.778 1329.722 71.722 1329.667 71.667 c +f +*U +0.000 0.239 0.141 0.333 k +*u +1331 72 m +1332 71 l +1331 72 l +f +*U +0.000 0.271 0.169 0.290 k +*u +1139 71 m +1140 70 l +1139 71 l +f +*U +0.000 0.376 0.255 0.000 k +*u +1329 71 m +1330 70 l +1329 71 l +f +*U +0.000 0.463 0.325 0.271 k +*u +1142 70 m +1143 69 l +1142 70 l +f +*U +0.000 0.714 0.573 0.286 k +*u +1143.667 69.667 m +1143.222 69.222 1144.278 69.278 1144.333 69.333 c +1144.778 69.778 1143.722 69.722 1143.667 69.667 c +f +*U +0.000 0.333 0.255 0.282 k +*u +1326 70 m +1327 69 l +1326 70 l +f +*U +0.000 0.431 0.322 0.180 k +*u +1144 69 m +1145 68 l +1144 69 l +f +*U +0.000 0.545 0.420 0.455 k +*u +1145.667 68.667 m +1145.222 68.223 1146.278 68.278 1146.333 68.333 c +1146.778 68.778 1145.722 68.722 1145.667 68.667 c +f +*U +0.000 0.263 0.192 0.102 k +*u +1324 69 m +1325 68 l +1324 69 l +f +*U +0.000 0.267 0.200 0.275 k +*u +1147 68 m +1148 67 l +1147 68 l +f +*U +0.000 0.616 0.490 0.384 k +*u +1148.667 67.667 m +1148.222 67.222 1149.278 67.278 1149.333 67.333 c +1149.778 67.778 1148.722 67.722 1148.667 67.667 c +f +*U +0.000 0.796 0.620 0.204 k +*u +1152 68 m +1152.980 66.217 1152.908 66.406 1155 66 c +1153.860 67 1153.388 67.309 1152 68 c +f +*U +0.000 0.710 0.522 0.271 k +*u +1317 68 m +1318.506 67.317 1319.315 67.174 1321 67 c +1319.494 67.683 1318.685 67.826 1317 68 c +f +*U +0.000 0.388 0.278 0.322 k +*u +1321 68 m +1322 67 l +1321 68 l +f +*U +0.000 0.161 0.129 0.145 k +*u +1322 68 m +1323 67 l +1322 68 l +f +*U +0.000 0.286 0.208 0.067 k +*u +1149 67 m +1150 66 l +1149 67 l +f +*U +0.000 0.525 0.365 0.416 k +*u +1150.667 66.667 m +1150.222 66.222 1151.278 66.278 1151.333 66.333 c +1151.778 66.778 1150.722 66.722 1150.667 66.667 c +f +*U +0.000 0.518 0.384 0.447 k +*u +1316.667 66.667 m +1316.222 66.222 1317.278 66.278 1317.333 66.333 c +1317.778 66.778 1316.722 66.722 1316.667 66.667 c +f +*U +0.000 0.263 0.216 0.361 k +*u +1318 67 m +1319 66 l +1318 67 l +f +*U +0.000 0.118 0.122 0.180 k +*u +1319 67 m +1320 66 l +1319 67 l +f +*U +0.000 0.518 0.361 0.129 k +*u +1152 66 m +1153 65 l +1152 66 l +f +*U +0.000 0.576 0.471 0.416 k +*u +1153.667 65.667 m +1153.222 65.222 1154.278 65.278 1154.333 65.333 c +1154.778 65.778 1153.722 65.722 1153.667 65.667 c +f +*U +0.000 0.745 0.659 0.239 k +*u +1155 66 m +1156.789 64.578 1157.706 64.303 1160 64 c +1158.307 65 1156.960 65.520 1155 66 c +f +*U +0.000 0.502 0.341 0.396 k +*u +1312.333 65.333 m +1312.278 65.278 1312.223 64.222 1312.667 64.667 c +1312.722 64.722 1312.778 65.778 1312.333 65.333 c +f +*U +0.000 0.490 0.412 0.510 k +*u +1313 66 m +1314.249 65.315 1314.549 65.251 1316 65 c +1314.752 65.685 1314.451 65.749 1313 66 c +f +*U +0.000 0.333 0.243 0.137 k +*u +1316 66 m +1317 65 l +1316 66 l +f +*U +0.000 0.314 0.373 0.047 k +*u +1155 65 m +1156 64 l +1155 65 l +f +*U +0.000 0.749 0.710 0.251 k +*u +1310.667 64.667 m +1310.222 64.223 1311.278 64.278 1311.333 64.333 c +1311.778 64.778 1310.722 64.722 1310.667 64.667 c +f +*U +0.000 0.388 0.278 0.027 k +*u +1313 65 m +1314 64 l +1313 65 l +f +*U +0.008 0.024 0.000 0.220 k +*u +1158 64 m +1159 63 l +1158 64 l +f +*U +0.004 0.012 0.000 0.549 k +*u +1159 64 m +1160 63 l +1159 64 l +f +*U +0.000 0.631 0.455 0.369 k +*u +1160.667 63.667 m +1160.222 63.222 1161.278 63.278 1161.333 63.333 c +1161.778 63.778 1160.722 63.722 1160.667 63.667 c +f +*U +0.000 0.412 0.337 0.588 k +*u +1307 64 m +1308.249 63.315 1308.548 63.251 1310 63 c +1308.752 63.685 1308.452 63.749 1307 64 c +f +*U +0.000 0.239 0.192 0.153 k +*u +1310 64 m +1311 63 l +1310 64 l +f +*U +0.000 0.204 0.129 0.071 k +*u +1161 63 m +1162 62 l +1161 63 l +f +*U +0.000 0.325 0.216 0.302 k +*u +1162 63 m +1163 62 l +1162 63 l +f +*U +0.000 0.608 0.451 0.392 k +*u +1163 63 m +1164.249 62.315 1164.548 62.251 1166 62 c +1164.752 62.685 1164.451 62.749 1163 63 c +f +*U +0.000 0.576 0.455 0.424 k +*u +1304.667 62.667 m +1304.222 62.222 1305.278 62.278 1305.333 62.333 c +1305.778 62.778 1304.722 62.722 1304.667 62.667 c +f +*U +0.000 0.341 0.259 0.118 k +*u +1307 63 m +1308 62 l +1307 63 l +f +*U +0.000 0.318 0.231 0.129 k +*u +1165 62 m +1166 61 l +1165 62 l +f +*U +0.000 0.392 0.290 0.408 k +*u +1166 62 m +1167 61 l +1166 62 l +f +*U +0.000 0.565 0.420 0.435 k +*u +1167 62 m +1168.249 61.315 1168.548 61.251 1170 61 c +1168.752 61.685 1168.452 61.749 1167 62 c +f +*U +0.000 0.514 0.384 0.486 k +*u +1300 62 m +1301.249 61.315 1301.548 61.251 1303 61 c +1301.752 61.685 1301.451 61.749 1300 62 c +f +*U +0.000 0.322 0.212 0.145 k +*u +1303 62 m +1304 61 l +1303 62 l +f +*U +0.000 0.122 0.055 0.129 k +*u +1168 61 m +1169 60 l +1168 61 l +f +*U +0.000 0.220 0.161 0.318 k +*u +1169 61 m +1170 60 l +1169 61 l +f +*U +0.000 0.580 0.478 0.420 k +*u +1170.667 60.667 m +1170.222 60.222 1171.278 60.278 1171.333 60.333 c +1171.778 60.778 1170.722 60.722 1170.667 60.667 c +f +*U +0.000 0.600 0.431 0.373 k +*u +1293 60 m +1295 59.324 1296.732 59.613 1299 60 c +1296.761 60.811 1295.353 60.529 1293 60 c +f +*U +0.000 0.475 0.369 0.165 k +*u +1299 61 m +1300 60 l +1299 61 l +f +*U +0.000 0.314 0.263 0.047 k +*u +1300 61 m +1301 60 l +1300 61 l +f +*U +0.000 0.141 0.173 0.071 k +*u +1172 60 m +1173 59 l +1172 60 l +f +*U +0.000 0.325 0.255 0.306 k +*u +1173 60 m +1174 59 l +1173 60 l +f +*U +0.000 0.541 0.376 0.459 k +*u +1174 60 m +1175.506 59.317 1176.315 59.174 1178 59 c +1176.494 59.683 1175.685 59.826 1174 60 c +f +*U +0.000 0.161 0.098 0.282 k +*u +1296 60 m +1297 59 l +1296 60 l +f +*U +0.000 0.082 0.078 0.157 k +*u +1176 59 m +1177 58 l +1176 59 l +f +*U +0.000 0.247 0.184 0.239 k +*u +1177 59 m +1178 58 l +1177 59 l +f +*U +0.000 0.561 0.424 0.439 k +*u +1178 59 m +1179.506 58.317 1180.315 58.174 1182 58 c +1180.494 58.683 1179.685 58.826 1178 59 c +f +*U +0.000 0.663 0.486 0.337 k +*u +1288 59 m +1289.249 58.315 1289.548 58.251 1291 58 c +1289.752 58.685 1289.451 58.749 1288 59 c +f +*U +0.000 0.459 0.318 0.227 k +*u +1291 59 m +1292 58 l +1291 59 l +f +*U +0.000 0.129 0.086 0.071 k +*u +1292.667 58.667 m +1292.222 58.222 1293.278 58.278 1293.333 58.333 c +1293.778 58.778 1292.722 58.722 1292.667 58.667 c +f +*U +0.000 0.176 0.125 0.110 k +*u +1181 58 m +1182 57 l +1181 58 l +f +*U +0.000 0.478 0.325 0.267 k +*u +1182 58 m +1183 57 l +1182 58 l +f +*U +0.000 0.490 0.369 0.510 k +*u +1183 58 m +1184.249 57.315 1184.548 57.251 1186 57 c +1184.752 57.685 1184.452 57.749 1183 58 c +f +*U +0.000 0.631 0.498 0.369 k +*u +1282 58 m +1283.769 57.221 1285 57 1287 57 c +1285.231 57.779 1283.964 57.912 1282 58 c +f +*U +0.000 0.541 0.392 0.114 k +*u +1287 58 m +1288 57 l +1287 58 l +f +*U +0.000 0.239 0.157 0.082 k +*u +1186 57 m +1187 56 l +1186 57 l +f +*U +0.000 0.384 0.275 0.290 k +*u +1187 57 m +1188 56 l +1187 57 l +f +*U +0.000 0.573 0.525 0.427 k +*u +1188 57 m +1189.249 56.315 1189.548 56.251 1191 56 c +1189.752 56.685 1189.452 56.749 1188 57 c +f +*U +0.000 0.420 0.361 0.580 k +*u +1280 57 m +1281 56 l +1280 57 l +f +*U +0.000 0.482 0.353 0.216 k +*u +1281 57 m +1282 56 l +1281 57 l +f +*U +0.000 0.282 0.224 0.047 k +*u +1282.667 56.667 m +1282.222 56.222 1283.278 56.278 1283.333 56.333 c +1283.778 56.778 1282.722 56.722 1282.667 56.667 c +f +*U +0.000 0.384 0.259 0.306 k +*u +1192.667 55.667 m +1192.222 55.222 1193.278 55.278 1193.333 55.333 c +1193.778 55.778 1192.722 55.722 1192.667 55.667 c +f +*U +0.000 0.498 0.373 0.502 k +*u +1194.667 55.667 m +1194.222 55.222 1195.278 55.278 1195.333 55.333 c +1195.778 55.778 1194.722 55.722 1194.667 55.667 c +f +*U +0.000 0.749 0.545 0.251 k +*u +1196 56 m +1197.506 55.317 1198.315 55.174 1200 55 c +1198.494 55.683 1197.685 55.826 1196 56 c +f +*U +0.000 0.580 0.431 0.420 k +*u +1272 56 m +1273.506 55.317 1274.315 55.174 1276 55 c +1274.494 55.683 1273.685 55.826 1272 56 c +f +*U +0.000 0.333 0.208 0.333 k +*u +1276 56 m +1277 55 l +1276 56 l +f +*U +0.000 0.137 0.078 0.102 k +*u +1277.667 55.667 m +1277.222 55.222 1278.278 55.278 1278.333 55.333 c +1278.778 55.777 1277.723 55.723 1277.667 55.667 c +f +*U +0.000 0.176 0.125 0.235 k +*u +1198.667 54.667 m +1198.222 54.222 1199.278 54.278 1199.333 54.333 c +1199.778 54.777 1198.723 54.723 1198.667 54.667 c +f +*U +0.000 0.545 0.451 0.455 k +*u +1200 55 m +1201.769 54.221 1203 54 1205 54 c +1203.231 54.779 1201.964 54.912 1200 55 c +f +*U +0.000 0.741 0.620 0.259 k +*u +1216 55 m +1217.314 53.382 1217.877 53.307 1220 53 c +1218.624 53.911 1217.560 54.404 1216 55 c +f +*U +0.000 0.588 0.612 0.388 k +*u +1264.667 54.667 m +1264.222 54.222 1265.278 54.278 1265.333 54.333 c +1265.778 54.777 1264.723 54.723 1264.667 54.667 c +f +*U +0.000 0.420 0.447 0.553 k +*u +1266 55 m +1267.249 54.315 1267.548 54.251 1269 54 c +1267.752 54.685 1267.452 54.749 1266 55 c +f +*U +0.000 0.200 0.333 0.329 k +*u +1269 55 m +1270 54 l +1269 55 l +f +*U +0.000 0.078 0.251 0.157 k +*u +1270.667 54.667 m +1270.222 54.222 1271.278 54.278 1271.333 54.333 c +1271.778 54.777 1270.723 54.723 1270.667 54.667 c +f +*U +0.000 0.122 0.118 0.302 k +*u +1206.667 53.667 m +1206.222 53.222 1207.278 53.278 1207.333 53.333 c +1207.778 53.778 1206.722 53.722 1206.667 53.667 c +f +*U +0.000 0.612 0.510 0.035 k +*u +1208 54 m +1209 53 l +1208 54 l +f +*U +0.000 0.529 0.420 0.471 k +*u +1210 54 m +1212 53 1213.747 53 1216 53 c +1213.948 53.874 1212.253 53.953 1210 54 c +f +*U +0.000 0.557 0.447 0.443 k +*u +1253 54 m +1255.332 53 1257.457 53 1260 53 c +1257.668 53.985 1255.543 53.981 1253 54 c +f +*U +0.000 0.329 0.239 0.192 k +*u +1260 54 m +1261.506 53.317 1262.315 53.174 1264 53 c +1262.494 53.683 1261.685 53.826 1260 54 c +f +*U +0.000 0.345 0.282 0.173 k +*u +1217 53 m +1219.332 52 1221.457 52 1224 52 c +1221.668 52.985 1219.544 52.981 1217 53 c +f +*U +0.000 0.608 0.424 0.227 k +*u +1224.667 52.667 m +1224.222 52.222 1225.278 52.278 1225.333 52.333 c +1225.778 52.778 1224.722 52.722 1224.667 52.667 c +f +*U +0.000 0.525 0.424 0.475 k +*u +1226 53 m +1228 52 1229.747 52 1232 52 c +1229.948 52.874 1228.253 52.953 1226 53 c +f +*U +0.000 0.392 0.392 0.608 k +*u +1232 53 m +1234.613 51.902 1237 52 1240 52 c +1237.387 53 1234.835 52.993 1232 53 c +f +*U +0.000 0.478 0.337 0.506 k +*u +1240 53 m +1241.506 52.317 1242.315 52.174 1244 52 c +1242.494 52.683 1241.685 52.826 1240 53 c +f +*U +0.000 0.467 0.329 0.275 k +*u +1244.667 52.667 m +1244.222 52.222 1245.278 52.278 1245.333 52.333 c +1245.778 52.778 1244.722 52.722 1244.667 52.667 c +f +*U +0.000 0.404 0.286 0.110 k +*u +1246 53 m +1248 52 1249.747 52 1252 52 c +1249.948 52.874 1248.253 52.953 1246 53 c +f +*U +0.000 0.106 0.090 0.067 k +*u +1252.667 52.667 m +1252.222 52.222 1253.278 52.278 1253.333 52.333 c +1253.778 52.777 1252.723 52.723 1252.667 52.667 c +f +*U +%%Trailer +%%EOF diff --git a/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.eps b/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.eps new file mode 100644 index 0000000..fe74ae3 --- /dev/null +++ b/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.eps @@ -0,0 +1,28071 @@ +%!PS-Adobe-3.0 EPSF-3.0 +%%Creator: Adobe Illustrator by AutoTrace version 0.31.1 +%%Title: /var/www/autotracer.org/temp_dir_m/25f86a2855585e93e61da0f2839bb576/technicalkorea_Logo.eps +%%CreationDate: Tue Jul 1 04:59:13 2025 +%%BoundingBox: 0 0 2094 600 +%%DocumentData: Clean7Bit +%%EndComments +%%BeginProlog +/bd { bind def } bind def +/incompound false def +/m { moveto } bd +/l { lineto } bd +/c { curveto } bd +/F { incompound not {fill} if } bd +/f { closepath F } bd +/S { stroke } bd +/*u { /incompound true def } bd +/*U { /incompound false def f} bd +/k { setcmykcolor } bd +/K { k } bd +%%EndProlog +%%BeginSetup +%%EndSetup +0.000 0.000 0.000 0.000 k +*u +0 600 m +0 395 l +2.656 400.517 3 406.612 6.468 412 c +15.646 426.865 33.640 436.640 51 437 c +50 438.783 50 438.594 48 439 c +57.403 441.779 69.218 440 79 440 c +142 440 l +348 440 l +1023 440 l +1013.597 437.221 1001.782 439 992 439 c +929 439 l +724 439 l +53 439 l +59.678 436.198 69.784 438 77 438 c +130 438 l +313 438 l +802 438 l +953 438 l +1000 438 l +1006.746 438 1015.382 436.560 1021.910 438.318 c +1028.865 440.190 1035.484 451.822 1040.170 457 c +1051.647 469.684 1064.752 480.969 1078 491.739 c +1115.698 522.386 1162.655 542.211 1211 546.830 c +1270.668 552.532 1330.755 531 1377 493.540 c +1391.785 481.543 1405.287 468.291 1417.845 454 c +1422.293 448.938 1428.382 437 1435 435.318 c +1440.178 433.942 1446.752 435 1452 435 c +1488 435 l +1603 435 l +1975 435 l +1975 410 l +1598 410 l +1480 410 l +1443 410 l +1436.570 410 1429.295 409 1423 410.529 c +1414.316 412.540 1409.882 421.408 1404.870 428 c +1395.994 439.674 1385.879 450.987 1375 460.830 c +1339.790 492.687 1295.380 518.597 1247 521.911 c +1189.677 525.836 1137.711 505.369 1093 470.338 c +1078.487 458.967 1065.337 445.924 1053.289 432 c +1045.483 422.979 1040.211 412.343 1027 412 c +951.439 410 875.588 412 800 412 c +346 412 l +143 412 l +79 412 l +68.784 412 56.989 413.612 47 411.319 c +25.723 406.435 28 384.934 28 368 c +28 236 l +28 219.459 23.618 191.367 46 188 c +45.350 189.300 45.853 189 44 189 c +48 190 l +47.350 191.300 47.853 191 46 191 c +55.963 193.945 68.631 192 79 192 c +147 192 l +367 192 l +812 192 l +958 192 l +985 192 1013 193.925 1040 191 c +1029 186.711 1017.488 188 1006 188 c +949 188 l +746 188 l +513.345 188 280.567 188.358 48 189 c +48 187 l +708 187 l +925 187 l +997 187 l +1008.831 187 1021.229 188 1033 186.895 c +1043.211 185.875 1048.521 174.214 1054.211 167 c +1066 151.956 1079.889 138.204 1095 126.424 c +1137.864 93 1187.948 76.740 1242 77 c +1293.516 77.249 1341.887 99.730 1380 133.285 c +1392 143.903 1402.337 156.917 1411.576 170 c +1416 176.377 1419.345 185.301 1428 186.775 c +1434.378 187.862 1441.539 187 1448 187 c +1486 187 l +1605 187 l +1973 187 l +1973 228 l +1991.816 213.537 2013.250 202 2033 189 c +2040.776 183.821 2051.203 179.405 2057 172 c +2046.379 167.980 2036.523 159.845 2027 153.691 c +2009 142 1990.829 130.798 1973 119 c +1973 162 l +1607 162 l +1493 162 l +1458 162 l +1452.692 162 1446.176 163 1441 161.682 c +1434.719 160 1430 149.848 1426.338 145 c +1415.872 131.643 1403.990 119.341 1391 108.438 c +1351.307 75 1298.445 52.254 1246 52 c +1186.955 51.716 1132 66.518 1084 101.884 c +1068 113.547 1053.250 127.194 1040.286 142 c +1035.508 147.457 1029.281 159.806 1021.985 161.682 c +1016.820 163 1010.312 162 1005 162 c +970 162 l +859 162 l +502 162 l +118 162 l +94 162 l +63.275 162 22.657 155.452 5.493 188 c +3 192.609 1.452 197.822 1 203 c +-1.292 197.538 0 189.887 0 184 c +0 143 l +0 0 l +2094 0 l +2094 600 l +0 600 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1220.667 547.667 m +1220.222 547.222 1221.278 547.278 1221.333 547.333 c +1221.778 547.778 1220.722 547.722 1220.667 547.667 c +f +*U +0.000 0.000 0.000 0.408 k +*u +1222 548 m +1223.506 547.317 1224.315 547.174 1226 547 c +1224.494 547.683 1223.685 547.826 1222 548 c +f +*U +0.000 0.000 0.000 0.498 k +*u +1226 548 m +1228.890 546.787 1231.874 547 1235 547 c +1232 548.213 1229 547.998 1226 548 c +f +*U +0.000 0.000 0.000 0.259 k +*u +1235 548 m +1236.769 547.221 1238 547 1240 547 c +1238.231 547.779 1236.964 547.912 1235 548 c +f +*U +0.000 0.000 0.000 0.435 k +*u +1208 547 m +1209.249 546.315 1209.548 546.251 1211 546 c +1209.752 546.685 1209.451 546.749 1208 547 c +f +*U +0.000 0.000 0.000 0.706 k +*u +1211 547 m +1212 546 l +1211 547 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1097 505 m +1102.506 505.267 1106.507 504.498 1112 504 c +1111.402 505.195 1111.534 504.978 1110 506 c +1111.798 508.376 1112 511 1113 514 c +1117.498 511.951 1123 512.486 1128 512 c +1127 520 l +1133.353 520.383 1138 520.728 1144 523 c +1143.417 525.914 1144.588 524.930 1142 527 c +1144 527.529 1145.875 527.948 1148 528 c +1148.986 529.479 1149 529.203 1149 531 c +1152 529.921 1154.825 528.604 1158 528 c +1156 532 l +1164.214 535.235 1170 536.679 1179 536 c +1177.777 537.195 1177.580 537.317 1176 538 c +1192 536 l +1190.211 537.422 1189.294 537.697 1187 538 c +1189.974 539.754 1192.648 542 1196 543 c +1202.709 544.728 1209.612 543.318 1216 546 c +1218.673 542.941 1223.233 544.168 1227 544.305 c +1235.305 544.606 1243.588 544.364 1251.884 544.219 c +1256.600 544 1263.284 544.889 1264 539 c +1267 540 l +1265.564 538.550 1264.885 537.778 1264 536 c +1269 536 l +1270.582 538 1271 537.733 1273 536 c +1277 536 l +1278 540 l +1280 540 l +1281 536 l +1285 539 l +1285 537.203 1285 537.479 1286 536 c +1289.458 536.692 1293.276 537.234 1297 535 c +1296 534 l +1302 534 l +1299.979 533 1298 532.504 1296 532 c +1297.684 530.717 1299.572 529.475 1300 532 c +1305 529 l +1304 528 l +1307.472 528.329 1310.633 529 1314 530 c +1309.697 533.253 1304 534.641 1299 536.333 c +1286.644 540.449 1273.894 543.338 1261 545 c +1218.743 551 1176 544 1137 527.421 c +1123.816 521.779 1107.527 514.888 1097 505 c +f +*U +0.000 0.000 0.000 0.714 k +*u +1248.667 546.667 m +1248.223 546.223 1249.277 546.277 1249.333 546.333 c +1249.778 546.778 1248.722 546.722 1248.667 546.667 c +f +*U +0.000 0.000 0.000 0.471 k +*u +1250.667 546.667 m +1250.222 546.222 1251.278 546.278 1251.333 546.333 c +1251.778 546.778 1250.722 546.722 1250.667 546.667 c +f +*U +0.000 0.000 0.000 0.212 k +*u +1252.667 546.667 m +1252.222 546.222 1253.278 546.278 1253.333 546.333 c +1253.778 546.778 1252.722 546.722 1252.667 546.667 c +f +*U +0.000 0.000 0.000 0.333 k +*u +1199 546 m +1200 545 l +1199 546 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1200.667 545.667 m +1200.222 545.222 1201.278 545.278 1201.333 545.333 c +1201.778 545.778 1200.722 545.722 1200.667 545.667 c +f +*U +0.000 0.000 0.000 0.996 k +*u +1187 539 m +1188.648 538 1190.175 537.551 1192 537 c +1186.275 536.347 1181.495 537.749 1176 539 c +1177 537.985 1177.612 537.691 1179 537 c +1170.375 535.591 1164 536.497 1156 532 c +1156.406 529.907 1156.217 529.980 1158 529 c +1154.812 529 1152 530.303 1149 531 c +1148 528 l +1145.646 528 1144.232 527.791 1142 527 c +1144 523 l +1138.183 521.579 1132.916 520.993 1127 520 c +1128 512 l +1122.997 512.954 1117.879 512.549 1113 514 c +1111.862 511.207 1110 507.540 1112 505 c +1108 504.450 1104.859 506.945 1101 506 c +1094 504.285 1088.645 500 1083 495.846 c +1072.743 488.290 1063 479.954 1054 471 c +1048.283 465.376 1038.172 458.932 1040 450 c +1038.271 449 1037.406 448.392 1036 447 c +1036 449 l +1031.474 445.298 1030.846 441.527 1032 436 c +1030 437 l +1030.768 435.686 1030.686 435.768 1032 435 c +1030.723 433 1030.723 433.915 1032 432 c +1029 434 l +1026.227 431.732 1022.444 432.412 1019 432 c +1020 434 l +1008.634 430.453 995.831 432 984 432 c +921 432 l +710 432 l +271 432 l +127 432 l +101.328 432 74.463 429.782 49 433 c +53 434 l +51.542 435 50.752 435.436 49 436 c +48 432 l +43 434 l +44 432 l +39.342 432.898 35.518 432.375 31 431 c +30.695 424 23.491 425.482 20 421 c +24 421 l +22.469 419 20.951 417.532 19 416 c +19 420 l +16.912 418.828 15.321 411.481 13 414 c +11.275 412.723 10.221 412.314 12 411 c +10.316 410.776 9.687 410.782 8 411 c +8.980 409.217 8.908 409.406 11 409 c +8.299 407.261 7 406 6 403 c +7.267 401.457 7.489 400.952 8 399 c +4 400 l +6.466 394.711 7 390.778 8 385 c +6.814 386 6.396 386.339 5 387 c +6 384 l +4.373 385.717 4 385.899 5 388 c +4 393 l +-1.639 383.933 0 373.290 0 363 c +0 305 l +24 305 l +24 391 l +25 389 l +25.751 391 25.656 391.596 24 393 c +24.727 395.753 24.607 398.517 26 401 c +24 404 l +25.915 402.723 25 402.723 27 404 c +28 399 l +29.187 401.180 29.234 402.514 29 405 c +34.487 405.255 32.224 409 34.895 412.489 c +36.307 414.307 38.989 415 41 416 c +40.489 414 40.267 413.543 39 412 c +40 414 l +38.217 413 38.406 413 38 411 c +39.878 411.176 41.199 411.438 43 412 c +42 415 l +44.592 415 45.707 414.737 48 414 c +47 416 l +86.624 411 127.988 414 168 414 c +378 414 l +1024 414 l +1016.841 417 1005.744 415 998 415 c +941 415 l +743 415 l +56 415 l +64.280 417.448 74.393 416 83 416 c +137 416 l +312 416 l +886 416 l +995 416 l +1004.996 416 1015 416 1025 415.995 c +1030.506 415.905 1034.575 414.502 1039.826 417 c +1043.661 418.902 1046 422.759 1048.600 426 c +1052.525 430.910 1056.589 435.507 1060.985 439.999 c +1076.853 456.214 1093.284 471.210 1112 484 c +1126.948 494.423 1143 502.860 1160 509.550 c +1165.691 511.808 1175.917 512.565 1178 519 c +1179 517.466 1178.805 517.598 1180 517 c +1183.857 518.867 1189.271 518.625 1192 522 c +1195 521.472 1197 522 1200 523 c +1197.812 524.885 1195.713 526 1193 527 c +1196.767 526.871 1200.391 524.566 1203 528 c +1205.934 527.360 1208 527.360 1211 528 c +1209.952 526 1209.487 525 1209 523 c +1217 525 l +1214.761 525.811 1213.353 525.529 1211 525 c +1213 527 1214.000 528.429 1217 528 c +1219 527 l +1222.348 527.279 1226.657 528.965 1231 528 c +1232 527.747 1233.863 526.284 1235 526 c +1237.340 525.415 1239.191 526.397 1241 527 c +1242 526 l +1242 528 l +1243 526 l +1244.300 526.650 1244 526 1244 528 c +1244.986 526.521 1245 526.797 1245 525 c +1245.685 526.248 1245.749 526.549 1246 528 c +1248.855 527.294 1251 527.513 1254 528 c +1253 524 l +1255.378 524.181 1257.628 524.233 1260 524 c +1260 528 l +1261 525.538 1261.334 524.568 1264 524 c +1263 521 l +1271.274 520.324 1277.667 518.358 1286 520 c +1284.843 518.183 1284.855 518 1285 516 c +1286.528 517.474 1286.840 517.918 1287 520 c +1289.409 519.728 1291.581 519.799 1294 520 c +1294.307 517.877 1294.382 517.314 1296 516 c +1295 513 l +1298.604 512 1301.263 511.594 1304 509 c +1310.537 511.439 1311.791 507.453 1316 503 c +1318.992 503 1321.189 502.883 1324 504 c +1323 500 l +1325.420 501.382 1326 502.363 1327 505 c +1327.506 503 1327.686 502.268 1329 501 c +1327.744 499.263 1327.345 498 1327 496 c +1349.291 482.355 1368.859 466.798 1387 447.996 c +1396.451 438.263 1406.258 427.833 1413 416 c +1415.741 415.723 1417.586 414.291 1420 413 c +1420 414.797 1419.986 414.522 1419 416 c +1968 416 l +1968 432 l +1586 432 l +1480 432 l +1463.783 432 1443.713 428.891 1429 436 c +1427.990 434.831 1427.516 434.685 1426 434 c +1424 440 l +1418.649 440.829 1416.401 443.682 1416 449 c +1417 445 l +1418.739 448.573 1415.598 458.891 1411 455 c +1409.287 456.647 1408.306 456.631 1408 459 c +1409.478 458 1409.203 458 1411 458 c +1409.465 467.785 1397 476.545 1389.999 482.834 c +1374.955 496.309 1358.416 507.820 1341 517.988 c +1333.655 522.277 1323.626 528.946 1315 529.748 c +1311.380 530 1307.517 528.743 1304 528 c +1303.441 530.579 1302.466 530.972 1300 532 c +1300.000 529.312 1298.323 530.572 1296 531 c +1298 531.881 1299.854 532.496 1302 533 c +1299.948 533.874 1298.253 533.953 1296 534 c +1295.404 537.935 1289 536.731 1286 536 c +1285 539 l +1283 537.999 1282.901 537.923 1282 536 c +1280 540 l +1278 540 l +1277 536 l +1275.313 536.218 1274.684 536.224 1273 536 c +1271.722 538.898 1269.750 539.483 1269 536 c +1266.968 536.323 1266 536.340 1264 536 c +1267 539 l +1265.502 539.479 1265.650 539.400 1264 539 c +1263.720 545 1256.869 544.287 1252 544.487 c +1244 544.813 1235.971 544.989 1228 544.634 c +1223.594 544.438 1219.714 543.187 1216 546 c +1209.178 543.964 1201.981 544.830 1195 543 c +1192 542.248 1189.747 540.246 1187 539 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1258 546 m +1259 545 l +1258 546 l +f +*U +0.000 0.000 0.000 0.557 k +*u +1259 546 m +1260 545 l +1259 546 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1260 546 m +1261 545 l +1260 546 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1192 545 m +1193 544 l +1192 545 l +f +*U +0.000 0.000 0.000 0.424 k +*u +1193 545 m +1194 544 l +1193 545 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1194 545 m +1195 544 l +1194 545 l +f +*U +0.012 0.012 0.000 0.678 k +*u +1265 545 m +1266 544 l +1265 545 l +f +*U +0.008 0.008 0.000 0.435 k +*u +1266 545 m +1267 544 l +1266 545 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1267 545 m +1268 544 l +1267 545 l +f +*U +0.000 0.000 0.000 0.267 k +*u +1187 544 m +1188 543 l +1187 544 l +f +*U +0.000 0.000 0.000 0.553 k +*u +1188 544 m +1189 543 l +1188 544 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1189 544 m +1190 543 l +1189 544 l +f +*U +0.000 0.000 0.000 0.686 k +*u +1271 544 m +1272 543 l +1271 544 l +f +*U +0.000 0.000 0.000 0.314 k +*u +1272 544 m +1273 543 l +1272 544 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1182 543 m +1183 542 l +1182 543 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1183 543 m +1184 542 l +1183 543 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1276 543 m +1277 542 l +1276 543 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1277 543 m +1278 542 l +1277 543 l +f +*U +0.000 0.000 0.000 0.286 k +*u +1178 542 m +1179 541 l +1178 542 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1179 542 m +1180 541 l +1179 542 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1280 542 m +1281 541 l +1280 542 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1281 542 m +1282 541 l +1281 542 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1174 541 m +1175 540 l +1174 541 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1175 541 m +1176 540 l +1175 541 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1284 541 m +1285 540 l +1284 541 l +f +*U +0.000 0.000 0.000 0.424 k +*u +1285 541 m +1286 540 l +1285 541 l +f +*U +0.000 0.000 0.000 0.294 k +*u +1170 540 m +1171 539 l +1170 540 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1171 540 m +1172 539 l +1171 540 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1288 540 m +1289 539 l +1288 540 l +f +*U +0.000 0.000 0.000 0.302 k +*u +1289 540 m +1290 539 l +1289 540 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1166 539 m +1167 538 l +1166 539 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1167 539 m +1168 538 l +1167 539 l +f +*U +0.000 0.000 0.000 0.416 k +*u +1292 539 m +1293 538 l +1292 539 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1163 538 m +1164 537 l +1163 538 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1164 538 m +1165 537 l +1164 538 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1295 538 m +1296 537 l +1295 538 l +f +*U +0.000 0.000 0.000 0.376 k +*u +1160 537 m +1161 536 l +1160 537 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1161 537 m +1162 536 l +1161 537 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1298 537 m +1299 536 l +1298 537 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1299 537 m +1300 536 l +1299 537 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1157 536 m +1158 535 l +1157 536 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1158 536 m +1159 535 l +1158 536 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1301 536 m +1302 535 l +1301 536 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1302 536 m +1303 535 l +1302 536 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1154 535 m +1155 534 l +1154 535 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1304 535 m +1305 534 l +1304 535 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1151 534 m +1152 533 l +1151 534 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1152 534 m +1153 533 l +1152 534 l +f +*U +0.000 0.000 0.000 0.557 k +*u +1307 534 m +1308 533 l +1307 534 l +f +*U +0.000 0.000 0.000 0.576 k +*u +1149 533 m +1150 532 l +1149 533 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1309 533 m +1310 532 l +1309 533 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1310 533 m +1311 532 l +1310 533 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1146 532 m +1147 531 l +1146 532 l +f +*U +0.000 0.000 0.000 0.576 k +*u +1312 532 m +1313 531 l +1312 532 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1144 531 m +1145 530 l +1144 531 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1314 531 m +1315 530 l +1314 531 l +f +*U +0.000 0.000 0.000 0.278 k +*u +1141 530 m +1142 529 l +1141 530 l +f +*U +0.000 0.000 0.000 0.357 k +*u +1317 530 m +1318 529 l +1317 530 l +f +*U +0.000 0.000 0.000 0.392 k +*u +1139 529 m +1140 528 l +1139 529 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1319 529 m +1320 528 l +1319 529 l +f +*U +0.000 0.000 0.000 0.267 k +*u +1136 528 m +1137 527 l +1136 528 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1137 528 m +1138 527 l +1137 528 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1193 528 m +1195.187 525.968 1197 524.906 1200 524 c +1197.184 522.642 1195 521.920 1192 522 c +1189.177 519.689 1182.345 517 1179 519 c +1177.407 514.799 1183.789 517 1186 517.630 c +1194.832 519.818 1203.937 521.406 1213 522 c +1239.991 524 1266.293 521.434 1292 512.319 c +1303.849 508 1315 500.221 1327 497 c +1327.689 498.688 1327.676 499 1329 500 c +1327.825 501.879 1327.870 502.716 1328 505 c +1323 500 l +1324 504 l +1321.301 503.264 1318.766 503.253 1316 503 c +1312.638 508.242 1310.278 512.630 1304 509 c +1301.737 512 1298.686 512.301 1295 513 c +1295.986 514.479 1296 514.203 1296 516 c +1294.733 517.543 1294.511 518 1294 520 c +1287 520 l +1287 517.898 1286.455 517.629 1285 516 c +1284.930 517.952 1284.646 517.940 1286 519 c +1283 520 1280 518.908 1277 518.998 c +1272.265 519 1267.750 520.793 1263 521 c +1263.986 522.479 1264 522.203 1264 524 c +1261.965 525.226 1261.674 525.702 1261 528 c +1260.317 526.494 1260.174 525.685 1260 524 c +1257.353 524.578 1255.636 524.607 1253 524 c +1254 528 l +1250.641 527.802 1246.615 528.853 1246 525 c +1245 526.479 1245 526.203 1245 528 c +1243.804 527.402 1244 527.534 1243 526 c +1243 528 l +1241.700 527.350 1242 527.853 1242 526 c +1233.779 527 1217.519 531.663 1211 525 c +1217 526 l +1209 523 l +1211 528 l +1208.194 527.598 1205.806 527.598 1203 528 c +1199.774 525 1196.868 527.178 1193 528 c +f +*U +0.000 0.000 0.000 0.212 k +*u +1322 528 m +1323 527 l +1322 528 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1134 527 m +1135 526 l +1134 527 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1324 527 m +1325 526 l +1324 527 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1132 526 m +1133 525 l +1132 526 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1326 526 m +1327 525 l +1326 526 l +f +*U +0.000 0.000 0.000 0.341 k +*u +1130 525 m +1131 524 l +1130 525 l +f +*U +0.000 0.000 0.000 0.306 k +*u +1328 525 m +1329 524 l +1328 525 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1128 524 m +1129 523 l +1128 524 l +f +*U +0.000 0.000 0.000 0.427 k +*u +1330 524 m +1331 523 l +1330 524 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1126 523 m +1127 522 l +1126 523 l +f +*U +0.000 0.000 0.000 0.612 k +*u +1216.667 522.667 m +1216.223 522.223 1217.277 522.277 1217.333 522.333 c +1217.778 522.778 1216.722 522.722 1216.667 522.667 c +f +*U +0.000 0.000 0.000 0.478 k +*u +1218 523 m +1219.249 522.315 1219.548 522.251 1221 522 c +1219.752 522.685 1219.451 522.749 1218 523 c +f +*U +0.000 0.000 0.000 0.290 k +*u +1221 523 m +1222.248 522.315 1222.548 522.251 1224 522 c +1222.752 522.685 1222.451 522.749 1221 523 c +f +*U +0.024 0.000 0.020 0.125 k +*u +1224 523 m +1227.698 521.448 1232 522 1236 522 c +1232.303 523.552 1227.983 523 1224 523 c +f +*U +0.000 0.000 0.000 0.314 k +*u +1236 523 m +1237.769 522.221 1239 522 1241 522 c +1239.231 522.779 1237.964 522.912 1236 523 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1241.667 522.667 m +1241.222 522.222 1242.278 522.278 1242.333 522.333 c +1242.778 522.778 1241.722 522.722 1241.667 522.667 c +f +*U +0.000 0.000 0.000 0.867 k +*u +1243.667 522.667 m +1243.223 522.223 1244.277 522.277 1244.333 522.333 c +1244.778 522.778 1243.722 522.722 1243.667 522.667 c +f +*U +0.000 0.000 0.000 0.404 k +*u +1332 523 m +1333 522 l +1332 523 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1124 522 m +1125 521 l +1124 522 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1206 522 m +1207 521 l +1206 522 l +f +*U +0.000 0.000 0.000 0.427 k +*u +1207.667 521.667 m +1207.223 521.223 1208.277 521.277 1208.333 521.333 c +1208.778 521.778 1207.722 521.722 1207.667 521.667 c +f +*U +0.000 0.000 0.000 0.235 k +*u +1209 522 m +1210 521 l +1209 522 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1250 522 m +1251.248 521.315 1251.548 521.251 1253 521 c +1251.752 521.685 1251.451 521.749 1250 522 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1253 522 m +1254 521 l +1253 522 l +f +*U +0.000 0.000 0.000 0.459 k +*u +1334 522 m +1335 521 l +1334 522 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1122 521 m +1123 520 l +1122 521 l +f +*U +0.000 0.000 0.000 0.608 k +*u +1200 521 m +1201 520 l +1200 521 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1201 521 m +1202 520 l +1201 521 l +f +*U +0.000 0.000 0.000 0.310 k +*u +1258 521 m +1259 520 l +1258 521 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1259 521 m +1260 520 l +1259 521 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1260 521 m +1261 520 l +1260 521 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1336 521 m +1337 520 l +1336 521 l +f +*U +0.000 0.000 0.000 0.443 k +*u +1120 520 m +1121 519 l +1120 520 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1194 520 m +1195 519 l +1194 520 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1195 520 m +1196 519 l +1195 520 l +f +*U +0.012 0.012 0.000 0.341 k +*u +1264 520 m +1265 519 l +1264 520 l +f +*U +0.008 0.008 0.000 0.608 k +*u +1265 520 m +1266 519 l +1265 520 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1338 520 m +1339 519 l +1338 520 l +f +*U +0.000 0.000 0.000 0.329 k +*u +1118 519 m +1119 518 l +1118 519 l +f +*U +0.000 0.000 0.008 0.733 k +*u +1189 519 m +1190 518 l +1189 519 l +f +*U +0.000 0.000 0.008 0.396 k +*u +1190 519 m +1191 518 l +1190 519 l +f +*U +0.000 0.000 0.008 0.310 k +*u +1269 519 m +1270 518 l +1269 519 l +f +*U +0.000 0.000 0.008 0.741 k +*u +1270 519 m +1271 518 l +1270 519 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1116 518 m +1117 517 l +1116 518 l +f +*U +0.008 0.008 0.000 0.627 k +*u +1185 518 m +1186 517 l +1185 518 l +f +*U +0.008 0.008 0.000 0.282 k +*u +1186 518 m +1187 517 l +1186 518 l +f +*U +0.008 0.008 0.000 0.224 k +*u +1273 518 m +1274 517 l +1273 518 l +f +*U +0.008 0.008 0.000 0.655 k +*u +1274 518 m +1275 517 l +1274 518 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1341 518 m +1342 517 l +1341 518 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1115 517 m +1116 516 l +1115 517 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1181 517 m +1182 516 l +1181 517 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1182 517 m +1183 516 l +1182 517 l +f +*U +0.012 0.012 0.000 0.184 k +*u +1277 517 m +1278 516 l +1277 517 l +f +*U +0.008 0.008 0.000 0.690 k +*u +1278 517 m +1279 516 l +1278 517 l +f +*U +0.000 0.000 0.000 0.322 k +*u +1343 517 m +1344 516 l +1343 517 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1113 516 m +1114 515 l +1113 516 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1177 516 m +1178 515 l +1177 516 l +f +*U +0.000 0.000 0.000 0.384 k +*u +1178 516 m +1179 515 l +1178 516 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1281 516 m +1282 515 l +1281 516 l +f +*U +0.000 0.000 0.000 0.463 k +*u +1111 515 m +1112 514 l +1111 515 l +f +*U +0.000 0.000 0.000 0.510 k +*u +1174 515 m +1175 514 l +1174 515 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1284 515 m +1285 514 l +1284 515 l +f +*U +0.000 0.000 0.000 0.643 k +*u +1285 515 m +1286 514 l +1285 515 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1346 515 m +1347 514 l +1346 515 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1109 514 m +1110 513 l +1109 514 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1171 514 m +1172 513 l +1171 514 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1288 514 m +1289 513 l +1288 514 l +f +*U +0.000 0.000 0.000 0.412 k +*u +1348 514 m +1349 513 l +1348 514 l +f +*U +0.000 0.000 0.000 0.290 k +*u +1168 513 m +1169 512 l +1168 513 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1290 513 m +1291 512 l +1290 513 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1291 513 m +1292 512 l +1291 513 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1350 513 m +1351 512 l +1350 513 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1106 512 m +1107 511 l +1106 512 l +f +*U +0.000 0.000 0.000 0.502 k +*u +1165 512 m +1166 511 l +1165 512 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1294 512 m +1295 511 l +1294 512 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1351 512 m +1352 511 l +1351 512 l +f +*U +0.000 0.000 0.000 0.259 k +*u +1104 511 m +1105 510 l +1104 511 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1162 511 m +1163 510 l +1162 511 l +f +*U +0.000 0.000 0.000 0.380 k +*u +1296 511 m +1297 510 l +1296 511 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1353 511 m +1354 510 l +1353 511 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1103 510 m +1104 509 l +1103 510 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1159 510 m +1160 509 l +1159 510 l +f +*U +0.000 0.000 0.000 0.600 k +*u +1299 510 m +1300 509 l +1299 510 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1101 509 m +1102 508 l +1101 509 l +f +*U +0.000 0.000 0.000 0.455 k +*u +1157 509 m +1158 508 l +1157 509 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1301 509 m +1302 508 l +1301 509 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1302 509 m +1303 508 l +1302 509 l +f +*U +0.000 0.000 0.000 0.471 k +*u +1356 509 m +1357 508 l +1356 509 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1155 508 m +1156 507 l +1155 508 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1098 507 m +1099 506 l +1098 507 l +f +*U +0.000 0.000 0.000 0.431 k +*u +1152 507 m +1153 506 l +1152 507 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1306 507 m +1307 506 l +1306 507 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1359 507 m +1360 506 l +1359 507 l +f +*U +0.000 0.000 0.000 0.420 k +*u +1150 506 m +1151 505 l +1150 506 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1308 506 m +1309 505 l +1308 506 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1360 506 m +1361 505 l +1360 506 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1095 505 m +1096 504 l +1095 505 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1148 505 m +1149 504 l +1148 505 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1310 505 m +1311 504 l +1310 505 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1362 505 m +1363 504 l +1362 505 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1145 504 m +1146 503 l +1145 504 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1146 504 m +1147 503 l +1146 504 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1313 504 m +1314 503 l +1313 504 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1363 504 m +1364 503 l +1363 504 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1092 503 m +1093 502 l +1092 503 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1143 503 m +1144 502 l +1143 503 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1314 503 m +1315 502 l +1314 503 l +f +*U +0.000 0.000 0.000 0.624 k +*u +1141 502 m +1142 501 l +1141 502 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1317 502 m +1318 501 l +1317 502 l +f +*U +0.000 0.000 0.000 0.310 k +*u +1366 502 m +1367 501 l +1366 502 l +f +*U +0.000 0.000 0.000 0.408 k +*u +1089 501 m +1090 500 l +1089 501 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1139 501 m +1140 500 l +1139 501 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1318 501 m +1319 500 l +1318 501 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1088 500 m +1089 499 l +1088 500 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1137 500 m +1138 499 l +1137 500 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1320 500 m +1321 499 l +1320 500 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1369 500 m +1370 499 l +1369 500 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1086 499 m +1087 498 l +1086 499 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1135 499 m +1136 498 l +1135 499 l +f +*U +0.000 0.000 0.000 0.235 k +*u +1322 499 m +1323 498 l +1322 499 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1370 499 m +1371 498 l +1370 499 l +f +*U +0.000 0.000 0.000 0.467 k +*u +1085 498 m +1086 497 l +1085 498 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1134 498 m +1135 497 l +1134 498 l +f +*U +0.000 0.000 0.000 0.353 k +*u +1324 498 m +1325 497 l +1324 498 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1326 497 m +1327 496 l +1326 497 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1373 497 m +1374 496 l +1373 497 l +f +*U +0.000 0.000 0.000 0.192 k +*u +1082 496 m +1083 495 l +1082 496 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1130 496 m +1131 495 l +1130 496 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1374 496 m +1375 495 l +1374 496 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1081 495 m +1082 494 l +1081 495 l +f +*U +0.000 0.000 0.000 0.447 k +*u +1128 495 m +1129 494 l +1128 495 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1126 494 m +1127 493 l +1126 494 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1331 494 m +1332 493 l +1331 494 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1377 494 m +1378 493 l +1377 494 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1078 493 m +1079 492 l +1078 493 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1125 493 m +1126 492 l +1125 493 l +f +*U +0.000 0.000 0.000 0.314 k +*u +1378 493 m +1379 492 l +1378 493 l +f +1077 492 m +1078 491 l +1077 492 l +f +*U +0.000 0.000 0.000 0.404 k +*u +1123 492 m +1124 491 l +1123 492 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1334 492 m +1335 491 l +1334 492 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1379 492 m +1380 491 l +1379 492 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1076 491 m +1077 490 l +1076 491 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1121 491 m +1122 490 l +1121 491 l +f +*U +0.000 0.000 0.000 0.627 k +*u +1336 491 m +1337 490 l +1336 491 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1380 491 m +1381 490 l +1380 491 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1120 490 m +1121 489 l +1120 490 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1337 490 m +1338 489 l +1337 490 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1118 489 m +1119 488 l +1118 489 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1339 489 m +1340 488 l +1339 489 l +f +*U +0.000 0.000 0.000 0.439 k +*u +1072 488 m +1073 487 l +1072 488 l +f +*U +0.000 0.000 0.000 0.525 k +*u +1384 488 m +1385 487 l +1384 488 l +f +*U +0.000 0.000 0.000 0.537 k +*u +1115 487 m +1116 486 l +1115 487 l +f +*U +0.000 0.000 0.000 0.490 k +*u +1342 487 m +1343 486 l +1342 487 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1385 487 m +1386 486 l +1385 487 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1113 486 m +1114 485 l +1113 486 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1386 486 m +1387 485 l +1386 486 l +f +*U +0.000 0.000 0.000 0.482 k +*u +1112 485 m +1113 484 l +1112 485 l +f +*U +0.000 0.000 0.000 0.439 k +*u +1345 485 m +1346 484 l +1345 485 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1067 484 m +1068 483 l +1067 484 l +f +1346 484 m +1347 483 l +1346 484 l +f +*U +0.000 0.000 0.000 0.506 k +*u +1066 483 m +1067 482 l +1066 483 l +f +1109 483 m +1110 482 l +1109 483 l +f +*U +0.000 0.000 0.000 0.816 k +*u +1348 483 m +1349 482 l +1348 483 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1065 482 m +1066 481 l +1065 482 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1349 482 m +1350 481 l +1349 482 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1391 482 m +1392 481 l +1391 482 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1064 481 m +1065 480 l +1064 481 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1106 481 m +1107 480 l +1106 481 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1392 481 m +1393 480 l +1392 481 l +f +*U +0.000 0.000 0.000 0.816 k +*u +1063 480 m +1064 479 l +1063 480 l +f +*U +0.000 0.333 0.275 0.169 k +*u +1209 480 m +1210.769 479.221 1212 479 1214 479 c +1212.231 479.779 1210.964 479.912 1209 480 c +f +*U +0.000 0.310 0.216 0.306 k +*u +1214.667 479.667 m +1214.222 479.222 1215.278 479.278 1215.333 479.333 c +1215.778 479.778 1214.722 479.722 1214.667 479.667 c +f +*U +0.000 0.682 0.471 0.220 k +*u +1216.667 479.667 m +1216.222 479.222 1217.278 479.278 1217.333 479.333 c +1217.778 479.778 1216.722 479.722 1216.667 479.667 c +f +*U +0.000 0.584 0.416 0.416 k +*u +1218 480 m +1220.890 478.787 1223.874 479 1227 479 c +1224 480.213 1221 479.998 1218 480 c +f +*U +0.000 0.482 0.482 0.518 k +*u +1227 480 m +1228.769 479.221 1230 479 1232 479 c +1230.231 479.779 1228.964 479.912 1227 480 c +f +*U +0.000 0.549 0.522 0.380 k +*u +1232.667 479.667 m +1232.222 479.222 1233.278 479.278 1233.333 479.333 c +1233.778 479.778 1232.722 479.722 1232.667 479.667 c +f +*U +0.000 0.384 0.416 0.165 k +*u +1234 480 m +1235.249 479.315 1235.548 479.251 1237 479 c +1235.752 479.685 1235.452 479.749 1234 480 c +f +*U +0.000 0.145 0.255 0.161 k +*u +1237.667 479.667 m +1237.222 479.222 1238.278 479.278 1238.333 479.333 c +1238.778 479.777 1237.722 479.722 1237.667 479.667 c +f +*U +0.000 0.000 0.000 0.494 k +*u +1393 480 m +1394 479 l +1393 480 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1103 479 m +1104 478 l +1103 479 l +f +*U +0.000 0.239 0.208 0.008 k +*u +1201 479 m +1202 478 l +1201 479 l +f +*U +0.000 0.302 0.251 0.149 k +*u +1202 479 m +1203 478 l +1202 479 l +f +*U +0.000 0.392 0.310 0.290 k +*u +1203 479 m +1204 478 l +1203 479 l +f +*U +0.000 0.514 0.416 0.486 k +*u +1204 479 m +1205.506 478.317 1206.315 478.174 1208 478 c +1206.494 478.683 1205.685 478.826 1204 479 c +f +*U +0.000 0.851 0.698 0.149 k +*u +1208 477 m +1212 477.749 1215.899 477.997 1220 478 c +1216.479 479.478 1210.661 480 1208 477 c +f +*U +0.000 0.863 0.616 0.129 k +*u +1186 475 m +1187 472 l +1211.465 475.213 1236.492 471.285 1261 473 c +1258 477.519 1245.341 477.930 1240 478 c +1227.931 478.172 1216 478.866 1204 477.802 c +1197.857 477.262 1192.257 475 1186 475 c +f +*U +0.000 0.694 0.424 0.306 k +*u +1233 479 m +1235.332 478 1237.457 478 1240 478 c +1237.669 478.984 1235.543 478.981 1233 479 c +f +*U +0.000 0.451 0.435 0.549 k +*u +1240 479 m +1241.769 478.221 1243 478 1245 478 c +1243.231 478.779 1241.964 478.912 1240 479 c +f +*U +0.000 0.475 0.373 0.259 k +*u +1245 479 m +1246 478 l +1245 479 l +f +*U +0.000 0.435 0.325 0.000 k +*u +1246.667 478.667 m +1246.222 478.222 1247.278 478.278 1247.333 478.333 c +1247.778 478.778 1246.722 478.722 1246.667 478.667 c +f +*U +0.000 0.000 0.000 0.392 k +*u +1353 479 m +1354 478 l +1353 479 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1394 479 m +1395 478 l +1394 479 l +f +*U +0.000 0.000 0.000 0.494 k +*u +1102 478 m +1103 477 l +1102 478 l +f +*U +0.000 0.259 0.118 0.129 k +*u +1195 478 m +1196 477 l +1195 478 l +f +*U +0.000 0.388 0.204 0.286 k +*u +1196 478 m +1197 477 l +1196 478 l +f +*U +0.000 0.624 0.494 0.376 k +*u +1197 478 m +1198.769 477.221 1200 477 1202 477 c +1200.231 477.779 1198.964 477.912 1197 478 c +f +*U +0.000 0.518 0.349 0.482 k +*u +1248 478 m +1249.506 477.317 1250.315 477.174 1252 477 c +1250.494 477.683 1249.685 477.826 1248 478 c +f +*U +0.000 0.298 0.224 0.204 k +*u +1252.667 477.667 m +1252.222 477.222 1253.278 477.278 1253.333 477.333 c +1253.778 477.778 1252.722 477.722 1252.667 477.667 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1395 478 m +1396 477 l +1395 478 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1101 477 m +1102 476 l +1101 477 l +f +*U +0.000 0.341 0.263 0.141 k +*u +1190 477 m +1191 476 l +1190 477 l +f +*U +0.000 0.451 0.263 0.290 k +*u +1191 477 m +1192 476 l +1191 477 l +f +*U +0.000 0.741 0.659 0.259 k +*u +1192 477 m +1194 476 1195.747 476 1198 476 c +1195.948 476.874 1194.253 476.953 1192 477 c +f +*U +0.000 0.910 0.918 0.063 k +*u +1248 477 m +1249.769 476.221 1251 476 1253 476 c +1251.231 476.779 1249.964 476.912 1248 477 c +f +*U +0.000 0.718 0.667 0.282 k +*u +1253 477 m +1254.248 476.315 1254.548 476.251 1256 476 c +1254.752 476.685 1254.451 476.749 1253 477 c +f +*U +0.000 0.416 0.200 0.584 k +*u +1256 477 m +1257 476 l +1256 477 l +f +*U +0.000 0.373 0.267 0.337 k +*u +1257 477 m +1258 476 l +1257 477 l +f +*U +0.000 0.149 0.043 0.129 k +*u +1258.667 476.667 m +1258.222 476.222 1259.278 476.278 1259.333 476.333 c +1259.778 476.777 1258.722 476.722 1258.667 476.667 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1356 477 m +1357 476 l +1356 477 l +f +*U +0.000 0.043 0.204 0.290 k +*u +1184.667 475.667 m +1184.222 475.222 1185.278 475.278 1185.333 475.333 c +1185.778 475.778 1184.722 475.722 1184.667 475.667 c +f +*U +0.000 0.341 0.153 0.357 k +*u +1186 476 m +1187 475 l +1186 476 l +f +*U +0.000 0.675 0.412 0.325 k +*u +1187 476 m +1189.332 475 1191.457 475 1194 475 c +1191.668 475.984 1189.544 475.981 1187 476 c +f +*U +0.000 0.514 0.322 0.486 k +*u +1260 476 m +1261.249 475.315 1261.548 475.251 1263 475 c +1261.752 475.685 1261.451 475.749 1260 476 c +f +*U +0.000 0.412 0.137 0.078 k +*u +1263 476 m +1264 475 l +1263 476 l +f +*U +0.000 0.000 0.000 0.518 k +*u +1357 476 m +1358 475 l +1357 476 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1397 476 m +1398 475 l +1397 476 l +f +*U +0.000 0.000 0.000 0.365 k +*u +1057 475 m +1058 474 l +1057 475 l +f +*U +0.000 0.000 0.000 0.388 k +*u +1098 475 m +1099 474 l +1098 475 l +f +*U +0.000 0.275 0.231 0.059 k +*u +1181 475 m +1182 474 l +1181 475 l +f +*U +0.000 0.435 0.314 0.322 k +*u +1182 475 m +1183 474 l +1182 475 l +f +*U +0.000 0.635 0.655 0.345 k +*u +1183 475 m +1184.249 474.315 1184.548 474.251 1186 474 c +1184.752 474.685 1184.452 474.749 1183 475 c +f +*U +0.000 0.796 0.592 0.204 k +*u +1261 475 m +1262 473 l +1263.635 473.545 1263.455 473.365 1264 475 c +1261 475 l +f +*U +0.000 0.522 0.373 0.443 k +*u +1264.667 474.667 m +1264.222 474.222 1265.278 474.278 1265.333 474.333 c +1265.778 474.778 1264.722 474.722 1264.667 474.667 c +f +*U +0.000 0.435 0.278 0.227 k +*u +1266 475 m +1267 474 l +1266 475 l +f +*U +0.000 0.314 0.200 0.039 k +*u +1267 475 m +1268 474 l +1267 475 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1398 475 m +1399 474 l +1398 475 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1056 474 m +1057 473 l +1056 474 l +f +*U +0.000 0.000 0.000 0.231 k +*u +1097 474 m +1098 473 l +1097 474 l +f +*U +0.000 0.216 0.192 0.043 k +*u +1177 474 m +1178 473 l +1177 474 l +f +*U +0.000 0.333 0.239 0.337 k +*u +1178 474 m +1179 473 l +1178 474 l +f +*U +0.000 0.573 0.518 0.427 k +*u +1179.667 473.667 m +1179.222 473.222 1180.278 473.278 1180.333 473.333 c +1180.778 473.778 1179.722 473.722 1179.667 473.667 c +f +*U +0.000 0.859 0.694 0.141 k +*u +1181 474 m +1182.750 472.745 1183.857 472.386 1186 472 c +1184.460 473.803 1183.403 473.832 1181 474 c +f +*U +0.000 0.843 0.910 0.090 k +*u +1186.333 473.333 m +1186.278 473.278 1186.222 472.222 1186.667 472.667 c +1186.723 472.723 1186.777 473.778 1186.333 473.333 c +f +*U +0.000 0.910 0.788 0.090 k +*u +1258 473 m +1262.216 471.231 1267.459 472 1272 472 c +1267.693 474 1262.585 474.272 1258 473 c +f +*U +0.000 0.518 0.471 0.455 k +*u +1267 474 m +1268.248 473.315 1268.548 473.251 1270 473 c +1268.752 473.685 1268.452 473.749 1267 474 c +f +*U +0.000 0.263 0.263 0.341 k +*u +1270 474 m +1271 473 l +1270 474 l +f +*U +0.000 0.239 0.196 0.176 k +*u +1271 474 m +1272 473 l +1271 474 l +f +*U +0.000 0.000 0.000 0.745 k +*u +1399 474 m +1400 473 l +1399 474 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1055 473 m +1056 472 l +1055 473 l +f +*U +0.000 0.027 0.020 0.322 k +*u +1173 471 m +1176 471 l +1175 473 l +1173.365 472.455 1173.545 472.635 1173 471 c +f +*U +0.000 0.502 0.502 0.498 k +*u +1175 473 m +1176.248 472.315 1176.548 472.251 1178 472 c +1176.752 472.685 1176.451 472.749 1175 473 c +f +*U +0.000 0.973 0.914 0.027 k +*u +1178 473 m +1179.769 472.221 1181 472 1183 472 c +1181.231 472.779 1179.964 472.912 1178 473 c +f +*U +0.000 0.918 0.918 0.082 k +*u +1188.667 472.667 m +1188.222 472.222 1189.278 472.278 1189.333 472.333 c +1189.778 472.778 1188.722 472.722 1188.667 472.667 c +f +*U +0.000 1.000 1.000 0.000 k +*u +1191 473 m +1192.769 472.221 1194 472 1196 472 c +1194.231 472.779 1192.964 472.912 1191 473 c +f +*U +0.000 0.776 0.847 0.153 k +*u +1196 473 m +1198 472 1199.747 472 1202 472 c +1199.948 472.874 1198.253 472.953 1196 473 c +f +*U +0.000 1.000 1.000 0.000 k +*u +1202 473 m +1206.720 471 1212.920 472 1218 472 c +1251 472 l +1246.280 473.981 1240 473 1235 473 c +1202 473 l +f +*U +0.000 0.820 0.875 0.125 k +*u +1251 473 m +1252.769 472.221 1254 472 1256 472 c +1254.231 472.779 1252.964 472.912 1251 473 c +f +*U +0.000 0.467 0.333 0.506 k +*u +1272.667 472.667 m +1272.222 472.222 1273.278 472.278 1273.333 472.333 c +1273.778 472.778 1272.722 472.722 1272.667 472.667 c +f +*U +0.000 0.122 0.035 0.180 k +*u +1176 472 m +1184.358 468.493 1197.940 471 1207 471 c +1276 471 l +1273 472.638 1270.260 472 1267 472 c +1260.668 471.941 1254.332 472 1248 472 c +1176 472 l +f +*U +0.000 0.000 0.000 0.753 k +*u +1361 473 m +1362 472 l +1361 473 l +f +*U +0.000 0.000 0.004 0.827 k +*u +1400 473 m +1401 472 l +1400 473 l +f +*U +0.000 0.000 0.000 0.494 k +*u +1054 472 m +1055 471 l +1054 472 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1094 472 m +1095 471 l +1094 472 l +f +*U +0.000 0.000 0.000 0.471 k +*u +1362 472 m +1363 471 l +1362 472 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1053 471 m +1054 470 l +1053 471 l +f +*U +0.000 0.000 0.000 0.341 k +*u +1093 471 m +1094 470 l +1093 471 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1363 471 m +1364 470 l +1363 471 l +f +*U +0.008 0.008 0.000 0.745 k +*u +1402 471 m +1403 470 l +1402 471 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1052 470 m +1053 469 l +1052 470 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1051 469 m +1052 468 l +1051 469 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1050 468 m +1051 467 l +1050 468 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1089 468 m +1090 467 l +1089 468 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1049 467 m +1050 466 l +1049 467 l +f +*U +0.000 0.000 0.000 0.510 k +*u +1088 467 m +1089 466 l +1088 467 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1368 467 m +1369 466 l +1368 467 l +f +*U +0.000 0.000 0.008 0.765 k +*u +1406 467 m +1407 466 l +1406 467 l +f +*U +0.000 0.000 0.000 0.294 k +*u +1087 466 m +1088 465 l +1087 466 l +f +*U +0.000 0.000 0.000 0.396 k +*u +1369 466 m +1370 465 l +1369 466 l +f +*U +0.000 0.000 0.008 0.639 k +*u +1407 466 m +1408 465 l +1407 466 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1047 465 m +1048 464 l +1047 465 l +f +*U +0.000 0.000 0.000 0.443 k +*u +1370 465 m +1371 464 l +1370 465 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1408 465 m +1409 464 l +1408 465 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1046 464 m +1047 463 l +1046 464 l +f +*U +0.000 0.000 0.000 0.251 k +*u +1371 464 m +1372 463 l +1371 464 l +f +*U +0.000 0.000 0.008 0.651 k +*u +1409 464 m +1410 463 l +1409 464 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1045 463 m +1046 462 l +1045 463 l +f +*U +0.000 0.000 0.008 0.663 k +*u +1410 463 m +1411 462 l +1410 463 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1044 462 m +1045 461 l +1044 462 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1082 462 m +1083 461 l +1082 462 l +f +*U +0.000 0.000 0.008 0.251 k +*u +1411 462 m +1412 461 l +1411 462 l +f +*U +0.000 0.000 0.000 0.729 k +*u +1043 461 m +1044 460 l +1043 461 l +f +*U +0.000 0.000 0.000 0.463 k +*u +1081 461 m +1082 460 l +1081 461 l +f +*U +0.000 0.271 0.192 0.224 k +*u +1145 461 m +1146 460 l +1145 461 l +f +*U +0.000 0.400 0.282 0.600 k +*u +1146 461 m +1152.202 458.397 1161.298 460 1168 460 c +1161.797 462.603 1152.702 461 1146 461 c +f +*U +0.000 0.569 0.451 0.431 k +*u +1168 461 m +1169.969 459.937 1171.798 459.468 1174 459 c +1171.943 460.582 1170.613 460.826 1168 461 c +f +*U +0.000 0.278 0.259 0.722 k +*u +1173 461 m +1174.249 460.315 1174.548 460.251 1176 460 c +1174.752 460.685 1174.452 460.749 1173 461 c +f +*U +0.004 0.000 0.000 0.741 k +*u +1176 461 m +1177 460 l +1176 461 l +f +*U +0.000 0.424 0.345 0.576 k +*u +1283 461 m +1288.469 458.705 1296 460 1302 460 c +1296.531 462.295 1288.901 461 1283 461 c +f +*U +0.000 0.286 0.200 0.333 k +*u +1302.667 460.667 m +1302.222 460.222 1303.278 460.278 1303.333 460.333 c +1303.778 460.778 1302.722 460.722 1302.667 460.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1411 461 m +1409.723 459 1409.723 459.915 1411 458 c +1408 459 l +1408.275 456.730 1409.181 456.721 1410 455 c +1415.614 458.509 1418 449.335 1418 445 c +1417 449 l +1414.756 443.432 1418.748 440.397 1424 440 c +1426 434 l +1428.670 434.534 1428.443 433.215 1429 436 c +1439.506 428.578 1458.445 432 1471 432 c +1574 432 l +1968 432 l +1968 415 l +1619 415 l +1552.427 415 1485.454 413 1419 416 c +1420 413 l +1418 414.486 1416 415.836 1414 417 c +1419 407 1438.511 411 1448 411 c +1549 411 l +1974 411 l +1974 435 l +1592 435 l +1481 435 l +1449 435 l +1444.596 435 1438.312 433.875 1434.184 435.603 c +1430.813 437 1428.585 441.253 1426.399 444 c +1421.695 449.910 1417 456.566 1411 461 c +f +*U +0.000 0.000 0.008 0.200 k +*u +1412 461 m +1413 460 l +1412 461 l +f +*U +0.000 0.000 0.000 0.682 k +*u +1042 460 m +1043 459 l +1042 460 l +f +*U +0.000 0.000 0.000 0.400 k +*u +1080 460 m +1081 459 l +1080 460 l +f +*U +0.000 0.153 0.137 0.180 k +*u +1143 460 m +1144 459 l +1143 460 l +f +*U +0.000 0.686 0.506 0.314 k +*u +1144 460 m +1145.248 459.315 1145.548 459.251 1147 459 c +1145.752 459.685 1145.451 459.749 1144 460 c +f +*U +0.000 0.875 0.620 0.125 k +*u +1133 452 m +1133 450 l +1143.965 447.389 1159.403 448.480 1166 459 c +1168 458.754 1169.874 458.769 1172 459 c +1168.565 460.441 1164.703 460 1161 460 c +1156 460 1150.724 460.623 1146 459.200 c +1141.257 457.771 1137.281 454.383 1133 452 c +f +*U +0.000 0.141 0.094 0.271 k +*u +1174 460 m +1175 459 l +1174 460 l +f +*U +0.000 0.671 0.498 0.329 k +*u +1283 460 m +1283.545 458.365 1283.365 458.545 1285 458 c +1285 460 l +1283 460 l +f +*U +0.000 0.863 0.624 0.133 k +*u +1284 457 m +1286 455 1287.676 452.259 1290.224 450.862 c +1297 447 1307.481 449 1315 449 c +1313.378 451.388 1312.428 453 1312 456 c +1309.291 455.352 1306.784 455 1304 455 c +1305.800 455.562 1307 455.824 1309 456 c +1304 460.863 1288.450 463.171 1284 457 c +f +*U +0.000 0.286 0.204 0.082 k +*u +1305 460 m +1306 459 l +1305 460 l +f +*U +0.000 0.000 0.000 0.612 k +*u +1041 459 m +1042 458 l +1041 459 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1079 459 m +1080 458 l +1079 459 l +f +*U +0.000 0.314 0.251 0.086 k +*u +1141 459 m +1142 458 l +1141 459 l +f +*U +0.000 0.663 0.506 0.337 k +*u +1142.667 458.667 m +1142.222 458.222 1143.278 458.278 1143.333 458.333 c +1143.778 458.778 1142.722 458.722 1142.667 458.667 c +f +*U +0.000 0.757 0.596 0.243 k +*u +1166 459 m +1165 458 l +1165 456 l +1167.364 456.482 1167.518 456.636 1168 459 c +1166 459 l +f +*U +0.000 0.545 0.431 0.455 k +*u +1169.667 458.667 m +1169.222 458.222 1170.278 458.278 1170.333 458.333 c +1170.778 458.778 1169.722 458.722 1169.667 458.667 c +f +*U +0.000 0.447 0.298 0.337 k +*u +1171 459 m +1172 458 l +1171 459 l +f +*U +0.000 0.243 0.161 0.082 k +*u +1172 459 m +1173 458 l +1172 459 l +f +*U +0.000 0.325 0.220 0.039 k +*u +1283 459 m +1284 458 l +1283 459 l +f +*U +0.000 0.549 0.380 0.329 k +*u +1305.667 458.667 m +1305.222 458.222 1306.278 458.278 1306.333 458.333 c +1306.778 458.778 1305.722 458.722 1305.667 458.667 c +f +*U +0.000 0.298 0.212 0.000 k +*u +1307 459 m +1308 458 l +1307 459 l +f +*U +0.000 0.000 0.000 0.361 k +*u +1040 458 m +1041 457 l +1040 458 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1078 458 m +1079 457 l +1078 458 l +f +*U +0.000 0.235 0.180 0.090 k +*u +1139 458 m +1140 457 l +1139 458 l +f +*U +0.000 0.749 0.565 0.251 k +*u +1139 456 m +1140.580 456.683 1140.777 456.805 1142 458 c +1140.420 457.316 1140.223 457.195 1139 456 c +f +*U +0.000 0.443 0.337 0.557 k +*u +1168 458 m +1169 457 l +1168 458 l +f +*U +0.000 0.404 0.267 0.192 k +*u +1169 458 m +1170 457 l +1169 458 l +f +*U +0.000 0.392 0.282 0.361 k +*u +1308 458 m +1309 457 l +1308 458 l +f +*U +0.000 0.000 0.000 0.722 k +*u +1378 458 m +1379 457 l +1378 458 l +f +*U +0.000 0.000 0.000 0.224 k +*u +1039 457 m +1040 456 l +1039 457 l +f +*U +0.000 0.302 0.212 0.278 k +*u +1138 457 m +1139 456 l +1138 457 l +f +*U +0.000 0.278 0.271 0.122 k +*u +1284 457 m +1285 456 l +1284 457 l +f +*U +0.000 0.769 0.482 0.224 k +*u +1304 456 m +1306.332 455 1308.457 455 1311 455 c +1308.644 456.371 1306.743 456 1304 456 c +f +*U +0.000 0.298 0.208 0.306 k +*u +1310 457 m +1311 456 l +1310 457 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1038 456 m +1039 455 l +1038 456 l +f +*U +0.000 0.569 0.459 0.165 k +*u +1136 456 m +1137 455 l +1136 456 l +f +*U +0.000 0.741 0.506 0.259 k +*u +1136 454 m +1137.580 454.683 1137.778 454.805 1139 456 c +1137.420 455.316 1137.223 455.195 1136 454 c +f +*U +0.000 0.557 0.396 0.443 k +*u +1163.667 455.667 m +1163.222 455.222 1164.278 455.278 1164.333 455.333 c +1164.778 455.778 1163.722 455.722 1163.667 455.667 c +f +*U +0.000 0.278 0.212 0.212 k +*u +1165 456 m +1166 455 l +1165 456 l +f +*U +0.000 0.314 0.200 0.459 k +*u +1285 456 m +1286 455 l +1285 456 l +f +*U +0.000 0.596 0.396 0.404 k +*u +1286 456 m +1286 453 l +1286.696 454.554 1286.696 454.446 1286 456 c +f +*U +0.000 0.243 0.224 0.055 k +*u +1312 456 m +1313 455 l +1312 456 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1038 455 m +1033.585 449.946 1028.679 441.305 1022.826 438 c +1018.671 435.701 1011.614 437 1007 437 c +969 437 l +833 437 l +243 437 l +109 437 l +68 437 l +58.250 437 48.548 437.463 39 435 c +24.783 431.584 11 422.596 4.901 409 c +1.701 402 0.947 394.492 0 387 c +2 388.988 2.579 390 3 393 c +5 388 l +3 386.181 3.920 385.305 6 384 c +6 385.797 5.986 385.522 5 387 c +6.635 386.455 6.455 386.635 7 385 c +9 390.551 7 395.360 4 400 c +8 399 l +7.693 401 7.618 401.686 6 403 c +7.409 405.564 8.403 406.670 11 408 c +8 411 l +12 410 l +11.402 411.195 11.534 410.977 10 412 c +11.416 412.472 11.814 412.814 13 414 c +15.367 410.507 17.329 418.372 19 420 c +18.782 418.313 18.776 417.684 19 416 c +21.437 417.306 22.694 418.563 24 421 c +22.316 421.224 21.687 421.218 20 421 c +24 424.478 32 424.227 31 431 c +35.444 431.946 39.463 432.483 44 432 c +43 434 l +44.723 433 46 432.465 48 432 c +49 436 l +53 435 l +49 434 l +54.619 430.634 62.653 432 69 432 c +114 432 l +282 432 l +804 432 l +954 432 l +997 432 l +1004.677 432 1012.812 430.954 1020 434 c +1019 432 l +1022.312 432.552 1024 431.678 1028 433 c +1029 432 l +1029 434 l +1030.186 432.964 1030.604 432.661 1032 432 c +1031.548 433.863 1030.908 435.308 1030 437 c +1032 436 l +1031.454 441.569 1032.295 444.690 1036 449 c +1036 447 l +1040 450 l +1039.676 452.204 1039.433 453.328 1038 455 c +f +*U +0.000 0.192 0.114 0.153 k +*u +1134 455 m +1135 454 l +1134 455 l +f +*U +0.000 0.322 0.196 0.529 k +*u +1135 455 m +1136 454 l +1135 455 l +f +*U +0.000 0.482 0.388 0.518 k +*u +1161.667 454.667 m +1161.222 454.222 1162.278 454.278 1162.333 454.333 c +1162.778 454.777 1161.722 454.722 1161.667 454.667 c +f +*U +0.000 0.361 0.267 0.153 k +*u +1163 455 m +1164 454 l +1163 455 l +f +*U +0.000 0.369 0.357 0.475 k +*u +1312.667 454.667 m +1312.222 454.222 1313.278 454.278 1313.333 454.333 c +1313.778 454.778 1312.722 454.722 1312.667 454.667 c +f +*U +0.000 0.000 0.000 0.749 k +*u +1417 455 m +1418 454 l +1417 455 l +f +*U +0.000 0.349 0.220 0.263 k +*u +1133 454 m +1134 453 l +1133 454 l +f +*U +0.000 0.714 0.557 0.286 k +*u +1131 452 m +1133 451.590 1133.963 452 1136 453 c +1133.859 453.410 1133 452.968 1131 452 c +f +*U +0.000 0.369 0.318 0.631 k +*u +1160 454 m +1161 453 l +1160 454 l +f +*U +0.000 0.353 0.259 0.122 k +*u +1161 454 m +1162 453 l +1161 454 l +f +*U +0.000 0.812 0.600 0.188 k +*u +1312 454 m +1313.446 449.667 1316.885 449 1321 448 c +1318.952 451.731 1316 453.201 1312 454 c +f +*U +0.000 0.427 0.341 0.169 k +*u +1315 454 m +1316 453 l +1315 454 l +f +*U +0.020 0.024 0.000 0.753 k +*u +1382 454 m +1383 453 l +1382 454 l +f +*U +0.000 0.000 0.000 0.373 k +*u +1418 454 m +1419 453 l +1418 454 l +f +*U +0.000 0.341 0.227 0.129 k +*u +1131 453 m +1132 452 l +1131 453 l +f +*U +0.000 0.533 0.388 0.345 k +*u +1157 453 m +1158.248 452.315 1158.548 452.251 1160 452 c +1158.752 452.685 1158.452 452.749 1157 453 c +f +*U +0.000 0.275 0.188 0.059 k +*u +1286 453 m +1287 452 l +1286 453 l +f +*U +0.000 0.529 0.357 0.471 k +*u +1287.333 452.333 m +1287.278 452.278 1287.222 451.222 1287.667 451.667 c +1287.723 451.723 1287.777 452.778 1287.333 452.333 c +f +*U +0.000 0.298 0.145 0.102 k +*u +1317 453 m +1318 452 l +1317 453 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1419 453 m +1420 452 l +1419 453 l +f +*U +0.000 0.282 0.188 0.310 k +*u +1130 452 m +1131 451 l +1130 452 l +f +*U +0.000 0.604 0.482 0.396 k +*u +1156 452 m +1157 451 l +1156 452 l +f +*U +0.000 0.396 0.286 0.220 k +*u +1157 452 m +1158 451 l +1157 452 l +f +*U +0.000 0.282 0.208 0.357 k +*u +1318 452 m +1319 451 l +1318 452 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1034 451 m +1035 450 l +1034 451 l +f +*U +0.000 0.435 0.239 0.094 k +*u +1128 451 m +1129 450 l +1128 451 l +f +*U +0.000 0.639 0.459 0.361 k +*u +1129.667 450.667 m +1129.222 450.222 1130.278 450.278 1130.333 450.333 c +1130.778 450.778 1129.722 450.722 1129.667 450.667 c +f +*U +0.000 0.867 0.675 0.133 k +*u +1129 450 m +1131 449 1132.747 449 1135 449 c +1132.787 450.393 1131.609 450.374 1129 450 c +f +*U +0.000 0.451 0.329 0.388 k +*u +1154.667 450.667 m +1154.222 450.222 1155.278 450.278 1155.333 450.333 c +1155.778 450.778 1154.722 450.722 1154.667 450.667 c +f +*U +0.000 0.251 0.188 0.122 k +*u +1156 451 m +1157 450 l +1156 451 l +f +*U +0.000 0.298 0.196 0.239 k +*u +1287 451 m +1288 450 l +1287 451 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1288 451 m +1289 450 l +1288 451 l +f +*U +0.000 0.608 0.443 0.341 k +*u +1289 451 m +1290.458 449.919 1291.248 449.564 1293 449 c +1291.457 450.267 1290.952 450.489 1289 451 c +f +*U +0.000 0.000 0.000 0.655 k +*u +1033 450 m +1034 449 l +1033 450 l +f +*U +0.000 0.275 0.196 0.396 k +*u +1127 450 m +1128 449 l +1127 450 l +f +*U +0.000 0.741 0.741 0.259 k +*u +1128 450 m +1131.989 445.435 1146 448 1152 448 c +1144.846 451 1135.658 448.177 1128 450 c +f +*U +0.000 0.510 0.416 0.490 k +*u +1153 450 m +1154 449 l +1153 450 l +f +*U +0.000 0.298 0.239 0.192 k +*u +1154 450 m +1155 449 l +1154 450 l +f +*U +0.000 0.208 0.169 0.141 k +*u +1290 450 m +1291 449 l +1290 450 l +f +*U +0.000 0.337 0.267 0.004 k +*u +1321 450 m +1322 449 l +1321 450 l +f +*U +0.000 0.000 0.000 0.361 k +*u +1032 449 m +1033 448 l +1032 449 l +f +*U +0.000 0.141 0.114 0.259 k +*u +1125 449 m +1126 448 l +1125 449 l +f +*U +0.000 0.271 0.271 0.729 k +*u +1126.667 448.667 m +1126.222 448.222 1127.278 448.278 1127.333 448.333 c +1127.778 448.778 1126.722 448.722 1126.667 448.667 c +f +*U +0.000 0.192 0.188 0.263 k +*u +1152 449 m +1153 448 l +1152 449 l +f +*U +0.000 0.573 0.514 0.427 k +*u +1292.667 448.667 m +1292.222 448.222 1293.278 448.278 1293.333 448.333 c +1293.778 448.778 1292.722 448.722 1292.667 448.667 c +f +*U +0.000 0.753 0.753 0.247 k +*u +1294 449 m +1301.169 445.992 1312.239 448 1320 448 c +1312.831 451 1301.761 449 1294 449 c +f +*U +0.000 0.373 0.282 0.549 k +*u +1321.667 448.667 m +1321.222 448.222 1322.278 448.278 1322.333 448.333 c +1322.778 448.778 1321.722 448.722 1321.667 448.667 c +f +*U +0.000 0.000 0.000 0.780 k +*u +1422 449 m +1423 448 l +1422 449 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1031 448 m +1032 447 l +1031 448 l +f +*U +0.094 0.000 0.027 0.216 k +*u +1294 448 m +1295.248 447.315 1295.548 447.251 1297 447 c +1295.752 447.685 1295.451 447.749 1294 448 c +f +*U +0.000 0.000 0.000 0.796 k +*u +1423 448 m +1424 447 l +1423 448 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1030 447 m +1031 446 l +1030 447 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1066 447 m +1067 446 l +1066 447 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1424 447 m +1425 446 l +1424 447 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1389 446 m +1390 445 l +1389 446 l +f +*U +0.000 0.000 0.000 0.796 k +*u +1426 444 m +1427 443 l +1426 444 l +f +*U +0.000 0.000 0.000 0.541 k +*u +1027 443 m +1028 442 l +1027 443 l +f +*U +0.000 0.000 0.000 0.298 k +*u +1392 443 m +1393 442 l +1392 443 l +f +*U +0.000 0.000 0.000 0.369 k +*u +1427 443 m +1428 442 l +1427 443 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1026 442 m +1027 441 l +1026 442 l +f +*U +0.000 0.000 0.000 0.545 k +*u +1393 442 m +1394 441 l +1393 442 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1428 442 m +1429 441 l +1428 442 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1025 441 m +1026 440 l +1025 441 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1394 441 m +1395 440 l +1394 441 l +f +*U +0.012 0.000 0.016 0.000 k +*u +48 440 m +52 437 l +58.834 440.647 68.400 439 76 439 c +129 439 l +322 439 l +1023 439 l +1015.841 442 1004.744 440 997 440 c +940 440 l +740 440 l +48 440 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1395 440 m +1396 439 l +1395 440 l +f +*U +0.000 0.000 0.000 0.729 k +*u +1024 439 m +1025 438 l +1024 439 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1059 439 m +1060 438 l +1059 439 l +f +*U +0.000 0.000 0.000 0.408 k +*u +1430 439 m +1431 438 l +1430 439 l +f +*U +0.000 0.000 0.000 0.004 k +*u +1439 436 m +1445.817 437.623 1453 437 1460 437 c +1495 437 l +1608 437 l +1969 437 l +1965.730 439.477 1962 439.000 1958 439 c +1939 439 l +1861 439 l +1558 439 l +1469 439 l +1448 439 l +1444.213 438.992 1441.171 439.349 1439 436 c +f +*U +0.024 0.000 0.027 0.102 k +*u +52 438 m +59 434.996 70.256 437 78 437 c +135 437 l +333 437 l +1022 437 l +1014.841 440 1003.744 438 996 438 c +939 438 l +740 438 l +52 438 l +f +*U +0.024 0.000 0.031 0.325 k +*u +1022.667 437.667 m +1022.222 437.222 1023.278 437.278 1023.333 437.333 c +1023.778 437.778 1022.722 437.722 1022.667 437.667 c +f +*U +0.000 0.000 0.000 0.200 k +*u +1058 438 m +1059 437 l +1058 438 l +f +*U +0.000 0.000 0.000 0.325 k +*u +1431 438 m +1432 437 l +1431 438 l +f +*U +0.000 0.000 0.000 0.420 k +*u +44 437 m +45 436 l +44 437 l +f +*U +0.000 0.000 0.000 0.588 k +*u +45 437 m +46 436 l +45 437 l +f +*U +0.000 0.000 0.000 0.824 k +*u +46 437 m +47 436 l +46 437 l +f +*U +0.000 0.000 0.000 0.263 k +*u +1057 437 m +1058 436 l +1057 437 l +f +*U +0.000 0.224 0.169 0.035 k +*u +1110 437 m +1111 436 l +1110 437 l +f +*U +0.000 0.529 0.408 0.471 k +*u +1111 437 m +1117.584 434.237 1125.949 436.679 1133 435 c +1129.196 439.354 1116.561 437 1111 437 c +f +*U +0.000 0.373 0.271 0.592 k +*u +1133.667 436.667 m +1133.222 436.222 1134.278 436.278 1134.333 436.333 c +1134.778 436.778 1133.722 436.722 1133.667 436.667 c +f +*U +0.000 0.514 0.420 0.486 k +*u +1298 435 m +1307.524 437.267 1318.247 436 1328 436 c +1321.814 438.596 1312.678 437 1306 437 c +1302.895 436.994 1300 437.407 1298 435 c +f +*U +0.000 0.604 0.486 0.396 k +*u +1328 437 m +1331.366 435.584 1335.373 435.673 1339 435 c +1335.734 437.474 1331.990 437.000 1328 437 c +f +*U +0.000 0.000 0.000 0.537 k +*u +40 436 m +41 435 l +40 436 l +f +*U +0.004 0.000 0.004 0.996 k +*u +57 436 m +63.919 433 74.520 435 82 435 c +139 435 l +335 435 l +1015 435 l +1008 437.903 997.480 436 990 436 c +933 436 l +737 436 l +57 436 l +f +*U +0.000 0.000 0.000 0.475 k +*u +1056 436 m +1057 435 l +1056 436 l +f +*U +0.000 0.263 0.204 0.357 k +*u +1109 436 m +1110 435 l +1109 436 l +f +*U +0.000 0.545 0.447 0.455 k +*u +1110 436 m +1111 435 l +1110 436 l +f +*U +0.000 0.863 0.604 0.137 k +*u +1106 427 m +1101 427 l +1101 425 l +1121 425 l +1123.329 429.352 1128.185 431.948 1132 435 c +1124.775 438 1104.947 438.189 1106 427 c +f +*U +0.000 0.353 0.259 0.176 k +*u +1133 436 m +1134 435 l +1133 436 l +f +*U +0.000 0.875 0.624 0.125 k +*u +1299 436 m +1298.808 431.871 1297.540 428.769 1296 425 c +1348 425 l +1338.944 441.346 1314.725 436 1299 436 c +f +*U +0.000 0.173 0.157 0.192 k +*u +1339 436 m +1340 435 l +1339 436 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1398 436 m +1399 435 l +1398 436 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1432 436 m +1433 435 l +1432 436 l +f +*U +0.000 0.000 0.000 0.451 k +*u +36 435 m +37 434 l +36 435 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1055 435 m +1056 434 l +1055 435 l +f +*U +0.000 0.282 0.239 0.176 k +*u +1108 435 m +1109 434 l +1108 435 l +f +*U +0.000 0.506 0.431 0.494 k +*u +1131 435 m +1132 434 l +1131 435 l +f +*U +0.000 0.227 0.176 0.122 k +*u +1132 435 m +1133 434 l +1132 435 l +f +*U +0.000 0.518 0.475 0.090 k +*u +1298.333 434.333 m +1298.278 434.278 1298.222 433.222 1298.667 433.667 c +1298.723 433.723 1298.777 434.777 1298.333 434.333 c +f +*U +0.000 0.725 0.549 0.275 k +*u +1339 435 m +1340.324 432.313 1341.313 431.324 1344 430 c +1342.451 432 1341 433.451 1339 435 c +f +*U +0.000 0.294 0.224 0.098 k +*u +1340 435 m +1341 434 l +1340 435 l +f +*U +0.000 0.000 0.000 0.475 k +*u +1399 435 m +1400 434 l +1399 435 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1974 435 m +1974 410 l +1976.413 415.750 1976.413 429.250 1974 435 c +f +*U +0.000 0.000 0.000 0.400 k +*u +33 434 m +34 433 l +33 434 l +f +*U +0.000 0.000 0.000 0.988 k +*u +55 434 m +61.919 431 72.520 433 80 433 c +137 433 l +334 433 l +1016 433 l +1009 435.903 998.480 434 991 434 c +934 434 l +737 434 l +55 434 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1054 434 m +1055 433 l +1054 434 l +f +*U +0.000 0.416 0.325 0.133 k +*u +1107 434 m +1108 433 l +1107 434 l +f +*U +0.000 0.529 0.392 0.318 k +*u +1129 434 m +1129 432 l +1130.635 432.545 1130.455 432.365 1131 434 c +1129 434 l +f +*U +0.000 0.294 0.235 0.220 k +*u +1341 434 m +1342 433 l +1341 434 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1400 434 m +1401 433 l +1400 434 l +f +*U +0.000 0.000 0.000 0.220 k +*u +30 433 m +31 432 l +30 433 l +f +*U +0.000 0.000 0.000 0.592 k +*u +31 433 m +32 432 l +31 433 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1053 433 m +1054 432 l +1053 433 l +f +*U +0.000 0.349 0.282 0.247 k +*u +1106 433 m +1107 432 l +1106 433 l +f +*U +0.000 0.514 0.369 0.427 k +*u +1298 433 m +1298 430 l +1298.696 431.554 1298.696 431.446 1298 433 c +f +*U +0.000 0.227 0.200 0.263 k +*u +1342 433 m +1343 432 l +1342 433 l +f +*U +0.000 0.000 0.000 0.384 k +*u +28 432 m +29 431 l +28 432 l +f +*U +0.000 0.412 0.314 0.208 k +*u +1105 432 m +1106 431 l +1105 432 l +f +*U +0.063 0.000 0.012 0.275 k +*u +1128 432 m +1129 431 l +1128 432 l +f +*U +0.000 0.624 0.522 0.067 k +*u +1343 432 m +1344 431 l +1343 432 l +f +*U +0.000 0.000 0.000 0.349 k +*u +26 431 m +27 430 l +26 431 l +f +*U +0.000 0.753 0.576 0.235 k +*u +1104 431 m +1102 427 l +1106 427 l +1106 431 l +1104 431 l +f +*U +0.000 0.478 0.349 0.416 k +*u +1124 428 m +1125.457 429 1125.897 429.543 1127 431 c +1124.876 430 1124.899 430 1124 428 c +f +*U +0.000 0.188 0.149 0.082 k +*u +1127 431 m +1128 430 l +1127 431 l +f +*U +0.000 0.137 0.145 0.412 k +*u +1344 431 m +1345 430 l +1344 431 l +f +*U +0.000 0.000 0.000 0.239 k +*u +24 430 m +25 429 l +24 430 l +f +*U +0.000 0.000 0.000 0.212 k +*u +1051 430 m +1052 429 l +1051 430 l +f +*U +0.000 0.400 0.227 0.310 k +*u +1103 430 m +1104 429 l +1103 430 l +f +*U +0.000 0.263 0.216 0.090 k +*u +1297 430 m +1298 429 l +1297 430 l +f +*U +0.000 0.369 0.306 0.271 k +*u +1345 430 m +1346 429 l +1345 430 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1403 430 m +1404 429 l +1403 430 l +f +*U +0.000 0.000 0.000 0.514 k +*u +1050 429 m +1051 428 l +1050 429 l +f +*U +0.000 0.553 0.455 0.447 k +*u +1297.333 428.333 m +1297.278 428.278 1297.222 427.222 1297.667 427.667 c +1297.722 427.722 1297.778 428.778 1297.333 428.333 c +f +*U +0.000 0.314 0.369 0.192 k +*u +1346 429 m +1347 428 l +1346 429 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1404 429 m +1405 428 l +1404 429 l +f +*U +0.000 0.000 0.000 0.451 k +*u +21 428 m +22 427 l +21 428 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1049 428 m +1050 427 l +1049 428 l +f +*U +0.000 0.325 0.267 0.298 k +*u +1101 428 m +1102 427 l +1101 428 l +f +*U +0.000 0.686 0.518 0.306 k +*u +1121 428 m +1121 426 l +1122.635 426.545 1122.455 426.365 1123 428 c +1121 428 l +f +*U +0.000 0.365 0.294 0.259 k +*u +1123 428 m +1124 427 l +1123 428 l +f +*U +0.000 0.227 0.192 0.086 k +*u +1296 428 m +1297 427 l +1296 428 l +f +*U +0.000 0.325 0.212 0.282 k +*u +1347 428 m +1348 427 l +1347 428 l +f +*U +0.000 0.412 0.325 0.341 k +*u +1100 427 m +1101 426 l +1100 427 l +f +*U +0.000 0.310 0.263 0.204 k +*u +1122 427 m +1123 426 l +1122 427 l +f +*U +0.000 0.420 0.392 0.580 k +*u +1347 427 m +1348 426 l +1347 427 l +f +*U +0.000 0.220 0.235 0.239 k +*u +1348 427 m +1349 426 l +1348 427 l +f +*U +0.000 0.000 0.000 0.188 k +*u +18 426 m +19 425 l +18 426 l +f +*U +0.000 0.349 0.263 0.290 k +*u +1099 426 m +1100 425 l +1099 426 l +f +*U +0.000 0.533 0.482 0.467 k +*u +1099 425 m +1100.769 424.221 1102 424 1104 424 c +1102 425 1101.229 425 1099 425 c +f +*U +0.000 0.357 0.255 0.192 k +*u +1121 426 m +1122 425 l +1121 426 l +f +*U +0.000 0.173 0.125 0.329 k +*u +1295 426 m +1296 425 l +1295 426 l +f +*U +0.000 0.592 0.471 0.408 k +*u +1303 425 m +1307.720 423 1313.920 424 1319 424 c +1350 424 l +1346.182 426.207 1340.402 425 1336 425 c +1303 425 l +f +*U +0.000 0.278 0.247 0.239 k +*u +1349 426 m +1350 425 l +1349 426 l +f +*U +0.000 0.000 0.000 0.275 k +*u +1406 426 m +1407 425 l +1406 426 l +f +*U +0.000 0.000 0.000 0.773 k +*u +17 425 m +18 424 l +17 425 l +f +*U +0.000 0.000 0.000 0.220 k +*u +1047 425 m +1048 424 l +1047 425 l +f +*U +0.000 0.192 0.161 0.447 k +*u +1098 425 m +1099 424 l +1098 425 l +f +*U +0.000 0.616 0.518 0.384 k +*u +1104 425 m +1108.724 423 1114.910 424 1120 424 c +1115.276 425.982 1109 425 1104 425 c +f +*U +0.000 0.082 0.051 0.380 k +*u +1120 425 m +1121 424 l +1120 425 l +f +*U +0.000 0.239 0.180 0.576 k +*u +1294 425 m +1295 424 l +1294 425 l +f +*U +0.000 0.400 0.400 0.600 k +*u +1295 425 m +1297.613 423.902 1300 424 1303 424 c +1300.387 425 1297.836 424.993 1295 425 c +f +*U +0.000 0.239 0.129 0.278 k +*u +1350 425 m +1351 424 l +1350 425 l +f +*U +0.000 0.000 0.004 0.361 k +*u +1407 425 m +1408 424 l +1407 425 l +f +*U +0.000 0.000 0.000 0.349 k +*u +1046 424 m +1047 423 l +1046 424 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1045 423 m +1046 422 l +1045 423 l +f +*U +0.008 0.008 0.000 0.200 k +*u +1409 422 m +1410 421 l +1409 422 l +f +*U +0.008 0.008 0.000 0.643 k +*u +1410 421 m +1411 420 l +1410 421 l +f +*U +0.000 0.000 0.000 0.208 k +*u +1043 420 m +1044 419 l +1043 420 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1042 419 m +1043 418 l +1042 419 l +f +*U +0.000 0.000 0.000 0.792 k +*u +10 418 m +11 417 l +10 418 l +f +*U +0.008 0.008 0.000 0.494 k +*u +1412 418 m +1413 417 l +1412 418 l +f +*U +0.000 0.000 0.000 0.533 k +*u +9 417 m +10 416 l +9 417 l +f +*U +0.000 0.000 0.000 1.000 k +*u +56 416 m +63 412.996 74.256 415 82 415 c +139 415 l +337 415 l +1024 415 l +1014.317 412 1002 414 992 414 c +927 414 l +713 414 l +287 414 l +150 414 l +120.557 414 90.368 412 61 414 c +56.305 414.375 51.748 415.650 47 416 c +48 414 l +46.365 414.545 46.545 414.365 46 416 c +42 415 l +42 413.203 42 413.479 43 412 c +40.734 411.657 38.346 411.382 40 414 c +39 412 l +40.618 413.314 40.693 413.877 41 416 c +38.711 415.239 35.767 414.630 34.328 412.490 c +32 409.247 33.743 405.592 29 405 c +29 399 l +27 404 l +24 404 l +24.768 402.686 24.686 402.768 26 402 c +24 399 24.308 396.349 24 393 c +25.267 391.457 25.489 390.952 26 389 c +25 391 l +21.895 383.601 24 372 24 364 c +24 305 l +15.957 305 7.998 305.609 0 305 c +7.409 301.891 18.975 304 27 304 c +27 371 l +27 381.888 25.902 394 33.380 402.960 c +41.502 412.660 53.403 413 65 413 c +101 413 l +286 413 l +823 413 l +974 413 l +1015 413 l +1024 413 1032.654 412 1041 416 c +1038.167 416.926 1036.303 415.540 1033.424 415.394 c +1027 415 1020.376 416 1014 416 c +952 416 l +745 416 l +56 416 l +f +*U +0.000 0.000 0.000 0.212 k +*u +8 416 m +9 415 l +8 416 l +f +*U +0.024 0.024 0.000 0.976 k +*u +1424 416 m +1428.720 414 1434.920 415 1440 415 c +1472 415 l +1583 415 l +1968 415 l +1963.280 416.981 1957 416 1952 416 c +1921 416 l +1810 416 l +1424 416 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1037 415 m +1038 414 l +1037 415 l +f +*U +0.000 0.000 0.000 0.298 k +*u +1038 415 m +1039 414 l +1038 415 l +f +*U +0.008 0.000 0.012 0.988 k +*u +1422 415 m +1425.691 412.204 1430.515 413 1435 413 c +1461 413 l +1566 413 l +1969 413 l +1964.785 414.769 1959.536 414 1955 414 c +1926 414 l +1825 414 l +1555 414 l +1469 414 l +1453.686 414 1437 412.200 1422 415 c +f +*U +0.000 0.000 0.000 0.647 k +*u +7 414 m +8 413 l +7 414 l +f +*U +0.000 0.000 0.000 0.808 k +*u +1035 414 m +1036 413 l +1035 414 l +f +*U +0.000 0.000 0.000 0.345 k +*u +1036 414 m +1037 413 l +1036 414 l +f +*U +0.000 0.255 0.075 0.110 k +*u +1089 414 m +1093.471 412 1099.183 413 1104 413 c +1099.529 414.876 1093.817 414 1089 414 c +f +*U +0.000 0.361 0.220 0.047 k +*u +1104 414 m +1105.769 413.221 1107 413 1109 413 c +1107.231 413.779 1105.964 413.912 1104 414 c +f +*U +0.000 0.251 0.063 0.114 k +*u +1298 414 m +1303.217 411.811 1310.381 413 1316 413 c +1352 413 l +1346.784 415.189 1339.619 414 1334 414 c +1298 414 l +f +*U +0.000 0.231 0.161 0.118 k +*u +1352 414 m +1354.613 412.902 1357 413 1360 413 c +1357.387 414 1354.836 413.993 1352 414 c +f +*U +0.000 0.000 0.000 0.173 k +*u +1415 414 m +1416 413 l +1415 414 l +f +*U +0.000 0.000 0.000 0.239 k +*u +6 413 m +7 412 l +6 413 l +f +*U +0.000 0.000 0.000 0.812 k +*u +50 413 m +51 412 l +50 413 l +f +*U +0.000 0.000 0.000 0.490 k +*u +51 413 m +58 409.996 69.256 412 77 412 c +135 412 l +336 412 l +1033 412 l +1025.841 415 1014.744 413 1007 413 c +949 413 l +748 413 l +51 413 l +f +*U +0.000 0.690 0.486 0.310 k +*u +1088 413 m +1088 411 l +1090 411 l +1089.455 412.635 1089.635 412.455 1088 413 c +f +*U +0.000 0.733 0.722 0.267 k +*u +1089.667 412.667 m +1089.222 412.222 1090.278 412.278 1090.333 412.333 c +1090.778 412.778 1089.722 412.722 1089.667 412.667 c +f +*U +0.000 0.800 0.875 0.125 k +*u +1091 413 m +1095.724 411 1101.910 412 1107 412 c +1102.276 413.982 1096 413 1091 413 c +f +*U +0.000 0.475 0.525 0.475 k +*u +1107 413 m +1108 412 l +1107 413 l +f +*U +0.000 0.227 0.302 0.259 k +*u +1108 413 m +1109 412 l +1108 413 l +f +*U +0.000 0.565 0.420 0.396 k +*u +1298 413 m +1298 408 l +1298.830 410 1298.830 410.970 1298 413 c +f +*U +0.000 0.773 0.855 0.145 k +*u +1299 413 m +1303.969 410.915 1310.650 412 1316 412 c +1352 412 l +1347 414 1340.350 413 1335 413 c +1299 413 l +f +*U +0.000 0.859 0.612 0.137 k +*u +1352 413 m +1354 412 1355.747 412 1358 412 c +1358 410 l +1315 410 l +1306 410 1296.397 408.986 1291 401 c +1294.474 401.231 1297.560 402.704 1301 402.946 c +1314.869 403.916 1329 403 1343 403 c +1346.604 403 1358.640 401 1360.824 404.545 c +1363.322 408.491 1353.592 407.999 1352 408 c +1355.590 409 1358.703 408.815 1361 412 c +1357.959 412.900 1355.169 412.992 1352 413 c +f +*U +0.000 0.278 0.180 0.345 k +*u +1360 413 m +1361 412 l +1360 413 l +f +*U +0.000 0.000 0.000 0.525 k +*u +1417 413 m +1418 412 l +1417 413 l +f +*U +0.000 0.000 0.000 0.686 k +*u +46 412 m +47 411 l +46 412 l +f +*U +0.000 0.000 0.000 0.192 k +*u +47 412 m +48 411 l +47 412 l +f +*U +0.000 0.235 0.149 0.337 k +*u +1087 412 m +1088 411 l +1087 412 l +f +*U +0.000 0.851 0.596 0.141 k +*u +1082 401 m +1086.620 401 1093.403 399.742 1097.696 401.603 c +1100.704 402.908 1102.175 406.339 1105 408 c +1103.272 413.208 1093.657 413.509 1089.299 410.825 c +1086.243 408.943 1083.492 404 1082 401 c +f +*U +0.000 0.808 0.718 0.173 k +*u +1104 412 m +1105 410 l +1106.635 410.545 1106.455 410.365 1107 412 c +1104 412 l +f +*U +0.000 0.286 0.275 0.235 k +*u +1107 412 m +1108 411 l +1107 412 l +f +*U +0.000 0.925 0.663 0.075 k +*u +1299 412 m +1299 408 l +1318.474 410.576 1338.184 410 1358 410 c +1358 412 l +1338.254 411.592 1318.764 410.440 1299 412 c +f +*U +0.000 0.843 0.580 0.157 k +*u +1303 412 m +1307.720 410 1313.920 411 1319 411 c +1352 411 l +1347.280 412.981 1341 412 1336 412 c +1303 412 l +f +*U +0.000 0.263 0.173 0.157 k +*u +1361 412 m +1362 411 l +1361 412 l +f +*U +0.000 0.000 0.000 0.541 k +*u +1419 412 m +1420 411 l +1419 412 l +f +*U +0.000 0.000 0.000 0.341 k +*u +5 411 m +6 410 l +5 411 l +f +*U +0.000 0.000 0.000 0.624 k +*u +43 411 m +44 410 l +43 411 l +f +*U +0.000 0.365 0.243 0.173 k +*u +1086 411 m +1087 410 l +1086 411 l +f +*U +0.000 0.471 0.337 0.529 k +*u +1087 411 m +1088 410 l +1087 411 l +f +*U +0.000 0.333 0.310 0.275 k +*u +1106 411 m +1107 410 l +1106 411 l +f +*U +0.000 0.910 0.663 0.090 k +*u +1360 411 m +1357.440 409 1355.192 409 1352 409 c +1356.775 406.991 1359.915 407.950 1363 403 c +1296 403 l +1296 401 l +1367 401 l +1365 404.706 1362.922 408 1360 411 c +f +*U +0.000 0.702 0.498 0.298 k +*u +1361 411 m +1361.683 409.420 1361.805 409.223 1363 408 c +1362.316 409.580 1362.195 409.777 1361 411 c +f +*U +0.000 0.000 0.000 0.188 k +*u +1422 411 m +1423 410 l +1422 411 l +f +*U +0.055 0.063 0.000 0.580 k +*u +1423 411 m +1427.720 409 1433.920 410 1439 410 c +1471 410 l +1583 410 l +1974 410 l +1969.280 411.981 1963 411 1958 411 c +1926 411 l +1813 411 l +1423 411 l +f +*U +0.000 0.000 0.000 0.365 k +*u +41 410 m +42 409 l +41 410 l +f +*U +0.000 0.000 0.000 0.004 k +*u +56 410 m +56 408 l +1032 408 l +1023.793 411.476 1012.764 410 1004 410 c +947 410 l +748 410 l +56 410 l +f +*U +0.000 0.631 0.427 0.369 k +*u +1086 410 m +1085 408.521 1085 408.797 1085 407 c +1086.289 408.443 1086.401 408.234 1086 410 c +f +*U +0.000 0.506 0.247 0.275 k +*u +1105 410 m +1106 409 l +1105 410 l +f +*U +0.000 0.000 0.000 0.200 k +*u +4 409 m +5 408 l +4 409 l +f +*U +0.000 0.000 0.000 0.592 k +*u +39 409 m +40 408 l +39 409 l +f +*U +0.000 0.278 0.165 0.071 k +*u +1297 409 m +1298 408 l +1297 409 l +f +*U +0.000 0.325 0.208 0.306 k +*u +1363 409 m +1364 408 l +1363 409 l +f +*U +0.008 0.008 0.000 0.827 k +*u +35 408 m +36 407 l +35 408 l +f +*U +0.000 0.259 0.302 0.329 k +*u +1084 408 m +1085 407 l +1084 408 l +f +*U +0.000 0.776 0.627 0.071 k +*u +1086 408 m +1085 406 l +1087 406 l +1087 407.853 1087.300 407.350 1086 408 c +f +*U +0.000 0.565 0.439 0.435 k +*u +1102 408 m +1102 406 l +1103.635 406.545 1103.455 406.365 1104 408 c +1102 408 l +f +*U +0.000 0.635 0.486 0.051 k +*u +1296 408 m +1297 407 l +1296 408 l +f +*U +0.000 0.741 0.549 0.239 k +*u +1295 407 m +1297 406.249 1297.596 406.344 1299 408 c +1295 407 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1363.333 407.333 m +1363.278 407.278 1363.222 406.222 1363.667 406.667 c +1363.722 406.723 1363.777 407.778 1363.333 407.333 c +f +*U +0.000 0.204 0.180 0.145 k +*u +1364 408 m +1365 407 l +1364 408 l +f +*U +0.000 0.000 0.000 0.216 k +*u +3 407 m +4 406 l +3 407 l +f +*U +0.008 0.008 0.000 0.737 k +*u +36 407 m +37 406 l +36 407 l +f +*U +0.000 0.447 0.404 0.475 k +*u +1084 407 m +1085 406 l +1084 407 l +f +*U +0.000 0.341 0.224 0.145 k +*u +1294 407 m +1295 406 l +1294 407 l +f +*U +0.000 0.427 0.325 0.573 k +*u +1364 407 m +1365 406 l +1364 407 l +f +*U +0.000 0.000 0.000 0.678 k +*u +3 406 m +4 405 l +3 406 l +f +*U +0.008 0.008 0.000 0.192 k +*u +35 406 m +36 405 l +35 406 l +f +*U +0.000 0.733 0.557 0.267 k +*u +1083 406 m +1083 404 l +1084.635 404.545 1084.455 404.365 1085 406 c +1083 406 l +f +*U +0.000 0.278 0.204 0.063 k +*u +1102 406 m +1103 405 l +1102 406 l +f +*U +0.000 0.337 0.243 0.286 k +*u +1293 406 m +1294 405 l +1293 406 l +f +*U +0.000 0.584 0.451 0.416 k +*u +1365 406 m +1365.406 403.908 1365.217 403.980 1367 403 c +1366.309 404.388 1366 404.861 1365 406 c +f +*U +0.000 0.000 0.000 0.345 k +*u +34 405 m +35 404 l +34 405 l +f +*U +0.000 0.361 0.290 0.278 k +*u +1082 405 m +1083 404 l +1082 405 l +f +*U +0.000 0.325 0.235 0.184 k +*u +1101 405 m +1102 404 l +1101 405 l +f +*U +0.000 0.694 0.561 0.306 k +*u +1292 405 m +1292 403 l +1293.635 403.545 1293.455 403.365 1294 405 c +1292 405 l +f +*U +0.000 0.263 0.208 0.259 k +*u +1366 405 m +1367 404 l +1366 405 l +f +*U +0.000 0.000 0.000 0.173 k +*u +2 404 m +3 403 l +2 404 l +f +*U +0.000 0.000 0.000 0.314 k +*u +33 404 m +34 403 l +33 404 l +f +*U +0.000 0.255 0.220 0.094 k +*u +1081 404 m +1082 403 l +1081 404 l +f +*U +0.000 0.545 0.467 0.455 k +*u +1082 404 m +1083 403 l +1082 404 l +f +*U +0.000 0.353 0.255 0.227 k +*u +1100 404 m +1101 403 l +1100 404 l +f +*U +0.000 0.365 0.302 0.635 k +*u +1291 404 m +1292 403 l +1291 404 l +f +*U +0.000 0.733 0.573 0.267 k +*u +1361.667 403.667 m +1361.222 403.222 1362.278 403.278 1362.333 403.333 c +1362.778 403.778 1361.722 403.722 1361.667 403.667 c +f +*U +0.000 0.000 0.000 0.671 k +*u +2 403 m +3 402 l +2 403 l +f +*U +0.000 0.000 0.008 0.792 k +*u +32 403 m +33 402 l +32 403 l +f +*U +0.000 0.400 0.271 0.545 k +*u +1081 403 m +1080 400 l +1083 400 l +1082.309 401.388 1082 401.861 1081 403 c +f +*U +0.000 0.376 0.302 0.424 k +*u +1099 403 m +1100 402 l +1099 403 l +f +*U +0.000 0.612 0.490 0.388 k +*u +1289 400 m +1303 400 l +1300.722 402.278 1294.392 399.965 1291 402 c +1292 403 l +1289.876 402 1289.899 402 1289 400 c +f +*U +0.000 0.686 0.498 0.294 k +*u +1366 403 m +1366.000 400.649 1365.347 401 1363 401 c +1365.388 399.631 1369.689 400.928 1366 403 c +f +*U +0.000 0.412 0.247 0.239 k +*u +1080 402 m +1081 401 l +1080 402 l +f +*U +0.000 0.380 0.286 0.149 k +*u +1288 402 m +1289 401 l +1288 402 l +f +*U +0.000 0.137 0.086 0.369 k +*u +1368 402 m +1369 401 l +1368 402 l +f +*U +0.000 0.000 0.000 0.267 k +*u +31 401 m +32 400 l +31 401 l +f +*U +0.031 0.000 0.016 0.078 k +*u +1078.667 400.667 m +1078.222 400.222 1079.278 400.278 1079.333 400.333 c +1079.778 400.778 1078.722 400.722 1078.667 400.667 c +f +*U +0.000 0.596 0.439 0.400 k +*u +1083 401 m +1087.471 399 1093.183 400 1098 400 c +1093.529 401.876 1087.817 401 1083 401 c +f +*U +0.031 0.000 0.008 0.455 k +*u +1287 401 m +1288 400 l +1287 401 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1288 401 m +1289 400 l +1288 401 l +f +*U +0.000 0.522 0.400 0.447 k +*u +1303 401 m +1308.463 398.708 1316 400 1322 400 c +1363 400 l +1357.537 402.292 1349.887 401 1344 401 c +1303 401 l +f +*U +0.000 0.243 0.161 0.733 k +*u +1368 401 m +1369 400 l +1368 401 l +f +*U +0.000 0.000 0.000 0.545 k +*u +1 400 m +2 399 l +1 400 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1 399 m +2 398 l +1 399 l +f +*U +0.000 0.000 0.000 0.196 k +*u +30 399 m +31 398 l +30 399 l +f +*U +0.000 0.000 0.000 0.831 k +*u +29 398 m +30 397 l +29 398 l +f +*U +0.000 0.000 0.000 0.322 k +*u +29 397 m +30 396 l +29 397 l +f +*U +0.000 0.000 0.000 0.467 k +*u +0 395 m +0 392 l +0.696 393.554 0.696 393.446 0 395 c +f +*U +0.000 0.000 0.000 0.812 k +*u +28 395 m +29 394 l +28 395 l +f +*U +0.000 0.000 0.000 0.306 k +*u +28 394 m +29 393 l +28 394 l +f +*U +0.000 0.000 0.000 0.859 k +*u +0.333 391.333 m +0.278 391.278 0.222 390.222 0.667 390.667 c +0.722 390.722 0.778 391.778 0.333 391.333 c +f +*U +0.000 0.357 0.333 0.149 k +*u +1073 390 m +1077.974 387.913 1084.638 389 1090 389 c +1085 391 1078.362 390 1073 390 c +f +*U +0.000 0.329 0.247 0.192 k +*u +1285 390 m +1287.613 388.902 1290 389 1293 389 c +1290.387 390 1287.835 389.993 1285 390 c +f +*U +0.000 0.192 0.102 0.114 k +*u +1293.333 389.333 m +1293.278 389.278 1293.222 388.222 1293.667 388.667 c +1293.722 388.722 1293.778 389.778 1293.333 389.333 c +f +*U +0.000 0.369 0.329 0.137 k +*u +1295 388 m +1304.222 390.196 1314.559 389 1324 389 c +1376 389 l +1370.293 391.395 1362 390 1356 390 c +1314 390 l +1308.940 390 1298.508 392 1295 388 c +f +*U +0.000 0.000 0.000 0.812 k +*u +27 389 m +27 304 l +29.395 309.707 28 317.846 28 324 c +28 367 l +28 373.686 29.599 382.806 27 389 c +f +*U +0.000 0.875 0.612 0.125 k +*u +1072 389 m +1070 378 l +1083 378 l +1084 382 1086.260 385.235 1088 389 c +1072 389 l +f +*U +0.000 0.325 0.286 0.475 k +*u +1088 389 m +1088 387 l +1089.635 387.545 1089.455 387.365 1090 389 c +1088 389 l +f +*U +0.000 0.224 0.165 0.286 k +*u +1284 389 m +1285 388 l +1284 389 l +f +*U +0.000 0.635 0.514 0.365 k +*u +1285 389 m +1285 384 l +1285.830 386 1285.830 386.970 1285 389 c +f +*U +0.000 0.824 0.627 0.176 k +*u +1286 389 m +1287.506 388.317 1288.315 388.174 1290 388 c +1289.776 386.316 1289.782 385.687 1290 384 c +1291.255 385.751 1291.614 386.857 1292 389 c +1286 389 l +f +*U +0.000 0.490 0.478 0.510 k +*u +1292 389 m +1293 388 l +1292 389 l +f +*U +0.000 0.678 0.475 0.322 k +*u +1296 389 m +1296.477 385.223 1296 379.552 1299 377 c +1298 381 1298.405 385.480 1296 389 c +f +*U +0.000 0.831 0.643 0.169 k +*u +1297 387 m +1305.923 389 1315.866 388 1325 388 c +1376 388 l +1370.537 390.292 1362.887 389 1357 389 c +1316 389 l +1310.940 389 1300.508 391 1297 387 c +f +*U +0.000 0.165 0.114 0.204 k +*u +1376 389 m +1377 388 l +1376 389 l +f +*U +0.000 0.259 0.192 0.082 k +*u +1284 388 m +1285 387 l +1284 388 l +f +*U +0.000 0.882 0.620 0.118 k +*u +1286 388 m +1285 379 l +1283.814 380 1283.396 380.339 1282 381 c +1282.576 378.313 1284.968 376.798 1287.361 379.333 c +1289.461 381.558 1289.624 385 1290 388 c +1286 388 l +f +*U +0.000 0.341 0.302 0.243 k +*u +1292 388 m +1293 387 l +1292 388 l +f +*U +0.000 0.859 0.620 0.141 k +*u +1298 388 m +1299 382 l +1303 384 l +1303.640 378.907 1315.759 381 1320 381 c +1376 381 l +1369.564 383.701 1359.951 382 1353 382 c +1304 382 l +1311.717 384.281 1320.982 383 1329 383 c +1378 383 l +1374.413 390.540 1364.181 388 1357 388 c +1298 388 l +f +*U +0.000 0.565 0.427 0.435 k +*u +1376.333 387.333 m +1376.278 387.278 1376.222 386.222 1376.667 386.667 c +1376.722 386.722 1376.777 387.778 1376.333 387.333 c +f +*U +0.000 0.337 0.216 0.373 k +*u +1071 387 m +1072 386 l +1071 387 l +f +*U +0.000 0.588 0.451 0.412 k +*u +1086 387 m +1086 385 l +1087.635 385.545 1087.455 385.365 1088 387 c +1086 387 l +f +*U +0.000 0.388 0.290 0.122 k +*u +1377 387 m +1378 386 l +1377 387 l +f +*U +0.000 0.290 0.196 0.043 k +*u +1070 386 m +1071 385 l +1070 386 l +f +*U +0.000 0.667 0.447 0.333 k +*u +1071.333 385.333 m +1071.278 385.278 1071.222 384.222 1071.667 384.667 c +1071.722 384.723 1071.777 385.778 1071.333 385.333 c +f +*U +0.000 0.408 0.306 0.263 k +*u +1087 386 m +1088 385 l +1087 386 l +f +*U +0.000 0.278 0.188 0.106 k +*u +1291 386 m +1292 385 l +1291 386 l +f +*U +0.000 0.498 0.400 0.133 k +*u +1296 386 m +1297 385 l +1296 386 l +f +*U +0.000 0.620 0.459 0.380 k +*u +1377.333 385.333 m +1377.278 385.278 1377.222 384.222 1377.667 384.667 c +1377.722 384.723 1377.777 385.778 1377.333 385.333 c +f +*U +0.000 0.333 0.224 0.341 k +*u +1070 385 m +1071 384 l +1070 385 l +f +*U +0.000 0.435 0.333 0.420 k +*u +1085.667 384.667 m +1085.222 384.222 1086.278 384.278 1086.333 384.333 c +1086.778 384.778 1085.722 384.722 1085.667 384.667 c +f +*U +0.000 0.114 0.090 0.271 k +*u +1284 385 m +1285 384 l +1284 385 l +f +*U +0.000 0.404 0.369 0.004 k +*u +1296 385 m +1297 384 l +1296 385 l +f +*U +0.000 0.196 0.157 0.290 k +*u +1378 385 m +1379 384 l +1378 385 l +f +*U +0.000 0.396 0.263 0.000 k +*u +1069 384 m +1070 383 l +1069 384 l +f +*U +0.000 0.800 0.596 0.200 k +*u +1070 384 m +1069 381 1068.635 379 1071 377 c +1070 384 l +f +*U +0.000 0.698 0.522 0.302 k +*u +1084 384 m +1084 381 l +1084.696 382.554 1084.696 382.446 1084 384 c +f +*U +0.000 0.349 0.298 0.651 k +*u +1085 384 m +1086 383 l +1085 384 l +f +*U +0.000 0.086 0.075 0.169 k +*u +1086 384 m +1087 383 l +1086 384 l +f +*U +0.000 0.773 0.600 0.227 k +*u +1283 384 m +1281.511 381.696 1280 379.503 1279 377 c +1282.306 377 1285.727 376.399 1288 379 c +1284.966 378.476 1283.720 378.400 1282 381 c +1285 379 l +1285.481 381.201 1285.481 381.799 1285 384 c +1283 384 l +f +*U +0.000 0.620 0.522 0.345 k +*u +1289 384 m +1288 380 l +1289.303 381.668 1289.553 381.992 1289 384 c +f +*U +0.000 0.412 0.318 0.318 k +*u +1290 384 m +1291 383 l +1290 384 l +f +*U +0.000 0.890 0.627 0.106 k +*u +1298 384 m +1298 378 l +1378 378 l +1378 383 l +1304 383 l +1310.436 380.299 1320 382 1327 382 c +1376 382 l +1370.309 379.919 1363 381 1357 381 c +1320 381 l +1315.950 381 1303.743 378.929 1303 384 c +1300.987 383.499 1299.961 383.363 1298 384 c +f +*U +0.000 0.612 0.580 0.337 k +*u +1378.333 383.333 m +1378.278 383.278 1378.222 382.222 1378.667 382.667 c +1378.722 382.722 1378.778 383.778 1378.333 383.333 c +f +*U +0.000 0.353 0.255 0.247 k +*u +1085 383 m +1086 382 l +1085 383 l +f +*U +0.000 0.388 0.310 0.612 k +*u +1282 383 m +1283 382 l +1282 383 l +f +*U +0.000 0.329 0.271 0.051 k +*u +1290 383 m +1291 382 l +1290 383 l +f +*U +0.000 0.184 0.141 0.337 k +*u +1379 383 m +1380 382 l +1379 383 l +f +*U +0.000 0.286 0.216 0.051 k +*u +1068 382 m +1069 381 l +1068 382 l +f +*U +0.000 0.863 0.671 0.137 k +*u +1378 382 m +1378 378 l +1299 378 l +1305.436 375.299 1315 377 1322 377 c +1359 377 l +1365.834 377 1373.416 376 1380 378 c +1379.436 379.752 1379 380.542 1378 382 c +f +*U +0.000 0.678 0.518 0.322 k +*u +1379.333 381.333 m +1379.278 381.278 1379.222 380.222 1379.667 380.667 c +1379.722 380.722 1379.778 381.778 1379.333 381.333 c +f +*U +0.000 0.698 0.561 0.302 k +*u +1068 381 m +1068 377 l +1068.710 378.759 1068.710 379.241 1068 381 c +f +*U +0.000 0.443 0.318 0.431 k +*u +1083.333 380.333 m +1083.278 380.278 1083.222 379.222 1083.667 379.667 c +1083.722 379.723 1083.777 380.778 1083.333 380.333 c +f +*U +0.000 0.302 0.220 0.224 k +*u +1084 381 m +1085 380 l +1084 381 l +f +*U +0.000 0.396 0.263 0.192 k +*u +1280 381 m +1281 380 l +1280 381 l +f +*U +0.000 0.325 0.298 0.188 k +*u +1289 381 m +1290 380 l +1289 381 l +f +*U +0.000 0.239 0.145 0.051 k +*u +1296 381 m +1297 380 l +1296 381 l +f +*U +0.000 0.439 0.275 0.145 k +*u +1380 381 m +1381 380 l +1380 381 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1288 380 m +1289 379 l +1288 380 l +f +*U +0.000 0.294 0.192 0.290 k +*u +1296 380 m +1297 379 l +1296 380 l +f +*U +0.000 0.667 0.459 0.333 k +*u +1380 380 m +1379 377 l +1380.766 377.979 1380.956 378.222 1380 380 c +f +*U +0.000 0.361 0.278 0.373 k +*u +1067 379 m +1068 378 l +1067 379 l +f +*U +0.000 0.275 0.200 0.122 k +*u +1083 379 m +1084 378 l +1083 379 l +f +*U +0.000 0.227 0.243 0.400 k +*u +1279 379 m +1280 378 l +1279 379 l +f +*U +0.000 0.204 0.192 0.573 k +*u +1288 379 m +1289 378 l +1288 379 l +f +*U +0.000 0.365 0.325 0.635 k +*u +1296.333 378.333 m +1296.278 378.278 1296.222 377.222 1296.667 377.667 c +1296.723 377.723 1296.777 378.778 1296.333 378.333 c +f +*U +0.000 0.231 0.282 0.224 k +*u +1381 379 m +1382 378 l +1381 379 l +f +*U +0.000 0.396 0.369 0.604 k +*u +1067 378 m +1068 377 l +1067 378 l +f +*U +0.000 0.729 0.584 0.271 k +*u +1071 378 m +1074.698 376.448 1079 377 1083 377 c +1079.302 378.552 1074.983 378 1071 378 c +f +*U +0.000 0.227 0.231 0.173 k +*u +1278 378 m +1279 377 l +1278 378 l +f +*U +0.000 0.341 0.369 0.518 k +*u +1381.333 377.333 m +1381.278 377.278 1381.222 376.222 1381.667 376.667 c +1381.722 376.722 1381.777 377.778 1381.333 377.333 c +f +*U +0.008 0.000 0.039 0.235 k +*u +1066 377 m +1067 376 l +1066 377 l +f +*U +0.000 0.345 0.290 0.271 k +*u +1067 377 m +1068 376 l +1067 377 l +f +*U +0.000 0.345 0.337 0.141 k +*u +1068 377 m +1072.217 375.231 1077.459 376 1082 376 c +1077.783 377.769 1072.541 377 1068 377 c +f +*U +0.000 0.075 0.075 0.141 k +*u +1082 377 m +1083 376 l +1082 377 l +f +*U +0.000 0.078 0.098 0.200 k +*u +1277 377 m +1278 376 l +1277 377 l +f +*U +0.000 0.514 0.420 0.059 k +*u +1278 377 m +1280 376 1281.747 376 1284 376 c +1281.948 376.874 1280.253 376.953 1278 377 c +f +*U +0.000 0.224 0.251 0.192 k +*u +1284 377 m +1285.506 376.317 1286.315 376.174 1288 376 c +1286.494 376.683 1285.685 376.826 1284 377 c +f +*U +0.000 0.408 0.376 0.114 k +*u +1296 377 m +1303 373.996 1314.256 376 1322 376 c +1381 376 l +1373.841 379 1362.744 377 1355 377 c +1296 377 l +f +*U +0.000 0.051 0.055 0.212 k +*u +1061 366 m +1062 365 l +1061 366 l +f +*U +0.000 0.314 0.231 0.306 k +*u +1062 366 m +1063 365 l +1062 366 l +f +*U +0.000 0.388 0.278 0.451 k +*u +1063 366 m +1064 365 l +1063 366 l +f +*U +0.000 0.420 0.306 0.251 k +*u +1064 366 m +1067.432 364.560 1071.300 365 1075 365 c +1071.568 366.440 1067.700 366 1064 366 c +f +*U +0.000 0.204 0.157 0.592 k +*u +1075 366 m +1076 365 l +1075 366 l +f +*U +0.000 0.373 0.251 0.278 k +*u +1262 366 m +1269 362.998 1278.342 365.823 1286 364 c +1282 368.565 1267.868 366 1262 366 c +f +*U +0.000 0.169 0.122 0.188 k +*u +1292 366 m +1293 365 l +1292 366 l +f +*U +0.000 0.373 0.251 0.278 k +*u +1293 366 m +1300.879 362.694 1313.466 365 1322 365 c +1387 365 l +1379 368.306 1366.534 366 1358 366 c +1293 366 l +f +*U +0.000 0.333 0.239 0.298 k +*u +1061 365 m +1062 364 l +1061 365 l +f +*U +0.000 0.886 0.639 0.114 k +*u +1062 365 m +1060.848 361.339 1059.742 357.774 1059 354 c +1067.597 354 1073 355.555 1075 365 c +1062 365 l +f +*U +0.000 0.400 0.365 0.600 k +*u +1075 365 m +1076 364 l +1075 365 l +f +*U +0.000 0.267 0.208 0.145 k +*u +1261.333 364.333 m +1261.278 364.278 1261.222 363.222 1261.667 363.667 c +1261.723 363.723 1261.777 364.778 1261.333 364.333 c +f +*U +0.000 0.871 0.604 0.125 k +*u +1262 365 m +1259.401 357.925 1251.946 358.723 1246 361 c +1241 354 l +1256.413 352.714 1272.503 354 1288 354 c +1384 354 l +1379.785 355.769 1374.536 355 1370 355 c +1343 355 l +1248 355 l +1253.436 356.607 1259.360 356 1265 356 c +1292 356 l +1384 356 l +1379.785 357.769 1374.536 357 1370 357 c +1344 357 l +1252 357 l +1266.222 361.322 1283.269 359 1298 359 c +1384 359 l +1378.697 362.618 1369.285 360 1363 360 c +1310 360 l +1302.427 360 1289.233 357.173 1285 365 c +1262 365 l +f +*U +0.000 0.251 0.188 0.090 k +*u +1291 365 m +1292 364 l +1291 365 l +f +*U +0.000 0.714 0.510 0.286 k +*u +1291 363 m +1292.580 363.683 1292.777 363.805 1294 365 c +1292.420 364.316 1292.223 364.195 1291 363 c +f +*U +0.000 0.839 0.584 0.161 k +*u +1294 363 m +1308.271 366.398 1325.354 364 1340 364 c +1354.951 364 1372.432 366.468 1387 363 c +1383.394 367 1372.217 365 1367 365 c +1313 365 l +1307.940 365 1297.508 367 1294 363 c +f +*U +0.000 0.243 0.184 0.122 k +*u +1387 365 m +1388 364 l +1387 365 l +f +*U +0.000 0.498 0.396 0.502 k +*u +1061.333 363.333 m +1061.278 363.278 1061.222 362.222 1061.667 362.667 c +1061.722 362.722 1061.777 363.778 1061.333 363.333 c +f +*U +0.000 0.341 0.271 0.243 k +*u +1075 364 m +1076 363 l +1075 364 l +f +*U +0.000 0.067 0.067 0.176 k +*u +1088 364 m +1089 363 l +1088 364 l +f +*U +0.000 0.196 0.153 0.208 k +*u +1245 364 m +1246 363 l +1245 364 l +f +*U +0.000 0.694 0.561 0.306 k +*u +1285 364 m +1285.980 362.217 1285.908 362.406 1288 362 c +1286.861 363 1286.388 363.309 1285 364 c +f +*U +0.000 0.290 0.278 0.333 k +*u +1286 364 m +1287 363 l +1286 364 l +f +*U +0.000 0.318 0.227 0.149 k +*u +1290 364 m +1291 363 l +1290 364 l +f +*U +0.000 0.875 0.631 0.114 k +*u +1288 361 m +1295 357.996 1306.256 360 1314 360 c +1361 360 l +1368.555 360 1376.591 361.314 1384 360 c +1371.804 356.395 1355.711 359 1343 359 c +1259 359 l +1262.959 357.339 1267.740 358 1272 358 c +1297 358 l +1384 358 l +1384 354 l +1388 354 l +1386 357 l +1387.479 356 1387.203 356 1389 356 c +1386.575 367 1375 364 1366 364 c +1316 364 l +1306.514 364 1296.677 365.344 1288 361 c +f +*U +0.000 0.537 0.392 0.463 k +*u +1387.333 363.333 m +1387.278 363.278 1387.222 362.222 1387.667 362.667 c +1387.722 362.722 1387.777 363.778 1387.333 363.333 c +f +*U +0.000 0.200 0.141 0.067 k +*u +1060 363 m +1061 362 l +1060 363 l +f +*U +0.000 0.282 0.220 0.424 k +*u +1088 363 m +1089 362 l +1088 363 l +f +*U +0.000 0.204 0.169 0.133 k +*u +1089 363 m +1090 362 l +1089 363 l +f +*U +0.000 0.325 0.318 0.675 k +*u +1245 363 m +1246 362 l +1245 363 l +f +*U +0.000 0.706 0.533 0.294 k +*u +1246 363 m +1244.602 360.950 1243.749 359.354 1243 357 c +1244.867 358.548 1246.438 360 1248 362 c +1246 363 l +f +*U +0.000 0.349 0.271 0.322 k +*u +1261 363 m +1262 362 l +1261 363 l +f +*U +0.000 0.392 0.278 0.361 k +*u +1288 363 m +1289 362 l +1288 363 l +f +*U +0.000 0.753 0.569 0.247 k +*u +1288 361 m +1289.580 361.683 1289.777 361.805 1291 363 c +1289.420 362.316 1289.223 362.195 1288 361 c +f +*U +0.000 0.400 0.275 0.184 k +*u +1060 362 m +1061 361 l +1060 362 l +f +*U +0.000 0.420 0.286 0.251 k +*u +1074 362 m +1075 361 l +1074 362 l +f +*U +0.000 0.424 0.329 0.506 k +*u +1088 362 m +1088 360 l +1090 360 l +1090 362 l +1088 362 l +f +*U +0.000 0.255 0.192 0.149 k +*u +1244 362 m +1245 361 l +1244 362 l +f +*U +0.000 0.341 0.267 0.200 k +*u +1260 362 m +1261 361 l +1260 362 l +f +*U +0.000 0.306 0.224 0.047 k +*u +1388 362 m +1389 361 l +1388 362 l +f +*U +0.000 0.251 0.196 0.227 k +*u +1090 361 m +1091 360 l +1090 361 l +f +*U +0.000 0.365 0.235 0.604 k +*u +1248 361 m +1249 360 l +1248 361 l +f +*U +0.000 0.306 0.200 0.286 k +*u +1249 361 m +1250 360 l +1249 361 l +f +*U +0.000 0.169 0.110 0.098 k +*u +1250 361 m +1251 360 l +1250 361 l +f +*U +0.000 0.255 0.176 0.322 k +*u +1258 361 m +1259 360 l +1258 361 l +f +*U +0.000 0.714 0.580 0.286 k +*u +1259.667 360.667 m +1259.222 360.222 1260.278 360.278 1260.333 360.333 c +1260.778 360.778 1259.722 360.722 1259.667 360.667 c +f +*U +0.000 0.467 0.325 0.306 k +*u +1388 361 m +1389 360 l +1388 361 l +f +*U +0.000 0.290 0.216 0.055 k +*u +1059 360 m +1060 359 l +1059 360 l +f +*U +0.000 0.655 0.510 0.345 k +*u +1072 360 m +1069.176 353.787 1065.243 354 1059 354 c +1063.989 351.907 1074 352.287 1072 360 c +f +*U +0.000 0.247 0.176 0.310 k +*u +1073 360 m +1074 359 l +1073 360 l +f +*U +0.153 0.004 0.000 0.196 k +*u +1087 360 m +1088 359 l +1087 360 l +f +*U +0.000 0.843 0.647 0.157 k +*u +1088 360 m +1088 356 l +1092 356 l +1091 360 l +1088 360 l +f +*U +0.000 0.318 0.204 0.118 k +*u +1243 360 m +1244 359 l +1243 360 l +f +*U +0.000 0.671 0.537 0.329 k +*u +1248 360 m +1250.613 358.902 1253 359 1256 359 c +1253.387 360 1250.836 359.993 1248 360 c +f +*U +0.000 0.502 0.463 0.498 k +*u +1388.333 359.333 m +1388.278 359.278 1388.222 358.222 1388.667 358.667 c +1388.722 358.722 1388.778 359.778 1388.333 359.333 c +f +*U +0.000 0.420 0.294 0.278 k +*u +1059 359 m +1060 358 l +1059 359 l +f +*U +0.000 0.337 0.235 0.055 k +*u +1073 359 m +1074 358 l +1073 359 l +f +*U +0.000 0.220 0.259 0.239 k +*u +1087 359 m +1088 358 l +1087 359 l +f +*U +0.000 0.592 0.471 0.408 k +*u +1091.333 358.333 m +1091.278 358.278 1091.222 357.222 1091.667 357.667 c +1091.722 357.723 1091.777 358.778 1091.333 358.333 c +f +*U +0.000 0.192 0.188 0.278 k +*u +1389 359 m +1390 358 l +1389 359 l +f +*U +0.000 0.639 0.498 0.361 k +*u +1059.333 357.333 m +1059.278 357.278 1059.222 356.222 1059.667 356.667 c +1059.722 356.722 1059.777 357.778 1059.333 357.333 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1087.333 357.333 m +1087.278 357.278 1087.222 356.222 1087.667 356.667 c +1087.722 356.722 1087.777 357.778 1087.333 357.333 c +f +*U +0.000 0.443 0.294 0.004 k +*u +1092 358 m +1093 357 l +1092 358 l +f +*U +0.000 0.349 0.247 0.180 k +*u +1242 358 m +1243 357 l +1242 358 l +f +*U +0.000 0.824 0.620 0.153 k +*u +1252 358 m +1256.215 356.231 1261.465 357 1266 357 c +1292 357 l +1384 357 l +1379.785 358.769 1374.536 358 1370 358 c +1344 358 l +1252 358 l +f +*U +0.000 0.427 0.380 0.329 k +*u +1389 358 m +1390 357 l +1389 358 l +f +*U +0.000 0.337 0.204 0.000 k +*u +1058 357 m +1059 356 l +1058 357 l +f +*U +0.000 0.102 0.067 0.180 k +*u +1072 357 m +1073 356 l +1072 357 l +f +*U +0.000 0.478 0.384 0.224 k +*u +1086 357 m +1087 356 l +1086 357 l +f +*U +0.000 0.455 0.294 0.275 k +*u +1092 357 m +1093 356 l +1092 357 l +f +*U +0.000 0.035 0.067 0.153 k +*u +1210 357 m +1211 356 l +1210 357 l +f +*U +0.000 0.424 0.306 0.278 k +*u +1211.667 356.667 m +1211.222 356.222 1212.278 356.278 1212.333 356.333 c +1212.778 356.778 1211.722 356.722 1211.667 356.667 c +f +*U +0.000 0.592 0.592 0.408 k +*u +1213 357 m +1215 353 l +1215.683 354.506 1215.826 355.315 1216 357 c +1213 357 l +f +*U +0.012 0.149 0.000 0.208 k +*u +1239 357 m +1240 356 l +1239 357 l +f +*U +0.000 0.588 0.373 0.412 k +*u +1240 357 m +1241.249 356.315 1241.548 356.251 1243 356 c +1241.752 356.685 1241.452 356.749 1240 357 c +f +*U +0.000 0.898 0.537 0.102 k +*u +1386 357 m +1386.901 355 1387 355 1389 354 c +1388 355.923 1387.924 355.999 1386 357 c +f +*U +0.000 0.655 0.384 0.345 k +*u +1389 357 m +1389.406 354.908 1389.217 354.980 1391 354 c +1390.309 355.388 1390 355.861 1389 357 c +f +*U +0.000 0.255 0.094 0.118 k +*u +1390.333 356.333 m +1390.278 356.278 1390.222 355.222 1390.667 355.667 c +1390.722 355.722 1390.777 356.778 1390.333 356.333 c +f +*U +0.000 0.416 0.282 0.286 k +*u +1058 356 m +1059 355 l +1058 356 l +f +*U +0.000 0.122 0.176 0.220 k +*u +1082.667 355.667 m +1082.222 355.222 1083.278 355.278 1083.333 355.333 c +1083.778 355.778 1082.722 355.722 1082.667 355.667 c +f +*U +0.000 0.345 0.247 0.290 k +*u +1084 356 m +1085 355 l +1084 356 l +f +*U +0.000 0.686 0.514 0.314 k +*u +1085.667 355.667 m +1085.222 355.222 1086.278 355.278 1086.333 355.333 c +1086.778 355.778 1085.722 355.722 1085.667 355.667 c +f +*U +0.000 0.910 0.651 0.090 k +*u +1085 355 m +1086.506 354.317 1087.315 354.174 1089 354 c +1087.276 355 1087 355 1085 355 c +f +*U +0.000 0.678 0.482 0.216 k +*u +1088 356 m +1089.223 354.805 1089.420 354.684 1091 354 c +1090 355.783 1090 355.594 1088 356 c +f +*U +0.000 0.478 0.329 0.522 k +*u +1091 356 m +1091 353 l +1091.696 354.554 1091.696 354.446 1091 356 c +f +*U +0.000 0.263 0.153 0.067 k +*u +1092 356 m +1093 355 l +1092 356 l +f +*U +0.000 0.125 0.051 0.110 k +*u +1207 356 m +1208 355 l +1207 356 l +f +*U +0.000 0.898 0.643 0.102 k +*u +1208 356 m +1209.926 353.792 1212 354 1215 354 c +1215 356 l +1208 356 l +f +*U +0.000 0.620 0.518 0.380 k +*u +1209.667 355.667 m +1209.222 355.222 1210.278 355.278 1210.333 355.333 c +1210.778 355.778 1209.722 355.722 1209.667 355.667 c +f +*U +0.000 0.161 0.235 0.263 k +*u +1231 356 m +1232 355 l +1231 356 l +f +*U +0.000 0.475 0.380 0.478 k +*u +1232 356 m +1233 355 l +1232 356 l +f +*U +0.000 0.365 0.443 0.149 k +*u +1233 356 m +1234.248 355.315 1234.548 355.251 1236 355 c +1234.751 355.685 1234.452 355.749 1233 356 c +f +*U +0.000 0.467 0.302 0.059 k +*u +1236.667 355.667 m +1236.222 355.222 1237.278 355.278 1237.333 355.333 c +1237.778 355.778 1236.722 355.722 1236.667 355.667 c +f +*U +0.000 0.537 0.482 0.447 k +*u +1238.667 355.667 m +1238.222 355.222 1239.278 355.278 1239.333 355.333 c +1239.778 355.778 1238.722 355.722 1238.667 355.667 c +f +*U +0.000 0.714 0.502 0.286 k +*u +1240 356 m +1240.654 352.946 1242 353 1245 353 c +1241 355 l +1242 356 l +1240 356 l +f +*U +0.000 0.878 0.671 0.122 k +*u +1248 356 m +1252.215 354.231 1257.465 355 1262 355 c +1289 355 l +1384 355 l +1379.785 356.769 1374.536 356 1370 356 c +1343 356 l +1248 356 l +f +*U +0.000 0.361 0.361 0.639 k +*u +1058.333 354.333 m +1058.278 354.278 1058.222 353.222 1058.667 353.667 c +1058.722 353.722 1058.777 354.778 1058.333 354.333 c +f +*U +0.000 0.518 0.341 0.176 k +*u +1071 355 m +1072 354 l +1071 355 l +f +*U +0.000 0.208 0.165 0.027 k +*u +1079 355 m +1080 354 l +1079 355 l +f +*U +0.000 0.698 0.620 0.302 k +*u +1080 353 m +1091 353 l +1087.676 354.492 1082.641 355.976 1080 353 c +f +*U +0.000 0.208 0.137 0.067 k +*u +1204 355 m +1205 354 l +1204 355 l +f +*U +0.000 0.467 0.325 0.200 k +*u +1205 355 m +1206 354 l +1205 355 l +f +*U +0.000 0.780 0.635 0.220 k +*u +1206.667 354.667 m +1206.222 354.222 1207.278 354.278 1207.333 354.333 c +1207.778 354.778 1206.722 354.722 1206.667 354.667 c +f +*U +0.000 0.800 0.686 0.200 k +*u +1229 355 m +1230.223 353.805 1230.420 353.684 1232 353 c +1231 354.783 1231 354.594 1229 355 c +f +*U +0.000 0.741 0.784 0.196 k +*u +1232 353 m +1236 354 l +1233.954 354.751 1233.404 354.656 1232 353 c +f +*U +0.000 0.706 0.686 0.294 k +*u +1233 354 m +1235.332 353 1237.457 353 1240 353 c +1237.557 354.530 1235.855 354.392 1233 354 c +f +*U +0.000 0.831 0.776 0.149 k +*u +1238.667 354.667 m +1238.222 354.222 1239.278 354.278 1239.333 354.333 c +1239.778 354.778 1238.722 354.722 1238.667 354.667 c +f +*U +0.000 0.251 0.192 0.110 k +*u +1057 354 m +1058 353 l +1057 354 l +f +*U +0.000 0.357 0.216 0.102 k +*u +1071 354 m +1072 353 l +1071 354 l +f +*U +0.000 0.192 0.161 0.243 k +*u +1077 354 m +1078 353 l +1077 354 l +f +*U +0.000 0.400 0.361 0.600 k +*u +1078.667 353.667 m +1078.222 353.222 1079.278 353.278 1079.333 353.333 c +1079.778 353.778 1078.722 353.722 1078.667 353.667 c +f +*U +0.000 0.800 0.580 0.200 k +*u +1081.667 353.667 m +1081.222 353.222 1082.278 353.278 1082.333 353.333 c +1082.778 353.778 1081.722 353.722 1081.667 353.667 c +f +*U +0.000 0.047 0.031 0.192 k +*u +1092 354 m +1093 353 l +1092 354 l +f +*U +0.000 0.110 0.231 0.114 k +*u +1202 354 m +1203 353 l +1202 354 l +f +*U +0.000 0.365 0.365 0.635 k +*u +1203.667 353.667 m +1203.222 353.222 1204.278 353.278 1204.333 353.333 c +1204.778 353.778 1203.722 353.722 1203.667 353.667 c +f +*U +0.000 0.659 0.514 0.341 k +*u +1205 354 m +1208 352.673 1211.586 353 1215 353 c +1211.837 354.327 1208.415 354.000 1205 354 c +f +*U +0.000 0.145 0.114 0.263 k +*u +1227 354 m +1228 353 l +1227 354 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1228.667 353.667 m +1228.222 353.222 1229.278 353.278 1229.333 353.333 c +1229.778 353.778 1228.722 353.722 1228.667 353.667 c +f +*U +0.000 0.671 0.702 0.298 k +*u +1246 354 m +1250.215 352.231 1255.464 353 1260 353 c +1289 353 l +1390 353 l +1385.785 354.769 1380.536 354 1376 354 c +1347 354 l +1246 354 l +f +*U +0.000 0.345 0.345 0.655 k +*u +1390 354 m +1391 353 l +1390 354 l +f +*U +0.020 0.000 0.000 0.282 k +*u +1069.667 352.667 m +1069.222 352.222 1070.278 352.278 1070.333 352.333 c +1070.778 352.778 1069.722 352.722 1069.667 352.667 c +f +*U +0.082 0.000 0.082 0.129 k +*u +1081 353 m +1082 352 l +1081 353 l +f +*U +0.000 0.196 0.145 0.125 k +*u +1203.667 352.667 m +1203.222 352.222 1204.278 352.278 1204.333 352.333 c +1204.778 352.778 1203.722 352.722 1203.667 352.667 c +f +*U +0.000 0.271 0.153 0.094 k +*u +1213 353 m +1214.249 352.315 1214.548 352.251 1216 352 c +1214.752 352.685 1214.452 352.749 1213 353 c +f +*U +0.000 0.114 0.106 0.192 k +*u +1229.667 352.667 m +1229.222 352.222 1230.278 352.278 1230.333 352.333 c +1230.778 352.778 1229.722 352.722 1229.667 352.667 c +f +*U +0.000 0.302 0.125 0.067 k +*u +1388 353 m +1389.248 352.315 1389.548 352.251 1391 352 c +1389.752 352.685 1389.451 352.749 1388 353 c +f +*U +0.000 0.000 0.000 0.075 k +*u +38 344 m +38 342 l +248 342 l +248 328 l +169 328 l +169 308 l +171 308 l +171 326 l +221 326 l +228.998 326 238 324.805 245.941 326 c +251 327 252 340 248.397 342.972 c +245 345.544 236.929 344 233 344 c +193 344 l +38 344 l +f +*U +0.000 0.000 0.000 0.067 k +*u +283 344 m +283 342 l +303 342 324 340.473 344 343 c +338.293 345.395 330 344 324 344 c +283 344 l +f +*U +0.000 0.000 0.000 0.075 k +*u +381 344 m +381 342 l +402 342 l +402 317 l +402 313.346 400.779 308.904 405 308 c +403.315 310.695 404 313.738 404 317 c +404 334 l +404 336.397 405 341.905 402.833 343.500 c +401.413 344.522 398.639 344 397 344 c +381 344 l +f +*U +0.000 0.000 0.000 0.067 k +*u +476 344 m +476 342 l +498 342 l +498 344 l +476 344 l +f +*U +0.000 0.000 0.000 0.055 k +*u +523 344 m +525.431 341.218 529.491 342 533 342 c +533 344 l +523 344 l +f +*U +0.000 0.000 0.000 0.075 k +*u +613 343 m +619.202 340.397 628.298 342 635 342 c +635 344 l +627.863 344 619.871 345 613 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +658 256 m +661 263.399 659 274.993 659 283 c +659 342 l +663.930 342 673.587 340 677 344 c +672.386 343.703 661.217 346.237 658 342.258 c +656.459 340.299 657.287 337.229 657.576 335 c +658.219 330 658 324.999 658 320 c +658 256 l +f +*U +0.000 0.000 0.000 0.075 k +*u +723 344 m +728.261 340.406 736.835 342 743 342 c +791 342 l +783.828 345 774.666 344 767 344 c +723 344 l +f +855 339 m +861.361 343.592 871.617 342.758 879 341 c +878.203 344.720 875.390 344 872 344 c +866.888 344 855 346 855 339 c +f +*U +0.000 0.000 0.000 0.067 k +*u +937 344 m +937 342 l +958 342 l +958 271 l +960 271 l +960 325 l +960 329 961.939 340.167 958.397 342.972 c +956.719 344.301 953.992 343.986 952 343.999 c +937 344 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1424 343 m +1429.281 338.999 1439.557 341 1446 341 c +1446 305 l +1450 307 l +1445 318.691 1451.483 332.607 1446 344 c +1438.638 343 1431.415 343 1424 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1503 342 m +1509.638 339.215 1523 339.975 1530 342 c +1523.242 344.909 1509.979 344 1503 342 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1943 343 m +1948.750 338.644 1958 341.897 1965 339 c +1963 344 l +1956.487 342.449 1949.659 343 1943 343 c +f +*U +0.000 0.000 0.000 0.161 k +*u +268 341 m +272.467 339.644 278.216 341.960 283 342 c +278 344 272.854 342.539 268 341 c +f +*U +0.000 0.000 0.000 0.133 k +*u +340 343 m +343 341.673 346.586 342 350 342 c +346.837 343.327 343.414 343.000 340 343 c +f +*U +0.000 0.000 0.000 0.141 k +*u +380 343 m +380 254 l +402 254 l +396.639 256.249 386.863 252.344 382.603 256.603 c +378.748 260.459 381 272.899 381 278 c +381 324 l +381 329.509 382.740 338.261 380 343 c +f +*U +0.000 0.000 0.000 0.067 k +*u +519 343 m +520.934 332.581 520 321.567 520 311 c +520 256 l +522.802 262.678 521 272.785 521 280 c +521 320 l +521 327.591 520.233 335.578 522 343 c +519 343 l +f +*U +0.000 0.000 0.000 0.157 k +*u +533.667 342.667 m +533.222 342.222 534.278 342.278 534.333 342.333 c +534.778 342.778 533.722 342.722 533.667 342.667 c +f +*U +0.000 0.000 0.000 0.075 k +*u +678 343 m +680.338 333.181 679 322 679 312 c +679 256 l +681 256 l +681 321 l +681 327 683.405 339.182 678 343 c +f +*U +0.000 0.000 0.000 0.137 k +*u +716 343 m +718.890 341.787 721.874 342 725 342 c +722 343.213 719 342.998 716 343 c +f +*U +0.000 0.000 0.000 0.129 k +*u +936 343 m +936 277 l +936 271.319 933.549 257.889 938 254 c +936.473 262.226 937 270.661 937 279 c +937 318 l +937 322.989 936.823 328 937 333 c +937.204 336.798 938.331 339.800 936 343 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1541 333 m +1552.458 342.259 1563.919 341 1578 341 c +1632 341 l +1632 343 l +1609 343 1585.778 344.470 1563 342.910 c +1555.191 342.376 1543.470 341.855 1541 333 c +f +1678 342 m +1684.678 339.198 1694.784 341 1702 341 c +1740 341 l +1746.834 341 1754.416 340 1761 342 c +1754.322 344.802 1744.216 343 1737 343 c +1700 343 l +1692.719 343 1685 343.695 1678 342 c +f +1798 342 m +1805.639 338.794 1817.729 341 1826 341 c +1873 341 l +1880.722 341 1889.565 339.802 1897 342 c +1889 345.306 1876.534 343 1868 343 c +1823 343 l +1814.790 343 1806 343.910 1798 342 c +f +*U +0.000 0.000 0.000 0.149 k +*u +37 342 m +37 328 l +38.667 331.972 38.667 338 37 342 c +f +*U +0.000 0.000 0.000 0.843 k +*u +38 342 m +38 328 l +39.667 331.972 39.667 338 38 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +39 342 m +39 328 l +84 328 l +84 255 l +104 255 l +104 328 l +147 328 l +147 342 l +39 342 l +f +*U +0.000 0.000 0.000 0.502 k +*u +147 342 m +147 328 l +148.796 332.279 147.909 337.419 149 342 c +147 342 l +f +*U +0.000 0.000 0.000 1.000 k +*u +149 342 m +149 255 l +249 255 l +249 269 l +169 269 l +169 296 l +166.727 292.523 167.889 288.994 167.985 285 c +168 277.977 167.882 270.994 168 264 c +194.536 265.978 221.374 265 248 265 c +247.971 262.575 248.282 259.481 246.397 257.603 c +242.527 253.750 230 256 225 256 c +152 256 l +152 305 l +152 309.955 153.774 319.380 150 323 c +152.697 326.851 152 331.439 152 336 c +247 336 l +247 329 l +168 329 l +168 323.686 168.242 318.306 167.911 313 c +167.774 310.792 166.850 307.834 168.357 305.898 c +170.552 303 176.906 305 180 305 c +191.999 304.932 204 305 216 305 c +216 296 l +170 296 l +170 294 l +217 294 l +217 307 l +169 307 l +169 328 l +248 328 l +248 342 l +149 342 l +f +*U +0.000 0.000 0.000 0.565 k +*u +275 342 m +276 341 l +275 342 l +f +*U +0.000 0.000 0.000 0.835 k +*u +276.667 341.667 m +276.222 341.222 277.278 341.278 277.333 341.333 c +277.778 341.778 276.722 341.722 276.667 341.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +365 288 m +358.261 288 351.753 289.944 345 290 c +345 269 l +298 269 l +293.583 269 283.993 267.214 280.603 270.603 c +277.463 273.744 279 281.938 279 286 c +279 328 l +345 328 l +345 309 l +348.433 309.434 352.677 309.327 355 312 c +351 311 l +351 328 l +349.902 325.387 350 322.835 350 320 c +349.190 322.729 349 325 349 328 c +346.699 322.517 349.734 315.928 346 311 c +347.722 316.825 347 323 346 329 c +278 329 l +278 325 l +276.285 326.551 275.177 327.244 273 328 c +271.600 322 272.998 316 273 310 c +273 270 l +277 271 l +278 267 l +275 269 l +274.438 267.199 274.176 265.878 274 264 c +273.438 265.801 273.176 267 273 269 c +272 267 271.561 265 271 263 c +268.234 263.676 267.348 263.604 265 262 c +264 265.534 263.510 268.354 264 272 c +262 271 l +262.934 272.723 263.535 274 264 276 c +261 275 l +262 279 l +263 277 l +264.769 281.215 264 286.464 264 291 c +264 301.834 266.730 317 262 327 c +264 326 l +263.339 327.396 263 327.814 262 329 c +263.367 330.731 263.984 333 265.564 334.658 c +268.309 337.354 273.537 336.315 277 336 c +277.228 338 277 337.890 279 339 c +278 337.521 278 337.797 278 336 c +297.472 337.254 317.471 335.999 337 336 c +342.945 336 352.661 338.707 357.870 335 c +359.627 333.792 360.672 331.638 362 330 c +359 324.658 360 317.970 360 312 c +356 312 l +364.876 308.285 365 316.411 364.985 323 c +364.776 331.411 361.647 338.267 352.999 340.485 c +344.854 342.575 336.325 342 328 342 c +291 342 l +283 342 272.886 342.842 266 338 c +260.527 334 260 327.249 260 321 c +260 279 l +260 272 259.582 264.689 265.329 259.800 c +271.276 254.742 281.613 255 289 255 c +305.663 254.994 322.339 254.806 339 255 c +345.793 255 355.403 255.340 360.442 260.532 c +367 267.310 365 279.432 365 288 c +f +*U +0.000 0.000 0.000 0.784 k +*u +347.667 341.667 m +347.222 341.222 348.278 341.278 348.333 341.333 c +348.778 341.778 347.722 341.722 347.667 341.667 c +f +*U +0.000 0.000 0.000 0.514 k +*u +349 342 m +350 341 l +349 342 l +f +*U +0.000 0.000 0.000 0.196 k +*u +352.667 341.667 m +352.222 341.222 353.278 341.278 353.333 341.333 c +353.778 341.778 352.722 341.722 352.667 341.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +382 342 m +382 255 l +402 255 l +402 293 l +477 293 l +477 255 l +496 255 l +496 342 l +477 342 l +477 307 l +402 307 l +402 342 l +382 342 l +f +*U +0.000 0.000 0.000 0.145 k +*u +475 342 m +475 309 l +405 309 l +411.194 306.401 420.314 308 427 308 c +476 308 l +476 330 l +476 333.983 476.552 338.301 475 342 c +f +*U +0.000 0.000 0.000 0.635 k +*u +476 342 m +476 308 l +477.328 311 477.000 314.581 477 318 c +477 325.215 478.802 335.323 476 342 c +f +*U +0.000 0.000 0.000 0.855 k +*u +496 342 m +496 255 l +498.395 260.707 497 268.846 497 275 c +497 319 l +497 325.951 498.701 335.564 496 342 c +f +*U +0.000 0.000 0.000 0.161 k +*u +497 342 m +497 255 l +476 255 l +482.202 252.397 491.298 254 498 254 c +498 315 l +498 323 500 334.600 497 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +521 342 m +521 255 l +539 255 l +539 320 l +536.960 317.763 536.388 316.617 538 314 c +534.952 308.288 536 301.340 536 295 c +536 256 l +527 256 l +527 317 l +527 325 529.264 334.805 522 340 c +526 339.907 528.433 337.780 532 336 c +531 338 l +532.635 337.455 532.455 337.635 533 336 c +534.797 336 534.521 336 536 337 c +537 336 l +536.438 334.199 536.176 332.878 536 331 c +536.685 332.248 536.749 332.548 537 334 c +537.225 331.765 537 331 536 329 c +536.873 326.519 537 324.638 537 322 c +540.167 321.588 540.838 318.289 543 316 c +547 311.801 552.312 308.388 557 304.861 c +571 294.254 585 283.464 599 272.611 c +605.712 267.375 613.978 258.378 622 255.500 c +625.547 254.227 630.278 255 634 255 c +634 342 l +615 342 l +615 320.949 615 299.981 616 279 c +599.355 295.299 578.505 308 560 322.235 c +552 328.219 543.366 337.927 534 341.272 c +530 342.687 525 342 521 342 c +f +*U +0.000 0.000 0.000 0.725 k +*u +534 342 m +535 341 l +534 342 l +f +*U +0.000 0.000 0.000 0.145 k +*u +614 342 m +614 283 l +612.483 283.957 611.661 284.387 610 285 c +611.549 282.864 612.864 281.549 615 280 c +615 322 l +615 328 616.395 336.293 614 342 c +f +*U +0.000 0.000 0.000 0.153 k +*u +634 342 m +634 255 l +636.395 260.707 635 268.846 635 275 c +635 319 l +635 325.951 636.701 335.564 634 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +659 342 m +659 255 l +679 255 l +679 342 l +659 342 l +f +*U +0.000 0.000 0.000 0.200 k +*u +707 340 m +709.533 339.463 711.512 340.220 714 341 c +711.328 341.799 709.568 341 707 340 c +f +*U +0.000 0.000 0.000 0.569 k +*u +716 342 m +717 341 l +716 342 l +f +*U +0.000 0.000 0.000 0.882 k +*u +717.667 341.667 m +717.222 341.222 718.278 341.278 718.333 341.333 c +718.778 341.778 717.722 341.722 717.667 341.667 c +f +*U +0.000 0.000 0.000 0.996 k +*u +806 288 m +800.959 288.216 795.988 289.841 791 289 c +792.981 280.677 790.819 272.352 792 264 c +739 264 l +735 264 723.533 262.871 723 267 c +720 265 l +720.462 270 719 275.691 719 281 c +719 329 l +771 329 l +777 329 786.400 330.884 790 325 c +790.685 326.248 790.749 326.548 791 328 c +792.254 322.426 791.350 316.569 793 311 c +800 312 l +800 320.200 800.248 328.211 803 336 c +792 342.480 781.309 342 769 342 c +730 342 l +721.969 342 710.324 342.670 704.649 335.787 c +700.958 331.311 701 325.467 701 320 c +701 295 l +701 285.335 697.933 269.255 704.649 261.329 c +709.588 255.499 718.907 255 726 255 c +742.994 254.802 760 254.993 777 255 c +784.338 255 794.781 254.715 800.660 259.800 c +808 266.288 806 279.211 806 288 c +f +*U +0.000 0.000 0.000 0.788 k +*u +788.667 341.667 m +788.223 341.223 789.277 341.278 789.333 341.333 c +789.778 341.778 788.722 341.722 788.667 341.667 c +f +*U +0.000 0.000 0.000 0.525 k +*u +790 342 m +791 341 l +790 342 l +f +*U +0.000 0.000 0.000 0.098 k +*u +791 342 m +793.283 340.779 795.428 340.348 798 340 c +795.686 341.591 793.810 341.858 791 342 c +f +*U +0.000 0.000 0.000 1.000 k +*u +818 278 m +823 280 l +822 283 l +823.796 283.969 823.681 285.432 825.194 286.889 c +826.774 288.409 829 287.791 830.611 289.306 c +832.810 291.495 833 298.935 834 302 c +835.714 300.450 836.823 299.756 839 299 c +838 296 l +841 295 l +840.458 292.326 840.493 291.269 842 289 c +850 301.314 860.923 315 866 329 c +868 329 l +873.587 314.239 886.418 302.728 892 288 c +896 290 l +895 296 l +893.805 295.402 894 295.534 893 294 c +892 295.207 889.170 296.995 888 299 c +887.230 300.321 887.249 303.259 887 305 c +886.895 305.737 889 305.375 886 306 c +887.479 306.986 887.203 307 889 307 c +887.752 307.685 887.452 307.749 886 308 c +887 312 l +885.263 311.938 885.360 311.980 884 313 c +883 310 l +881.483 310.957 880.661 311.387 879 312 c +879.764 314.746 879.764 316.254 879 319 c +888 321 l +888.197 318.624 888.247 316.372 888 314 c +890.580 313 892.253 312.747 895 313 c +895.628 310 896.659 307.856 896 305 c +896.810 303.230 896.497 301.947 898 301 c +896.964 299.814 896.661 299.396 896 298 c +898.377 297.689 898.983 297.747 901 299 c +901 297.203 901 297.479 902 296 c +905 297 l +904 292.337 904.911 289.835 910 290 c +910.560 284.738 913.861 280.204 918 277 c +916.703 275.406 916.465 274.982 916 273 c +917.797 273 917.522 273 919 274 c +919.902 272 920 272 922 271 c +921.954 268.752 922 268 923 266 c +920.717 264.554 920.418 263.689 920 261 c +921 262.458 921.436 263.248 922 265 c +923.938 261.993 925.532 260 929 259 c +922.952 255.612 912.227 253.236 912 263 c +909.433 264.246 908.914 265 909 268 c +910 266.466 909.805 266.598 911 266 c +912 271.764 907.541 271.650 903 272 c +903.986 273.479 904 273.203 904 275 c +902.521 275.986 902.797 276 901 276 c +902 277.186 902.339 277.604 903 279 c +900.777 279.184 900.810 279.240 899 278 c +892.386 281.530 883.352 280 876 280 c +851 280 l +844.697 280 838.703 280.351 833.274 276.532 c +830.404 274.513 828.884 270.872 827 268 c +826 271 l +823 270 l +824.341 268.726 825.403 267.959 827 267 c +825.952 265 825.487 264 825 262 c +823 262 822.734 261.830 821 261 c +822 263 l +816 261 l +817 256 l +807 256 l +808.283 260.441 810.639 264 813 268 c +814 265 l +815.554 267.485 815.542 269 815 272 c +818 273 l +818 277 l +811.345 272.962 806.249 261.951 803 255 c +808.192 255 818.207 253 822.391 256.603 c +827.945 261.295 829.256 272.479 836.185 275.397 c +841 277.438 848.806 276 854 276 c +866.992 276 880 276.241 892.999 275.995 c +904 275.786 904.250 262.539 911.529 256.603 c +916 252.850 927.332 255 933 255 c +921.231 277 906 298 892.344 319 c +888.903 324.272 885.735 329.719 882.308 334.999 c +880.831 337.274 879.276 340.246 876.674 341.397 c +872.829 343 860.974 343.216 857.379 340.972 c +852.377 337.851 848.859 328.923 845.808 324 c +840 314.649 834.265 305.249 828.308 296 c +824.582 290.215 820 284.615 818 278 c +f +938 342 m +938 255 l +1033 255 l +1033 269 l +958 269 l +958 342 l +938 342 l +f +*U +0.000 0.427 0.302 0.239 k +*u +1054.333 341.333 m +1054.278 341.278 1054.222 340.222 1054.667 340.667 c +1054.723 340.723 1054.777 341.778 1054.333 341.333 c +f +*U +0.000 0.525 0.416 0.475 k +*u +1055 340 m +1066.604 342.763 1080 341 1092 341 c +1096.941 341 1102.923 342 1107 339 c +1108.703 343.519 1098.748 342 1096 342 c +1066 342 l +1062.385 342 1057.271 343 1055 340 c +f +*U +0.000 0.341 0.243 0.047 k +*u +1108.333 341.333 m +1108.278 341.278 1108.222 340.222 1108.667 340.667 c +1108.723 340.723 1108.777 341.778 1108.333 341.333 c +f +*U +0.000 0.420 0.369 0.282 k +*u +1191 342 m +1192 341 l +1191 342 l +f +*U +0.000 0.525 0.416 0.475 k +*u +1192 342 m +1197.462 339.708 1205 341 1211 341 c +1252 341 l +1394 341 l +1388.537 343.292 1380.887 342 1375 342 c +1334 342 l +1192 342 l +f +*U +0.000 0.388 0.267 0.031 k +*u +1394.333 341.333 m +1394.278 341.278 1394.222 340.222 1394.667 340.667 c +1394.723 340.723 1394.777 341.777 1394.333 341.333 c +f +*U +0.000 0.000 0.000 0.161 k +*u +1529 342 m +1530 340 l +1531.635 340.545 1531.455 340.365 1532 342 c +1529 342 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1632 342 m +1634.890 340.787 1637.874 341 1641 341 c +1638 342.213 1635 341.998 1632 342 c +f +*U +0.000 0.000 0.000 0.071 k +*u +1640 341 m +1641.769 340.221 1643 340 1645 340 c +1643 341.301 1642.372 341.330 1640 341 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1760 342 m +1762.332 341 1764.457 341 1767 341 c +1764.669 341.984 1762.543 341.981 1760 342 c +f +*U +0.000 0.000 0.000 0.133 k +*u +1896 342 m +1896 326 l +1897.812 330.319 1897.812 337.681 1896 342 c +f +*U +0.000 0.000 0.000 0.149 k +*u +1942 342 m +1940.286 339.376 1938.944 336.987 1938 334 c +1940.574 336.358 1942.298 338.952 1944 342 c +1942 342 l +f +*U +0.000 0.000 0.000 0.325 k +*u +148 341 m +148 328 l +149.591 331.791 149.591 337.209 148 341 c +f +*U +0.000 0.000 0.000 0.745 k +*u +353 341 m +354 340 l +353 341 l +f +*U +0.000 0.000 0.000 0.169 k +*u +355.667 340.667 m +355.222 340.222 356.278 340.278 356.333 340.333 c +356.778 340.778 355.722 340.722 355.667 340.667 c +f +*U +0.000 0.000 0.000 0.067 k +*u +381 341 m +381 256 l +383.395 261.707 382 269.846 382 276 c +382 319 l +382 325.686 383.599 334.806 381 341 c +f +*U +0.000 0.000 0.000 0.125 k +*u +519 341 m +519 256 l +521.395 261.707 520 269.846 520 276 c +520 319 l +520 325.686 521.599 334.806 519 341 c +f +*U +0.000 0.000 0.000 0.996 k +*u +522 340 m +528.915 333.235 527 324 527 315 c +527 256 l +536 256 l +536 294 l +536 300.340 534.952 307.288 538 313 c +537 316.780 538.349 318.645 540 322 c +538 323.277 538.915 323.277 537 322 c +537.284 324.853 537.557 326.603 536 329 c +537.336 330.826 537.690 331.753 538 334 c +537.315 332.752 537.251 332.452 537 331 c +536.660 333 536.677 333.968 537 336 c +536 337 l +531 338 l +532 336 l +528.566 338.505 526.390 340.606 522 340 c +f +*U +0.000 0.000 0.000 0.157 k +*u +536 341 m +537.223 339.805 537.420 339.684 539 339 c +537.777 340.195 537.580 340.316 536 341 c +f +*U +0.000 0.000 0.000 0.769 k +*u +794 341 m +795 340 l +794 341 l +f +*U +0.000 0.000 0.000 0.608 k +*u +878 341 m +879 340 l +878 341 l +f +*U +0.000 0.000 0.000 0.094 k +*u +879 341 m +879.564 339.248 879.919 338.458 881 337 c +880.689 339.291 880.634 339.320 879 341 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1053 336 m +1053.363 333.768 1053.363 332.232 1053 330 c +1112 330 l +1109.601 333.899 1107.435 336.220 1107 341 c +1072 341 l +1063.987 341 1058.563 342 1053 336 c +f +*U +0.000 0.341 0.318 0.008 k +*u +1190 341 m +1191 340 l +1190 341 l +f +*U +0.000 0.875 0.608 0.125 k +*u +1191 341 m +1191 339 l +1286 339 l +1276.597 336.221 1264.782 338 1255 338 c +1192 338 l +1199.639 334.794 1211.729 337 1220 337 c +1283 337 l +1283 333 l +1255.927 329.579 1227.296 332 1200 332 c +1207.400 328.895 1218.993 331 1227 331 c +1287 331 l +1288 338 l +1291.694 337 1295.214 337 1299 337 c +1297.752 337.685 1297.452 337.749 1296 338 c +1305.683 340.862 1317.924 339 1328 339 c +1392 339 l +1386.293 341.395 1378 340 1372 340 c +1331 340 l +1284.362 340 1237.700 341 1191 341 c +f +*U +0.000 0.882 0.635 0.118 k +*u +1296 341 m +1303.879 337.694 1316.466 340 1325 340 c +1392 340 l +1382.317 337 1370 339 1360 339 c +1296 339 l +1299.619 336.322 1300.850 334.591 1301 330 c +1395 330 l +1394.694 333.752 1393.759 337.320 1393 341 c +1296 341 l +f +*U +0.000 0.733 0.533 0.267 k +*u +1393 341 m +1393 338 l +1395 339 l +1394.455 340.635 1394.635 340.455 1393 341 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1425 341 m +1425 253 l +1446 253 l +1440.286 255.398 1432.169 254 1426 254 c +1426 314 l +1426 322 1428 333.601 1425 341 c +f +*U +0.000 0.000 0.000 0.855 k +*u +1426 341 m +1426 254 l +1428.701 260.436 1427 270 1427 277 c +1427 321 l +1427 327 1428.395 335.293 1426 341 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1427 341 m +1427 254 l +1446 254 l +1446 292 l +1459.982 283.441 1473.942 274.834 1488 266.400 c +1494.470 262.518 1501.682 256.505 1509 254.499 c +1517.380 252.203 1528.330 254 1537 254 c +1529.973 261 1518.663 265.461 1510 270.427 c +1493.561 279.852 1477.411 291.497 1460 299 c +1482.270 313.736 1506.223 326 1529 340 c +1525.565 341.441 1521.703 341 1518 341 c +1513.502 341 1508.356 341.663 1504 340.351 c +1496.680 338 1489.450 332 1483 328 c +1470.699 320.335 1458 313 1446 305 c +1446 341 l +1427 341 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1491 335 m +1495.302 333.994 1499.507 337.689 1503 340 c +1498.778 340.616 1494.663 336.949 1491 335 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1503 341 m +1504 340 l +1503 341 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1529 341 m +1530 340 l +1529 341 l +f +*U +0.000 0.000 0.000 0.506 k +*u +1554 341 m +1555 340 l +1554 341 l +f +*U +0.000 0.000 0.000 0.855 k +*u +1555.667 340.667 m +1555.222 340.222 1556.278 340.278 1556.333 340.333 c +1556.778 340.777 1555.722 340.722 1555.667 340.667 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1636 255 m +1630.194 257.303 1622.186 256 1616 256 c +1574 256 l +1563.575 256 1553.913 253.776 1548 264 c +1545 262 l +1543.393 267.482 1544.298 272.443 1543.826 278 c +1542.614 292.285 1543 306.647 1543 321 c +1541.231 316.785 1542 311.536 1542 307 c +1542 280 l +1540.304 284.639 1541 290 1541 295 c +1541 302.647 1539.780 311.446 1541 318.972 c +1541.455 320.915 1542.816 322.241 1543.361 324 c +1544 326.697 1542.720 330.297 1544 332.694 c +1547.265 338.455 1556.648 333.660 1558 340 c +1566.631 335.508 1576.540 336 1586 336 c +1628 336 l +1635.905 336 1643.682 337.177 1651 334 c +1650 330 l +1649 332 l +1647.833 328.992 1647.521 325.261 1650 323 c +1649 325 l +1653 324 l +1644.764 313.519 1650 295.666 1648.830 283 c +1648 275.920 1646.705 268 1651 262 c +1650 261 l +1648.483 261.957 1647.662 262.387 1646 263 c +1643.373 259.674 1641 257.375 1637 256 c +1644.933 252.766 1652.822 259.407 1654.481 267 c +1655.735 272.734 1655 279 1655 285 c +1655 319 l +1654.997 325.661 1654.998 333 1648.956 337.297 c +1642.231 342 1631.781 341 1624 341 c +1569 341 l +1561 341 1550.307 341.777 1544.214 335.775 c +1539.258 330.894 1539 322.545 1539 316 c +1538.933 302 1538.407 287.932 1539 274 c +1539.305 268 1540.919 261.234 1546 257.728 c +1549.735 255.202 1554.704 255 1559 254.425 c +1571.338 252.746 1584.555 254 1597 254 c +1609 254 1624.361 251.560 1636 255 c +f +*U +0.000 0.000 0.000 0.808 k +*u +1638.667 340.667 m +1638.222 340.222 1639.278 340.278 1639.333 340.333 c +1639.778 340.778 1638.722 340.722 1638.667 340.667 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1677 341 m +1677 254 l +1679.395 259.707 1678 267.846 1678 274 c +1678 318 l +1678 324.951 1679.701 334.564 1677 341 c +f +*U +0.000 0.000 0.000 0.851 k +*u +1678 341 m +1678 254 l +1680.395 259.707 1679 267.846 1679 274 c +1679 318 l +1679 324.951 1680.701 334.564 1678 341 c +f +*U +0.000 0.000 0.000 0.996 k +*u +1679 341 m +1679 338 l +1760 338 l +1760 336 l +1680 336 l +1680 256 l +1696 256 l +1696 266 1698 278.211 1696 288 c +1703.463 288.834 1711.460 288 1719 287.999 c +1723.253 287.979 1728.340 288.223 1732 286 c +1733.662 286.613 1734.483 287 1736 288 c +1735.522 286 1735.295 284.504 1734 283 c +1735.636 280.382 1735.730 278.558 1739 279 c +1739.777 277.298 1740.588 275.810 1741 274 c +1742.767 273 1743.608 272.434 1745 271 c +1747.502 271.402 1749.489 271.359 1752 271 c +1751 266.465 1753.520 264.181 1758 264 c +1759 262 1759 261.902 1761 261 c +1761.642 263.842 1763.253 265.681 1765 268 c +1762.460 269.693 1761.684 272.422 1761 269 c +1757 274 l +1752 272 l +1752 273.410 1752.851 279 1752 280 c +1750.303 281.980 1749.186 278.744 1750 282 c +1747.944 281.513 1746.856 281 1745 280 c +1744 281 l +1745.517 281.958 1746.338 282.387 1748 283 c +1746.494 283.683 1745.685 283.826 1744 284 c +1753.243 290.648 1766.731 283.345 1775.786 291.419 c +1778.777 294 1780 298 1780.699 302 c +1782.276 312.675 1783.853 333.465 1771.996 338.521 c +1762.259 342.672 1750.334 341 1740 341 c +1679 341 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1765 341 m +1766 340 l +1765 341 l +f +*U +0.000 0.000 0.000 0.502 k +*u +1766 341 m +1767 340 l +1766 341 l +f +*U +0.000 0.000 0.000 0.200 k +*u +1767 341 m +1769 339.775 1770.658 339.355 1773 339 c +1770.958 340.416 1769.489 340.745 1767 341 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1797 341 m +1797 256 l +1799.395 261.707 1798 269.846 1798 276 c +1798 319 l +1798 325.686 1799.599 334.806 1797 341 c +f +*U +0.000 0.000 0.000 0.851 k +*u +1798 341 m +1798 254 l +1800.395 259.707 1799 267.846 1799 274 c +1799 318 l +1799 324.951 1800.701 334.564 1798 341 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1799 341 m +1799 254 l +1860 254 l +1878 254 l +1880.762 254 1884.206 253.505 1886.815 254.603 c +1891.372 256.523 1894.169 263.750 1896 268 c +1818 268 l +1818 276.954 1816.760 286.543 1820 295 c +1816 296 l +1816 285.911 1813.562 272.892 1819 264 c +1823 264 l +1827.782 267.623 1836.197 266 1842 266 c +1888 266 l +1881 263.970 1873 265 1866 265 c +1824 265 l +1828.720 263 1834.920 264 1840 264 c +1871 264 l +1877.237 264 1885 265.537 1890 261 c +1888 262 l +1887.835 253.173 1874 256 1868 256 c +1800 256 l +1800 336 l +1888 336 l +1888 328 l +1839 328 l +1831.722 328 1823 329.518 1816 328 c +1816.654 320 1816.359 311.882 1816 304 c +1831.677 305.519 1848.224 304 1864 304 c +1864 296 l +1832 296 l +1828 296 1822.666 297.177 1821 293 c +1865 293 l +1865 306 l +1818 306 l +1818 327 l +1896 327 l +1894.855 331.810 1894.855 336.190 1896 341 c +1799 341 l +f +1890 254 m +1894.853 254 1904.246 252.186 1908.366 255 c +1914.572 259.309 1914.958 269.959 1921.379 273.972 c +1925.246 276.389 1932.606 275 1937 275 c +1971 275 l +1977.708 275 1982.871 276 1987 270 c +1992 273 l +1991 278 l +1989.805 276.777 1989.684 276.580 1989 275 c +1987.328 275.338 1987.690 275.537 1987 274 c +1985.868 276.328 1985.484 276.978 1987 279 c +1975.641 282.358 1960.833 280 1949 280 c +1941.869 280 1933.868 281 1927 279 c +1928 277 l +1927 276 l +1923 278 l +1921.517 276 1916.355 277.250 1916 280 c +1911 276 l +1910.961 278.627 1910.839 280.664 1912 283 c +1912.532 287.842 1915.597 288.210 1920 288 c +1919.277 294 1920.394 299 1922 305 c +1923.672 304.662 1923.310 304.463 1924 306 c +1928 304 l +1927.805 306.424 1927.590 308.648 1927 311 c +1928.397 311.662 1928.813 311.964 1930 313 c +1930 311 l +1931.300 311.650 1931 311 1931 313 c +1932.944 312.598 1933 312.598 1935 313 c +1936 311 1936 310.902 1938 310 c +1935.182 306 1934.649 302.227 1929 302 c +1927 287 l +1944.985 287 1963 286.267 1981 288 c +1981 292 l +1982 288 l +1983.195 289.223 1983.316 289.420 1984 291 c +1986.877 288.691 1988.808 287.950 1992 290 c +1992.338 285.727 1993.331 283.397 1996 280 c +1997.797 280 1997.521 280 1999 281 c +1999.648 278.606 2000 277.464 2002 276 c +2000 269 l +2001.801 268.438 2003 268.176 2005 268 c +2003.521 267 2003.797 267 2002 267 c +2004.401 264.987 2005.890 264.657 2009 265 c +2010 262.229 2010.945 259.969 2011 257 c +2009 261 l +2006.749 256 2004.263 255.764 1999 257 c +1999.986 258.479 2000 258.203 2000 260 c +1998.584 259.528 1998.186 259.186 1997 258 c +1995 261.930 1992.625 266.562 1989 269 c +1990 264.302 1993.289 256.564 1998 254.603 c +2003.297 252.489 2011.444 254 2017 254 c +2014.701 260 2010.612 265.493 2007.192 271 c +2000.539 281.715 1993.696 292.313 1987 303 c +1984.198 300.326 1983 296.294 1981 293 c +1979.977 294.534 1980.196 294.402 1979 295 c +1977.701 294.350 1978 294.853 1978 293 c +1976 293 l +1976.175 296.585 1974.198 299.859 1976 303 c +1973.992 303.553 1973.667 303.303 1972 302 c +1970.343 303.664 1969 304.875 1967 306 c +1969.363 299.545 1973.778 294 1977 288 c +1929 288 l +1934 301.975 1945.877 313 1951 327 c +1944 328 l +1944.892 326 1945.402 325.481 1947 324 c +1944 324 l +1945 319 l +1942.622 318.617 1942.644 316.363 1942 314 c +1940.507 314.999 1940.734 314.968 1939 315 c +1937.741 317.498 1936.440 318.632 1934 320 c +1935 322.243 1935.182 322.577 1935 325 c +1936.822 325.990 1936.716 326.867 1937 329 c +1938.479 328 1938.203 328 1940 328 c +1939 330 l +1943 328 l +1943.494 331 1943 332.000 1940 333 c +1947 336.523 1953.786 334.868 1961 337 c +1960.636 335.505 1960.198 327.855 1962 332 c +1964.939 329 1969.397 327.339 1970 323 c +1978 314 l +1977 312.261 1976.308 310.445 1975 309 c +1977.799 307 1980.760 305.927 1984 305 c +1982.851 310.943 1978.871 315.940 1975.681 321 c +1972.297 326.370 1967.910 337.839 1961.816 340.397 c +1958.944 341.602 1955 341 1952 341 c +1949.243 340.999 1945.798 341.467 1943.329 339.972 c +1940.557 338.294 1939 334.672 1937.399 332 c +1927.600 316 l +1919.747 302.917 1911.642 289.953 1903.575 277 c +1898.951 269.576 1893 262.205 1890 254 c +f +*U +0.000 0.000 0.000 0.184 k +*u +266.667 339.667 m +266.222 339.222 267.278 339.278 267.333 339.333 c +267.778 339.778 266.722 339.722 266.667 339.667 c +f +*U +0.000 0.000 0.000 0.773 k +*u +268 340 m +269 339 l +268 340 l +f +*U +0.000 0.000 0.000 0.702 k +*u +356 340 m +357 339 l +356 340 l +f +*U +0.000 0.000 0.000 0.153 k +*u +357.667 339.667 m +357.222 339.222 358.278 339.278 358.333 339.333 c +358.778 339.778 357.722 339.722 357.667 339.667 c +f +*U +0.000 0.000 0.000 0.753 k +*u +709 340 m +710 339 l +709 340 l +f +*U +0.000 0.000 0.000 0.765 k +*u +797 340 m +798 339 l +797 340 l +f +*U +0.000 0.576 0.431 0.424 k +*u +1054 340 m +1054 336 l +1054.710 337.759 1054.710 338.241 1054 340 c +f +*U +0.000 0.408 0.357 0.114 k +*u +1108.333 339.333 m +1108.278 339.278 1108.222 338.222 1108.667 338.667 c +1108.722 338.722 1108.777 339.778 1108.333 339.333 c +f +*U +0.000 0.486 0.412 0.290 k +*u +1190 340 m +1191 339 l +1190 340 l +f +*U +0.000 0.000 0.000 0.075 k +*u +1525 338 m +1527.457 337.484 1528.502 338 1530 340 c +1528 339.453 1526.745 338.890 1525 338 c +f +*U +0.000 0.000 0.000 0.769 k +*u +1550 340 m +1551 339 l +1550 340 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1558 340 m +1554.752 334.808 1547.456 338.432 1544.169 333 c +1542.619 330.512 1543.697 327.184 1542.945 324.421 c +1539 310.450 1541 294.552 1541 280 c +1542.769 284.215 1542 289.465 1542 294 c +1542 321 l +1543.692 315.275 1543 308.940 1543 303 c +1543 294.265 1543.334 285.691 1543.791 277 c +1544 271.522 1542.600 267.230 1545 262 c +1546.396 262.661 1546.814 262.964 1548 264 c +1551.815 254.311 1560 256 1569 256 c +1624 256 l +1632.962 255.986 1640.944 253.814 1646 263 c +1650 261 l +1651 262 l +1647.318 269.250 1648.621 276.236 1648.961 284 c +1649.552 297.500 1646.300 311.964 1653 324 c +1649 325 l +1650 323 l +1648.348 325.719 1648.347 328.823 1648 332 c +1649 330.466 1648.805 330.598 1650 330 c +1651 334 l +1643.507 338.510 1632.561 336 1624 336 c +1602.813 336 1578 332.322 1558 340 c +f +*U +0.000 0.000 0.000 0.671 k +*u +1644 340 m +1645 339 l +1644 340 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1645 340 m +1646.458 338.919 1647.248 338.564 1649 338 c +1647.457 339.267 1646.952 339.489 1645 340 c +f +*U +0.000 0.000 0.000 0.827 k +*u +1769 340 m +1770 339 l +1769 340 l +f +*U +0.000 0.000 0.000 0.863 k +*u +1895 340 m +1895 328 l +1896.512 331.604 1896.512 336.396 1895 340 c +f +*U +0.000 0.000 0.000 0.114 k +*u +261 333 m +262.968 334.868 264.488 336.744 266 339 c +262.718 337.748 261.728 336.425 261 333 c +f +*U +0.000 0.000 0.000 0.725 k +*u +266 339 m +267 338 l +266 339 l +f +*U +0.000 0.000 0.000 0.996 k +*u +277 339 m +275.723 337 275.723 337.915 277 336 c +268.909 337.450 265.627 336.462 262 329 c +264 326 l +262 327 l +266.932 311.864 264 292.764 264 277 c +263 279 l +262 277.623 261.596 276.560 261 275 c +262.797 275 262.522 275 264 276 c +262 271 l +264 272 l +263.185 268.202 263.688 265.626 265 262 c +267.266 263 268.477 263.306 271 263 c +271.644 265 271.906 266.795 272 269 c +272.562 267.199 272.824 265.878 273 264 c +273.924 265.648 274.449 267.175 275 269 c +276.186 267.964 276.604 267.661 278 267 c +277 271 l +273 270 l +273 309 l +273 315.348 271.891 321.745 273 328 c +274.767 327 275.607 326.434 277 325 c +277.683 326.506 277.826 327.315 278 329 c +346 329 l +346.780 322.831 347.460 317 346 311 c +349.786 314.308 348 323.233 348 328 c +348.810 325.271 348.979 322.850 349 320 c +350 322.613 349.993 325 350 328 c +351.607 322.563 351 316.642 351 311 c +353.669 311.430 354.626 310.763 357 310 c +357 312.351 357.652 311.935 360 312 c +360 317.602 359.373 324 362 329 c +357.914 339.779 349.335 336 340 336 c +319.688 335.787 298 338.213 278 336 c +279 339 l +277 339 l +f +*U +0.000 0.000 0.000 0.675 k +*u +358 339 m +359 338 l +358 339 l +f +*U +0.000 0.000 0.000 0.212 k +*u +359 339 m +360 338 l +359 339 l +f +*U +0.000 0.000 0.000 0.682 k +*u +538 339 m +539 338 l +538 339 l +f +*U +0.000 0.000 0.000 0.118 k +*u +539 339 m +540.450 337.392 541 336.936 543 336 c +541.771 337.870 541 338.224 539 339 c +f +*U +0.000 0.000 0.000 0.133 k +*u +704 336 m +705.457 337 705.897 337.543 707 339 c +704.876 338 704.899 338 704 336 c +f +*U +0.000 0.000 0.000 0.733 k +*u +707 339 m +708 338 l +707 339 l +f +*U +0.000 0.000 0.000 0.765 k +*u +799 339 m +800 338 l +799 339 l +f +*U +0.000 0.000 0.000 0.267 k +*u +800 339 m +800.545 337.365 800.365 337.545 802 337 c +801.455 338.635 801.635 338.455 800 339 c +f +*U +0.000 0.000 0.000 0.235 k +*u +854 339 m +855 338 l +854 339 l +f +*U +0.000 0.690 0.631 0.251 k +*u +1107 339 m +1107 336 l +1107.696 337.554 1107.696 337.446 1107 339 c +f +*U +0.000 0.651 0.486 0.349 k +*u +1190 339 m +1190 336 1189.792 333.925 1192 332 c +1191.405 334.396 1191 336.767 1190 339 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1191 339 m +1191 335.922 1191.438 333 1192 330 c +1287 330 l +1279.600 333 1268 331 1260 331 c +1200 331 l +1207 333 1215.573 332 1223 332 c +1242.417 332 1263.893 329.453 1283 333 c +1283 337 l +1192 337 l +1201.403 339.779 1213.218 338 1223 338 c +1286 338 l +1278 341.306 1265.534 339 1257 339 c +1191 339 l +f +*U +0.000 0.580 0.392 0.416 k +*u +1394 339 m +1394 335.389 1395.207 332.211 1392 330 c +1393.506 329.317 1394.315 329.174 1396 329 c +1395.926 332.575 1395.692 335.818 1394 339 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1547 339 m +1548 338 l +1547 339 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1772 339 m +1773 338 l +1772 339 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1773.667 338.667 m +1773.222 338.222 1774.278 338.278 1774.333 338.333 c +1774.778 338.778 1773.722 338.722 1773.667 338.667 c +f +*U +0.000 0.000 0.000 0.651 k +*u +1964 339 m +1965 338 l +1964 339 l +f +*U +0.000 0.000 0.000 0.141 k +*u +1965 339 m +1965.547 337 1966 335.745 1967 334 c +1967.375 336.419 1966.693 337.218 1965 339 c +f +*U +0.000 0.000 0.000 0.220 k +*u +360 338 m +361 337 l +360 338 l +f +*U +0.000 0.000 0.000 0.831 k +*u +800 338 m +801 337 l +800 338 l +f +*U +0.000 0.000 0.000 0.075 k +*u +853 338 m +852 336.521 852 336.797 852 335 c +853.289 336.443 853.401 336.234 853 338 c +f +*U +0.000 0.000 0.000 0.655 k +*u +854 338 m +855 337 l +854 338 l +f +*U +0.000 0.000 0.000 0.071 k +*u +937 338 m +937 256 l +939.292 261.462 938 269 938 275 c +938 317 l +938 323.420 939.497 332 937 338 c +f +*U +0.000 0.259 0.192 0.090 k +*u +1053 338 m +1054 337 l +1053 338 l +f +*U +0.000 0.392 0.220 0.341 k +*u +1108.333 337.333 m +1108.278 337.278 1108.222 336.222 1108.667 336.667 c +1108.723 336.723 1108.777 337.778 1108.333 337.333 c +f +*U +0.000 0.388 0.306 0.286 k +*u +1288 338 m +1289 337 l +1288 338 l +f +*U +0.000 0.427 0.333 0.004 k +*u +1289 338 m +1290 337 l +1289 338 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1431 338 m +1427 330.610 1429 320 1429 312 c +1429 256 l +1440 256 l +1440 267 1441.209 279.000 1440 290 c +1442.979 290.596 1441.733 291.567 1444 291 c +1445 292 l +1444.466 294.670 1445.785 294.443 1443 295 c +1446.375 295.457 1448.391 295.223 1451 293 c +1455 294 l +1453.466 292.978 1453.598 293.195 1453 292 c +1456 291 l +1455 289 l +1458.629 286.899 1463 289 1466 287 c +1468 292 l +1464 290 l +1466 294 l +1463.851 295.236 1456.647 297 1458 300 c +1456.526 302.358 1455.440 306.306 1452 306.500 c +1448.447 306.700 1446.841 301 1443.333 304.167 c +1439.311 307.751 1441.765 309.947 1442 314 c +1442.422 321.278 1442 328.708 1442 336 c +1439.194 329.313 1441 319.233 1441 312 c +1438.801 319.438 1440 328.271 1440 336 c +1436.580 336 1434 336.325 1431 338 c +f +*U +0.000 0.000 0.000 0.584 k +*u +1524 338 m +1525 337 l +1524 338 l +f +*U +0.000 0.000 0.000 0.169 k +*u +1649 338 m +1650.330 336.248 1651.247 335.330 1653 334 c +1651.847 336.249 1651.249 336.847 1649 338 c +f +*U +0.000 0.000 0.000 1.000 k +*u +1679 338 m +1679 254 l +1698 254 l +1698 287 l +1705.526 287 1717 289.170 1724 286 c +1727.728 284.311 1730.884 281 1734 278.414 c +1753 262.750 l +1756.344 259.987 1759.841 256 1764 254.600 c +1771.303 251.994 1782.278 254 1790 254 c +1781 263 1769 269.783 1759 277.373 c +1754.494 280.753 1749.901 285.603 1744 285 c +1745.506 284.317 1746.315 284.174 1748 284 c +1746.400 283 1745.337 282.280 1744 281 c +1745 280 l +1750 282 l +1749.613 279.910 1749.616 280.289 1752 280 c +1752 272 l +1757 274 l +1760 269 l +1761.195 269.598 1760.978 269.466 1762 271 c +1762.901 269 1763 269 1765 268 c +1762.665 265.716 1761.409 264.229 1761 261 c +1758 264 l +1753.965 264.429 1751.657 266.859 1752 271 c +1749.312 271.592 1747.659 271.675 1745 271 c +1743.771 272.870 1743 273.224 1741 274 c +1740.752 276 1740.213 277 1739 279 c +1737 278.622 1736.240 278 1735 281 c +1734.839 281.375 1737 281.377 1734 282 c +1735.333 284 1735.679 285.552 1736 288 c +1732 286 l +1729.777 288.437 1726.208 287.912 1723 287.975 c +1714.614 288 1704 289.749 1696 288 c +1696.876 277.482 1696 266.572 1696 256 c +1680 256 l +1680 336 l +1760 336 l +1760 338 l +1679 338 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1774 338 m +1775 337 l +1774 338 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1775 338 m +1776.755 335.287 1777.833 333.611 1781 333 c +1779.210 335.445 1777.895 337 1775 338 c +f +*U +0.000 0.000 0.000 0.812 k +*u +360 337 m +361 336 l +360 337 l +f +*U +0.000 0.000 0.000 0.224 k +*u +361 337 m +362 336 l +361 337 l +f +*U +0.000 0.000 0.000 0.996 k +*u +479 337 m +479 330 478.884 323 479 316 c +479 313 479.940 309.399 478 307 c +478.598 305.805 478.466 306 480 305 c +461.492 303 442.591 304 424 304 c +418.504 304 408.270 302 404 306 c +401 304 l +400 336 l +384 336 l +384 256 l +400 256 l +400 264.332 399.915 272.669 400 281 c +400 285.375 401.167 289.738 400 294 c +415.345 295 430.608 295 446 295 c +455.295 295 464.832 295.702 474 294 c +473 296 l +474.850 295.798 476 295.798 478 296 c +477.952 293.670 477.797 293.994 480 293 c +479.776 291.316 479.782 290.687 480 289 c +478 290 l +480 278.957 479 267.203 479 256 c +495 256 l +495 336 l +489.600 336 484.282 335.742 479 337 c +f +*U +0.000 0.000 0.000 0.827 k +*u +801 337 m +802 336 l +801 337 l +f +*U +0.000 0.000 0.000 0.227 k +*u +802 337 m +803 336 l +802 337 l +f +*U +0.000 0.000 0.000 0.216 k +*u +881 337 m +882 336 l +881 337 l +f +*U +0.000 0.271 0.196 0.255 k +*u +1053 337 m +1054 336 l +1053 337 l +f +*U +0.043 0.000 0.071 0.396 k +*u +1288 337 m +1289 336 l +1288 337 l +f +*U +0.000 0.451 0.353 0.180 k +*u +1292 337 m +1293 336 l +1292 337 l +f +*U +0.000 0.702 0.553 0.298 k +*u +1293 337 m +1294.248 336.315 1294.548 336.251 1296 336 c +1294.752 336.685 1294.451 336.749 1293 337 c +f +*U +0.000 0.584 0.584 0.416 k +*u +1296 337 m +1297.248 336.315 1297.548 336.251 1299 336 c +1297.752 336.685 1297.452 336.749 1296 337 c +f +*U +0.000 0.635 0.443 0.357 k +*u +1299 337 m +1300 333 l +1300.751 335 1300.656 335.596 1299 337 c +f +*U +0.000 0.106 0.067 0.122 k +*u +1395 337 m +1396 336 l +1395 337 l +f +*U +0.000 0.000 0.000 0.098 k +*u +1521 336 m +1522.809 335.426 1523 335.535 1525 336 c +1523.341 336.406 1522.758 336.309 1521 336 c +f +*U +0.000 0.000 0.000 0.788 k +*u +1544 337 m +1545 336 l +1544 337 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1960 337 m +1953.445 335 1946.674 336 1940 334 c +1942 331.998 1942.903 330.929 1943 328 c +1939 330 l +1940 328 l +1937 329 l +1936.501 327.201 1936.267 326.281 1935 325 c +1934.834 323 1934.555 321.804 1934 320 c +1942 314 l +1944 320 l +1945 319 l +1944 324 l +1945.915 322.723 1945 322.723 1947 324 c +1944 328 l +1946.590 327.435 1950.248 327.898 1952.572 326.601 c +1956 324.606 1958 319.366 1960 316 c +1963.171 310.633 1966.869 306.574 1971 302 c +1976 304 l +1973.470 300.177 1975.978 297.212 1976 293 c +1978 293.501 1979 293.637 1981 293 c +1984.465 297.246 1986.168 301.549 1985 307 c +1981.505 305.871 1978.520 307.387 1975 308 c +1978 313 l +1976 316.927 1973.812 320.679 1970 323 c +1969.776 327.728 1965.586 329.413 1962 332 c +1961.274 329.821 1961.561 330.220 1960 331 c +1960.452 333.241 1960.838 334.884 1960 337 c +f +40 336 m +40 329 l +55 329 74 332.196 88 326 c +87 318.526 88 310.551 88 303 c +88 256 l +103 256 l +103 329 l +144 329 l +144 336 l +40 336 l +f +152 336 m +152 331.354 152.313 327 150 323 c +153.524 318.323 152 309.597 152 304 c +152 256 l +225 256 l +230.330 256 235.670 255.904 240.999 256 c +242.984 256 245.590 255.865 246.972 257.603 c +248.468 259.484 247.992 262.768 248 265 c +199 265 l +188.695 265 178.210 265.561 168 264 c +169.301 274.446 166.876 285.466 168 296 c +169 294.466 168.805 294.598 170 294 c +173.701 296.622 179.518 295.979 184 295.999 c +194.666 296 205.334 296 216 296 c +216 305 l +204.357 305 192.635 304.604 181 305 c +178 305 171 303.824 168.983 305.948 c +167.236 307.701 167.906 310.802 167.965 313 c +168 318.328 168 323.671 168 329 c +247 329 l +247 336 l +152 336 l +f +*U +0.000 0.000 0.000 0.090 k +*u +362 336 m +364.278 327.651 365 320.686 365 312 c +367 312 l +367 319.634 367.930 330.355 362 336 c +f +*U +0.000 0.000 0.000 0.682 k +*u +542 336 m +543 335 l +542 336 l +f +*U +0.000 0.000 0.000 0.996 k +*u +616 336 m +616 299 l +616 291.661 615.447 283.624 619 277 c +623 280 l +622.976 276.554 622 274.713 620 272 c +619 275 l +616 274.700 614.652 274.995 614 272 c +610 282 l +609.315 280.752 609.251 280.452 609 279 c +606.715 280.588 604.754 280.700 602 281 c +603.186 282.186 603.584 282.528 605 283 c +602 285.478 599.167 287.871 596 290 c +594 288 l +593.658 290.602 593.459 291.946 595 294 c +590 296.451 586.648 300.786 582 303.667 c +580.295 304.723 578.583 304.813 577 306 c +576 303 l +574.814 304.186 574.416 304.528 573 305 c +573 301 l +576 301 l +576 296 l +580.731 295.471 583.468 293.995 582 289 c +584 289 583.724 289 584 287 c +591 288 l +591.195 283.869 591.189 280.197 596 280 c +597.222 278.267 598 277.849 600 277 c +600.796 272.450 604 271.911 607 269 c +612 271 l +612 267 l +612.683 268.506 612.826 269.315 613 271 c +616 263 l +619.199 263 620.875 262.386 620 259 c +624.291 257.179 627.247 256 632 256 c +632 336 l +616 336 l +f +*U +0.000 0.000 0.000 0.137 k +*u +657 336 m +657 254 l +662.715 254 676 251.540 680 256 c +675.303 254.882 663.409 252.798 659.603 256.603 c +655.862 260.345 658 272 658 277 c +658 317 l +658 322.887 659.292 330.538 657 336 c +f +*U +0.000 0.000 0.000 0.996 k +*u +664 336 m +664 256 l +673 256 l +673 336 l +664 336 l +f +*U +0.000 0.000 0.000 0.196 k +*u +703 336 m +704 335 l +703 336 l +f +*U +0.000 0.000 0.000 0.114 k +*u +803 336 m +804 332 l +804.751 334 804.656 334.596 803 336 c +f +*U +0.000 0.000 0.000 0.996 k +*u +944 336 m +944 256 l +1011 256 l +1015.400 256 1027.971 253.850 1030.972 257.602 c +1032.312 259.276 1031.976 262 1032 264 c +978 264 l +971 264 961 262.350 955 266 c +952 265 l +953.343 272.365 952 280.485 952 288 c +952 336 l +944 336 l +f +*U +0.000 0.561 0.463 0.318 k +*u +1108 336 m +1108 333 l +1108.696 334.554 1108.696 334.446 1108 336 c +f +*U +0.000 0.302 0.224 0.157 k +*u +1189 336 m +1189 333 l +1189.696 334.554 1189.696 334.446 1189 336 c +f +*U +0.000 0.698 0.537 0.302 k +*u +1287 336 m +1287 330 l +1287.951 332.285 1287.951 333.715 1287 336 c +f +*U +0.000 0.118 0.063 0.176 k +*u +1288 336 m +1288 329 l +1289 331.534 1289 333.466 1288 336 c +f +*U +0.000 0.431 0.310 0.090 k +*u +1395 336 m +1396 335 l +1395 336 l +f +*U +0.000 0.000 0.000 0.761 k +*u +1495 336 m +1496 335 l +1495 336 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1543 336 m +1544 335 l +1543 336 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1800 336 m +1800 256 l +1868 256 l +1874.243 256 1888.339 252.975 1888 262 c +1890 261 l +1886.645 265.749 1878.243 264 1873 264 c +1824 264 l +1830.868 266 1838.869 265 1846 265 c +1888 265 l +1883.280 266.981 1877 266 1872 266 c +1839 266 l +1834.423 266 1826.197 267.658 1823 264 c +1821 264.402 1820.943 264.402 1819 264 c +1814.610 274.280 1816.439 285 1816 296 c +1821 293 l +1822 296 l +1835.586 294.506 1850.274 296 1864 296 c +1864 304 l +1853 304 1842.000 303.951 1831 304 c +1825.937 304 1820.979 305 1816 304 c +1816.761 311.353 1817.516 320.795 1816 328 c +1823.794 328.871 1832 328 1840 328 c +1888 328 l +1888 336 l +1800 336 l +f +*U +0.000 0.000 0.000 0.710 k +*u +262 335 m +263 334 l +262 335 l +f +*U +0.000 0.000 0.000 0.149 k +*u +544 335 m +545.223 333.805 545.420 333.684 547 333 c +545.777 334.195 545.580 334.316 544 335 c +f +*U +0.000 0.000 0.000 0.200 k +*u +702.333 334.333 m +702.278 334.278 702.222 333.222 702.667 333.667 c +702.722 333.722 702.778 334.778 702.333 334.333 c +f +*U +0.000 0.000 0.000 0.733 k +*u +703 335 m +704 334 l +703 335 l +f +*U +0.000 0.000 0.000 1.000 k +*u +802 335 m +799.654 327.528 800 319.764 800 312 c +797.558 311.891 795.377 311.572 793 311 c +791.660 316.627 791.872 322.254 792 328 c +791.315 326.752 791.251 326.451 791 325 c +786.553 330.882 777.644 329 771 329 c +719 329 l +719 307.660 718.430 286.235 720 265 c +721.314 265.768 721.232 265.686 722 267 c +724 264 l +731.213 265.221 739.599 264 747 264 c +761.998 264 777 264.185 792 264 c +791.510 272.494 791.417 281.523 792 290 c +786 291 l +786 269 l +740 269 l +735.281 269 726.390 267.311 722.318 270 c +718.716 272.431 720 279.309 720 283 c +720 315 l +720 318.565 719 324.610 722.434 326.972 c +726.403 329.704 735.362 328 740 328 c +786 328 l +786 309 l +790.704 309.371 800.650 308.986 804.397 312 c +806.351 313.608 805.985 316.769 805.999 319 c +806 324.758 806 330.621 802 335 c +f +*U +0.000 0.635 0.451 0.365 k +*u +1053 335 m +1053 331 l +1053.710 332.759 1053.710 333.241 1053 335 c +f +*U +0.000 0.000 0.000 0.675 k +*u +1519 335 m +1520 334 l +1519 335 l +f +*U +0.000 0.000 0.000 0.255 k +*u +1520 335 m +1521 334 l +1520 335 l +f +*U +0.000 0.000 0.000 0.133 k +*u +849 334 m +849 330 l +850.434 331.393 851 332.233 852 334 c +849 334 l +f +*U +0.000 0.424 0.325 0.098 k +*u +1109 334 m +1110 333 l +1109 334 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1517 334 m +1518 333 l +1517 334 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1653 334 m +1656.654 318 1656 302.349 1656 286 c +1656 278.680 1656.716 269.601 1652.911 263 c +1649.440 256.988 1642.787 257.507 1639 253 c +1644.525 253.748 1649.893 255.313 1653.347 260 c +1657 265 1656.998 272 1657 278 c +1657 309 l +1657 317 1658.856 327.485 1653 334 c +f +*U +0.000 0.000 0.000 0.180 k +*u +1937.333 333.333 m +1937.278 333.278 1937.222 332.222 1937.667 332.667 c +1937.722 332.722 1937.778 333.778 1937.333 333.333 c +f +*U +0.000 0.000 0.000 0.686 k +*u +1938 334 m +1939 333 l +1938 334 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1968 334 m +1968.899 331.876 1968.876 331.899 1971 331 c +1969.896 332.457 1969.457 332.897 1968 334 c +f +*U +0.000 0.000 0.000 0.129 k +*u +260 333 m +257.599 323.720 258 314.513 258 305 c +258 292.256 257.999 279.680 259 267 c +260.908 271.636 259 277 259 282 c +258.781 292.964 258.746 304 259 315 c +259 320.683 261.674 327.556 260 333 c +f +*U +0.000 0.000 0.000 0.710 k +*u +261 333 m +262 332 l +261 333 l +f +*U +0.000 0.000 0.000 0.600 k +*u +546 333 m +547 332 l +546 333 l +f +*U +0.000 0.000 0.000 0.110 k +*u +547 333 m +550.358 328.622 554.915 325 560 323 c +556.600 327.482 552.218 330.882 547 333 c +f +*U +0.000 0.000 0.000 0.118 k +*u +701 333 m +698 319 699 305 699 291 c +699 282 698 272.632 701 264 c +702.590 269.170 700.275 275.621 700 281 c +699.560 291.942 699.887 303 700 314 c +700 319.906 702.716 327.418 701 333 c +f +*U +0.000 0.000 0.000 0.671 k +*u +702 333 m +703 332 l +702 333 l +f +*U +0.000 0.000 0.000 0.114 k +*u +884 333 m +884.684 331.420 884.805 331.223 886 330 c +885.316 331.580 885.195 331.777 884 333 c +f +*U +0.000 0.243 0.180 0.259 k +*u +1052 333 m +1052 330 l +1052.696 331.554 1052.696 331.446 1052 333 c +f +*U +0.000 0.157 0.165 0.176 k +*u +1111 333 m +1112 332 l +1111 333 l +f +*U +0.000 0.506 0.392 0.494 k +*u +1300 333 m +1300 329 l +1304 329 l +1300 333 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1487 331 m +1488.580 331.683 1488.777 331.805 1490 333 c +1488.419 332.316 1488.223 332.196 1487 331 c +f +*U +0.000 0.000 0.000 0.718 k +*u +1490 333 m +1491 332 l +1490 333 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1513 331 m +1515.509 330.434 1516.220 331 1518 333 c +1516 332.453 1514.745 331.890 1513 331 c +f +1540 333 m +1538 326 l +1540.353 327.901 1540.877 330 1540 333 c +f +*U +0.000 0.000 0.000 0.765 k +*u +1541 333 m +1542 332 l +1541 333 l +f +*U +0.000 0.000 0.000 0.141 k +*u +805 332 m +806 324 l +807.232 327 806.825 329.328 805 332 c +f +*U +0.000 0.435 0.435 0.565 k +*u +1111 332 m +1112 331 l +1111 332 l +f +*U +0.000 0.184 0.137 0.361 k +*u +1112 332 m +1113 331 l +1112 332 l +f +*U +0.000 0.263 0.329 0.384 k +*u +1191 332 m +1192 331 l +1191 332 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1779 332 m +1780 331 l +1779 332 l +f +*U +0.000 0.000 0.000 0.196 k +*u +1780.333 331.333 m +1780.278 331.278 1780.222 330.222 1780.667 330.667 c +1780.722 330.723 1780.777 331.778 1780.333 331.333 c +f +*U +0.000 0.549 0.490 0.451 k +*u +1105 330 m +1107.890 328.787 1110.874 329 1114 329 c +1111.184 330.629 1108.238 330 1105 330 c +f +*U +0.000 0.392 0.294 0.184 k +*u +1113 331 m +1114 330 l +1113 331 l +f +*U +0.000 0.220 0.153 0.102 k +*u +1396 331 m +1397 330 l +1396 331 l +f +*U +0.000 0.000 0.000 0.157 k +*u +1483 330 m +1484.809 329.426 1485 329.535 1487 330 c +1485.341 330.406 1484.758 330.309 1483 330 c +f +*U +0.000 0.000 0.000 0.753 k +*u +1512 331 m +1513 330 l +1512 331 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1969 331 m +1970 330 l +1969 331 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1970.333 330.333 m +1970.278 330.278 1970.222 329.222 1970.667 329.667 c +1970.722 329.722 1970.778 330.778 1970.333 330.333 c +f +*U +0.000 0.000 0.000 0.596 k +*u +260 330 m +261 329 l +260 330 l +f +*U +0.000 0.000 0.000 0.616 k +*u +701 330 m +702 329 l +701 330 l +f +*U +0.000 0.000 0.000 0.714 k +*u +849 330 m +850 329 l +849 330 l +f +*U +0.000 0.000 0.000 0.761 k +*u +885 330 m +886 329 l +885 330 l +f +*U +0.000 0.000 0.000 0.102 k +*u +886 330 m +886.944 327 888.286 324.624 890 322 c +890.962 325.672 888.789 327.790 886 330 c +f +*U +0.000 0.584 0.482 0.416 k +*u +1052 330 m +1053.506 329.317 1054.315 329.174 1056 329 c +1054.494 329.683 1053.685 329.826 1052 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1056 330 m +1060.720 328 1066.920 329 1072 329 c +1105 329 l +1100.280 330.981 1094 330 1089 330 c +1056 330 l +f +*U +0.000 0.169 0.149 0.224 k +*u +1114 330 m +1115 329 l +1114 330 l +f +*U +0.000 0.404 0.278 0.247 k +*u +1193 330 m +1194 329 l +1193 330 l +f +*U +0.000 0.541 0.431 0.459 k +*u +1194 330 m +1195.769 329.221 1197 329 1199 329 c +1197.231 329.779 1195.964 329.912 1194 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1199 330 m +1205.919 327 1216.520 329 1224 329 c +1280 329 l +1273 331.903 1262.480 330 1255 330 c +1199 330 l +f +*U +0.000 0.522 0.400 0.478 k +*u +1280 330 m +1282.613 328.902 1285 329 1288 329 c +1285.387 330 1282.835 329.993 1280 330 c +f +*U +0.000 0.694 0.561 0.306 k +*u +1304 330 m +1311.399 326.895 1322.993 329 1331 329 c +1392 329 l +1384.600 332 1373 330 1365 330 c +1304 330 l +f +*U +0.000 0.216 0.141 0.404 k +*u +1396 330 m +1397 329 l +1396 330 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1508 328 m +1510 327.590 1510.963 328 1513 329 c +1510.860 329.410 1510 328.968 1508 328 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1780 330 m +1780 328 l +1782 328 l +1782 330 l +1780 330 l +f +*U +0.000 0.000 0.000 0.231 k +*u +1935 330 m +1936 329 l +1935 330 l +f +*U +0.000 0.000 0.000 0.655 k +*u +364 329 m +365 328 l +364 329 l +f +*U +0.000 0.000 0.000 0.808 k +*u +551 329 m +552 328 l +551 329 l +f +*U +0.000 0.000 0.000 0.612 k +*u +805 329 m +806 328 l +805 329 l +f +*U +0.000 0.000 0.000 0.000 k +*u +866.667 328.667 m +866.222 328.222 867.278 328.278 867.333 328.333 c +867.778 328.778 866.722 328.722 866.667 328.667 c +f +*U +0.000 0.169 0.114 0.063 k +*u +1195 329 m +1196 328 l +1195 329 l +f +*U +0.000 0.000 0.000 1.000 k +*u +1558 327 m +1555.663 327.519 1554.360 327.480 1552 327 c +1558.248 321 1557 315 1557 307 c +1557 272 l +1555.308 277.725 1556 284 1556 290 c +1556 320 l +1554 315.531 1555 309.809 1555 305 c +1555 294 1552.890 280.522 1556 270 c +1552.911 274 1554 280 1554 285 c +1554 321 l +1552.231 316.785 1553 311.536 1553 307 c +1553 280 l +1552.994 276 1550.995 269.732 1554 267 c +1552.964 265.814 1552.661 265.396 1552 264 c +1555 264.614 1554.395 263.395 1557 266 c +1557 264 l +1562 268.917 1571.341 267 1578 267 c +1633 267 l +1631.723 265 1631.723 265.915 1633 264 c +1634 265 1634.308 265.611 1635 267 c +1636.757 265.267 1637.642 264.659 1640 264 c +1639.402 265.195 1639.534 264.978 1638 266 c +1641.511 269.368 1640 277.401 1640 282 c +1640 311 l +1640.000 315 1638.806 320.206 1640 324 c +1639 328 l +1619 327.290 1597.519 328 1577 328 c +1572.735 328 1568.242 327.588 1564 328 c +1561 328.277 1559.227 330 1558 327 c +f +*U +0.000 0.000 0.000 0.820 k +*u +1654 329 m +1655 328 l +1654 329 l +f +*U +0.000 0.000 0.000 0.243 k +*u +1934 329 m +1935 328 l +1934 329 l +f +*U +0.000 0.000 0.000 0.737 k +*u +1935 329 m +1936 328 l +1935 329 l +f +*U +0.000 0.000 0.000 0.188 k +*u +1971 329 m +1972 328 l +1971 329 l +f +*U +0.000 0.000 0.000 0.000 k +*u +104 328 m +108.215 326.231 113.464 327 118 327 c +147 327 l +142.785 328.769 137.536 328 133 328 c +104 328 l +f +*U +0.000 0.000 0.000 0.133 k +*u +104 327 m +104 255 l +99.198 255 88.240 252.966 84.603 256.603 c +81 260 83 270.410 83 275 c +83 327 l +40 327 l +44.215 325.231 49.464 326 54 326 c +82 326 l +82 254 l +105 254 l +105 326 l +147 326 l +147 254 l +250 254 l +250 270 l +248 265.529 249 259.817 249 255 c +175 255 l +169 255 162.999 254.959 157 255 c +154.582 255 151.474 254.732 149.603 256.603 c +146 260 148 270.410 148 275 c +148 292.208 145.855 311 149 328 c +134.538 325.315 118.684 327 104 327 c +f +*U +0.000 0.000 0.000 0.867 k +*u +279 328 m +279 270 l +280.981 274.720 280 280.920 280 286 c +280 314 l +280 318.536 280.769 323.785 279 328 c +f +*U +0.000 0.000 0.000 0.000 k +*u +280 328 m +285.951 325.503 294.580 327 301 327 c +345 327 l +339 329.497 330.420 328 324 328 c +280 328 l +f +721 328 m +726.951 325.503 735.580 327 742 327 c +786 327 l +780 329.497 771.420 328 765 328 c +721 328 l +f +*U +0.000 0.000 0.000 0.082 k +*u +846 328 m +844.296 325 842.939 322.260 842 319 c +844.821 321.605 846.482 324.483 848 328 c +846 328 l +f +*U +0.000 0.000 0.000 0.102 k +*u +865 325 m +866.457 326 866.897 326.543 868 328 c +865.876 327 865.899 327 865 325 c +f +*U +0.000 0.000 0.000 0.125 k +*u +1472 321 m +1482 327 l +1477.705 327.702 1473.987 324.621 1472 321 c +f +*U +0.000 0.000 0.000 0.702 k +*u +1482 328 m +1483 327 l +1482 328 l +f +*U +0.000 0.000 0.000 0.765 k +*u +1507 328 m +1508 327 l +1507 328 l +f +*U +0.000 0.000 0.000 0.890 k +*u +1780.333 327.333 m +1780.278 327.278 1780.222 326.222 1780.667 326.667 c +1780.722 326.723 1780.777 327.778 1780.333 327.333 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1781 328 m +1781 300 l +1783.604 306.207 1783.604 321.793 1781 328 c +f +*U +0.000 0.000 0.000 0.098 k +*u +1952 328 m +1952.684 326.420 1952.805 326.223 1954 325 c +1953.316 326.580 1953.195 326.777 1952 328 c +f +*U +0.000 0.000 0.000 0.686 k +*u +1971 328 m +1972 327 l +1971 328 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1972 328 m +1973.508 323.269 1976.410 319.216 1979 315 c +1980.187 319.889 1975.422 324.898 1972 328 c +f +*U +0.000 0.000 0.000 0.141 k +*u +280 327 m +280 272 l +282.189 277.217 281 284.381 281 290 c +281 326 l +344 326 l +338.293 328.395 330 327 324 327 c +280 327 l +f +*U +0.000 0.000 0.000 0.106 k +*u +344 327 m +342.423 321.665 341 310.732 346 307 c +344.820 313.355 346.459 321 344 327 c +f +*U +0.000 0.000 0.000 0.153 k +*u +721 327 m +721 270 l +786 270 l +780.293 272.395 772 271 766 271 c +722 271 l +722 326 l +784 326 l +784 319.757 783.222 313 785 307 c +787.709 307.648 790.216 307.942 793 308 c +791 308.871 788.187 308.991 786.603 310.603 c +783.338 313.925 785 322.689 785 327 c +721 327 l +f +*U +0.000 0.000 0.000 0.075 k +*u +785 327 m +785 310 l +786.883 314.486 786.883 322.514 785 327 c +f +*U +0.000 0.000 0.000 0.592 k +*u +847 327 m +848 326 l +847 327 l +f +*U +0.000 0.000 0.000 0.000 k +*u +867 327 m +863.441 323.609 861.755 319.216 858 316 c +857.516 312.696 856.536 311 854 309 c +852.926 302.808 847.781 296.667 845 291 c +889 291 l +886.655 296.373 883 300.984 880 305.996 c +875.946 312.991 872.250 320.731 867 327 c +f +*U +0.000 0.000 0.000 0.161 k +*u +868.333 326.333 m +868.278 326.278 868.222 325.222 868.667 325.667 c +868.722 325.722 868.778 326.778 868.333 326.333 c +f +*U +0.000 0.000 0.000 0.129 k +*u +1506.667 326.667 m +1506.222 326.222 1507.278 326.278 1507.333 326.333 c +1507.778 326.778 1506.722 326.722 1506.667 326.667 c +f +*U +0.000 0.000 0.000 0.012 k +*u +1559 325 m +1567.923 327 1577.866 326 1587 326 c +1636 326 l +1630.537 328.292 1622.887 327 1617 327 c +1577 327 l +1572 327 1562.407 328.899 1559 325 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1698 327 m +1703.217 324.811 1710.381 326 1716 326 c +1755 326 l +1749.783 328.189 1742.619 327 1737 327 c +1698 327 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1755 327 m +1756.717 325 1757.566 324.651 1760 324 c +1758.314 325.656 1757.254 326.251 1755 327 c +f +*U +0.000 0.000 0.000 0.761 k +*u +1757 327 m +1758 326 l +1757 327 l +f +*U +0.000 0.000 0.000 0.075 k +*u +1818 327 m +1818 320.654 1817.522 314.208 1819 308 c +1821 312.974 1820 319.638 1820 325 c +1897 325 l +1891.726 328.996 1881.423 327 1875 327 c +1818 327 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1951 327 m +1952 326 l +1951 327 l +f +*U +0.000 0.000 0.000 0.071 k +*u +148 326 m +148 256 l +150 260.969 149 267.650 149 273 c +149 307 l +149 312.887 150.292 320.538 148 326 c +f +*U +0.000 0.000 0.000 0.820 k +*u +555 326 m +556 325 l +555 326 l +f +*U +0.000 0.000 0.000 0.859 k +*u +720 326 m +720 270 l +721.769 274.215 721 279.465 721 284 c +721 311 l +721 315.809 721.875 321.531 720 326 c +f +*U +0.000 0.000 0.000 0.671 k +*u +864 326 m +865 325 l +864 326 l +f +*U +0.000 0.000 0.000 0.639 k +*u +869 326 m +870 325 l +869 326 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1503 324 m +1504.580 324.683 1504.777 324.805 1506 326 c +1504.420 325.316 1504.223 325.195 1503 324 c +f +*U +0.000 0.000 0.000 0.161 k +*u +1538 326 m +1538 268 l +1539.981 272.720 1539 278.920 1539 284 c +1539 312 l +1539 316.536 1539.769 321.785 1538 326 c +f +*U +0.000 0.000 0.000 0.600 k +*u +1539 326 m +1540 325 l +1539 326 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1559 269 m +1636 269 l +1636 326 l +1579 326 l +1574.766 326 1562.918 328 1560 324.397 c +1557.456 321 1559 312.929 1559 309 c +1559 269 l +f +*U +0.000 0.000 0.000 0.067 k +*u +1698 326 m +1698 302 l +1700.633 308.274 1699.858 319 1700 326 c +1698 326 l +f +*U +0.000 0.000 0.000 0.000 k +*u +1700 326 m +1700 302 l +1719 302 1740.201 299.510 1759 303 c +1759 308 1761.253 320.332 1757.397 324 c +1754 327.425 1746.315 326 1742 326 c +1700 326 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1932 326 m +1929 321.997 1926.230 317.784 1925 313 c +1928.309 316 1932.684 321.314 1932 326 c +f +*U +0.000 0.000 0.000 0.576 k +*u +1933 326 m +1934 325 l +1933 326 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1951 326 m +1949.286 323.376 1947.944 320.987 1947 318 c +1949.464 320.284 1951.502 322.551 1951 326 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1952 326 m +1950.218 322.226 1947.742 319.243 1948 315 c +1940 310.991 1935 297.600 1931 290 c +1945.210 290 1959.845 291 1974 290 c +1970.750 297.805 1965.749 304.792 1961.370 312 c +1958.365 316.945 1956.264 321.945 1952 326 c +f +*U +0.000 0.000 0.000 0.627 k +*u +1954 326 m +1955 325 l +1954 326 l +f +*U +0.000 0.000 0.000 0.141 k +*u +869 325 m +869.944 322 871.286 319.624 873 317 c +873.502 320.449 871.464 322.716 869 325 c +f +*U +0.000 0.000 0.000 0.639 k +*u +1477 325 m +1478 324 l +1477 325 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1502 325 m +1503 324 l +1502 325 l +f +*U +0.000 0.000 0.000 0.882 k +*u +1539.333 324.333 m +1539.278 324.278 1539.222 323.222 1539.667 323.667 c +1539.723 323.723 1539.777 324.778 1539.333 324.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1560 325 m +1560 270 l +1635 270 l +1635 309 l +1635 312.731 1636.423 320.302 1633.972 323.397 c +1631 327 1619.234 325 1615 325 c +1560 325 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1954 325 m +1954.547 323 1955 321.744 1956 320 c +1956.375 322.419 1955.693 323.218 1954 325 c +f +*U +0.000 0.000 0.000 0.000 k +*u +700.333 323.333 m +700.277 323.278 700.222 322.222 700.667 322.667 c +700.722 322.722 700.778 323.778 700.333 323.333 c +f +*U +0.000 0.000 0.000 0.090 k +*u +806 324 m +806 311 l +808.794 314.688 808 319.519 808 324 c +806 324 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1496 321 m +1498.837 320.325 1500.522 321.495 1503 323 c +1500.311 323.405 1498.444 322.225 1496 321 c +f +*U +0.000 0.000 0.000 0.651 k +*u +1655.333 323.333 m +1655.278 323.278 1655.222 322.222 1655.667 322.667 c +1655.722 322.722 1655.777 323.778 1655.333 323.333 c +f +*U +0.000 0.000 0.000 0.157 k +*u +1759 324 m +1759 303 l +1761.351 307.369 1761.449 319.711 1759 324 c +f +*U +0.000 0.000 0.000 0.780 k +*u +1949 324 m +1950 323 l +1949 324 l +f +*U +0.000 0.000 0.000 0.757 k +*u +559 323 m +560 322 l +559 323 l +f +*U +0.000 0.000 0.000 0.090 k +*u +560 323 m +562.319 320 564.622 318.432 568 317 c +565.709 320 563.641 321.761 560 323 c +f +*U +0.000 0.000 0.000 0.831 k +*u +871 323 m +872 322 l +871 323 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1474 323 m +1475 322 l +1474 323 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1760 323 m +1761 322 l +1760 323 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1956 323 m +1957 322 l +1956 323 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1974 323 m +1975 322 l +1974 323 l +f +*U +0.000 0.000 0.000 0.824 k +*u +560 322 m +561 321 l +560 322 l +f +*U +0.000 0.000 0.000 0.749 k +*u +844 322 m +845 321 l +844 322 l +f +*U +0.000 0.000 0.000 0.122 k +*u +862 322 m +861 320.255 860.547 318.875 860 317 c +861.693 318.782 862.375 319.581 862 322 c +f +*U +0.000 0.000 0.000 0.827 k +*u +890 322 m +891 321 l +890 322 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1471 322 m +1472 321 l +1471 322 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1497 322 m +1498 321 l +1497 322 l +f +*U +0.000 0.000 0.000 0.871 k +*u +1655 322 m +1655 274 l +1656.552 277.699 1656 282 1656 286 c +1656 309 l +1656 313.260 1656.661 318 1655 322 c +f +*U +0.000 0.000 0.000 0.616 k +*u +259 321 m +259 276 l +260.661 279.959 260 284.740 260 289 c +260 310 l +260 313.702 260.441 317.565 259 321 c +f +*U +0.000 0.000 0.000 0.635 k +*u +700 321 m +700 276 l +701.661 279.959 701 284.740 701 289 c +701 310 l +701 313.702 701.441 317.565 700 321 c +f +*U +0.000 0.000 0.000 0.996 k +*u +879 319 m +879.508 316.408 879.508 314.593 879 312 c +883 310 l +883.986 311.479 884 311.203 884 313 c +885.493 312 885.266 312 887 312 c +886.423 309.289 886.232 308.605 889 308 c +887.522 307 887.797 307 886 307 c +887.791 304 888.463 290.190 895 296 c +896 290 l +890.818 288.394 885.381 289 880 289 c +853 289 l +847.537 289 840.729 287.777 841 295 c +839.521 295.986 839.797 296 838 296 c +838.986 297.479 839 297.203 839 299 c +834 302 l +832.781 298.586 832.532 293.624 830.647 290.607 c +827.879 286.179 821.909 286.980 823 280 c +817 279 l +817.194 276.894 817.417 275 818 273 c +816.203 273 816.479 272.986 815 272 c +815.224 269.625 815.214 267.376 815 265 c +813 268 l +809.974 264.391 807.832 260.662 807 256 c +817 256 l +816 261 l +818.172 261.464 819.958 262 822 263 c +821 261 l +823.979 261.596 822.733 262.567 825 262 c +825.613 263.661 826 264.483 827 266 c +825.550 267.608 824.949 268 823 269 c +826 271 l +826 269.203 826 269.479 827 268 c +830.854 272 832.458 276 838 278.532 c +842.983 280.687 848.690 280 854 280 c +882 280 l +887.552 280 893 280.668 898 278 c +899.804 278.555 901 278.834 903 279 c +901 276 l +904 275 l +903 272 l +907.215 271.394 911.430 271.215 911 266 c +910 268 l +908.235 265.304 908.957 263.863 912 263 c +910.624 253 923 255.829 929 258 c +926.540 260.196 924.463 262 923 265 c +921.919 263.542 921.564 262.752 921 261 c +920.862 263.667 921 264 923 266 c +922.434 267.773 922 269 922 271 c +919 274 l +916 273 l +918 277 l +914.586 280.751 911 284.951 910 290 c +905.168 290 904.463 292.500 905 297 c +903.203 297 903.479 296.986 902 296 c +901 299 l +899.177 298.255 897.977 298 896 298 c +898 301 l +895.658 301.781 895.980 301.654 898 303 c +897.455 304.635 897.635 304.455 896 305 c +897.550 308 896.183 309.916 895 313 c +892.440 312.887 890.456 313.265 888 314 c +888.496 316.556 888.442 318.429 888 321 c +884.864 320.580 881.976 320 879 319 c +f +*U +0.000 0.000 0.000 0.157 k +*u +892.333 320.333 m +892.278 320.278 892.222 319.222 892.667 319.667 c +892.722 319.722 892.778 320.778 892.333 320.333 c +f +1464 318 m +1466.690 317.595 1468.556 318.775 1471 320 c +1468 320.675 1466.478 319.505 1464 318 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1760 321 m +1760 307 l +1761.667 310.972 1761.667 317 1760 321 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1930 321 m +1931 320 l +1930 321 l +f +*U +0.000 0.000 0.000 0.659 k +*u +1957 321 m +1958 320 l +1957 321 l +f +*U +0.000 0.000 0.000 0.027 k +*u +539 320 m +539 317 l +539.696 318.554 539.696 318.446 539 320 c +f +*U +0.000 0.000 0.000 0.765 k +*u +563 320 m +564 319 l +563 320 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1469 320 m +1470 319 l +1469 320 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1699 320 m +1699 313.654 1699.478 307.208 1698 301 c +1701 301 l +1699.540 307 1701.403 314.274 1699 320 c +f +*U +0.000 0.000 0.000 0.647 k +*u +1976 320 m +1977 319 l +1976 320 l +f +*U +0.000 0.000 0.000 0.761 k +*u +540 319 m +541 318 l +540 319 l +f +*U +0.000 0.000 0.000 0.125 k +*u +841 319 m +840 317.255 839.547 315.875 839 314 c +840.693 315.782 841.375 316.581 841 319 c +f +*U +0.000 0.000 0.000 0.745 k +*u +842 319 m +843 318 l +842 319 l +f +*U +0.000 0.000 0.000 0.725 k +*u +892 319 m +893 318 l +892 319 l +f +*U +0.000 0.000 0.000 0.094 k +*u +893 319 m +893.684 317.420 893.805 317.223 895 316 c +894.316 317.580 894.195 317.777 893 319 c +f +*U +0.000 0.118 0.239 0.184 k +*u +1051 319 m +1052 318 l +1051 319 l +f +*U +0.000 0.216 0.047 0.082 k +*u +1052 319 m +1053 318 l +1052 319 l +f +*U +0.000 0.129 0.059 0.169 k +*u +1109 319 m +1110.506 318.317 1111.315 318.174 1113 318 c +1111.494 318.683 1110.685 318.826 1109 319 c +f +*U +0.000 0.169 0.122 0.137 k +*u +1126 319 m +1127.769 318.221 1129 318 1131 318 c +1129.231 318.779 1127.964 318.912 1126 319 c +f +*U +0.000 0.176 0.106 0.153 k +*u +1202 319 m +1203.249 318.315 1203.548 318.251 1205 318 c +1203.752 318.685 1203.451 318.749 1202 319 c +f +*U +0.000 0.251 0.184 0.110 k +*u +1281.667 318.667 m +1281.222 318.222 1282.278 318.278 1282.333 318.333 c +1282.778 318.778 1281.722 318.722 1281.667 318.667 c +f +*U +0.000 0.075 0.059 0.153 k +*u +1297.667 318.667 m +1297.222 318.222 1298.278 318.278 1298.333 318.333 c +1298.778 318.778 1297.722 318.722 1297.667 318.667 c +f +*U +0.000 0.098 0.078 0.227 k +*u +1396.667 318.667 m +1396.222 318.222 1397.278 318.278 1397.333 318.333 c +1397.778 318.778 1396.722 318.722 1396.667 318.667 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1492 319 m +1493 318 l +1492 319 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1946 319 m +1947 318 l +1946 319 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1958.333 318.333 m +1958.278 318.278 1958.222 317.222 1958.667 317.667 c +1958.723 317.723 1958.777 318.777 1958.333 318.333 c +f +540 318 m +540 255 l +542.395 260.707 541 268.846 541 275 c +541 316 l +543 314.242 544.581 313 547 312 c +544.951 314.832 543 316.520 540 318 c +f +*U +0.000 0.000 0.000 0.765 k +*u +859 318 m +860 317 l +859 318 l +f +*U +0.000 0.000 0.000 0.675 k +*u +874 318 m +875 317 l +874 318 l +f +*U +0.000 0.388 0.294 0.078 k +*u +1050 318 m +1050 315 l +1050.696 316.554 1050.696 316.446 1050 318 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1051 318 m +1056.707 315.605 1064.846 317 1071 317 c +1112 317 l +1106.293 319.395 1098 318 1092 318 c +1051 318 l +f +*U +0.000 0.235 0.204 0.765 k +*u +1112 318 m +1113 317 l +1112 318 l +f +*U +0.000 0.643 0.482 0.357 k +*u +1120 314 m +1124.336 312.848 1128 316.766 1133 316 c +1128.217 319.622 1124.585 316.330 1120 314 c +f +*U +0.000 0.263 0.180 0.149 k +*u +1132 318 m +1133 317 l +1132 318 l +f +*U +0.000 0.314 0.196 0.310 k +*u +1202 318 m +1203 317 l +1202 318 l +f +*U +0.000 0.580 0.467 0.420 k +*u +1203.667 317.667 m +1203.222 317.222 1204.278 317.278 1204.333 317.333 c +1204.778 317.778 1203.722 317.722 1203.667 317.667 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1204 317 m +1205.623 314.565 1208.716 314.819 1206 316 c +1213.999 318.364 1223.688 317 1232 317 c +1282 317 l +1281 312 l +1282.580 311.317 1282.777 311.195 1284 310 c +1284.985 312.806 1283.633 315 1283 318 c +1231 318 l +1222.393 318 1212.280 319.447 1204 317 c +f +*U +0.000 0.208 0.153 0.102 k +*u +1283 318 m +1283 315 l +1283.696 316.554 1283.696 316.446 1283 318 c +f +*U +0.000 0.878 0.627 0.122 k +*u +1296 318 m +1295.570 312.551 1295.260 311.437 1299 307.500 c +1298 307 l +1306 303.593 1319.203 306 1328 306 c +1397 306 l +1397 317 l +1331 317 l +1319.718 317 1307 315.379 1296 318 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1297 318 m +1305 314.593 1318.203 317 1327 317 c +1396 317 l +1387.882 320.407 1374.797 318 1366 318 c +1297 318 l +f +*U +0.000 0.600 0.616 0.376 k +*u +1396 318 m +1397 315 l +1397.685 316.248 1397.749 316.549 1398 318 c +1396 318 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1466 318 m +1467 317 l +1466 318 l +f +*U +0.000 0.000 0.000 0.792 k +*u +1490 318 m +1491 317 l +1490 318 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1946 318 m +1945 316.255 1944.547 314.875 1944 313 c +1948 315 l +1947.309 316.388 1947 316.861 1946 318 c +f +*U +0.000 0.000 0.000 0.576 k +*u +539.333 316.333 m +539.278 316.278 539.222 315.222 539.667 315.667 c +539.722 315.722 539.778 316.778 539.333 316.333 c +f +*U +0.000 0.000 0.000 0.659 k +*u +567 317 m +568 316 l +567 317 l +f +*U +0.000 0.000 0.000 0.051 k +*u +568 317 m +570 314.542 571.790 313.641 575 313 c +572.841 315 570.801 316 568 317 c +f +*U +0.000 0.000 0.000 0.114 k +*u +874 317 m +874.547 315 875 313.745 876 312 c +876.375 314.419 875.693 315.218 874 317 c +f +*U +0.000 0.682 0.776 0.188 k +*u +1051 317 m +1051 312 l +1051.830 314 1051.830 314.970 1051 317 c +f +*U +0.000 0.906 0.667 0.094 k +*u +1052 317 m +1051 306 l +1135 306 l +1133.239 309.561 1132.478 312 1133 316 c +1126.471 317.490 1123 311.750 1117 312.502 c +1113.762 312.910 1112.182 316.296 1108.896 316.852 c +1102.898 317.867 1096 317 1090 317 c +1052 317 l +f +*U +0.000 0.451 0.329 0.314 k +*u +1112.333 316.333 m +1112.278 316.278 1112.222 315.222 1112.667 315.667 c +1112.722 315.723 1112.777 316.778 1112.333 316.333 c +f +*U +0.000 0.235 0.176 0.110 k +*u +1124 317 m +1125 316 l +1124 317 l +f +*U +0.000 0.259 0.176 0.353 k +*u +1133 317 m +1134 316 l +1133 317 l +f +*U +0.000 0.380 0.247 0.129 k +*u +1203 317 m +1204 316 l +1203 317 l +f +*U +0.000 0.882 0.647 0.118 k +*u +1206 317 m +1207.364 315.181 1207.492 315.969 1207 314 c +1212 313 l +1210.952 311 1210.488 310 1210 308 c +1217.426 305 1226 307.997 1234 308 c +1252.180 308 1270 308.419 1288 306 c +1285.880 308.630 1284.237 310.917 1281 312 c +1281.562 313.801 1281.824 315 1282 317 c +1206 317 l +f +*U +0.000 0.310 0.224 0.200 k +*u +1295 317 m +1296 316 l +1295 317 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1457 314 m +1459.837 313.325 1461.522 314.495 1464 316 c +1461.311 316.405 1459.444 315.225 1457 314 c +f +*U +0.000 0.000 0.000 0.616 k +*u +1464 317 m +1465 316 l +1464 317 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1489.667 316.667 m +1489.222 316.222 1490.278 316.278 1490.333 316.333 c +1490.778 316.778 1489.722 316.722 1489.667 316.667 c +f +*U +0.000 0.000 0.000 0.118 k +*u +1959 317 m +1959.899 313.173 1961.819 310.249 1964 307 c +1964.572 310.923 1961.728 314.354 1959 317 c +f +*U +0.000 0.000 0.000 0.608 k +*u +894 316 m +895 315 l +894 316 l +f +*U +0.000 0.000 0.000 0.075 k +*u +895 316 m +895.547 314 896 312.745 897 311 c +897.710 313.531 897 314.516 895 316 c +f +*U +0.000 0.278 0.204 0.031 k +*u +1123 316 m +1124 315 l +1123 316 l +f +*U +0.000 0.569 0.404 0.431 k +*u +1133.333 315.333 m +1133.278 315.278 1133.222 314.222 1133.667 314.667 c +1133.722 314.722 1133.777 315.778 1133.333 315.333 c +f +*U +0.000 0.165 0.125 0.169 k +*u +1134 316 m +1135 315 l +1134 316 l +f +*U +0.000 0.275 0.200 0.145 k +*u +1294 316 m +1295 315 l +1294 316 l +f +*U +0.000 0.675 0.494 0.325 k +*u +1295 316 m +1294 314 l +1296 314 l +1296 315.853 1296.300 315.350 1295 316 c +f +*U +0.000 0.306 0.353 0.027 k +*u +1398.333 315.333 m +1398.278 315.278 1398.222 314.222 1398.667 314.667 c +1398.722 314.722 1398.777 315.778 1398.333 315.333 c +f +*U +0.000 0.000 0.000 0.106 k +*u +1481 312 m +1484.534 311.424 1486.762 313.397 1489 316 c +1486 314.955 1483.618 313.586 1481 312 c +f +*U +0.000 0.000 0.000 0.788 k +*u +1927 316 m +1928 315 l +1927 316 l +f +*U +0.000 0.000 0.000 0.859 k +*u +539 315 m +539 255 l +540.875 259.469 540 265.191 540 270 c +540 299 l +540 304 540.981 310.280 539 315 c +f +*U +0.000 0.000 0.000 0.125 k +*u +858 315 m +857 313.521 857 313.797 857 312 c +858.289 313.443 858.401 313.234 858 315 c +f +*U +0.000 0.459 0.424 0.192 k +*u +1050 315 m +1050 310 l +1050.830 312 1050.830 312.970 1050 315 c +f +*U +0.000 0.412 0.314 0.125 k +*u +1113 315 m +1114 314 l +1113 315 l +f +*U +0.000 0.286 0.208 0.231 k +*u +1121 315 m +1122 314 l +1121 315 l +f +*U +0.000 0.290 0.212 0.141 k +*u +1205 315 m +1206 314 l +1205 315 l +f +*U +0.000 0.396 0.286 0.176 k +*u +1283 315 m +1284 314 l +1283 315 l +f +*U +0.000 0.796 0.769 0.141 k +*u +1397 315 m +1397 306 l +1398.256 308.994 1398.256 312 1397 315 c +f +*U +0.000 0.000 0.000 0.816 k +*u +1461 315 m +1462 314 l +1461 315 l +f +*U +0.000 0.000 0.000 0.800 k +*u +1485 315 m +1486 314 l +1485 315 l +f +1979 315 m +1980 314 l +1979 315 l +f +*U +0.000 0.000 0.000 0.710 k +*u +571 314 m +572 313 l +571 314 l +f +*U +0.000 0.000 0.000 0.094 k +*u +837 314 m +837 311 l +838.195 312.223 838.316 312.420 839 314 c +837 314 l +f +*U +0.000 0.000 0.000 0.816 k +*u +839 314 m +840 313 l +839 314 l +f +*U +0.000 0.533 0.424 0.467 k +*u +1113 314 m +1114.543 312.733 1115 312.511 1117 312 c +1115.542 313 1114.752 313.436 1113 314 c +f +*U +0.000 0.196 0.169 0.216 k +*u +1119 314 m +1120 313 l +1119 314 l +f +*U +0.000 0.427 0.376 0.573 k +*u +1132 314 m +1132 310 l +1132.710 311.759 1132.710 312.241 1132 314 c +f +*U +0.000 0.376 0.282 0.247 k +*u +1133 314 m +1134 313 l +1133 314 l +f +*U +0.000 0.188 0.165 0.110 k +*u +1206 314 m +1207 313 l +1206 314 l +f +*U +0.000 0.290 0.278 0.710 k +*u +1207 314 m +1208 313 l +1207 314 l +f +*U +0.000 0.710 0.490 0.290 k +*u +1208 314 m +1209 309 l +1210.274 310.341 1211 311.403 1212 313 c +1208 314 l +f +*U +0.000 0.467 0.373 0.533 k +*u +1294 314 m +1294 311 l +1294.696 312.554 1294.696 312.446 1294 314 c +f +*U +0.000 0.420 0.451 0.094 k +*u +1398 314 m +1398 309 l +1398.830 311 1398.830 311.970 1398 314 c +f +*U +0.000 0.000 0.000 0.733 k +*u +1943 314 m +1944 313 l +1943 314 l +f +*U +0.000 0.000 0.000 0.149 k +*u +1981 314 m +1982 310 l +1982.553 312 1982.303 312.332 1981 314 c +f +*U +0.000 0.000 0.000 0.792 k +*u +547 313 m +548 312 l +547 313 l +f +*U +0.000 0.000 0.000 0.137 k +*u +573 313 m +574.223 311.805 574.420 311.684 576 311 c +574.777 312.195 574.580 312.316 573 313 c +f +*U +0.000 0.000 0.000 0.663 k +*u +856 313 m +857 312 l +856 313 l +f +*U +0.000 0.000 0.000 0.620 k +*u +877 313 m +878 312 l +877 313 l +f +*U +0.000 0.341 0.271 0.118 k +*u +1117 313 m +1118 312 l +1117 313 l +f +*U +0.000 0.710 0.553 0.290 k +*u +1118.667 312.667 m +1118.222 312.222 1119.278 312.278 1119.333 312.333 c +1119.778 312.778 1118.722 312.722 1118.667 312.667 c +f +*U +0.000 0.000 0.000 0.153 k +*u +1924 313 m +1923 311.255 1922.547 309.875 1922 308 c +1923.693 309.782 1924.375 310.581 1924 313 c +f +*U +0.000 0.000 0.000 0.631 k +*u +1925 313 m +1926 312 l +1925 313 l +f +*U +0.000 0.000 0.000 0.996 k +*u +1929 313 m +1928.455 311.365 1928.635 311.545 1927 311 c +1928 304 l +1924 306 l +1923.274 303.821 1923.561 304.220 1922 305 c +1919.825 299.325 1918.419 294 1920 288 c +1915.576 288.690 1911.467 288.267 1912 283 c +1910 281 1910.814 278.697 1911 276 c +1916 280 l +1916.251 278.548 1916.315 278.248 1917 277 c +1919.259 277 1921.290 276.624 1923 278 c +1924.517 277 1925.339 276.613 1927 276 c +1928.276 277.915 1928.277 277 1927 279 c +1936.521 281.267 1947.251 280 1957 280 c +1966.749 280 1977.479 281.267 1987 279 c +1985.907 277 1985.838 276.265 1986 274 c +1987.819 275.365 1987 275.492 1989 275 c +1990 278 l +1992 273 l +1989.567 271.538 1988.823 270.712 1988 268 c +1992.365 267.405 1994.627 261.447 1997 258 c +1998.417 258.472 1998.814 258.814 2000 260 c +1999 257 l +2003.462 255.684 2008.227 255.219 2008 261 c +2008.957 259.483 2009.387 258.662 2010 257 c +2011.533 260 2010.509 262 2009 265 c +2006.539 265 2004.400 265.434 2002 266 c +2003.478 266.986 2003.204 267 2005 267 c +2003.352 267.924 2001.825 268.449 2000 269 c +2002 276 l +2000.488 277.653 1999.819 278.894 1999 281 c +1996 280 l +1994 283.445 1992.720 286 1992 290 c +1988.786 288.587 1986.946 289.231 1984 291 c +1983 288 l +1982 292 l +1981.317 290.494 1981.174 289.685 1981 288 c +1927 287 l +1927.931 292.260 1928.728 296.660 1929 302 c +1934.463 301.221 1935.407 305 1938 309 c +1935 313 l +1933 312.590 1932.298 312.465 1931 311 c +1929.977 312.534 1930.195 312.402 1929 313 c +f +*U +0.000 0.000 0.000 0.125 k +*u +1943 313 m +1942 311.255 1941.547 309.875 1941 308 c +1942.693 309.782 1943.375 310.581 1943 313 c +f +*U +0.000 0.000 0.000 0.627 k +*u +364 312 m +365 311 l +364 312 l +f +*U +0.000 0.000 0.000 0.259 k +*u +365 312 m +366 311 l +365 312 l +f +*U +0.000 0.000 0.000 0.106 k +*u +547 312 m +548.402 309.726 549.515 309 552 308 c +550.394 309.914 549.217 310.837 547 312 c +f +*U +0.000 0.000 0.000 0.600 k +*u +548 312 m +549 311 l +548 312 l +f +*U +0.000 0.000 0.000 0.624 k +*u +805 312 m +806 311 l +805 312 l +f +*U +0.000 0.000 0.000 0.137 k +*u +856 312 m +855 310.521 855 310.797 855 309 c +856.289 310.443 856.401 310.234 856 312 c +f +*U +0.000 0.522 0.341 0.000 k +*u +1208 312 m +1209 311 l +1208 312 l +f +*U +0.000 0.333 0.310 0.231 k +*u +1285 312 m +1286 311 l +1285 312 l +f +*U +0.000 0.612 0.420 0.373 k +*u +1295 312 m +1295 309 l +1295.696 310.554 1295.696 310.446 1295 312 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1453 312 m +1454 310 l +1455.635 310.545 1455.455 310.365 1456 312 c +1453 312 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1456 312 m +1457 311 l +1456 312 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1480 312 m +1481 311 l +1480 312 l +f +*U +0.000 0.000 0.000 0.690 k +*u +1981 312 m +1982 311 l +1981 312 l +f +*U +0.000 0.000 0.000 0.537 k +*u +357 311 m +358 310 l +357 311 l +f +*U +0.000 0.000 0.000 0.129 k +*u +347 309 m +352.305 306.836 359.395 309.558 365 310 c +359.672 312.215 352.581 309.706 347 309 c +f +*U +0.000 0.000 0.000 0.671 k +*u +575 311 m +576 310 l +575 311 l +f +*U +0.000 0.000 0.000 0.098 k +*u +576 311 m +579.358 306.622 583.915 303 589 301 c +585.678 305.500 581 308.833 576 311 c +f +*U +0.000 0.000 0.000 0.545 k +*u +798 311 m +799 310 l +798 311 l +f +*U +0.000 0.000 0.000 0.141 k +*u +799 311 m +801.332 310 803.457 310 806 310 c +803.668 310.985 801.543 310.981 799 311 c +f +*U +0.000 0.000 0.000 0.110 k +*u +835 311 m +833 305 l +835.181 306.896 836 308.259 837 311 c +835 311 l +f +*U +0.000 0.000 0.000 0.620 k +*u +837 311 m +838 310 l +837 311 l +f +*U +0.000 0.000 0.000 0.078 k +*u +878 311 m +878.833 306.696 880.634 303.791 884 301 c +882.616 304.781 880.761 308 878 311 c +f +*U +0.000 0.000 0.000 0.224 k +*u +898 311 m +899 310 l +898 311 l +f +*U +0.000 0.251 0.208 0.102 k +*u +1133 311 m +1134 310 l +1133 311 l +f +*U +0.000 0.533 0.408 0.463 k +*u +1285 311 m +1285 308 l +1285.696 309.554 1285.696 309.446 1285 311 c +f +*U +0.000 0.329 0.239 0.224 k +*u +1294 311 m +1295 310 l +1294 311 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1449 309 m +1451.509 308.434 1452.220 309 1454 311 c +1449 309 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1476 309 m +1478 308.590 1478.962 309 1481 310 c +1478.860 310.410 1478 309.968 1476 309 c +f +*U +0.000 0.000 0.000 0.812 k +*u +1924 311 m +1925 310 l +1924 311 l +f +*U +0.000 0.000 0.000 0.878 k +*u +348.667 309.667 m +348.222 309.222 349.278 309.278 349.333 309.333 c +349.778 309.778 348.722 309.722 348.667 309.667 c +f +*U +0.000 0.000 0.000 0.569 k +*u +350 310 m +351 309 l +350 310 l +f +*U +0.000 0.000 0.000 0.643 k +*u +790.667 309.667 m +790.223 309.223 791.278 309.278 791.333 309.333 c +791.778 309.778 790.722 309.722 790.667 309.667 c +f +*U +0.000 0.000 0.000 0.188 k +*u +794 310 m +795.769 309.221 797 309 799 309 c +797.231 309.779 795.964 309.912 794 310 c +f +*U +0.000 0.000 0.000 0.749 k +*u +879 310 m +880 309 l +879 310 l +f +*U +0.000 0.000 0.000 0.129 k +*u +898 310 m +898.545 308.365 898.365 308.545 900 308 c +900 310 l +898 310 l +f +*U +0.000 0.471 0.400 0.412 k +*u +1050 310 m +1050 305 l +1050.830 307 1050.830 307.970 1050 310 c +f +*U +0.000 0.639 0.463 0.341 k +*u +1133 310 m +1133.684 308.420 1133.805 308.223 1135 307 c +1134.316 308.580 1134.195 308.777 1133 310 c +f +*U +0.000 0.294 0.243 0.118 k +*u +1134 310 m +1135 309 l +1134 310 l +f +*U +0.000 0.306 0.239 0.694 k +*u +1208 310 m +1209 309 l +1208 310 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1453 310 m +1454 309 l +1453 310 l +f +*U +0.000 0.000 0.000 0.000 k +*u +1818 310 m +1818 306 l +1865 306 l +1861.301 307.552 1856.983 307 1853 307 c +1832 307 l +1826.819 307 1821.973 306.207 1818 310 c +f +*U +0.000 0.000 0.000 0.090 k +*u +1983 310 m +1985 305 l +1985.710 307.530 1985 308.516 1983 310 c +f +*U +0.000 0.000 0.000 0.169 k +*u +171 309 m +174.699 307.448 179 308 183 308 c +203 308 l +206.567 308 211.649 308.869 214.852 306.972 c +219.877 303.997 219 294 212.956 293 c +199 290.846 183 293 169 293 c +172.699 291.448 177 292 181 292 c +204 292 l +207.652 292 213.326 290.952 216.682 292.603 c +220 294.282 220 304.700 217.972 307.397 c +215.739 310.216 209 309 206 309 c +171 309 l +f +*U +0.000 0.000 0.000 0.678 k +*u +552 309 m +553 308 l +552 309 l +f +*U +0.000 0.133 0.149 0.169 k +*u +1135 309 m +1136 308 l +1135 309 l +f +*U +0.000 0.294 0.239 0.051 k +*u +1286 309 m +1287 308 l +1286 309 l +f +*U +0.000 0.290 0.196 0.357 k +*u +1295 309 m +1296 308 l +1295 309 l +f +*U +0.000 0.478 0.478 0.522 k +*u +1296 309 m +1297 308 l +1296 309 l +f +*U +0.000 1.000 0.725 0.000 k +*u +1297 309 m +1298.223 307.805 1298.420 307.684 1300 307 c +1298.777 308.195 1298.580 308.316 1297 309 c +f +*U +0.000 0.463 0.361 0.443 k +*u +1398 309 m +1398 306 l +1398.696 307.554 1398.696 307.446 1398 309 c +f +*U +0.000 0.000 0.000 0.710 k +*u +1475 309 m +1476 308 l +1475 309 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1940 309 m +1941 308 l +1940 309 l +f +*U +0.000 0.000 0.000 0.000 k +*u +169 308 m +173.720 306 179.920 307 185 307 c +216 307 l +211.280 308.981 205 308 200 308 c +169 308 l +f +*U +0.000 0.000 0.000 0.859 k +*u +402 308 m +408.436 305.299 418 307 425 307 c +477 307 l +470.564 309.701 460.951 308 454 308 c +402 308 l +f +*U +0.000 0.000 0.000 0.149 k +*u +853 308 m +853 306 l +854.635 306.545 854.455 306.365 855 308 c +853 308 l +f +*U +0.000 0.000 0.000 0.765 k +*u +899 308 m +900 307 l +899 308 l +f +*U +0.000 0.000 0.000 0.122 k +*u +900 308 m +900.810 305.778 901.739 304 903 302 c +903.410 304.888 902 306 900 308 c +f +*U +0.000 0.537 0.416 0.463 k +*u +1135 308 m +1132.692 306.241 1130.908 306 1128 306 c +1130.278 304.900 1136.531 303.938 1135 308 c +f +*U +0.000 0.376 0.282 0.624 k +*u +1211 308 m +1212 307 l +1211 308 l +f +*U +0.000 0.882 0.592 0.118 k +*u +1216 307 m +1222.194 304.401 1231.314 306 1238 306 c +1285 306 l +1278.650 309.376 1269.998 308 1263 308 c +1247.304 308 1231.625 307 1216 307 c +f +*U +0.000 0.471 0.345 0.212 k +*u +1286 308 m +1287 307 l +1286 308 l +f +*U +0.000 0.392 0.322 0.267 k +*u +1296 308 m +1297 307 l +1296 308 l +f +*U +0.000 0.361 0.271 0.482 k +*u +1297.333 307.333 m +1297.278 307.278 1297.222 306.222 1297.667 306.667 c +1297.722 306.722 1297.778 307.778 1297.333 307.333 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1466 303 m +1470 302.321 1473.438 305 1476 308 c +1472.360 306.848 1469.252 304.988 1466 303 c +f +*U +0.000 0.000 0.000 0.173 k +*u +1819 308 m +1823.720 306 1829.920 307 1835 307 c +1845.467 307 1856.647 305.862 1867 307 c +1862.280 308.981 1856 308 1851 308 c +1819 308 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1922 308 m +1923 307 l +1922 308 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1940 308 m +1939 306.255 1938.547 304.875 1938 303 c +1939.693 304.782 1940.375 305.581 1940 308 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1965 308 m +1966 307 l +1965 308 l +f +*U +0.000 0.000 0.000 0.098 k +*u +553 307 m +554.223 305.805 554.420 305.684 556 305 c +554.777 306.195 554.580 306.316 553 307 c +f +*U +0.000 0.000 0.000 0.812 k +*u +881 307 m +882 306 l +881 307 l +f +*U +0.000 0.027 0.016 0.541 k +*u +1136 307 m +1137 306 l +1136 307 l +f +*U +0.000 0.302 0.208 0.086 k +*u +1211 307 m +1212 306 l +1211 307 l +f +*U +0.000 0.475 0.380 0.525 k +*u +1212 307 m +1214.718 303.890 1220 305 1224 305 c +1220.304 306.551 1215.951 306 1212 307 c +f +*U +0.000 0.518 0.404 0.482 k +*u +1280 306 m +1283.698 304.448 1288 305 1292 305 c +1288.552 307.402 1284 306 1280 306 c +f +*U +0.000 0.349 0.224 0.188 k +*u +1291 307 m +1292 306 l +1291 307 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1448 307 m +1449 306 l +1448 307 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1920.333 306.333 m +1920.278 306.278 1920.222 305.222 1920.667 305.667 c +1920.722 305.722 1920.778 306.778 1920.333 306.333 c +f +*U +0.000 0.000 0.000 0.082 k +*u +1965 307 m +1965.526 304.457 1965.878 303.465 1968 302 c +1967.251 304.254 1966.656 305.313 1965 307 c +f +*U +0.000 0.000 0.000 0.000 k +*u +217 306 m +217 295 l +218.431 298.410 218.431 302.590 217 306 c +f +*U +0.000 0.000 0.000 0.765 k +*u +556 306 m +557 305 l +556 306 l +f +*U +0.000 0.000 0.000 0.816 k +*u +834 306 m +835 305 l +834 306 l +f +*U +0.000 0.000 0.000 0.145 k +*u +852.333 305.333 m +852.278 305.278 852.222 304.222 852.667 304.667 c +852.722 304.722 852.778 305.778 852.333 305.333 c +f +*U +0.000 0.392 0.298 0.608 k +*u +1051 306 m +1057.678 303.198 1067.784 305 1075 305 c +1128 305 l +1121.322 307.802 1111.216 306 1104 306 c +1051 306 l +f +*U +0.000 0.047 0.035 0.816 k +*u +1136 306 m +1137 305 l +1136 306 l +f +*U +0.000 0.392 0.298 0.608 k +*u +1224 306 m +1229.217 303.811 1236.381 305 1242 305 c +1280 305 l +1274.784 307.189 1267.619 306 1262 306 c +1224 306 l +f +*U +0.000 0.235 0.149 0.357 k +*u +1292 306 m +1293 305 l +1292 306 l +f +*U +0.000 0.333 0.227 0.435 k +*u +1298 306 m +1299 305 l +1298 306 l +f +*U +0.000 0.392 0.298 0.608 k +*u +1299 306 m +1307 302.593 1320.203 305 1329 305 c +1398 305 l +1389.882 308.407 1376.797 306 1368 306 c +1299 306 l +f +*U +0.000 0.247 0.216 0.349 k +*u +1398 306 m +1399 305 l +1398 306 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1470 306 m +1471 305 l +1470 306 l +f +*U +0.000 0.000 0.000 0.627 k +*u +1760 306 m +1761 305 l +1760 306 l +f +*U +0.000 0.000 0.000 0.851 k +*u +1865 306 m +1865 293 l +1866.591 296.791 1866.591 302.209 1865 306 c +f +*U +0.000 0.000 0.000 0.129 k +*u +1866 306 m +1866 292 l +1867.667 295.972 1867.667 302 1866 306 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1918 304 m +1921 304 l +1920 306 l +1918.365 305.455 1918.545 305.635 1918 304 c +f +*U +0.000 0.000 0.000 0.800 k +*u +1938 306 m +1939 305 l +1938 306 l +f +*U +0.000 0.000 0.000 0.718 k +*u +851 305 m +852 304 l +851 305 l +f +*U +0.000 0.000 0.000 0.690 k +*u +882 305 m +883 304 l +882 305 l +f +*U +0.000 0.000 0.000 0.682 k +*u +901 305 m +902 304 l +901 305 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1468 305 m +1469 304 l +1468 305 l +f +*U +0.000 0.000 0.000 0.216 k +*u +1986 305 m +1987 304 l +1986 305 l +f +*U +0.000 0.875 0.624 0.125 k +*u +0 304 m +3.415 275.239 0.989 244.987 1 216 c +1 207 1.178 189 10 184 c +9 187 l +16 187 l +16 192 l +13.603 192 10.582 191.716 8.742 193.603 c +4.524 197.931 8 211.340 8 217 c +8 296 l +25 296 l +25 303 l +16.661 303 8.226 302.473 0 304 c +f +*U +0.000 0.745 0.553 0.137 k +*u +2 304 m +8.928 301 19.503 303 27 303 c +20 305.907 9.497 304 2 304 c +f +*U +0.000 0.529 0.424 0.471 k +*u +27 304 m +27 216 l +29.497 221.951 28 230.580 28 237 c +28 281 l +28 287.951 29.701 297.564 27 304 c +f +*U +0.000 0.000 0.000 0.827 k +*u +584 304 m +585 303 l +584 304 l +f +*U +0.000 0.000 0.000 0.212 k +*u +832 304 m +833 303 l +832 304 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1918 304 m +1917 300 l +1918.434 301.393 1919 302.233 1920 304 c +1918 304 l +f +*U +0.000 0.000 0.000 0.592 k +*u +1937 304 m +1938 303 l +1937 304 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1986 304 m +1987 303 l +1986 304 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1987 304 m +1987.547 302 1988 300.745 1989 299 c +1989.566 301.509 1988.847 302.220 1987 304 c +f +*U +0.000 0.878 0.631 0.122 k +*u +25 303 m +25 296 l +8 296 l +8 217 l +8 211.280 7 205.681 7 200 c +6.995 197.774 6.812 194.596 8.742 193 c +10.581 191.534 13.806 192 16 192 c +16 187 l +9 187 l +14.729 166.871 38 164 56 164 c +53.463 166 51.218 166.670 48 167 c +58.732 170.394 70.870 169 82 169 c +143 169 l +347 169 l +573.316 169 799.773 168 1026 168 c +1023.904 166.957 1022.301 166.397 1020 166 c +1023.746 164.425 1028 164.434 1032 163 c +1026.917 159.292 1028.860 154.570 1034 152 c +1034.482 147.602 1037.710 144.720 1042 144 c +1043.302 137.874 1051.372 127.403 1058 127 c +1060 121 l +1065.645 117.731 1070.265 112.945 1075.455 108.999 c +1084.809 101.890 1094.383 95 1104.385 88.790 c +1134.840 69.853 1172.407 57.574 1208 53.835 c +1230.812 51.439 1255.294 52.482 1278 56.194 c +1287.576 57.760 1297.239 62.310 1307 62 c +1312.651 67 1322.939 65.752 1327 72 c +1332.257 72 1337.333 75 1342 77.400 c +1351.411 82 1360 86.993 1368.950 92.731 c +1372.926 95.325 1375.304 98.590 1380 100 c +1380 104 l +1387 103.403 1392.546 110.925 1397.458 115.326 c +1406 123 1415.699 131.761 1422.624 141 c +1426 145.676 1429.982 150.383 1433 155.286 c +1434.874 157.982 1436 161.339 1439 162.972 c +1441.710 164.417 1445 163.998 1448 164 c +1449.545 169 1453.191 168.990 1458 169 c +1478 169 l +1571 169 l +1827 169 l +1918 169 l +1932.570 169 1948.564 170.879 1962.985 168.856 c +1966.189 168.407 1968.792 166.496 1972 166 c +1971.613 163.910 1971.616 164.289 1974 164 c +1975 149.673 1975 135.396 1975 121 c +1982.528 124.210 1989 130.403 1996 134.640 c +2016 146.761 2035.364 160.180 2055 173 c +2051.417 177.778 2043.203 182.381 2037 186 c +2034 187.663 2030.666 188.867 2028 191 c +2029 192 l +2022.569 194 2017.566 198.699 2012 202.371 c +2005 206.960 1997.472 210.666 1990.434 215 c +1985.255 218.421 1981 222.529 1975 224 c +1975 212.795 1977.422 198.436 1973 188 c +1974.801 186.685 1974.833 186.277 1975 184 c +1973.814 185 1973.396 185.339 1972 186 c +1968.765 183.562 1963.922 184 1960 184 c +1933 184 l +1828 184 l +1560 184 l +1472 184 l +1457.950 184 1442.908 185.529 1429 184 c +1424.554 188.593 1420.781 180.451 1418.570 177.454 c +1414.841 172.400 1410.443 167.829 1406.669 162.831 c +1403.309 158.382 1400.831 152.978 1397 149 c +1397.661 147.603 1397.964 147.187 1399 146 c +1397 145.930 1397 145.646 1396 147 c +1388.668 143.421 1383.819 135.383 1378 130 c +1379.943 129.378 1380.949 129.564 1383 130 c +1379.505 128.242 1376 128.553 1374 125 c +1369.507 125 1366.900 121.701 1363.485 119 c +1359.730 116 1355.532 113.778 1351.579 111 c +1336.876 101.279 1321.828 93.423 1304.999 87.715 c +1298.627 85.554 1292.888 81.909 1286 83 c +1279.646 78 1268.692 78.522 1261 77.421 c +1240.338 74.461 1219.358 75.788 1199 79.625 c +1192.383 80.872 1185.525 80.815 1179 82.795 c +1170.709 85.311 1162 87.656 1154 91 c +1149.521 92.958 1146 96.249 1141 96 c +1137.817 100.206 1130 102.419 1125.428 105 c +1116.708 109.812 1108.985 116 1100.910 121.890 c +1098 123.857 1090.870 130.413 1088 128 c +1077.695 141 1064.620 151.726 1054.411 164.985 c +1049.525 171.332 1045.859 180.996 1037.780 184.219 c +1032.550 186.306 1022.720 184 1017 184 c +967 184 l +792 184 l +289 184 l +126 184 l +74 184 l +62.741 184 51 183.376 40 185 c +40.986 186.479 41 186.203 41 188 c +37 188 l +35.781 191.439 33.303 192.655 30 194 c +30.636 201.291 27 208.512 27 216 c +27 303 l +25 303 l +f +*U +0.000 0.000 0.000 0.220 k +*u +559 303 m +560 302 l +559 303 l +f +*U +0.000 0.000 0.000 0.800 k +*u +560 303 m +561 302 l +560 303 l +f +*U +0.000 0.000 0.000 0.090 k +*u +831 303 m +830 301.521 830 301.797 830 300 c +831.289 301.443 831.401 301.234 831 303 c +f +*U +0.000 0.000 0.000 0.733 k +*u +832 303 m +833 302 l +832 303 l +f +*U +0.000 0.000 0.000 0.133 k +*u +850 303 m +848.817 300.672 847.777 298.489 847 296 c +849.256 298 850.728 299.867 850 303 c +f +*U +0.000 0.000 0.000 0.624 k +*u +1465 303 m +1466 302 l +1465 303 l +f +*U +0.000 0.000 0.000 0.153 k +*u +1701 302 m +1706.217 299.811 1713.381 301 1719 301 c +1731.812 301 1746.506 299 1759 302 c +1753.902 303.568 1746.469 302 1741 302 c +1701 302 l +f +*U +0.000 0.000 0.000 0.827 k +*u +1919 303 m +1920 302 l +1919 303 l +f +*U +0.000 0.000 0.000 0.275 k +*u +1937 303 m +1938 302 l +1937 303 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1968 303 m +1969 302 l +1968 303 l +f +*U +0.000 0.000 0.000 0.820 k +*u +849 302 m +850 301 l +849 302 l +f +*U +0.000 0.000 0.000 0.804 k +*u +884 302 m +885 301 l +884 302 l +f +*U +0.000 0.000 0.000 0.608 k +*u +903 302 m +904 301 l +903 302 l +f +*U +0.000 0.000 0.000 0.831 k +*u +1463 302 m +1464 301 l +1463 302 l +f +*U +0.000 0.000 0.000 0.118 k +*u +1460 300 m +1462.187 297.968 1464 296.906 1467 296 c +1465.771 297.870 1465 298.224 1463 299 c +1466 301 l +1463.726 301.409 1462.219 300.788 1460 300 c +f +*U +0.000 0.000 0.000 0.596 k +*u +1757 302 m +1758 301 l +1757 302 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1936 302 m +1934.216 298.641 1932.268 295.810 1932 292 c +1934.509 294.996 1936.347 298.460 1938 302 c +1936 302 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1968 302 m +1968.683 300.420 1968.805 300.222 1970 299 c +1969.316 300.580 1969.195 300.777 1968 302 c +f +*U +0.000 0.631 0.420 0.365 k +*u +0 301 m +0 208 l +2.802 214.678 1 224.784 1 232 c +1 279 l +1 285.686 2.599 294.806 0 301 c +f +*U +0.000 0.000 0.000 0.106 k +*u +561 301 m +562.450 299.392 563 298.936 565 298 c +563.550 299.608 562.949 300 561 301 c +f +*U +0.000 0.000 0.000 0.796 k +*u +588 301 m +589 300 l +588 301 l +f +*U +0.000 0.000 0.000 0.133 k +*u +589 301 m +590.450 299.392 591 298.936 593 298 c +591.550 299.608 590.949 300 589 301 c +f +*U +0.000 0.000 0.000 0.106 k +*u +884 301 m +884.651 298.566 885 297.717 887 296 c +886.251 298.254 885.656 299.314 884 301 c +f +*U +0.000 0.000 0.000 0.137 k +*u +905 301 m +906 297 l +906.393 298.924 906 299.360 905 301 c +f +*U +0.000 0.000 0.000 0.843 k +*u +1698 301 m +1703.217 298.811 1710.381 300 1716 300 c +1753 300 l +1747.783 302.189 1740.619 301 1735 301 c +1698 301 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1780 301 m +1781 300 l +1780 301 l +f +*U +0.000 0.000 0.000 0.596 k +*u +830 300 m +831 299 l +830 300 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1916 300 m +1915 298.255 1914.547 296.875 1914 295 c +1915.693 296.782 1916.375 297.581 1916 300 c +f +*U +0.000 0.000 0.000 0.659 k +*u +1917 300 m +1918 299 l +1917 300 l +f +*U +0.000 0.000 0.000 0.671 k +*u +565 299 m +566 298 l +565 299 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1461 299 m +1462 298 l +1461 299 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1970.333 298.333 m +1970.278 298.278 1970.222 297.222 1970.667 297.667 c +1970.722 297.722 1970.778 298.778 1970.333 298.333 c +f +*U +0.000 0.000 0.000 0.729 k +*u +1989 299 m +1990 298 l +1989 299 l +f +*U +0.000 0.000 0.000 0.243 k +*u +1990 299 m +1991 298 l +1990 299 l +f +*U +0.000 0.000 0.000 0.129 k +*u +565 298 m +565.545 296.365 565.365 296.545 567 296 c +567 298 l +565 298 l +f +*U +0.000 0.000 0.000 0.643 k +*u +592 298 m +593 297 l +592 298 l +f +*U +0.000 0.000 0.000 0.322 k +*u +593 298 m +594 297 l +593 298 l +f +*U +0.000 0.000 0.000 0.831 k +*u +829 298 m +830 297 l +829 298 l +f +*U +0.000 0.000 0.000 0.596 k +*u +1971 298 m +1972 297 l +1971 298 l +f +*U +0.000 0.000 0.000 0.102 k +*u +1990 298 m +1990.545 296.365 1990.365 296.545 1992 296 c +1992 298 l +1990 298 l +f +*U +0.000 0.000 0.000 0.812 k +*u +593 297 m +594 296 l +593 297 l +f +*U +0.000 0.000 0.000 0.090 k +*u +594 297 m +595.223 295.805 595.420 295.684 597 295 c +596 296.783 596 296.594 594 297 c +f +*U +0.000 0.000 0.000 0.173 k +*u +827.333 296.333 m +827.278 296.278 827.222 295.222 827.667 295.667 c +827.722 295.722 827.778 296.778 827.333 296.333 c +f +*U +0.000 0.000 0.000 0.776 k +*u +846 297 m +847 296 l +846 297 l +f +*U +0.000 0.000 0.000 0.690 k +*u +887 297 m +888 296 l +887 297 l +f +*U +0.000 0.000 0.000 0.114 k +*u +907 297 m +907.810 294.778 908.739 293 910 291 c +910.410 293.888 909 295 907 297 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1779 297 m +1780 296 l +1779 297 l +f +*U +0.000 0.000 0.000 0.063 k +*u +1971 297 m +1973 291 l +1973.744 293.735 1972.915 294.968 1971 297 c +f +*U +0.000 0.000 0.000 0.725 k +*u +569 296 m +570 295 l +569 296 l +f +*U +0.000 0.000 0.000 0.129 k +*u +846 296 m +843 290 l +891 290 l +890.190 292.222 889.261 293.990 888 296 c +887.590 293.860 888 293 889 291 c +845 291 l +846 293 846.577 293.769 846 296 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1466 296 m +1467 295 l +1466 296 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1467.667 295.667 m +1467.222 295.222 1468.278 295.278 1468.333 295.333 c +1468.778 295.778 1467.722 295.722 1467.667 295.667 c +f +*U +0.000 0.000 0.000 0.149 k +*u +1779.333 295.333 m +1779.278 295.278 1779.222 294.222 1779.667 294.667 c +1779.722 294.722 1779.778 295.778 1779.333 295.333 c +f +*U +0.000 0.000 0.000 0.773 k +*u +1932 296 m +1933 295 l +1932 296 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1992 296 m +1993 293 1994.415 290.618 1996 288 c +1996.576 291.534 1994.603 293.762 1992 296 c +f +*U +0.000 0.000 0.000 0.235 k +*u +569 295 m +570 294 l +569 295 l +f +*U +0.000 0.000 0.000 0.749 k +*u +596 295 m +597 294 l +596 295 l +f +*U +0.000 0.000 0.000 0.133 k +*u +597 295 m +599.319 292 601.622 290.432 605 289 c +602.701 291.971 600.505 293.641 597 295 c +f +*U +0.000 0.000 0.000 0.102 k +*u +826 295 m +825 293.521 825 293.797 825 292 c +826.289 293.443 826.401 293.234 826 295 c +f +*U +0.000 0.000 0.000 0.765 k +*u +827 295 m +828 294 l +827 295 l +f +*U +0.000 0.278 0.173 0.082 k +*u +1051 295 m +1058.399 291.895 1069.993 294 1078 294 c +1138 294 l +1130.600 297 1119 295 1111 295 c +1051 295 l +f +*U +0.000 0.263 0.196 0.192 k +*u +1138 295 m +1139.248 294.315 1139.548 294.251 1141 294 c +1139.752 294.685 1139.451 294.749 1138 295 c +f +*U +0.000 0.278 0.173 0.082 k +*u +1213 293 m +1221.624 295 1231.174 294 1240 294 c +1287 294 l +1281.784 296.189 1274.619 295 1269 295 c +1231 295 l +1226 295 1216.407 296.899 1213 293 c +f +*U +0.000 0.271 0.243 0.180 k +*u +1296 295 m +1297.248 294.315 1297.548 294.251 1299 294 c +1297.751 294.685 1297.452 294.749 1296 295 c +f +*U +0.000 0.267 0.196 0.063 k +*u +1299 295 m +1302 293.673 1305.586 294 1309 294 c +1305.837 295.327 1302.415 295.000 1299 295 c +f +*U +0.000 0.278 0.227 0.157 k +*u +1313 295 m +1314.248 294.315 1314.548 294.251 1316 294 c +1314.752 294.685 1314.451 294.749 1313 295 c +f +*U +0.000 0.353 0.286 0.043 k +*u +1316 295 m +1317.506 294.317 1318.315 294.174 1320 294 c +1318.494 294.683 1317.685 294.826 1316 295 c +f +*U +0.000 0.278 0.173 0.082 k +*u +1320 295 m +1326.919 292 1337.520 294 1345 294 c +1399 294 l +1392 296.903 1381.480 295 1374 295 c +1320 295 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1468 295 m +1469 294 l +1468 295 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1469 295 m +1470.223 293.805 1470.420 293.684 1472 293 c +1470.777 294.195 1470.580 294.316 1469 295 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1778 295 m +1779 294 l +1778 295 l +f +*U +0.000 0.000 0.000 0.090 k +*u +1913 295 m +1911.952 293 1911.487 292 1911 290 c +1912.693 291.782 1913.375 292.581 1913 295 c +f +*U +0.000 0.000 0.000 0.796 k +*u +1914 295 m +1915 294 l +1914 295 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1973 295 m +1974 294 l +1973 295 l +f +*U +0.000 0.000 0.000 0.843 k +*u +169 294 m +173.720 292 179.920 293 185 293 c +217 293 l +212.280 294.981 206 294 201 294 c +169 294 l +f +*U +0.000 0.000 0.000 0.824 k +*u +889 294 m +890 293 l +889 294 l +f +*U +0.000 0.000 0.000 0.792 k +*u +908 294 m +909 293 l +908 294 l +f +*U +0.000 0.506 0.506 0.494 k +*u +1050.333 293.333 m +1050.278 293.278 1050.222 292.222 1050.667 292.667 c +1050.722 292.722 1050.778 293.778 1050.333 293.333 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1051 294 m +1055 291 l +1062 294.980 1073 293 1081 293 c +1140 293 l +1140 289 l +1140.779 290.769 1140.912 292 1141 294 c +1051 294 l +f +*U +0.000 0.522 0.345 0.471 k +*u +1214.333 293.333 m +1214.278 293.278 1214.222 292.222 1214.667 292.667 c +1214.722 292.722 1214.778 293.778 1214.333 293.333 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1215 294 m +1221.194 291.401 1230.314 293 1237 293 c +1254.524 293 1273.751 295.202 1291 292 c +1285.726 295.996 1275.423 294 1269 294 c +1215 294 l +f +*U +0.149 0.000 0.008 0.133 k +*u +1295.333 293.333 m +1295.278 293.278 1295.222 292.222 1295.667 292.667 c +1295.722 292.723 1295.777 293.778 1295.333 293.333 c +f +*U +0.000 0.702 0.557 0.298 k +*u +1296 294 m +1296 289 l +1296.683 290.506 1296.826 291.315 1297 293 c +1305 293 l +1302 294.213 1299 293.998 1296 294 c +f +*U +0.000 0.882 0.624 0.118 k +*u +1297 293 m +1297 289 l +1284.958 293.668 1273.859 293 1261 293 c +1215 293 l +1216 287 l +1216.685 288.248 1216.749 288.549 1217 290 c +1224 290 l +1221.894 289.356 1220.205 289 1218 289 c +1218 283 l +1250.935 281.586 1284 282 1317 282 c +1315.600 285 1314 287.825 1313 291 c +1310.566 291.651 1309.717 292 1308 294 c +1304.305 293.533 1300.735 293 1297 293 c +f +*U +0.000 0.635 0.463 0.365 k +*u +1308 294 m +1308.899 291.876 1308.876 291.899 1311 291 c +1309.897 292.457 1309.457 292.897 1308 294 c +f +*U +0.000 0.392 0.310 0.580 k +*u +1313 294 m +1314 293 l +1313 294 l +f +*U +0.000 0.745 0.557 0.255 k +*u +1312 291 m +1313 290 l +1314.596 290.959 1315.659 291.726 1317 293 c +1314.333 293 1313.893 292.911 1312 291 c +f +*U +0.000 0.667 0.663 0.298 k +*u +1316 294 m +1319.448 291.598 1323.896 292.966 1328 293 c +1324.302 294.551 1319.983 294 1316 294 c +f +*U +0.000 0.663 0.467 0.337 k +*u +1328 294 m +1334.194 291.401 1343.314 293 1350 293 c +1398 293 l +1391.806 295.599 1382.686 294 1376 294 c +1328 294 l +f +*U +0.000 0.420 0.424 0.176 k +*u +1398 294 m +1398 290 l +1398.710 291.759 1398.710 292.241 1398 294 c +f +*U +0.000 0.000 0.000 0.055 k +*u +1767 286 m +1772.368 286.838 1777.190 289.221 1780 294 c +1775.951 292.207 1769.735 289.435 1767 286 c +f +*U +0.000 0.000 0.000 0.137 k +*u +402 293 m +408.436 290.299 418 292 425 292 c +475 292 l +475 255 l +476.661 258.959 476 263.740 476 268 c +476 293 l +402 293 l +f +*U +0.000 0.000 0.000 0.635 k +*u +476 293 m +476 255 l +477.441 258.435 477 262.298 477 266 c +477 274 479 285.600 476 293 c +f +*U +0.000 0.000 0.000 0.086 k +*u +572 293 m +573.573 290.338 575 289.228 578 288 c +576.170 290.348 574.637 291.617 572 293 c +f +*U +0.000 0.000 0.000 0.816 k +*u +573 293 m +574 292 l +573 293 l +f +*U +0.000 0.859 0.608 0.137 k +*u +1051 293 m +1052 283 l +1079.394 279.538 1108.379 282 1136 282 c +1136 284 l +1056 284 l +1062.584 285.946 1070 285 1077 285 c +1117 285 l +1123.705 285 1132.831 286.880 1138 282 c +1140 282 l +1140.890 285.870 1140.490 289 1140 293 c +1078 293 l +1072.473 293 1059.796 295.344 1056 291 c +1054.175 292.336 1053.247 292.690 1051 293 c +f +*U +0.000 0.522 0.365 0.122 k +*u +1291 293 m +1292 292 l +1291 293 l +f +*U +0.000 0.267 0.212 0.039 k +*u +1312 293 m +1313 292 l +1312 293 l +f +*U +0.000 0.871 0.624 0.129 k +*u +1319 292 m +1320.249 291.315 1320.548 291.251 1322 291 c +1320.722 288 1319.830 285 1319 282 c +1397 282 l +1397 293 l +1346 293 l +1337.393 293 1327.280 294.448 1319 292 c +f +*U +0.000 0.898 0.851 0.047 k +*u +1397 293 m +1397 290 l +1397.696 291.554 1397.696 291.446 1397 293 c +f +*U +0.000 0.000 0.000 0.098 k +*u +1472 293 m +1473.458 291.919 1474.248 291.564 1476 291 c +1474.457 292.267 1473.952 292.489 1472 293 c +f +*U +0.000 0.000 0.000 0.839 k +*u +1818 293 m +1822.720 291 1828.920 292 1834 292 c +1865 292 l +1860.280 293.981 1854 293 1849 293 c +1818 293 l +f +*U +0.000 0.000 0.000 0.671 k +*u +1865 293 m +1866 292 l +1865 293 l +f +*U +0.000 0.000 0.000 0.133 k +*u +1931 293 m +1929 289 l +1976 289 l +1975 293 l +1974.315 291.752 1974.251 291.452 1974 290 c +1960 291.554 1945 290 1931 290 c +1931.400 291.650 1931.479 291.502 1931 293 c +f +*U +0.000 0.000 0.000 0.635 k +*u +1993 293 m +1994 292 l +1993 293 l +f +*U +0.000 0.000 0.000 0.165 k +*u +344 290 m +348 291 l +345.954 291.751 345.404 291.656 344 290 c +f +*U +0.000 0.000 0.000 0.078 k +*u +348 292 m +348 290 l +350 290 l +350 292 l +348 292 l +f +*U +0.000 0.000 0.000 0.722 k +*u +600 292 m +601 291 l +600 292 l +f +*U +0.000 0.000 0.000 0.082 k +*u +784 292 m +784 271 l +786 271 l +786 277.541 786.862 284.699 785 291 c +792 290 798.934 288.303 806 288 c +806 272 l +807.797 272 807.521 272 809 273 c +808 277 809.393 284 806.972 287.486 c +805.447 289.622 802.364 289.842 800 290.245 c +794.702 291 789.378 291.955 784 292 c +f +*U +0.000 0.000 0.000 0.078 k +*u +823 292 m +821.770 289.365 820.766 286.804 820 284 c +822.573 286.383 823.933 288.660 825 292 c +823 292 l +f +*U +0.000 0.000 0.000 0.624 k +*u +825 292 m +826 291 l +825 292 l +f +*U +0.000 0.000 0.000 0.616 k +*u +843 292 m +844 291 l +843 292 l +f +*U +0.000 0.584 0.439 0.329 k +*u +1050 292 m +1050 289 l +1050.696 290.554 1050.696 290.446 1050 292 c +f +*U +0.000 0.259 0.153 0.408 k +*u +1153 292 m +1154 291 l +1153 292 l +f +*U +0.000 0.314 0.184 0.043 k +*u +1154 292 m +1155 291 l +1154 292 l +f +*U +0.000 0.427 0.282 0.098 k +*u +1214 292 m +1215 291 l +1214 292 l +f +*U +0.000 0.447 0.314 0.400 k +*u +1291.667 291.667 m +1291.222 291.222 1292.278 291.278 1292.333 291.333 c +1292.778 291.778 1291.722 291.722 1291.667 291.667 c +f +*U +0.000 0.102 0.059 0.082 k +*u +1295.333 291.333 m +1295.278 291.278 1295.222 290.222 1295.667 290.667 c +1295.722 290.723 1295.777 291.778 1295.333 291.333 c +f +*U +0.000 0.400 0.282 0.098 k +*u +1311 292 m +1312 291 l +1311 292 l +f +*U +0.000 0.318 0.388 0.267 k +*u +1315 292 m +1316.506 291.317 1317.315 291.174 1319 291 c +1317.494 291.683 1316.685 291.826 1315 292 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1446 292 m +1446 264 l +1446 260.293 1445 255.582 1448 253 c +1446.414 261.541 1447 270.342 1447 279 c +1447 283.260 1447.661 288 1446 292 c +f +*U +0.000 0.000 0.000 0.776 k +*u +1473 292 m +1474 291 l +1473 292 l +f +*U +0.000 0.000 0.000 0.161 k +*u +1818 292 m +1822.720 290 1828.920 291 1834 291 c +1866 291 l +1861.280 292.981 1855 292 1850 292 c +1818 292 l +f +*U +0.000 0.000 0.000 0.078 k +*u +169 291 m +169 271 l +171 271 l +171 291 l +169 291 l +f +*U +0.000 0.000 0.000 0.106 k +*u +343 291 m +343 272 l +345 272 l +345 277.819 346.627 286.213 343 291 c +f +*U +0.000 0.000 0.000 0.894 k +*u +345.667 290.667 m +345.222 290.222 346.278 290.278 346.333 290.333 c +346.778 290.778 345.722 290.722 345.667 290.667 c +f +*U +0.000 0.000 0.000 0.600 k +*u +347 291 m +348 290 l +347 291 l +f +*U +0.000 0.000 0.000 0.169 k +*u +350 291 m +351.506 290.317 352.315 290.174 354 290 c +352.494 290.683 351.685 290.826 350 291 c +f +*U +0.000 0.000 0.000 0.082 k +*u +402 291 m +402 254 l +406.630 260.777 403.860 274 404 282 c +404 285.548 405 288.710 402 291 c +f +*U +0.000 0.000 0.000 0.243 k +*u +785 291 m +786 290 l +785 291 l +f +*U +0.000 0.000 0.000 0.541 k +*u +788 291 m +789 290 l +788 291 l +f +*U +0.000 0.000 0.000 0.808 k +*u +891.333 290.333 m +891.278 290.278 891.222 289.222 891.667 289.667 c +891.722 289.722 891.778 290.778 891.333 290.333 c +f +*U +0.000 0.000 0.000 0.710 k +*u +910 291 m +911 290 l +910 291 l +f +*U +0.000 0.000 0.000 0.102 k +*u +911 291 m +912.305 286.905 914.607 283.550 917 280 c +917.717 284.411 914 288.208 911 291 c +f +*U +0.000 0.133 0.122 0.078 k +*u +1141 291 m +1142 290 l +1141 291 l +f +*U +0.000 0.408 0.275 0.004 k +*u +1152.333 290.333 m +1152.278 290.278 1152.222 289.222 1152.667 289.667 c +1152.722 289.722 1152.777 290.778 1152.333 290.333 c +f +*U +0.000 0.698 0.522 0.302 k +*u +1153 288 m +1154.560 288.596 1155.623 289 1157 290 c +1154.303 290.854 1153.614 290.851 1153 288 c +f +*U +0.000 0.263 0.129 0.310 k +*u +1156 291 m +1157 290 l +1156 291 l +f +*U +0.000 0.588 0.451 0.412 k +*u +1293 291 m +1294 290 l +1293 291 l +f +*U +0.000 0.439 0.298 0.086 k +*u +1294 291 m +1295 290 l +1294 291 l +f +*U +0.000 0.204 0.141 0.122 k +*u +1314.333 290.333 m +1314.278 290.278 1314.222 289.222 1314.667 289.667 c +1314.722 289.722 1314.778 290.778 1314.333 290.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1319 284 m +1319.464 286.172 1320 287.958 1321 290 c +1314.568 291.356 1313.905 287.344 1319 284 c +f +*U +0.000 0.318 0.188 0.063 k +*u +1319.667 290.667 m +1319.222 290.222 1320.278 290.278 1320.333 290.333 c +1320.778 290.778 1319.722 290.722 1319.667 290.667 c +f +*U +0.000 0.420 0.263 0.094 k +*u +1321.333 290.333 m +1321.278 290.278 1321.222 289.222 1321.667 289.667 c +1321.722 289.722 1321.777 290.778 1321.333 290.333 c +f +*U +0.000 0.000 0.000 0.110 k +*u +1447 291 m +1447 255 l +1448.552 258.698 1448 263 1448 267 c +1448 289 l +1450.360 287.687 1452.391 286.659 1455 286 c +1452.579 288.268 1450 289.685 1447 291 c +f +*U +0.000 0.000 0.000 0.725 k +*u +1448 291 m +1449 290 l +1448 291 l +f +*U +0.000 0.000 0.000 0.596 k +*u +1475 291 m +1476 290 l +1475 291 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1476 291 m +1478.383 288.549 1480.793 287.178 1484 286 c +1481.654 288.730 1479.449 289.975 1476 291 c +f +*U +0.000 0.000 0.000 0.067 k +*u +1818 291 m +1818 270 l +1820.643 276.299 1818.394 284.254 1820 291 c +1818 291 l +f +*U +0.000 0.000 0.000 0.773 k +*u +1929 291 m +1930 290 l +1929 291 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1994 291 m +1995 290 l +1994 291 l +f +*U +0.000 0.000 0.000 0.827 k +*u +352 290 m +353 289 l +352 290 l +f +*U +0.000 0.000 0.000 0.561 k +*u +353 290 m +354 289 l +353 290 l +f +*U +0.000 0.000 0.000 0.200 k +*u +357.667 289.667 m +357.222 289.222 358.278 289.278 358.333 289.333 c +358.778 289.778 357.722 289.722 357.667 289.667 c +f +*U +0.000 0.000 0.000 0.078 k +*u +359 290 m +361 288.418 362.388 288.174 365 288 c +365 280.237 364.973 272.702 364 265 c +367 269.401 369.457 282.706 365.972 287.436 c +364.435 289.522 361.327 289.677 359 290 c +f +*U +0.000 0.000 0.000 0.753 k +*u +577 290 m +578 289 l +577 290 l +f +*U +0.000 0.000 0.000 0.533 k +*u +794 290 m +795 289 l +794 290 l +f +*U +0.000 0.000 0.000 0.776 k +*u +842 290 m +843 289 l +842 290 l +f +*U +0.000 0.000 0.000 0.616 k +*u +843 290 m +847.720 288 853.920 289 859 289 c +891 289 l +886.280 290.981 880 290 875 290 c +843 290 l +f +*U +0.000 0.404 0.314 0.286 k +*u +1141.333 289.333 m +1141.278 289.278 1141.222 288.222 1141.667 288.667 c +1141.722 288.722 1141.777 289.778 1141.333 289.333 c +f +*U +0.000 0.341 0.392 0.239 k +*u +1157 290 m +1158 289 l +1157 290 l +f +*U +0.000 0.145 0.094 0.192 k +*u +1215 290 m +1216 289 l +1215 290 l +f +*U +0.000 0.780 0.553 0.220 k +*u +1217 290 m +1216.659 283.801 1217.589 282 1224 282 c +1221.948 282.874 1220.253 282.953 1218 283 c +1218 289 l +1224 289 l +1221.669 289.984 1219.543 289.981 1217 290 c +f +*U +0.000 0.604 0.486 0.396 k +*u +1294 290 m +1295 289 l +1294 290 l +f +*U +0.000 0.290 0.290 0.710 k +*u +1313.333 289.333 m +1313.278 289.278 1313.222 288.222 1313.667 288.667 c +1313.722 288.722 1313.777 289.778 1313.333 289.333 c +f +*U +0.000 0.663 0.698 0.267 k +*u +1397 290 m +1397 284 l +1397.951 286.285 1397.951 287.715 1397 290 c +f +*U +0.000 0.322 0.290 0.157 k +*u +1398 290 m +1398 285 l +1398.830 287 1398.830 287.970 1398 290 c +f +*U +0.000 0.000 0.000 0.804 k +*u +1450 290 m +1451 289 l +1450 290 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1819 290 m +1819 283 1819.623 275.818 1818 269 c +1873 269 l +1880.751 269 1891 270.863 1898 267 c +1899.183 269.328 1900.223 271.511 1901 274 c +1893.242 268.414 1884.246 270 1875 270 c +1820 270 l +1820 276.169 1821.398 284.285 1819 290 c +f +*U +0.000 0.000 0.000 0.110 k +*u +1910 290 m +1909 288.522 1909 288.797 1909 287 c +1910.290 288.443 1910.401 288.233 1910 290 c +f +*U +0.000 0.000 0.000 0.820 k +*u +1911 290 m +1912 289 l +1911 290 l +f +*U +0.000 0.000 0.000 0.812 k +*u +1976 290 m +1977 289 l +1976 290 l +f +*U +0.000 0.000 0.000 0.827 k +*u +358 289 m +359 288 l +358 289 l +f +*U +0.000 0.000 0.000 0.659 k +*u +359 289 m +360 288 l +359 289 l +f +*U +0.000 0.000 0.000 0.690 k +*u +578 289 m +579 288 l +578 289 l +f +*U +0.000 0.000 0.000 0.667 k +*u +604 289 m +605 288 l +604 289 l +f +*U +0.000 0.000 0.000 0.125 k +*u +605 289 m +606.624 286.956 607.643 286 610 285 c +608.598 287.274 607.485 287.987 605 289 c +f +*U +0.000 0.000 0.000 0.541 k +*u +800 289 m +801 288 l +800 289 l +f +*U +0.000 0.455 0.322 0.188 k +*u +1050 289 m +1050 284 l +1050.830 286 1050.830 286.970 1050 289 c +f +*U +0.000 0.278 0.231 0.251 k +*u +1152 289 m +1153 288 l +1152 289 l +f +*U +0.000 0.784 0.565 0.188 k +*u +1153 284 m +1157 285 l +1155.752 285.685 1155.451 285.749 1154 286 c +1156.786 286.458 1157.455 286.369 1159 284 c +1159.683 285.506 1159.826 286.315 1160 288 c +1155.836 288.646 1153.747 288.465 1153 284 c +f +*U +0.000 0.639 0.655 0.345 k +*u +1157 289 m +1158 288 l +1157 289 l +f +*U +0.000 0.318 0.486 0.373 k +*u +1158 289 m +1159 288 l +1158 289 l +f +*U +0.000 0.325 0.239 0.294 k +*u +1320 289 m +1321 288 l +1320 289 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1478 289 m +1479 288 l +1478 289 l +f +*U +0.000 0.000 0.000 0.776 k +*u +1770 289 m +1771 288 l +1770 289 l +f +*U +0.000 0.000 0.000 0.616 k +*u +1929 289 m +1933.720 287 1939.920 288 1945 288 c +1977 288 l +1972.280 289.981 1966 289 1961 289 c +1929 289 l +f +*U +0.000 0.588 0.455 0.357 k +*u +1141 288 m +1141 284 l +1141.710 285.759 1141.710 286.241 1141 288 c +f +*U +0.000 0.655 0.545 0.345 k +*u +1152 288 m +1152 282 l +1152.951 284.285 1152.951 285.715 1152 288 c +f +*U +0.000 0.114 0.216 0.318 k +*u +1160 288 m +1161 287 l +1160 288 l +f +*U +0.000 0.404 0.298 0.137 k +*u +1314.333 287.333 m +1314.278 287.278 1314.222 286.222 1314.667 286.667 c +1314.722 286.722 1314.778 287.778 1314.333 287.333 c +f +*U +0.000 0.353 0.243 0.345 k +*u +1319 288 m +1320 287 l +1319 288 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1453 288 m +1454 287 l +1453 288 l +f +*U +0.000 0.000 0.000 0.718 k +*u +1480 288 m +1481 287 l +1480 288 l +f +*U +0.000 0.000 0.000 0.655 k +*u +1766 288 m +1767 287 l +1766 288 l +f +*U +0.000 0.000 0.000 0.780 k +*u +1996 288 m +1997 287 l +1996 288 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1997 288 m +1997.683 286.420 1997.805 286.223 1999 285 c +1998.316 286.580 1998.195 286.777 1997 288 c +f +*U +0.000 0.000 0.000 0.188 k +*u +579.667 286.667 m +579.222 286.222 580.278 286.278 580.333 286.333 c +580.778 286.778 579.722 286.722 579.667 286.667 c +f +*U +0.000 0.741 0.478 0.259 k +*u +1051 287 m +1051 283 l +1051.710 284.759 1051.710 285.241 1051 287 c +f +*U +0.000 0.886 0.667 0.110 k +*u +1154 287 m +1157 285 l +1155 284 1154.222 283.733 1153 282 c +1160 282 l +1159 287 l +1154 287 l +f +*U +0.000 0.267 0.259 0.706 k +*u +1160 287 m +1161 286 l +1160 287 l +f +*U +0.000 0.553 0.388 0.196 k +*u +1216.333 286.333 m +1216.278 286.278 1216.222 285.222 1216.667 285.667 c +1216.722 285.722 1216.777 286.778 1216.333 286.333 c +f +*U +0.122 0.000 0.031 0.161 k +*u +1317 287 m +1318 286 l +1317 287 l +f +*U +0.000 0.451 0.271 0.133 k +*u +1319 287 m +1320 286 l +1319 287 l +f +*U +0.000 0.000 0.000 0.792 k +*u +1455 287 m +1456 286 l +1455 287 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1698 287 m +1698 253 l +1700 253 l +1700 285 l +1709.432 285 1719 286 1728 283 c +1721.767 290 1706.728 287 1698 287 c +f +*U +0.000 0.000 0.000 0.631 k +*u +1724 287 m +1725 286 l +1724 287 l +f +*U +0.000 0.000 0.000 0.043 k +*u +1746 287 m +1747.506 286.317 1748.315 286.174 1750 286 c +1750 283 l +1755 283 l +1754.402 284.196 1754.534 283.977 1753 285 c +1754.314 285.768 1754.232 285.686 1755 287 c +1746 287 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1755 287 m +1757.234 284 1759.750 284.856 1763 286 c +1760.387 287 1757.835 286.993 1755 287 c +f +*U +0.000 0.000 0.000 0.165 k +*u +1763 287 m +1764.506 286.317 1765.315 286.174 1767 286 c +1765.494 286.683 1764.685 286.826 1763 287 c +f +*U +0.000 0.000 0.000 0.078 k +*u +1907 287 m +1906 282 l +1907.656 283.686 1908.251 284.746 1909 287 c +1907 287 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1909 287 m +1910 286 l +1909 287 l +f +*U +0.000 0.000 0.000 0.075 k +*u +581 286 m +583 282.223 585.961 280.341 590 279 c +587.451 282 584.610 284.201 581 286 c +f +*U +0.000 0.000 0.000 0.710 k +*u +582 286 m +583 285 l +582 286 l +f +*U +0.000 0.000 0.000 0.831 k +*u +913 286 m +914 285 l +913 286 l +f +*U +0.000 0.451 0.357 0.506 k +*u +1160 286 m +1160 283 l +1160.696 284.554 1160.696 284.446 1160 286 c +f +*U +0.000 0.459 0.337 0.153 k +*u +1315 286 m +1316 285 l +1315 286 l +f +*U +0.000 0.310 0.216 0.055 k +*u +1316 286 m +1317 285 l +1316 286 l +f +*U +0.016 0.035 0.000 0.188 k +*u +1319.333 285.333 m +1319.278 285.278 1319.222 284.222 1319.667 284.667 c +1319.723 284.723 1319.777 285.777 1319.333 285.333 c +f +*U +0.000 0.000 0.000 0.094 k +*u +1455 286 m +1458.420 281.873 1462.878 279.478 1468 278 c +1464.458 281.653 1459.766 284.255 1455 286 c +f +*U +0.000 0.000 0.000 0.176 k +*u +1484.667 285.667 m +1484.222 285.222 1485.278 285.278 1485.333 285.333 c +1485.778 285.778 1484.722 285.722 1484.667 285.667 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1747 286 m +1748 285 l +1747 286 l +f +*U +0.000 0.000 0.000 0.180 k +*u +1748 286 m +1748.545 284.365 1748.365 284.545 1750 284 c +1750 286 l +1748 286 l +f +*U +0.000 0.000 0.000 0.882 k +*u +615 285 m +615 281 l +615.710 282.760 615.710 283.240 615 285 c +f +*U +0.000 0.937 0.667 0.063 k +*u +1056 285 m +1062.194 282.401 1071.314 284 1078 284 c +1115 284 l +1122.281 284 1129.880 284.695 1137 283 c +1133.298 287.236 1121.373 285 1116 285 c +1056 285 l +f +*U +0.078 0.000 0.020 0.259 k +*u +1151 285 m +1151 282 l +1151.696 283.554 1151.696 283.446 1151 285 c +f +*U +0.000 0.239 0.196 0.141 k +*u +1161 285 m +1162 284 l +1161 285 l +f +*U +0.000 0.937 0.667 0.063 k +*u +1224 285 m +1230.436 282.299 1240 284 1247 284 c +1296 284 l +1289.564 286.701 1279.951 285 1273 285 c +1224 285 l +f +*U +0.000 0.671 0.529 0.329 k +*u +1316 285 m +1316.899 282.876 1316.876 282.899 1319 282 c +1317.897 283.457 1317.457 283.897 1316 285 c +f +*U +0.000 0.369 0.239 0.086 k +*u +1317 285 m +1318 284 l +1317 285 l +f +*U +0.000 0.937 0.667 0.063 k +*u +1328 285 m +1333.707 282.605 1341.846 284 1348 284 c +1392 284 l +1386.293 286.395 1378 285 1372 285 c +1328 285 l +f +*U +0.000 0.204 0.176 0.047 k +*u +1398 285 m +1399 284 l +1398 285 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1458 285 m +1459 284 l +1458 285 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1486.667 284.667 m +1486.222 284.222 1487.278 284.278 1487.333 284.333 c +1487.778 284.778 1486.722 284.722 1486.667 284.667 c +f +*U +0.000 0.000 0.000 0.627 k +*u +1998 285 m +1999 284 l +1998 285 l +f +*U +0.000 0.000 0.000 0.067 k +*u +1999 285 m +2000 281.826 2001.785 279.509 2004 277 c +2003.829 280.924 2002 282.680 1999 285 c +f +*U +0.000 0.000 0.000 0.718 k +*u +820 284 m +821 283 l +820 284 l +f +*U +0.000 0.212 0.141 0.106 k +*u +1050.333 283.333 m +1050.278 283.278 1050.222 282.222 1050.667 282.667 c +1050.722 282.722 1050.778 283.778 1050.333 283.333 c +f +*U +0.000 0.510 0.447 0.404 k +*u +1140 284 m +1141 283 l +1140 284 l +f +*U +0.000 0.290 0.255 0.329 k +*u +1141 284 m +1142 283 l +1141 284 l +f +*U +0.000 0.369 0.329 0.259 k +*u +1161 284 m +1162 283 l +1161 284 l +f +*U +0.000 0.506 0.486 0.494 k +*u +1216.333 283.333 m +1216.278 283.278 1216.222 282.222 1216.667 282.667 c +1216.722 282.722 1216.777 283.778 1216.333 283.333 c +f +*U +0.000 0.243 0.216 0.051 k +*u +1318.667 283.667 m +1318.222 283.222 1319.278 283.278 1319.333 283.333 c +1319.778 283.778 1318.722 283.722 1318.667 283.667 c +f +*U +0.000 0.416 0.416 0.584 k +*u +1397.333 283.333 m +1397.278 283.278 1397.222 282.222 1397.667 282.667 c +1397.722 282.722 1397.778 283.778 1397.333 283.333 c +f +*U +0.000 0.000 0.000 0.584 k +*u +1487 284 m +1488 283 l +1487 284 l +f +*U +0.000 0.000 0.000 0.773 k +*u +586 283 m +587 282 l +586 283 l +f +*U +0.000 0.000 0.000 0.184 k +*u +818.333 282.333 m +818.278 282.278 818.222 281.222 818.667 281.667 c +818.722 281.722 818.778 282.778 818.333 282.333 c +f +*U +0.000 0.000 0.000 0.788 k +*u +915 283 m +916 282 l +915 283 l +f +*U +0.000 0.733 0.624 0.251 k +*u +1051 283 m +1052.769 282.221 1054 282 1056 282 c +1054.231 282.779 1052.964 282.912 1051 283 c +f +*U +0.000 0.698 0.514 0.290 k +*u +1136.667 282.667 m +1136.222 282.222 1137.278 282.278 1137.333 282.333 c +1137.778 282.778 1136.722 282.722 1136.667 282.667 c +f +*U +0.000 0.216 0.216 0.318 k +*u +1140 283 m +1141 282 l +1140 283 l +f +*U +0.000 0.659 0.545 0.341 k +*u +1160 283 m +1161.506 282.317 1162.315 282.174 1164 282 c +1162.494 282.683 1161.685 282.826 1160 283 c +f +*U +0.000 0.200 0.125 0.494 k +*u +1164 283 m +1165 282 l +1164 283 l +f +*U +0.039 0.000 0.012 0.231 k +*u +1215.333 282.333 m +1215.278 282.278 1215.222 281.222 1215.667 281.667 c +1215.723 281.723 1215.777 282.777 1215.333 282.333 c +f +*U +0.000 0.655 0.455 0.173 k +*u +1299.667 282.667 m +1299.222 282.222 1300.278 282.278 1300.333 282.333 c +1300.778 282.778 1299.722 282.722 1299.667 282.667 c +f +*U +0.000 0.561 0.416 0.439 k +*u +1301 283 m +1302.248 282.315 1302.548 282.251 1304 282 c +1302.752 282.685 1302.451 282.749 1301 283 c +f +*U +0.000 0.714 0.533 0.286 k +*u +1304 283 m +1305.248 282.315 1305.548 282.251 1307 282 c +1305.752 282.685 1305.452 282.749 1304 283 c +f +*U +0.000 0.000 0.000 0.118 k +*u +1489 283 m +1493.467 279 1499.361 275.785 1505 274 c +1500.973 278.359 1494.838 281.874 1489 283 c +f +*U +0.000 0.000 0.000 0.200 k +*u +1728 283 m +1729 282 l +1728 283 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1729 283 m +1730 282 l +1729 283 l +f +*U +0.000 0.000 0.000 0.149 k +*u +1752 283 m +1753.223 281.805 1753.420 281.684 1755 281 c +1753.777 282.195 1753.580 282.316 1752 283 c +f +*U +0.000 0.361 0.282 0.275 k +*u +1051.667 281.667 m +1051.222 281.222 1052.278 281.278 1052.333 281.333 c +1052.778 281.778 1051.722 281.722 1051.667 281.667 c +f +*U +0.000 0.247 0.204 0.267 k +*u +1053 282 m +1060 278.996 1071.256 281 1079 281 c +1137 281 l +1129.841 284 1118.744 282 1111 282 c +1053 282 l +f +*U +0.000 0.498 0.380 0.286 k +*u +1137.667 281.667 m +1137.222 281.222 1138.278 281.278 1138.333 281.333 c +1138.778 281.778 1137.722 281.722 1137.667 281.667 c +f +*U +0.000 0.314 0.247 0.173 k +*u +1139 282 m +1140 281 l +1139 282 l +f +*U +0.000 0.451 0.310 0.282 k +*u +1152 282 m +1153.249 281.315 1153.548 281.251 1155 281 c +1153.752 281.685 1153.452 281.749 1152 282 c +f +*U +0.000 0.498 0.380 0.043 k +*u +1155 282 m +1157.332 281 1159.457 281 1162 281 c +1159.669 281.984 1157.543 281.981 1155 282 c +f +*U +0.000 0.443 0.314 0.227 k +*u +1162 282 m +1163.249 281.315 1163.548 281.251 1165 281 c +1163.752 281.685 1163.452 281.749 1162 282 c +f +*U +0.000 0.404 0.286 0.302 k +*u +1216.667 281.667 m +1216.222 281.222 1217.278 281.278 1217.333 281.333 c +1217.778 281.778 1216.722 281.722 1216.667 281.667 c +f +*U +0.000 0.392 0.298 0.208 k +*u +1218 282 m +1219.769 281.221 1221 281 1223 281 c +1221.231 281.779 1219.964 281.912 1218 282 c +f +*U +0.000 0.247 0.204 0.267 k +*u +1223 282 m +1229.678 279.198 1239.784 281 1247 281 c +1299 281 l +1292.322 283.802 1282.216 282 1275 282 c +1223 282 l +f +*U +0.000 0.294 0.239 0.165 k +*u +1304.667 281.667 m +1304.222 281.222 1305.278 281.278 1305.333 281.333 c +1305.778 281.778 1304.722 281.722 1304.667 281.667 c +f +*U +0.000 0.396 0.302 0.337 k +*u +1306.667 281.667 m +1306.222 281.222 1307.278 281.278 1307.333 281.333 c +1307.778 281.778 1306.722 281.722 1306.667 281.667 c +f +*U +0.000 0.380 0.294 0.149 k +*u +1308 282 m +1309.506 281.317 1310.315 281.174 1312 281 c +1310.494 281.683 1309.685 281.826 1308 282 c +f +*U +0.000 0.275 0.200 0.396 k +*u +1312 282 m +1313 281 l +1312 282 l +f +*U +0.000 0.247 0.204 0.267 k +*u +1313 282 m +1320 278.996 1331.256 281 1339 281 c +1398 281 l +1390.841 284 1379.744 282 1372 282 c +1313 282 l +f +*U +0.000 0.000 0.000 0.737 k +*u +1463 282 m +1464 281 l +1463 282 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1730 282 m +1731 281 l +1730 282 l +f +*U +0.000 0.000 0.000 0.071 k +*u +1905 282 m +1904 280.521 1904 280.797 1904 279 c +1905.289 280.443 1905.401 280.234 1905 282 c +f +*U +0.000 0.000 0.000 0.749 k +*u +1906 282 m +1907 281 l +1906 282 l +f +*U +0.000 0.000 0.000 0.561 k +*u +615 281 m +616 280 l +615 281 l +f +*U +0.000 0.000 0.000 0.200 k +*u +817.333 280.333 m +817.278 280.278 817.222 279.222 817.667 279.667 c +817.722 279.722 817.778 280.778 817.333 280.333 c +f +*U +0.000 0.000 0.000 0.000 k +*u +818 281 m +819 280 l +818 281 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1492 281 m +1493 280 l +1492 281 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1730 281 m +1731.624 278.956 1732.643 278 1735 277 c +1733.376 279 1732.357 279.896 1730 281 c +f +*U +0.000 0.000 0.000 0.612 k +*u +1754 281 m +1755 280 l +1754 281 l +f +*U +0.000 0.000 0.000 0.082 k +*u +1755 281 m +1756.450 279.392 1757 278.936 1759 278 c +1757.550 279.608 1756.949 280 1755 281 c +f +*U +0.000 0.000 0.000 0.729 k +*u +590 280 m +591 279 l +590 280 l +f +*U +0.000 0.000 0.000 0.000 k +*u +615 280 m +616 279 l +615 280 l +f +*U +0.000 0.000 0.000 0.776 k +*u +917 280 m +918 279 l +917 280 l +f +*U +0.000 0.000 0.000 0.125 k +*u +918 280 m +919 277 920.414 274.618 922 272 c +922.576 275.534 920.603 277.762 918 280 c +f +*U +0.000 0.000 0.000 0.796 k +*u +2001 280 m +2002 279 l +2001 280 l +f +*U +0.000 0.000 0.000 0.137 k +*u +2002.333 279.333 m +2002.278 279.278 2002.222 278.222 2002.667 278.667 c +2002.723 278.723 2002.777 279.777 2002.333 279.333 c +f +*U +0.000 0.000 0.000 0.341 k +*u +590 279 m +591 278 l +590 279 l +f +*U +0.000 0.000 0.000 0.576 k +*u +591 279 m +592 278 l +591 279 l +f +*U +0.000 0.000 0.000 0.133 k +*u +816 279 m +814.602 276.950 813.749 275.354 813 273 c +815 274.908 816.250 276.208 816 279 c +f +*U +0.000 0.000 0.000 0.773 k +*u +1468 279 m +1469 278 l +1468 279 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1904 279 m +1905 278 l +1904 279 l +f +*U +0.000 0.000 0.000 0.063 k +*u +591 278 m +594 273 l +599 272 l +596.681 274.841 594.378 276.568 591 278 c +f +*U +0.000 0.000 0.000 0.694 k +*u +616.333 277.333 m +616.278 277.278 616.222 276.222 616.667 276.667 c +616.722 276.722 616.778 277.778 616.333 277.333 c +f +*U +0.000 0.000 0.000 0.075 k +*u +1468 278 m +1469.543 276.733 1470 276.511 1472 276 c +1470.542 277 1469.752 277.436 1468 278 c +f +*U +0.000 0.000 0.000 0.702 k +*u +1735 278 m +1736 277 l +1735 278 l +f +*U +0.000 0.000 0.000 0.639 k +*u +1758 278 m +1759 277 l +1758 278 l +f +*U +0.000 0.000 0.000 0.671 k +*u +919 277 m +920 276 l +919 277 l +f +*U +0.000 0.000 0.000 0.706 k +*u +1499 277 m +1500 276 l +1499 277 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1760 277 m +1761.223 275.805 1761.420 275.684 1763 275 c +1761.777 276.195 1761.580 276.316 1760 277 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1903 277 m +1904 276 l +1903 277 l +f +*U +0.000 0.000 0.000 0.655 k +*u +2003 277 m +2004 276 l +2003 277 l +f +*U +0.000 0.000 0.000 0.051 k +*u +2004 277 m +2004.547 275 2005 273.745 2006 272 c +2006.710 274.531 2006 275.516 2004 277 c +f +*U +0.000 0.000 0.000 0.753 k +*u +595 276 m +596 275 l +595 276 l +f +*U +0.000 0.000 0.000 0.745 k +*u +815 276 m +816 275 l +815 276 l +f +*U +0.000 0.000 0.000 0.749 k +*u +834 276 m +835 275 l +834 276 l +f +*U +0.000 0.000 0.000 0.129 k +*u +833 272 m +840.188 275 848.323 274 856 274 c +898 274 l +893.280 275.981 887 275 882 275 c +849 275 l +843.679 275 835.945 277.210 833 272 c +f +*U +0.000 0.000 0.000 0.784 k +*u +899 276 m +900 275 l +899 276 l +f +*U +0.000 0.000 0.000 0.184 k +*u +1471.667 275.667 m +1471.222 275.222 1472.278 275.278 1472.333 275.333 c +1472.778 275.778 1471.722 275.722 1471.667 275.667 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1473 276 m +1474 275 l +1473 276 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1736 276 m +1738.719 272.223 1741.644 269.688 1746 268 c +1743.264 271.575 1740 274 1736 276 c +f +*U +0.000 0.000 0.000 0.000 k +*u +259.333 274.333 m +259.278 274.278 259.222 273.222 259.667 273.667 c +259.722 273.722 259.778 274.778 259.333 274.333 c +f +*U +0.000 0.000 0.000 0.114 k +*u +899 275 m +899.684 273.420 899.805 273.223 901 272 c +900.316 273.580 900.195 273.777 899 275 c +f +1473 275 m +1474.717 273 1475.566 272.651 1478 272 c +1476.313 273.656 1475.254 274.251 1473 275 c +f +*U +0.000 0.000 0.000 0.737 k +*u +1762 275 m +1763 274 l +1762 275 l +f +*U +0.000 0.000 0.000 0.106 k +*u +1763 275 m +1768.354 268.424 1778.192 261.301 1786 258 c +1780.827 264.785 1771 272.274 1763 275 c +f +*U +0.000 0.000 0.000 0.831 k +*u +1920 275 m +1921 274 l +1920 275 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1920 272 m +1933.679 275.257 1949.965 273 1964 273 c +1969.259 273 1976.967 274.410 1981.895 272.397 c +1985.436 270.950 1987 266.437 1990 264 c +1989 267 1987.593 271 1984.621 272.972 c +1981 275 1974.935 274 1971 274 c +1939 274 l +1934 274 1923 276.201 1920 272 c +f +*U +0.000 0.000 0.000 0.000 k +*u +1922 275 m +1927.708 272.605 1935.846 274 1942 274 c +1984 274 l +1978.293 276.395 1970 275 1964 275 c +1922 275 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1984 275 m +1985 274 l +1984 275 l +f +*U +0.000 0.000 0.000 0.698 k +*u +1504 274 m +1505 273 l +1504 274 l +f +*U +0.000 0.000 0.000 0.290 k +*u +1505 274 m +1506 273 l +1505 274 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1655.333 273.333 m +1655.278 273.278 1655.222 272.222 1655.667 272.667 c +1655.722 272.722 1655.777 273.778 1655.333 273.333 c +f +*U +0.000 0.000 0.000 0.741 k +*u +1901 274 m +1902 273 l +1901 274 l +f +*U +0.000 0.000 0.000 0.784 k +*u +599 273 m +600 272 l +599 273 l +f +*U +0.000 0.000 0.000 0.063 k +*u +812 273 m +810.652 271.232 809.878 270 809 268 c +811.343 269.347 812.401 270.259 812 273 c +f +*U +0.000 0.000 0.000 0.631 k +*u +813 273 m +814 272 l +813 273 l +f +*U +0.000 0.000 0.000 0.808 k +*u +832 273 m +833 272 l +832 273 l +f +*U +0.000 0.000 0.000 0.604 k +*u +1506 273 m +1507 272 l +1506 273 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1507 273 m +1508.223 271.805 1508.420 271.684 1510 271 c +1508.777 272.195 1508.580 272.316 1507 273 c +f +*U +0.000 0.000 0.000 0.722 k +*u +1741 273 m +1742 272 l +1741 273 l +f +*U +0.000 0.000 0.000 0.784 k +*u +1919 273 m +1920 272 l +1919 273 l +f +*U +0.000 0.000 0.000 0.161 k +*u +806 272 m +806 268 l +806.710 269.760 806.710 270.241 806 272 c +f +*U +0.000 0.000 0.000 0.114 k +*u +832 272 m +831 270.255 830.547 268.875 830 267 c +831.693 268.782 832.375 269.581 832 272 c +f +*U +0.000 0.000 0.000 0.196 k +*u +901.333 271.333 m +901.278 271.278 901.222 270.222 901.667 270.667 c +901.722 270.722 901.778 271.778 901.333 271.333 c +f +*U +0.000 0.000 0.000 0.753 k +*u +1766 272 m +1767 271 l +1766 272 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1919 272 m +1918 270.522 1918 270.797 1918 269 c +1919.290 270.443 1919.401 270.233 1919 272 c +f +*U +0.000 0.000 0.000 0.110 k +*u +2007 272 m +2008.460 268 2010.660 264.537 2013 261 c +2013.886 265.544 2010.329 269.281 2007 272 c +f +*U +0.000 0.000 0.000 0.141 k +*u +169 271 m +175.919 268 186.520 270 194 270 c +249 270 l +242 272.903 231.480 271 224 271 c +169 271 l +f +*U +0.000 0.000 0.000 0.153 k +*u +280 271 m +285.951 268.503 294.580 270 301 270 c +345 270 l +339 272.497 330.420 271 324 271 c +280 271 l +f +*U +0.000 0.000 0.000 0.161 k +*u +600 271 m +601.223 269.805 601.420 269.684 603 269 c +601.777 270.195 601.580 270.316 600 271 c +f +*U +0.000 0.000 0.000 0.710 k +*u +902 271 m +903 270 l +902 271 l +f +*U +0.000 0.000 0.000 0.102 k +*u +924 271 m +924.777 268.511 925.817 266.328 927 264 c +927.728 267 926.256 268.853 924 271 c +f +*U +0.000 0.000 0.000 0.153 k +*u +958 271 m +964.436 268.299 974 270 981 270 c +1032 270 l +1025.564 272.701 1015.951 271 1009 271 c +958 271 l +f +*U +0.000 0.000 0.000 0.325 k +*u +1032 271 m +1033 270 l +1032 271 l +f +*U +0.000 0.306 0.227 0.243 k +*u +1052 271 m +1052 268 l +1053 269 1053.309 269.612 1054 271 c +1052 271 l +f +*U +0.000 0.478 0.349 0.161 k +*u +1054 271 m +1061 267.996 1072.256 270 1080 270 c +1138 270 l +1130.841 273 1119.744 271 1112 271 c +1054 271 l +f +*U +0.000 0.051 0.043 0.286 k +*u +1141 271 m +1142 270 l +1141 271 l +f +*U +0.000 0.318 0.220 0.455 k +*u +1142 271 m +1143 270 l +1142 271 l +f +*U +0.000 0.263 0.184 0.153 k +*u +1143 271 m +1144 270 l +1143 271 l +f +*U +0.000 0.478 0.349 0.161 k +*u +1147 271 m +1154.649 267.790 1166.712 270 1175 270 c +1167.351 273.210 1155.288 271 1147 271 c +f +*U +0.000 0.435 0.314 0.361 k +*u +1175 271 m +1176 270 l +1175 271 l +f +*U +0.000 0.247 0.212 0.227 k +*u +1195 271 m +1196.248 270.315 1196.548 270.251 1198 270 c +1196.752 270.685 1196.451 270.749 1195 271 c +f +*U +0.000 0.478 0.349 0.161 k +*u +1198 271 m +1204.194 268.401 1213.314 270 1220 270 c +1268 270 l +1261.806 272.599 1252.686 271 1246 271 c +1198 271 l +f +*U +0.000 0.416 0.247 0.298 k +*u +1268 271 m +1269.769 270.221 1271 270 1273 270 c +1271.231 270.779 1269.964 270.912 1268 271 c +f +*U +0.000 0.192 0.114 0.188 k +*u +1273.333 270.333 m +1273.278 270.278 1273.222 269.222 1273.667 269.667 c +1273.723 269.723 1273.777 270.777 1273.333 270.333 c +f +*U +0.000 0.298 0.231 0.106 k +*u +1278 271 m +1279 270 l +1278 271 l +f +*U +0.000 0.471 0.341 0.169 k +*u +1279 271 m +1284.715 268.602 1292.831 270 1299 270 c +1293.285 272.398 1285.169 271 1279 271 c +f +*U +0.000 0.278 0.196 0.098 k +*u +1299 271 m +1300 270 l +1299 271 l +f +*U +0.000 0.282 0.192 0.075 k +*u +1307.667 270.667 m +1307.222 270.222 1308.278 270.278 1308.333 270.333 c +1308.778 270.778 1307.722 270.722 1307.667 270.667 c +f +*U +0.000 0.467 0.318 0.275 k +*u +1309 271 m +1310.249 270.315 1310.548 270.251 1312 270 c +1310.752 270.685 1310.452 270.749 1309 271 c +f +*U +0.000 0.153 0.098 0.106 k +*u +1312 271 m +1313 270 l +1312 271 l +f +*U +0.000 0.216 0.165 0.161 k +*u +1316 271 m +1317 270 l +1316 271 l +f +*U +0.000 0.310 0.235 0.286 k +*u +1317 271 m +1318.506 270.317 1319.315 270.174 1321 270 c +1319.494 270.683 1318.685 270.826 1317 271 c +f +*U +0.000 0.478 0.349 0.161 k +*u +1321 271 m +1327.436 268.299 1337 270 1344 270 c +1393 270 l +1386.564 272.701 1376.951 271 1370 271 c +1321 271 l +f +*U +0.000 0.408 0.314 0.129 k +*u +1393 271 m +1396 268 l +1396.951 270.507 1395.348 270.706 1393 271 c +f +*U +0.000 0.000 0.000 0.545 k +*u +1481 271 m +1482 270 l +1481 271 l +f +*U +0.000 0.000 0.000 0.804 k +*u +1509 271 m +1510 270 l +1509 271 l +f +*U +0.000 0.000 0.000 0.141 k +*u +1510.667 270.667 m +1510.222 270.222 1511.278 270.278 1511.333 270.333 c +1511.778 270.778 1510.722 270.722 1510.667 270.667 c +f +*U +0.000 0.000 0.000 0.612 k +*u +169 270 m +175.919 267 186.520 269 194 269 c +249 269 l +242 271.903 231.480 270 224 270 c +169 270 l +f +*U +0.000 0.000 0.000 0.851 k +*u +280 270 m +285.951 267.503 294.580 269 301 269 c +345 269 l +339 271.497 330.420 270 324 270 c +280 270 l +f +721 270 m +726.951 267.503 735.580 269 742 269 c +786 269 l +780 271.497 771.420 270 765 270 c +721 270 l +f +*U +0.000 0.000 0.000 0.239 k +*u +902 270 m +903 269 l +902 270 l +f +*U +0.000 0.000 0.000 0.851 k +*u +958 270 m +964.678 267.198 974.784 269 982 269 c +1033 269 l +1026.564 271.701 1016.951 270 1010 270 c +958 270 l +f +*U +0.000 0.000 0.000 0.086 k +*u +1033 270 m +1033 254 l +1036 258.484 1035 264.749 1035 270 c +1033 270 l +f +*U +0.000 0.859 0.616 0.133 k +*u +1053 270 m +1053.482 267.636 1053.636 267.482 1056 267 c +1055.198 263.829 1055.599 261.232 1056 258 c +1136 258 l +1135 262.609 1135.960 265.571 1137 270 c +1053 270 l +f +*U +0.000 0.459 0.345 0.541 k +*u +1137.333 269.333 m +1137.278 269.278 1137.222 268.222 1137.667 268.667 c +1137.722 268.722 1137.777 269.778 1137.333 269.333 c +f +*U +0.000 0.102 0.086 0.184 k +*u +1138 270 m +1139 269 l +1138 270 l +f +*U +0.000 0.271 0.176 0.196 k +*u +1141.333 269.333 m +1141.278 269.278 1141.222 268.222 1141.667 268.667 c +1141.722 268.722 1141.777 269.778 1141.333 269.333 c +f +*U +0.000 0.612 0.408 0.353 k +*u +1142 270 m +1142 266 l +1143 267.458 1143.436 268.248 1144 270 c +1142 270 l +f +*U +0.000 0.655 0.549 0.345 k +*u +1147 270 m +1147 263 l +1148 265.534 1148 267.466 1147 270 c +f +*U +0.000 0.878 0.620 0.122 k +*u +1148 270 m +1148 267 1147.474 263 1149.742 260.742 c +1151.802 258.683 1155.340 259 1158 258.715 c +1166.621 257.652 1175.319 258 1184 258 c +1180.970 262.517 1177 264.215 1176 270 c +1148 270 l +f +*U +0.000 0.122 0.086 0.188 k +*u +1176 270 m +1177 269 l +1176 270 l +f +*U +0.000 0.404 0.306 0.294 k +*u +1194 270 m +1195 269 l +1194 270 l +f +*U +0.000 0.812 0.655 0.188 k +*u +1194 266 m +1198 269 l +1195.251 269.603 1194.500 268.638 1194 266 c +f +*U +0.000 0.886 0.639 0.114 k +*u +1192 258 m +1264 258 l +1261 263.656 1266.715 265 1270 269 c +1252.776 268 1235.258 269 1218 269 c +1212.485 269 1202 271 1197.228 268.651 c +1193.931 267 1192.774 261.285 1192 258 c +f +*U +0.000 0.839 0.616 0.161 k +*u +1199 270 m +1205.194 267.401 1214.314 269 1221 269 c +1255 269 l +1260.628 269.000 1266.457 268 1272 269 c +1265.564 271.701 1255.951 270 1249 270 c +1199 270 l +f +*U +0.000 0.451 0.294 0.549 k +*u +1272 270 m +1273 269 l +1272 270 l +f +*U +0.000 0.235 0.176 0.114 k +*u +1276 270 m +1277 269 l +1276 270 l +f +*U +0.000 0.718 0.518 0.282 k +*u +1271 260 m +1275.314 262 1276.665 265.876 1280 269 c +1275.894 269.917 1273 263 1271 260 c +f +*U +0.000 0.855 0.604 0.141 k +*u +1271 258 m +1278.564 258 1286.480 257.330 1294 258.174 c +1297.428 258.559 1300.468 260.538 1303.830 260.860 c +1306.956 261 1309.747 259.775 1312.986 260.484 c +1317.567 261.486 1319 267 1323 267.687 c +1329 268.499 1336.776 267 1343 267 c +1392 267 l +1386.293 269.395 1378 268 1372 268 c +1328 268 l +1335 270 1343.573 269 1351 269 c +1395 269 l +1389 271.497 1380.420 270 1374 270 c +1327 270 l +1321.541 270.000 1308.956 271.874 1307 266 c +1304.706 266.303 1303.788 266.579 1302 268 c +1299 267 l +1298 271.221 1293.654 270 1290 270 c +1286.941 270 1282.926 270.656 1280 269.500 c +1276.675 268 1272.924 261 1271 258 c +f +*U +0.000 0.647 0.443 0.333 k +*u +1299 270 m +1299.406 267.907 1299.216 267.980 1301 267 c +1300.309 268.388 1300 268.861 1299 270 c +f +*U +0.000 0.455 0.322 0.353 k +*u +1306.333 269.333 m +1306.278 269.278 1306.222 268.222 1306.667 268.667 c +1306.722 268.722 1306.777 269.778 1306.333 269.333 c +f +*U +0.000 0.361 0.337 0.639 k +*u +1307 270 m +1308 269 l +1307 270 l +f +*U +0.000 0.714 0.553 0.286 k +*u +1312 270 m +1313.769 269.221 1315 269 1317 269 c +1315.231 269.779 1313.964 269.912 1312 270 c +f +*U +0.000 0.702 0.525 0.298 k +*u +1395 270 m +1395 266 l +1395.710 267.759 1395.710 268.241 1395 270 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1511 270 m +1512 269 l +1511 270 l +f +*U +0.000 0.000 0.000 0.157 k +*u +1514.333 269.333 m +1514.278 269.278 1514.222 268.222 1514.667 268.667 c +1514.722 268.722 1514.777 269.778 1514.333 269.333 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1539 270 m +1540 269 l +1539 270 l +f +*U +0.000 0.000 0.000 0.824 k +*u +1917 270 m +1918 269 l +1917 270 l +f +*U +0.000 0.000 0.000 0.698 k +*u +1987 270 m +1988 269 l +1987 270 l +f +*U +0.000 0.000 0.000 0.518 k +*u +364 269 m +365 268 l +364 269 l +f +*U +0.000 0.000 0.000 0.604 k +*u +604 269 m +605 268 l +604 269 l +f +*U +0.000 0.000 0.000 0.549 k +*u +805 269 m +806 268 l +805 269 l +f +*U +0.000 0.000 0.000 0.157 k +*u +903.333 268.333 m +903.278 268.278 903.222 267.222 903.667 267.667 c +903.722 267.722 903.778 268.778 903.333 268.333 c +f +*U +0.000 0.243 0.169 0.553 k +*u +1176 269 m +1177 268 l +1176 269 l +f +*U +0.000 0.361 0.271 0.239 k +*u +1193 269 m +1194 268 l +1193 269 l +f +*U +0.000 0.600 0.576 0.400 k +*u +1271 269 m +1272 268 l +1271 269 l +f +*U +0.000 0.294 0.169 0.071 k +*u +1272 269 m +1273 268 l +1272 269 l +f +*U +0.000 0.255 0.176 0.114 k +*u +1275.333 268.333 m +1275.278 268.278 1275.222 267.222 1275.667 267.667 c +1275.722 267.722 1275.778 268.778 1275.333 268.333 c +f +*U +0.000 0.302 0.224 0.153 k +*u +1300 269 m +1301 268 l +1300 269 l +f +*U +0.000 0.596 0.447 0.345 k +*u +1321 269 m +1322.248 268.315 1322.548 268.251 1324 268 c +1322.752 268.685 1322.451 268.749 1321 269 c +f +*U +0.000 0.859 0.616 0.133 k +*u +1328 269 m +1333.707 266.605 1341.846 268 1348 268 c +1392 268 l +1384.848 265.886 1376.427 267 1369 267 c +1327 267 l +1329 257.518 1336.680 258 1345 258 c +1361 257.994 1377 258.956 1393 259 c +1393.655 261.537 1394.276 263 1396 265 c +1395 269 l +1328 269 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1483 269 m +1484.223 267.805 1484.420 267.684 1486 267 c +1484.777 268.195 1484.580 268.316 1483 269 c +f +*U +0.000 0.000 0.000 0.839 k +*u +1559 269 m +1565.678 266.198 1575.784 268 1583 268 c +1636 268 l +1629.322 270.802 1619.216 269 1612 269 c +1559 269 l +f +*U +0.000 0.000 0.000 0.620 k +*u +1818 269 m +1824.678 266.198 1834.784 268 1842 268 c +1896 268 l +1889.322 270.802 1879.216 269 1872 269 c +1818 269 l +f +*U +0.000 0.000 0.000 0.259 k +*u +1896 269 m +1896 266 l +1896.696 267.554 1896.696 267.446 1896 269 c +f +*U +0.000 0.000 0.000 0.141 k +*u +1917.333 268.333 m +1917.278 268.278 1917.222 267.222 1917.667 267.667 c +1917.722 267.723 1917.777 268.778 1917.333 268.333 c +f +*U +0.000 0.000 0.000 0.702 k +*u +2008 269 m +2009 268 l +2008 269 l +f +*U +0.000 0.000 0.000 0.506 k +*u +260 268 m +261 267 l +260 268 l +f +*U +0.000 0.000 0.000 0.157 k +*u +604.667 267.667 m +604.222 267.222 605.278 267.278 605.333 267.333 c +605.778 267.778 604.722 267.722 604.667 267.667 c +f +*U +0.000 0.000 0.000 0.533 k +*u +701 268 m +702 267 l +701 268 l +f +*U +0.000 0.000 0.000 0.059 k +*u +805 268 m +804.719 264.256 803.789 262.510 801 260 c +801 258 l +802 257 l +804 257 l +806.226 260.710 806.484 263.797 807 268 c +805 268 l +f +*U +0.000 0.000 0.000 0.137 k +*u +809 268 m +808 266.521 808 266.797 808 265 c +809.289 266.443 809.401 266.234 809 268 c +f +*U +0.000 0.000 0.000 0.769 k +*u +810 268 m +811 267 l +810 268 l +f +*U +0.000 0.000 0.000 0.749 k +*u +829 268 m +830 267 l +829 268 l +f +*U +0.000 0.306 0.216 0.000 k +*u +1052 268 m +1053 267 l +1052 268 l +f +*U +0.000 0.275 0.200 0.243 k +*u +1137 268 m +1138 267 l +1137 268 l +f +*U +0.000 0.247 0.165 0.039 k +*u +1141 268 m +1142 267 l +1141 268 l +f +*U +0.000 0.059 0.031 0.592 k +*u +1143 268 m +1142 265 l +1143.766 265.979 1143.956 266.222 1143 268 c +f +*U +0.000 0.553 0.420 0.447 k +*u +1176.333 267.333 m +1176.278 267.278 1176.222 266.222 1176.667 266.667 c +1176.722 266.722 1176.777 267.778 1176.333 267.333 c +f +*U +0.000 0.380 0.314 0.463 k +*u +1268 266 m +1269.580 266.683 1269.777 266.805 1271 268 c +1269.420 267.316 1269.223 267.195 1268 266 c +f +*U +0.000 0.380 0.290 0.020 k +*u +1271 268 m +1272 267 l +1271 268 l +f +*U +0.000 0.302 0.231 0.149 k +*u +1305 268 m +1306 267 l +1305 268 l +f +*U +0.000 0.690 0.529 0.310 k +*u +1306 268 m +1305 266 l +1307 266 l +1307 267.853 1307.300 267.350 1306 268 c +f +*U +0.000 0.463 0.286 0.212 k +*u +1320 268 m +1321 267 l +1320 268 l +f +*U +0.000 0.133 0.141 0.267 k +*u +1321 268 m +1322.248 267.315 1322.548 267.251 1324 267 c +1322.752 267.685 1322.451 267.749 1321 268 c +f +*U +0.000 0.463 0.376 0.298 k +*u +1324 268 m +1325 267 l +1324 268 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1486 268 m +1487 267 l +1486 268 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1515 268 m +1517.487 265.868 1519.809 264.732 1523 264 c +1520.973 266.754 1518.313 267.426 1515 268 c +f +*U +0.000 0.000 0.000 0.714 k +*u +1747 268 m +1748 267 l +1747 268 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1916 268 m +1917 267 l +1916 268 l +f +*U +0.000 0.000 0.000 0.243 k +*u +829 267 m +830 266 l +829 267 l +f +*U +0.000 0.000 0.000 0.149 k +*u +904 267 m +904.547 265 905 263.745 906 262 c +906.375 264.419 905.693 265.218 904 267 c +f +*U +0.000 0.443 0.341 0.557 k +*u +1053 267 m +1053 264 l +1053.696 265.554 1053.696 265.446 1053 267 c +f +*U +0.000 0.671 0.482 0.329 k +*u +1054 267 m +1054 263.831 1054 261 1055 258 c +1056 260.847 1055.515 263.968 1056 267 c +1054 267 l +f +*U +0.000 0.722 0.557 0.278 k +*u +1135 267 m +1135 264 1135.190 261.729 1136 259 c +1136.668 261.787 1136.172 264.387 1135 267 c +f +*U +0.000 0.267 0.173 0.329 k +*u +1136 267 m +1137 266 l +1136 267 l +f +*U +0.000 0.345 0.235 0.055 k +*u +1177 267 m +1178 266 l +1177 267 l +f +*U +0.000 0.518 0.396 0.482 k +*u +1193.333 266.333 m +1193.278 266.278 1193.222 265.222 1193.667 265.667 c +1193.722 265.723 1193.777 266.778 1193.333 266.333 c +f +*U +0.000 0.365 0.267 0.549 k +*u +1302.667 266.667 m +1302.222 266.222 1303.278 266.278 1303.333 266.333 c +1303.778 266.778 1302.722 266.722 1302.667 266.667 c +f +*U +0.000 0.620 0.455 0.125 k +*u +1304 267 m +1305 266 l +1304 267 l +f +*U +0.000 0.329 0.271 0.212 k +*u +1325 267 m +1326 266 l +1325 267 l +f +*U +0.000 0.592 0.424 0.337 k +*u +1326 267 m +1326.406 264.908 1326.217 264.980 1328 264 c +1327.309 265.388 1327 265.861 1326 267 c +f +*U +0.000 0.000 0.000 0.133 k +*u +1486 267 m +1488.856 263.887 1491.878 261.969 1496 261 c +1493 263.952 1489.915 265.760 1486 267 c +f +*U +0.000 0.000 0.000 0.145 k +*u +1539 267 m +1540.965 254.625 1552.471 253 1563 253 c +1639 253 l +1633 255.497 1624.420 254 1618 254 c +1572 254 l +1564.251 254 1555 253 1548 257 c +1543.848 259.472 1541.841 263.404 1539 267 c +f +*U +0.000 0.000 0.000 0.682 k +*u +1654 267 m +1655 266 l +1654 267 l +f +*U +0.000 0.000 0.000 0.122 k +*u +1747 267 m +1748.624 264.956 1749.643 264 1752 263 c +1750.376 265 1749.357 265.896 1747 267 c +f +*U +0.000 0.000 0.000 0.706 k +*u +1773 267 m +1774 266 l +1773 267 l +f +*U +0.000 0.000 0.000 0.714 k +*u +1895 267 m +1896 266 l +1895 267 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1916 267 m +1915 265.521 1915 265.797 1915 264 c +1916.290 265.443 1916.401 265.233 1916 267 c +f +*U +0.000 0.000 0.000 0.996 k +*u +349 266 m +344.829 263.722 338.732 264.490 334 264.200 c +321 263.407 307.943 263.938 295 264 c +288.649 264 282.729 265.499 277 262 c +278.248 261.315 278.548 261.251 280 261 c +281.294 253.546 292.180 256 298 256 c +316.570 256 335.671 254.595 354 258 c +352.376 261.247 350.610 264.439 351 266 c +349 266 l +f +*U +0.000 0.000 0.000 0.741 k +*u +363 266 m +364 265 l +363 266 l +f +*U +0.000 0.000 0.000 0.706 k +*u +608 266 m +609 265 l +608 266 l +f +*U +0.000 0.000 0.000 0.737 k +*u +804 266 m +805 265 l +804 266 l +f +*U +0.000 0.000 0.000 0.675 k +*u +926 266 m +927 265 l +926 266 l +f +*U +0.000 0.455 0.310 0.365 k +*u +1177 266 m +1178 265 l +1177 266 l +f +*U +0.000 0.463 0.302 0.443 k +*u +1266.667 265.667 m +1266.222 265.222 1267.278 265.278 1267.333 265.333 c +1267.778 265.778 1266.722 265.722 1266.667 265.667 c +f +*U +0.000 0.275 0.224 0.247 k +*u +1268 266 m +1269 265 l +1268 266 l +f +*U +0.000 0.369 0.263 0.314 k +*u +1275 266 m +1276 265 l +1275 266 l +f +*U +0.000 0.000 0.000 0.745 k +*u +1518 266 m +1519 265 l +1518 266 l +f +*U +0.000 0.000 0.000 0.749 k +*u +1540 266 m +1541 265 l +1540 266 l +f +*U +0.000 0.000 0.000 0.239 k +*u +1895.333 265.333 m +1895.278 265.278 1895.222 264.222 1895.667 264.667 c +1895.722 264.722 1895.777 265.778 1895.333 265.333 c +f +*U +0.000 0.000 0.000 0.643 k +*u +1896 266 m +1897 265 l +1896 266 l +f +*U +0.000 0.000 0.000 0.745 k +*u +261 265 m +262 264 l +261 265 l +f +*U +0.000 0.000 0.000 0.133 k +*u +608 265 m +609.223 263.805 609.420 263.684 611 263 c +609.777 264.195 609.580 264.316 608 265 c +f +*U +0.000 0.000 0.000 0.678 k +*u +702 265 m +703 264 l +702 265 l +f +*U +0.000 0.000 0.000 0.157 k +*u +804 265 m +803 261 l +804.303 262.668 804.553 262.992 804 265 c +f +*U +0.000 0.000 0.000 0.690 k +*u +808 265 m +809 264 l +808 265 l +f +*U +0.004 0.027 0.000 0.278 k +*u +1143 265 m +1144 264 l +1143 265 l +f +*U +0.000 0.447 0.337 0.553 k +*u +1177 265 m +1178 264 l +1177 265 l +f +*U +0.000 0.125 0.086 0.129 k +*u +1178 265 m +1179 264 l +1178 265 l +f +*U +0.000 0.702 0.494 0.298 k +*u +1193 265 m +1192 261 l +1193.656 262.404 1193.751 262.953 1193 265 c +f +*U +0.000 0.380 0.325 0.620 k +*u +1264.667 264.667 m +1264.222 264.222 1265.278 264.278 1265.333 264.333 c +1265.778 264.778 1264.722 264.722 1264.667 264.667 c +f +*U +0.000 0.282 0.153 0.063 k +*u +1266 265 m +1267 264 l +1266 265 l +f +*U +0.000 0.506 0.431 0.212 k +*u +1319 265 m +1320 264 l +1319 265 l +f +*U +0.000 0.675 0.475 0.325 k +*u +1394 265 m +1393 259 l +1394.654 261.177 1394.994 262.425 1394 265 c +f +*U +0.000 0.408 0.294 0.192 k +*u +1395 265 m +1396 264 l +1395 265 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1491 265 m +1492 264 l +1491 265 l +f +*U +0.000 0.000 0.000 0.549 k +*u +1894 265 m +1895 264 l +1894 265 l +f +*U +0.000 0.000 0.000 0.725 k +*u +1990 265 m +1991 264 l +1990 265 l +f +*U +0.000 0.000 0.000 0.125 k +*u +261.333 263.333 m +261.278 263.278 261.222 262.222 261.667 262.667 c +261.722 262.722 261.778 263.778 261.333 263.333 c +f +702.333 263.333 m +702.278 263.278 702.222 262.222 702.667 262.667 c +702.722 262.722 702.778 263.778 702.333 263.333 c +f +*U +0.000 0.306 0.224 0.055 k +*u +1053.333 263.333 m +1053.278 263.278 1053.222 262.222 1053.667 262.667 c +1053.722 262.722 1053.777 263.778 1053.333 263.333 c +f +*U +0.000 0.694 0.541 0.306 k +*u +1178.333 263.333 m +1178.278 263.278 1178.222 262.222 1178.667 262.667 c +1178.722 262.722 1178.777 263.778 1178.333 263.333 c +f +*U +0.000 0.494 0.341 0.000 k +*u +1192 264 m +1193 263 l +1192 264 l +f +*U +0.000 0.498 0.412 0.369 k +*u +1262 264 m +1262 260 l +1262.911 261.376 1263.404 262.440 1264 264 c +1262 264 l +f +*U +0.000 0.400 0.227 0.098 k +*u +1264 264 m +1265 263 l +1264 264 l +f +*U +0.000 0.451 0.412 0.549 k +*u +1318 264 m +1319 263 l +1318 264 l +f +*U +0.000 0.012 0.051 0.220 k +*u +1319 264 m +1320 263 l +1319 264 l +f +*U +0.000 0.196 0.129 0.094 k +*u +1326 264 m +1327 263 l +1326 264 l +f +*U +0.000 0.471 0.310 0.529 k +*u +1327.333 263.333 m +1327.278 263.278 1327.222 262.222 1327.667 262.667 c +1327.722 262.722 1327.777 263.778 1327.333 263.333 c +f +*U +0.000 0.125 0.078 0.176 k +*u +1395 264 m +1396 263 l +1395 264 l +f +*U +0.000 0.000 0.000 0.137 k +*u +1522 264 m +1524.187 261.968 1526 260.906 1529 260 c +1526.826 262.295 1525 263.273 1522 264 c +f +*U +0.000 0.000 0.000 0.804 k +*u +1653 264 m +1654 263 l +1653 264 l +f +*U +0.000 0.000 0.000 0.788 k +*u +1752 264 m +1753 263 l +1752 264 l +f +*U +0.000 0.000 0.000 0.757 k +*u +1777 264 m +1778 263 l +1777 264 l +f +*U +0.000 0.000 0.000 0.129 k +*u +1894 264 m +1895 263 l +1894 264 l +f +*U +0.000 0.000 0.000 0.173 k +*u +1914.333 263.333 m +1914.278 263.278 1914.222 262.222 1914.667 262.667 c +1914.722 262.722 1914.777 263.778 1914.333 263.333 c +f +*U +0.000 0.000 0.000 0.102 k +*u +1990 264 m +1990.651 261.566 1991 260.717 1993 259 c +1992.251 261.254 1991.656 262.314 1990 264 c +f +*U +0.000 0.000 0.000 0.631 k +*u +262 263 m +263 262 l +262 263 l +f +*U +0.000 0.000 0.000 0.137 k +*u +611 263 m +612.402 260.726 613.515 260 616 259 c +614.394 260.914 613.217 261.837 611 263 c +f +*U +0.000 0.000 0.000 0.710 k +*u +612 263 m +613 262 l +612 263 l +f +*U +0.000 0.000 0.000 0.616 k +*u +703 263 m +704 262 l +703 263 l +f +*U +0.000 0.000 0.000 0.608 k +*u +826 263 m +827 262 l +826 263 l +f +*U +0.000 0.000 0.000 0.831 k +*u +907 263 m +908 262 l +907 263 l +f +*U +0.000 0.000 0.000 0.588 k +*u +928 263 m +929 262 l +928 263 l +f +*U +0.000 0.000 0.000 0.114 k +*u +929 263 m +929 261 l +930.635 261.545 930.455 261.365 931 263 c +929 263 l +f +*U +0.000 0.263 0.165 0.086 k +*u +1147 263 m +1148 262 l +1147 263 l +f +*U +0.000 0.424 0.325 0.463 k +*u +1179 263 m +1180.248 262.315 1180.548 262.251 1182 262 c +1180.752 262.685 1180.451 262.749 1179 263 c +f +*U +0.000 0.478 0.396 0.522 k +*u +1182.333 262.333 m +1182.278 262.278 1182.222 261.222 1182.667 261.667 c +1182.722 261.722 1182.777 262.778 1182.333 262.333 c +f +*U +0.000 0.463 0.329 0.271 k +*u +1192 263 m +1193 262 l +1192 263 l +f +*U +0.000 0.333 0.259 0.431 k +*u +1318 263 m +1319 262 l +1318 263 l +f +*U +0.000 0.000 0.000 0.741 k +*u +1523 263 m +1524 262 l +1523 263 l +f +*U +0.000 0.000 0.000 0.529 k +*u +1541 263 m +1542 262 l +1541 263 l +f +*U +0.000 0.000 0.000 0.663 k +*u +1753 263 m +1754 262 l +1753 263 l +f +*U +0.000 0.000 0.000 0.176 k +*u +1893.333 262.333 m +1893.278 262.278 1893.222 261.222 1893.667 261.667 c +1893.722 261.722 1893.777 262.778 1893.333 262.333 c +f +*U +0.000 0.000 0.000 0.553 k +*u +1894 263 m +1895 262 l +1894 263 l +f +*U +0.000 0.000 0.000 0.694 k +*u +1913 263 m +1914 262 l +1913 263 l +f +*U +0.000 0.000 0.000 0.224 k +*u +262 262 m +263 261 l +262 262 l +f +*U +0.000 0.000 0.000 0.800 k +*u +263 262 m +264 261 l +263 262 l +f +*U +0.000 0.000 0.000 0.671 k +*u +361 262 m +362 261 l +361 262 l +f +*U +0.000 0.000 0.000 0.216 k +*u +703 262 m +704 261 l +703 262 l +f +*U +0.000 0.000 0.000 0.604 k +*u +802 262 m +803 261 l +802 262 l +f +*U +0.000 0.000 0.000 0.204 k +*u +826 262 m +827 261 l +826 262 l +f +*U +0.000 0.000 0.000 0.125 k +*u +907 262 m +907.651 259.566 908 258.717 910 257 c +909.251 259.254 908.656 260.314 907 262 c +f +*U +0.000 0.157 0.106 0.173 k +*u +1136 262 m +1137 261 l +1136 262 l +f +*U +0.000 0.388 0.247 0.353 k +*u +1148 262 m +1149 261 l +1148 262 l +f +*U +0.000 0.310 0.196 0.000 k +*u +1191 262 m +1192 261 l +1191 262 l +f +*U +0.000 0.114 0.184 0.243 k +*u +1271 262 m +1272 261 l +1271 262 l +f +*U +0.000 0.573 0.408 0.392 k +*u +1303 262 m +1304.249 261.315 1304.548 261.251 1306 261 c +1304.751 261.685 1304.452 261.749 1303 262 c +f +*U +0.000 0.333 0.251 0.282 k +*u +1317 262 m +1318 261 l +1317 262 l +f +*U +0.000 0.318 0.204 0.361 k +*u +1327 262 m +1328 261 l +1327 262 l +f +*U +0.000 0.000 0.000 0.702 k +*u +1496 262 m +1497 261 l +1496 262 l +f +*U +0.000 0.000 0.000 0.110 k +*u +1753 262 m +1755.719 258.222 1758.644 255.688 1763 254 c +1760.264 257.575 1757 260 1753 262 c +f +*U +0.000 0.000 0.000 0.698 k +*u +1892 262 m +1893 261 l +1892 262 l +f +*U +0.000 0.000 0.000 0.227 k +*u +1913 262 m +1914 261 l +1913 262 l +f +*U +0.000 0.000 0.000 0.243 k +*u +263 261 m +264 260 l +263 261 l +f +*U +0.000 0.000 0.000 0.090 k +*u +825 261 m +822 255 l +824.640 256.536 825.818 257.939 825 261 c +f +*U +0.000 0.000 0.000 0.118 k +*u +930 261 m +931 258.515 931.726 257.402 934 256 c +932.906 258.357 932 259.599 930 261 c +f +*U +0.000 0.165 0.106 0.141 k +*u +1148 261 m +1149 260 l +1148 261 l +f +*U +0.000 0.545 0.416 0.357 k +*u +1182 261 m +1182.545 259.365 1182.365 259.545 1184 259 c +1184 261 l +1182 261 l +f +*U +0.000 0.125 0.110 0.204 k +*u +1190 261 m +1191 260 l +1190 261 l +f +*U +0.000 0.522 0.341 0.400 k +*u +1191 261 m +1189 260 l +1190.482 259.209 1191.796 259 1191 261 c +f +*U +0.000 0.118 0.184 0.141 k +*u +1263 261 m +1264 260 l +1263 261 l +f +*U +0.000 0.188 0.063 0.204 k +*u +1268 261 m +1269 260 l +1268 261 l +f +*U +0.000 0.549 0.325 0.451 k +*u +1269.667 260.667 m +1269.222 260.222 1270.278 260.278 1270.333 260.333 c +1270.778 260.778 1269.722 260.722 1269.667 260.667 c +f +*U +0.000 0.608 0.518 0.392 k +*u +1300 259 m +1301.580 259.683 1301.777 259.805 1303 261 c +1301.420 260.316 1301.223 260.195 1300 259 c +f +*U +0.000 0.220 0.161 0.133 k +*u +1303.667 260.667 m +1303.222 260.222 1304.278 260.278 1304.333 260.333 c +1304.778 260.778 1303.722 260.722 1303.667 260.667 c +f +*U +0.000 0.404 0.290 0.251 k +*u +1305 261 m +1306 260 l +1305 261 l +f +*U +0.000 0.639 0.451 0.275 k +*u +1313 261 m +1314.506 260.317 1315.315 260.174 1317 260 c +1315.494 260.683 1314.686 260.826 1313 261 c +f +*U +0.000 0.667 0.533 0.333 k +*u +1328 261 m +1329.450 259.392 1330 258.936 1332 258 c +1330.550 259.608 1329.948 260 1328 261 c +f +*U +0.000 0.000 0.000 0.784 k +*u +1781 261 m +1782 260 l +1781 261 l +f +*U +0.000 0.000 0.000 0.125 k +*u +1892 261 m +1893 260 l +1892 261 l +f +*U +0.000 0.000 0.000 0.733 k +*u +1893 261 m +1894 260 l +1893 261 l +f +*U +0.000 0.000 0.000 0.063 k +*u +1912 261 m +1911 257 l +1912.753 258.330 1913.670 259.247 1915 261 c +1912 261 l +f +*U +0.000 0.000 0.000 0.722 k +*u +2013 261 m +2014 260 l +2013 261 l +f +*U +0.000 0.000 0.000 0.098 k +*u +2014 261 m +2014.683 259.420 2014.805 259.222 2016 258 c +2015.316 259.580 2015.195 259.777 2014 261 c +f +*U +0.000 0.000 0.000 0.196 k +*u +264 260 m +265 259 l +264 260 l +f +*U +0.000 0.000 0.000 0.792 k +*u +265 260 m +266 259 l +265 260 l +f +*U +0.000 0.000 0.000 0.812 k +*u +359 260 m +360 259 l +359 260 l +f +*U +0.000 0.000 0.000 0.804 k +*u +616 260 m +617 259 l +616 260 l +f +*U +0.000 0.000 0.000 0.255 k +*u +705 260 m +706 259 l +705 260 l +f +*U +0.000 0.000 0.000 0.824 k +*u +706 260 m +707 259 l +706 260 l +f +800 260 m +801 259 l +800 260 l +f +*U +0.000 0.000 0.000 0.820 k +*u +805 260 m +806 259 l +805 260 l +f +*U +0.000 0.000 0.000 0.804 k +*u +824 260 m +825 259 l +824 260 l +f +*U +0.000 0.439 0.294 0.094 k +*u +1137 260 m +1138 259 l +1137 260 l +f +*U +0.000 0.161 0.153 0.275 k +*u +1149 260 m +1150 259 l +1149 260 l +f +*U +0.000 0.498 0.431 0.502 k +*u +1150 260 m +1151 259 l +1150 260 l +f +*U +0.000 0.494 0.329 0.094 k +*u +1184 260 m +1185 259 l +1184 260 l +f +*U +0.000 0.455 0.298 0.118 k +*u +1188 260 m +1189 259 l +1188 260 l +f +*U +0.000 0.718 0.580 0.282 k +*u +1262 260 m +1263.249 259.315 1263.548 259.251 1265 259 c +1263.752 259.685 1263.452 259.749 1262 260 c +f +*U +0.000 0.392 0.416 0.357 k +*u +1265.667 259.667 m +1265.222 259.222 1266.278 259.278 1266.333 259.333 c +1266.778 259.778 1265.722 259.722 1265.667 259.667 c +f +*U +0.000 0.729 0.671 0.271 k +*u +1266 258 m +1267.580 258.683 1267.777 258.805 1269 260 c +1267.420 259.316 1267.223 259.195 1266 258 c +f +*U +0.000 0.875 0.835 0.098 k +*u +1268 259 m +1269.809 258.426 1270 258.535 1272 259 c +1270.191 259.574 1269.931 259.465 1268 259 c +f +*U +0.000 0.455 0.314 0.196 k +*u +1307 260 m +1308 259 l +1307 260 l +f +*U +0.000 0.690 0.478 0.310 k +*u +1308 260 m +1309.249 259.315 1309.548 259.251 1311 259 c +1309.752 259.685 1309.452 259.749 1308 260 c +f +*U +0.000 0.447 0.325 0.553 k +*u +1311 260 m +1312.248 259.315 1312.548 259.251 1314 259 c +1312.752 259.685 1312.451 259.749 1311 260 c +f +*U +0.000 0.396 0.286 0.208 k +*u +1314 260 m +1315 259 l +1314 260 l +f +*U +0.000 0.329 0.239 0.055 k +*u +1315 260 m +1316 259 l +1315 260 l +f +*U +0.000 0.278 0.239 0.063 k +*u +1394.333 259.333 m +1394.278 259.278 1394.222 258.222 1394.667 258.667 c +1394.723 258.723 1394.777 259.777 1394.333 259.333 c +f +*U +0.000 0.000 0.000 0.106 k +*u +1497 260 m +1499.633 257.340 1502.414 256 1506 255 c +1503.356 257.717 1500.694 259 1497 260 c +f +*U +0.000 0.000 0.000 0.176 k +*u +1529.667 259.667 m +1529.222 259.222 1530.278 259.278 1530.333 259.333 c +1530.778 259.778 1529.722 259.722 1529.667 259.667 c +f +*U +0.000 0.000 0.000 0.310 k +*u +1891.667 259.667 m +1891.222 259.222 1892.278 259.278 1892.333 259.333 c +1892.778 259.778 1891.722 259.722 1891.667 259.667 c +f +*U +0.000 0.000 0.000 0.824 k +*u +1911 260 m +1912 259 l +1911 260 l +f +*U +0.000 0.000 0.000 0.631 k +*u +1993 260 m +1994 259 l +1993 260 l +f +*U +0.000 0.000 0.000 0.263 k +*u +265 259 m +266 258 l +265 259 l +f +*U +0.000 0.000 0.000 0.639 k +*u +266 259 m +267 258 l +266 259 l +f +*U +0.000 0.000 0.000 0.106 k +*u +348 254 m +352.391 254.594 356 255.826 360 258 c +356.543 258.579 350.301 256.677 348 254 c +f +*U +0.000 0.000 0.000 0.110 k +*u +616 259 m +617.624 256.956 618.643 256 621 255 c +619.376 257 618.357 257.896 616 259 c +f +*U +0.000 0.000 0.000 0.094 k +*u +706 259 m +707.465 256.878 708.457 256.526 711 256 c +709.369 257.366 707.962 258 706 259 c +f +*U +0.000 0.000 0.000 0.651 k +*u +707 259 m +708 258 l +707 259 l +f +*U +0.000 0.000 0.000 0.153 k +*u +797 257 m +799.291 257.311 799.320 257.366 801 259 c +799.248 258.436 798.458 258 797 257 c +f +*U +0.000 0.310 0.224 0.247 k +*u +1054 259 m +1055 258 l +1054 259 l +f +*U +0.000 0.400 0.278 0.600 k +*u +1136.667 258.667 m +1136.222 258.222 1137.278 258.278 1137.333 258.333 c +1137.778 258.778 1136.722 258.722 1136.667 258.667 c +f +*U +0.000 0.196 0.125 0.141 k +*u +1138 259 m +1129.439 256.469 1118.901 258 1110 258 c +1055 258 l +1059.609 255.344 1068.602 257 1074 257 c +1119 257 l +1123.999 257 1129 256.941 1134 257 c +1135.998 257 1138.953 256.691 1138 259 c +f +*U +0.000 0.235 0.243 0.282 k +*u +1150 259 m +1151 258 l +1150 259 l +f +*U +0.000 0.714 0.506 0.286 k +*u +1151 259 m +1153.890 257.787 1156.874 258 1160 258 c +1157 259.213 1154 258.998 1151 259 c +f +*U +0.000 0.498 0.498 0.502 k +*u +1184 259 m +1185.506 258.317 1186.315 258.174 1188 258 c +1186.494 258.683 1185.685 258.826 1184 259 c +f +*U +0.000 0.706 0.753 0.196 k +*u +1188 259 m +1189.506 258.317 1190.315 258.174 1192 258 c +1190.494 258.683 1189.685 258.826 1188 259 c +f +*U +0.000 0.804 0.812 0.114 k +*u +1264.667 258.667 m +1264.222 258.222 1265.278 258.278 1265.333 258.333 c +1265.778 258.778 1264.722 258.722 1264.667 258.667 c +f +*U +0.000 0.667 0.451 0.333 k +*u +1296 259 m +1297.506 258.317 1298.315 258.174 1300 258 c +1298.494 258.683 1297.685 258.826 1296 259 c +f +*U +0.000 0.325 0.212 0.251 k +*u +1300 259 m +1301 258 l +1300 259 l +f +*U +0.000 0.271 0.176 0.153 k +*u +1308.667 258.667 m +1308.222 258.222 1309.278 258.278 1309.333 258.333 c +1309.778 258.778 1308.722 258.722 1308.667 258.667 c +f +*U +0.000 0.710 0.486 0.286 k +*u +1333 259 m +1334.249 258.315 1334.548 258.251 1336 258 c +1334.752 258.685 1334.451 258.749 1333 259 c +f +*U +0.000 0.808 0.627 0.192 k +*u +1384 259 m +1386.890 257.787 1389.874 258 1393 258 c +1390 259.213 1387 258.998 1384 259 c +f +*U +0.000 0.349 0.322 0.651 k +*u +1393 259 m +1394 258 l +1393 259 l +f +*U +0.000 0.000 0.000 0.678 k +*u +1501 259 m +1502 258 l +1501 259 l +f +*U +0.000 0.000 0.000 0.710 k +*u +1530 259 m +1531 258 l +1530 259 l +f +*U +0.000 0.000 0.000 0.169 k +*u +1531 259 m +1532.687 257.344 1533.746 256.749 1536 256 c +1534.314 257.656 1533.254 258.251 1531 259 c +f +*U +0.000 0.000 0.000 0.812 k +*u +1758 259 m +1759 258 l +1758 259 l +f +*U +0.000 0.000 0.000 0.090 k +*u +1787 259 m +1786.952 256.670 1786.796 256.994 1789 256 c +1788.308 257.389 1788 257.860 1787 259 c +f +*U +0.000 0.000 0.000 0.078 k +*u +1891 259 m +1892 258 l +1891 259 l +f +*U +0.000 0.000 0.000 0.094 k +*u +1993 259 m +1993.684 257.420 1993.805 257.223 1995 256 c +1994.316 257.580 1994.195 257.777 1993 259 c +f +*U +0.000 0.000 0.000 0.212 k +*u +267 258 m +268 257 l +267 258 l +f +*U +0.000 0.000 0.000 0.608 k +*u +268 258 m +269 257 l +268 258 l +f +*U +0.000 0.000 0.000 0.639 k +*u +709 258 m +710 257 l +709 258 l +f +*U +0.000 0.000 0.000 0.635 k +*u +910 258 m +911 257 l +910 258 l +f +*U +0.000 0.000 0.000 0.824 k +*u +931 258 m +932 257 l +931 258 l +f +*U +0.000 0.196 0.125 0.141 k +*u +1151 258 m +1154.699 256.448 1159 257 1163 257 c +1183 257 l +1179.301 258.552 1174.983 258 1171 258 c +1151 258 l +f +*U +0.000 0.325 0.212 0.063 k +*u +1183 258 m +1185.890 256.787 1188.874 257 1192 257 c +1189 258.213 1186 257.998 1183 258 c +f +*U +0.000 0.196 0.125 0.141 k +*u +1192 258 m +1195.699 256.448 1200 257 1204 257 c +1225 257 l +1299 257 l +1295.301 258.552 1290.983 258 1287 258 c +1266 258 l +1192 258 l +f +1330 258 m +1335.707 255.605 1343.846 257 1350 257 c +1394 257 l +1388.293 259.395 1380 258 1374 258 c +1330 258 l +f +*U +0.000 0.000 0.000 0.204 k +*u +1890.333 257.333 m +1890.278 257.278 1890.222 256.222 1890.667 256.667 c +1890.723 256.723 1890.777 257.777 1890.333 257.333 c +f +*U +0.000 0.000 0.000 0.553 k +*u +1891 258 m +1892 257 l +1891 258 l +f +*U +0.000 0.000 0.000 0.675 k +*u +1910 258 m +1911 257 l +1910 258 l +f +*U +0.000 0.000 0.000 0.647 k +*u +2015 258 m +2016 257 l +2015 258 l +f +*U +0.000 0.000 0.000 0.055 k +*u +268 257 m +270.516 255 272.903 254.465 276 254 c +273.954 256.433 271 256.597 268 257 c +f +*U +0.000 0.000 0.000 0.678 k +*u +271 257 m +272 256 l +271 257 l +f +*U +0.000 0.000 0.000 0.671 k +*u +353 257 m +354 256 l +353 257 l +f +*U +0.000 0.000 0.000 0.639 k +*u +794 257 m +795 256 l +794 257 l +f +*U +0.000 0.000 0.000 0.082 k +*u +795 257 m +792.600 256.197 790.628 255.907 789 254 c +791 254.226 796 254.330 795 257 c +f +*U +0.000 0.000 0.000 0.251 k +*u +796 257 m +797 256 l +796 257 l +f +*U +0.000 0.000 0.000 0.161 k +*u +802 257 m +801 255.522 801 255.797 801 254 c +822 254 l +815.592 256.689 808.348 253.470 802 257 c +f +*U +0.000 0.000 0.000 0.663 k +*u +803 257 m +804 256 l +803 257 l +f +*U +0.000 0.000 0.000 0.078 k +*u +910 257 m +910.406 254.908 910.217 254.980 912 254 c +911.316 255.580 911.195 255.777 910 257 c +f +*U +0.000 0.000 0.000 0.757 k +*u +1646 257 m +1647 256 l +1646 257 l +f +*U +0.000 0.000 0.000 0.569 k +*u +1889 257 m +1890 256 l +1889 257 l +f +*U +0.000 0.000 0.000 0.078 k +*u +1910 257 m +1909 255.521 1909 255.797 1909 254 c +1910.766 254.979 1910.956 255.222 1910 257 c +f +*U +0.000 0.000 0.000 0.565 k +*u +276 256 m +277 255 l +276 256 l +f +*U +0.000 0.000 0.000 0.827 k +*u +277 256 m +278.248 255.315 278.548 255.251 280 255 c +278.752 255.685 278.452 255.749 277 256 c +f +*U +0.000 0.000 0.000 0.847 k +*u +345 256 m +346.248 255.315 346.548 255.251 348 255 c +346.752 255.685 346.452 255.749 345 256 c +f +*U +0.000 0.000 0.000 0.157 k +*u +520 256 m +523.613 251.865 534.751 254 540 254 c +533.987 256.523 526.440 254.467 520 256 c +f +*U +0.000 0.000 0.000 0.659 k +*u +621 256 m +622 255 l +621 256 l +f +*U +0.000 0.000 0.000 0.169 k +*u +712 256 m +713.248 255.315 713.549 255.251 715 255 c +713.751 255.685 713.452 255.749 712 256 c +f +*U +0.000 0.000 0.000 0.553 k +*u +717 256 m +718 255 l +717 256 l +f +*U +0.000 0.000 0.000 0.839 k +*u +718.667 255.667 m +718.222 255.222 719.278 255.278 719.333 255.333 c +719.778 255.778 718.722 255.722 718.667 255.667 c +f +*U +0.000 0.000 0.000 0.890 k +*u +786.667 255.667 m +786.222 255.222 787.278 255.278 787.333 255.333 c +787.778 255.778 786.722 255.722 786.667 255.667 c +f +*U +0.000 0.000 0.000 0.639 k +*u +788 256 m +789 255 l +788 256 l +f +*U +0.000 0.000 0.000 0.345 k +*u +933 256 m +934 255 l +933 256 l +f +*U +0.000 0.000 0.000 0.820 k +*u +1506 256 m +1507 255 l +1506 256 l +f +*U +0.000 0.000 0.000 0.114 k +*u +1536.667 255.667 m +1536.222 255.222 1537.278 255.278 1537.333 255.333 c +1537.778 255.778 1536.722 255.722 1536.667 255.667 c +f +*U +0.000 0.000 0.000 0.776 k +*u +1551 256 m +1552 255 l +1551 256 l +f +*U +0.000 0.000 0.000 0.769 k +*u +1643 256 m +1644 255 l +1643 256 l +f +*U +0.000 0.000 0.000 0.635 k +*u +1788 256 m +1789 255 l +1788 256 l +f +*U +0.000 0.000 0.000 0.247 k +*u +1789 256 m +1790 255 l +1789 256 l +f +1797.333 255.333 m +1797.278 255.278 1797.222 254.222 1797.667 254.667 c +1797.722 254.722 1797.778 255.778 1797.333 255.333 c +f +*U +0.000 0.000 0.000 0.208 k +*u +1889 256 m +1890 255 l +1889 256 l +f +*U +0.000 0.000 0.000 0.165 k +*u +1995.333 255.333 m +1995.278 255.278 1995.222 254.222 1995.667 254.667 c +1995.722 254.722 1995.778 255.778 1995.333 255.333 c +f +*U +0.000 0.000 0.000 0.153 k +*u +2017 256 m +2011.881 252 2002.237 254 1996 254 c +2002.445 251.296 2012 253 2019 253 c +2018.309 254.388 2018 254.861 2017 256 c +f +*U +0.000 0.000 0.000 0.157 k +*u +276 255 m +282.436 252.299 292 254 299 254 c +348 254 l +341.564 256.701 331.951 255 325 255 c +276 255 l +f +621 255 m +624.959 253.339 629.737 254 634 254 c +630 255.661 625.263 255 621 255 c +f +717 255 m +723.436 252.299 733 254 740 254 c +789 254 l +782.564 256.701 772.951 255 766 255 c +717 255 l +f +*U +0.000 0.000 0.000 0.161 k +*u +912 255 m +918.202 252.397 927.298 254 934 254 c +927.798 256.603 918.702 255 912 255 c +f +938 255 m +945.879 251.694 958.466 254 967 254 c +1033 254 l +1025 257.306 1012.534 255 1004 255 c +938 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1506 255 m +1508.435 252.214 1512.484 253 1516 253 c +1540 253 l +1536.753 254.877 1532.729 254 1529 254 c +1521.304 253.988 1513.592 253.591 1506 255 c +f +*U +0.000 0.000 0.000 0.733 k +*u +1537 255 m +1538 254 l +1537 255 l +f +*U +0.000 0.000 0.000 0.667 k +*u +1556 255 m +1557 254 l +1556 255 l +f +*U +0.000 0.000 0.000 0.855 k +*u +1557.667 254.667 m +1557.222 254.222 1558.278 254.278 1558.333 254.333 c +1558.778 254.778 1557.722 254.722 1557.667 254.667 c +f +*U +0.000 0.000 0.000 0.878 k +*u +1635 255 m +1636.248 254.315 1636.549 254.251 1638 254 c +1636.751 254.685 1636.452 254.749 1635 255 c +f +*U +0.000 0.000 0.000 0.565 k +*u +1638 255 m +1639 254 l +1638 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1790 255 m +1781.715 252.551 1771.615 254 1763 254 c +1767.994 251 1778 253 1784 253 c +1786 253 1791 252.226 1790 255 c +f +*U +0.000 0.000 0.000 0.447 k +*u +1888.667 254.667 m +1888.222 254.222 1889.278 254.278 1889.333 254.333 c +1889.778 254.778 1888.722 254.722 1888.667 254.667 c +f +*U +0.000 0.000 0.000 0.792 k +*u +1996 255 m +1997 254 l +1996 255 l +f +*U +0.000 0.000 0.000 0.145 k +*u +1678 254 m +1683.715 251.602 1691.831 253 1698 253 c +1692.285 255.398 1684.169 254 1678 254 c +f +1798 254 m +1801.699 252.448 1806 253 1810 253 c +1832 253 l +1909 253 l +1905.301 254.552 1900.983 254 1897 254 c +1875 254 l +1798 254 l +f +*U +0.000 0.106 0.086 0.180 k +*u +1057 247 m +1058 246 l +1057 247 l +f +*U +0.000 0.341 0.341 0.659 k +*u +1058.333 246.333 m +1058.278 246.278 1058.222 245.222 1058.667 245.667 c +1058.722 245.722 1058.778 246.778 1058.333 246.333 c +f +*U +0.000 0.498 0.396 0.502 k +*u +1059 247 m +1061.613 245.902 1064 246 1067 246 c +1064.387 247 1061.836 246.993 1059 247 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1067 247 m +1073.678 244.198 1083.784 246 1091 246 c +1144 246 l +1137.322 248.802 1127.216 247 1120 247 c +1067 247 l +f +*U +0.000 0.498 0.380 0.502 k +*u +1144 247 m +1146 246 1147.747 246 1150 246 c +1147.948 246.874 1146.253 246.953 1144 247 c +f +*U +0.000 0.561 0.408 0.267 k +*u +1150.333 246.333 m +1150.278 246.278 1150.222 245.222 1150.667 245.667 c +1150.722 245.722 1150.778 246.778 1150.333 246.333 c +f +*U +0.000 0.263 0.184 0.424 k +*u +1161 247 m +1162 246 l +1161 247 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1162 247 m +1170 243.593 1183.203 246 1192 246 c +1258 246 l +1250 249.306 1237.534 247 1229 247 c +1162 247 l +f +*U +0.000 0.247 0.184 0.753 k +*u +1258.667 246.667 m +1258.222 246.222 1259.278 246.278 1259.333 246.333 c +1259.778 246.778 1258.722 246.722 1258.667 246.667 c +f +*U +0.000 0.035 0.024 0.267 k +*u +1260 247 m +1261 246 l +1260 247 l +f +*U +0.000 0.082 0.047 0.369 k +*u +1268 247 m +1269 246 l +1268 247 l +f +*U +0.000 0.494 0.357 0.506 k +*u +1269 247 m +1270 244 l +1274 246 l +1272.231 246.779 1270.964 246.912 1269 247 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1274 247 m +1277.958 245.339 1282.740 246 1287 246 c +1310 246 l +1306 247.661 1301.260 247 1297 247 c +1274 247 l +f +*U +0.000 0.424 0.322 0.196 k +*u +1310.333 246.333 m +1310.278 246.278 1310.222 245.222 1310.667 245.667 c +1310.722 245.722 1310.778 246.778 1310.333 246.333 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1324 247 m +1329.951 244.503 1338.580 246 1345 246 c +1391 246 l +1385 248.497 1376.420 247 1370 247 c +1324 247 l +f +*U +0.000 0.082 0.114 0.212 k +*u +1391 247 m +1392 246 l +1391 247 l +f +*U +0.000 0.882 0.639 0.118 k +*u +1059 246 m +1059.836 242.935 1060.738 237.971 1063.510 236 c +1066.366 234 1071.701 235 1075 235 c +1105 235 l +1106 240 l +1072 240 l +1079.434 242.197 1088.278 241 1096 241 c +1100.539 241 1105.529 241.903 1110 241.375 c +1116 240.662 1121.966 238.401 1128 238 c +1128 235 l +1152 235 l +1151.825 238.819 1150.848 242.292 1150 246 c +1059 246 l +f +*U +0.000 0.878 0.627 0.122 k +*u +1162 246 m +1164.772 242 1168.415 237.292 1173 235.588 c +1179.519 233.244 1189.201 235 1196 235 c +1252 235 l +1252 239 l +1250.804 238.402 1251 238.534 1250 237 c +1246.447 242 1236.560 240 1231 240 c +1176 240 l +1176 242 l +1248 242 l +1248 244 l +1168 244 l +1170.729 244.810 1173 244.979 1176 245 c +1171.783 246.769 1166.541 246 1162 246 c +f +*U +0.000 0.910 0.627 0.090 k +*u +1168 245 m +1173.951 242.503 1182.580 244 1189 244 c +1227 244 l +1234.810 244 1242.620 244.828 1250 242 c +1242.283 239.719 1233 241 1225 241 c +1176 241 l +1181.217 238.811 1188.381 240 1194 240 c +1230 240 l +1237.251 240 1244.709 241 1251 237 c +1253 243 l +1249 243 l +1249 245 l +1252.419 244.377 1254.691 243.810 1258 245 c +1250.600 248 1239 246 1231 246 c +1209.980 246 1188.944 245.173 1168 245 c +f +*U +0.000 0.525 0.388 0.475 k +*u +1258 246 m +1259 245 l +1258 246 l +f +*U +0.000 0.263 0.176 0.278 k +*u +1259 246 m +1260 245 l +1259 246 l +f +*U +0.000 0.314 0.196 0.322 k +*u +1269 246 m +1270 245 l +1269 246 l +f +*U +0.000 0.878 0.643 0.122 k +*u +1271 246 m +1272.314 241.402 1276.667 239.579 1278 235 c +1362 235 l +1370.177 235 1386.780 231.173 1388 242 c +1385.915 242 1386.276 241.862 1386 244 c +1385.317 242.494 1385.174 241.685 1385 240 c +1344 240 l +1338.621 240 1331.439 238.637 1327 242 c +1325 242 l +1323.777 240.805 1323.580 240.684 1322 240 c +1322 236 l +1318.590 238 1315.720 241 1311.985 242.441 c +1303.438 245.641 1294.926 244.796 1286 245 c +1280.970 245 1276 245.997 1271 246 c +f +*U +0.000 0.922 0.639 0.078 k +*u +1280 246 m +1285.860 243.541 1293.705 245.268 1300 244.960 c +1304.225 244.753 1307.973 243 1312 242 c +1309.645 246.492 1305.605 245.998 1301 246 c +1280 246 l +f +*U +0.000 0.275 0.200 0.027 k +*u +1323 246 m +1324 245 l +1323 246 l +f +*U +0.000 0.910 0.627 0.090 k +*u +1324 246 m +1326.236 238.589 1333.630 240 1340 240 c +1385 240 l +1385 244 l +1385.986 242.521 1386 242.797 1386 241 c +1388.179 242.539 1388.573 243.355 1389 246 c +1324 246 l +f +*U +0.000 0.710 0.510 0.290 k +*u +1389 246 m +1389 242 l +1389.911 243.377 1390.404 244.440 1391 246 c +1389 246 l +f +*U +0.000 0.569 0.396 0.431 k +*u +1058 245 m +1059 244 l +1058 245 l +f +*U +0.000 0.620 0.482 0.380 k +*u +1150 245 m +1151 240 l +1151.791 242.307 1151.475 243 1150 245 c +f +*U +0.000 0.325 0.275 0.078 k +*u +1151 245 m +1152 244 l +1151 245 l +f +*U +0.000 0.710 0.565 0.290 k +*u +1162 245 m +1164 241 l +1164.369 243.223 1163.859 243.735 1162 245 c +f +*U +0.000 0.808 0.596 0.184 k +*u +1249 245 m +1249 243 l +1251.873 242.656 1254.175 242.385 1257 243 c +1254.444 244.190 1251.805 244.702 1249 245 c +f +*U +0.000 0.541 0.416 0.459 k +*u +1257 245 m +1258 244 l +1257 245 l +f +*U +0.000 0.231 0.153 0.329 k +*u +1258 245 m +1259 244 l +1258 245 l +f +*U +0.000 0.592 0.435 0.345 k +*u +1310.667 244.667 m +1310.222 244.222 1311.278 244.278 1311.333 244.333 c +1311.778 244.778 1310.722 244.722 1310.667 244.667 c +f +*U +0.000 0.224 0.173 0.125 k +*u +1312 245 m +1313 244 l +1312 245 l +f +*U +0.000 0.310 0.310 0.690 k +*u +1322 245 m +1322.545 243.365 1322.365 243.545 1324 243 c +1324 245 l +1322 245 l +f +*U +0.000 0.318 0.231 0.333 k +*u +1390 245 m +1391 244 l +1390 245 l +f +*U +0.000 0.443 0.306 0.035 k +*u +1058 244 m +1059 243 l +1058 244 l +f +*U +0.000 0.733 0.541 0.267 k +*u +1059 244 m +1060 239 l +1060.651 241.234 1060.318 242 1059 244 c +f +*U +0.000 0.239 0.188 0.137 k +*u +1162 244 m +1163 243 l +1162 244 l +f +*U +0.000 0.361 0.239 0.318 k +*u +1270 244 m +1271 243 l +1270 244 l +f +*U +0.000 0.431 0.376 0.569 k +*u +1312 244 m +1313 243 l +1312 244 l +f +*U +0.000 0.329 0.263 0.216 k +*u +1313 244 m +1314 243 l +1313 244 l +f +*U +0.000 0.153 0.133 0.259 k +*u +1322 244 m +1323 243 l +1322 244 l +f +*U +0.000 0.878 0.675 0.114 k +*u +1326 244 m +1331.463 241.708 1339 243 1345 243 c +1384 243 l +1378.537 245.292 1370.887 244 1365 244 c +1326 244 l +f +*U +0.000 0.290 0.216 0.031 k +*u +1390 244 m +1391 243 l +1390 244 l +f +*U +0.000 0.251 0.176 0.733 k +*u +1271.333 242.333 m +1271.278 242.278 1271.222 241.222 1271.667 241.667 c +1271.722 241.722 1271.778 242.778 1271.333 242.333 c +f +*U +0.000 0.514 0.439 0.486 k +*u +1313 243 m +1314 242 l +1313 243 l +f +*U +0.000 0.322 0.251 0.180 k +*u +1314 243 m +1315 242 l +1314 243 l +f +*U +0.000 0.561 0.404 0.137 k +*u +1323 243 m +1324 242 l +1323 243 l +f +*U +0.000 0.780 0.541 0.220 k +*u +1324 243 m +1324 240 l +1325 241 1325.309 241.612 1326 243 c +1324 243 l +f +*U +0.000 0.541 0.514 0.459 k +*u +1107 242 m +1108.769 241.221 1110 241 1112 241 c +1110.231 241.779 1108.964 241.912 1107 242 c +f +*U +0.000 0.020 0.004 0.282 k +*u +1152.333 241.333 m +1152.278 241.278 1152.222 240.222 1152.667 240.667 c +1152.722 240.722 1152.778 241.778 1152.333 241.333 c +f +*U +0.000 0.827 0.627 0.157 k +*u +1176 242 m +1182.436 239.299 1192 241 1199 241 c +1250 241 l +1243.564 243.701 1233.951 242 1227 242 c +1176 242 l +f +*U +0.000 0.612 0.482 0.388 k +*u +1253 242 m +1252.278 239.582 1252 237.528 1252 235 c +1240 235 l +1243.958 233.339 1248.737 234 1253 234 c +1253.190 236.971 1253.834 239.260 1255 242 c +1253 242 l +f +*U +0.000 0.663 0.490 0.337 k +*u +1272.667 241.667 m +1272.222 241.222 1273.278 241.278 1273.333 241.333 c +1273.778 241.778 1272.722 241.722 1272.667 241.667 c +f +*U +0.000 0.482 0.459 0.518 k +*u +1314 242 m +1315 241 l +1314 242 l +f +*U +0.000 0.396 0.306 0.122 k +*u +1315 242 m +1316 241 l +1315 242 l +f +*U +0.000 0.612 0.459 0.388 k +*u +1323.333 241.333 m +1323.278 241.278 1323.223 240.222 1323.667 240.667 c +1323.722 240.722 1323.778 241.778 1323.333 241.333 c +f +*U +0.000 0.827 0.627 0.157 k +*u +1328 242 m +1333.216 239.811 1340.381 241 1346 241 c +1384 241 l +1378.783 243.189 1371.619 242 1366 242 c +1328 242 l +f +*U +0.000 0.580 0.451 0.349 k +*u +1388 242 m +1388 239 l +1388.696 240.554 1388.696 240.446 1388 242 c +f +*U +0.000 0.267 0.220 0.318 k +*u +1389 242 m +1390 241 l +1389 242 l +f +*U +0.000 0.251 0.188 0.298 k +*u +1059 241 m +1060 240 l +1059 241 l +f +*U +0.000 0.910 0.627 0.090 k +*u +1072 241 m +1075.959 239.339 1080.740 240 1085 240 c +1108 240 l +1104 241.661 1099.260 241 1095 241 c +1072 241 l +f +*U +0.000 0.310 0.169 0.075 k +*u +1108 241 m +1109 240 l +1108 241 l +f +*U +0.000 0.506 0.380 0.000 k +*u +1112 241 m +1113 240 l +1112 241 l +f +*U +0.000 0.255 0.188 0.149 k +*u +1164 241 m +1165 240 l +1164 241 l +f +*U +0.000 0.549 0.459 0.451 k +*u +1165 241 m +1166 240 l +1165 241 l +f +*U +0.000 0.427 0.322 0.122 k +*u +1273 241 m +1274 240 l +1273 241 l +f +*U +0.000 0.275 0.204 0.376 k +*u +1316 241 m +1317 240 l +1316 241 l +f +*U +0.000 0.153 0.145 0.118 k +*u +1389 241 m +1390 240 l +1389 241 l +f +*U +0.000 0.392 0.325 0.443 k +*u +1106.333 239.333 m +1106.278 239.278 1106.222 238.222 1106.667 238.667 c +1106.722 238.722 1106.778 239.778 1106.333 239.333 c +f +*U +0.000 0.290 0.247 0.102 k +*u +1107 240 m +1108 239 l +1107 240 l +f +*U +0.000 0.227 0.188 0.212 k +*u +1115 240 m +1116 239 l +1115 240 l +f +*U +0.000 0.686 0.486 0.310 k +*u +1116 240 m +1118.432 238.683 1120.248 238.723 1123 239 c +1120.668 239.985 1118.543 239.981 1116 240 c +f +*U +0.000 0.494 0.424 0.478 k +*u +1152 240 m +1152 234 l +1152.951 236.285 1152.951 237.715 1152 240 c +f +*U +0.000 0.180 0.118 0.420 k +*u +1166 240 m +1167 239 l +1166 240 l +f +*U +0.000 0.263 0.165 0.714 k +*u +1167 240 m +1168 239 l +1167 240 l +f +*U +0.000 0.231 0.137 0.035 k +*u +1253 240 m +1254 239 l +1253 240 l +f +*U +0.000 0.576 0.447 0.424 k +*u +1275.667 239.667 m +1275.222 239.222 1276.278 239.278 1276.333 239.333 c +1276.778 239.778 1275.722 239.722 1275.667 239.667 c +f +*U +0.000 0.722 0.553 0.278 k +*u +1317 240 m +1317.684 238.420 1317.804 238.223 1319 237 c +1318.316 238.580 1318.195 238.777 1317 240 c +f +*U +0.000 0.431 0.310 0.322 k +*u +1060 239 m +1061 238 l +1060 239 l +f +*U +0.000 0.561 0.478 0.439 k +*u +1061 239 m +1061 236 l +1061.696 237.554 1061.696 237.446 1061 239 c +f +*U +0.000 0.471 0.349 0.506 k +*u +1105 239 m +1105 234 l +1105.830 236 1105.830 236.970 1105 239 c +f +*U +0.000 0.329 0.282 0.165 k +*u +1118 239 m +1119 238 l +1118 239 l +f +*U +0.000 0.506 0.424 0.494 k +*u +1120 239 m +1121.248 238.315 1121.549 238.251 1123 238 c +1121.752 238.685 1121.452 238.749 1120 239 c +f +*U +0.000 0.216 0.141 0.059 k +*u +1167 239 m +1168 238 l +1167 239 l +f +*U +0.000 0.698 0.537 0.302 k +*u +1168.667 238.667 m +1168.222 238.222 1169.278 238.278 1169.333 238.333 c +1169.778 238.778 1168.722 238.722 1168.667 238.667 c +f +*U +0.000 0.369 0.267 0.212 k +*u +1276 239 m +1277 238 l +1276 239 l +f +*U +0.000 0.384 0.278 0.525 k +*u +1277.333 238.333 m +1277.278 238.278 1277.222 237.222 1277.667 237.667 c +1277.722 237.722 1277.778 238.778 1277.333 238.333 c +f +*U +0.000 0.286 0.192 0.133 k +*u +1321 239 m +1322 238 l +1321 239 l +f +*U +0.000 0.698 0.478 0.302 k +*u +1322 239 m +1321 237.521 1321 237.797 1321 236 c +1322.290 237.443 1322.401 237.234 1322 239 c +f +*U +0.000 0.271 0.204 0.059 k +*u +1388.333 238.333 m +1388.278 238.278 1388.222 237.222 1388.667 237.667 c +1388.722 237.722 1388.778 238.778 1388.333 238.333 c +f +*U +0.000 0.247 0.208 0.059 k +*u +1060 238 m +1061 237 l +1060 238 l +f +*U +0.000 0.200 0.188 0.122 k +*u +1106 238 m +1107 237 l +1106 238 l +f +*U +0.000 0.176 0.137 0.086 k +*u +1125 238 m +1126 237 l +1125 238 l +f +*U +0.000 0.635 0.471 0.365 k +*u +1126 238 m +1126.545 236.365 1126.365 236.545 1128 236 c +1128 238 l +1126 238 l +f +*U +0.000 0.325 0.271 0.318 k +*u +1169 238 m +1170 237 l +1169 238 l +f +*U +0.000 0.243 0.180 0.012 k +*u +1253 238 m +1254 237 l +1253 238 l +f +*U +0.000 0.498 0.388 0.000 k +*u +1319 238 m +1320 237 l +1319 238 l +f +*U +0.000 0.420 0.298 0.404 k +*u +1387.333 237.333 m +1387.278 237.278 1387.222 236.222 1387.667 236.667 c +1387.722 236.722 1387.778 237.778 1387.333 237.333 c +f +*U +0.000 0.373 0.282 0.012 k +*u +1126 237 m +1127 236 l +1126 237 l +f +*U +0.000 0.204 0.176 0.110 k +*u +1153 237 m +1153 234 l +1153.696 235.554 1153.696 235.446 1153 237 c +f +*U +0.000 0.318 0.286 0.227 k +*u +1170 237 m +1171 236 l +1170 237 l +f +*U +0.000 0.263 0.196 0.298 k +*u +1253 237 m +1253 234 l +1253.696 235.554 1253.696 235.446 1253 237 c +f +*U +0.000 0.482 0.478 0.518 k +*u +1277 237 m +1276 234 l +1277.766 234.979 1277.956 235.222 1277 237 c +f +*U +0.000 0.129 0.122 0.337 k +*u +1061.333 235.333 m +1061.278 235.278 1061.222 234.222 1061.667 234.667 c +1061.722 234.722 1061.778 235.778 1061.333 235.333 c +f +*U +0.000 0.420 0.325 0.580 k +*u +1062.333 235.333 m +1062.278 235.278 1062.222 234.222 1062.667 234.667 c +1062.722 234.722 1062.778 235.778 1062.333 235.333 c +f +*U +0.000 0.306 0.239 0.580 k +*u +1127.333 235.333 m +1127.278 235.278 1127.222 234.222 1127.667 234.667 c +1127.722 234.722 1127.778 235.778 1127.333 235.333 c +f +*U +0.000 0.365 0.318 0.102 k +*u +1171 236 m +1172 235 l +1171 236 l +f +*U +0.000 0.420 0.298 0.561 k +*u +1386.333 235.333 m +1386.278 235.278 1386.223 234.222 1386.667 234.667 c +1386.722 234.722 1386.778 235.778 1386.333 235.333 c +f +*U +0.000 0.227 0.173 0.227 k +*u +1387 236 m +1388 235 l +1387 236 l +f +*U +0.000 0.729 0.580 0.271 k +*u +1063 235 m +1067.215 233.231 1072.464 234 1077 234 c +1105 234 l +1100.785 235.769 1095.536 235 1091 235 c +1063 235 l +f +1128 235 m +1134.687 232.194 1144.767 234 1152 234 c +1145.313 236.806 1135.233 235 1128 235 c +f +*U +0.000 0.341 0.282 0.149 k +*u +1172 235 m +1173 234 l +1172 235 l +f +*U +0.000 0.471 0.447 0.529 k +*u +1173.667 234.667 m +1173.222 234.222 1174.278 234.278 1174.333 234.333 c +1174.778 234.778 1173.722 234.722 1173.667 234.667 c +f +*U +0.000 0.729 0.580 0.271 k +*u +1175 235 m +1180.951 232.503 1189.580 234 1196 234 c +1240 234 l +1234 236.497 1225.420 235 1219 235 c +1175 235 l +f +*U +0.000 0.255 0.180 0.157 k +*u +1275 235 m +1276 234 l +1275 235 l +f +*U +0.000 0.729 0.580 0.271 k +*u +1278 235 m +1281.699 233.448 1286 234 1290 234 c +1311 234 l +1386 234 l +1382.301 235.552 1377.983 235 1374 235 c +1353 235 l +1278 235 l +f +*U +0.004 0.000 0.000 0.000 k +*u +1971 228 m +1969.647 227 1969.645 227.177 1968 227 c +1968 190 l +1432 190 l +1436.215 188.231 1441.464 189 1446 189 c +1473 189 l +1567 189 l +1840 189 l +1925 189 l +1939 189 1955.321 191.257 1969 188 c +1969 224 l +1969.810 221.271 1969.979 218.850 1970 216 c +1971.452 219.427 1972.263 224.480 1971 228 c +f +*U +0.000 0.204 0.137 0.133 k +*u +1973 228 m +1974 227 l +1973 228 l +f +*U +0.000 0.333 0.259 0.667 k +*u +1973 227 m +1974 226 l +1973 227 l +f +*U +0.000 0.694 0.478 0.282 k +*u +1974 227 m +1971.938 214.812 1974.578 201.484 1973 189 c +1975.477 192.270 1975.000 195.999 1975 200 c +1975 207.751 1973 218 1977 225 c +1975.814 226.186 1975.416 226.528 1974 227 c +f +*U +0.000 0.306 0.224 0.176 k +*u +1976 226 m +1977 225 l +1976 226 l +f +*U +0.000 0.318 0.227 0.337 k +*u +1977 225 m +1978 224 l +1977 225 l +f +*U +0.000 0.184 0.188 0.102 k +*u +1136 224 m +1137 223 l +1136 224 l +f +*U +0.031 0.000 0.039 0.169 k +*u +1176 224 m +1177 223 l +1176 224 l +f +*U +0.000 0.733 0.588 0.267 k +*u +1973 224 m +1973 192 l +1974.328 195 1974.000 198.581 1974 202 c +1974 208.686 1975.599 217.806 1973 224 c +f +*U +0.000 0.698 0.541 0.302 k +*u +1978.333 223.333 m +1978.278 223.278 1978.222 222.222 1978.667 222.667 c +1978.722 222.722 1978.778 223.778 1978.333 223.333 c +f +*U +0.000 0.373 0.298 0.208 k +*u +1979 224 m +1980 223 l +1979 224 l +f +*U +0.000 0.133 0.090 0.208 k +*u +1066 223 m +1067 222 l +1066 223 l +f +*U +0.000 0.329 0.298 0.671 k +*u +1067 223 m +1068 222 l +1067 223 l +f +*U +0.000 0.525 0.412 0.475 k +*u +1068 223 m +1072.969 220.915 1079.650 222 1085 222 c +1120 222 l +1115 224 1108.350 223 1103 223 c +1068 223 l +f +*U +0.000 0.141 0.078 0.224 k +*u +1120 223 m +1121 222 l +1120 223 l +f +*U +0.000 0.063 0.031 0.686 k +*u +1135 223 m +1136 222 l +1135 223 l +f +*U +0.000 0.588 0.588 0.412 k +*u +1136 223 m +1137.458 221.919 1138.248 221.564 1140 221 c +1138.457 222.267 1137.952 222.489 1136 223 c +f +*U +0.000 0.529 0.400 0.471 k +*u +1139 223 m +1143.724 221 1149.910 222 1155 222 c +1150.276 223.982 1144 223 1139 223 c +f +*U +0.000 0.224 0.192 0.337 k +*u +1155 223 m +1156 222 l +1155 223 l +f +*U +0.000 0.278 0.180 0.094 k +*u +1175.333 222.333 m +1175.278 222.278 1175.222 221.222 1175.667 221.667 c +1175.722 221.722 1175.778 222.778 1175.333 222.333 c +f +*U +0.000 0.525 0.412 0.475 k +*u +1176 223 m +1180.969 220.915 1187.650 222 1193 222 c +1207 222 1223.321 224.257 1237 221 c +1233.803 224.658 1225.577 223 1221 223 c +1176 223 l +f +*U +0.000 0.298 0.259 0.702 k +*u +1237.667 222.667 m +1237.222 222.222 1238.278 222.278 1238.333 222.333 c +1238.778 222.778 1237.722 222.722 1237.667 222.667 c +f +*U +0.000 0.118 0.122 0.196 k +*u +1239 223 m +1240 222 l +1239 223 l +f +*U +0.000 0.341 0.247 0.204 k +*u +1266 223 m +1266 220 l +1266.696 221.554 1266.696 221.446 1266 223 c +f +*U +0.000 0.525 0.412 0.475 k +*u +1267 220 m +1274.573 224.212 1286.527 222 1295 222 c +1355 222 l +1362.993 222 1373.844 223.980 1381 220 c +1382 223 l +1294 223 l +1274 223 l +1270.610 223 1267.797 223.720 1267 220 c +f +*U +0.000 0.239 0.180 0.176 k +*u +1382 223 m +1383 222 l +1382 223 l +f +*U +0.000 0.431 0.431 0.569 k +*u +1979 223 m +1980 222 l +1979 223 l +f +*U +0.000 0.416 0.325 0.329 k +*u +1980 223 m +1981 222 l +1980 223 l +f +*U +0.000 0.875 0.627 0.125 k +*u +1067 222 m +1069.303 218.837 1071.658 213.242 1075.329 211.603 c +1079.551 209.719 1086.451 211 1091 211 c +1126 211 l +1124.811 214.701 1122.757 218.979 1118.816 220.436 c +1114 222.214 1107 221 1102 221 c +1090.306 221 1078.604 220.533 1067 222 c +f +*U +0.000 0.941 0.659 0.059 k +*u +1070 222 m +1074.720 220 1080.920 221 1086 221 c +1120 221 l +1115.280 222.981 1109 222 1104 222 c +1070 222 l +f +*U +0.000 0.647 0.529 0.341 k +*u +1120.333 221.333 m +1120.278 221.278 1120.222 220.222 1120.667 220.667 c +1120.722 220.722 1120.778 221.778 1120.333 221.333 c +f +*U +0.000 0.478 0.365 0.173 k +*u +1136.667 221.667 m +1136.222 221.222 1137.278 221.278 1137.333 221.333 c +1137.778 221.778 1136.722 221.722 1136.667 221.667 c +f +*U +0.000 0.886 0.647 0.114 k +*u +1140 222 m +1141.657 220 1143.887 218.760 1145.326 216.742 c +1146.630 214.912 1146.943 212.610 1149.183 211.603 c +1152.475 210 1157.459 211 1161 211 c +1159.231 211.779 1157.964 211.912 1156 212 c +1161.382 223 1146.695 222 1140 222 c +f +*U +0.000 0.643 0.522 0.357 k +*u +1155.333 221.333 m +1155.278 221.278 1155.222 220.222 1155.667 220.667 c +1155.722 220.722 1155.778 221.778 1155.333 221.333 c +f +*U +0.000 0.875 0.627 0.125 k +*u +1176 222 m +1176 218.577 1176 214.938 1178.920 212.514 c +1181 210.636 1184.292 211 1187 211 c +1193.292 210.987 1199.722 210.628 1206 211 c +1209.773 211.310 1212.695 213.205 1216 211 c +1218.709 211.648 1221.215 211.942 1224 212 c +1224.272 220.344 1229.279 219.399 1236 221 c +1230 223.464 1223 221 1217 221 c +1203.284 220.841 1189.644 221.962 1176 222 c +f +*U +0.000 0.941 0.659 0.059 k +*u +1184 222 m +1188.215 220.231 1193.464 221 1198 221 c +1224 221 l +1219.785 222.769 1214.536 222 1210 222 c +1184 222 l +f +*U +0.000 0.416 0.298 0.361 k +*u +1237 222 m +1238 221 l +1237 222 l +f +*U +0.000 0.941 0.659 0.059 k +*u +1268 222 m +1271 218 l +1276.837 223.572 1289.407 221 1297 221 c +1368 221 l +1359.642 224.507 1346 222 1337 222 c +1268 222 l +f +*U +0.000 0.875 0.620 0.125 k +*u +1272 218 m +1271 220 l +1269.787 217 1270 214 1270 211 c +1288.808 211 1308.257 209.555 1327 211 c +1331.214 211.396 1334.743 213.694 1339 214 c +1339 211 l +1363 211 l +1366.417 211 1370.579 210.351 1373.917 211 c +1376.340 211.663 1381.961 219 1379.472 221.278 c +1378.196 222.430 1375.553 222 1374 222 c +1369.277 222 1364.736 221 1360 221 c +1301 221 l +1280 221 l +1276.470 221 1272.855 221.992 1272 218 c +f +*U +0.000 0.345 0.235 0.325 k +*u +1381 222 m +1382 221 l +1381 222 l +f +*U +0.000 0.388 0.302 0.141 k +*u +1982 222 m +1983 221 l +1982 222 l +f +*U +0.000 0.255 0.180 0.039 k +*u +1067 221 m +1068 220 l +1067 221 l +f +*U +0.000 0.482 0.329 0.416 k +*u +1068.333 220.333 m +1068.278 220.278 1068.222 219.222 1068.667 219.667 c +1068.722 219.722 1068.778 220.778 1068.333 220.333 c +f +*U +0.000 0.282 0.259 0.216 k +*u +1121 221 m +1122 220 l +1121 221 l +f +*U +0.000 0.235 0.208 0.239 k +*u +1139 221 m +1140 220 l +1139 221 l +f +*U +0.000 0.647 0.431 0.353 k +*u +1140.667 220.667 m +1140.222 220.222 1141.278 220.278 1141.333 220.333 c +1141.778 220.778 1140.722 220.722 1140.667 220.667 c +f +*U +0.000 0.365 0.298 0.153 k +*u +1156 221 m +1157 220 l +1156 221 l +f +*U +0.000 0.427 0.282 0.188 k +*u +1175 221 m +1176 220 l +1175 221 l +f +*U +0.000 0.506 0.388 0.494 k +*u +1234.667 220.667 m +1234.222 220.222 1235.278 220.278 1235.333 220.333 c +1235.778 220.778 1234.722 220.722 1234.667 220.667 c +f +*U +0.000 0.298 0.220 0.212 k +*u +1236 221 m +1237 220 l +1236 221 l +f +*U +0.000 0.259 0.180 0.067 k +*u +1381 221 m +1382 220 l +1381 221 l +f +*U +0.000 0.529 0.443 0.471 k +*u +1982.667 220.667 m +1982.222 220.222 1983.278 220.278 1983.333 220.333 c +1983.778 220.778 1982.722 220.722 1982.667 220.667 c +f +*U +0.000 0.584 0.525 0.416 k +*u +1121.333 219.333 m +1121.278 219.278 1121.222 218.222 1121.667 218.667 c +1121.722 218.722 1121.778 219.778 1121.333 219.333 c +f +*U +0.000 0.463 0.353 0.255 k +*u +1141 220 m +1142 219 l +1141 220 l +f +*U +0.000 0.678 0.635 0.267 k +*u +1156 220 m +1156.684 218.420 1156.805 218.223 1158 217 c +1157.316 218.580 1157.195 218.777 1156 220 c +f +*U +0.000 0.184 0.118 0.180 k +*u +1157 220 m +1158 219 l +1157 220 l +f +*U +0.000 0.573 0.388 0.427 k +*u +1175 220 m +1175 216 l +1175.710 217.760 1175.710 218.240 1175 220 c +f +*U +0.000 0.624 0.443 0.376 k +*u +1224 217 m +1227.412 218.446 1230.304 218.959 1234 219 c +1230.302 220.551 1226.279 220.515 1224 217 c +f +*U +0.000 0.216 0.165 0.133 k +*u +1234 220 m +1235 219 l +1234 220 l +f +*U +0.000 0.741 0.537 0.259 k +*u +1267 220 m +1269 216 l +1269.558 218.308 1268.996 218.756 1267 220 c +f +*U +0.000 0.349 0.282 0.278 k +*u +1985 220 m +1986 219 l +1985 220 l +f +*U +0.000 0.306 0.216 0.008 k +*u +1068 219 m +1069 218 l +1068 219 l +f +*U +0.000 0.431 0.302 0.443 k +*u +1069.333 218.333 m +1069.278 218.278 1069.222 217.222 1069.667 217.667 c +1069.722 217.722 1069.778 218.778 1069.333 218.333 c +f +*U +0.000 0.345 0.282 0.145 k +*u +1122 219 m +1123 218 l +1122 219 l +f +*U +0.000 0.333 0.176 0.090 k +*u +1142 219 m +1143 218 l +1142 219 l +f +*U +0.000 0.631 0.482 0.369 k +*u +1143 219 m +1146 214 l +1146.611 216.816 1145.444 217.675 1143 219 c +f +*U +0.000 0.271 0.200 0.071 k +*u +1226 219 m +1227.506 218.317 1228.314 218.174 1230 218 c +1228.494 218.683 1227.685 218.826 1226 219 c +f +*U +0.000 0.337 0.243 0.086 k +*u +1267 219 m +1268 218 l +1267 219 l +f +*U +0.000 0.722 0.592 0.278 k +*u +1986 219 m +1987.229 217 1987.868 216.777 1990 216 c +1988.607 217.434 1987.767 218 1986 219 c +f +*U +0.000 0.341 0.239 0.000 k +*u +1987 219 m +1988 218 l +1987 219 l +f +*U +0.000 0.718 0.514 0.282 k +*u +1070.333 217.333 m +1070.278 217.278 1070.222 216.222 1070.667 216.667 c +1070.722 216.722 1070.778 217.778 1070.333 217.333 c +f +*U +0.000 0.290 0.271 0.106 k +*u +1158 218 m +1159 217 l +1158 218 l +f +*U +0.000 0.239 0.216 0.141 k +*u +1225.333 217.333 m +1225.278 217.278 1225.222 216.222 1225.667 216.667 c +1225.722 216.722 1225.778 217.778 1225.333 217.333 c +f +*U +0.000 0.404 0.286 0.369 k +*u +1268 218 m +1269 217 l +1268 218 l +f +*U +0.000 0.357 0.282 0.384 k +*u +1379 218 m +1380 217 l +1379 218 l +f +*U +0.000 0.357 0.255 0.027 k +*u +1069 217 m +1070 216 l +1069 217 l +f +*U +0.000 0.118 0.165 0.325 k +*u +1123 217 m +1124 216 l +1123 217 l +f +*U +0.000 0.714 0.514 0.243 k +*u +1158 217 m +1156 212 l +1161 212 l +1160 213.962 1159.366 215.369 1158 217 c +f +*U +0.000 0.459 0.333 0.541 k +*u +1224 217 m +1224 214 l +1224.696 215.554 1224.696 215.446 1224 217 c +f +*U +0.000 0.204 0.153 0.161 k +*u +1268 217 m +1269 216 l +1268 217 l +f +*U +0.000 0.251 0.188 0.153 k +*u +1990 217 m +1991 216 l +1990 217 l +f +*U +0.000 0.616 0.475 0.384 k +*u +27 216 m +27 206 l +28.346 209.207 28.346 212.793 27 216 c +f +*U +0.000 0.271 0.176 0.612 k +*u +1070 216 m +1071 215 l +1070 216 l +f +*U +0.000 0.761 0.553 0.239 k +*u +1071 216 m +1071.526 213.457 1071.878 212.465 1074 211 c +1073.199 213 1072.503 214.337 1071 216 c +f +*U +0.000 0.227 0.145 0.133 k +*u +1124 216 m +1125 215 l +1124 216 l +f +*U +0.000 0.373 0.271 0.227 k +*u +1145 216 m +1146 215 l +1145 216 l +f +*U +0.000 0.063 0.035 0.706 k +*u +1175 216 m +1176 215 l +1175 216 l +f +*U +0.000 0.616 0.455 0.384 k +*u +1269 216 m +1269 211 l +1269.830 213 1269.830 213.970 1269 216 c +f +*U +0.000 0.494 0.369 0.506 k +*u +1377.333 215.333 m +1377.278 215.278 1377.222 214.222 1377.667 214.667 c +1377.722 214.722 1377.778 215.778 1377.333 215.333 c +f +*U +0.000 0.208 0.137 0.475 k +*u +1378 216 m +1379 215 l +1378 216 l +f +*U +0.000 0.745 0.545 0.247 k +*u +1990 216 m +1990 214 l +1992 214 l +1992 216 l +1990 216 l +f +*U +0.000 0.263 0.176 0.141 k +*u +1070 215 m +1071 214 l +1070 215 l +f +*U +0.000 0.855 0.541 0.145 k +*u +1080 215 m +1084.215 213.231 1089.465 214 1094 214 c +1120 214 l +1115.785 215.769 1110.536 215 1106 215 c +1080 215 l +f +*U +0.000 0.067 0.047 0.267 k +*u +1175 215 m +1176 214 l +1175 215 l +f +*U +0.000 0.678 0.510 0.322 k +*u +1176.667 214.667 m +1176.222 214.222 1177.278 214.278 1177.333 214.333 c +1177.778 214.778 1176.722 214.722 1176.667 214.667 c +f +*U +0.000 0.855 0.541 0.145 k +*u +1184 215 m +1190.687 212.194 1200.767 214 1208 214 c +1201.313 216.806 1191.233 215 1184 215 c +f +1272 215 m +1276.720 213 1282.920 214 1288 214 c +1320 214 l +1315.280 215.980 1309 215 1304 215 c +1272 215 l +f +*U +0.000 0.388 0.302 0.612 k +*u +1992 215 m +1993 214 l +1992 215 l +f +*U +0.000 0.333 0.263 0.149 k +*u +1993 215 m +1994 214 l +1993 215 l +f +*U +0.000 0.918 0.694 0.082 k +*u +1080 214 m +1084.215 212.231 1089.465 213 1094 213 c +1121 213 l +1116.785 214.769 1111.535 214 1107 214 c +1080 214 l +f +*U +0.000 0.400 0.275 0.231 k +*u +1125 214 m +1126 213 l +1125 214 l +f +*U +0.000 0.263 0.188 0.149 k +*u +1160 214 m +1161 213 l +1160 214 l +f +*U +0.000 0.392 0.294 0.298 k +*u +1177 214 m +1178 213 l +1177 214 l +f +*U +0.000 0.271 0.169 0.282 k +*u +1224.333 213.333 m +1224.278 213.278 1224.222 212.222 1224.667 212.667 c +1224.722 212.722 1224.778 213.778 1224.333 213.333 c +f +*U +0.000 0.678 0.510 0.322 k +*u +1333 214 m +1335 213 1336.747 213 1339 213 c +1336.948 213.874 1335.253 213.953 1333 214 c +f +*U +0.000 0.369 0.247 0.353 k +*u +1377 214 m +1378 213 l +1377 214 l +f +*U +0.000 0.459 0.333 0.384 k +*u +1993.667 213.667 m +1993.222 213.223 1994.277 213.277 1994.333 213.333 c +1994.778 213.778 1993.722 213.722 1993.667 213.667 c +f +*U +0.000 0.275 0.176 0.180 k +*u +1071 213 m +1072 212 l +1071 213 l +f +*U +0.000 0.302 0.220 0.357 k +*u +1126 213 m +1127 212 l +1126 213 l +f +*U +0.000 0.361 0.263 0.000 k +*u +1146 213 m +1147 212 l +1146 213 l +f +*U +0.000 0.306 0.224 0.396 k +*u +1161 213 m +1162 212 l +1161 213 l +f +*U +0.000 0.518 0.388 0.408 k +*u +1178.333 212.333 m +1178.278 212.278 1178.222 211.222 1178.667 211.667 c +1178.722 211.722 1178.778 212.778 1178.333 212.333 c +f +*U +0.000 0.525 0.329 0.380 k +*u +1210 211 m +1211.580 211.684 1211.777 211.805 1213 213 c +1211.420 212.316 1211.223 212.195 1210 211 c +f +*U +0.000 0.545 0.435 0.455 k +*u +1213 213 m +1214.248 212.315 1214.548 212.251 1216 212 c +1214.751 212.685 1214.452 212.749 1213 213 c +f +*U +0.000 0.502 0.357 0.345 k +*u +1332 210 m +1333 211 1333.309 211.612 1334 213 c +1331.797 212 1331.952 212.330 1332 210 c +f +*U +0.000 0.165 0.141 0.129 k +*u +1334 213 m +1335 212 l +1334 213 l +f +*U +0.000 0.439 0.310 0.165 k +*u +1338 213 m +1338 210 l +1338.696 211.554 1338.696 211.446 1338 213 c +f +*U +0.000 0.506 0.337 0.494 k +*u +1376 213 m +1377 212 l +1376 213 l +f +*U +0.000 0.380 0.275 0.306 k +*u +1996 213 m +1997 212 l +1996 213 l +f +*U +0.000 0.592 0.427 0.408 k +*u +1124 211 m +1126 210.249 1126.596 210.344 1128 212 c +1124 211 l +f +*U +0.000 0.349 0.239 0.329 k +*u +1147 212 m +1148 211 l +1147 212 l +f +*U +0.000 0.588 0.467 0.412 k +*u +1159 211 m +1161 210.249 1161.596 210.344 1163 212 c +1159 211 l +f +*U +0.000 0.416 0.298 0.294 k +*u +1163 212 m +1164 211 l +1163 212 l +f +*U +0.000 0.325 0.192 0.098 k +*u +1212 212 m +1213 211 l +1212 212 l +f +*U +0.106 0.000 0.110 0.184 k +*u +1215 212 m +1216 211 l +1215 212 l +f +*U +0.000 0.416 0.341 0.584 k +*u +1217.667 211.667 m +1217.222 211.222 1218.278 211.278 1218.333 211.333 c +1218.778 211.778 1217.722 211.722 1217.667 211.667 c +f +*U +0.000 0.659 0.443 0.341 k +*u +1219 212 m +1220.769 211.221 1222 211 1224 211 c +1222.231 211.779 1220.964 211.912 1219 212 c +f +*U +0.000 0.173 0.106 0.137 k +*u +1224 212 m +1225 211 l +1224 212 l +f +*U +0.000 0.322 0.208 0.341 k +*u +1376 212 m +1377 211 l +1376 212 l +f +*U +0.000 0.706 0.490 0.259 k +*u +1996 212 m +1997.222 210.267 1998 209.849 2000 209 c +1998.771 210.870 1998 211.224 1996 212 c +f +*U +0.000 0.251 0.188 0.153 k +*u +1998 212 m +1999 211 l +1998 212 l +f +*U +0.000 0.459 0.376 0.090 k +*u +1072 211 m +1073 210 l +1072 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1073 211 m +1077.969 208.915 1084.650 210 1090 210 c +1124 210 l +1119 212 1112.350 211 1107 211 c +1073 211 l +f +*U +0.020 0.000 0.008 0.898 k +*u +1128 211 m +1129 210 l +1128 211 l +f +*U +0.000 0.027 0.020 0.627 k +*u +1129 211 m +1130 210 l +1129 211 l +f +*U +0.000 0.020 0.016 0.255 k +*u +1130 211 m +1131 210 l +1130 211 l +f +*U +0.000 0.259 0.180 0.443 k +*u +1148 211 m +1149 210 l +1148 211 l +f +*U +0.000 0.576 0.388 0.416 k +*u +1149 211 m +1150.248 210.315 1150.548 210.251 1152 210 c +1150.752 210.685 1150.452 210.749 1149 211 c +f +*U +0.000 0.345 0.345 0.655 k +*u +1152 211 m +1154.332 210 1156.457 210 1159 210 c +1156.668 210.984 1154.543 210.981 1152 211 c +f +*U +0.000 0.161 0.153 0.839 k +*u +1163.667 210.667 m +1163.222 210.222 1164.278 210.278 1164.333 210.333 c +1164.778 210.778 1163.722 210.722 1163.667 210.667 c +f +*U +0.000 0.047 0.047 0.631 k +*u +1165 211 m +1166 210 l +1165 211 l +f +*U +0.000 0.243 0.184 0.165 k +*u +1178 211 m +1179 210 l +1178 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1179 211 m +1187.367 207.489 1200.924 210 1210 210 c +1201.633 213.511 1188 211 1179 211 c +f +*U +0.000 0.329 0.227 0.275 k +*u +1210 211 m +1211 210 l +1210 211 l +f +*U +0.000 0.145 0.129 0.267 k +*u +1221 211 m +1222.248 210.315 1222.549 210.251 1224 210 c +1222.752 210.685 1222.451 210.749 1221 211 c +f +*U +0.000 0.333 0.243 0.361 k +*u +1269 211 m +1270 210 l +1269 211 l +f +*U +0.000 0.404 0.404 0.596 k +*u +1270 211 m +1275.707 208.605 1283.846 210 1290 210 c +1332 210 l +1326.293 212.395 1318 211 1312 211 c +1270 211 l +f +*U +0.000 0.533 0.435 0.467 k +*u +1339 211 m +1340.506 210.317 1341.315 210.174 1343 210 c +1341.494 210.683 1340.686 210.826 1339 211 c +f +*U +0.000 0.404 0.404 0.596 k +*u +1343 211 m +1346.699 209.448 1351 210 1355 210 c +1376 210 l +1372.301 211.552 1367.983 211 1364 211 c +1343 211 l +f +*U +0.000 0.431 0.282 0.545 k +*u +2000 210 m +2001 209 l +2000 210 l +f +*U +0.000 0.361 0.239 0.027 k +*u +2001 210 m +2002 209 l +2001 210 l +f +*U +0.000 0.416 0.267 0.310 k +*u +2002 209 m +2003 208 l +2002 209 l +f +*U +0.000 0.455 0.333 0.349 k +*u +0.333 207.333 m +0.278 207.278 0.222 206.222 0.667 206.667 c +0.722 206.722 0.778 207.778 0.333 207.333 c +f +*U +0.000 0.651 0.482 0.349 k +*u +1 208 m +1 200 l +2 202.770 2 205.230 1 208 c +f +*U +0.000 0.537 0.498 0.388 k +*u +2002.667 207.667 m +2002.222 207.223 2003.277 207.277 2003.333 207.333 c +2003.778 207.778 2002.722 207.722 2002.667 207.667 c +f +*U +0.000 0.310 0.345 0.047 k +*u +2004 208 m +2005 207 l +2004 208 l +f +*U +0.000 0.184 0.137 0.047 k +*u +28 207 m +29 206 l +28 207 l +f +*U +0.000 0.357 0.322 0.310 k +*u +2005 207 m +2006 206 l +2005 207 l +f +*U +0.000 0.286 0.220 0.165 k +*u +0.333 205.333 m +0.278 205.278 0.222 204.222 0.667 204.667 c +0.722 204.722 0.778 205.778 0.333 205.333 c +f +*U +0.000 0.271 0.200 0.212 k +*u +28 206 m +29 205 l +28 206 l +f +*U +0.000 0.553 0.420 0.357 k +*u +2005.667 205.667 m +2005.222 205.223 2006.277 205.277 2006.333 205.333 c +2006.778 205.778 2005.722 205.722 2005.667 205.667 c +f +*U +0.000 0.510 0.396 0.180 k +*u +2007 206 m +2008 205 l +2007 206 l +f +*U +0.000 0.192 0.161 0.055 k +*u +0 204 m +1 203 l +0 204 l +f +*U +0.000 0.604 0.471 0.396 k +*u +28.333 203.333 m +28.278 203.278 28.222 202.222 28.667 202.667 c +28.722 202.722 28.778 203.778 28.333 203.333 c +f +*U +0.000 0.325 0.239 0.231 k +*u +2010 204 m +2011 203 l +2010 204 l +f +*U +0.000 0.282 0.196 0.024 k +*u +29 203 m +30 202 l +29 203 l +f +*U +0.000 0.443 0.373 0.557 k +*u +2011 203 m +2012 202 l +2011 203 l +f +*U +0.000 0.400 0.275 0.255 k +*u +29 202 m +30 201 l +29 202 l +f +*U +0.000 0.337 0.239 0.310 k +*u +2013 202 m +2014 201 l +2013 202 l +f +*U +0.000 0.435 0.290 0.439 k +*u +29 201 m +30 200 l +29 201 l +f +*U +0.000 0.376 0.267 0.482 k +*u +2014 201 m +2015 200 l +2014 201 l +f +*U +0.000 0.106 0.086 0.224 k +*u +2015 201 m +2016 200 l +2015 201 l +f +*U +0.000 0.349 0.235 0.165 k +*u +1 200 m +2 199 l +1 200 l +f +*U +0.000 0.408 0.337 0.094 k +*u +30 200 m +31 199 l +30 200 l +f +*U +0.000 0.220 0.125 0.122 k +*u +1080 200 m +1081.506 199.317 1082.315 199.174 1084 199 c +1082.494 199.683 1081.685 199.826 1080 200 c +f +*U +0.000 0.063 0.051 0.216 k +*u +1086 200 m +1087 199 l +1086 200 l +f +*U +0.000 0.208 0.078 0.118 k +*u +1088 200 m +1089.248 199.315 1089.549 199.251 1091 199 c +1089.751 199.685 1089.452 199.749 1088 200 c +f +*U +0.000 0.286 0.169 0.071 k +*u +1095 200 m +1098.699 198.448 1103 199 1107 199 c +1127 199 l +1123.301 200.552 1118.983 200 1115 200 c +1095 200 l +f +*U +0.016 0.000 0.024 0.204 k +*u +1163 200 m +1163 198 l +1164.635 198.545 1164.455 198.365 1165 200 c +1163 200 l +f +*U +0.000 0.286 0.169 0.071 k +*u +1175 200 m +1181.687 197.194 1191.767 199 1199 199 c +1192.313 201.806 1182.233 200 1175 200 c +f +*U +0.000 0.165 0.165 0.204 k +*u +1204 200 m +1205.248 199.315 1205.548 199.251 1207 199 c +1205.751 199.685 1205.452 199.749 1204 200 c +f +*U +0.004 0.000 0.024 0.212 k +*u +1266 200 m +1267 199 l +1266 200 l +f +*U +0.000 0.106 0.314 0.196 k +*u +1267 200 m +1268 199 l +1267 200 l +f +*U +0.000 0.094 0.082 0.153 k +*u +1274 200 m +1275 199 l +1274 200 l +f +*U +0.000 0.306 0.275 0.110 k +*u +1279.667 199.667 m +1279.222 199.222 1280.278 199.278 1280.333 199.333 c +1280.778 199.778 1279.722 199.722 1279.667 199.667 c +f +*U +0.000 0.063 0.016 0.200 k +*u +1298 200 m +1299.248 199.315 1299.549 199.251 1301 199 c +1299.751 199.685 1299.452 199.749 1298 200 c +f +*U +0.000 0.286 0.169 0.071 k +*u +1315 200 m +1319.724 198 1325.910 199 1331 199 c +1326.276 200.982 1320 200 1315 200 c +f +*U +0.000 0.039 0.035 0.169 k +*u +1333 200 m +1334 199 l +1333 200 l +f +*U +0.000 0.286 0.169 0.071 k +*u +1346 200 m +1350.217 198.231 1355.459 199 1360 199 c +1355.783 200.769 1350.541 200 1346 200 c +f +*U +0.000 0.125 0.122 0.157 k +*u +1365 200 m +1366.506 199.317 1367.315 199.174 1369 199 c +1367.494 199.683 1366.685 199.826 1365 200 c +f +*U +0.000 0.333 0.239 0.271 k +*u +2016 200 m +2017 199 l +2016 200 l +f +*U +0.000 0.271 0.188 0.000 k +*u +1 199 m +2 198 l +1 199 l +f +*U +0.000 0.533 0.435 0.467 k +*u +2 199 m +2 196 l +2.696 197.554 2.696 197.446 2 199 c +f +*U +0.000 0.569 0.435 0.412 k +*u +30 199 m +31 195 l +31.393 196.924 31 197.360 30 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1080 199 m +1084.188 196.579 1091 198 1096 198 c +1108.785 198 1122.402 199.339 1135 197 c +1131.914 200.531 1124.411 199 1120 199 c +1080 199 l +f +*U +0.000 0.318 0.255 0.682 k +*u +1164 199 m +1165 198 l +1164 199 l +f +*U +0.000 0.769 0.616 0.212 k +*u +1165 199 m +1166 195 l +1169 197 1171.302 197.882 1175 198 c +1171.837 199.327 1168.415 199.000 1165 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1175 199 m +1184.696 194.931 1197.633 199.468 1208 197 c +1205.565 199.786 1201.516 199.000 1198 199 c +1175 199 l +f +*U +0.000 0.310 0.263 0.180 k +*u +1266 199 m +1266 196 l +1266.696 197.554 1266.696 197.446 1266 199 c +f +*U +0.000 0.639 0.725 0.275 k +*u +1267 199 m +1267 192 l +1268 194.534 1268 196.466 1267 199 c +f +*U +0.000 0.682 0.553 0.318 k +*u +1268 199 m +1271.697 197.449 1276 198 1280 198 c +1276.303 199.551 1271.983 199 1268 199 c +f +*U +0.000 0.639 0.541 0.149 k +*u +1280 199 m +1279 197 l +1281 197 l +1281 198.853 1281.300 198.350 1280 199 c +f +*U +0.000 0.471 0.353 0.035 k +*u +1288 199 m +1289 198 l +1288 199 l +f +*U +0.000 0.514 0.380 0.239 k +*u +1289 199 m +1290 198 l +1289 199 l +f +*U +0.000 0.651 0.533 0.349 k +*u +1290 199 m +1297.409 195.891 1308.975 198 1317 198 c +1309.591 201 1298 199 1290 199 c +f +*U +0.000 0.675 0.482 0.325 k +*u +1317 199 m +1321.469 197 1327.192 198 1332 198 c +1363 198 l +1358.531 199.875 1352.809 199 1348 199 c +1317 199 l +f +*U +0.000 0.812 0.592 0.188 k +*u +1361 196 m +1362.872 196 1363.612 196 1365 195 c +1366.459 196.312 1367 197.231 1368 199 c +1364.830 198.827 1362.864 198.644 1361 196 c +f +*U +0.000 0.047 0.024 0.686 k +*u +1368 199 m +1369 198 l +1368 199 l +f +*U +0.000 0.424 0.361 0.576 k +*u +2017 199 m +2018 198 l +2017 199 l +f +*U +0.000 0.251 0.184 0.220 k +*u +2018 199 m +2019 198 l +2018 199 l +f +*U +0.000 0.263 0.243 0.125 k +*u +31 198 m +32 197 l +31 198 l +f +*U +0.000 0.353 0.216 0.047 k +*u +1080 198 m +1081 197 l +1080 198 l +f +*U +0.000 0.878 0.631 0.118 k +*u +1082 198 m +1083.523 194.843 1086 189 1089.415 187.600 c +1093.757 185.574 1101.283 187 1106 187 c +1144 187 l +1144 192 l +1138.978 192.912 1135.892 197 1130.981 197.811 c +1115 200 1097.886 197.672 1082 198 c +f +*U +0.000 0.776 0.796 0.125 k +*u +1088 198 m +1090.613 196.902 1093 197 1096 197 c +1093.387 198 1090.836 197.993 1088 198 c +f +*U +0.000 0.494 0.361 0.000 k +*u +1135 198 m +1136 197 l +1135 198 l +f +*U +0.000 0.231 0.192 0.149 k +*u +1164 198 m +1165 197 l +1164 198 l +f +*U +0.000 0.875 0.627 0.125 k +*u +1167 189 m +1169.811 188.837 1172.227 187.623 1175 187.212 c +1181.456 186.259 1188.485 187 1195 187 c +1200.940 187 1207.275 186.308 1213 188 c +1211.205 191 1209.833 195 1206.695 196.972 c +1203.965 198.594 1200 198.000 1197 198 c +1178 198 l +1175.348 198.000 1170.968 198.771 1168.742 196.972 c +1166.565 195.212 1167 191.470 1167 189 c +f +*U +0.000 0.255 0.227 0.357 k +*u +1208 198 m +1209 197 l +1208 198 l +f +*U +0.000 0.867 0.624 0.133 k +*u +1268 198 m +1267.822 193.920 1267.630 190.287 1264 188 c +1267.958 186.339 1272.737 187 1277 187 c +1277.794 188.871 1279.375 191 1279.568 193 c +1280 199 1271.684 198.000 1268 198 c +f +*U +0.000 0.792 0.678 0.208 k +*u +1278 198 m +1278.901 196 1279 196 1281 195 c +1280 196.923 1279.924 196.999 1278 198 c +f +*U +0.000 0.306 0.325 0.196 k +*u +1287 198 m +1288 197 l +1287 198 l +f +*U +0.000 0.624 0.600 0.337 k +*u +1288 198 m +1287.438 196.199 1287.176 194.878 1287 193 c +1290 198 l +1288 198 l +f +*U +0.000 0.882 0.631 0.118 k +*u +1288 193 m +1307 193 l +1306.582 190.311 1306.283 189.446 1304 188 c +1308.720 186 1314.920 187 1320 187 c +1330.816 187 1344.307 184.811 1354.830 187.299 c +1359.709 188.453 1363.982 192.189 1365 197 c +1361.308 196.869 1357.750 197.975 1353.999 197.999 c +1338.334 198 1322.665 198 1307 198 c +1300.721 198 1290.249 200.410 1288 193 c +f +*U +0.000 0.020 0.008 0.278 k +*u +1368 198 m +1369 197 l +1368 198 l +f +*U +0.000 0.533 0.439 0.467 k +*u +2018 198 m +2019 197 l +2018 198 l +f +*U +0.000 0.337 0.247 0.263 k +*u +2019 198 m +2020 197 l +2019 198 l +f +*U +0.000 0.361 0.251 0.243 k +*u +1081 197 m +1082 196 l +1081 197 l +f +*U +0.000 0.502 0.353 0.478 k +*u +1082.333 196.333 m +1082.278 196.278 1082.222 195.222 1082.667 195.667 c +1082.722 195.722 1082.778 196.778 1082.333 196.333 c +f +*U +0.000 0.580 0.475 0.420 k +*u +1208 197 m +1208.684 195.420 1208.805 195.223 1210 194 c +1209.316 195.580 1209.195 195.777 1208 197 c +f +*U +0.000 0.435 0.286 0.427 k +*u +1366.333 196.333 m +1366.278 196.278 1366.222 195.222 1366.667 195.667 c +1366.722 195.722 1366.778 196.778 1366.333 196.333 c +f +*U +0.000 0.404 0.345 0.235 k +*u +1367 197 m +1368 196 l +1367 197 l +f +*U +0.000 0.514 0.388 0.486 k +*u +2020 197 m +2021 196 l +2020 197 l +f +*U +0.000 0.306 0.231 0.231 k +*u +2021 197 m +2022 196 l +2021 197 l +f +*U +0.000 0.224 0.169 0.098 k +*u +2 196 m +3 195 l +2 196 l +f +*U +0.000 0.580 0.459 0.420 k +*u +3 196 m +3 193 l +3.696 194.554 3.696 194.446 3 196 c +f +*U +0.000 0.251 0.157 0.216 k +*u +32 196 m +33 195 l +32 196 l +f +*U +0.000 0.310 0.220 0.588 k +*u +1136 196 m +1137 195 l +1136 196 l +f +*U +0.000 0.337 0.255 0.047 k +*u +1165 196 m +1166 195 l +1165 196 l +f +*U +0.000 0.412 0.329 0.204 k +*u +1266.333 195.333 m +1266.278 195.278 1266.222 194.222 1266.667 194.667 c +1266.722 194.722 1266.778 195.778 1266.333 195.333 c +f +*U +0.000 0.937 0.671 0.063 k +*u +1274 196 m +1275 193.867 1275.882 193.217 1278 192 c +1277 196 l +1274 196 l +f +*U +0.000 0.165 0.137 0.145 k +*u +1286.333 195.333 m +1286.278 195.278 1286.222 194.222 1286.667 194.667 c +1286.722 194.722 1286.777 195.778 1286.333 195.333 c +f +*U +0.000 0.404 0.310 0.514 k +*u +2021.667 195.667 m +2021.222 195.222 2022.278 195.278 2022.333 195.333 c +2022.778 195.778 2021.722 195.722 2021.667 195.667 c +f +*U +0.000 0.671 0.486 0.329 k +*u +30 195 m +31.904 193 33.534 192 36 191 c +34 193.323 32.892 194.194 30 195 c +f +*U +0.000 0.263 0.173 0.094 k +*u +33 195 m +34 194 l +33 195 l +f +*U +0.000 0.220 0.157 0.118 k +*u +1082 195 m +1083 194 l +1082 195 l +f +*U +0.000 0.553 0.427 0.447 k +*u +1083 195 m +1084 194 l +1083 195 l +f +*U +0.000 0.612 0.443 0.388 k +*u +1136.667 194.667 m +1136.222 194.222 1137.278 194.278 1137.333 194.333 c +1137.778 194.778 1136.722 194.722 1136.667 194.667 c +f +*U +0.000 0.400 0.286 0.247 k +*u +1138 195 m +1139 194 l +1138 195 l +f +*U +0.000 0.659 0.478 0.325 k +*u +1166 195 m +1165 190 l +1166.879 191.623 1166.916 192.700 1166 195 c +f +*U +0.000 0.314 0.243 0.306 k +*u +1210 195 m +1211 194 l +1210 195 l +f +*U +0.000 0.522 0.541 0.459 k +*u +1280 195 m +1280 192 l +1280.696 193.554 1280.696 193.446 1280 195 c +f +*U +0.000 0.463 0.325 0.537 k +*u +1365 195 m +1366 194 l +1365 195 l +f +*U +0.000 0.455 0.435 0.545 k +*u +2023 195 m +2024 194 l +2023 195 l +f +*U +0.000 0.212 0.137 0.267 k +*u +2024 195 m +2025 194 l +2024 195 l +f +*U +0.000 0.333 0.216 0.000 k +*u +1083 194 m +1084 193 l +1083 194 l +f +*U +0.000 0.447 0.314 0.451 k +*u +1084.333 193.333 m +1084.278 193.278 1084.222 192.222 1084.667 192.667 c +1084.722 192.722 1084.778 193.778 1084.333 193.333 c +f +*U +0.000 0.471 0.380 0.529 k +*u +1138.667 193.667 m +1138.222 193.222 1139.278 193.278 1139.333 193.333 c +1139.778 193.778 1138.722 193.722 1138.667 193.667 c +f +*U +0.000 0.361 0.259 0.200 k +*u +1140 194 m +1141 193 l +1140 194 l +f +*U +0.000 0.498 0.388 0.502 k +*u +1210 194 m +1211 193 l +1210 194 l +f +*U +0.000 0.616 0.420 0.353 k +*u +1266 194 m +1265.697 191.706 1265.421 190.788 1264 189 c +1267.458 187.697 1267 191.778 1266 194 c +f +*U +0.000 0.412 0.412 0.588 k +*u +1364 194 m +1365 193 l +1364 194 l +f +*U +0.000 0.243 0.176 0.071 k +*u +1365 194 m +1366 193 l +1365 194 l +f +*U +0.000 0.522 0.345 0.333 k +*u +2024.667 193.667 m +2024.222 193.222 2025.278 193.278 2025.333 193.333 c +2025.778 193.778 2024.722 193.722 2024.667 193.667 c +f +*U +0.000 0.349 0.231 0.078 k +*u +2026 194 m +2027 193 l +2026 194 l +f +*U +0.000 0.486 0.345 0.106 k +*u +3 193 m +4 192 l +3 193 l +f +*U +0.000 0.533 0.361 0.392 k +*u +1140 193 m +1141.248 192.315 1141.549 192.251 1143 192 c +1141.752 192.685 1141.452 192.749 1140 193 c +f +*U +0.000 0.282 0.196 0.165 k +*u +1143 193 m +1144 192 l +1143 193 l +f +*U +0.000 0.129 0.102 0.196 k +*u +1211 193 m +1212 192 l +1211 193 l +f +*U +0.000 0.208 0.161 0.227 k +*u +1287 193 m +1288 192 l +1287 193 l +f +*U +0.000 0.714 0.714 0.286 k +*u +1288 193 m +1290.332 192 1292.457 192 1295 192 c +1292.668 192.985 1290.543 192.981 1288 193 c +f +*U +0.000 0.694 0.537 0.306 k +*u +1295 193 m +1296.506 192.317 1297.315 192.174 1299 192 c +1297.494 192.683 1296.685 192.826 1295 193 c +f +*U +0.000 0.537 0.392 0.463 k +*u +1299 193 m +1300.769 192.221 1302 192 1304 192 c +1302.231 192.779 1300.964 192.912 1299 193 c +f +*U +0.000 0.769 0.561 0.231 k +*u +1304 193 m +1304.457 191 1304.581 190.792 1304 189 c +1306.905 187.905 1306.880 190.550 1307 193 c +1304 193 l +f +*U +0.000 0.306 0.345 0.271 k +*u +1364 193 m +1365 192 l +1364 193 l +f +*U +0.000 0.475 0.325 0.525 k +*u +2026 193 m +2027 192 l +2026 193 l +f +*U +0.000 0.224 0.145 0.333 k +*u +2027 193 m +2028 192 l +2027 193 l +f +*U +0.000 0.490 0.337 0.384 k +*u +4.333 191.333 m +4.278 191.278 4.222 190.222 4.667 190.667 c +4.722 190.722 4.778 191.778 4.333 191.333 c +f +*U +0.000 0.290 0.216 0.149 k +*u +36 192 m +37 191 l +36 192 l +f +*U +0.020 0.000 0.020 0.000 k +*u +46 192 m +53 188.996 64.256 191 72 191 c +130 191 l +332 191 l +1032 191 l +1024.841 194 1013.744 192 1006 192 c +948 192 l +746 192 l +46 192 l +f +*U +0.008 0.012 0.000 0.000 k +*u +56 189 m +62.919 186 73.520 188 81 188 c +138 188 l +335 188 l +804 188 l +955 188 l +982.955 188 1012.512 185.346 1040 190 c +1034.725 193 1028 189 1022 189 c +969 189 l +775 189 l +56 189 l +f +*U +0.000 0.369 0.239 0.612 k +*u +1085 192 m +1086 191 l +1085 192 l +f +*U +0.000 0.580 0.396 0.420 k +*u +1086.333 191.333 m +1086.278 191.278 1086.222 190.222 1086.667 190.667 c +1086.722 190.722 1086.778 191.778 1086.333 191.333 c +f +*U +0.000 0.325 0.325 0.675 k +*u +1144.333 191.333 m +1144.278 191.278 1144.222 190.222 1144.667 190.667 c +1144.722 190.722 1144.778 191.778 1144.333 191.333 c +f +*U +0.000 0.365 0.267 0.090 k +*u +1165 192 m +1166 191 l +1165 192 l +f +*U +0.000 0.369 0.337 0.224 k +*u +1211 192 m +1212 191 l +1211 192 l +f +*U +0.000 0.443 0.302 0.239 k +*u +1304 192 m +1305 191 l +1304 192 l +f +*U +0.000 0.384 0.259 0.518 k +*u +1361 190 m +1362.580 190.684 1362.777 190.805 1364 192 c +1362.420 191.316 1362.223 191.195 1361 190 c +f +*U +0.020 0.000 0.020 0.000 k +*u +1432 192 m +1436.720 190 1442.920 191 1448 191 c +1479 191 l +1588 191 l +1968 191 l +1963.280 192.981 1957 192 1952 192 c +1921 192 l +1812 192 l +1432 192 l +f +*U +0.000 0.349 0.255 0.031 k +*u +2029 192 m +2030 191 l +2029 192 l +f +*U +0.000 0.365 0.263 0.286 k +*u +37 191 m +38 190 l +37 191 l +f +*U +0.000 0.020 0.012 0.000 k +*u +48 191 m +55 187.996 66.256 190 74 190 c +132 190 l +333 190 l +1032 190 l +1024.841 193 1013.744 191 1006 191 c +948 191 l +747 191 l +48 191 l +f +*U +0.000 0.251 0.169 0.157 k +*u +1085 191 m +1086 190 l +1085 191 l +f +*U +0.000 0.153 0.118 0.114 k +*u +1145 191 m +1146 190 l +1145 191 l +f +*U +0.000 0.565 0.459 0.435 k +*u +1211.333 190.333 m +1211.278 190.278 1211.222 189.222 1211.667 189.667 c +1211.722 189.722 1211.778 190.778 1211.333 190.333 c +f +*U +0.000 0.388 0.290 0.039 k +*u +1278 191 m +1279 190 l +1278 191 l +f +*U +0.000 0.318 0.235 0.129 k +*u +1305 191 m +1306 190 l +1305 191 l +f +*U +0.000 0.020 0.012 0.000 k +*u +1432 191 m +1436.720 189 1442.920 190 1448 190 c +1479 190 l +1588 190 l +1968 190 l +1963.280 191.981 1957 191 1952 191 c +1921 191 l +1812 191 l +1432 191 l +f +*U +0.000 0.506 0.369 0.490 k +*u +2028.667 190.667 m +2028.222 190.223 2029.277 190.277 2029.333 190.333 c +2029.778 190.778 2028.722 190.722 2028.667 190.667 c +f +*U +0.000 0.322 0.235 0.239 k +*u +2030 191 m +2031 190 l +2030 191 l +f +*U +0.000 0.282 0.200 0.016 k +*u +4 190 m +5 189 l +4 190 l +f +*U +0.000 0.569 0.388 0.431 k +*u +5.333 189.333 m +5.278 189.278 5.222 188.222 5.667 188.667 c +5.722 188.722 5.778 189.778 5.333 189.333 c +f +*U +0.000 0.780 0.537 0.220 k +*u +37 190 m +37.980 188.217 37.908 188.406 40 188 c +38.777 189.195 38.580 189.316 37 190 c +f +*U +0.000 0.322 0.235 0.004 k +*u +39 190 m +40 189 l +39 190 l +f +*U +0.004 0.000 0.000 0.000 k +*u +44 190 m +48.869 186.970 58.251 189 64 189 c +116 189 l +310 189 l +1032 189 l +1024.841 192 1013.744 190 1006 190 c +948 190 l +745 190 l +44 190 l +f +*U +0.000 0.408 0.275 0.173 k +*u +1086 190 m +1087 189 l +1086 190 l +f +*U +0.000 0.329 0.235 0.341 k +*u +1144.333 189.333 m +1144.278 189.278 1144.222 188.222 1144.667 188.667 c +1144.722 188.722 1144.778 189.778 1144.333 189.333 c +f +*U +0.000 0.467 0.333 0.114 k +*u +1165.667 189.667 m +1165.222 189.222 1166.278 189.278 1166.333 189.333 c +1166.778 189.778 1165.722 189.722 1165.667 189.667 c +f +*U +0.000 0.384 0.384 0.616 k +*u +1168 190 m +1169 189 l +1168 190 l +f +*U +0.000 0.278 0.204 0.145 k +*u +1212 190 m +1213 189 l +1212 190 l +f +*U +0.000 0.353 0.255 0.184 k +*u +1265 190 m +1266 189 l +1265 190 l +f +*U +0.000 0.561 0.396 0.416 k +*u +1277 190 m +1275.554 187.717 1274.689 187.418 1272 187 c +1274 186 1275.747 186 1278 186 c +1277.826 187.685 1277.683 188.494 1277 190 c +f +*U +0.000 0.267 0.208 0.082 k +*u +1304 190 m +1305 189 l +1304 190 l +f +*U +0.000 0.443 0.325 0.306 k +*u +1305 190 m +1306 189 l +1305 190 l +f +*U +0.000 0.525 0.412 0.471 k +*u +1358.667 189.667 m +1358.222 189.222 1359.278 189.278 1359.333 189.333 c +1359.778 189.778 1358.722 189.722 1358.667 189.667 c +f +*U +0.000 0.318 0.204 0.294 k +*u +1360 190 m +1361 189 l +1360 190 l +f +*U +0.000 0.263 0.176 0.114 k +*u +1361 190 m +1362 189 l +1361 190 l +f +*U +0.000 0.600 0.455 0.400 k +*u +2030.667 189.667 m +2030.222 189.222 2031.278 189.278 2031.333 189.333 c +2031.778 189.778 2030.722 189.722 2030.667 189.667 c +f +*U +0.000 0.137 0.090 0.180 k +*u +2032 190 m +2033 189 l +2032 190 l +f +*U +0.000 0.439 0.298 0.553 k +*u +40 189 m +41 188 l +40 189 l +f +*U +0.000 0.400 0.275 0.314 k +*u +41 189 m +42 188 l +41 189 l +f +*U +0.000 0.290 0.204 0.027 k +*u +42 189 m +43 188 l +42 189 l +f +*U +0.000 0.376 0.243 0.408 k +*u +1087 189 m +1088 188 l +1087 189 l +f +*U +0.000 0.173 0.200 0.118 k +*u +1169 189 m +1170 188 l +1169 189 l +f +*U +0.000 0.404 0.345 0.243 k +*u +1170 189 m +1171 188 l +1170 189 l +f +*U +0.000 0.224 0.149 0.298 k +*u +1263 189 m +1264 188 l +1263 189 l +f +*U +0.000 0.141 0.145 0.392 k +*u +1303 189 m +1304 188 l +1303 189 l +f +*U +0.000 0.596 0.486 0.404 k +*u +1357.333 188.333 m +1357.278 188.278 1357.222 187.222 1357.667 187.667 c +1357.722 187.722 1357.778 188.778 1357.333 188.333 c +f +*U +0.000 0.482 0.373 0.322 k +*u +1358 189 m +1359 188 l +1358 189 l +f +*U +0.008 0.012 0.000 0.000 k +*u +1430 189 m +1434.720 187 1440.920 188 1446 188 c +1477 188 l +1587 188 l +1968 188 l +1963.280 189.981 1957 189 1952 189 c +1921 189 l +1811 189 l +1430 189 l +f +*U +0.000 0.561 0.388 0.439 k +*u +2032 189 m +2033 188 l +2032 189 l +f +*U +0.000 0.420 0.286 0.235 k +*u +2033 189 m +2034 188 l +2033 189 l +f +*U +0.000 0.365 0.239 0.035 k +*u +5 188 m +6 187 l +5 188 l +f +*U +0.000 0.604 0.467 0.396 k +*u +41 188 m +42.248 187.315 42.549 187.251 44 187 c +42.752 187.685 42.452 187.749 41 188 c +f +*U +0.000 0.392 0.278 0.353 k +*u +44 188 m +45 187 l +44 188 l +f +*U +0.000 0.216 0.161 0.110 k +*u +45 188 m +46.248 187.315 46.549 187.251 48 187 c +46.752 187.685 46.452 187.749 45 188 c +f +*U +0.000 0.192 0.149 0.671 k +*u +1144.333 187.333 m +1144.278 187.278 1144.222 186.222 1144.667 186.667 c +1144.722 186.722 1144.778 187.778 1144.333 187.333 c +f +*U +0.000 0.341 0.278 0.384 k +*u +1172 188 m +1173 187 l +1172 188 l +f +*U +0.000 0.373 0.271 0.557 k +*u +1212 188 m +1212 186 l +1214 186 l +1213.455 187.635 1213.635 187.455 1212 188 c +f +*U +0.000 0.373 0.263 0.318 k +*u +1213 188 m +1214 187 l +1213 188 l +f +*U +0.000 0.490 0.349 0.467 k +*u +1261 188 m +1262.926 185.792 1265 186 1268 186 c +1265.717 187.222 1263.572 187.652 1261 188 c +f +*U +0.000 0.365 0.278 0.047 k +*u +1301 188 m +1302 187 l +1301 188 l +f +*U +0.000 0.498 0.365 0.502 k +*u +1302 188 m +1301 186 l +1303 186 l +1303 187.853 1303.300 187.350 1302 188 c +f +*U +0.000 0.663 0.475 0.275 k +*u +1303.333 187.333 m +1303.278 187.278 1303.222 186.222 1303.667 186.667 c +1303.722 186.722 1303.778 187.778 1303.333 187.333 c +f +*U +0.000 0.341 0.278 0.204 k +*u +1358 188 m +1359 187 l +1358 188 l +f +*U +0.000 0.753 0.514 0.227 k +*u +1973 188 m +1974 184 l +1975 185.458 1975.436 186.248 1976 188 c +1973 188 l +f +*U +0.000 0.573 0.396 0.376 k +*u +2033.667 187.667 m +2033.222 187.222 2034.278 187.278 2034.333 187.333 c +2034.778 187.778 2033.722 187.722 2033.667 187.667 c +f +*U +0.000 0.271 0.200 0.200 k +*u +2035 188 m +2036 187 l +2035 188 l +f +*U +0.000 0.455 0.298 0.247 k +*u +6 187 m +7 186 l +6 187 l +f +*U +0.000 0.506 0.337 0.494 k +*u +7.333 186.333 m +7.278 186.278 7.222 185.222 7.667 185.667 c +7.722 185.722 7.778 186.778 7.333 186.333 c +f +*U +0.000 0.914 0.635 0.086 k +*u +40 186 m +44.917 182.699 54 185 60 185 c +111 185 l +303 185 l +795 185 l +953 185 l +1004 185 l +1014.283 185 1024.836 185.752 1035 184 c +1031.803 187.658 1023.577 186 1019 186 c +975 186 l +796 186 l +279 186 l +116 186 l +64 186 l +56.424 186 47.290 187.580 40 186 c +f +*U +0.000 0.655 0.494 0.345 k +*u +44 187 m +45.506 186.317 46.315 186.174 48 186 c +46.494 186.683 45.685 186.826 44 187 c +f +*U +0.000 0.525 0.424 0.475 k +*u +48 187 m +55 183.996 66.256 186 74 186 c +132 186 l +334 186 l +1035 186 l +1027.841 189 1016.744 187 1009 187 c +951 187 l +749 187 l +48 187 l +f +*U +0.000 0.325 0.239 0.475 k +*u +1035 187 m +1036 186 l +1035 187 l +f +*U +0.000 0.247 0.184 0.118 k +*u +1036 187 m +1037 186 l +1036 187 l +f +*U +0.000 0.459 0.349 0.122 k +*u +1088 187 m +1089 186 l +1088 187 l +f +*U +0.000 0.443 0.329 0.494 k +*u +1089 187 m +1094.216 184.811 1101.381 186 1107 186 c +1144 186 l +1138.783 188.189 1131.619 187 1126 187 c +1089 187 l +f +*U +0.024 0.000 0.027 0.227 k +*u +1145 187 m +1146 186 l +1145 187 l +f +*U +0.000 0.259 0.224 0.278 k +*u +1173 187 m +1174 186 l +1173 187 l +f +*U +0.000 0.443 0.329 0.494 k +*u +1174 187 m +1177.699 185.448 1182 186 1186 186 c +1209 186 l +1205.301 187.552 1200.983 187 1197 187 c +1174 187 l +f +*U +0.000 0.478 0.314 0.373 k +*u +1209 187 m +1210.248 186.315 1210.549 186.251 1212 186 c +1210.752 186.685 1210.452 186.749 1209 187 c +f +*U +0.000 0.380 0.275 0.306 k +*u +1268 187 m +1269.506 186.317 1270.315 186.174 1272 186 c +1270.494 186.683 1269.685 186.826 1268 187 c +f +*U +0.000 0.443 0.329 0.494 k +*u +1304 187 m +1308.969 184.915 1315.650 186 1321 186 c +1357 186 l +1352 188 1345.350 187 1340 187 c +1304 187 l +f +*U +0.000 0.271 0.212 0.275 k +*u +1357 187 m +1358 186 l +1357 187 l +f +*U +0.000 0.216 0.192 0.039 k +*u +1425 187 m +1426 186 l +1425 187 l +f +*U +0.000 0.306 0.243 0.271 k +*u +1426 187 m +1427 186 l +1426 187 l +f +*U +0.000 0.416 0.345 0.584 k +*u +1427 187 m +1428.506 186.317 1429.314 186.174 1431 186 c +1429.494 186.683 1428.685 186.826 1427 187 c +f +*U +0.000 0.525 0.424 0.475 k +*u +1431 187 m +1435.720 185 1441.920 186 1447 186 c +1478 186 l +1589 186 l +1973 186 l +1968.280 187.980 1962 187 1957 187 c +1926 187 l +1815 187 l +1431 187 l +f +*U +0.000 0.384 0.278 0.412 k +*u +2035.667 186.667 m +2035.222 186.222 2036.278 186.278 2036.333 186.333 c +2036.778 186.778 2035.722 186.722 2035.667 186.667 c +f +*U +0.000 0.694 0.514 0.306 k +*u +1035 186 m +1036.693 184.938 1038 184.480 1040 184 c +1038.211 185.422 1037.294 185.697 1035 186 c +f +*U +0.000 0.314 0.200 0.145 k +*u +1423 186 m +1424 185 l +1423 186 l +f +*U +0.000 0.643 0.510 0.337 k +*u +1424.667 185.667 m +1424.222 185.222 1425.278 185.278 1425.333 185.333 c +1425.778 185.778 1424.722 185.722 1424.667 185.667 c +f +*U +0.000 0.914 0.635 0.086 k +*u +1429 184 m +1436.724 185.839 1445 185 1453 185 c +1493 185 l +1623 185 l +1853 185 l +1927 185 l +1941.930 185 1957.180 185.947 1972 184 c +1969.897 186.407 1967 185.994 1964 186 c +1945 186 l +1866 186 l +1547 186 l +1459 186 l +1438 186 l +1434.683 185.999 1431.276 186.604 1429 184 c +f +*U +0.000 0.459 0.392 0.541 k +*u +2037 186 m +2038 185 l +2037 186 l +f +*U +0.000 0.349 0.263 0.082 k +*u +2038 186 m +2039 185 l +2038 186 l +f +*U +0.000 0.478 0.314 0.251 k +*u +7 185 m +8 184 l +7 185 l +f +*U +0.000 0.878 0.616 0.122 k +*u +48 185 m +55 181.996 66.256 184 74 184 c +132 184 l +333 184 l +1032 184 l +1024.841 187 1013.744 185 1006 185 c +948 185 l +747 185 l +48 185 l +f +*U +0.000 0.094 0.047 0.463 k +*u +1040 185 m +1041 184 l +1040 185 l +f +*U +0.000 0.482 0.306 0.510 k +*u +1422.667 184.667 m +1422.222 184.222 1423.278 184.278 1423.333 184.333 c +1423.778 184.778 1422.722 184.722 1422.667 184.667 c +f +*U +0.000 0.878 0.616 0.122 k +*u +1431 185 m +1435.720 183 1441.920 184 1447 184 c +1478 184 l +1587 184 l +1968 184 l +1963.280 185.981 1957 185 1952 185 c +1921 185 l +1812 185 l +1431 185 l +f +*U +0.000 0.545 0.388 0.431 k +*u +2038.667 184.667 m +2038.222 184.223 2039.277 184.277 2039.333 184.333 c +2039.778 184.778 2038.722 184.722 2038.667 184.667 c +f +*U +0.000 0.686 0.435 0.302 k +*u +8 184 m +9 181.783 10 180.606 12 179 c +11 184 l +8 184 l +f +*U +0.000 0.800 0.686 0.161 k +*u +1040 184 m +1040.684 181.791 1041 181.297 1043 180 c +1042 181.769 1041.459 182.688 1040 184 c +f +*U +0.000 0.561 0.482 0.388 k +*u +1041 184 m +1041 182 l +1043 182 l +1042.455 183.635 1042.635 183.455 1041 184 c +f +*U +0.000 0.365 0.333 0.012 k +*u +1420 184 m +1421 183 l +1420 184 l +f +*U +0.000 0.463 0.463 0.537 k +*u +1421 184 m +1422 183 l +1421 184 l +f +*U +0.000 0.502 0.498 0.475 k +*u +2040 184 m +2041 183 l +2040 184 l +f +*U +0.000 0.365 0.380 0.239 k +*u +2041 184 m +2042 183 l +2041 184 l +f +*U +0.000 0.349 0.212 0.086 k +*u +8 183 m +9 182 l +8 183 l +f +*U +0.000 0.259 0.247 0.188 k +*u +1419 183 m +1420 182 l +1419 183 l +f +*U +0.000 0.435 0.412 0.565 k +*u +1420 183 m +1421 182 l +1420 183 l +f +*U +0.000 0.439 0.365 0.459 k +*u +2041.667 182.667 m +2041.222 182.222 2042.278 182.278 2042.333 182.333 c +2042.778 182.778 2041.722 182.722 2041.667 182.667 c +f +*U +0.000 0.180 0.157 0.169 k +*u +2043 183 m +2044 182 l +2043 183 l +f +*U +0.000 0.651 0.537 0.349 k +*u +1043.333 181.333 m +1043.278 181.278 1043.222 180.222 1043.667 180.667 c +1043.722 180.722 1043.778 181.778 1043.333 181.333 c +f +*U +0.000 0.282 0.220 0.098 k +*u +1418 182 m +1419 181 l +1418 182 l +f +*U +0.000 0.686 0.529 0.314 k +*u +1419 182 m +1417.738 179.990 1416.810 178.222 1416 176 c +1418.583 177.570 1419.675 179.282 1421 182 c +1419 182 l +f +*U +0.000 0.537 0.420 0.416 k +*u +2043 182 m +2044 181 l +2043 182 l +f +*U +0.000 0.259 0.216 0.251 k +*u +2044 182 m +2045 181 l +2044 182 l +f +*U +0.000 0.235 0.212 0.176 k +*u +1044 181 m +1045 180 l +1044 181 l +f +*U +0.000 0.212 0.137 0.169 k +*u +2046 181 m +2047 180 l +2046 181 l +f +*U +0.000 0.388 0.388 0.612 k +*u +1044 180 m +1045 179 l +1044 180 l +f +*U +0.000 0.235 0.173 0.129 k +*u +1417 180 m +1418 179 l +1417 180 l +f +*U +0.000 0.471 0.388 0.529 k +*u +2046 180 m +2047 179 l +2046 180 l +f +*U +0.000 0.376 0.231 0.318 k +*u +2047 180 m +2048 179 l +2047 180 l +f +*U +0.000 0.635 0.498 0.365 k +*u +1045.333 178.333 m +1045.278 178.278 1045.222 177.222 1045.667 177.667 c +1045.722 177.722 1045.778 178.778 1045.333 178.333 c +f +*U +0.000 0.988 0.671 0.012 k +*u +1419 179 m +1418 177.521 1418 177.797 1418 176 c +1419.290 177.443 1419.401 177.233 1419 179 c +f +*U +0.000 0.376 0.290 0.600 k +*u +2048 179 m +2049 178 l +2048 179 l +f +*U +0.000 0.322 0.259 0.075 k +*u +2049 179 m +2050 178 l +2049 179 l +f +*U +0.000 0.106 0.059 0.118 k +*u +12 178 m +13 177 l +12 178 l +f +*U +0.000 0.227 0.173 0.341 k +*u +1046 178 m +1047 177 l +1046 178 l +f +*U +0.000 0.627 0.502 0.373 k +*u +2049 178 m +2050 177 l +2049 178 l +f +*U +0.000 0.455 0.341 0.290 k +*u +2050 178 m +2051 177 l +2050 178 l +f +*U +0.000 0.290 0.188 0.078 k +*u +13 177 m +14 176 l +13 177 l +f +*U +0.000 0.447 0.329 0.553 k +*u +2050.667 176.667 m +2050.223 176.223 2051.278 176.278 2051.333 176.333 c +2051.778 176.778 2050.722 176.722 2050.667 176.667 c +f +*U +0.000 0.212 0.157 0.251 k +*u +2052 177 m +2053 176 l +2052 177 l +f +*U +0.000 0.247 0.157 0.145 k +*u +14 176 m +15 175 l +14 176 l +f +*U +0.000 0.349 0.224 0.510 k +*u +15 176 m +16 175 l +15 176 l +f +*U +0.000 0.078 0.051 0.169 k +*u +1098.333 175.333 m +1098.278 175.278 1098.222 174.222 1098.667 174.667 c +1098.722 174.722 1098.778 175.778 1098.333 175.333 c +f +*U +0.000 0.384 0.412 0.133 k +*u +1099 176 m +1103.720 174 1109.920 175 1115 175 c +1149 175 l +1144.280 176.980 1138 176 1133 176 c +1099 176 l +f +*U +0.000 0.361 0.333 0.306 k +*u +1149 176 m +1150 175 l +1149 176 l +f +*U +0.000 0.102 0.133 0.204 k +*u +1150 176 m +1151 175 l +1150 176 l +f +*U +0.000 0.384 0.412 0.133 k +*u +1185 176 m +1189.215 174.231 1194.465 175 1199 175 c +1227 175 l +1222.785 176.769 1217.536 176 1213 176 c +1185 176 l +f +*U +0.000 0.235 0.282 0.039 k +*u +1227 176 m +1228 175 l +1227 176 l +f +*U +0.000 0.318 0.251 0.141 k +*u +1256 176 m +1257.506 175.317 1258.315 175.174 1260 175 c +1258.494 175.683 1257.685 175.826 1256 176 c +f +*U +0.000 0.392 0.373 0.129 k +*u +1260 176 m +1264.217 174.231 1269.459 175 1274 175 c +1269.783 176.769 1264.541 176 1260 176 c +f +*U +0.000 0.008 0.004 0.243 k +*u +1296 176 m +1297 175 l +1296 176 l +f +*U +0.000 0.055 0.098 0.490 k +*u +1297 176 m +1298 174 l +1299.635 174.545 1299.455 174.365 1300 176 c +1297 176 l +f +*U +0.000 0.231 0.224 0.098 k +*u +1300.667 175.667 m +1300.222 175.222 1301.278 175.278 1301.333 175.333 c +1301.778 175.778 1300.722 175.722 1300.667 175.667 c +f +*U +0.000 0.384 0.412 0.133 k +*u +1302 176 m +1306.469 174 1312.191 175 1317 175 c +1348 175 l +1343.531 176.875 1337.809 176 1333 176 c +1302 176 l +f +*U +0.000 0.039 0.165 0.431 k +*u +1348.667 175.667 m +1348.222 175.222 1349.278 175.278 1349.333 175.333 c +1349.778 175.778 1348.722 175.722 1348.667 175.667 c +f +*U +0.000 0.161 0.141 0.176 k +*u +1350 176 m +1351 175 l +1350 176 l +f +*U +0.000 0.694 0.545 0.306 k +*u +1415 176 m +1413.545 173.344 1412 170.832 1411 168 c +1413.665 170.231 1415.825 172.419 1415 176 c +f +*U +0.000 0.690 0.494 0.310 k +*u +2053 176 m +2053 174 l +2055 174 l +2054.455 175.635 2054.635 175.455 2053 176 c +f +*U +0.000 0.286 0.176 0.047 k +*u +2054 176 m +2055 175 l +2054 176 l +f +*U +0.000 0.263 0.173 0.063 k +*u +15 175 m +16 174 l +15 175 l +f +*U +0.000 0.271 0.176 0.400 k +*u +1048 175 m +1049 174 l +1048 175 l +f +*U +0.000 0.510 0.384 0.490 k +*u +1099 175 m +1099.545 173.365 1099.365 173.545 1101 173 c +1101 175 l +1099 175 l +f +*U +0.000 0.910 0.663 0.082 k +*u +1101 175 m +1102 173 1103 172.260 1105 171 c +1105 175 l +1101 175 l +f +*U +0.000 0.867 0.753 0.075 k +*u +1105 175 m +1105 170 l +1107 170 l +1107 175 l +1105 175 l +f +*U +0.000 0.871 0.616 0.125 k +*u +1107 175 m +1106 169 l +1108 167 1109.547 165.421 1111 163 c +1124.682 166.257 1140.961 164 1155 164 c +1154 167.322 1153 169.275 1150 171 c +1149.461 175.291 1143.577 174 1140 174 c +1128.929 174 1118 174.657 1107 175 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1112 175 m +1115.699 173.448 1120 174 1124 174 c +1145 174 l +1141.301 175.552 1136.983 175 1133 175 c +1112 175 l +f +*U +0.000 0.678 0.525 0.286 k +*u +1145 175 m +1146.940 174 1148.898 173.561 1151 173 c +1149.266 175 1147.645 174.923 1145 175 c +f +*U +0.000 0.522 0.365 0.298 k +*u +1185.333 174.333 m +1185.278 174.278 1185.222 173.222 1185.667 173.667 c +1185.722 173.722 1185.778 174.778 1185.333 174.333 c +f +*U +0.000 0.690 0.541 0.306 k +*u +1186 173 m +1192 174 l +1189.471 175 1187.824 175 1186 173 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1192 175 m +1195.699 173.448 1200 174 1204 174 c +1225 174 l +1221.301 175.552 1216.983 175 1213 175 c +1192 175 l +f +*U +0.000 0.831 0.600 0.149 k +*u +1225 175 m +1221.309 172.204 1216.485 173 1212 173 c +1202.898 173 1194 172.648 1185 172 c +1181 165 l +1191.522 168.283 1203 167 1214 167 c +1272 167 l +1267 169 1260.362 168 1255 168 c +1258 168.900 1260.831 168.992 1264 169 c +1260.881 170.312 1257.782 169.891 1255 172 c +1252.280 170.967 1249.813 170.278 1248 168 c +1244.336 170.567 1239.395 170.445 1235 171 c +1235.980 169.217 1235.907 169.406 1238 169 c +1234.414 168.319 1230.664 168.259 1227 168 c +1228.479 168.986 1228.203 169 1230 169 c +1226 170.661 1221.260 170 1217 170 c +1192 170 l +1192 172 l +1216 172 l +1220.296 172 1224.302 171.260 1227 175 c +1225 175 l +f +*U +0.000 0.392 0.392 0.608 k +*u +1227 175 m +1228 174 l +1227 175 l +f +*U +0.000 0.655 0.518 0.322 k +*u +1228 175 m +1228.980 173.217 1228.907 173.406 1231 173 c +1229.860 174 1229.389 174.309 1228 175 c +f +*U +0.000 0.259 0.192 0.106 k +*u +1237 175 m +1238 174 l +1237 175 l +f +*U +0.000 0.757 0.588 0.243 k +*u +1238.333 174.333 m +1238.278 174.278 1238.222 173.222 1238.667 173.667 c +1238.722 173.722 1238.778 174.778 1238.333 174.333 c +f +*U +0.000 0.573 0.447 0.427 k +*u +1239 175 m +1241.836 173.693 1244.998 172.939 1248 172 c +1245.271 174.787 1242.827 174.956 1239 175 c +f +*U +0.000 0.251 0.188 0.157 k +*u +1246 175 m +1247 174 l +1246 175 l +f +*U +0.000 0.251 0.196 0.133 k +*u +1253 175 m +1254 174 l +1253 175 l +f +*U +0.000 0.486 0.380 0.365 k +*u +1254.667 174.667 m +1254.222 174.222 1255.278 174.278 1255.333 174.333 c +1255.778 174.778 1254.722 174.722 1254.667 174.667 c +f +*U +0.000 0.690 0.749 0.251 k +*u +1256 175 m +1258.613 173.902 1261 174 1264 174 c +1261.387 175 1258.835 174.993 1256 175 c +f +*U +0.000 0.749 0.847 0.145 k +*u +1264 175 m +1266.613 173.902 1269 174 1272 174 c +1269.387 175 1266.836 174.993 1264 175 c +f +*U +0.000 0.882 0.627 0.118 k +*u +1254 173 m +1256.529 169.493 1259.940 170 1264 170 c +1260.959 169 1258.169 169 1255 169 c +1259.974 166.913 1266.638 168 1272 168 c +1264.848 165.886 1256.427 167 1249 167 c +1206 167 l +1199.931 167 1186.617 169.579 1183 164 c +1250 164 l +1267 164 l +1269.301 164 1272.496 163.564 1274.471 165 c +1277.520 167.286 1276.363 172.889 1272.856 173.972 c +1267.975 175.480 1258.816 174.424 1254 173 c +f +*U +0.000 0.384 0.384 0.616 k +*u +1273 175 m +1274 174 l +1273 175 l +f +*U +0.000 0.263 0.224 0.322 k +*u +1274 175 m +1275 174 l +1274 175 l +f +*U +0.075 0.216 0.000 0.192 k +*u +1297 175 m +1298 174 l +1297 175 l +f +*U +0.000 0.631 0.639 0.361 k +*u +1299 175 m +1300.223 173.805 1300.420 173.684 1302 173 c +1300.777 174.195 1300.580 174.316 1299 175 c +f +*U +0.000 0.773 0.631 0.212 k +*u +1301.667 174.667 m +1301.222 174.222 1302.278 174.278 1302.333 174.333 c +1302.778 174.778 1301.722 174.722 1301.667 174.667 c +f +*U +0.000 0.745 0.851 0.149 k +*u +1302 174 m +1305.985 173 1310.830 174.000 1315 174 c +1344 174 l +1340 175.661 1335.260 175 1331 175 c +1321.805 175 1310.842 176.614 1302 174 c +f +*U +0.000 0.918 0.659 0.082 k +*u +1312 174 m +1318.965 171 1329.475 173 1337 172.996 c +1340.593 172.961 1343.614 172 1346 175 c +1334.957 172.950 1323.203 174 1312 174 c +f +*U +0.000 0.788 0.616 0.212 k +*u +1346 175 m +1345 172.896 1344.954 172.248 1345 170 c +1346.840 171.717 1347.349 172.566 1348 175 c +1346 175 l +f +*U +0.000 0.580 0.522 0.306 k +*u +1348 175 m +1348 173 l +1349.635 173.545 1349.455 173.365 1350 175 c +1348 175 l +f +*U +0.000 0.408 0.325 0.224 k +*u +1414 175 m +1415 174 l +1414 175 l +f +*U +0.000 0.475 0.349 0.098 k +*u +2055 175 m +2056 174 l +2055 175 l +f +*U +0.000 0.204 0.145 0.102 k +*u +1049 174 m +1050 173 l +1049 174 l +f +*U +0.000 0.533 0.475 0.035 k +*u +1151 174 m +1152 173 l +1151 174 l +f +*U +0.000 0.918 0.659 0.082 k +*u +1186 171 m +1197.524 175.489 1212.781 173 1225 173 c +1217 176.305 1204.531 174 1196 174 c +1191.995 173.998 1188.334 174.600 1186 171 c +f +*U +0.000 0.894 0.643 0.106 k +*u +1226 174 m +1222.730 171.523 1219 172 1215 172 c +1192 172 l +1192 170 l +1230 170 l +1228.521 169 1228.797 169 1227 169 c +1230.382 167.640 1234.352 168 1238 168 c +1235 171 l +1239 170.240 1243.650 170.538 1247 168 c +1248 171 1246.257 173 1242.981 173.682 c +1237.459 174.621 1231.755 172.932 1226 174 c +f +*U +0.000 0.357 0.298 0.020 k +*u +1231 174 m +1232.769 173.221 1234 173 1236 173 c +1234.231 173.779 1232.964 173.912 1231 174 c +f +*U +0.000 0.608 0.490 0.392 k +*u +1236.667 173.667 m +1236.222 173.222 1237.278 173.278 1237.333 173.333 c +1237.778 173.778 1236.722 173.722 1236.667 173.667 c +f +*U +0.000 0.329 0.275 0.137 k +*u +1247 174 m +1248 173 l +1247 174 l +f +*U +0.000 0.388 0.314 0.125 k +*u +1252.333 173.333 m +1252.278 173.278 1252.222 172.222 1252.667 172.667 c +1252.722 172.722 1252.778 173.778 1252.333 173.333 c +f +*U +0.000 0.714 0.588 0.286 k +*u +1252 171 m +1253.923 171.902 1253.999 172 1255 174 c +1253 173 1253 172.924 1252 171 c +f +*U +0.000 0.318 0.294 0.216 k +*u +1275 174 m +1276 173 l +1275 174 l +f +*U +0.000 0.859 0.604 0.137 k +*u +1301 173 m +1302 170.237 1307.468 166.678 1304 165 c +1308 162.843 1312.478 163.944 1317 163.996 c +1327.786 164 1335.368 163.682 1345 169 c +1343 173.893 1338.660 173.000 1334 173 c +1323.230 173 1311.529 174.955 1301 173 c +f +*U +0.000 0.710 0.537 0.290 k +*u +2055 174 m +2053.964 172.813 2053.662 172.397 2053 171 c +2054.849 171.967 2055.722 172 2055 174 c +f +*U +0.016 0.008 0.000 0.741 k +*u +2056 174 m +2057 173 l +2056 174 l +f +*U +0.000 0.408 0.286 0.329 k +*u +18 173 m +19 172 l +18 173 l +f +*U +0.000 0.627 0.471 0.373 k +*u +19 173 m +20 171.543 20.543 171 22 170 c +21 172 21 172 19 173 c +f +*U +0.000 0.365 0.306 0.635 k +*u +1049 173 m +1050 172 l +1049 173 l +f +*U +0.000 0.267 0.196 0.082 k +*u +1100 173 m +1101 172 l +1100 173 l +f +*U +0.000 0.698 0.553 0.302 k +*u +1101 173 m +1103.732 169 1106.678 166 1111 164 c +1108.464 168 1105.345 171 1101 173 c +f +*U +0.000 0.651 0.471 0.349 k +*u +1150 172 m +1151.551 170 1152.855 168.218 1154 166 c +1154.785 168.916 1153.644 170.511 1152 173 c +1150 172 l +f +*U +0.000 0.208 0.188 0.302 k +*u +1182 173 m +1183 172 l +1182 173 l +f +*U +0.000 0.714 0.514 0.286 k +*u +1183 171 m +1184.580 171.684 1184.777 171.805 1186 173 c +1183.907 172.594 1183.980 172.783 1183 171 c +f +*U +0.000 0.357 0.337 0.392 k +*u +1276 173 m +1277 172 l +1276 173 l +f +*U +0.000 0.141 0.114 0.145 k +*u +1289 173 m +1290 172 l +1289 173 l +f +*U +0.000 0.384 0.310 0.106 k +*u +1300 173 m +1301 172 l +1300 173 l +f +*U +0.000 0.004 0.000 0.298 k +*u +2056 173 m +2057 172 l +2056 173 l +f +*U +0.000 0.094 0.071 0.184 k +*u +19 172 m +20 171 l +19 172 l +f +*U +0.000 0.761 0.522 0.239 k +*u +22 172 m +23.382 169.580 24.363 168.939 27 168 c +25.410 169.752 24 170.794 22 172 c +f +*U +0.000 0.655 0.525 0.345 k +*u +1050.333 171.333 m +1050.278 171.278 1050.222 170.222 1050.667 170.667 c +1050.722 170.722 1050.778 171.778 1050.333 171.333 c +f +*U +0.000 0.106 0.110 0.278 k +*u +1181 172 m +1182 171 l +1181 172 l +f +*U +0.000 0.333 0.333 0.667 k +*u +1182 172 m +1183 171 l +1182 172 l +f +*U +0.000 0.294 0.184 0.165 k +*u +1248 172 m +1249 171 l +1248 172 l +f +*U +0.000 0.271 0.243 0.188 k +*u +1251 172 m +1252 171 l +1251 172 l +f +*U +0.000 0.514 0.408 0.478 k +*u +1276 172 m +1276 169 l +1276.696 170.554 1276.696 170.446 1276 172 c +f +*U +0.000 0.322 0.271 0.424 k +*u +1287 172 m +1288 171 l +1287 172 l +f +*U +0.000 0.631 0.475 0.369 k +*u +1288 172 m +1289.248 171.315 1289.548 171.251 1291 171 c +1289.751 171.685 1289.452 171.749 1288 172 c +f +*U +0.000 0.361 0.267 0.220 k +*u +1291 172 m +1292 171 l +1291 172 l +f +*U +0.000 0.118 0.176 0.267 k +*u +1299 172 m +1300 171 l +1299 172 l +f +*U +0.000 0.275 0.275 0.725 k +*u +1300 172 m +1301 171 l +1300 172 l +f +*U +0.000 0.392 0.298 0.239 k +*u +1412 172 m +1413 171 l +1412 172 l +f +*U +0.000 0.341 0.231 0.314 k +*u +2054 172 m +2055 171 l +2054 172 l +f +*U +0.000 0.412 0.306 0.235 k +*u +1051 171 m +1052 170 l +1051 171 l +f +*U +0.000 0.800 0.784 0.122 k +*u +1182 171 m +1183 168 l +1183.685 169.249 1183.749 169.548 1184 171 c +1182 171 l +f +*U +0.000 0.557 0.435 0.443 k +*u +1248 171 m +1249.506 170.317 1250.315 170.174 1252 170 c +1250.494 170.683 1249.685 170.826 1248 171 c +f +*U +0.000 0.212 0.196 0.137 k +*u +1286 171 m +1287 170 l +1286 171 l +f +*U +0.000 0.478 0.408 0.498 k +*u +1287 171 m +1288 170 l +1287 171 l +f +*U +0.000 0.937 0.678 0.063 k +*u +1288 171 m +1287 164 l +1291 164 l +1291.262 166.428 1291.262 168.572 1291 171 c +1288 171 l +f +*U +0.000 0.627 0.475 0.373 k +*u +1291 171 m +1291 168 l +1291.696 169.554 1291.696 169.446 1291 171 c +f +*U +0.000 0.294 0.220 0.271 k +*u +1292 171 m +1293 170 l +1292 171 l +f +*U +0.000 0.294 0.208 0.314 k +*u +1300 171 m +1301 170 l +1300 171 l +f +*U +0.000 0.478 0.427 0.522 k +*u +1301 171 m +1302 170 l +1301 171 l +f +*U +0.000 0.475 0.349 0.412 k +*u +2051.667 170.667 m +2051.223 170.223 2052.278 170.278 2052.333 170.333 c +2052.778 170.778 2051.722 170.722 2051.667 170.667 c +f +*U +0.000 0.275 0.176 0.102 k +*u +2053 171 m +2054 170 l +2053 171 l +f +*U +0.000 0.114 0.090 0.173 k +*u +22 170 m +23 169 l +22 170 l +f +*U +0.000 0.337 0.247 0.027 k +*u +1052 170 m +1053 169 l +1052 170 l +f +*U +0.000 0.184 0.157 0.078 k +*u +1103 170 m +1104 169 l +1103 170 l +f +*U +0.000 0.353 0.255 0.204 k +*u +1154 170 m +1155 169 l +1154 170 l +f +*U +0.000 0.396 0.412 0.075 k +*u +1182.333 169.333 m +1182.278 169.278 1182.222 168.222 1182.667 168.667 c +1182.722 168.722 1182.778 169.778 1182.333 169.333 c +f +*U +0.000 0.322 0.208 0.059 k +*u +1277 170 m +1277 167 l +1277.696 168.554 1277.696 168.446 1277 170 c +f +*U +0.000 0.314 0.275 0.290 k +*u +1286 170 m +1287 169 l +1286 170 l +f +*U +0.000 0.722 0.596 0.278 k +*u +1287.333 169.333 m +1287.278 169.278 1287.222 168.222 1287.667 168.667 c +1287.722 168.722 1287.778 169.778 1287.333 169.333 c +f +*U +0.000 0.522 0.376 0.400 k +*u +1292 170 m +1292 165 l +1292.830 167 1292.830 167.969 1292 170 c +f +*U +0.000 0.667 0.592 0.333 k +*u +1302.667 169.667 m +1302.222 169.222 1303.278 169.278 1303.333 169.333 c +1303.778 169.778 1302.722 169.722 1302.667 169.667 c +f +*U +0.000 0.584 0.427 0.349 k +*u +2049 170 m +2048 168 l +2050 168 l +2050 169.853 2050.300 169.350 2049 170 c +f +*U +0.000 0.396 0.380 0.604 k +*u +2050 170 m +2051 169 l +2050 170 l +f +*U +0.000 0.310 0.255 0.290 k +*u +2051 170 m +2052 169 l +2051 170 l +f +*U +0.000 0.686 0.506 0.031 k +*u +24 169 m +25 168 l +24 169 l +f +*U +0.000 0.882 0.635 0.118 k +*u +54 169 m +60.919 166 71.520 168 79 168 c +136 168 l +333 168 l +1016 168 l +1009 170.903 998.480 169 991 169 c +934 169 l +737 169 l +54 169 l +f +*U +0.000 0.655 0.455 0.314 k +*u +1052 169 m +1053.523 164.519 1056.174 161.720 1060 159 c +1058 163 1055.451 166.215 1052 169 c +f +*U +0.000 0.584 0.337 0.000 k +*u +1104 169 m +1105 168 l +1104 169 l +f +*U +0.000 0.478 0.380 0.522 k +*u +1286 169 m +1286 163 l +1286.951 165.285 1286.951 166.715 1286 169 c +f +*U +0.000 0.361 0.282 0.243 k +*u +1303 169 m +1304 168 l +1303 169 l +f +*U +0.431 0.000 0.184 0.000 k +*u +1344 169 m +1345 168 l +1344 169 l +f +*U +0.000 0.263 0.212 0.220 k +*u +1410 169 m +1411 168 l +1410 169 l +f +*U +0.000 0.882 0.635 0.118 k +*u +1449 169 m +1453.469 167 1459.191 168 1464 168 c +1494 168 l +1600 168 l +1967 168 l +1962.531 169.875 1956.809 169 1952 169 c +1922 169 l +1816 169 l +1449 169 l +f +*U +0.000 0.282 0.220 0.082 k +*u +2050 169 m +2051 168 l +2050 169 l +f +*U +0.000 0.204 0.133 0.118 k +*u +26 168 m +27 167 l +26 168 l +f +*U +0.000 0.510 0.431 0.490 k +*u +27.667 167.667 m +27.222 167.222 28.278 167.278 28.333 167.333 c +28.778 167.778 27.722 167.722 27.667 167.667 c +f +*U +0.000 0.882 0.627 0.118 k +*u +48 168 m +55.782 163.635 65.383 165 74 165 c +125 165 l +317 165 l +1020 165 l +1012.841 168 1001.744 166 994 166 c +937 166 l +737 166 l +512.682 166 288.312 164.556 64 166 c +58.486 166 53.541 167.981 48 168 c +f +*U +0.000 0.831 0.600 0.149 k +*u +56 168 m +63 164.996 74.256 167 82 167 c +139 167 l +337 167 l +1026 167 l +1018.841 170 1007.744 168 1000 168 c +943 168 l +744 168 l +56 168 l +f +*U +0.000 0.478 0.373 0.502 k +*u +1276 168 m +1276 165 l +1276.696 166.554 1276.696 166.446 1276 168 c +f +*U +0.000 0.078 0.047 0.184 k +*u +1285 168 m +1286 167 l +1285 168 l +f +*U +0.000 0.388 0.243 0.188 k +*u +1304 168 m +1305 167 l +1304 168 l +f +*U +0.000 0.467 0.467 0.533 k +*u +1341 168 m +1342 167 l +1341 168 l +f +*U +0.000 0.251 0.259 0.435 k +*u +1342 168 m +1343 167 l +1342 168 l +f +*U +0.000 0.310 0.267 0.129 k +*u +1409 168 m +1410 167 l +1409 168 l +f +*U +0.000 0.561 0.427 0.357 k +*u +1410 168 m +1409 166.521 1409 166.797 1409 165 c +1410.289 166.443 1410.401 166.234 1410 168 c +f +*U +0.000 0.831 0.600 0.149 k +*u +1448 168 m +1452.469 166 1458.191 167 1463 167 c +1494 167 l +1600 167 l +1968 167 l +1963.531 168.875 1957.809 168 1953 168 c +1922 168 l +1816 168 l +1448 168 l +f +*U +0.000 0.737 0.561 0.263 k +*u +2042 164 m +2044.222 164.810 2045.990 165.739 2048 167 c +2045 167.698 2043.578 166.511 2042 164 c +f +*U +0.063 0.000 0.012 0.278 k +*u +2048 168 m +2049 167 l +2048 168 l +f +*U +0.000 0.259 0.196 0.106 k +*u +28 167 m +29 166 l +28 167 l +f +*U +0.000 0.502 0.420 0.498 k +*u +29.667 166.667 m +29.222 166.222 30.278 166.278 30.333 166.333 c +30.778 166.778 29.722 166.722 29.667 166.667 c +f +*U +0.000 0.906 0.655 0.094 k +*u +56 167 m +63 163.996 74.256 166 82 166 c +139 166 l +337 166 l +1024 166 l +1016.841 169 1005.744 167 998 167 c +941 167 l +743 167 l +56 167 l +f +*U +0.000 0.208 0.247 0.267 k +*u +1155 167 m +1156 166 l +1155 167 l +f +*U +0.000 0.345 0.263 0.212 k +*u +1180.667 166.667 m +1180.222 166.222 1181.278 166.278 1181.333 166.333 c +1181.778 166.778 1180.722 166.722 1180.667 166.667 c +f +*U +0.000 0.667 0.494 0.333 k +*u +1291 167 m +1289.774 164.965 1289.298 164.674 1287 164 c +1288.769 163.221 1290 163 1292 163 c +1291.826 164.685 1291.683 165.494 1291 167 c +f +*U +0.000 0.482 0.447 0.118 k +*u +1306 167 m +1307 166 l +1306 167 l +f +*U +0.000 0.412 0.345 0.412 k +*u +1340.667 166.667 m +1340.222 166.222 1341.278 166.278 1341.333 166.333 c +1341.778 166.778 1340.722 166.722 1340.667 166.667 c +f +*U +0.000 0.906 0.655 0.094 k +*u +1448 167 m +1452.469 165 1458.191 166 1463 166 c +1494 166 l +1600 166 l +1968 166 l +1963.531 167.875 1957.809 167 1953 167 c +1922 167 l +1816 167 l +1448 167 l +f +*U +0.000 0.220 0.176 0.102 k +*u +31 166 m +32 165 l +31 166 l +f +*U +0.000 0.584 0.424 0.400 k +*u +32 166 m +33.248 165.315 33.548 165.251 35 165 c +33.752 165.685 33.452 165.749 32 166 c +f +*U +0.000 0.400 0.286 0.212 k +*u +1055 166 m +1056 165 l +1055 166 l +f +*U +0.000 0.580 0.459 0.349 k +*u +1155.333 165.333 m +1155.278 165.278 1155.222 164.222 1155.667 164.667 c +1155.722 164.722 1155.778 165.778 1155.333 165.333 c +f +*U +0.000 0.553 0.467 0.447 k +*u +1178 163 m +1181 165 l +1178.860 166 1178.473 165.251 1178 163 c +f +*U +0.000 0.290 0.345 0.243 k +*u +1304 166 m +1305 165 l +1304 166 l +f +*U +0.000 0.592 0.490 0.333 k +*u +1305.667 165.667 m +1305.222 165.222 1306.278 165.278 1306.333 165.333 c +1306.778 165.778 1305.722 165.722 1305.667 165.667 c +f +*U +0.000 0.573 0.482 0.427 k +*u +1339 166 m +1340 165 l +1339 166 l +f +*U +0.000 0.318 0.271 0.259 k +*u +1340 166 m +1341 165 l +1340 166 l +f +*U +0.000 0.408 0.329 0.247 k +*u +1408 166 m +1409 165 l +1408 166 l +f +*U +0.000 0.882 0.627 0.118 k +*u +1448 166 m +1452.469 164 1458.191 165 1463 165 c +1493 165 l +1597 165 l +1851 165 l +1933 165 l +1945.430 165 1959.861 162.946 1972 165 c +1967.531 166.875 1961.809 166 1957 166 c +1926 166 l +1819 166 l +1448 166 l +f +*U +0.000 0.357 0.278 0.125 k +*u +2045 166 m +2046 165 l +2045 166 l +f +*U +0.000 0.216 0.161 0.176 k +*u +34 165 m +35 164 l +34 165 l +f +*U +0.000 0.667 0.525 0.333 k +*u +35 165 m +36.769 164.221 38 164 40 164 c +38.231 164.779 36.964 164.912 35 165 c +f +*U +0.000 0.871 0.616 0.125 k +*u +56 165 m +61.707 162.605 69.846 164 76 164 c +120 164 l +273 164 l +803 164 l +974 164 l +988.325 164 1002.677 164.265 1016.999 163.995 c +1022.983 163.883 1026.670 158.761 1032 163 c +1024.402 166.657 1014.282 165 1006 165 c +951 165 l +755 165 l +56 165 l +f +*U +0.000 0.094 0.086 0.192 k +*u +1056 165 m +1057 164 l +1056 165 l +f +*U +0.000 0.255 0.176 0.118 k +*u +1177.333 164.333 m +1177.278 164.278 1177.222 163.222 1177.667 163.667 c +1177.722 163.722 1177.778 164.778 1177.333 164.333 c +f +*U +0.000 0.992 0.753 0.000 k +*u +1179 165 m +1180.506 164.317 1181.315 164.174 1183 164 c +1181.494 164.683 1180.685 164.826 1179 165 c +f +*U +0.000 0.490 0.345 0.490 k +*u +1275.333 164.333 m +1275.278 164.278 1275.222 163.222 1275.667 163.667 c +1275.722 163.722 1275.778 164.778 1275.333 164.333 c +f +*U +0.000 0.369 0.267 0.231 k +*u +1276 165 m +1277 164 l +1276 165 l +f +*U +0.000 0.302 0.231 0.267 k +*u +1292.333 164.333 m +1292.278 164.278 1292.222 163.222 1292.667 163.667 c +1292.722 163.722 1292.778 164.778 1292.333 164.333 c +f +*U +0.000 0.329 0.267 0.196 k +*u +1301 165 m +1302 164 l +1301 165 l +f +*U +0.000 0.706 0.678 0.251 k +*u +1299 164 m +1301 163 1302.747 163 1305 163 c +1302.817 164.430 1301.625 164.328 1299 164 c +f +*U +0.000 0.729 0.549 0.271 k +*u +1310 164 m +1316.988 161 1331.781 161.866 1339 164 c +1330.505 166 1318.899 164 1310 164 c +f +*U +0.000 0.325 0.278 0.384 k +*u +1339 165 m +1340 164 l +1339 165 l +f +*U +0.000 0.192 0.125 0.129 k +*u +1407 165 m +1408 164 l +1407 165 l +f +*U +0.000 0.871 0.616 0.125 k +*u +1448 165 m +1452.469 163 1458.191 164 1463 164 c +1494 164 l +1600 164 l +1969 164 l +1964.531 165.875 1958.809 165 1954 165 c +1923 165 l +1817 165 l +1448 165 l +f +*U +0.000 0.259 0.188 0.224 k +*u +38.667 163.667 m +38.222 163.222 39.278 163.278 39.333 163.333 c +39.778 163.778 38.722 163.722 38.667 163.667 c +f +*U +0.000 0.608 0.478 0.392 k +*u +40 164 m +41.769 163.221 43 163 45 163 c +43.231 163.779 41.964 163.912 40 164 c +f +*U +0.000 0.729 0.549 0.271 k +*u +45 164 m +52 160.996 63.256 163 71 163 c +129 163 l +329 163 l +1024 163 l +1016.841 166 1005.744 164 998 164 c +940 164 l +740 164 l +45 164 l +f +*U +0.000 0.408 0.294 0.306 k +*u +1110 164 m +1111 163 l +1110 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1112 164 m +1116.215 162.231 1121.464 163 1126 163 c +1155 163 l +1150.785 164.769 1145.536 164 1141 164 c +1112 164 l +f +*U +0.000 0.408 0.408 0.592 k +*u +1155 164 m +1156 163 l +1155 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1179 164 m +1186.879 160.694 1199.466 163 1208 163 c +1275 163 l +1267 166.306 1254.534 164 1246 164 c +1179 164 l +f +*U +0.000 0.161 0.180 0.192 k +*u +1298.333 163.333 m +1298.278 163.278 1298.222 162.222 1298.667 162.667 c +1298.722 162.722 1298.778 163.778 1298.333 163.333 c +f +*U +0.000 0.749 0.804 0.118 k +*u +1305 164 m +1306.248 163.315 1306.548 163.251 1308 163 c +1306.752 163.685 1306.452 163.749 1305 164 c +f +*U +0.000 0.275 0.235 0.216 k +*u +1338 164 m +1339 163 l +1338 164 l +f +*U +0.000 0.729 0.549 0.271 k +*u +1438 162 m +1445 163.695 1452.719 163 1460 163 c +1495 163 l +1609 163 l +1973 163 l +1973 120 l +1974.875 124.469 1974 130.191 1974 135 c +1974 164 l +1571 164 l +1472 164 l +1448 164 l +1444.483 164.000 1440.435 164.786 1438 162 c +f +*U +0.000 0.596 0.471 0.404 k +*u +2040 164 m +2040 162 l +2041.635 162.545 2041.455 162.365 2042 164 c +2040 164 l +f +*U +0.000 0.318 0.227 0.051 k +*u +2042 164 m +2043 163 l +2042 164 l +f +*U +0.000 0.176 0.125 0.157 k +*u +45.667 162.667 m +45.222 162.222 46.278 162.278 46.333 162.333 c +46.778 162.778 45.722 162.722 45.667 162.667 c +f +*U +0.000 0.384 0.290 0.129 k +*u +47 163 m +54 159.996 65.256 162 73 162 c +130 162 l +329 162 l +1020 162 l +1012.841 165 1001.744 163 994 163 c +937 163 l +738 163 l +47 163 l +f +*U +0.000 0.361 0.271 0.227 k +*u +1020 163 m +1021.506 162.317 1022.315 162.174 1024 162 c +1022.494 162.683 1021.685 162.826 1020 163 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1111 163 m +1115.469 161 1121.192 162 1126 162 c +1155 162 l +1150.531 163.875 1144.809 163 1140 163 c +1111 163 l +f +*U +0.000 0.263 0.204 0.361 k +*u +1155 163 m +1156 162 l +1155 163 l +f +*U +0.000 0.384 0.290 0.129 k +*u +1178 163 m +1186 159.593 1199.203 162 1208 162 c +1276 162 l +1267.882 165.407 1254.797 163 1246 163 c +1178 163 l +f +*U +0.000 0.271 0.231 0.255 k +*u +1286 163 m +1288 162 1289.747 162 1292 162 c +1289.948 162.874 1288.253 162.953 1286 163 c +f +*U +0.000 0.106 0.090 0.208 k +*u +1292 163 m +1293 162 l +1292 163 l +f +*U +0.000 0.412 0.455 0.141 k +*u +1299 163 m +1300.506 162.317 1301.315 162.174 1303 162 c +1301.494 162.683 1300.685 162.826 1299 163 c +f +*U +0.000 0.290 0.325 0.184 k +*u +1303 163 m +1305.890 161.787 1308.874 162 1312 162 c +1309 163.213 1306 162.998 1303 163 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1312 163 m +1319.169 159.992 1330.239 162 1338 162 c +1330.831 165 1319.761 163 1312 163 c +f +*U +0.000 0.522 0.380 0.431 k +*u +1437.333 162.333 m +1437.278 162.278 1437.222 161.222 1437.667 161.667 c +1437.722 161.722 1437.778 162.778 1437.333 162.333 c +f +*U +0.000 0.384 0.290 0.129 k +*u +1439 163 m +1443.720 161 1449.920 162 1455 162 c +1486 162 l +1595 162 l +1973 162 l +1968.280 163.980 1962 163 1957 163 c +1926 163 l +1817 163 l +1439 163 l +f +*U +0.000 0.286 0.212 0.118 k +*u +1024 162 m +1025 161 l +1024 162 l +f +*U +0.000 0.424 0.282 0.251 k +*u +1405 162 m +1406 161 l +1405 162 l +f +*U +0.000 0.725 0.518 0.275 k +*u +1436.333 161.333 m +1436.278 161.278 1436.223 160.222 1436.667 160.667 c +1436.722 160.722 1436.778 161.778 1436.333 161.333 c +f +*U +0.000 0.275 0.200 0.102 k +*u +1438 162 m +1439 161 l +1438 162 l +f +*U +0.000 0.435 0.329 0.380 k +*u +2037 162 m +2037 160 l +2038.635 160.545 2038.455 160.365 2039 162 c +2037 162 l +f +*U +0.000 0.353 0.282 0.043 k +*u +2039 162 m +2040 161 l +2039 162 l +f +*U +0.020 0.000 0.027 0.000 k +*u +56 161 m +63 157.996 74.256 160 82 160 c +139 160 l +337 160 l +1023 160 l +1015.841 163 1004.744 161 997 161 c +940 161 l +742 161 l +56 161 l +f +*U +0.000 0.333 0.243 0.376 k +*u +1025 161 m +1026 160 l +1025 161 l +f +*U +0.000 0.243 0.157 0.122 k +*u +1404 161 m +1405 160 l +1404 161 l +f +*U +0.000 0.408 0.294 0.247 k +*u +1437 161 m +1438 160 l +1437 161 l +f +*U +0.020 0.000 0.027 0.000 k +*u +1440 161 m +1444.469 159 1450.191 160 1455 160 c +1486 160 l +1595 160 l +1971 160 l +1971 128 l +1972.552 131.699 1972 136 1972 140 c +1972 161 l +1440 161 l +f +*U +0.000 0.514 0.463 0.486 k +*u +2036 161 m +2037 160 l +2036 161 l +f +*U +0.000 0.290 0.235 0.439 k +*u +1026 160 m +1027 159 l +1026 160 l +f +*U +0.000 0.498 0.373 0.408 k +*u +1027.333 159.333 m +1027.278 159.278 1027.222 158.222 1027.667 158.667 c +1027.722 158.722 1027.778 159.778 1027.333 159.333 c +f +*U +0.000 0.400 0.333 0.220 k +*u +1060 160 m +1061 159 l +1060 160 l +f +*U +0.000 0.600 0.486 0.400 k +*u +1404 160 m +1403 158.521 1403 158.797 1403 157 c +1404.289 158.443 1404.401 158.234 1404 160 c +f +*U +0.000 0.400 0.325 0.447 k +*u +1435.667 159.667 m +1435.222 159.222 1436.278 159.278 1436.333 159.333 c +1436.778 159.778 1435.722 159.722 1435.667 159.667 c +f +*U +0.000 0.694 0.478 0.282 k +*u +1974 160 m +1974 122 l +1977 129.399 1975 140.993 1975 149 c +1975 152.702 1975.441 156.566 1974 160 c +f +*U +0.000 0.259 0.165 0.565 k +*u +2034.667 159.667 m +2034.222 159.222 2035.278 159.278 2035.333 159.333 c +2035.778 159.778 2034.722 159.722 2034.667 159.667 c +f +*U +0.000 0.051 0.031 0.192 k +*u +2036 160 m +2037 159 l +2036 160 l +f +*U +0.000 0.749 0.553 0.251 k +*u +1060 159 m +1061 155 l +1061.553 157 1061.303 157.332 1060 159 c +f +*U +0.000 0.314 0.243 0.271 k +*u +1061 159 m +1062 158 l +1061 159 l +f +*U +0.000 0.420 0.416 0.580 k +*u +1435 159 m +1436 158 l +1435 159 l +f +*U +0.000 0.510 0.373 0.490 k +*u +2032 159 m +2032 157 l +2033.635 157.545 2033.455 157.365 2034 159 c +2032 159 l +f +*U +0.000 0.376 0.255 0.267 k +*u +2034 159 m +2035 158 l +2034 159 l +f +*U +0.000 0.157 0.133 0.188 k +*u +1027 158 m +1028 157 l +1027 158 l +f +*U +0.000 0.420 0.384 0.580 k +*u +1028 158 m +1029 157 l +1028 158 l +f +*U +0.000 0.251 0.184 0.133 k +*u +1062 158 m +1063 157 l +1062 158 l +f +*U +0.000 0.392 0.302 0.357 k +*u +1402 158 m +1403 157 l +1402 158 l +f +*U +0.000 0.533 0.396 0.384 k +*u +1434.333 157.333 m +1434.278 157.278 1434.222 156.222 1434.667 156.667 c +1434.722 156.722 1434.778 157.778 1434.333 157.333 c +f +*U +0.000 0.325 0.267 0.263 k +*u +1435 158 m +1436 157 l +1435 158 l +f +*U +0.000 0.227 0.180 0.357 k +*u +1028 157 m +1029 156 l +1028 157 l +f +*U +0.000 0.624 0.490 0.376 k +*u +1062 157 m +1063.324 154.313 1064.313 153.324 1067 152 c +1065.451 154 1064 155.451 1062 157 c +f +*U +0.000 0.267 0.200 0.165 k +*u +1063 157 m +1064 156 l +1063 157 l +f +*U +0.000 0.290 0.235 0.227 k +*u +1401 157 m +1402 156 l +1401 157 l +f +*U +0.000 0.569 0.467 0.431 k +*u +1402 157 m +1403 156 l +1402 157 l +f +*U +0.000 0.471 0.420 0.529 k +*u +2030 157 m +2031 156 l +2030 157 l +f +*U +0.000 0.388 0.329 0.110 k +*u +2031 157 m +2032 156 l +2031 157 l +f +*U +0.000 0.427 0.345 0.114 k +*u +1400 156 m +1401 155 l +1400 156 l +f +*U +0.000 0.537 0.420 0.463 k +*u +1433 156 m +1434 155 l +1433 156 l +f +*U +0.000 0.200 0.165 0.129 k +*u +1434 156 m +1435 155 l +1434 156 l +f +*U +0.000 0.361 0.294 0.357 k +*u +2029 156 m +2030 155 l +2029 156 l +f +*U +0.000 0.216 0.141 0.173 k +*u +1399 155 m +1400 154 l +1399 155 l +f +*U +0.000 0.298 0.251 0.243 k +*u +1433 155 m +1434 154 l +1433 155 l +f +*U +0.000 0.494 0.376 0.498 k +*u +2027 155 m +2028 154 l +2027 155 l +f +*U +0.000 0.192 0.169 0.157 k +*u +2028 155 m +2029 154 l +2028 155 l +f +*U +0.000 0.267 0.196 0.110 k +*u +1030 154 m +1031 153 l +1030 154 l +f +*U +0.000 0.620 0.431 0.380 k +*u +1399.333 153.333 m +1399.278 153.278 1399.222 152.222 1399.667 152.667 c +1399.722 152.722 1399.778 153.778 1399.333 153.333 c +f +*U +0.000 0.612 0.561 0.388 k +*u +1431.333 153.333 m +1431.278 153.278 1431.222 152.222 1431.667 152.667 c +1431.722 152.722 1431.778 153.778 1431.333 153.333 c +f +*U +0.000 0.306 0.267 0.435 k +*u +1432 154 m +1433 153 l +1432 154 l +f +*U +0.000 0.396 0.306 0.365 k +*u +2026 154 m +2027 153 l +2026 154 l +f +*U +0.000 0.259 0.196 0.231 k +*u +1031 153 m +1032 152 l +1031 153 l +f +*U +0.000 0.427 0.271 0.349 k +*u +1398 153 m +1399 152 l +1398 153 l +f +*U +0.000 0.467 0.420 0.533 k +*u +2024 153 m +2025 152 l +2024 153 l +f +*U +0.000 0.392 0.294 0.012 k +*u +2025 153 m +2026 152 l +2025 153 l +f +*U +0.000 0.322 0.224 0.255 k +*u +1032 152 m +1033 151 l +1032 152 l +f +*U +0.000 0.384 0.365 0.616 k +*u +1033 152 m +1034 151 l +1033 152 l +f +*U +0.000 0.710 0.498 0.282 k +*u +1067 152 m +1067.684 149.791 1068 149.297 1070 148 c +1069 149.948 1068.607 150.550 1067 152 c +f +*U +0.000 0.180 0.129 0.188 k +*u +1125 152 m +1126 151 l +1125 152 l +f +*U +0.000 0.616 0.455 0.373 k +*u +1126 152 m +1130.564 149.361 1138.689 151 1144 151 c +1138.777 153.191 1131.632 152 1126 152 c +f +*U +0.000 0.522 0.400 0.447 k +*u +1144 152 m +1147.959 150.339 1152.740 151 1157 151 c +1180 151 l +1176 152.661 1171.260 152 1167 152 c +1144 152 l +f +*U +0.000 0.718 0.545 0.282 k +*u +1180 152 m +1181.458 150.919 1182.248 150.564 1184 150 c +1182.686 151.618 1182 151.693 1180 152 c +f +*U +0.000 0.000 0.000 0.298 k +*u +1214.667 151.667 m +1214.222 151.222 1215.278 151.278 1215.333 151.333 c +1215.778 151.778 1214.722 151.722 1214.667 151.667 c +f +*U +0.000 0.145 0.114 0.180 k +*u +1233 152 m +1234 151 l +1233 152 l +f +*U +0.000 0.325 0.325 0.675 k +*u +1234 152 m +1235 151 l +1234 152 l +f +*U +0.000 0.529 0.384 0.467 k +*u +1235.333 151.333 m +1235.278 151.278 1235.222 150.222 1235.667 150.667 c +1235.722 150.722 1235.778 151.778 1235.333 151.333 c +f +*U +0.000 0.741 0.529 0.251 k +*u +1236 152 m +1236.307 149.877 1236.382 149.314 1238 148 c +1237.404 149.560 1236.911 150.623 1236 152 c +f +*U +0.000 0.616 0.463 0.376 k +*u +1237 152 m +1242.469 149.705 1250 151 1256 151 c +1250.531 153.295 1242.901 152 1237 152 c +f +*U +0.000 0.522 0.400 0.447 k +*u +1256 152 m +1261.707 149.605 1269.846 151 1276 151 c +1290.998 151 1307.230 152.742 1322 150 c +1318.696 153.781 1309.740 152 1305 152 c +1256 152 l +f +*U +0.000 0.278 0.251 0.722 k +*u +1322 152 m +1323 151 l +1322 152 l +f +*U +0.000 0.145 0.094 0.333 k +*u +1323 152 m +1324 151 l +1323 152 l +f +*U +0.000 0.804 0.600 0.196 k +*u +1397 152 m +1395.998 149.386 1395.678 147.773 1396 145 c +1399 146 l +1397 149 l +1398.924 150 1399 150 1400 152 c +1397 152 l +f +*U +0.000 0.455 0.463 0.490 k +*u +1430 152 m +1431 151 l +1430 152 l +f +*U +0.110 0.000 0.071 0.133 k +*u +1431 152 m +1432 151 l +1431 152 l +f +*U +0.000 0.514 0.337 0.486 k +*u +2022 152 m +2023 151 l +2022 152 l +f +*U +0.000 0.349 0.204 0.290 k +*u +2023 152 m +2024 151 l +2023 152 l +f +*U +0.000 0.263 0.184 0.325 k +*u +1126 151 m +1127 150 l +1126 151 l +f +*U +0.000 0.894 0.651 0.106 k +*u +1128 151 m +1131.547 146.985 1139.689 140.968 1145 139.938 c +1151 138.752 1158.724 140 1165 140 c +1205 140 l +1205 142 l +1202.214 142.355 1199.684 143.535 1196.911 143.871 c +1193.952 144.229 1190.807 143.588 1188 145 c +1184.936 146.650 1183.611 150 1179.946 150.772 c +1174.300 151.876 1167.742 151 1162 151 c +1128 151 l +f +*U +0.000 0.243 0.176 0.090 k +*u +1234 151 m +1235 150 l +1234 151 l +f +*U +0.000 0.882 0.635 0.118 k +*u +1237 151 m +1238.959 144.618 1244.912 145.185 1248 140 c +1265.500 140 1284.675 137.762 1302 140 c +1307.844 140.959 1317 145.842 1320 151 c +1237 151 l +f +*U +0.000 0.263 0.176 0.133 k +*u +1322 151 m +1323 150 l +1322 151 l +f +*U +0.000 0.341 0.282 0.286 k +*u +1396 151 m +1397 150 l +1396 151 l +f +*U +0.000 0.306 0.345 0.365 k +*u +1430 151 m +1431 150 l +1430 151 l +f +*U +0.000 0.545 0.451 0.455 k +*u +1034 150 m +1035 149 l +1034 150 l +f +*U +0.000 0.698 0.510 0.278 k +*u +1128.667 149.667 m +1128.222 149.222 1129.278 149.278 1129.333 149.333 c +1129.778 149.778 1128.722 149.722 1128.667 149.667 c +f +*U +0.000 0.282 0.208 0.224 k +*u +1235 150 m +1236 149 l +1235 150 l +f +*U +0.000 0.275 0.180 0.329 k +*u +1320 150 m +1321 149 l +1320 150 l +f +*U +0.000 0.286 0.208 0.369 k +*u +1395 150 m +1396 149 l +1395 150 l +f +*U +0.000 0.310 0.231 0.396 k +*u +1429 150 m +1430 149 l +1429 150 l +f +*U +0.000 0.384 0.267 0.259 k +*u +2020 150 m +2021 149 l +2020 150 l +f +*U +0.000 0.294 0.212 0.176 k +*u +1034 149 m +1035 148 l +1034 149 l +f +*U +0.000 0.349 0.271 0.243 k +*u +1070 149 m +1071 148 l +1070 149 l +f +*U +0.000 0.282 0.220 0.204 k +*u +1129 149 m +1130 148 l +1129 149 l +f +*U +0.000 0.224 0.169 0.443 k +*u +1184 149 m +1185 148 l +1184 149 l +f +*U +0.000 0.459 0.302 0.525 k +*u +1317.667 148.667 m +1317.222 148.222 1318.278 148.278 1318.333 148.333 c +1318.778 148.778 1317.722 148.722 1317.667 148.667 c +f +*U +0.000 0.278 0.141 0.086 k +*u +1319 149 m +1320 148 l +1319 149 l +f +*U +0.000 0.271 0.180 0.204 k +*u +1394 149 m +1395 148 l +1394 149 l +f +*U +0.000 0.651 0.494 0.349 k +*u +1427 149 m +1427 147 l +1428.635 147.545 1428.455 147.365 1429 149 c +1427 149 l +f +*U +0.000 0.553 0.384 0.380 k +*u +2017.667 148.667 m +2017.222 148.222 2018.278 148.278 2018.333 148.333 c +2018.778 148.778 2017.722 148.722 2017.667 148.667 c +f +*U +0.000 0.247 0.169 0.110 k +*u +2019 149 m +2020 148 l +2019 149 l +f +*U +0.000 0.306 0.224 0.259 k +*u +1035 148 m +1036 147 l +1035 148 l +f +*U +0.000 0.486 0.365 0.125 k +*u +1071 148 m +1072 147 l +1071 148 l +f +*U +0.000 0.420 0.314 0.275 k +*u +1131 148 m +1132 147 l +1131 148 l +f +*U +0.000 0.553 0.361 0.412 k +*u +1184 148 m +1188 143.180 1193.174 144 1199 144 c +1194.338 145.956 1188.933 146 1184 148 c +f +*U +0.000 0.200 0.165 0.165 k +*u +1236 148 m +1237 147 l +1236 148 l +f +*U +0.000 0.431 0.325 0.424 k +*u +1237 148 m +1237.684 146.420 1237.805 146.223 1239 145 c +1238.316 146.580 1238.195 146.777 1237 148 c +f +*U +0.000 0.318 0.251 0.431 k +*u +1317 148 m +1318 147 l +1317 148 l +f +*U +0.000 0.306 0.204 0.188 k +*u +1393 148 m +1394 147 l +1393 148 l +f +*U +0.000 0.522 0.404 0.478 k +*u +1394 148 m +1395 147 l +1394 148 l +f +*U +0.000 0.278 0.231 0.102 k +*u +1428 148 m +1429 147 l +1428 148 l +f +*U +0.000 0.380 0.259 0.290 k +*u +2017 148 m +2018 147 l +2017 148 l +f +*U +0.000 0.208 0.161 0.306 k +*u +1036 147 m +1037 146 l +1036 147 l +f +*U +0.000 0.243 0.212 0.416 k +*u +1072 147 m +1073 146 l +1072 147 l +f +*U +0.000 0.255 0.204 0.133 k +*u +1132 147 m +1133 146 l +1132 147 l +f +*U +0.000 0.714 0.537 0.286 k +*u +1133.667 146.667 m +1133.222 146.222 1134.278 146.278 1134.333 146.333 c +1134.778 146.778 1133.722 146.722 1133.667 146.667 c +f +*U +0.000 0.196 0.184 0.153 k +*u +1316 147 m +1317 146 l +1316 147 l +f +*U +0.000 0.400 0.290 0.035 k +*u +1392 147 m +1393 146 l +1392 147 l +f +*U +0.000 0.718 0.545 0.282 k +*u +1393 147 m +1392 145 l +1394 145 l +1394 146.853 1394.300 146.350 1393 147 c +f +*U +0.000 0.667 0.424 0.333 k +*u +1425 147 m +1425 144 l +1426.195 145.223 1426.316 145.420 1427 147 c +1425 147 l +f +*U +0.000 0.361 0.275 0.184 k +*u +1427 147 m +1428 146 l +1427 147 l +f +*U +0.000 0.204 0.133 0.122 k +*u +2016 147 m +2017 146 l +2016 147 l +f +*U +0.000 0.412 0.306 0.282 k +*u +1037 146 m +1038 145 l +1037 146 l +f +*U +0.000 0.565 0.467 0.435 k +*u +1072 146 m +1073 145 l +1072 146 l +f +*U +0.000 0.412 0.341 0.141 k +*u +1073 146 m +1074 145 l +1073 146 l +f +*U +0.000 0.306 0.243 0.216 k +*u +1134 146 m +1135 145 l +1134 146 l +f +*U +0.000 0.475 0.392 0.525 k +*u +1135 146 m +1136 145 l +1135 146 l +f +*U +0.000 0.102 0.067 0.227 k +*u +1195 146 m +1196.248 145.315 1196.549 145.251 1198 145 c +1196.751 145.685 1196.452 145.749 1195 146 c +f +*U +0.000 0.200 0.173 0.329 k +*u +1237 146 m +1238 145 l +1237 146 l +f +*U +0.000 0.592 0.498 0.408 k +*u +1313 146 m +1314 145 l +1313 146 l +f +*U +0.000 0.471 0.353 0.208 k +*u +1314 146 m +1315 145 l +1314 146 l +f +*U +0.000 0.506 0.396 0.451 k +*u +2012.667 145.667 m +2012.222 145.222 2013.278 145.278 2013.333 145.333 c +2013.778 145.778 2012.722 145.722 2012.667 145.667 c +f +*U +0.000 0.345 0.259 0.220 k +*u +2014 146 m +2015 145 l +2014 146 l +f +*U +0.000 0.569 0.467 0.431 k +*u +1073 145 m +1074 144 l +1073 145 l +f +*U +0.000 0.247 0.212 0.341 k +*u +1074 145 m +1075 144 l +1074 145 l +f +*U +0.000 0.114 0.129 0.125 k +*u +1135 145 m +1136 144 l +1135 145 l +f +*U +0.000 0.647 0.420 0.133 k +*u +1199 145 m +1200 144 l +1199 145 l +f +*U +0.000 0.180 0.169 0.153 k +*u +1238 145 m +1239 144 l +1238 145 l +f +*U +0.000 0.459 0.361 0.125 k +*u +1239 145 m +1240 144 l +1239 145 l +f +*U +0.000 0.580 0.486 0.420 k +*u +1240 145 m +1241.506 144.317 1242.315 144.174 1244 144 c +1242.494 144.683 1241.686 144.826 1240 145 c +f +*U +0.000 0.329 0.282 0.580 k +*u +1312 145 m +1313 144 l +1312 145 l +f +*U +0.000 0.224 0.141 0.584 k +*u +1391 145 m +1392 144 l +1391 145 l +f +*U +0.000 0.482 0.427 0.231 k +*u +2012 145 m +2013 144 l +2012 145 l +f +*U +0.000 0.188 0.118 0.671 k +*u +1039 144 m +1040 143 l +1039 144 l +f +*U +0.000 0.741 0.463 0.259 k +*u +1040 144 m +1040.684 142.420 1040.805 142.223 1042 141 c +1042 144 l +1040 144 l +f +*U +0.000 0.463 0.443 0.173 k +*u +1075 144 m +1076 143 l +1075 144 l +f +*U +0.000 0.192 0.137 0.294 k +*u +1137 144 m +1138 143 l +1137 144 l +f +*U +0.000 0.698 0.533 0.302 k +*u +1138.667 143.667 m +1138.222 143.222 1139.278 143.278 1139.333 143.333 c +1139.778 143.778 1138.722 143.722 1138.667 143.667 c +f +*U +0.000 0.067 0.114 0.302 k +*u +1200 144 m +1201 143 l +1200 144 l +f +*U +0.000 0.086 0.012 0.192 k +*u +1243 144 m +1244 143 l +1243 144 l +f +*U +0.000 0.290 0.161 0.376 k +*u +1244 144 m +1245 143 l +1244 144 l +f +*U +0.000 0.416 0.259 0.573 k +*u +1309.667 143.667 m +1309.222 143.222 1310.278 143.278 1310.333 143.333 c +1310.778 143.778 1309.722 143.722 1309.667 143.667 c +f +*U +0.000 0.337 0.180 0.039 k +*u +1311 144 m +1312 143 l +1311 144 l +f +*U +0.000 0.682 0.498 0.282 k +*u +1390 144 m +1387.794 141.748 1385.807 139.576 1384 137 c +1387 138.489 1390 140.283 1390 144 c +f +*U +0.000 0.243 0.149 0.686 k +*u +1424 144 m +1425 143 l +1424 144 l +f +*U +0.000 0.180 0.114 0.125 k +*u +1425 144 m +1426 143 l +1425 144 l +f +*U +0.000 0.443 0.286 0.463 k +*u +2009.667 143.667 m +2009.222 143.223 2010.277 143.277 2010.333 143.333 c +2010.778 143.778 2009.722 143.722 2009.667 143.667 c +f +*U +0.000 0.169 0.102 0.173 k +*u +2011 144 m +2012 143 l +2011 144 l +f +*U +0.000 0.180 0.118 0.176 k +*u +1039 143 m +1040 142 l +1039 143 l +f +*U +0.000 0.502 0.400 0.341 k +*u +1075 143 m +1076.223 141.805 1076.420 141.684 1078 141 c +1076.777 142.195 1076.580 142.316 1075 143 c +f +*U +0.000 0.365 0.263 0.247 k +*u +1139 143 m +1140 142 l +1139 143 l +f +*U +0.000 0.471 0.365 0.486 k +*u +1200 143 m +1201 142 l +1200 143 l +f +*U +0.000 0.420 0.329 0.259 k +*u +1201 143 m +1202 142 l +1201 143 l +f +*U +0.000 0.275 0.235 0.067 k +*u +1202 143 m +1203 142 l +1202 143 l +f +*U +0.000 0.137 0.110 0.122 k +*u +1210 143 m +1211 142 l +1210 143 l +f +*U +0.000 0.290 0.216 0.306 k +*u +1211 143 m +1212 142 l +1211 143 l +f +*U +0.000 0.537 0.467 0.431 k +*u +1212 143 m +1214 142 1215.747 142 1218 142 c +1215.948 142.874 1214.253 142.953 1212 143 c +f +*U +0.000 0.267 0.216 0.259 k +*u +1218 143 m +1219 142 l +1218 143 l +f +*U +0.000 0.349 0.224 0.000 k +*u +1245 143 m +1246 142 l +1245 143 l +f +*U +0.000 0.471 0.345 0.306 k +*u +1246 143 m +1246 140 l +1246.696 141.554 1246.696 141.446 1246 143 c +f +*U +0.000 0.576 0.435 0.353 k +*u +1247 143 m +1246 139 l +1247.656 140.404 1247.751 140.954 1247 143 c +f +*U +0.000 0.357 0.259 0.310 k +*u +1309 143 m +1310 142 l +1309 143 l +f +*U +0.000 0.161 0.098 0.263 k +*u +1424 143 m +1425 142 l +1424 143 l +f +*U +0.000 0.557 0.361 0.427 k +*u +2008 143 m +2009 142 l +2008 143 l +f +*U +0.000 0.478 0.322 0.098 k +*u +2009 143 m +2010 142 l +2009 143 l +f +*U +0.000 0.282 0.212 0.075 k +*u +1040 142 m +1041 141 l +1040 142 l +f +*U +0.000 0.329 0.239 0.055 k +*u +1140 142 m +1141 141 l +1140 142 l +f +*U +0.000 0.580 0.455 0.420 k +*u +1205 142 m +1206.769 141.221 1208 141 1210 141 c +1208.231 141.779 1206.964 141.912 1205 142 c +f +*U +0.000 0.945 0.667 0.055 k +*u +1205 141 m +1208.959 139.339 1213.737 140 1218 140 c +1218 142 l +1205 141 l +f +*U +0.000 0.667 0.522 0.333 k +*u +1218 142 m +1212.887 138 1203.218 140 1197 140 c +1146 140 l +1152.436 137.299 1162 139 1169 139 c +1220 139 l +1219.316 140.580 1219.195 140.777 1218 142 c +f +*U +0.000 0.329 0.251 0.075 k +*u +1219 142 m +1220 141 l +1219 142 l +f +*U +0.000 0.604 0.459 0.396 k +*u +1306 142 m +1307 141 l +1306 142 l +f +*U +0.000 0.361 0.298 0.396 k +*u +1307 142 m +1308 141 l +1307 142 l +f +*U +0.000 0.369 0.306 0.353 k +*u +1423 142 m +1424 141 l +1423 142 l +f +*U +0.000 0.659 0.471 0.341 k +*u +2006.667 141.667 m +2006.222 141.222 2007.278 141.278 2007.333 141.333 c +2007.778 141.778 2006.722 141.722 2006.667 141.667 c +f +*U +0.000 0.184 0.125 0.133 k +*u +2008 142 m +2009 141 l +2008 142 l +f +*U +0.000 0.361 0.337 0.086 k +*u +1041 141 m +1042 140 l +1041 141 l +f +*U +0.000 0.620 0.475 0.380 k +*u +1042 141 m +1043 140 l +1042 141 l +f +*U +0.000 0.706 0.490 0.294 k +*u +1077 141 m +1078.573 138.338 1080 137.228 1083 136 c +1081 138.447 1079.763 139.700 1077 141 c +f +*U +0.000 0.325 0.235 0.082 k +*u +1142 141 m +1143 140 l +1142 141 l +f +*U +0.000 0.443 0.337 0.188 k +*u +1220 141 m +1221 140 l +1220 141 l +f +*U +0.000 0.412 0.388 0.588 k +*u +1304 141 m +1305 140 l +1304 141 l +f +*U +0.000 0.420 0.318 0.380 k +*u +1305 141 m +1306 140 l +1305 141 l +f +*U +0.000 0.427 0.325 0.341 k +*u +1422 141 m +1423 140 l +1422 141 l +f +*U +0.000 0.439 0.431 0.561 k +*u +2005 141 m +2006 140 l +2005 141 l +f +*U +0.000 0.329 0.227 0.325 k +*u +2006 141 m +2007 140 l +2006 141 l +f +*U +0.000 0.267 0.220 0.235 k +*u +1042 140 m +1043 139 l +1042 140 l +f +*U +0.000 0.604 0.412 0.000 k +*u +1144 140 m +1145 139 l +1144 140 l +f +*U +0.000 0.400 0.388 0.600 k +*u +1220.667 139.667 m +1220.222 139.222 1221.278 139.278 1221.333 139.333 c +1221.778 139.778 1220.722 139.722 1220.667 139.667 c +f +*U +0.000 0.416 0.267 0.325 k +*u +1222 140 m +1223 139 l +1222 140 l +f +*U +0.000 0.145 0.075 0.220 k +*u +1222 138 m +1223.580 138.684 1223.777 138.805 1225 140 c +1223.420 139.316 1223.223 139.195 1222 138 c +f +*U +0.000 0.204 0.137 0.169 k +*u +1227 139 m +1230.607 137.487 1234.260 138 1238 139 c +1234.672 140 1230.479 139.411 1227 139 c +f +*U +0.000 0.259 0.165 0.396 k +*u +1229 140 m +1230.248 139.315 1230.548 139.251 1232 139 c +1230.751 139.685 1230.452 139.749 1229 140 c +f +*U +0.000 0.227 0.153 0.286 k +*u +1232 140 m +1233.248 139.315 1233.548 139.251 1235 139 c +1233.751 139.685 1233.452 139.749 1232 140 c +f +*U +0.000 0.067 0.078 0.518 k +*u +1239.667 139.667 m +1239.222 139.222 1240.278 139.278 1240.333 139.333 c +1240.778 139.778 1239.722 139.722 1239.667 139.667 c +f +*U +0.000 0.667 0.522 0.333 k +*u +1248 140 m +1253.216 137.811 1260.381 139 1266 139 c +1304 139 l +1298.783 141.189 1291.619 140 1286 140 c +1248 140 l +f +*U +0.000 0.404 0.314 0.596 k +*u +1421 140 m +1422 139 l +1421 140 l +f +*U +0.000 0.498 0.384 0.427 k +*u +2003.667 139.667 m +2003.222 139.222 2004.278 139.278 2004.333 139.333 c +2004.778 139.778 2003.722 139.722 2003.667 139.667 c +f +*U +0.000 0.373 0.298 0.259 k +*u +1043 139 m +1044 138 l +1043 139 l +f +*U +0.000 0.675 0.533 0.294 k +*u +1044 139 m +1045 136.643 1045.956 135.624 1048 134 c +1046.987 136.485 1046.274 137.598 1044 139 c +f +*U +0.012 0.000 0.024 0.145 k +*u +1145.667 138.667 m +1145.222 138.222 1146.278 138.278 1146.333 138.333 c +1146.778 138.778 1145.722 138.722 1145.667 138.667 c +f +*U +0.000 0.035 0.024 0.251 k +*u +1238 139 m +1239 138 l +1238 139 l +f +*U +0.000 0.310 0.251 0.071 k +*u +1247 139 m +1248 138 l +1247 139 l +f +*U +0.000 0.039 0.035 0.220 k +*u +1299.667 138.667 m +1299.222 138.222 1300.278 138.278 1300.333 138.333 c +1300.778 138.778 1299.722 138.722 1299.667 138.667 c +f +*U +0.000 0.424 0.365 0.576 k +*u +1420 139 m +1421 138 l +1420 139 l +f +*U +0.000 0.455 0.357 0.102 k +*u +2003 139 m +2004 138 l +2003 139 l +f +*U +0.000 0.420 0.388 0.580 k +*u +1419 138 m +1420 137 l +1419 138 l +f +*U +0.000 0.235 0.173 0.110 k +*u +1420 138 m +1421 137 l +1420 138 l +f +*U +0.000 0.561 0.424 0.192 k +*u +2001 138 m +2002 137 l +2001 138 l +f +*U +0.000 0.337 0.255 0.071 k +*u +2002 138 m +2003 137 l +2002 138 l +f +*U +0.000 0.145 0.086 0.169 k +*u +1083 137 m +1084 136 l +1083 137 l +f +*U +0.000 0.110 0.047 0.729 k +*u +1383 137 m +1384 136 l +1383 137 l +f +*U +0.000 0.318 0.251 0.110 k +*u +1419 137 m +1420 136 l +1419 137 l +f +*U +0.000 0.333 0.302 0.153 k +*u +2000 137 m +2001 136 l +2000 137 l +f +*U +0.000 0.796 0.576 0.204 k +*u +1083 136 m +1084 132.767 1085.455 130.310 1088 128 c +1089.198 129.245 1089 129 1091 129 c +1088.615 131.749 1086 133.943 1083 136 c +f +*U +0.000 0.271 0.290 0.102 k +*u +1084 136 m +1085 135 l +1084 136 l +f +*U +0.000 0.490 0.365 0.510 k +*u +1417 136 m +1418 135 l +1417 136 l +f +*U +0.000 0.231 0.149 0.318 k +*u +1418 136 m +1419 135 l +1418 136 l +f +*U +0.000 0.463 0.345 0.431 k +*u +1995 134 m +1996.580 134.684 1996.777 134.805 1998 136 c +1996.420 135.316 1996.223 135.195 1995 134 c +f +*U +0.000 0.129 0.102 0.475 k +*u +1998 136 m +1999 135 l +1998 136 l +f +*U +0.000 0.267 0.196 0.251 k +*u +1085 135 m +1086 134 l +1085 135 l +f +*U +0.000 0.545 0.361 0.455 k +*u +1416 135 m +1417 134 l +1416 135 l +f +*U +0.000 0.384 0.255 0.157 k +*u +1417 135 m +1418 134 l +1417 135 l +f +*U +0.000 0.275 0.216 0.082 k +*u +1997 135 m +1998 134 l +1997 135 l +f +*U +0.000 0.341 0.239 0.271 k +*u +1086 134 m +1087 133 l +1086 134 l +f +*U +0.000 0.514 0.380 0.486 k +*u +1380 134 m +1381 133 l +1380 134 l +f +*U +0.000 0.616 0.431 0.380 k +*u +1415 134 m +1413.242 131.988 1412 130.419 1411 128 c +1413.348 129.773 1415 131 1415 134 c +f +*U +0.000 0.224 0.137 0.314 k +*u +1416 134 m +1417 133 l +1416 134 l +f +*U +0.000 0.525 0.408 0.475 k +*u +1994 134 m +1995 133 l +1994 134 l +f +*U +0.000 0.337 0.243 0.306 k +*u +1995 134 m +1996 133 l +1995 134 l +f +*U +0.000 0.204 0.157 0.125 k +*u +1048 133 m +1049 132 l +1048 133 l +f +*U +0.000 0.494 0.420 0.227 k +*u +1087 133 m +1088 132 l +1087 133 l +f +*U +0.000 0.510 0.510 0.459 k +*u +1379 133 m +1380 132 l +1379 133 l +f +*U +0.000 0.796 0.600 0.196 k +*u +1380 133 m +1378.390 131.672 1377.299 130.617 1376 129 c +1380 128 l +1379.402 129.196 1379.534 128.977 1378 130 c +1379.994 130.847 1380.699 131 1380 133 c +f +*U +0.000 0.533 0.400 0.455 k +*u +1992.667 132.667 m +1992.222 132.222 1993.278 132.278 1993.333 132.333 c +1993.778 132.778 1992.722 132.722 1992.667 132.667 c +f +*U +0.000 0.318 0.220 0.051 k +*u +1994 133 m +1995 132 l +1994 133 l +f +*U +0.000 0.341 0.235 0.439 k +*u +1088 132 m +1089 131 l +1088 132 l +f +*U +0.000 0.251 0.271 0.157 k +*u +1377 132 m +1378 131 l +1377 132 l +f +*U +0.000 0.212 0.188 0.373 k +*u +1992 132 m +1993 131 l +1992 132 l +f +*U +0.000 0.525 0.424 0.475 k +*u +1051 131 m +1052 130 l +1051 131 l +f +*U +0.000 0.286 0.263 0.180 k +*u +1376 131 m +1377 130 l +1376 131 l +f +*U +0.000 0.439 0.341 0.349 k +*u +1989 131 m +1989 129 l +1990.635 129.545 1990.455 129.365 1991 131 c +1989 131 l +f +*U +0.000 0.337 0.275 0.059 k +*u +1991 131 m +1992 130 l +1991 131 l +f +*U +0.000 0.486 0.431 0.514 k +*u +1052 130 m +1053 129 l +1052 130 l +f +*U +0.000 0.275 0.200 0.286 k +*u +1091 130 m +1092 129 l +1091 130 l +f +*U +0.000 0.325 0.204 0.204 k +*u +1375 130 m +1376 129 l +1375 130 l +f +*U +0.000 0.953 0.620 0.047 k +*u +1380 128 m +1381.580 128.684 1381.777 128.805 1383 130 c +1381.420 129.317 1381.223 129.195 1380 128 c +f +*U +0.000 0.525 0.396 0.475 k +*u +1988 130 m +1989 129 l +1988 130 l +f +*U +0.000 0.251 0.180 0.349 k +*u +1092 129 m +1093 128 l +1092 129 l +f +*U +0.000 0.306 0.200 0.302 k +*u +1374 129 m +1375 128 l +1374 129 l +f +*U +0.000 0.486 0.310 0.514 k +*u +1375 129 m +1376 128 l +1375 129 l +f +*U +0.000 0.180 0.141 0.059 k +*u +1412 129 m +1413 128 l +1412 129 l +f +*U +0.000 0.408 0.333 0.424 k +*u +1986.667 128.667 m +1986.222 128.223 1987.277 128.277 1987.333 128.333 c +1987.778 128.778 1986.722 128.722 1986.667 128.667 c +f +*U +0.000 0.192 0.173 0.149 k +*u +1988 129 m +1989 128 l +1988 129 l +f +*U +0.000 0.506 0.561 0.427 k +*u +1054 128 m +1054.545 126.365 1054.365 126.545 1056 126 c +1056 128 l +1054 128 l +f +*U +0.000 0.588 0.443 0.329 k +*u +1092 128 m +1093.624 125.956 1094.643 125 1097 124 c +1095.376 126 1094.357 126.896 1092 128 c +f +*U +0.000 0.192 0.129 0.506 k +*u +1173 128 m +1174 127 l +1173 128 l +f +*U +0.000 0.220 0.220 0.780 k +*u +1174.667 127.667 m +1174.222 127.223 1175.278 127.278 1175.333 127.333 c +1175.778 127.778 1174.722 127.722 1174.667 127.667 c +f +*U +0.000 0.580 0.420 0.420 k +*u +1176 128 m +1180.271 125 1188.772 127 1194 127 c +1240 127 l +1234.293 129.395 1226 128 1220 128 c +1176 128 l +f +*U +0.000 0.529 0.412 0.471 k +*u +1240 128 m +1247.409 124.891 1258.975 127 1267 127 c +1259.591 130 1248 128 1240 128 c +f +*U +0.000 0.620 0.467 0.380 k +*u +1264 126 m +1266.698 125 1269 125.647 1272 126 c +1269 128 1267.224 127 1264 126 c +f +*U +0.000 0.247 0.247 0.753 k +*u +1271 128 m +1272.506 127.317 1273.315 127.174 1275 127 c +1273.494 127.683 1272.685 127.826 1271 128 c +f +*U +0.000 0.192 0.192 0.478 k +*u +1275 128 m +1276 127 l +1275 128 l +f +*U +0.000 0.098 0.102 0.200 k +*u +1276 128 m +1277 127 l +1276 128 l +f +*U +0.000 0.675 0.482 0.325 k +*u +1373 125 m +1374 126 1374.309 126.612 1375 128 c +1372.797 127 1372.952 127.330 1373 125 c +f +*U +0.000 0.545 0.435 0.384 k +*u +1409 128 m +1408 126.522 1408 126.797 1408 125 c +1409.289 126.443 1409.401 126.234 1409 128 c +f +*U +0.000 0.322 0.298 0.678 k +*u +1410 128 m +1411 127 l +1410 128 l +f +*U +0.000 0.443 0.282 0.475 k +*u +1984 128 m +1984 126 l +1985.635 126.545 1985.455 126.365 1986 128 c +1984 128 l +f +*U +0.000 0.212 0.133 0.169 k +*u +1986 128 m +1987 127 l +1986 128 l +f +*U +0.000 0.792 0.620 0.208 k +*u +1057 127 m +1057.514 124 1058.289 123.366 1061 122 c +1059.774 123.922 1058.627 125.412 1057 127 c +f +*U +0.000 0.478 0.365 0.161 k +*u +1176 127 m +1177 126 l +1176 127 l +f +*U +0.000 0.878 0.620 0.122 k +*u +1180 127 m +1184 124 l +1192.981 124.818 1202.873 121.439 1212 121 c +1230.863 120.213 1248.573 122.424 1267 126 c +1259.601 129 1248 127 1240 127 c +1180 127 l +f +*U +0.000 0.259 0.224 0.122 k +*u +1410 127 m +1411 126 l +1410 127 l +f +*U +0.000 0.192 0.145 0.125 k +*u +1096 126 m +1097 125 l +1096 126 l +f +*U +0.000 0.220 0.188 0.318 k +*u +1180 126 m +1181 125 l +1180 126 l +f +*U +0.000 0.604 0.451 0.392 k +*u +1181 126 m +1182.249 125.315 1182.548 125.251 1184 125 c +1182.752 125.685 1182.451 125.749 1181 126 c +f +*U +0.000 0.263 0.263 0.220 k +*u +1268 126 m +1269 125 l +1268 126 l +f +*U +0.000 0.224 0.173 0.051 k +*u +1370 126 m +1371 125 l +1370 126 l +f +*U +0.000 0.353 0.290 0.173 k +*u +1409 126 m +1410 125 l +1409 126 l +f +*U +0.000 0.443 0.357 0.373 k +*u +1981 126 m +1981 124 l +1982.635 124.545 1982.455 124.365 1983 126 c +1981 126 l +f +*U +0.000 0.243 0.243 0.278 k +*u +1983 126 m +1984 125 l +1983 126 l +f +*U +0.000 0.325 0.231 0.275 k +*u +1097 125 m +1098 124 l +1097 125 l +f +*U +0.000 0.294 0.239 0.027 k +*u +1183 125 m +1184 124 l +1183 125 l +f +*U +0.000 0.620 0.463 0.361 k +*u +1185 125 m +1186.249 124.315 1186.548 124.251 1188 124 c +1186.752 124.685 1186.451 124.749 1185 125 c +f +*U +0.000 0.600 0.459 0.400 k +*u +1256 124 m +1258.698 123 1261 123.647 1264 124 c +1261.244 125 1258.893 124.532 1256 124 c +f +*U +0.000 0.173 0.141 0.380 k +*u +1264 125 m +1265 124 l +1264 125 l +f +*U +0.000 0.149 0.129 0.110 k +*u +1265 125 m +1266 124 l +1265 125 l +f +*U +0.000 0.216 0.165 0.263 k +*u +1369 125 m +1370 124 l +1369 125 l +f +*U +0.000 0.643 0.475 0.341 k +*u +1404 121 m +1405.753 122.330 1406.670 123.247 1408 125 c +1405.751 123.847 1405 123.249 1404 121 c +f +*U +0.000 0.298 0.255 0.176 k +*u +1408 125 m +1409 124 l +1408 125 l +f +*U +0.000 0.247 0.220 0.094 k +*u +1187 124 m +1188 123 l +1187 124 l +f +*U +0.000 0.412 0.325 0.231 k +*u +1188 124 m +1189 123 l +1188 124 l +f +*U +0.000 0.600 0.506 0.400 k +*u +1189.667 123.667 m +1189.223 123.223 1190.278 123.278 1190.333 123.333 c +1190.778 123.778 1189.722 123.722 1189.667 123.667 c +f +*U +0.000 0.306 0.208 0.204 k +*u +1260 124 m +1261 123 l +1260 124 l +f +*U +0.000 0.290 0.204 0.341 k +*u +1368 124 m +1369 123 l +1368 124 l +f +*U +0.000 0.376 0.298 0.118 k +*u +1407 124 m +1408 123 l +1407 124 l +f +*U +0.000 0.220 0.153 0.118 k +*u +1980 124 m +1981 123 l +1980 124 l +f +*U +0.000 0.302 0.220 0.071 k +*u +1100 123 m +1101 122 l +1100 123 l +f +*U +0.000 0.310 0.224 0.059 k +*u +1192 123 m +1193 122 l +1192 123 l +f +*U +0.000 0.333 0.243 0.212 k +*u +1193 123 m +1194 122 l +1193 123 l +f +*U +0.000 0.510 0.357 0.475 k +*u +1194 123 m +1195.249 122.315 1195.548 122.251 1197 122 c +1195.752 122.685 1195.451 122.749 1194 123 c +f +*U +0.000 0.753 0.569 0.247 k +*u +1248 123 m +1249.249 122.315 1249.548 122.251 1251 122 c +1249.752 122.685 1249.452 122.749 1248 123 c +f +*U +0.000 0.549 0.455 0.451 k +*u +1251 123 m +1252.249 122.315 1252.548 122.251 1254 122 c +1252.752 122.685 1252.451 122.749 1251 123 c +f +*U +0.000 0.498 0.369 0.200 k +*u +1254 123 m +1255 122 l +1254 123 l +f +*U +0.000 0.502 0.376 0.031 k +*u +1255 123 m +1256 122 l +1255 123 l +f +*U +0.000 0.086 0.027 0.153 k +*u +1256 123 m +1257 122 l +1256 123 l +f +*U +0.000 0.271 0.275 0.388 k +*u +1367 123 m +1368 122 l +1367 123 l +f +*U +0.000 0.459 0.416 0.541 k +*u +1368 123 m +1369 122 l +1368 123 l +f +*U +0.000 0.380 0.298 0.094 k +*u +1406 123 m +1407 122 l +1406 123 l +f +*U +0.000 0.553 0.478 0.447 k +*u +1977 123 m +1978 122 l +1977 123 l +f +*U +0.000 0.325 0.224 0.310 k +*u +1978 123 m +1979 122 l +1978 123 l +f +*U +0.000 0.365 0.263 0.224 k +*u +1101 122 m +1102 121 l +1101 122 l +f +*U +0.000 0.176 0.137 0.125 k +*u +1198 122 m +1199 121 l +1198 122 l +f +*U +0.000 0.176 0.137 0.298 k +*u +1199 122 m +1200 121 l +1199 122 l +f +*U +0.000 0.643 0.498 0.357 k +*u +1200 122 m +1202.613 120.902 1205 121 1208 121 c +1205.387 122 1202.835 121.993 1200 122 c +f +*U +0.000 0.706 0.518 0.294 k +*u +1240 122 m +1241.769 121.221 1243 121 1245 121 c +1243.231 121.779 1241.964 121.912 1240 122 c +f +*U +0.000 0.545 0.424 0.455 k +*u +1245 122 m +1246.249 121.315 1246.548 121.251 1248 121 c +1246.752 121.685 1246.451 121.749 1245 122 c +f +*U +0.000 0.235 0.176 0.278 k +*u +1248.667 121.667 m +1248.222 121.222 1249.278 121.278 1249.333 121.333 c +1249.778 121.778 1248.722 121.722 1248.667 121.667 c +f +*U +0.000 0.200 0.149 0.071 k +*u +1250 122 m +1251 121 l +1250 122 l +f +*U +0.000 0.294 0.243 0.204 k +*u +1405 122 m +1406 121 l +1405 122 l +f +*U +0.000 0.471 0.380 0.529 k +*u +1974.333 121.333 m +1974.278 121.278 1974.222 120.222 1974.667 120.667 c +1974.722 120.722 1974.778 121.778 1974.333 121.333 c +f +*U +0.000 0.408 0.294 0.424 k +*u +1102 121 m +1103 120 l +1102 121 l +f +*U +0.000 0.173 0.161 0.247 k +*u +1205 121 m +1206.249 120.315 1206.548 120.251 1208 120 c +1206.752 120.685 1206.451 120.749 1205 121 c +f +*U +0.000 0.502 0.357 0.192 k +*u +1208 121 m +1209 120 l +1208 121 l +f +*U +0.000 0.604 0.514 0.396 k +*u +1209 121 m +1211.331 120 1213.457 120 1216 120 c +1213.668 120.985 1211.543 120.981 1209 121 c +f +*U +0.000 0.843 0.851 0.149 k +*u +1216 121 m +1221.469 118.705 1229 120 1235 120 c +1229.531 122.295 1221.901 121 1216 121 c +f +*U +0.000 0.553 0.541 0.447 k +*u +1235 121 m +1236.249 120.315 1236.548 120.251 1238 120 c +1236.752 120.685 1236.452 120.749 1235 121 c +f +*U +0.000 0.675 0.400 0.243 k +*u +1238.667 120.667 m +1238.222 120.223 1239.278 120.278 1239.333 120.333 c +1239.778 120.778 1238.722 120.722 1238.667 120.667 c +f +*U +0.000 0.337 0.255 0.204 k +*u +1240 121 m +1241.249 120.315 1241.548 120.251 1243 120 c +1241.752 120.685 1241.451 120.749 1240 121 c +f +*U +0.000 0.169 0.137 0.082 k +*u +1243 121 m +1244 120 l +1243 121 l +f +*U +0.000 0.122 0.055 0.204 k +*u +1364 121 m +1365 120 l +1364 121 l +f +*U +0.000 0.400 0.298 0.600 k +*u +1365 121 m +1366 120 l +1365 121 l +f +*U +0.000 0.510 0.392 0.059 k +*u +1404 121 m +1405 120 l +1404 121 l +f +*U +0.000 0.671 0.463 0.094 k +*u +1975 121 m +1976 120 l +1975 121 l +f +*U +0.000 0.322 0.204 0.298 k +*u +1062 120 m +1063 119 l +1062 120 l +f +*U +0.000 0.427 0.286 0.573 k +*u +1063 120 m +1064 119 l +1063 120 l +f +*U +0.000 0.133 0.114 0.161 k +*u +1104 120 m +1105 119 l +1104 120 l +f +*U +0.000 0.090 0.020 0.224 k +*u +1218 120 m +1220.890 118.787 1223.874 119 1227 119 c +1224 120.213 1221 119.998 1218 120 c +f +*U +0.000 0.384 0.416 0.263 k +*u +1363 120 m +1364 119 l +1363 120 l +f +*U +0.000 0.506 0.329 0.443 k +*u +1402 120 m +1403 119 l +1402 120 l +f +*U +0.000 0.200 0.125 0.176 k +*u +1403 120 m +1404 119 l +1403 120 l +f +*U +0.031 0.000 0.012 0.588 k +*u +1973 120 m +1974 119 l +1973 120 l +f +*U +0.000 0.290 0.184 0.235 k +*u +1063 119 m +1064 118 l +1063 119 l +f +*U +0.000 0.494 0.357 0.455 k +*u +1104 119 m +1105 118 l +1104 119 l +f +*U +0.000 0.424 0.302 0.290 k +*u +1105 119 m +1106 118 l +1105 119 l +f +*U +0.000 0.627 0.506 0.373 k +*u +1362.667 118.667 m +1362.222 118.223 1363.278 118.278 1363.333 118.333 c +1363.778 118.778 1362.722 118.722 1362.667 118.667 c +f +*U +0.000 0.537 0.408 0.463 k +*u +1401 119 m +1402 118 l +1401 119 l +f +*U +0.000 0.329 0.220 0.075 k +*u +1402 119 m +1403 118 l +1402 119 l +f +*U +0.000 0.376 0.294 0.188 k +*u +1064 118 m +1065 117 l +1064 118 l +f +*U +0.000 0.522 0.424 0.478 k +*u +1065 118 m +1066 117 l +1065 118 l +f +*U +0.000 0.235 0.180 0.090 k +*u +1107 118 m +1108 117 l +1107 118 l +f +*U +0.000 0.318 0.388 0.086 k +*u +1360 118 m +1361 117 l +1360 118 l +f +*U +0.000 0.459 0.451 0.541 k +*u +1361 118 m +1362 117 l +1361 118 l +f +*U +0.000 0.522 0.341 0.431 k +*u +1400 118 m +1401 117 l +1400 118 l +f +*U +0.000 0.329 0.224 0.067 k +*u +1401 118 m +1402 117 l +1401 118 l +f +*U +0.000 0.404 0.325 0.561 k +*u +1066 117 m +1067 116 l +1066 117 l +f +*U +0.000 0.541 0.424 0.459 k +*u +1107 117 m +1108 116 l +1107 117 l +f +*U +0.000 0.322 0.247 0.310 k +*u +1108 117 m +1109 116 l +1108 117 l +f +*U +0.000 0.278 0.192 0.322 k +*u +1359 117 m +1360 116 l +1359 117 l +f +*U +0.000 0.553 0.404 0.447 k +*u +1399 117 m +1400 116 l +1399 117 l +f +*U +0.000 0.224 0.145 0.180 k +*u +1400 117 m +1401 116 l +1400 117 l +f +*U +0.055 0.000 0.059 0.157 k +*u +1066 116 m +1067 115 l +1066 116 l +f +*U +0.000 0.329 0.329 0.671 k +*u +1067 116 m +1068 115 l +1067 116 l +f +*U +0.000 0.486 0.353 0.404 k +*u +1108.667 115.667 m +1108.222 115.222 1109.278 115.278 1109.333 115.333 c +1109.778 115.778 1108.722 115.722 1108.667 115.667 c +f +*U +0.000 0.235 0.196 0.114 k +*u +1357 116 m +1358 115 l +1357 116 l +f +*U +0.000 0.490 0.388 0.510 k +*u +1358 116 m +1359 115 l +1358 116 l +f +*U +0.000 0.706 0.525 0.239 k +*u +1396 116 m +1396 113 l +1397.196 114.223 1397.316 114.420 1398 116 c +1396 116 l +f +*U +0.000 0.365 0.310 0.635 k +*u +1398 116 m +1399 115 l +1398 116 l +f +*U +0.000 0.212 0.157 0.075 k +*u +1399 116 m +1400 115 l +1399 116 l +f +*U +0.000 0.455 0.380 0.545 k +*u +1068 115 m +1069 114 l +1068 115 l +f +*U +0.000 0.443 0.341 0.196 k +*u +1111 115 m +1112 114 l +1111 115 l +f +*U +0.000 0.373 0.302 0.231 k +*u +1356 115 m +1357 114 l +1356 115 l +f +*U +0.000 0.451 0.451 0.549 k +*u +1357 115 m +1358 114 l +1357 115 l +f +*U +0.000 0.659 0.451 0.341 k +*u +1112 114 m +1112 112 l +1114 112 l +1113.455 113.635 1113.635 113.455 1112 114 c +f +*U +0.000 0.380 0.255 0.063 k +*u +1113 114 m +1114 113 l +1113 114 l +f +*U +0.000 0.490 0.408 0.263 k +*u +1070 113 m +1071 112 l +1070 113 l +f +*U +0.000 0.310 0.192 0.196 k +*u +1114 113 m +1115 112 l +1114 113 l +f +*U +0.000 0.106 0.102 0.404 k +*u +1353 113 m +1354 112 l +1353 113 l +f +*U +0.000 0.514 0.431 0.239 k +*u +1395 113 m +1396 112 l +1395 113 l +f +*U +0.000 0.094 0.055 0.329 k +*u +1071 112 m +1072 111 l +1071 112 l +f +*U +0.000 0.643 0.431 0.357 k +*u +1072 112 m +1072.545 110.365 1072.365 110.545 1074 110 c +1074 112 l +1072 112 l +f +*U +0.000 0.467 0.467 0.533 k +*u +1115 112 m +1116 111 l +1115 112 l +f +*U +0.000 0.302 0.318 0.110 k +*u +1116 112 m +1117 111 l +1116 112 l +f +*U +0.000 0.549 0.384 0.451 k +*u +1393 112 m +1394 111 l +1393 112 l +f +*U +0.000 0.220 0.137 0.333 k +*u +1394 112 m +1395 111 l +1394 112 l +f +*U +0.000 0.267 0.165 0.082 k +*u +1072 111 m +1073 110 l +1072 111 l +f +*U +0.000 0.384 0.318 0.251 k +*u +1117 111 m +1118 110 l +1117 111 l +f +*U +0.000 0.310 0.263 0.196 k +*u +1350 111 m +1351 110 l +1350 111 l +f +*U +0.000 0.471 0.369 0.478 k +*u +1351 111 m +1352 110 l +1351 111 l +f +*U +0.000 0.412 0.275 0.141 k +*u +1393 111 m +1394 110 l +1393 111 l +f +*U +0.000 0.361 0.243 0.016 k +*u +1119 110 m +1120 109 l +1119 110 l +f +*U +0.000 0.278 0.216 0.075 k +*u +1348 110 m +1349 109 l +1348 110 l +f +*U +0.000 0.475 0.333 0.463 k +*u +1388 107 m +1389.949 107.936 1390.550 108.392 1392 110 c +1390 109 1389.450 108.608 1388 107 c +f +*U +0.000 0.235 0.153 0.098 k +*u +1392 110 m +1393 109 l +1392 110 l +f +*U +0.000 0.663 0.537 0.337 k +*u +1075.667 108.667 m +1075.222 108.222 1076.278 108.278 1076.333 108.333 c +1076.778 108.778 1075.722 108.722 1075.667 108.667 c +f +*U +0.000 0.627 0.506 0.373 k +*u +1120 109 m +1120 107 l +1122 107 l +1121.455 108.635 1121.635 108.455 1120 109 c +f +*U +0.000 0.216 0.192 0.125 k +*u +1121 109 m +1122 108 l +1121 109 l +f +*U +0.000 0.369 0.263 0.341 k +*u +1347 109 m +1348 108 l +1347 109 l +f +*U +0.000 0.310 0.235 0.071 k +*u +1391 109 m +1392 108 l +1391 109 l +f +*U +0.000 0.227 0.220 0.212 k +*u +1076 108 m +1077 107 l +1076 108 l +f +*U +0.000 0.584 0.471 0.416 k +*u +1077 108 m +1078 107 l +1077 108 l +f +*U +0.000 0.341 0.275 0.290 k +*u +1122 108 m +1123 107 l +1122 108 l +f +*U +0.000 0.282 0.204 0.133 k +*u +1345 108 m +1346 107 l +1345 108 l +f +*U +0.000 0.184 0.169 0.176 k +*u +1077 107 m +1078 106 l +1077 107 l +f +*U +0.000 0.486 0.408 0.514 k +*u +1078 107 m +1079 106 l +1078 107 l +f +*U +0.000 0.592 0.431 0.392 k +*u +1122.667 106.667 m +1122.222 106.222 1123.278 106.278 1123.333 106.333 c +1123.778 106.778 1122.722 106.722 1122.667 106.667 c +f +*U +0.000 0.380 0.282 0.082 k +*u +1124 107 m +1125 106 l +1124 107 l +f +*U +0.000 0.620 0.447 0.353 k +*u +1344.667 106.667 m +1344.223 106.223 1345.278 106.278 1345.333 106.333 c +1345.778 106.778 1344.722 106.722 1344.667 106.667 c +f +*U +0.000 0.561 0.455 0.439 k +*u +1387 107 m +1388 106 l +1387 107 l +f +*U +0.000 0.322 0.243 0.267 k +*u +1388 107 m +1389 106 l +1388 107 l +f +*U +0.000 0.663 0.518 0.271 k +*u +1079 106 m +1080.543 104.733 1081 104.511 1083 104 c +1081.457 105.267 1080.952 105.489 1079 106 c +f +*U +0.000 0.761 0.576 0.239 k +*u +1125 106 m +1125.980 104.217 1125.908 104.406 1128 104 c +1126.861 105 1126.388 105.309 1125 106 c +f +*U +0.000 0.275 0.235 0.161 k +*u +1126 106 m +1127 105 l +1126 106 l +f +*U +0.000 0.373 0.255 0.208 k +*u +1342 106 m +1343 105 l +1342 106 l +f +*U +0.000 0.365 0.290 0.635 k +*u +1343 106 m +1344 105 l +1343 106 l +f +*U +0.000 0.455 0.404 0.545 k +*u +1386 106 m +1387 105 l +1386 106 l +f +*U +0.000 0.298 0.239 0.278 k +*u +1387 106 m +1388 105 l +1387 106 l +f +*U +0.102 0.000 0.027 0.137 k +*u +1128 105 m +1129 104 l +1128 105 l +f +*U +0.000 0.251 0.161 0.129 k +*u +1340 105 m +1341 104 l +1340 105 l +f +*U +0.000 0.655 0.506 0.345 k +*u +1341.667 104.667 m +1341.222 104.223 1342.278 104.278 1342.333 104.333 c +1342.778 104.778 1341.722 104.722 1341.667 104.667 c +f +*U +0.000 0.490 0.471 0.510 k +*u +1385 105 m +1386 104 l +1385 105 l +f +*U +0.000 0.286 0.251 0.141 k +*u +1386 105 m +1387 104 l +1386 105 l +f +*U +0.000 0.098 0.067 0.231 k +*u +1081 104 m +1082 103 l +1081 104 l +f +*U +0.000 0.455 0.322 0.545 k +*u +1082 104 m +1083 103 l +1082 104 l +f +*U +0.000 0.510 0.384 0.490 k +*u +1128 104 m +1129 103 l +1128 104 l +f +*U +0.000 0.439 0.310 0.278 k +*u +1129 104 m +1130 103 l +1129 104 l +f +*U +0.000 0.580 0.490 0.420 k +*u +1338 102 m +1339.581 102.684 1339.777 102.804 1341 104 c +1339.420 103.317 1339.223 103.195 1338 102 c +f +*U +0.000 0.753 0.686 0.192 k +*u +1380 104 m +1380 100 l +1384 102 l +1382.542 103 1381.752 103.436 1380 104 c +f +*U +0.000 0.075 0.039 0.651 k +*u +1384 104 m +1385 103 l +1384 104 l +f +*U +0.000 0.678 0.486 0.322 k +*u +1083.667 102.667 m +1083.222 102.222 1084.278 102.278 1084.333 102.333 c +1084.778 102.778 1083.722 102.722 1083.667 102.667 c +f +*U +0.000 0.463 0.361 0.537 k +*u +1130 103 m +1131 102 l +1130 103 l +f +*U +0.000 0.325 0.235 0.329 k +*u +1131 103 m +1132 102 l +1131 103 l +f +*U +0.000 0.322 0.267 0.361 k +*u +1337 103 m +1338 102 l +1337 103 l +f +*U +0.000 0.365 0.259 0.322 k +*u +1084 102 m +1085 101 l +1084 102 l +f +*U +0.000 0.561 0.451 0.439 k +*u +1085 102 m +1086 101 l +1085 102 l +f +*U +0.000 0.522 0.388 0.478 k +*u +1132 102 m +1133 101 l +1132 102 l +f +*U +0.000 0.325 0.224 0.337 k +*u +1133 102 m +1134 101 l +1133 102 l +f +*U +0.000 0.294 0.247 0.306 k +*u +1335 102 m +1336 101 l +1335 102 l +f +*U +0.000 0.620 0.514 0.380 k +*u +1336.667 101.667 m +1336.222 101.223 1337.278 101.278 1337.333 101.333 c +1337.778 101.778 1336.722 101.722 1336.667 101.667 c +f +*U +0.000 0.306 0.337 0.243 k +*u +1382 102 m +1383 101 l +1382 102 l +f +*U +0.000 0.255 0.188 0.098 k +*u +1085 101 m +1086 100 l +1085 101 l +f +*U +0.000 0.651 0.514 0.349 k +*u +1133 101 m +1134.543 99.733 1135 99.511 1137 99 c +1135.542 100 1134.752 100.436 1133 101 c +f +*U +0.000 0.388 0.282 0.212 k +*u +1135 101 m +1136 100 l +1135 101 l +f +*U +0.000 0.286 0.267 0.306 k +*u +1333 101 m +1334 100 l +1333 101 l +f +*U +0.000 0.494 0.471 0.506 k +*u +1334 101 m +1335 100 l +1334 101 l +f +*U +0.000 0.224 0.216 0.235 k +*u +1381 101 m +1382 100 l +1381 101 l +f +*U +0.000 0.329 0.235 0.525 k +*u +1087 100 m +1088 99 l +1087 100 l +f +*U +0.000 0.392 0.247 0.267 k +*u +1137 100 m +1138 99 l +1137 100 l +f +*U +0.000 0.278 0.231 0.239 k +*u +1331 100 m +1332 99 l +1331 100 l +f +*U +0.000 0.631 0.502 0.369 k +*u +1332.667 99.667 m +1332.222 99.222 1333.278 99.278 1333.333 99.333 c +1333.778 99.778 1332.722 99.722 1332.667 99.667 c +f +*U +0.000 0.722 0.600 0.204 k +*u +1373 96 m +1375.403 96.628 1376.958 97.562 1379 99 c +1376 99.483 1374.593 98.410 1373 96 c +f +*U +0.000 0.392 0.235 0.275 k +*u +1379 100 m +1380 99 l +1379 100 l +f +*U +0.000 0.533 0.361 0.165 k +*u +1088 99 m +1089 98 l +1088 99 l +f +*U +0.000 0.584 0.471 0.416 k +*u +1089 99 m +1090.223 97.805 1090.420 97.684 1092 97 c +1090.777 98.195 1090.580 98.316 1089 99 c +f +*U +0.000 0.478 0.392 0.522 k +*u +1138 99 m +1139 98 l +1138 99 l +f +*U +0.000 0.294 0.239 0.318 k +*u +1139 99 m +1140 98 l +1139 99 l +f +*U +0.000 0.251 0.208 0.165 k +*u +1329 99 m +1330 98 l +1329 99 l +f +*U +0.000 0.647 0.533 0.353 k +*u +1330.667 98.667 m +1330.222 98.223 1331.278 98.278 1331.333 98.333 c +1331.778 98.778 1330.722 98.722 1330.667 98.667 c +f +*U +0.000 0.243 0.235 0.357 k +*u +1378 99 m +1379 98 l +1378 99 l +f +*U +0.000 0.396 0.318 0.220 k +*u +1141 98 m +1142 97 l +1141 98 l +f +*U +0.000 0.278 0.235 0.239 k +*u +1327 98 m +1328 97 l +1327 98 l +f +*U +0.000 0.635 0.475 0.329 k +*u +1328.667 97.667 m +1328.222 97.222 1329.278 97.278 1329.333 97.333 c +1329.778 97.778 1328.722 97.722 1328.667 97.667 c +f +*U +0.000 0.349 0.271 0.506 k +*u +1376 98 m +1377 97 l +1376 98 l +f +*U +0.000 0.247 0.161 0.118 k +*u +1377 98 m +1378 97 l +1377 98 l +f +*U +0.000 0.482 0.420 0.114 k +*u +1091 97 m +1092 96 l +1091 97 l +f +*U +0.000 0.541 0.541 0.459 k +*u +1092 97 m +1093 96 l +1092 97 l +f +*U +0.000 0.588 0.459 0.412 k +*u +1141.667 96.667 m +1141.222 96.222 1142.278 96.278 1142.333 96.333 c +1142.778 96.778 1141.722 96.722 1141.667 96.667 c +f +*U +0.000 0.263 0.204 0.145 k +*u +1325 97 m +1326 96 l +1325 97 l +f +*U +0.000 0.522 0.396 0.392 k +*u +1326.667 96.667 m +1326.222 96.223 1327.278 96.278 1327.333 96.333 c +1327.778 96.778 1326.722 96.722 1326.667 96.667 c +f +*U +0.000 0.725 0.518 0.275 k +*u +1333.667 96.667 m +1333.222 96.222 1334.278 96.278 1334.333 96.333 c +1334.778 96.778 1333.722 96.722 1333.667 96.667 c +f +*U +0.000 0.514 0.337 0.435 k +*u +1093 96 m +1094 94.985 1094.611 94.691 1096 94 c +1095 95.783 1095 95.594 1093 96 c +f +*U +0.000 0.365 0.267 0.031 k +*u +1146 96 m +1147 95 l +1146 96 l +f +*U +0.000 0.416 0.322 0.243 k +*u +1323 96 m +1324 95 l +1323 96 l +f +*U +0.000 0.482 0.376 0.518 k +*u +1373 96 m +1374 95 l +1373 96 l +f +*U +0.000 0.224 0.169 0.196 k +*u +1374 96 m +1375 95 l +1374 96 l +f +*U +0.000 0.427 0.286 0.114 k +*u +1094 95 m +1095 94 l +1094 95 l +f +*U +0.000 0.522 0.369 0.475 k +*u +1146.667 94.667 m +1146.222 94.222 1147.278 94.278 1147.333 94.333 c +1147.778 94.778 1146.722 94.722 1146.667 94.667 c +f +*U +0.000 0.349 0.251 0.094 k +*u +1148 95 m +1149 94 l +1148 95 l +f +*U +0.000 0.353 0.267 0.082 k +*u +1320 95 m +1321 94 l +1320 95 l +f +*U +0.000 0.627 0.455 0.310 k +*u +1321.667 94.667 m +1321.222 94.222 1322.278 94.278 1322.333 94.333 c +1322.778 94.778 1321.722 94.722 1321.667 94.667 c +f +*U +0.000 0.690 0.506 0.294 k +*u +1326 95 m +1326.545 93.365 1326.365 93.545 1328 93 c +1328 95 l +1326 95 l +f +*U +0.000 0.412 0.318 0.451 k +*u +1372 95 m +1373 94 l +1372 95 l +f +*U +0.000 0.204 0.133 0.133 k +*u +1095 94 m +1096 93 l +1095 94 l +f +*U +0.000 0.471 0.392 0.529 k +*u +1096 94 m +1097 93 l +1096 94 l +f +*U +0.000 0.471 0.349 0.529 k +*u +1149 94 m +1150 93 l +1149 94 l +f +*U +0.000 0.278 0.204 0.329 k +*u +1150 94 m +1151 93 l +1150 94 l +f +*U +0.000 0.357 0.255 0.016 k +*u +1318 94 m +1319 93 l +1318 94 l +f +*U +0.000 0.565 0.475 0.435 k +*u +1370 94 m +1371 93 l +1370 94 l +f +*U +0.000 0.353 0.275 0.047 k +*u +1371 94 m +1372 93 l +1371 94 l +f +*U +0.000 0.349 0.251 0.322 k +*u +1097 93 m +1098 92 l +1097 93 l +f +*U +0.000 0.427 0.302 0.478 k +*u +1151.667 92.667 m +1151.222 92.222 1152.278 92.278 1152.333 92.333 c +1152.778 92.778 1151.722 92.722 1151.667 92.667 c +f +*U +0.000 0.212 0.161 0.153 k +*u +1153 93 m +1154 92 l +1153 93 l +f +*U +0.000 0.282 0.227 0.263 k +*u +1316 93 m +1317 92 l +1316 93 l +f +*U +0.000 0.431 0.431 0.569 k +*u +1368 93 m +1369 92 l +1368 93 l +f +*U +0.000 0.431 0.325 0.361 k +*u +1369 93 m +1370 92 l +1369 93 l +f +*U +0.000 0.125 0.102 0.129 k +*u +1098 92 m +1099 91 l +1098 92 l +f +*U +0.000 0.682 0.545 0.318 k +*u +1099.667 91.667 m +1099.222 91.222 1100.278 91.278 1100.333 91.333 c +1100.778 91.778 1099.722 91.722 1099.667 91.667 c +f +*U +0.000 0.737 0.545 0.263 k +*u +1152 92 m +1153.458 90.919 1154.248 90.564 1156 90 c +1154.457 91.267 1153.952 91.489 1152 92 c +f +*U +0.000 0.431 0.306 0.275 k +*u +1155 92 m +1156 91 l +1155 92 l +f +*U +0.000 0.051 0.055 0.149 k +*u +1156 92 m +1157 91 l +1156 92 l +f +*U +0.000 0.243 0.184 0.149 k +*u +1313 92 m +1314 91 l +1313 92 l +f +*U +0.000 0.624 0.478 0.333 k +*u +1314.667 91.667 m +1314.222 91.223 1315.278 91.278 1315.333 91.333 c +1315.778 91.778 1314.722 91.722 1314.667 91.667 c +f +*U +0.000 0.639 0.475 0.361 k +*u +1366.667 91.667 m +1366.223 91.223 1367.278 91.278 1367.333 91.333 c +1367.778 91.778 1366.722 91.722 1366.667 91.667 c +f +*U +0.000 0.184 0.153 0.263 k +*u +1368 92 m +1369 91 l +1368 92 l +f +*U +0.000 0.341 0.247 0.271 k +*u +1100 91 m +1101 90 l +1100 91 l +f +*U +0.000 0.737 0.573 0.263 k +*u +1101.667 90.667 m +1101.222 90.222 1102.278 90.278 1102.333 90.333 c +1102.778 90.778 1101.722 90.722 1101.667 90.667 c +f +*U +0.000 0.443 0.333 0.486 k +*u +1156.667 90.667 m +1156.222 90.222 1157.278 90.278 1157.333 90.333 c +1157.778 90.778 1156.722 90.722 1156.667 90.667 c +f +*U +0.000 0.227 0.196 0.204 k +*u +1158 91 m +1159 90 l +1158 91 l +f +*U +0.000 0.259 0.231 0.192 k +*u +1311 91 m +1312 90 l +1311 91 l +f +*U +0.000 0.392 0.282 0.435 k +*u +1365.667 90.667 m +1365.222 90.222 1366.278 90.278 1366.333 90.333 c +1366.778 90.778 1365.722 90.722 1365.667 90.667 c +f +*U +0.000 0.435 0.365 0.565 k +*u +1102.667 89.667 m +1102.222 89.222 1103.278 89.278 1103.333 89.333 c +1103.778 89.778 1102.722 89.722 1102.667 89.667 c +f +*U +0.000 0.451 0.451 0.549 k +*u +1159 90 m +1160 89 l +1159 90 l +f +*U +0.000 0.286 0.184 0.475 k +*u +1160 90 m +1161 89 l +1160 90 l +f +*U +0.000 0.263 0.173 0.118 k +*u +1161 90 m +1162 89 l +1161 90 l +f +*U +0.000 0.298 0.243 0.204 k +*u +1308 90 m +1309 89 l +1308 90 l +f +*U +0.000 0.580 0.447 0.408 k +*u +1309 90 m +1310.249 89.315 1310.548 89.251 1312 89 c +1310.752 89.685 1310.452 89.749 1309 90 c +f +*U +0.000 0.541 0.408 0.459 k +*u +1363 90 m +1363 88 l +1364.635 88.545 1364.455 88.365 1365 90 c +1363 90 l +f +*U +0.000 0.322 0.235 0.035 k +*u +1365 90 m +1366 89 l +1365 90 l +f +*U +0.067 0.000 0.067 0.176 k +*u +1103 89 m +1104 88 l +1103 89 l +f +*U +0.000 0.475 0.329 0.525 k +*u +1161.667 88.667 m +1161.222 88.222 1162.278 88.278 1162.333 88.333 c +1162.778 88.778 1161.722 88.722 1161.667 88.667 c +f +*U +0.000 0.278 0.176 0.412 k +*u +1163 89 m +1164 88 l +1163 89 l +f +*U +0.000 0.094 0.059 0.137 k +*u +1164 89 m +1165 88 l +1164 89 l +f +*U +0.000 0.094 0.055 0.208 k +*u +1305 89 m +1306 88 l +1305 89 l +f +*U +0.000 0.580 0.447 0.420 k +*u +1306.667 88.667 m +1306.222 88.222 1307.278 88.278 1307.333 88.333 c +1307.778 88.778 1306.722 88.722 1306.667 88.667 c +f +*U +0.000 0.271 0.200 0.349 k +*u +1105 88 m +1106 87 l +1105 88 l +f +*U +0.000 0.690 0.557 0.310 k +*u +1106.667 87.667 m +1106.222 87.222 1107.278 87.278 1107.333 87.333 c +1107.778 87.778 1106.722 87.722 1106.667 87.667 c +f +*U +0.000 0.588 0.447 0.412 k +*u +1164.667 87.667 m +1164.222 87.222 1165.278 87.278 1165.333 87.333 c +1165.778 87.778 1164.722 87.722 1164.667 87.667 c +f +*U +0.000 0.710 0.522 0.255 k +*u +1165 87 m +1166.506 86.317 1167.315 86.174 1169 86 c +1167.265 87 1167 87 1165 87 c +f +*U +0.000 0.486 0.365 0.000 k +*u +1167 88 m +1168 87 l +1167 88 l +f +*U +0.000 0.235 0.263 0.090 k +*u +1302 88 m +1303 87 l +1302 88 l +f +*U +0.000 0.298 0.314 0.455 k +*u +1303 88 m +1304 87 l +1303 88 l +f +*U +0.000 0.400 0.255 0.498 k +*u +1360.667 87.667 m +1360.222 87.222 1361.278 87.278 1361.333 87.333 c +1361.778 87.778 1360.722 87.722 1360.667 87.667 c +f +*U +0.000 0.220 0.141 0.165 k +*u +1362 88 m +1363 87 l +1362 88 l +f +*U +0.000 0.329 0.251 0.416 k +*u +1107 87 m +1108 86 l +1107 87 l +f +*U +0.000 0.494 0.345 0.235 k +*u +1169 87 m +1170 86 l +1169 87 l +f +*U +0.000 0.263 0.192 0.000 k +*u +1170 87 m +1171 86 l +1170 87 l +f +*U +0.000 0.271 0.227 0.118 k +*u +1299 87 m +1300 86 l +1299 87 l +f +*U +0.000 0.431 0.349 0.404 k +*u +1300 87 m +1301 86 l +1300 87 l +f +*U +0.000 0.612 0.545 0.388 k +*u +1301.667 86.667 m +1301.222 86.222 1302.278 86.278 1302.333 86.333 c +1302.778 86.778 1301.722 86.722 1301.667 86.667 c +f +*U +0.000 0.329 0.216 0.224 k +*u +1360 87 m +1361 86 l +1360 87 l +f +*U +0.000 0.263 0.192 0.078 k +*u +1108 86 m +1109 85 l +1108 86 l +f +*U +0.000 0.612 0.498 0.388 k +*u +1109.667 85.667 m +1109.222 85.222 1110.278 85.278 1110.333 85.333 c +1110.778 85.778 1109.722 85.722 1109.667 85.667 c +f +*U +0.000 0.616 0.486 0.384 k +*u +1170.667 85.667 m +1170.222 85.222 1171.278 85.278 1171.333 85.333 c +1171.778 85.778 1170.722 85.722 1170.667 85.667 c +f +*U +0.000 0.322 0.220 0.106 k +*u +1173 86 m +1174 85 l +1173 86 l +f +*U +0.000 0.369 0.314 0.224 k +*u +1296 86 m +1297 85 l +1296 86 l +f +*U +0.000 0.565 0.447 0.435 k +*u +1297.667 85.667 m +1297.223 85.223 1298.278 85.278 1298.333 85.333 c +1298.778 85.778 1297.722 85.722 1297.667 85.667 c +f +*U +0.000 0.416 0.294 0.502 k +*u +1358 86 m +1359 85 l +1358 86 l +f +*U +0.000 0.294 0.220 0.016 k +*u +1110 85 m +1111 84 l +1110 85 l +f +*U +0.000 0.737 0.561 0.263 k +*u +1111.667 84.667 m +1111.222 84.222 1112.278 84.278 1112.333 84.333 c +1112.778 84.778 1111.722 84.722 1111.667 84.667 c +f +*U +0.000 0.439 0.349 0.561 k +*u +1174.667 84.667 m +1174.222 84.223 1175.278 84.278 1175.333 84.333 c +1175.778 84.778 1174.722 84.722 1174.667 84.667 c +f +*U +0.000 0.259 0.192 0.306 k +*u +1176 85 m +1177 84 l +1176 85 l +f +*U +0.000 0.208 0.169 0.098 k +*u +1177 85 m +1178 84 l +1177 85 l +f +*U +0.000 0.110 0.090 0.192 k +*u +1292 85 m +1293 84 l +1292 85 l +f +*U +0.000 0.753 0.588 0.247 k +*u +1288 83 m +1291 82 1293.942 82.554 1296 85 c +1293.225 84.590 1290.673 83.851 1288 83 c +f +*U +0.000 0.545 0.388 0.455 k +*u +1356 85 m +1357 84 l +1356 85 l +f +*U +0.000 0.243 0.180 0.141 k +*u +1357 85 m +1358 84 l +1357 85 l +f +*U +0.000 0.447 0.322 0.239 k +*u +1112 84 m +1113 83 l +1112 84 l +f +*U +0.000 0.533 0.380 0.467 k +*u +1113 84 m +1114 83 l +1113 84 l +f +*U +0.000 0.663 0.565 0.271 k +*u +1176 84 m +1177.377 83 1178.440 82.596 1180 82 c +1178.686 83.618 1178 83.693 1176 84 c +f +*U +0.000 0.373 0.357 0.239 k +*u +1180 84 m +1181 83 l +1180 84 l +f +*U +0.000 0.208 0.227 0.055 k +*u +1181 84 m +1182 83 l +1181 84 l +f +*U +0.000 0.173 0.137 0.153 k +*u +1288 84 m +1289 83 l +1288 84 l +f +*U +0.000 0.310 0.224 0.290 k +*u +1289 84 m +1290 83 l +1289 84 l +f +*U +0.000 0.557 0.427 0.443 k +*u +1354 84 m +1355 83 l +1354 84 l +f +*U +0.000 0.294 0.216 0.349 k +*u +1355 84 m +1356 83 l +1355 84 l +f +*U +0.000 0.549 0.420 0.451 k +*u +1114.667 82.667 m +1114.222 82.222 1115.278 82.278 1115.333 82.333 c +1115.778 82.778 1114.722 82.722 1114.667 82.667 c +f +*U +0.000 0.612 0.514 0.388 k +*u +1180 83 m +1181.506 82.317 1182.315 82.174 1184 82 c +1182.494 82.683 1181.685 82.826 1180 83 c +f +*U +0.000 0.196 0.141 0.314 k +*u +1184 83 m +1185 82 l +1184 83 l +f +*U +0.000 0.188 0.141 0.137 k +*u +1185 83 m +1186 82 l +1185 83 l +f +*U +0.000 0.255 0.188 0.051 k +*u +1284 83 m +1285 82 l +1284 83 l +f +*U +0.000 0.333 0.239 0.255 k +*u +1285 83 m +1286 82 l +1285 83 l +f +*U +0.000 0.424 0.302 0.569 k +*u +1287 83 m +1288 82 l +1287 83 l +f +*U +0.000 0.565 0.431 0.373 k +*u +1348 81 m +1350.274 80.591 1351.781 81.212 1354 82 c +1351.538 82.697 1350.335 82 1348 81 c +f +*U +0.000 0.184 0.141 0.086 k +*u +1115 82 m +1116 81 l +1115 82 l +f +*U +0.000 0.584 0.408 0.365 k +*u +1116 82 m +1117.458 80.919 1118.248 80.564 1120 80 c +1118.457 81.267 1117.952 81.489 1116 82 c +f +*U +0.000 0.678 0.498 0.322 k +*u +1185 82 m +1186.249 81.315 1186.548 81.251 1188 81 c +1186.752 81.685 1186.451 81.749 1185 82 c +f +*U +0.000 0.388 0.275 0.322 k +*u +1188 82 m +1189 81 l +1188 82 l +f +*U +0.000 0.212 0.161 0.212 k +*u +1189 82 m +1190 81 l +1189 82 l +f +*U +0.000 0.416 0.286 0.078 k +*u +1280 82 m +1281 81 l +1280 82 l +f +*U +0.000 0.600 0.451 0.400 k +*u +1281 82 m +1282.769 81.221 1284 81 1286 81 c +1284.231 81.779 1282.964 81.912 1281 82 c +f +*U +0.000 0.059 0.043 0.149 k +*u +1352 82 m +1353 81 l +1352 82 l +f +*U +0.000 0.278 0.212 0.090 k +*u +1117 81 m +1118 80 l +1117 81 l +f +*U +0.000 0.667 0.537 0.333 k +*u +1190.667 80.667 m +1190.222 80.222 1191.278 80.278 1191.333 80.333 c +1191.778 80.778 1190.722 80.722 1190.667 80.667 c +f +*U +0.000 0.361 0.243 0.639 k +*u +1192 81 m +1193 80 l +1192 81 l +f +*U +0.000 0.345 0.224 0.439 k +*u +1193 81 m +1194 80 l +1193 81 l +f +*U +0.000 0.263 0.173 0.255 k +*u +1194 81 m +1195 80 l +1194 81 l +f +*U +0.000 0.153 0.098 0.129 k +*u +1195 81 m +1196 80 l +1195 81 l +f +*U +0.000 0.157 0.098 0.255 k +*u +1275 81 m +1276 80 l +1275 81 l +f +*U +0.000 0.349 0.227 0.322 k +*u +1276 81 m +1277 80 l +1276 81 l +f +*U +0.000 0.612 0.435 0.388 k +*u +1277 81 m +1278.249 80.315 1278.548 80.251 1280 80 c +1278.752 80.685 1278.452 80.749 1277 81 c +f +*U +0.000 0.310 0.267 0.129 k +*u +1350 81 m +1351 80 l +1350 81 l +f +*U +0.000 0.416 0.345 0.584 k +*u +1120.667 79.667 m +1120.222 79.222 1121.278 79.278 1121.333 79.333 c +1121.778 79.778 1120.722 79.722 1120.667 79.667 c +f +*U +0.000 0.278 0.227 0.098 k +*u +1268 80 m +1269.249 79.315 1269.548 79.251 1271 79 c +1269.752 79.685 1269.452 79.749 1268 80 c +f +*U +0.000 0.737 0.541 0.263 k +*u +1268 79 m +1270.698 78 1273 78.647 1276 79 c +1273.244 80 1270.893 79.532 1268 79 c +f +*U +0.000 0.302 0.196 0.569 k +*u +1346.667 79.667 m +1346.223 79.223 1347.278 79.278 1347.333 79.333 c +1347.778 79.778 1346.722 79.722 1346.667 79.667 c +f +*U +0.000 0.102 0.063 0.220 k +*u +1348 80 m +1349 79 l +1348 80 l +f +*U +0.000 0.176 0.141 0.110 k +*u +1121 79 m +1122 78 l +1121 79 l +f +*U +0.000 0.616 0.478 0.384 k +*u +1122.667 78.667 m +1122.222 78.222 1123.278 78.278 1123.333 78.333 c +1123.778 78.778 1122.722 78.722 1122.667 78.667 c +f +*U +0.000 0.514 0.392 0.486 k +*u +1202 79 m +1203.249 78.315 1203.548 78.251 1205 78 c +1203.752 78.685 1203.452 78.749 1202 79 c +f +*U +0.000 0.259 0.180 0.251 k +*u +1205.667 78.667 m +1205.222 78.222 1206.278 78.278 1206.333 78.333 c +1206.778 78.778 1205.722 78.722 1205.667 78.667 c +f +*U +0.000 0.063 0.039 0.149 k +*u +1207.667 78.667 m +1207.222 78.222 1208.278 78.278 1208.333 78.333 c +1208.778 78.778 1207.722 78.722 1207.667 78.667 c +f +*U +0.000 0.188 0.133 0.184 k +*u +1260.667 78.667 m +1260.222 78.223 1261.278 78.278 1261.333 78.333 c +1261.778 78.778 1260.722 78.722 1260.667 78.667 c +f +*U +0.000 0.239 0.161 0.322 k +*u +1262.667 78.667 m +1262.222 78.222 1263.278 78.278 1263.333 78.333 c +1263.778 78.778 1262.722 78.722 1262.667 78.667 c +f +*U +0.000 0.569 0.392 0.384 k +*u +1264 79 m +1265.506 78.317 1266.315 78.174 1268 78 c +1266.494 78.683 1265.685 78.826 1264 79 c +f +*U +0.000 0.561 0.369 0.439 k +*u +1344.667 78.667 m +1344.223 78.223 1345.278 78.278 1345.333 78.333 c +1345.778 78.778 1344.722 78.722 1344.667 78.667 c +f +*U +0.000 0.373 0.247 0.118 k +*u +1346 79 m +1347 78 l +1346 79 l +f +*U +0.000 0.627 0.463 0.373 k +*u +1124.667 77.667 m +1124.222 77.222 1125.278 77.278 1125.333 77.333 c +1125.778 77.778 1124.722 77.722 1124.667 77.667 c +f +*U +0.000 0.627 0.439 0.373 k +*u +1208 78 m +1209.249 77.315 1209.548 77.251 1211 77 c +1209.752 77.685 1209.452 77.749 1208 78 c +f +*U +0.000 0.482 0.416 0.518 k +*u +1211 78 m +1212.249 77.315 1212.548 77.251 1214 77 c +1212.752 77.685 1212.452 77.749 1211 78 c +f +*U +0.000 0.278 0.231 0.224 k +*u +1215.667 77.667 m +1215.222 77.222 1216.278 77.278 1216.333 77.333 c +1216.778 77.778 1215.722 77.722 1215.667 77.667 c +f +*U +0.000 0.231 0.192 0.137 k +*u +1217 78 m +1218.506 77.317 1219.315 77.174 1221 77 c +1219.494 77.683 1218.685 77.826 1217 78 c +f +*U +0.000 0.212 0.082 0.129 k +*u +1249 78 m +1250.506 77.317 1251.315 77.174 1253 77 c +1251.494 77.683 1250.685 77.826 1249 78 c +f +*U +0.000 0.349 0.251 0.216 k +*u +1253 78 m +1254.249 77.315 1254.548 77.251 1256 77 c +1254.752 77.685 1254.451 77.749 1253 78 c +f +*U +0.000 0.506 0.416 0.494 k +*u +1256 78 m +1257.249 77.315 1257.548 77.251 1259 77 c +1257.752 77.685 1257.451 77.749 1256 78 c +f +*U +0.000 0.702 0.537 0.298 k +*u +1259 78 m +1260.249 77.315 1260.548 77.251 1262 77 c +1260.752 77.685 1260.452 77.749 1259 78 c +f +*U +0.000 0.631 0.471 0.325 k +*u +1341 78 m +1342.249 77.315 1342.548 77.251 1344 77 c +1342.752 77.685 1342.451 77.749 1341 78 c +f +*U +0.000 0.204 0.129 0.286 k +*u +1344 78 m +1345 77 l +1344 78 l +f +*U +0.000 0.255 0.188 0.047 k +*u +1125 77 m +1126 76 l +1125 77 l +f +*U +0.000 0.659 0.455 0.314 k +*u +1126 77 m +1127.750 75.745 1128.857 75.386 1131 75 c +1129.249 76.255 1128 76.614 1126 77 c +f +*U +0.000 0.729 0.596 0.271 k +*u +1219 77 m +1220.769 76.221 1222 76 1224 76 c +1222.231 76.779 1220.964 76.912 1219 77 c +f +*U +0.000 0.447 0.353 0.553 k +*u +1224 77 m +1226.613 75.902 1229 76 1232 76 c +1229.387 77 1226.836 76.993 1224 77 c +f +*U +0.000 0.541 0.380 0.447 k +*u +1232 77 m +1234.613 75.902 1237 76 1240 76 c +1237.387 77 1234.835 76.993 1232 77 c +f +*U +0.000 0.478 0.373 0.522 k +*u +1240 77 m +1242.613 75.902 1245 76 1248 76 c +1245.387 77 1242.836 76.993 1240 77 c +f +*U +0.000 0.753 0.690 0.247 k +*u +1248 77 m +1249.249 76.315 1249.548 76.251 1251 76 c +1249.752 76.685 1249.452 76.749 1248 77 c +f +*U +0.000 0.894 0.922 0.078 k +*u +1251 77 m +1252.506 76.317 1253.315 76.174 1255 76 c +1253.494 76.683 1252.685 76.826 1251 77 c +f +*U +0.000 0.427 0.400 0.573 k +*u +1340.667 76.667 m +1340.222 76.222 1341.278 76.278 1341.333 76.333 c +1341.778 76.778 1340.722 76.722 1340.667 76.667 c +f +*U +0.000 0.294 0.247 0.184 k +*u +1342 77 m +1343 76 l +1342 77 l +f +*U +0.000 0.043 0.047 0.216 k +*u +1127 76 m +1128 75 l +1127 76 l +f +*U +0.000 0.533 0.443 0.467 k +*u +1338.667 75.667 m +1338.222 75.222 1339.278 75.278 1339.333 75.333 c +1339.778 75.778 1338.722 75.722 1338.667 75.667 c +f +*U +0.000 0.404 0.322 0.141 k +*u +1340 76 m +1341 75 l +1340 76 l +f +*U +0.000 0.365 0.263 0.231 k +*u +1130 75 m +1131 74 l +1130 75 l +f +*U +0.000 0.733 0.529 0.267 k +*u +1131.667 74.667 m +1131.222 74.222 1132.278 74.278 1132.333 74.333 c +1132.778 74.778 1131.722 74.722 1131.667 74.667 c +f +*U +0.000 0.510 0.400 0.447 k +*u +1336.667 74.667 m +1336.222 74.223 1337.278 74.278 1337.333 74.333 c +1337.778 74.778 1336.722 74.722 1336.667 74.667 c +f +*U +0.000 0.325 0.271 0.063 k +*u +1338 75 m +1339 74 l +1338 75 l +f +*U +0.000 0.349 0.243 0.271 k +*u +1132 74 m +1133 73 l +1132 74 l +f +*U +0.000 0.722 0.486 0.278 k +*u +1133 74 m +1134 72.985 1134.611 72.691 1136 72 c +1135 73.783 1135 73.594 1133 74 c +f +*U +0.000 0.565 0.549 0.357 k +*u +1331 73 m +1332.846 72.533 1334 72.699 1336 73 c +1333.955 73.775 1333 73.592 1331 73 c +f +*U +0.000 0.208 0.196 0.208 k +*u +1336 74 m +1337 73 l +1336 74 l +f +*U +0.000 0.427 0.278 0.000 k +*u +1134 73 m +1135 72 l +1134 73 l +f +*U +0.000 0.341 0.369 0.298 k +*u +1333 73 m +1334 72 l +1333 73 l +f +*U +0.000 0.137 0.173 0.098 k +*u +1334 73 m +1335 72 l +1334 73 l +f +*U +0.000 0.239 0.110 0.118 k +*u +1136 72 m +1137 71 l +1136 72 l +f +*U +0.000 0.345 0.200 0.396 k +*u +1137 72 m +1138 71 l +1137 72 l +f +*U +0.000 0.757 0.545 0.243 k +*u +1138 72 m +1139.750 70.745 1140.857 70.386 1143 70 c +1141.212 71.421 1140.294 71.697 1138 72 c +f +*U +0.000 0.788 0.620 0.212 k +*u +1326 70 m +1329 70 l +1328 72 l +1326.365 71.455 1326.545 71.635 1326 70 c +f +*U +0.000 0.486 0.314 0.514 k +*u +1329.667 71.667 m +1329.222 71.222 1330.278 71.278 1330.333 71.333 c +1330.778 71.778 1329.722 71.722 1329.667 71.667 c +f +*U +0.000 0.239 0.141 0.333 k +*u +1331 72 m +1332 71 l +1331 72 l +f +*U +0.000 0.271 0.169 0.290 k +*u +1139 71 m +1140 70 l +1139 71 l +f +*U +0.000 0.376 0.255 0.000 k +*u +1329 71 m +1330 70 l +1329 71 l +f +*U +0.000 0.463 0.325 0.271 k +*u +1142 70 m +1143 69 l +1142 70 l +f +*U +0.000 0.714 0.573 0.286 k +*u +1143.667 69.667 m +1143.222 69.222 1144.278 69.278 1144.333 69.333 c +1144.778 69.778 1143.722 69.722 1143.667 69.667 c +f +*U +0.000 0.333 0.255 0.282 k +*u +1326 70 m +1327 69 l +1326 70 l +f +*U +0.000 0.431 0.322 0.180 k +*u +1144 69 m +1145 68 l +1144 69 l +f +*U +0.000 0.545 0.420 0.455 k +*u +1145.667 68.667 m +1145.222 68.223 1146.278 68.278 1146.333 68.333 c +1146.778 68.778 1145.722 68.722 1145.667 68.667 c +f +*U +0.000 0.263 0.192 0.102 k +*u +1324 69 m +1325 68 l +1324 69 l +f +*U +0.000 0.267 0.200 0.275 k +*u +1147 68 m +1148 67 l +1147 68 l +f +*U +0.000 0.616 0.490 0.384 k +*u +1148.667 67.667 m +1148.222 67.222 1149.278 67.278 1149.333 67.333 c +1149.778 67.778 1148.722 67.722 1148.667 67.667 c +f +*U +0.000 0.796 0.620 0.204 k +*u +1152 68 m +1152.980 66.217 1152.908 66.406 1155 66 c +1153.860 67 1153.388 67.309 1152 68 c +f +*U +0.000 0.710 0.522 0.271 k +*u +1317 68 m +1318.506 67.317 1319.315 67.174 1321 67 c +1319.494 67.683 1318.685 67.826 1317 68 c +f +*U +0.000 0.388 0.278 0.322 k +*u +1321 68 m +1322 67 l +1321 68 l +f +*U +0.000 0.161 0.129 0.145 k +*u +1322 68 m +1323 67 l +1322 68 l +f +*U +0.000 0.286 0.208 0.067 k +*u +1149 67 m +1150 66 l +1149 67 l +f +*U +0.000 0.525 0.365 0.416 k +*u +1150.667 66.667 m +1150.222 66.222 1151.278 66.278 1151.333 66.333 c +1151.778 66.778 1150.722 66.722 1150.667 66.667 c +f +*U +0.000 0.518 0.384 0.447 k +*u +1316.667 66.667 m +1316.222 66.222 1317.278 66.278 1317.333 66.333 c +1317.778 66.778 1316.722 66.722 1316.667 66.667 c +f +*U +0.000 0.263 0.216 0.361 k +*u +1318 67 m +1319 66 l +1318 67 l +f +*U +0.000 0.118 0.122 0.180 k +*u +1319 67 m +1320 66 l +1319 67 l +f +*U +0.000 0.518 0.361 0.129 k +*u +1152 66 m +1153 65 l +1152 66 l +f +*U +0.000 0.576 0.471 0.416 k +*u +1153.667 65.667 m +1153.222 65.222 1154.278 65.278 1154.333 65.333 c +1154.778 65.778 1153.722 65.722 1153.667 65.667 c +f +*U +0.000 0.745 0.659 0.239 k +*u +1155 66 m +1156.789 64.578 1157.706 64.303 1160 64 c +1158.307 65 1156.960 65.520 1155 66 c +f +*U +0.000 0.502 0.341 0.396 k +*u +1312.333 65.333 m +1312.278 65.278 1312.223 64.222 1312.667 64.667 c +1312.722 64.722 1312.778 65.778 1312.333 65.333 c +f +*U +0.000 0.490 0.412 0.510 k +*u +1313 66 m +1314.249 65.315 1314.549 65.251 1316 65 c +1314.752 65.685 1314.451 65.749 1313 66 c +f +*U +0.000 0.333 0.243 0.137 k +*u +1316 66 m +1317 65 l +1316 66 l +f +*U +0.000 0.314 0.373 0.047 k +*u +1155 65 m +1156 64 l +1155 65 l +f +*U +0.000 0.749 0.710 0.251 k +*u +1310.667 64.667 m +1310.222 64.223 1311.278 64.278 1311.333 64.333 c +1311.778 64.778 1310.722 64.722 1310.667 64.667 c +f +*U +0.000 0.388 0.278 0.027 k +*u +1313 65 m +1314 64 l +1313 65 l +f +*U +0.008 0.024 0.000 0.220 k +*u +1158 64 m +1159 63 l +1158 64 l +f +*U +0.004 0.012 0.000 0.549 k +*u +1159 64 m +1160 63 l +1159 64 l +f +*U +0.000 0.631 0.455 0.369 k +*u +1160.667 63.667 m +1160.222 63.222 1161.278 63.278 1161.333 63.333 c +1161.778 63.778 1160.722 63.722 1160.667 63.667 c +f +*U +0.000 0.412 0.337 0.588 k +*u +1307 64 m +1308.249 63.315 1308.548 63.251 1310 63 c +1308.752 63.685 1308.452 63.749 1307 64 c +f +*U +0.000 0.239 0.192 0.153 k +*u +1310 64 m +1311 63 l +1310 64 l +f +*U +0.000 0.204 0.129 0.071 k +*u +1161 63 m +1162 62 l +1161 63 l +f +*U +0.000 0.325 0.216 0.302 k +*u +1162 63 m +1163 62 l +1162 63 l +f +*U +0.000 0.608 0.451 0.392 k +*u +1163 63 m +1164.249 62.315 1164.548 62.251 1166 62 c +1164.752 62.685 1164.451 62.749 1163 63 c +f +*U +0.000 0.576 0.455 0.424 k +*u +1304.667 62.667 m +1304.222 62.222 1305.278 62.278 1305.333 62.333 c +1305.778 62.778 1304.722 62.722 1304.667 62.667 c +f +*U +0.000 0.341 0.259 0.118 k +*u +1307 63 m +1308 62 l +1307 63 l +f +*U +0.000 0.318 0.231 0.129 k +*u +1165 62 m +1166 61 l +1165 62 l +f +*U +0.000 0.392 0.290 0.408 k +*u +1166 62 m +1167 61 l +1166 62 l +f +*U +0.000 0.565 0.420 0.435 k +*u +1167 62 m +1168.249 61.315 1168.548 61.251 1170 61 c +1168.752 61.685 1168.452 61.749 1167 62 c +f +*U +0.000 0.514 0.384 0.486 k +*u +1300 62 m +1301.249 61.315 1301.548 61.251 1303 61 c +1301.752 61.685 1301.451 61.749 1300 62 c +f +*U +0.000 0.322 0.212 0.145 k +*u +1303 62 m +1304 61 l +1303 62 l +f +*U +0.000 0.122 0.055 0.129 k +*u +1168 61 m +1169 60 l +1168 61 l +f +*U +0.000 0.220 0.161 0.318 k +*u +1169 61 m +1170 60 l +1169 61 l +f +*U +0.000 0.580 0.478 0.420 k +*u +1170.667 60.667 m +1170.222 60.222 1171.278 60.278 1171.333 60.333 c +1171.778 60.778 1170.722 60.722 1170.667 60.667 c +f +*U +0.000 0.600 0.431 0.373 k +*u +1293 60 m +1295 59.324 1296.732 59.613 1299 60 c +1296.761 60.811 1295.353 60.529 1293 60 c +f +*U +0.000 0.475 0.369 0.165 k +*u +1299 61 m +1300 60 l +1299 61 l +f +*U +0.000 0.314 0.263 0.047 k +*u +1300 61 m +1301 60 l +1300 61 l +f +*U +0.000 0.141 0.173 0.071 k +*u +1172 60 m +1173 59 l +1172 60 l +f +*U +0.000 0.325 0.255 0.306 k +*u +1173 60 m +1174 59 l +1173 60 l +f +*U +0.000 0.541 0.376 0.459 k +*u +1174 60 m +1175.506 59.317 1176.315 59.174 1178 59 c +1176.494 59.683 1175.685 59.826 1174 60 c +f +*U +0.000 0.161 0.098 0.282 k +*u +1296 60 m +1297 59 l +1296 60 l +f +*U +0.000 0.082 0.078 0.157 k +*u +1176 59 m +1177 58 l +1176 59 l +f +*U +0.000 0.247 0.184 0.239 k +*u +1177 59 m +1178 58 l +1177 59 l +f +*U +0.000 0.561 0.424 0.439 k +*u +1178 59 m +1179.506 58.317 1180.315 58.174 1182 58 c +1180.494 58.683 1179.685 58.826 1178 59 c +f +*U +0.000 0.663 0.486 0.337 k +*u +1288 59 m +1289.249 58.315 1289.548 58.251 1291 58 c +1289.752 58.685 1289.451 58.749 1288 59 c +f +*U +0.000 0.459 0.318 0.227 k +*u +1291 59 m +1292 58 l +1291 59 l +f +*U +0.000 0.129 0.086 0.071 k +*u +1292.667 58.667 m +1292.222 58.222 1293.278 58.278 1293.333 58.333 c +1293.778 58.778 1292.722 58.722 1292.667 58.667 c +f +*U +0.000 0.176 0.125 0.110 k +*u +1181 58 m +1182 57 l +1181 58 l +f +*U +0.000 0.478 0.325 0.267 k +*u +1182 58 m +1183 57 l +1182 58 l +f +*U +0.000 0.490 0.369 0.510 k +*u +1183 58 m +1184.249 57.315 1184.548 57.251 1186 57 c +1184.752 57.685 1184.452 57.749 1183 58 c +f +*U +0.000 0.631 0.498 0.369 k +*u +1282 58 m +1283.769 57.221 1285 57 1287 57 c +1285.231 57.779 1283.964 57.912 1282 58 c +f +*U +0.000 0.541 0.392 0.114 k +*u +1287 58 m +1288 57 l +1287 58 l +f +*U +0.000 0.239 0.157 0.082 k +*u +1186 57 m +1187 56 l +1186 57 l +f +*U +0.000 0.384 0.275 0.290 k +*u +1187 57 m +1188 56 l +1187 57 l +f +*U +0.000 0.573 0.525 0.427 k +*u +1188 57 m +1189.249 56.315 1189.548 56.251 1191 56 c +1189.752 56.685 1189.452 56.749 1188 57 c +f +*U +0.000 0.420 0.361 0.580 k +*u +1280 57 m +1281 56 l +1280 57 l +f +*U +0.000 0.482 0.353 0.216 k +*u +1281 57 m +1282 56 l +1281 57 l +f +*U +0.000 0.282 0.224 0.047 k +*u +1282.667 56.667 m +1282.222 56.222 1283.278 56.278 1283.333 56.333 c +1283.778 56.778 1282.722 56.722 1282.667 56.667 c +f +*U +0.000 0.384 0.259 0.306 k +*u +1192.667 55.667 m +1192.222 55.222 1193.278 55.278 1193.333 55.333 c +1193.778 55.778 1192.722 55.722 1192.667 55.667 c +f +*U +0.000 0.498 0.373 0.502 k +*u +1194.667 55.667 m +1194.222 55.222 1195.278 55.278 1195.333 55.333 c +1195.778 55.778 1194.722 55.722 1194.667 55.667 c +f +*U +0.000 0.749 0.545 0.251 k +*u +1196 56 m +1197.506 55.317 1198.315 55.174 1200 55 c +1198.494 55.683 1197.685 55.826 1196 56 c +f +*U +0.000 0.580 0.431 0.420 k +*u +1272 56 m +1273.506 55.317 1274.315 55.174 1276 55 c +1274.494 55.683 1273.685 55.826 1272 56 c +f +*U +0.000 0.333 0.208 0.333 k +*u +1276 56 m +1277 55 l +1276 56 l +f +*U +0.000 0.137 0.078 0.102 k +*u +1277.667 55.667 m +1277.222 55.222 1278.278 55.278 1278.333 55.333 c +1278.778 55.777 1277.723 55.723 1277.667 55.667 c +f +*U +0.000 0.176 0.125 0.235 k +*u +1198.667 54.667 m +1198.222 54.222 1199.278 54.278 1199.333 54.333 c +1199.778 54.777 1198.723 54.723 1198.667 54.667 c +f +*U +0.000 0.545 0.451 0.455 k +*u +1200 55 m +1201.769 54.221 1203 54 1205 54 c +1203.231 54.779 1201.964 54.912 1200 55 c +f +*U +0.000 0.741 0.620 0.259 k +*u +1216 55 m +1217.314 53.382 1217.877 53.307 1220 53 c +1218.624 53.911 1217.560 54.404 1216 55 c +f +*U +0.000 0.588 0.612 0.388 k +*u +1264.667 54.667 m +1264.222 54.222 1265.278 54.278 1265.333 54.333 c +1265.778 54.777 1264.723 54.723 1264.667 54.667 c +f +*U +0.000 0.420 0.447 0.553 k +*u +1266 55 m +1267.249 54.315 1267.548 54.251 1269 54 c +1267.752 54.685 1267.452 54.749 1266 55 c +f +*U +0.000 0.200 0.333 0.329 k +*u +1269 55 m +1270 54 l +1269 55 l +f +*U +0.000 0.078 0.251 0.157 k +*u +1270.667 54.667 m +1270.222 54.222 1271.278 54.278 1271.333 54.333 c +1271.778 54.777 1270.723 54.723 1270.667 54.667 c +f +*U +0.000 0.122 0.118 0.302 k +*u +1206.667 53.667 m +1206.222 53.222 1207.278 53.278 1207.333 53.333 c +1207.778 53.778 1206.722 53.722 1206.667 53.667 c +f +*U +0.000 0.612 0.510 0.035 k +*u +1208 54 m +1209 53 l +1208 54 l +f +*U +0.000 0.529 0.420 0.471 k +*u +1210 54 m +1212 53 1213.747 53 1216 53 c +1213.948 53.874 1212.253 53.953 1210 54 c +f +*U +0.000 0.557 0.447 0.443 k +*u +1253 54 m +1255.332 53 1257.457 53 1260 53 c +1257.668 53.985 1255.543 53.981 1253 54 c +f +*U +0.000 0.329 0.239 0.192 k +*u +1260 54 m +1261.506 53.317 1262.315 53.174 1264 53 c +1262.494 53.683 1261.685 53.826 1260 54 c +f +*U +0.000 0.345 0.282 0.173 k +*u +1217 53 m +1219.332 52 1221.457 52 1224 52 c +1221.668 52.985 1219.544 52.981 1217 53 c +f +*U +0.000 0.608 0.424 0.227 k +*u +1224.667 52.667 m +1224.222 52.222 1225.278 52.278 1225.333 52.333 c +1225.778 52.778 1224.722 52.722 1224.667 52.667 c +f +*U +0.000 0.525 0.424 0.475 k +*u +1226 53 m +1228 52 1229.747 52 1232 52 c +1229.948 52.874 1228.253 52.953 1226 53 c +f +*U +0.000 0.392 0.392 0.608 k +*u +1232 53 m +1234.613 51.902 1237 52 1240 52 c +1237.387 53 1234.835 52.993 1232 53 c +f +*U +0.000 0.478 0.337 0.506 k +*u +1240 53 m +1241.506 52.317 1242.315 52.174 1244 52 c +1242.494 52.683 1241.685 52.826 1240 53 c +f +*U +0.000 0.467 0.329 0.275 k +*u +1244.667 52.667 m +1244.222 52.222 1245.278 52.278 1245.333 52.333 c +1245.778 52.778 1244.722 52.722 1244.667 52.667 c +f +*U +0.000 0.404 0.286 0.110 k +*u +1246 53 m +1248 52 1249.747 52 1252 52 c +1249.948 52.874 1248.253 52.953 1246 53 c +f +*U +0.000 0.106 0.090 0.067 k +*u +1252.667 52.667 m +1252.222 52.222 1253.278 52.278 1253.333 52.333 c +1253.778 52.777 1252.723 52.723 1252.667 52.667 c +f +*U +%%Trailer +%%EOF diff --git a/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.svg b/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.svg new file mode 100644 index 0000000..a98e41e --- /dev/null +++ b/deploy/tkfb-package/web-ui/img/technicalkorea_Logo.svg @@ -0,0 +1,3390 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/index.html b/deploy/tkfb-package/web-ui/index.html new file mode 100644 index 0000000..e87b534 --- /dev/null +++ b/deploy/tkfb-package/web-ui/index.html @@ -0,0 +1,29 @@ + + + + + + (주)테크니컬코리아 생산팀 포털 + + + + + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/admin-settings.js b/deploy/tkfb-package/web-ui/js/admin-settings.js new file mode 100644 index 0000000..50b47fe --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/admin-settings.js @@ -0,0 +1,1260 @@ +// admin-settings.js - 관리자 설정 페이지 + +// 전역 변수 +let currentUser = null; +let users = []; +let filteredUsers = []; +let currentEditingUser = null; + +// DOM 요소 +const elements = { + // 시간 + timeValue: document.getElementById('timeValue'), + + // 사용자 정보 + userName: document.getElementById('userName'), + userRole: document.getElementById('userRole'), + userInitial: document.getElementById('userInitial'), + + // 검색 및 필터 + userSearch: document.getElementById('userSearch'), + filterButtons: document.querySelectorAll('.filter-btn'), + + // 테이블 + usersTableBody: document.getElementById('usersTableBody'), + emptyState: document.getElementById('emptyState'), + + // 버튼 + addUserBtn: document.getElementById('addUserBtn'), + saveUserBtn: document.getElementById('saveUserBtn'), + confirmDeleteBtn: document.getElementById('confirmDeleteBtn'), + + // 모달 + userModal: document.getElementById('userModal'), + deleteModal: document.getElementById('deleteModal'), + modalTitle: document.getElementById('modalTitle'), + + // 폼 + userForm: document.getElementById('userForm'), + userNameInput: document.getElementById('userName'), + userIdInput: document.getElementById('userId'), + userPasswordInput: document.getElementById('userPassword'), + userRoleSelect: document.getElementById('userRole'), + userEmailInput: document.getElementById('userEmail'), + userPhoneInput: document.getElementById('userPhone'), + passwordGroup: document.getElementById('passwordGroup'), + + // 토스트 + toastContainer: document.getElementById('toastContainer') +}; + +// ========== 초기화 ========== // +document.addEventListener('DOMContentLoaded', async () => { + console.log('🔧 관리자 설정 페이지 초기화 시작'); + + try { + await initializePage(); + console.log('✅ 관리자 설정 페이지 초기화 완료'); + } catch (error) { + console.error('❌ 페이지 초기화 오류:', error); + showToast('페이지를 불러오는 중 오류가 발생했습니다.', 'error'); + } +}); + +async function initializePage() { + // 이벤트 리스너 설정 + setupEventListeners(); + + // 사용자 목록 로드 + await loadUsers(); +} + +// ========== 사용자 정보 설정 ========== // +// navbar/sidebar는 app-init.js에서 공통 처리 +function setupUserInfo() { + const authData = getAuthData(); + if (authData && authData.user) { + currentUser = authData.user; + console.log('👤 사용자 정보 로드 완료:', currentUser.name, currentUser.role); + } +} + +function getAuthData() { + const token = localStorage.getItem('token'); + const user = localStorage.getItem('user'); + return { + token, + user: user ? JSON.parse(user) : null + }; +} + +// ========== 시간 업데이트 ========== // +function updateCurrentTime() { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + if (elements.timeValue) { + elements.timeValue.textContent = `${hours}시 ${minutes}분 ${seconds}초`; + } +} + +// ========== 이벤트 리스너 ========== // +function setupEventListeners() { + // 검색 + if (elements.userSearch) { + elements.userSearch.addEventListener('input', handleSearch); + } + + // 필터 버튼 + elements.filterButtons.forEach(btn => { + btn.addEventListener('click', handleFilter); + }); + + // 사용자 추가 버튼 + if (elements.addUserBtn) { + elements.addUserBtn.addEventListener('click', openAddUserModal); + } + + // 사용자 저장 버튼 + if (elements.saveUserBtn) { + elements.saveUserBtn.addEventListener('click', saveUser); + } + + // 삭제 확인 버튼 + if (elements.confirmDeleteBtn) { + elements.confirmDeleteBtn.addEventListener('click', confirmDeleteUser); + } + + // 로그아웃 버튼 + const logoutBtn = document.getElementById('logoutBtn'); + if (logoutBtn) { + logoutBtn.addEventListener('click', handleLogout); + } + + // 프로필 드롭다운 + const userProfile = document.getElementById('userProfile'); + const profileMenu = document.getElementById('profileMenu'); + if (userProfile && profileMenu) { + userProfile.addEventListener('click', (e) => { + e.stopPropagation(); + profileMenu.style.display = profileMenu.style.display === 'block' ? 'none' : 'block'; + }); + + document.addEventListener('click', () => { + profileMenu.style.display = 'none'; + }); + } +} + +// ========== 사용자 관리 ========== // +async function loadUsers() { + try { + console.log('👥 사용자 목록 로딩...'); + + // 실제 API에서 사용자 데이터 가져오기 + const response = await window.apiCall('/users'); + users = Array.isArray(response) ? response : (response.data || []); + + console.log(`✅ 사용자 ${users.length}명 로드 완료`); + + // 필터링된 사용자 목록 초기화 + filteredUsers = [...users]; + + // 테이블 렌더링 + renderUsersTable(); + + } catch (error) { + console.error('❌ 사용자 목록 로딩 오류:', error); + showToast('사용자 목록을 불러오는 중 오류가 발생했습니다.', 'error'); + users = []; + filteredUsers = []; + renderUsersTable(); + } +} + +function renderUsersTable() { + if (!elements.usersTableBody) return; + + if (filteredUsers.length === 0) { + elements.usersTableBody.innerHTML = ''; + if (elements.emptyState) { + elements.emptyState.style.display = 'block'; + } + return; + } + + if (elements.emptyState) { + elements.emptyState.style.display = 'none'; + } + + elements.usersTableBody.innerHTML = filteredUsers.map(user => ` + + + + + ${user.username} + + + ${getRoleIcon(user.role)} ${getRoleName(user.role)} + + + + + ${user.is_active ? '활성' : '비활성'} + + + ${formatDate(user.last_login) || '로그인 기록 없음'} + +
+ + ${user.role !== 'Admin' && user.role !== 'admin' ? ` + + ` : ''} + + + +
+ + + `).join(''); +} + +function getRoleIcon(role) { + const icons = { + admin: '👑', + leader: '👨‍💼', + user: '👤' + }; + return icons[role] || '👤'; +} + +function getRoleName(role) { + const names = { + admin: '관리자', + leader: '그룹장', + user: '작업자' + }; + return names[role] || '작업자'; +} + +function formatDate(dateString) { + if (!dateString) return null; + + const date = new Date(dateString); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); +} + +// ========== 검색 및 필터링 ========== // +function handleSearch(e) { + const searchTerm = e.target.value.toLowerCase(); + + filteredUsers = users.filter(user => { + return (user.name && user.name.toLowerCase().includes(searchTerm)) || + (user.username && user.username.toLowerCase().includes(searchTerm)) || + (user.email && user.email.toLowerCase().includes(searchTerm)); + }); + + renderUsersTable(); +} + +function handleFilter(e) { + const filterType = e.target.dataset.filter; + + // 활성 버튼 변경 + elements.filterButtons.forEach(btn => btn.classList.remove('active')); + e.target.classList.add('active'); + + // 필터링 + if (filterType === 'all') { + filteredUsers = [...users]; + } else { + filteredUsers = users.filter(user => user.role === filterType); + } + + renderUsersTable(); +} + +// ========== 모달 관리 ========== // +function openAddUserModal() { + currentEditingUser = null; + + if (elements.modalTitle) { + elements.modalTitle.textContent = '새 사용자 추가'; + } + + // 폼 초기화 + if (elements.userForm) { + elements.userForm.reset(); + } + + // 비밀번호 필드 표시 + if (elements.passwordGroup) { + elements.passwordGroup.style.display = 'block'; + } + + if (elements.userPasswordInput) { + elements.userPasswordInput.required = true; + } + + // 작업자 연결 섹션 숨기기 (새 사용자 추가 시) + const workerLinkGroup = document.getElementById('workerLinkGroup'); + if (workerLinkGroup) { + workerLinkGroup.style.display = 'none'; + } + + if (elements.userModal) { + elements.userModal.style.display = 'flex'; + } +} + +function editUser(userId) { + const user = users.find(u => u.user_id === userId); + if (!user) return; + + currentEditingUser = user; + + if (elements.modalTitle) { + elements.modalTitle.textContent = '사용자 정보 수정'; + } + + // 역할 이름을 HTML select option value로 변환 + const roleToValueMap = { + 'Admin': 'admin', + 'System Admin': 'admin', + 'User': 'user', + 'Guest': 'user' + }; + + // 폼에 데이터 채우기 + if (elements.userNameInput) elements.userNameInput.value = user.name || ''; + if (elements.userIdInput) elements.userIdInput.value = user.username || ''; + if (elements.userRoleSelect) elements.userRoleSelect.value = roleToValueMap[user.role] || 'user'; + if (elements.userEmailInput) elements.userEmailInput.value = user.email || ''; + if (elements.userPhoneInput) elements.userPhoneInput.value = user.phone || ''; + + // 비밀번호 필드 숨기기 (수정 시에는 선택사항) + if (elements.passwordGroup) { + elements.passwordGroup.style.display = 'none'; + } + + if (elements.userPasswordInput) { + elements.userPasswordInput.required = false; + } + + // 작업자 연결 섹션 표시 (수정 시에만) + const workerLinkGroup = document.getElementById('workerLinkGroup'); + if (workerLinkGroup) { + workerLinkGroup.style.display = 'block'; + updateLinkedWorkerDisplay(user); + } + + if (elements.userModal) { + elements.userModal.style.display = 'flex'; + } +} + +function closeUserModal() { + if (elements.userModal) { + elements.userModal.style.display = 'none'; + } + currentEditingUser = null; +} + +// 영구 삭제 (Hard Delete) +async function permanentDeleteUser(userId, username) { + if (!confirm(`⚠️ 경고: "${username}" 사용자를 영구 삭제하시겠습니까?\n\n이 작업은 되돌릴 수 없습니다!\n관련된 모든 데이터(로그인 기록, 권한 설정 등)도 함께 삭제됩니다.`)) { + return; + } + + // 이중 확인 + if (!confirm(`정말로 "${username}"을(를) 영구 삭제하시겠습니까?\n\n[확인]을 누르면 즉시 삭제됩니다.`)) { + return; + } + + try { + const response = await window.apiCall(`/users/${userId}/permanent`, 'DELETE'); + + if (response.success) { + showToast(`"${username}" 사용자가 영구 삭제되었습니다.`, 'success'); + await loadUsers(); + } else { + throw new Error(response.message || '사용자 삭제에 실패했습니다.'); + } + } catch (error) { + console.error('사용자 영구 삭제 오류:', error); + showToast(`사용자 삭제 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +function closeDeleteModal() { + if (elements.deleteModal) { + elements.deleteModal.style.display = 'none'; + } + currentEditingUser = null; +} + +// ========== 비밀번호 초기화 ========== // +async function resetPassword(userId, username) { + if (!confirm(`${username} 사용자의 비밀번호를 000000으로 초기화하시겠습니까?`)) { + return; + } + + try { + const response = await window.apiCall(`/users/${userId}/reset-password`, 'POST'); + + if (response.success) { + showToast(`${username}의 비밀번호가 000000으로 초기화되었습니다.`, 'success'); + } else { + showToast(response.message || '비밀번호 초기화에 실패했습니다.', 'error'); + } + } catch (error) { + console.error('비밀번호 초기화 오류:', error); + showToast('비밀번호 초기화 중 오류가 발생했습니다.', 'error'); + } +} +window.resetPassword = resetPassword; + +// ========== 사용자 CRUD ========== // +async function saveUser() { + try { + const formData = { + name: elements.userNameInput?.value, + username: elements.userIdInput?.value, + role: elements.userRoleSelect?.value, // HTML select value는 이미 'admin' 또는 'user' + email: elements.userEmailInput?.value + }; + + console.log('저장할 데이터:', formData); + + // 유효성 검사 + if (!formData.name || !formData.username || !formData.role) { + showToast('필수 항목을 모두 입력해주세요.', 'error'); + return; + } + + // 비밀번호 처리 + if (!currentEditingUser && elements.userPasswordInput?.value) { + formData.password = elements.userPasswordInput.value; + } else if (currentEditingUser && elements.userPasswordInput?.value) { + formData.password = elements.userPasswordInput.value; + } + + let response; + if (currentEditingUser) { + // 수정 + response = await window.apiCall(`/users/${currentEditingUser.user_id}`, 'PUT', formData); + } else { + // 생성 + response = await window.apiCall('/users', 'POST', formData); + } + + if (response.success || response.user_id) { + const action = currentEditingUser ? '수정' : '생성'; + showToast(`사용자가 성공적으로 ${action}되었습니다.`, 'success'); + + closeUserModal(); + await loadUsers(); + } else { + throw new Error(response.message || '사용자 저장에 실패했습니다.'); + } + + } catch (error) { + console.error('사용자 저장 오류:', error); + showToast(`사용자 저장 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +async function confirmDeleteUser() { + if (!currentEditingUser) return; + + try { + const response = await window.apiCall(`/users/${currentEditingUser.user_id}`, 'DELETE'); + + if (response.success) { + showToast('사용자가 성공적으로 삭제되었습니다.', 'success'); + closeDeleteModal(); + await loadUsers(); + } else { + throw new Error(response.message || '사용자 삭제에 실패했습니다.'); + } + + } catch (error) { + console.error('사용자 삭제 오류:', error); + showToast(`사용자 삭제 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +async function toggleUserStatus(userId) { + try { + const user = users.find(u => u.user_id === userId); + if (!user) return; + + const newStatus = !user.is_active; + const response = await window.apiCall(`/users/${userId}/status`, 'PUT', { is_active: newStatus }); + + if (response.success) { + const action = newStatus ? '활성화' : '비활성화'; + showToast(`사용자가 성공적으로 ${action}되었습니다.`, 'success'); + await loadUsers(); + } else { + throw new Error(response.message || '사용자 상태 변경에 실패했습니다.'); + } + + } catch (error) { + console.error('사용자 상태 변경 오류:', error); + showToast(`사용자 상태 변경 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +// ========== 로그아웃 ========== // +function handleLogout() { + if (confirm('로그아웃하시겠습니까?')) { + localStorage.clear(); + window.location.href = '/index.html'; + } +} + +// ========== 토스트 알림 ========== // +function showToast(message, type = 'info', duration = 3000) { + if (!elements.toastContainer) return; + + const toast = document.createElement('div'); + toast.className = `toast ${type}`; + + const iconMap = { + success: '✅', + error: '❌', + warning: '⚠️', + info: 'ℹ️' + }; + + toast.innerHTML = ` +
${iconMap[type] || 'ℹ️'}
+
${message}
+ + `; + + elements.toastContainer.appendChild(toast); + + // 자동 제거 + setTimeout(() => { + if (toast.parentElement) { + toast.remove(); + } + }, duration); +} + +// ========== 전역 함수 (HTML에서 호출) ========== // +window.editUser = editUser; +window.toggleUserStatus = toggleUserStatus; +window.closeUserModal = closeUserModal; +window.closeDeleteModal = closeDeleteModal; +window.permanentDeleteUser = permanentDeleteUser; + +// ========== 페이지 권한 관리 ========== // +let allPages = []; +let userPageAccess = []; + +// 모든 페이지 목록 로드 +async function loadAllPages() { + try { + const response = await apiCall('/pages'); + allPages = response.data || response || []; + console.log('📄 페이지 목록 로드:', allPages.length, '개'); + } catch (error) { + console.error('❌ 페이지 목록 로드 오류:', error); + allPages = []; + } +} + +// 사용자의 페이지 권한 로드 +async function loadUserPageAccess(userId) { + try { + const response = await apiCall(`/users/${userId}/page-access`); + userPageAccess = response.data?.pageAccess || []; + console.log(`👤 사용자 ${userId} 페이지 권한 로드:`, userPageAccess.length, '개'); + } catch (error) { + console.error('❌ 사용자 페이지 권한 로드 오류:', error); + userPageAccess = []; + } +} + + +// 페이지 권한 저장 +async function savePageAccess(userId, containerId = null) { + try { + // 특정 컨테이너가 지정되면 그 안에서만 체크박스 선택 + const container = containerId ? document.getElementById(containerId) : document; + const checkboxes = container.querySelectorAll('.page-access-checkbox:not([disabled])'); + + // 중복 page_id 제거 (Map 사용) + const pageAccessMap = new Map(); + checkboxes.forEach(checkbox => { + const pageId = parseInt(checkbox.dataset.pageId); + pageAccessMap.set(pageId, { + page_id: pageId, + can_access: checkbox.checked ? 1 : 0 + }); + }); + + const pageAccessData = Array.from(pageAccessMap.values()); + + console.log('📤 페이지 권한 저장:', userId, pageAccessData); + + await apiCall(`/users/${userId}/page-access`, 'PUT', { + pageAccess: pageAccessData + }); + + console.log('✅ 페이지 권한 저장 완료'); + } catch (error) { + console.error('❌ 페이지 권한 저장 오류:', error); + throw error; + } +} + + + + +// ========== 페이지 권한 관리 모달 ========== // +let currentPageAccessUser = null; + +// 페이지 권한 관리 모달 열기 +async function managePageAccess(userId) { + try { + // 페이지 목록이 없으면 로드 + if (allPages.length === 0) { + await loadAllPages(); + } + + // 사용자 정보 가져오기 + const user = users.find(u => u.user_id === userId); + if (!user) { + showToast('사용자를 찾을 수 없습니다.', 'error'); + return; + } + + currentPageAccessUser = user; + + // 사용자의 페이지 권한 로드 + await loadUserPageAccess(userId); + + // 모달 정보 업데이트 + const userName = user.name || user.username; + document.getElementById('pageAccessModalTitle').textContent = userName + ' - 페이지 권한 관리'; + document.getElementById('pageAccessUserName').textContent = userName; + document.getElementById('pageAccessUserRole').textContent = getRoleName(user.role); + document.getElementById('pageAccessUserAvatar').textContent = userName.charAt(0); + + // 페이지 권한 체크박스 렌더링 + renderPageAccessModalList(); + + // 모달 표시 + document.getElementById('pageAccessModal').style.display = 'flex'; + } catch (error) { + console.error('❌ 페이지 권한 관리 모달 오류:', error); + showToast('페이지 권한 관리를 열 수 없습니다.', 'error'); + } +} + +// 페이지 권한 모달 닫기 +function closePageAccessModal() { + document.getElementById('pageAccessModal').style.display = 'none'; + currentPageAccessUser = null; +} + +// 페이지 권한 체크박스 렌더링 (모달용) - 폴더 구조 형태 +function renderPageAccessModalList() { + const pageAccessList = document.getElementById('pageAccessModalList'); + if (!pageAccessList) return; + + // 폴더 구조 정의 (page_key 패턴 기준) + const folderStructure = { + 'dashboard': { name: '대시보드', icon: '📊', pages: [] }, + 'work': { name: '작업 관리', icon: '📋', pages: [] }, + 'safety': { name: '안전 관리', icon: '🛡️', pages: [] }, + 'attendance': { name: '근태 관리', icon: '📅', pages: [] }, + 'admin': { name: '시스템 관리', icon: '⚙️', pages: [] }, + 'profile': { name: '내 정보', icon: '👤', pages: [] } + }; + + // 페이지를 폴더별로 분류 + allPages.forEach(page => { + const pageKey = page.page_key || ''; + + if (pageKey === 'dashboard') { + folderStructure['dashboard'].pages.push(page); + } else if (pageKey.startsWith('work.')) { + folderStructure['work'].pages.push(page); + } else if (pageKey.startsWith('safety.')) { + folderStructure['safety'].pages.push(page); + } else if (pageKey.startsWith('attendance.')) { + folderStructure['attendance'].pages.push(page); + } else if (pageKey.startsWith('admin.')) { + folderStructure['admin'].pages.push(page); + } else if (pageKey.startsWith('profile.')) { + folderStructure['profile'].pages.push(page); + } + }); + + // HTML 생성 - 폴더 트리 형태 + let html = '
'; + + Object.keys(folderStructure).forEach(folderKey => { + const folder = folderStructure[folderKey]; + if (folder.pages.length === 0) return; + + const folderId = 'folder-' + folderKey; + + html += '
'; + html += '
'; + html += '' + folder.icon + ''; + html += '' + folder.name + ''; + html += '(' + folder.pages.length + ')'; + html += ''; + html += '
'; + + html += '
'; + + folder.pages.forEach(page => { + // 프로필과 대시보드는 모든 사용자가 접근 가능 + const isAlwaysAccessible = page.page_key === 'dashboard' || page.page_key.startsWith('profile.'); + const isChecked = userPageAccess.find(p => p.page_id === page.id && p.can_access === 1) || isAlwaysAccessible; + + // 파일명만 추출 (page_key에서) + const fileName = page.page_key.split('.').pop() || page.page_key; + + html += '
'; + html += ''; + html += '
'; + }); + + html += '
'; // folder-content + html += '
'; // folder-group + }); + + html += '
'; // folder-tree + + pageAccessList.innerHTML = html; +} + +// 폴더 접기/펼치기 +function toggleFolder(folderId) { + const content = document.getElementById(folderId); + const toggle = document.getElementById('toggle-' + folderId); + + if (content && toggle) { + const isExpanded = content.style.display !== 'none'; + content.style.display = isExpanded ? 'none' : 'block'; + toggle.textContent = isExpanded ? '▶' : '▼'; + } +} +window.toggleFolder = toggleFolder; + +// 페이지 권한 저장 (모달용) +async function savePageAccessFromModal() { + if (!currentPageAccessUser) { + showToast('사용자 정보가 없습니다.', 'error'); + return; + } + + try { + // 모달 컨테이너 지정 + await savePageAccess(currentPageAccessUser.user_id, 'pageAccessModalList'); + showToast('페이지 권한이 저장되었습니다.', 'success'); + + // 캐시 삭제 (사용자가 다시 로그인하거나 페이지 새로고침 필요) + localStorage.removeItem('userPageAccess'); + + closePageAccessModal(); + } catch (error) { + console.error('❌ 페이지 권한 저장 오류:', error); + showToast('페이지 권한 저장에 실패했습니다.', 'error'); + } +} + +// 전역 함수로 등록 +window.managePageAccess = managePageAccess; +window.closePageAccessModal = closePageAccessModal; + +// 저장 버튼 이벤트 리스너 +document.addEventListener('DOMContentLoaded', () => { + const saveBtn = document.getElementById('savePageAccessBtn'); + if (saveBtn) { + saveBtn.addEventListener('click', savePageAccessFromModal); + } +}); + +// ========== 작업자 연결 기능 ========== // +let departments = []; +let selectedWorkerId = null; + +// 연결된 작업자 정보 표시 업데이트 +function updateLinkedWorkerDisplay(user) { + const linkedWorkerInfo = document.getElementById('linkedWorkerInfo'); + if (!linkedWorkerInfo) return; + + if (user.worker_id && user.worker_name) { + linkedWorkerInfo.innerHTML = ` + + 👤 ${user.worker_name} + ${user.department_name ? `(${user.department_name})` : ''} + + `; + } else { + linkedWorkerInfo.innerHTML = '연결된 작업자 없음'; + } +} + +// 작업자 선택 모달 열기 +async function openWorkerSelectModal() { + if (!currentEditingUser) { + showToast('사용자 정보가 없습니다.', 'error'); + return; + } + + selectedWorkerId = currentEditingUser.worker_id || null; + + // 부서 목록 로드 + await loadDepartmentsForSelect(); + + // 모달 표시 + document.getElementById('workerSelectModal').style.display = 'flex'; +} +window.openWorkerSelectModal = openWorkerSelectModal; + +// 작업자 선택 모달 닫기 +function closeWorkerSelectModal() { + document.getElementById('workerSelectModal').style.display = 'none'; + selectedWorkerId = null; +} +window.closeWorkerSelectModal = closeWorkerSelectModal; + +// 부서 목록 로드 +async function loadDepartmentsForSelect() { + try { + const response = await window.apiCall('/departments'); + departments = response.data || response || []; + + renderDepartmentList(); + } catch (error) { + console.error('부서 목록 로드 실패:', error); + showToast('부서 목록을 불러오는데 실패했습니다.', 'error'); + } +} + +// 부서 목록 렌더링 +function renderDepartmentList() { + const container = document.getElementById('departmentList'); + if (!container) return; + + if (departments.length === 0) { + container.innerHTML = '
등록된 부서가 없습니다
'; + return; + } + + container.innerHTML = departments.map(dept => ` +
+ 📁 + ${dept.department_name} + ${dept.worker_count || 0}명 +
+ `).join(''); +} + +// 부서 선택 +async function selectDepartment(departmentId) { + // 활성 상태 업데이트 + document.querySelectorAll('.department-item').forEach(item => { + item.classList.remove('active'); + }); + document.querySelector(`.department-item[data-dept-id="${departmentId}"]`)?.classList.add('active'); + + // 해당 부서의 작업자 목록 로드 + await loadWorkersForSelect(departmentId); +} +window.selectDepartment = selectDepartment; + +// 부서별 작업자 목록 로드 +async function loadWorkersForSelect(departmentId) { + try { + const response = await window.apiCall(`/departments/${departmentId}/workers`); + const workers = response.data || response || []; + + renderWorkerListForSelect(workers); + } catch (error) { + console.error('작업자 목록 로드 실패:', error); + showToast('작업자 목록을 불러오는데 실패했습니다.', 'error'); + } +} + +// 작업자 목록 렌더링 (선택용) +function renderWorkerListForSelect(workers) { + const container = document.getElementById('workerListForSelect'); + if (!container) return; + + if (workers.length === 0) { + container.innerHTML = '
이 부서에 작업자가 없습니다
'; + return; + } + + // 이미 다른 계정에 연결된 작업자 확인을 위해 users 배열 사용 + const linkedWorkerIds = users + .filter(u => u.worker_id && u.user_id !== currentEditingUser?.user_id) + .map(u => u.worker_id); + + container.innerHTML = workers.map(worker => { + const isSelected = selectedWorkerId === worker.worker_id; + const isLinkedToOther = linkedWorkerIds.includes(worker.worker_id); + const linkedUser = isLinkedToOther ? users.find(u => u.worker_id === worker.worker_id) : null; + + return ` +
+
${worker.worker_name.charAt(0)}
+
+
${worker.worker_name}
+
${getJobTypeName(worker.job_type)}
+
+ ${isLinkedToOther ? `${linkedUser?.username} 연결됨` : ''} +
${isSelected ? '✓' : ''}
+
+ `; + }).join(''); +} + +// 직책 한글 변환 +function getJobTypeName(jobType) { + const names = { + leader: '그룹장', + worker: '작업자', + admin: '관리자' + }; + return names[jobType] || jobType || '-'; +} + +// 작업자 선택 +async function selectWorker(workerId, workerName) { + selectedWorkerId = workerId; + + // UI 업데이트 + document.querySelectorAll('.worker-select-item').forEach(item => { + item.classList.remove('selected'); + item.querySelector('.select-indicator').textContent = ''; + }); + + const selectedItem = document.querySelector(`.worker-select-item[onclick*="${workerId}"]`); + if (selectedItem) { + selectedItem.classList.add('selected'); + selectedItem.querySelector('.select-indicator').textContent = '✓'; + } + + // 서버에 저장 + try { + const response = await window.apiCall(`/users/${currentEditingUser.user_id}`, 'PUT', { + worker_id: workerId + }); + + if (response.success) { + // currentEditingUser 업데이트 + currentEditingUser.worker_id = workerId; + currentEditingUser.worker_name = workerName; + + // 부서 정보도 업데이트 + const dept = departments.find(d => + document.querySelector(`.department-item.active`)?.dataset.deptId == d.department_id + ); + if (dept) { + currentEditingUser.department_name = dept.department_name; + } + + // users 배열 업데이트 + const userIndex = users.findIndex(u => u.user_id === currentEditingUser.user_id); + if (userIndex !== -1) { + users[userIndex] = { ...users[userIndex], ...currentEditingUser }; + } + + // 표시 업데이트 + updateLinkedWorkerDisplay(currentEditingUser); + + showToast(`${workerName} 작업자가 연결되었습니다.`, 'success'); + closeWorkerSelectModal(); + } else { + throw new Error(response.message || '작업자 연결에 실패했습니다.'); + } + } catch (error) { + console.error('작업자 연결 오류:', error); + showToast(`작업자 연결 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} +window.selectWorker = selectWorker; + +// 작업자 연결 해제 +async function unlinkWorker() { + if (!currentEditingUser) { + showToast('사용자 정보가 없습니다.', 'error'); + return; + } + + if (!currentEditingUser.worker_id) { + showToast('연결된 작업자가 없습니다.', 'warning'); + closeWorkerSelectModal(); + return; + } + + if (!confirm('작업자 연결을 해제하시겠습니까?')) { + return; + } + + try { + const response = await window.apiCall(`/users/${currentEditingUser.user_id}`, 'PUT', { + worker_id: null + }); + + if (response.success) { + // currentEditingUser 업데이트 + currentEditingUser.worker_id = null; + currentEditingUser.worker_name = null; + currentEditingUser.department_name = null; + + // users 배열 업데이트 + const userIndex = users.findIndex(u => u.user_id === currentEditingUser.user_id); + if (userIndex !== -1) { + users[userIndex] = { ...users[userIndex], worker_id: null, worker_name: null, department_name: null }; + } + + // 표시 업데이트 + updateLinkedWorkerDisplay(currentEditingUser); + + showToast('작업자 연결이 해제되었습니다.', 'success'); + closeWorkerSelectModal(); + } else { + throw new Error(response.message || '연결 해제에 실패했습니다.'); + } + } catch (error) { + console.error('작업자 연결 해제 오류:', error); + showToast(`연결 해제 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} +window.unlinkWorker = unlinkWorker; + +// ========== 알림 수신자 관리 ========== // +let notificationRecipients = {}; +let allUsersForRecipient = []; +let currentNotificationType = null; + +const NOTIFICATION_TYPE_CONFIG = { + repair: { name: '설비 수리', icon: '🔧', description: '설비 수리 신청 시 알림을 받을 사용자' }, + safety: { name: '안전 신고', icon: '⚠️', description: '안전 관련 신고 시 알림을 받을 사용자' }, + nonconformity: { name: '부적합 신고', icon: '🚫', description: '부적합 사항 신고 시 알림을 받을 사용자' }, + equipment: { name: '설비 관련', icon: '🔩', description: '설비 관련 알림을 받을 사용자' }, + maintenance: { name: '정기점검', icon: '🛠️', description: '정기점검 알림을 받을 사용자' }, + system: { name: '시스템', icon: '📢', description: '시스템 알림을 받을 사용자' } +}; + +// 알림 수신자 목록 로드 +async function loadNotificationRecipients() { + try { + const response = await window.apiCall('/notification-recipients'); + if (response.success) { + notificationRecipients = response.data || {}; + renderNotificationTypeCards(); + } + } catch (error) { + console.error('알림 수신자 로드 오류:', error); + } +} + +// 알림 유형 카드 렌더링 +function renderNotificationTypeCards() { + const container = document.getElementById('notificationTypeCards'); + if (!container) return; + + let html = ''; + + Object.keys(NOTIFICATION_TYPE_CONFIG).forEach(type => { + const config = NOTIFICATION_TYPE_CONFIG[type]; + const recipients = notificationRecipients[type]?.recipients || []; + + html += ` +
+
+
+ ${config.icon} + ${config.name} +
+ +
+
+ ${recipients.length > 0 + ? recipients.map(r => ` + + 👤 + ${r.user_name || r.username} + + `).join('') + : '지정된 수신자 없음' + } +
+
+ `; + }); + + container.innerHTML = html; +} + +// 수신자 편집 모달 열기 +async function openRecipientModal(notificationType) { + currentNotificationType = notificationType; + const config = NOTIFICATION_TYPE_CONFIG[notificationType]; + + // 모달 정보 업데이트 + document.getElementById('recipientModalTitle').textContent = config.name + ' 알림 수신자'; + document.getElementById('recipientModalDesc').textContent = config.description; + + // 사용자 목록 로드 (users가 이미 로드되어 있으면 사용) + if (users.length === 0) { + await loadUsers(); + } + allUsersForRecipient = users.filter(u => u.is_active); + + // 현재 수신자 목록 + const currentRecipients = notificationRecipients[notificationType]?.recipients || []; + const currentRecipientIds = currentRecipients.map(r => r.user_id); + + // 사용자 목록 렌더링 + renderRecipientUserList(currentRecipientIds); + + // 검색 이벤트 + const searchInput = document.getElementById('recipientSearchInput'); + searchInput.value = ''; + searchInput.oninput = (e) => { + renderRecipientUserList(currentRecipientIds, e.target.value); + }; + + // 모달 표시 + document.getElementById('notificationRecipientModal').style.display = 'flex'; +} +window.openRecipientModal = openRecipientModal; + +// 수신자 사용자 목록 렌더링 +function renderRecipientUserList(selectedIds, searchTerm = '') { + const container = document.getElementById('recipientUserList'); + if (!container) return; + + let filteredUsers = allUsersForRecipient; + + if (searchTerm) { + const term = searchTerm.toLowerCase(); + filteredUsers = filteredUsers.filter(u => + (u.name && u.name.toLowerCase().includes(term)) || + (u.username && u.username.toLowerCase().includes(term)) + ); + } + + if (filteredUsers.length === 0) { + container.innerHTML = '
사용자가 없습니다
'; + return; + } + + container.innerHTML = filteredUsers.map(user => { + const isSelected = selectedIds.includes(user.user_id); + return ` +
+ +
${(user.name || user.username).charAt(0)}
+ +
+ `; + }).join(''); +} + +// 수신자 토글 +function toggleRecipientUser(userId, element) { + const checkbox = element.querySelector('input[type="checkbox"]'); + checkbox.checked = !checkbox.checked; + element.classList.toggle('selected', checkbox.checked); +} +window.toggleRecipientUser = toggleRecipientUser; + +// 수신자 모달 닫기 +function closeRecipientModal() { + document.getElementById('notificationRecipientModal').style.display = 'none'; + currentNotificationType = null; +} +window.closeRecipientModal = closeRecipientModal; + +// 알림 수신자 저장 +async function saveNotificationRecipients() { + if (!currentNotificationType) { + showToast('알림 유형이 선택되지 않았습니다.', 'error'); + return; + } + + try { + const checkboxes = document.querySelectorAll('#recipientUserList input[type="checkbox"]:checked'); + const userIds = Array.from(checkboxes).map(cb => parseInt(cb.dataset.userId)); + + const response = await window.apiCall(`/notification-recipients/${currentNotificationType}`, 'PUT', { + user_ids: userIds + }); + + if (response.success) { + showToast('알림 수신자가 저장되었습니다.', 'success'); + closeRecipientModal(); + await loadNotificationRecipients(); + } else { + throw new Error(response.message || '저장에 실패했습니다.'); + } + } catch (error) { + console.error('알림 수신자 저장 오류:', error); + showToast(`저장 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} +window.saveNotificationRecipients = saveNotificationRecipients; + +// 초기화 시 알림 수신자 로드 +const originalInitializePage = initializePage; +initializePage = async function() { + await originalInitializePage(); + await loadNotificationRecipients(); +}; diff --git a/deploy/tkfb-package/web-ui/js/admin.js b/deploy/tkfb-package/web-ui/js/admin.js new file mode 100644 index 0000000..b48105d --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/admin.js @@ -0,0 +1,34 @@ +// ✅ /js/admin.js (수정됨 - 중복 로딩 제거) +async function initDashboard() { + // 로그인 토큰 확인 + const token = localStorage.getItem('token'); + if (!token) { + location.href = '/index.html'; + return; + } + + // ✅ navbar, sidebar는 각각의 모듈에서 처리하도록 변경 + // load-navbar.js, load-sidebar.js가 자동으로 처리함 + + // ✅ 콘텐츠만 직접 로딩 (admin-sections.html이 자동 로딩됨) + console.log('관리자 대시보드 초기화 완료'); +} + +// ✅ 보조 함수 - 필요시 수동 컴포넌트 로딩용 +async function loadComponent(id, url) { + try { + const res = await fetch(url); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + const html = await res.text(); + const element = document.getElementById(id); + if (element) { + element.innerHTML = html; + } else { + console.warn(`요소를 찾을 수 없습니다: ${id}`); + } + } catch (err) { + console.error(`컴포넌트 로딩 실패 (${url}):`, err); + } +} + +document.addEventListener('DOMContentLoaded', initDashboard); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/api-base.js b/deploy/tkfb-package/web-ui/js/api-base.js new file mode 100644 index 0000000..5da185a --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/api-base.js @@ -0,0 +1,97 @@ +// /js/api-base.js +// API 기본 설정 및 보안 유틸리티 (비모듈 - 빠른 로딩용) + +(function() { + 'use strict'; + + // ==================== 보안 유틸리티 (XSS 방지) ==================== + + /** + * HTML 특수문자 이스케이프 (XSS 방지) + * innerHTML에 사용자 입력/API 데이터를 삽입할 때 반드시 사용 + * + * @param {string} str - 이스케이프할 문자열 + * @returns {string} 이스케이프된 문자열 + */ + window.escapeHtml = function(str) { + if (str === null || str === undefined) return ''; + if (typeof str !== 'string') str = String(str); + + const htmlEntities = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`', + '=': '=' + }; + + return str.replace(/[&<>"'`=\/]/g, function(char) { + return htmlEntities[char]; + }); + }; + + /** + * URL 파라미터 이스케이프 + */ + window.escapeUrl = function(str) { + if (str === null || str === undefined) return ''; + return encodeURIComponent(String(str)); + }; + + // ==================== API 설정 ==================== + + const API_PORT = 20005; + const API_PATH = '/api'; + + function getApiBaseUrl() { + const hostname = window.location.hostname; + const protocol = window.location.protocol; + return `${protocol}//${hostname}:${API_PORT}${API_PATH}`; + } + + // 전역 API 설정 + const apiUrl = getApiBaseUrl(); + window.API_BASE_URL = apiUrl; + window.API = apiUrl; // 이전 호환성 + + // 인증 헤더 생성 + window.getAuthHeaders = function() { + const token = localStorage.getItem('token'); + return { + 'Content-Type': 'application/json', + 'Authorization': token ? `Bearer ${token}` : '' + }; + }; + + // API 호출 헬퍼 (기존 시그니처 유지: endpoint, method, data) + // JSON 파싱하여 반환 + window.apiCall = async function(endpoint, method = 'GET', data = null) { + const url = `${window.API_BASE_URL}${endpoint}`; + const config = { + method: method, + headers: window.getAuthHeaders() + }; + + if (data && (method === 'POST' || method === 'PUT' || method === 'PATCH' || method === 'DELETE')) { + config.body = JSON.stringify(data); + } + + const response = await fetch(url, config); + + // 401 Unauthorized 처리 + if (response.status === 401) { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + window.location.href = '/index.html'; + throw new Error('인증이 만료되었습니다.'); + } + + // JSON 파싱하여 반환 + return response.json(); + }; + + console.log('✅ API 설정 완료:', window.API_BASE_URL); +})(); diff --git a/deploy/tkfb-package/web-ui/js/api-config.js b/deploy/tkfb-package/web-ui/js/api-config.js new file mode 100644 index 0000000..a80acf1 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/api-config.js @@ -0,0 +1,249 @@ +// api-config.js - nginx 프록시 대응 API 설정 +import { config } from './config.js'; +import { redirectToLogin } from './navigation.js'; + +function getApiBaseUrl() { + const hostname = window.location.hostname; + const protocol = window.location.protocol; + const port = window.location.port; + + console.log('🌐 감지된 환경:', { hostname, protocol, port }); + + // 🔗 nginx 프록시를 통한 접근 (권장) + // nginx가 /api/ 요청을 백엔드로 프록시하므로 포트 없이 접근 + if (hostname.startsWith('192.168.') || hostname.startsWith('10.') || hostname.startsWith('172.') || + hostname === 'localhost' || hostname === '127.0.0.1' || + hostname.includes('.local') || hostname.includes('hyungi')) { + + // 현재 웹서버의 도메인/IP를 그대로 사용하되 API 포트(config.api.port)로 직접 연결 + const baseUrl = `${protocol}//${hostname}:${config.api.port}${config.api.path}`; + + console.log('✅ nginx 프록시 사용:', baseUrl); + return baseUrl; + } + + // 🚨 백업: 직접 접근 (nginx 프록시 실패시에만) + console.warn('⚠️ 직접 API 접근 (백업 모드)'); + return `${protocol}//${hostname}:${config.api.port}${config.api.path}`; +} + +// API 설정 +const API_URL = getApiBaseUrl(); + +// 전역 변수로 설정 +window.API = API_URL; +window.API_BASE_URL = API_URL; + +function ensureAuthenticated() { + const token = localStorage.getItem('token'); + if (!token || token === 'undefined' || token === 'null') { + console.log('🚨 인증되지 않은 사용자. 로그인 페이지로 이동합니다.'); + clearAuthData(); // 만약을 위해 한번 더 정리 + redirectToLogin(); + return false; // 이후 코드 실행 방지 + } + + // 토큰 만료 확인 + if (isTokenExpired(token)) { + console.log('🚨 토큰이 만료되었습니다. 로그인 페이지로 이동합니다.'); + clearAuthData(); + alert('세션이 만료되었습니다. 다시 로그인해주세요.'); + redirectToLogin(); + return false; + } + + return token; +} + +// 토큰 만료 확인 함수 +function isTokenExpired(token) { + try { + const payload = JSON.parse(atob(token.split('.')[1])); + const currentTime = Math.floor(Date.now() / 1000); + return payload.exp < currentTime; + } catch (error) { + console.error('토큰 파싱 오류:', error); + return true; // 파싱 실패 시 만료된 것으로 간주 + } +} + +// 인증 데이터 정리 함수 +function clearAuthData() { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + localStorage.removeItem('userInfo'); + localStorage.removeItem('currentUser'); +} + +function getAuthHeaders() { + const token = localStorage.getItem('token'); + return { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + }; +} + +// 🔧 개선된 API 호출 함수 (에러 처리 강화) +async function apiCall(url, method = 'GET', data = null) { + // 상대 경로를 절대 경로로 변환 + const fullUrl = url.startsWith('http') ? url : `${API}${url}`; + + const options = { + method: method, + headers: { + 'Content-Type': 'application/json', + ...getAuthHeaders() + } + }; + + // POST/PUT 요청시 데이터 추가 + if (data && (method === 'POST' || method === 'PUT' || method === 'PATCH')) { + options.body = JSON.stringify(data); + } + + try { + console.log(`📡 API 호출: ${fullUrl} (${method})`); + const response = await fetch(fullUrl, options); + + // 인증 만료 처리 + if (response.status === 401) { + console.error('🚨 인증 실패: 토큰이 만료되었거나 유효하지 않습니다.'); + clearAuthData(); + alert('세션이 만료되었습니다. 다시 로그인해주세요.'); + redirectToLogin(); + throw new Error('인증에 실패했습니다.'); + } + + // 응답 실패 처리 + if (!response.ok) { + let errorMessage = `HTTP ${response.status}`; + try { + const contentType = response.headers.get('content-type'); + + if (contentType && contentType.includes('application/json')) { + const errorData = await response.json(); + console.error('📋 서버 에러 상세:', errorData); + + // 에러 메시지 추출 (여러 형식 지원) + if (typeof errorData === 'string') { + errorMessage = errorData; + } else if (errorData.error) { + errorMessage = typeof errorData.error === 'string' + ? errorData.error + : JSON.stringify(errorData.error); + } else if (errorData.message) { + errorMessage = errorData.message; + } else if (errorData.details) { + errorMessage = errorData.details; + } else { + errorMessage = `HTTP ${response.status}: ${JSON.stringify(errorData)}`; + } + } else { + const errorText = await response.text(); + console.error('📋 서버 에러 텍스트:', errorText); + errorMessage = errorText || errorMessage; + } + } catch (e) { + console.error('📋 에러 파싱 중 예외 발생:', e.message); + // 파싱 실패해도 HTTP 상태 코드는 전달 + } + throw new Error(errorMessage); + } + + const result = await response.json(); + console.log(`✅ API 성공: ${fullUrl}`); + return result; + + } catch (error) { + console.error(`❌ API 오류 (${fullUrl}):`, error); + console.error('❌ 에러 전체 내용:', JSON.stringify(error, null, 2)); + + // 네트워크 오류 vs 서버 오류 구분 + if (error.name === 'TypeError' && error.message.includes('fetch')) { + throw new Error('네트워크 연결 오류입니다. 인터넷 연결을 확인해주세요.'); + } + + throw error; + } +} + +// 디버깅 정보 +console.log('🔗 API Base URL:', API); +console.log('🌐 Current Location:', { + hostname: window.location.hostname, + protocol: window.location.protocol, + port: window.location.port, + href: window.location.href +}); + +// 🧪 API 연결 테스트 함수 (개발용) +async function testApiConnection() { + try { + console.log('🧪 API 연결 테스트 시작...'); + const response = await fetch(`${API}/health`, { + method: 'GET', + headers: { 'Content-Type': 'application/json' } + }); + + if (response.ok) { + console.log('✅ API 연결 성공!'); + return true; + } else { + console.log('❌ API 연결 실패:', response.status); + return false; + } + } catch (error) { + console.log('❌ API 연결 오류:', error.message); + return false; + } +} + +// API 헬퍼 함수들 +async function apiGet(url) { + return apiCall(url, 'GET'); +} + +async function apiPost(url, data) { + return apiCall(url, 'POST', data); +} + +async function apiPut(url, data) { + return apiCall(url, 'PUT', data); +} + +async function apiDelete(url) { + return apiCall(url, 'DELETE'); +} + +// 전역 함수로 설정 +window.ensureAuthenticated = ensureAuthenticated; +window.getAuthHeaders = getAuthHeaders; +window.apiCall = apiCall; +window.apiGet = apiGet; +window.apiPost = apiPost; +window.apiPut = apiPut; +window.apiDelete = apiDelete; +window.testApiConnection = testApiConnection; +window.isTokenExpired = isTokenExpired; +window.clearAuthData = clearAuthData; + +// 개발 모드에서 자동 테스트 +if (window.location.hostname === 'localhost' || window.location.hostname.startsWith('192.168.')) { + setTimeout(() => { + testApiConnection(); + }, 1000); +} + +// 주기적으로 토큰 만료 확인 (5분마다) +setInterval(() => { + const token = localStorage.getItem('token'); + if (token && isTokenExpired(token)) { + console.log('🚨 주기적 확인: 토큰이 만료되었습니다.'); + clearAuthData(); + alert('세션이 만료되었습니다. 다시 로그인해주세요.'); + redirectToLogin(); + } +}, config.app.tokenRefreshInterval); // 5분마다 확인 + +// ES6 모듈 export +export { API_URL as API_BASE_URL, API_URL as API, apiCall, getAuthHeaders }; \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/api-helper.js b/deploy/tkfb-package/web-ui/js/api-helper.js new file mode 100644 index 0000000..d322e3f --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/api-helper.js @@ -0,0 +1,136 @@ +// /public/js/api-helper.js +// ES6 모듈 의존성 제거 - 브라우저 호환성 개선 + +// API 설정 (window 객체에서 가져오기) +const API_BASE_URL = window.API_BASE_URL || 'http://localhost:20005/api'; + +// 인증 관련 함수들 (직접 구현) +function getToken() { + const token = localStorage.getItem('token'); + return token && token !== 'undefined' && token !== 'null' ? token : null; +} + +function clearAuthData() { + localStorage.removeItem('token'); + localStorage.removeItem('user'); +} + +/** + * 로그인 API를 호출합니다. (인증이 필요 없는 public 요청) + * @param {string} username - 사용자 아이디 + * @param {string} password - 사용자 비밀번호 + * @returns {Promise} - API 응답 결과 + */ +async function login(username, password) { + const response = await fetch(`${API_BASE_URL}/auth/login`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ username, password }), + }); + + const result = await response.json(); + if (!response.ok) { + // API 에러 응답을 그대로 에러 객체로 던져서 호출부에서 처리하도록 함 + throw new Error(result.error || '로그인에 실패했습니다.'); + } + return result; +} + + +/** + * 인증이 필요한 API 요청을 위한 fetch 래퍼 함수 + * @param {string} endpoint - /로 시작하는 API 엔드포인트 + * @param {object} options - fetch 함수에 전달할 옵션 + * @returns {Promise} - fetch 응답 객체 + */ +async function authFetch(endpoint, options = {}) { + const token = getToken(); + + if (!token) { + console.error('토큰이 없습니다. 로그인이 필요합니다.'); + clearAuthData(); // 인증 정보 정리 + window.location.href = '/index.html'; // 로그인 페이지로 리디렉션 + // 에러를 던져서 후속 실행을 중단 + throw new Error('인증 토큰이 없습니다.'); + } + + const defaultHeaders = { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }; + + const response = await fetch(`${API_BASE_URL}${endpoint}`, { + ...options, + headers: { + ...defaultHeaders, + ...options.headers + } + }); + + // 401 Unauthorized 에러 발생 시, 토큰이 유효하지 않다는 의미 + if (response.status === 401) { + console.error('인증 실패. 토큰이 만료되었거나 유효하지 않습니다.'); + clearAuthData(); // 만료된 인증 정보 정리 + window.location.href = '/index.html'; + throw new Error('인증에 실패했습니다.'); + } + + return response; +} + +// 공통 API 요청 함수들 + +/** + * GET 요청 헬퍼 + * @param {string} endpoint - API 엔드포인트 + */ +async function apiGet(endpoint) { + const response = await authFetch(endpoint); + return response.json(); +} + +/** + * POST 요청 헬퍼 + * @param {string} endpoint - API 엔드포인트 + * @param {object} data - 전송할 데이터 + */ +async function apiPost(endpoint, data) { + const response = await authFetch(endpoint, { + method: 'POST', + body: JSON.stringify(data) + }); + return response.json(); +} + +/** + * PUT 요청 헬퍼 + * @param {string} endpoint - API 엔드포인트 + * @param {object} data - 전송할 데이터 + */ +async function apiPut(endpoint, data) { + const response = await authFetch(endpoint, { + method: 'PUT', + body: JSON.stringify(data) + }); + return response.json(); +} + +/** + * DELETE 요청 헬퍼 + * @param {string} endpoint - API 엔드포인트 + */ +async function apiDelete(endpoint) { + const response = await authFetch(endpoint, { + method: 'DELETE' + }); + return response.json(); +} + +// 전역 함수로 설정 +window.login = login; +window.apiGet = apiGet; +window.apiPost = apiPost; +window.apiPut = apiPut; +window.apiDelete = apiDelete; +window.getToken = getToken; +window.clearAuthData = clearAuthData; \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/app-init.js b/deploy/tkfb-package/web-ui/js/app-init.js new file mode 100644 index 0000000..9bd6d56 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/app-init.js @@ -0,0 +1,587 @@ +// /js/app-init.js +// 앱 초기화 - 인증, 네비바, 사이드바를 한 번에 로드 +// 모든 페이지에서 이 하나의 스크립트만 로드하면 됨 + +(function() { + 'use strict'; + + // ===== 캐시 설정 ===== + const CACHE_DURATION = 10 * 60 * 1000; // 10분 + const COMPONENT_CACHE_PREFIX = 'component_v3_'; + + // ===== 인증 함수 ===== + function isLoggedIn() { + const token = localStorage.getItem('token'); + return token && token !== 'undefined' && token !== 'null'; + } + + function getUser() { + const user = localStorage.getItem('user'); + return user ? JSON.parse(user) : null; + } + + function clearAuthData() { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + localStorage.removeItem('userPageAccess'); + } + + // ===== 페이지 권한 캐시 ===== + let pageAccessPromise = null; + + async function getPageAccess(currentUser) { + if (!currentUser || !currentUser.user_id) return null; + + // 캐시 확인 + const cached = localStorage.getItem('userPageAccess'); + if (cached) { + try { + const cacheData = JSON.parse(cached); + if (Date.now() - cacheData.timestamp < CACHE_DURATION) { + return cacheData.pages; + } + } catch (e) { + localStorage.removeItem('userPageAccess'); + } + } + + // 이미 로딩 중이면 기존 Promise 반환 + if (pageAccessPromise) return pageAccessPromise; + + // 새로운 API 호출 + pageAccessPromise = (async () => { + try { + const response = await fetch(`${window.API_BASE_URL}/users/${currentUser.user_id}/page-access`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + } + }); + + if (!response.ok) return null; + + const data = await response.json(); + const pages = data.data.pageAccess || []; + + localStorage.setItem('userPageAccess', JSON.stringify({ + pages: pages, + timestamp: Date.now() + })); + + return pages; + } catch (error) { + console.error('페이지 권한 조회 오류:', error); + return null; + } finally { + pageAccessPromise = null; + } + })(); + + return pageAccessPromise; + } + + async function getAccessiblePageKeys(currentUser) { + const pages = await getPageAccess(currentUser); + if (!pages) return []; + return pages.filter(p => p.can_access === 1).map(p => p.page_key); + } + + // ===== 현재 페이지 키 추출 ===== + function getCurrentPageKey() { + const path = window.location.pathname; + if (!path.startsWith('/pages/')) return null; + const pagePath = path.substring(7).replace('.html', ''); + return pagePath.replace(/\//g, '.'); + } + + // ===== 컴포넌트 로더 ===== + async function loadComponent(name, selector, processor) { + const container = document.querySelector(selector); + if (!container) return; + + const paths = { + 'navbar': '/components/navbar.html', + 'sidebar-nav': '/components/sidebar-nav.html' + }; + + const componentPath = paths[name]; + if (!componentPath) return; + + try { + const cacheKey = COMPONENT_CACHE_PREFIX + name; + let html = sessionStorage.getItem(cacheKey); + + if (!html) { + const response = await fetch(componentPath); + if (!response.ok) throw new Error('컴포넌트 로드 실패'); + html = await response.text(); + try { sessionStorage.setItem(cacheKey, html); } catch (e) {} + } + + if (processor) { + const parser = new DOMParser(); + const doc = parser.parseFromString(html, 'text/html'); + await processor(doc); + container.innerHTML = doc.body.innerHTML; + } else { + container.innerHTML = html; + } + } catch (error) { + console.error(`컴포넌트 로드 오류 (${name}):`, error); + } + } + + // ===== 네비바 처리 ===== + const ROLE_NAMES = { + 'system admin': '시스템 관리자', + 'admin': '관리자', + 'leader': '그룹장', + 'user': '작업자', + 'support': '지원팀', + 'default': '사용자' + }; + + async function processNavbar(doc, currentUser, accessiblePageKeys) { + const userRole = (currentUser.role || '').toLowerCase(); + const isAdmin = userRole === 'admin' || userRole === 'system admin'; + + if (isAdmin) { + doc.querySelectorAll('.admin-only').forEach(el => el.classList.add('visible')); + } else { + doc.querySelectorAll('[data-page-key]').forEach(item => { + const pageKey = item.getAttribute('data-page-key'); + if (pageKey === 'dashboard' || pageKey.startsWith('profile.')) return; + if (!accessiblePageKeys.includes(pageKey)) item.remove(); + }); + doc.querySelectorAll('.admin-only').forEach(el => el.remove()); + } + + // 사용자 정보 표시 + const displayName = currentUser.name || currentUser.username; + const roleName = ROLE_NAMES[userRole] || ROLE_NAMES.default; + + const setElementText = (id, text) => { + const el = doc.getElementById(id); + if (el) el.textContent = text; + }; + + setElementText('userName', displayName); + setElementText('userRole', roleName); + setElementText('userInitial', displayName.charAt(0)); + } + + // ===== 사이드바 처리 ===== + async function processSidebar(doc, currentUser, accessiblePageKeys) { + const userRole = (currentUser.role || '').toLowerCase(); + const accessLevel = (currentUser.access_level || '').toLowerCase(); + // role 또는 access_level로 관리자 확인 + const isAdmin = userRole === 'admin' || userRole === 'system admin' || userRole === 'system' || + accessLevel === 'admin' || accessLevel === 'system'; + + if (isAdmin) { + doc.querySelectorAll('.admin-only').forEach(el => el.classList.add('visible')); + } else { + doc.querySelectorAll('[data-page-key]').forEach(item => { + const pageKey = item.getAttribute('data-page-key'); + if (pageKey === 'dashboard' || pageKey.startsWith('profile.')) return; + if (!accessiblePageKeys.includes(pageKey)) item.style.display = 'none'; + }); + doc.querySelectorAll('.nav-category.admin-only').forEach(el => el.remove()); + } + + // 현재 페이지 하이라이트 + const currentPath = window.location.pathname; + doc.querySelectorAll('.nav-item').forEach(item => { + const href = item.getAttribute('href'); + if (href && currentPath.includes(href.replace(/^\//, ''))) { + item.classList.add('active'); + const category = item.closest('.nav-category'); + if (category) category.classList.add('expanded'); + } + }); + + // 저장된 상태 복원 (기본값: 접힌 상태) + const isCollapsed = localStorage.getItem('sidebarCollapsed') !== 'false'; + const sidebar = doc.querySelector('.sidebar-nav'); + if (isCollapsed && sidebar) { + sidebar.classList.add('collapsed'); + document.body.classList.add('sidebar-collapsed'); + } + + const expandedCategories = JSON.parse(localStorage.getItem('sidebarExpanded') || '[]'); + expandedCategories.forEach(category => { + const el = doc.querySelector(`[data-category="${category}"]`); + if (el) el.classList.add('expanded'); + }); + } + + // ===== 사이드바 이벤트 설정 ===== + function setupSidebarEvents() { + const sidebar = document.getElementById('sidebarNav'); + const toggle = document.getElementById('sidebarToggle'); + if (!sidebar || !toggle) return; + + toggle.addEventListener('click', () => { + sidebar.classList.toggle('collapsed'); + document.body.classList.toggle('sidebar-collapsed'); + localStorage.setItem('sidebarCollapsed', sidebar.classList.contains('collapsed')); + }); + + sidebar.querySelectorAll('.nav-category-header').forEach(header => { + header.addEventListener('click', () => { + const category = header.closest('.nav-category'); + category.classList.toggle('expanded'); + + const expanded = []; + sidebar.querySelectorAll('.nav-category.expanded').forEach(cat => { + const name = cat.getAttribute('data-category'); + if (name) expanded.push(name); + }); + localStorage.setItem('sidebarExpanded', JSON.stringify(expanded)); + }); + }); + } + + // ===== 네비바 이벤트 설정 ===== + function setupNavbarEvents() { + const logoutButton = document.getElementById('logoutBtn'); + if (logoutButton) { + logoutButton.addEventListener('click', () => { + if (confirm('로그아웃 하시겠습니까?')) { + clearAuthData(); + window.location.href = '/index.html'; + } + }); + } + + // 알림 버튼 이벤트 + const notificationBtn = document.getElementById('notificationBtn'); + const notificationDropdown = document.getElementById('notificationDropdown'); + const notificationWrapper = document.getElementById('notificationWrapper'); + + if (notificationBtn && notificationDropdown) { + notificationBtn.addEventListener('click', (e) => { + e.stopPropagation(); + notificationDropdown.classList.toggle('show'); + }); + + document.addEventListener('click', (e) => { + if (notificationWrapper && !notificationWrapper.contains(e.target)) { + notificationDropdown.classList.remove('show'); + } + }); + } + } + + // ===== 알림 로드 ===== + async function loadNotifications() { + try { + const token = localStorage.getItem('token'); + if (!token) return; + + const response = await fetch(`${window.API_BASE_URL}/notifications/unread`, { + headers: { 'Authorization': `Bearer ${token}` } + }); + if (!response.ok) return; + + const result = await response.json(); + if (result.success) { + const notifications = result.data || []; + updateNotificationBadge(notifications.length); + renderNotificationList(notifications); + } + } catch (error) { + console.warn('알림 로드 오류:', error.message); + } + } + + function updateNotificationBadge(count) { + const badge = document.getElementById('notificationBadge'); + const btn = document.getElementById('notificationBtn'); + if (!badge) return; + + if (count > 0) { + badge.textContent = count > 99 ? '99+' : count; + badge.style.display = 'flex'; + btn?.classList.add('has-notifications'); + } else { + badge.style.display = 'none'; + btn?.classList.remove('has-notifications'); + } + } + + function renderNotificationList(notifications) { + const list = document.getElementById('notificationList'); + if (!list) return; + + if (notifications.length === 0) { + list.innerHTML = '
새 알림이 없습니다.
'; + return; + } + + const icons = { repair: '🔧', safety: '⚠️', system: '📢', equipment: '🔩', maintenance: '🛠️' }; + + list.innerHTML = notifications.slice(0, 5).map(n => ` +
+
${icons[n.type] || '🔔'}
+
+
${escapeHtml(n.title)}
+
${escapeHtml(n.message || '')}
+
+
${formatTimeAgo(n.created_at)}
+
+ `).join(''); + + list.querySelectorAll('.notification-item').forEach(item => { + item.addEventListener('click', () => { + const url = item.dataset.url; + // 수리 알림은 클릭해도 읽음 처리 안함 (수리 처리 페이지에서 확인 처리해야 함) + window.location.href = url || '/pages/admin/notifications.html'; + }); + }); + } + + function formatTimeAgo(dateString) { + const date = new Date(dateString); + const now = new Date(); + const diffMs = now - date; + const diffMins = Math.floor(diffMs / 60000); + const diffHours = Math.floor(diffMs / 3600000); + const diffDays = Math.floor(diffMs / 86400000); + + if (diffMins < 1) return '방금 전'; + if (diffMins < 60) return `${diffMins}분 전`; + if (diffHours < 24) return `${diffHours}시간 전`; + if (diffDays < 7) return `${diffDays}일 전`; + return date.toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' }); + } + + function escapeHtml(text) { + if (!text) return ''; + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } + + // ===== 날짜/시간 업데이트 ===== + function updateDateTime() { + const now = new Date(); + const timeEl = document.getElementById('timeValue'); + if (timeEl) { + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + timeEl.textContent = `${hours}시 ${minutes}분 ${seconds}초`; + } + + const dateEl = document.getElementById('dateValue'); + if (dateEl) { + const days = ['일', '월', '화', '수', '목', '토']; + dateEl.textContent = `${now.getMonth() + 1}월 ${now.getDate()}일 (${days[now.getDay()]})`; + } + } + + // ===== 날씨 업데이트 ===== + const WEATHER_ICONS = { clear: '☀️', rain: '🌧️', snow: '❄️', heat: '🔥', cold: '🥶', wind: '💨', fog: '🌫️', dust: '😷', cloudy: '⛅', overcast: '☁️' }; + const WEATHER_NAMES = { clear: '맑음', rain: '비', snow: '눈', heat: '폭염', cold: '한파', wind: '강풍', fog: '안개', dust: '미세먼지', cloudy: '구름많음', overcast: '흐림' }; + + async function updateWeather() { + try { + const token = localStorage.getItem('token'); + if (!token) return; + + // 캐시 확인 + const cached = sessionStorage.getItem('weatherCache'); + let result; + if (cached) { + const cacheData = JSON.parse(cached); + if (Date.now() - cacheData.timestamp < 5 * 60 * 1000) { + result = cacheData.data; + } + } + + if (!result) { + const response = await fetch(`${window.API_BASE_URL}/tbm/weather/current`, { + headers: { 'Authorization': `Bearer ${token}` } + }); + if (!response.ok) return; + result = await response.json(); + sessionStorage.setItem('weatherCache', JSON.stringify({ data: result, timestamp: Date.now() })); + } + + if (result.success && result.data) { + const { temperature, conditions } = result.data; + const tempEl = document.getElementById('weatherTemp'); + if (tempEl && temperature != null) tempEl.textContent = `${Math.round(temperature)}°C`; + + const iconEl = document.getElementById('weatherIcon'); + const descEl = document.getElementById('weatherDesc'); + if (conditions && conditions.length > 0) { + const primary = conditions[0]; + if (iconEl) iconEl.textContent = WEATHER_ICONS[primary] || '🌤️'; + if (descEl) descEl.textContent = WEATHER_NAMES[primary] || '맑음'; + } + } + } catch (error) { + console.warn('날씨 정보 로드 실패'); + } + } + + // ===== 메인 초기화 ===== + async function init() { + console.log('🚀 app-init 시작'); + + // 1. 인증 확인 + if (!isLoggedIn()) { + clearAuthData(); + window.location.href = '/index.html'; + return; + } + + const currentUser = getUser(); + if (!currentUser || !currentUser.username) { + clearAuthData(); + window.location.href = '/index.html'; + return; + } + + console.log('✅ 인증 확인:', currentUser.username); + + const userRole = (currentUser.role || '').toLowerCase(); + const accessLevel = (currentUser.access_level || '').toLowerCase(); + // role 또는 access_level로 관리자 확인 + const isAdmin = userRole === 'admin' || userRole === 'system admin' || userRole === 'system' || + accessLevel === 'admin' || accessLevel === 'system'; + + // 2. 페이지 접근 권한 체크 (Admin은 건너뛰기) + let accessiblePageKeys = []; + if (!isAdmin) { + const pageKey = getCurrentPageKey(); + if (pageKey && pageKey !== 'dashboard' && !pageKey.startsWith('profile.')) { + accessiblePageKeys = await getAccessiblePageKeys(currentUser); + if (!accessiblePageKeys.includes(pageKey)) { + alert('이 페이지에 접근할 권한이 없습니다.'); + window.location.href = '/pages/dashboard.html'; + return; + } + } + } + + // 3. 사이드바 컨테이너 생성 (없으면) + let sidebarContainer = document.getElementById('sidebar-container'); + if (!sidebarContainer) { + sidebarContainer = document.createElement('div'); + sidebarContainer.id = 'sidebar-container'; + document.body.prepend(sidebarContainer); + console.log('📦 사이드바 컨테이너 생성됨'); + } + + // 4. 네비바와 사이드바 동시 로드 + console.log('📥 컴포넌트 로딩 시작'); + await Promise.all([ + loadComponent('navbar', '#navbar-container', (doc) => processNavbar(doc, currentUser, accessiblePageKeys)), + loadComponent('sidebar-nav', '#sidebar-container', (doc) => processSidebar(doc, currentUser, accessiblePageKeys)) + ]); + console.log('✅ 컴포넌트 로딩 완료'); + + // 5. 이벤트 설정 + setupNavbarEvents(); + setupSidebarEvents(); + document.body.classList.add('has-sidebar'); + + // 6. 페이지 전환 로딩 인디케이터 설정 + setupPageTransitionLoader(); + + // 7. 날짜/시간 (비동기) + updateDateTime(); + setInterval(updateDateTime, 1000); + + // 8. 날씨 (백그라운드) + setTimeout(updateWeather, 100); + + // 9. 알림 로드 (30초마다 갱신) + setTimeout(loadNotifications, 200); + setInterval(loadNotifications, 30000); + + console.log('✅ app-init 완료'); + } + + // ===== 페이지 전환 로딩 인디케이터 ===== + function setupPageTransitionLoader() { + // 로딩 바 스타일 추가 + const style = document.createElement('style'); + style.textContent = ` + #page-loader { + position: fixed; + top: 0; + left: 0; + width: 0; + height: 3px; + background: linear-gradient(90deg, #3b82f6, #60a5fa); + z-index: 99999; + transition: width 0.3s ease; + box-shadow: 0 0 10px rgba(59, 130, 246, 0.5); + } + #page-loader.loading { + width: 70%; + } + #page-loader.done { + width: 100%; + opacity: 0; + transition: width 0.2s ease, opacity 0.3s ease 0.2s; + } + body.page-loading { + cursor: wait; + } + body.page-loading * { + pointer-events: none; + } + `; + document.head.appendChild(style); + + // 로딩 바 엘리먼트 생성 + const loader = document.createElement('div'); + loader.id = 'page-loader'; + document.body.appendChild(loader); + + // 모든 내부 링크에 클릭 이벤트 추가 + document.addEventListener('click', (e) => { + const link = e.target.closest('a'); + if (!link) return; + + const href = link.getAttribute('href'); + if (!href) return; + + // 외부 링크, 해시 링크, javascript: 링크 제외 + if (href.startsWith('http') || href.startsWith('#') || href.startsWith('javascript:')) return; + + // 새 탭 링크 제외 + if (link.target === '_blank') return; + + // 로딩 시작 + loader.classList.remove('done'); + loader.classList.add('loading'); + document.body.classList.add('page-loading'); + }); + + // 페이지 떠날 때 완료 표시 + window.addEventListener('beforeunload', () => { + const loader = document.getElementById('page-loader'); + if (loader) { + loader.classList.remove('loading'); + loader.classList.add('done'); + } + }); + } + + // DOMContentLoaded 시 실행 + if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', init); + } else { + init(); + } + + // 전역 노출 (필요시) + window.appInit = { getUser, clearAuthData, isLoggedIn }; +})(); diff --git a/deploy/tkfb-package/web-ui/js/attendance-validation.js b/deploy/tkfb-package/web-ui/js/attendance-validation.js new file mode 100644 index 0000000..2eb16e1 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/attendance-validation.js @@ -0,0 +1,1038 @@ +// 근태 검증 관리 시스템 - API 통합 개선판 + +// ======================================== +// API 설정 및 인증 (통합 방식) +// ======================================== +import { API, getAuthHeaders, apiCall } from '/js/api-config.js'; + +// ======================================== +// 전역 변수 및 설정 +// ======================================== + +let currentDate = new Date(); +let selectedDate = null; +let selectedDateWorkers = []; +let currentFilter = 'all'; +let editingWorker = null; + +// Rate Limiting 설정 - 더욱 엄격하게 +const RATE_LIMIT = { + maxConcurrent: 1, // 동시 최대 1개 요청만! + delayBetweenRequests: 2000, // 요청 간 2초 딜레이 + retryDelay: 5000, // 429 에러 시 5초 후 재시도 + maxRetries: 1 // 최대 1번만 재시도 +}; + +// 캐시 및 상태 관리 +let dateStatusCache = new Map(); +let requestQueue = []; +let activeRequests = 0; +let isProcessingQueue = false; + +// ======================================== +// 캐시 및 성능 관리 유틸리티 +// ======================================== + +/** + * 캐시 상태 확인 + */ +function getCacheStatus() { + return { + cachedDates: dateStatusCache.size, + activeRequests: activeRequests, + queuedRequests: requestQueue.length, + isProcessingQueue: isProcessingQueue + }; +} + +/** + * 캐시 클리어 + */ +function clearCache() { + dateStatusCache.clear(); + console.log('📦 캐시가 클리어되었습니다.'); +} + +/** + * 성능 상태 UI 업데이트 + */ +function updatePerformanceUI() { + const status = getCacheStatus(); + const performanceEl = document.getElementById('performanceStatus'); + + if (performanceEl) { + document.getElementById('activeReq').textContent = status.activeRequests; + document.getElementById('cacheCount').textContent = status.cachedDates; + document.getElementById('queueCount').textContent = status.queuedRequests; + + // 개발 환경에서만 표시 + if (window.location.hostname === 'localhost' || window.location.hostname.includes('dev')) { + performanceEl.classList.remove('hidden'); + } + } +} + +/** + * 성능 모니터링 (디버그용) + */ +function logPerformanceStatus() { + const status = getCacheStatus(); + console.log('📊 성능 상태:', status); + updatePerformanceUI(); +} + +// 개발 모드에서 성능 모니터링 (2초마다) +if (window.location.hostname === 'localhost' || window.location.hostname.includes('dev')) { + setInterval(logPerformanceStatus, 2000); +} + +// ======================================== +// 유틸리티 함수들 +// ======================================== + +/** + * 한국 시간 기준 날짜 문자열 반환 + */ +function getKoreaDateString(date = new Date()) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +/** + * 현재 로그인한 사용자 정보 가져오기 + */ +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + + try { + const userInfo = localStorage.getItem('user') || localStorage.getItem('userInfo'); + if (userInfo) { + return JSON.parse(userInfo); + } + } catch (error) { + console.log('localStorage에서 사용자 정보 가져오기 실패:', error); + } + + return null; +} + +// ======================================== +// Rate Limiting 및 Queue 시스템 +// ======================================== + +/** + * Rate Limited API 호출을 위한 Queue 처리 + */ +async function processRequestQueue() { + if (isProcessingQueue || requestQueue.length === 0) return; + + isProcessingQueue = true; + + while (requestQueue.length > 0 && activeRequests < RATE_LIMIT.maxConcurrent) { + const { resolve, reject, url, options, retryCount } = requestQueue.shift(); + activeRequests++; + + try { + const result = await makeRateLimitedRequest(url, options, retryCount); + resolve(result); + } catch (error) { + reject(error); + } finally { + activeRequests--; + updatePerformanceUI(); // UI 업데이트 + // 요청 간 딜레이 + if (requestQueue.length > 0) { + await new Promise(resolve => setTimeout(resolve, RATE_LIMIT.delayBetweenRequests)); + } + } + } + + isProcessingQueue = false; + + // 큐에 남은 요청이 있으면 다시 처리 + if (requestQueue.length > 0) { + setTimeout(processRequestQueue, RATE_LIMIT.delayBetweenRequests); + } +} + +/** + * Rate Limiting이 적용된 실제 API 호출 + */ +async function makeRateLimitedRequest(url, options = {}, retryCount = 0) { + const defaultOptions = { + headers: getAuthHeaders() + }; + + const finalOptions = { + ...defaultOptions, + ...options, + headers: { + ...defaultOptions.headers, + ...options.headers + } + }; + + try { + const response = await fetch(url, finalOptions); + + if (response.status === 401) { + showMessage('인증이 만료되었습니다. 다시 로그인해주세요.', 'error'); + localStorage.removeItem('token'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + if (response.status === 429) { + // Rate Limit 에러 처리 + if (retryCount < RATE_LIMIT.maxRetries) { + console.log(`Rate limit 도달, ${RATE_LIMIT.retryDelay}ms 후 재시도 (${retryCount + 1}/${RATE_LIMIT.maxRetries})`); + await new Promise(resolve => setTimeout(resolve, RATE_LIMIT.retryDelay * (retryCount + 1))); + return makeRateLimitedRequest(url, options, retryCount + 1); + } else { + throw new Error('Rate limit exceeded - 요청이 너무 많습니다. 잠시 후 다시 시도해주세요.'); + } + } + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})); + throw new Error(errorData.error || errorData.message || `HTTP ${response.status}`); + } + + return await response.json(); + } catch (error) { + console.error('API 호출 오류:', error); + throw error; + } +} + +/** + * API 호출 헬퍼 (Queue 시스템 사용) - 통합 apiCall 대신 사용 + */ +async function queuedApiCall(url, options = {}) { + return new Promise((resolve, reject) => { + requestQueue.push({ + resolve, + reject, + url, + options, + retryCount: 0 + }); + updatePerformanceUI(); // UI 업데이트 + processRequestQueue(); + }); +} + +// ======================================== +// 메시지 및 UI 헬퍼 함수들 +// ======================================== + +/** + * 메시지 표시 + */ +function showMessage(message, type = 'info') { + const container = document.getElementById('message-container'); + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => { + hideMessage(); + }, 5000); + } +} + +function hideMessage() { + document.getElementById('message-container').innerHTML = ''; +} + +/** + * 로딩 상태 표시 + */ +function showLoadingState() { + const workersList = document.getElementById('workersList'); + workersList.innerHTML = ` +
+
+
+ 작업자 데이터를 불러오는 중... +
+
+ `; +} + +/** + * 오류 상태 표시 + */ +function showErrorState(message = '데이터를 불러오는 중 오류가 발생했습니다.') { + const workersList = document.getElementById('workersList'); + workersList.innerHTML = ` +
+
⚠️
+

데이터 로딩 오류

+

${message}

+
+ `; +} + +// ======================================== +// API 호출 함수들 (통합 설정 사용) +// ======================================== + +/** + * 특정 날짜의 작업 보고서를 가져옵니다 + */ +async function fetchWorkReports(date) { + try { + return await queuedApiCall(`${API}/workreports/date/${date}`); + } catch (error) { + console.error('WorkReports API 호출 실패:', error); + return []; + } +} + +/** + * 특정 날짜의 일일 작업 보고서를 가져옵니다 + */ +async function fetchDailyWorkReports(date) { + try { + return await queuedApiCall(`${API}/daily-work-reports/date/${date}`); + } catch (error) { + console.error('DailyWorkReports API 호출 실패:', error); + return []; + } +} + +/** + * 특정 작업자의 근무시간을 수정합니다 + */ +async function updateWorkerHours(workerId, date, newHours, reason = '') { + try { + const data = { + worker_id: workerId, + report_date: date, + work_hours: parseFloat(newHours), + modification_reason: reason, + modified_by: getCurrentUser()?.user_id || getCurrentUser()?.id + }; + + return await queuedApiCall(`${API}/daily-work-reports/update-hours`, { + method: 'PUT', + body: JSON.stringify(data) + }); + } catch (error) { + console.error('작업자 시간 수정 실패:', error); + throw error; + } +} + +/** + * 특정 작업자의 작업 데이터를 삭제합니다 + */ +async function deleteWorkerReport(workerId, date) { + try { + return await queuedApiCall(`${API}/daily-work-reports/worker/${workerId}/date/${date}`, { + method: 'DELETE' + }); + } catch (error) { + console.error('작업자 데이터 삭제 실패:', error); + throw error; + } +} + +// ======================================== +// 계산 및 검증 함수들 +// ======================================== + +/** + * 상태에 따른 예상 근무시간을 계산합니다 + */ +function calculateExpectedHours(status, overtime_hours = 0) { + const baseHours = { + 'normal': 8, // 정상 출근 + 'half_day': 4, // 반차 + 'early_leave': 4, // 조퇴 + 'quarter_day': 2, // 1/4 휴가 + 'vacation': 0, // 휴가 + 'sick_leave': 0 // 병가 + }; + return (baseHours[status] || 8) + (overtime_hours || 0); +} + +/** + * 작업자의 검증 상태를 계산합니다 + */ +function getValidationStatus(worker) { + if (!worker.hasWorkReport || !worker.hasDailyReport) return 'missing'; + if (Math.abs(worker.difference) > 0) return 'needs-review'; + return 'normal'; +} + +/** + * 특정 날짜의 전체 상태를 계산합니다 (순차 호출) + */ +async function calculateDateStatus(dateStr) { + // 캐시 확인 + if (dateStatusCache.has(dateStr)) { + return dateStatusCache.get(dateStr); + } + + try { + console.log(`📊 ${dateStr} 상태 계산 시작 - 순차 호출`); + + // 1단계: WorkReports 먼저 가져오기 + console.log(`📝 1단계: WorkReports 조회 중...`); + const workReports = await fetchWorkReports(dateStr); + + // 2초 대기 (서버 부하 방지) + console.log(`⏳ 2초 대기 중... (서버 부하 방지)`); + await new Promise(resolve => setTimeout(resolve, 2000)); + + // 2단계: DailyWorkReports 가져오기 + console.log(`📊 2단계: DailyWorkReports 조회 중...`); + const dailyReports = await fetchDailyWorkReports(dateStr); + + let status; + if (workReports.length === 0 && dailyReports.length === 0) { + status = 'no-data'; + } else if (workReports.length === 0 || dailyReports.length === 0) { + status = 'missing'; + } else { + const hasDiscrepancy = workReports.some(wr => { + const dr = dailyReports.find(d => d.worker_id === wr.worker_id); + if (!dr) return true; + + const expected = calculateExpectedHours(wr.status, wr.overtime_hours); + return Math.abs(dr.work_hours - expected) > 0; + }); + status = hasDiscrepancy ? 'needs-review' : 'normal'; + } + + // 캐시에 저장 + dateStatusCache.set(dateStr, status); + console.log(`✅ ${dateStr} 상태 계산 완료: ${status}`); + return status; + } catch (error) { + console.error('날짜 상태 계산 오류:', error); + // 에러 시 캐시하지 않고 기본값 반환 + return 'no-data'; + } +} + +// ======================================== +// 캘린더 관련 함수들 +// ======================================== + +/** + * 현재 월의 캘린더 데이터를 생성합니다 (온디맨드 로딩) + */ +function generateCalendarStructure() { + const year = currentDate.getFullYear(); + const month = currentDate.getMonth(); + const firstDay = new Date(year, month, 1); + const startDate = new Date(firstDay); + startDate.setDate(startDate.getDate() - firstDay.getDay()); + + const calendar = []; + const current = new Date(startDate); + + for (let week = 0; week < 6; week++) { + const weekDays = []; + for (let day = 0; day < 7; day++) { + const dateStr = getKoreaDateString(current); + const isCurrentMonth = current.getMonth() === month; + + weekDays.push({ + date: new Date(current), + dateStr, + isCurrentMonth, + status: 'no-data' // 모든 날짜를 no-data로 시작 + }); + current.setDate(current.getDate() + 1); + } + calendar.push(weekDays); + } + + return calendar; +} + +/** + * 캘린더를 화면에 렌더링합니다 (자동 로딩 없음) + */ +async function renderCalendar() { + try { + showMessage('📅 캘린더를 표시합니다. 날짜를 클릭하면 순차적으로 상태를 확인할 수 있습니다.', 'success'); + + // 캘린더 구조만 렌더링 (API 호출 없음) + const calendar = generateCalendarStructure(); + const calendarGrid = document.getElementById('calendarGrid'); + calendarGrid.innerHTML = ''; + + // 캘린더 날짜들을 생성 (상태 로딩 없음) + calendar.flat().forEach((dateInfo) => { + const button = document.createElement('button'); + button.className = ` + calendar-day + ${dateInfo.isCurrentMonth ? 'text-gray-900 hover-enabled' : 'text-gray-400'} + ${selectedDate === dateInfo.dateStr ? 'selected' : ''} + no-data + `; + + button.innerHTML = ` +
+ ${dateInfo.date.getDate()} + ${dateInfo.isCurrentMonth ? + `
` : '' + } +
+ `; + + // 현재 월의 날짜만 클릭 가능 + if (dateInfo.isCurrentMonth) { + button.addEventListener('click', () => handleDateClick(dateInfo)); + button.title = `${dateInfo.dateStr} - 클릭하여 상태 확인`; + } else { + button.disabled = true; + button.style.cursor = 'not-allowed'; + } + + calendarGrid.appendChild(button); + }); + + // 월/년 표시 업데이트 + const monthNames = ['1월', '2월', '3월', '4월', '5월', '6월', '7월', '8월', '9월', '10월', '11월', '12월']; + document.getElementById('currentMonthYear').textContent = + `${currentDate.getFullYear()}년 ${monthNames[currentDate.getMonth()]}`; + + // 월간 요약 정보 초기화 + document.getElementById('normalCount').textContent = '?'; + document.getElementById('reviewCount').textContent = '?'; + document.getElementById('missingCount').textContent = '?'; + + hideMessage(); + + } catch (error) { + console.error('캘린더 렌더링 오류:', error); + showMessage('캘린더 로딩 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 특정 날짜의 상태만 로드하고 업데이트합니다 (순차 호출) + */ +async function loadAndUpdateDateStatus(dateStr, buttonElement) { + try { + // 로딩 상태 표시 + buttonElement.classList.add('loading-state'); + const statusDot = buttonElement.querySelector('.status-dot'); + if (statusDot) { + statusDot.style.background = '#3b82f6'; + statusDot.style.opacity = '1'; + statusDot.classList.add('pulse'); + } + + // 진행 상황 표시 + buttonElement.title = '1단계: WorkReports 조회 중...'; + + const status = await calculateDateStatus(dateStr); + + // 버튼 스타일 업데이트 + buttonElement.classList.remove('loading-state', 'no-data'); + buttonElement.classList.add(status); + buttonElement.title = `${dateStr} - 상태: ${status}`; + + // 상태 점 업데이트 + if (statusDot && status !== 'no-data') { + statusDot.classList.remove('pulse'); + statusDot.className = `status-dot ${ + status === 'needs-review' ? 'warning' : + status === 'missing' ? 'error' : + status === 'normal' ? 'normal' : '' + }`; + } + + console.log(`✅ ${dateStr} 상태 로드 완료: ${status}`); + + } catch (error) { + console.error(`❌ ${dateStr} 상태 로드 실패:`, error); + buttonElement.classList.remove('loading-state'); + buttonElement.classList.add('error-state'); + buttonElement.title = `${dateStr} - 로드 실패: ${error.message}`; + + const statusDot = buttonElement.querySelector('.status-dot'); + if (statusDot) { + statusDot.style.background = '#ef4444'; + statusDot.classList.remove('pulse'); + } + } +} + +// ======================================== +// 작업자 데이터 관련 함수들 +// ======================================== + +/** + * 특정 날짜의 모든 작업자 데이터를 조합합니다 (순차 호출) + */ +async function getWorkersForDate(dateStr) { + try { + console.log(`👥 ${dateStr} 작업자 데이터 조합 시작 - 순차 호출`); + + // 1단계: WorkReports 먼저 가져오기 + console.log(`📝 1단계: WorkReports 조회 중...`); + const workReports = await fetchWorkReports(dateStr); + + // 2초 대기 (서버 부하 방지) + console.log(`⏳ 2초 대기 중... (서버 부하 방지)`); + await new Promise(resolve => setTimeout(resolve, 2000)); + + // 2단계: DailyWorkReports 가져오기 + console.log(`📊 2단계: DailyWorkReports 조회 중...`); + const dailyReports = await fetchDailyWorkReports(dateStr); + + const workerMap = new Map(); + + // WorkReports 데이터 추가 + workReports.forEach(wr => { + workerMap.set(wr.worker_id, { + worker_id: wr.worker_id, + worker_name: wr.worker_name, + overtime_hours: wr.overtime_hours || 0, + status: wr.status || 'normal', + expected_hours: calculateExpectedHours(wr.status || 'normal', wr.overtime_hours), + reported_hours: null, + hasWorkReport: true, + hasDailyReport: false + }); + }); + + // DailyReports 데이터 추가 + dailyReports.forEach(dr => { + if (workerMap.has(dr.worker_id)) { + const worker = workerMap.get(dr.worker_id); + worker.reported_hours = dr.work_hours; + worker.hasDailyReport = true; + } else { + workerMap.set(dr.worker_id, { + worker_id: dr.worker_id, + worker_name: dr.worker_name, + overtime_hours: 0, + status: 'normal', + expected_hours: 8, + reported_hours: dr.work_hours, + hasWorkReport: false, + hasDailyReport: true + }); + } + }); + + const result = Array.from(workerMap.values()).map(worker => ({ + ...worker, + difference: worker.reported_hours !== null ? worker.reported_hours - worker.expected_hours : -worker.expected_hours, + validationStatus: getValidationStatus(worker) + })); + + console.log(`✅ ${dateStr} 작업자 데이터 조합 완료: ${result.length}명`); + return result; + + } catch (error) { + console.error('데이터 조합 오류:', error); + return []; + } +} + +// ======================================== +// 이벤트 핸들러 함수들 +// ======================================== + +/** + * 캘린더 날짜 클릭 이벤트 핸들러 (순차 호출) + */ +async function handleDateClick(dateInfo) { + if (!dateInfo.isCurrentMonth) return; + + selectedDate = dateInfo.dateStr; + + // 선택된 날짜 표시 업데이트 + document.querySelectorAll('.calendar-day').forEach(btn => { + btn.classList.remove('selected'); + }); + + const clickedButton = event.target.closest('.calendar-day'); + if (clickedButton) { + clickedButton.classList.add('selected'); + + // 해당 날짜의 상태가 아직 로드되지 않았다면 로드 + if (clickedButton.classList.contains('no-data')) { + showMessage(`📊 ${dateInfo.dateStr} 날짜의 상태를 확인하는 중... (순차 호출로 약 5초 소요)`, 'loading'); + await loadAndUpdateDateStatus(dateInfo.dateStr, clickedButton); + } + } + + // 작업자 데이터 로드 (순차 호출) + showLoadingState(); + showMessage(`👥 ${dateInfo.dateStr} 작업자 데이터를 순차적으로 로드 중... (약 5초 소요)`, 'loading'); + + try { + const workers = await getWorkersForDate(dateInfo.dateStr); + selectedDateWorkers = workers; + renderWorkersList(workers); + + showMessage(`✅ ${dateInfo.dateStr} 날짜의 데이터를 성공적으로 로드했습니다! (${workers.length}명)`, 'success'); + + } catch (error) { + console.error('날짜별 데이터 로딩 오류:', error); + showErrorState('해당 날짜의 데이터를 불러올 수 없습니다. 잠시 후 다시 시도해주세요.'); + showMessage(`❌ ${dateInfo.dateStr} 데이터 로드 실패: ${error.message}`, 'error'); + } +} + +/** + * 작업자 근무시간 수정 모달 열기 + */ +function openEditModal(worker) { + editingWorker = worker; + + document.getElementById('editWorkerName').value = worker.worker_name; + document.getElementById('editWorkerStatus').value = getStatusText(worker.status); + document.getElementById('editWorkHours').value = worker.reported_hours || 0; + document.getElementById('editReason').value = ''; + + document.getElementById('editModal').classList.remove('hidden'); +} + +/** + * 수정 모달 닫기 + */ +function closeEditModal() { + editingWorker = null; + document.getElementById('editModal').classList.add('hidden'); +} + +/** + * 수정된 작업 저장 + */ +async function saveEditedWork() { + if (!editingWorker) return; + + try { + const newHours = document.getElementById('editWorkHours').value; + const reason = document.getElementById('editReason').value; + + if (!newHours || isNaN(newHours)) { + showMessage('올바른 시간을 입력해주세요.', 'error'); + return; + } + + showMessage('수정 중...', 'loading'); + + await updateWorkerHours(editingWorker.worker_id, selectedDate, newHours, reason); + + showMessage('✅ 근무시간이 성공적으로 수정되었습니다!', 'success'); + closeEditModal(); + + // 데이터 새로고침 + const workers = await getWorkersForDate(selectedDate); + selectedDateWorkers = workers; + renderWorkersList(workers); + renderCalendar(); + + } catch (error) { + console.error('수정 실패:', error); + showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +/** + * 작업자 데이터 삭제 + */ +async function deleteWorker(worker) { + if (!confirm(`정말로 ${worker.worker_name}의 ${selectedDate} 작업 데이터를 삭제하시겠습니까?\n삭제된 데이터는 복구할 수 없습니다.`)) { + return; + } + + try { + showMessage('삭제 중...', 'loading'); + + await deleteWorkerReport(worker.worker_id, selectedDate); + + showMessage('✅ 작업 데이터가 성공적으로 삭제되었습니다!', 'success'); + + // 데이터 새로고침 + const workers = await getWorkersForDate(selectedDate); + selectedDateWorkers = workers; + renderWorkersList(workers); + renderCalendar(); + + } catch (error) { + console.error('삭제 실패:', error); + showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// ======================================== +// UI 렌더링 함수들 +// ======================================== + +/** + * 상태 텍스트 반환 + */ +function getStatusText(status) { + const statusMap = { + 'normal': '정상출근', + 'half_day': '반차', + 'vacation': '휴가', + 'early_leave': '조퇴', + 'quarter_day': '1/4 휴가', + 'sick_leave': '병가' + }; + return statusMap[status] || status; +} + +/** + * 상태 아이콘 반환 + */ +function getStatusIcon(status) { + switch (status) { + case 'normal': return '✅'; + case 'needs-review': return '⚠️'; + case 'missing': return '❌'; + default: return '❓'; + } +} + +/** + * 날짜 포맷팅 + */ +function formatDate(dateStr) { + const date = new Date(dateStr); + const month = date.getMonth() + 1; + const day = date.getDate(); + const weekdays = ['일', '월', '화', '수', '목', '금', '토']; + const weekday = weekdays[date.getDay()]; + return `${month}월 ${day}일 (${weekday})`; +} + +/** + * 작업자 리스트를 화면에 렌더링합니다 + */ +function renderWorkersList(workers) { + const workersList = document.getElementById('workersList'); + + if (!selectedDate || workers.length === 0) { + workersList.innerHTML = ` +
+
🔄
+

날짜를 클릭해주세요

+

+ 캘린더에서 날짜를 클릭하면 해당 날짜의 작업자 검증 내역을 확인할 수 있습니다.
+ 순차 호출 방식으로 안정적이지만 약 5초의 로딩 시간이 있습니다. +

+
+ `; + return; + } + + // 필터링 적용 + const filteredWorkers = workers.filter(worker => { + if (currentFilter === 'all') return true; + if (currentFilter === 'needsReview') return worker.validationStatus === 'needs-review'; + if (currentFilter === 'normal') return worker.validationStatus === 'normal'; + if (currentFilter === 'missing') return worker.validationStatus === 'missing'; + return true; + }); + + // HTML 생성 + workersList.innerHTML = ` +
+ +
+
+

📋 작업자 검증 현황

+

${formatDate(selectedDate)}

+
+ +
+ + +
+ ${filteredWorkers.map(worker => ` +
+ +
+
+
+ ${worker.worker_name.charAt(0)} +
+
+
${worker.worker_name}
+
작업자 ID: ${worker.worker_id}
+
+
+
${getStatusIcon(worker.validationStatus)}
+
+ + +
+
+ 그룹장 입력 + + ${worker.reported_hours !== null ? `${worker.reported_hours}시간` : '미입력'} + +
+ +
+ 시스템 계산 + ${worker.expected_hours}시간 +
+ +
+ 근무 상태 + + ${getStatusText(worker.status)} + ${worker.overtime_hours > 0 ? ` + 연장 ${worker.overtime_hours}시간` : ''} + +
+ + ${worker.difference !== 0 ? ` +
+ 시간 차이 + + ${worker.difference > 0 ? '+' : ''}${worker.difference}시간 + +
+ ` : ''} +
+ + +
+ + ${worker.hasDailyReport ? ` + + ` : ''} +
+
+ `).join('')} +
+ + + ${filteredWorkers.length === 0 ? ` +
+
🔍
+

해당 조건의 작업자가 없습니다

+

+ 다른 필터를 선택하거나 전체 보기를 확인해주세요.
+ 또는 해당 날짜에 등록된 작업자가 없을 수 있습니다. +

+
+ ` : ''} +
+ `; + + // 필터 이벤트 리스너 추가 + const filterSelect = document.getElementById('workerFilter'); + filterSelect.value = currentFilter; + filterSelect.addEventListener('change', (e) => { + currentFilter = e.target.value; + renderWorkersList(selectedDateWorkers); + }); +} + +// ======================================== +// 초기화 및 이벤트 리스너 등록 +// ======================================== + +/** + * 페이지 로드 시 초기화 함수 + */ +async function init() { + try { + // 인증 확인 (api-config.js의 ensureAuthenticated 대신 직접 확인) + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + showMessage('로그인이 필요합니다.', 'error'); + localStorage.removeItem('token'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + // 월 이동 버튼 이벤트 리스너 + document.getElementById('prevMonth').addEventListener('click', async () => { + currentDate.setMonth(currentDate.getMonth() - 1); + selectedDate = null; + dateStatusCache.clear(); // 캐시 클리어 + clearCache(); // 추가 캐시 클리어 + await renderCalendar(); + renderWorkersList([]); + showMessage('📅 이전 달로 이동했습니다. 날짜를 클릭하여 순차적으로 데이터를 확인하세요.', 'success'); + }); + + document.getElementById('nextMonth').addEventListener('click', async () => { + currentDate.setMonth(currentDate.getMonth() + 1); + selectedDate = null; + dateStatusCache.clear(); // 캐시 클리어 + clearCache(); // 추가 캐시 클리어 + await renderCalendar(); + renderWorkersList([]); + showMessage('📅 다음 달로 이동했습니다. 날짜를 클릭하여 순차적으로 데이터를 확인하세요.', 'success'); + }); + + // 모달 이벤트 리스너 + document.getElementById('editModal').addEventListener('click', (e) => { + if (e.target.id === 'editModal') { + closeEditModal(); + } + }); + + // 초기 렌더링 + await renderCalendar(); + + // 순차 호출 안내 메시지 + showMessage('🔄 API 통합 적용 완료! 순차 호출 시스템으로 안정성이 개선되었습니다.', 'success'); + + // 전역 함수로 등록 + window.openEditModal = openEditModal; + window.closeEditModal = closeEditModal; + window.saveEditedWork = saveEditedWork; + window.deleteWorker = deleteWorker; + + console.log('✅ 근태 검증 관리 시스템 초기화 완료 (API 통합)'); + console.log(`🔗 API 경로: ${API}`); + console.log(`📊 설정: 동시 최대 ${RATE_LIMIT.maxConcurrent}개 요청, ${RATE_LIMIT.delayBetweenRequests}ms 딜레이`); + console.log('🔄 API 호출 방식: 통합 설정 + 순차 호출'); + console.log('🚫 429 에러 방지: 각 날짜당 최소 5초 간격'); + + } catch (error) { + console.error('초기화 오류:', error); + showMessage('시스템 초기화 중 오류가 발생했습니다.', 'error'); + } +} + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', init); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/attendance.js b/deploy/tkfb-package/web-ui/js/attendance.js new file mode 100644 index 0000000..10ffcc7 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/attendance.js @@ -0,0 +1,176 @@ +import { API, getAuthHeaders } from '/js/api-config.js'; + +const yearSel = document.getElementById('year'); +const monthSel = document.getElementById('month'); +const container = document.getElementById('attendanceTableContainer'); + +const holidays = [ + '2025-01-01','2025-01-27','2025-01-28','2025-01-29','2025-01-30','2025-01-31', + '2025-03-01','2025-03-03','2025-05-01','2025-05-05','2025-05-06', + '2025-06-03','2025-06-06','2025-08-15','2025-10-03','2025-10-09','2025-12-25' +]; + +const leaveDefaults = { + '김두수':16,'임영규':16,'반치원':16,'황인용':16,'표영진':15, + '김윤섭':16,'이창호':16,'최광욱':16,'박현수':14,'조윤호':0 +}; + +let workers = []; + +// ✅ 셀렉트 박스 옵션 + 기본 선택 추가 +function fillSelectOptions() { + const currentY = new Date().getFullYear(); + const currentM = String(new Date().getMonth() + 1).padStart(2, '0'); + + for (let y = currentY; y <= currentY + 5; y++) { + const selected = y === currentY ? 'selected' : ''; + yearSel.insertAdjacentHTML('beforeend', ``); + } + + for (let m = 1; m <= 12; m++) { + const mm = String(m).padStart(2, '0'); + const selected = mm === currentM ? 'selected' : ''; + monthSel.insertAdjacentHTML('beforeend', ``); + } +} + +// ✅ 작업자 목록 불러오기 +async function fetchWorkers() { + try { + const res = await fetch(`${API}/workers`, { headers: getAuthHeaders() }); + const allWorkers = await res.json(); + + // 활성화된 작업자만 필터링 + workers = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + + workers.sort((a, b) => a.worker_id - b.worker_id); + } catch (err) { + alert('작업자 불러오기 실패'); + } +} + +// ✅ 출근부 불러오기 (해당 연도 전체) +async function loadAttendance() { + const year = yearSel.value; + const month = monthSel.value; + if (!year || !month) return alert('연도와 월을 선택하세요'); + + const lastDay = new Date(+year, +month, 0).getDate(); + const start = `${year}-01-01`; + const end = `${year}-12-31`; + + try { + const res = await fetch(`${API}/workreports?start=${start}&end=${end}`, { + headers: getAuthHeaders() + }); + const data = await res.json(); + renderTable(data, year, month, lastDay); + } catch (err) { + alert('출근부 로딩 실패'); + } +} + +// ✅ 테이블 렌더링 +function renderTable(data, year, month, lastDay) { + container.innerHTML = ''; + const weekdays = ['일','월','화','수','목','금','토']; + const tbl = document.createElement('table'); + + // ⬆️ 헤더 구성 + let thead = `작업자`; + for (let d = 1; d <= lastDay; d++) thead += `${d}`; + thead += `잔업합계사용연차잔여연차`; + for (let d = 1; d <= lastDay; d++) { + const dow = new Date(+year, +month - 1, d).getDay(); + thead += `${weekdays[dow]}`; + } + thead += ''; + tbl.innerHTML = thead; + + // ⬇️ 본문 + workers.forEach(w => { + // ✅ 월간 데이터 (표에 표시용) + const recsThisMonth = data.filter(r => + r.worker_id === w.worker_id && + new Date(r.date).getFullYear() === +year && + new Date(r.date).getMonth() + 1 === +month + ); + + // ✅ 연간 데이터 (연차 계산용) + const recsThisYear = data.filter(r => + r.worker_id === w.worker_id && + new Date(r.date).getFullYear() === +year + ); + + let otSum = 0; + let row = `${w.worker_name}`; + + for (let d = 1; d <= lastDay; d++) { + const dd = String(d).padStart(2, '0'); + const date = `${year}-${month}-${dd}`; + + const rec = recsThisMonth.find(r => { + const rDate = new Date(r.date); + const yyyy = rDate.getFullYear(); + const mm = String(rDate.getMonth() + 1).padStart(2, '0'); + const dd = String(rDate.getDate()).padStart(2, '0'); + return `${yyyy}-${mm}-${dd}` === date; + }); + + const dow = new Date(+year, +month - 1, d).getDay(); + const isWe = dow === 0 || dow === 6; + const isHo = holidays.includes(date); + + let txt = '', cls = ''; + if (rec) { + const ot = +rec.overtime_hours || 0; + if (ot > 0) { + txt = ot; cls = 'overtime-cell'; otSum += ot; + } else if (rec.work_details) { + const d = rec.work_details; + if (['연차','반차','반반차','조퇴'].includes(d)) { + txt = d; cls = 'leave'; + } else if (d === '유급') { + txt = d; cls = 'paid-leave'; + } else if (d === '휴무') { + txt = d; cls = 'holiday'; + } else { + txt = d; + } + } + } else { + txt = (isWe || isHo) ? '휴무' : ''; + cls = (isWe || isHo) ? 'holiday' : 'no-data'; + } + + row += `${txt}`; + } + + const usedTot = recsThisYear + .filter(r => ['연차','반차','반반차','조퇴'].includes(r.work_details)) + .reduce((s, r) => s + ( + r.work_details === '연차' ? 1 : + r.work_details === '반차' ? 0.5 : + r.work_details === '반반차' ? 0.25 : 0.75 + ), 0); + + const remain = (leaveDefaults[w.worker_name] || 0) - usedTot; + + row += `${otSum.toFixed(1)}`; + row += `${usedTot.toFixed(2)}${remain.toFixed(2)}`; + row += ``; + + tbl.insertAdjacentHTML('beforeend', row); + }); + + container.appendChild(tbl); +} + +// ✅ 초기 로딩 +fillSelectOptions(); +fetchWorkers().then(() => { + loadAttendance(); // 자동 조회 +}); +document.getElementById('loadAttendance').addEventListener('click', loadAttendance); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/auth-check.js b/deploy/tkfb-package/web-ui/js/auth-check.js new file mode 100644 index 0000000..de15476 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/auth-check.js @@ -0,0 +1,157 @@ +// /js/auth-check.js +// auth.js의 함수들을 직접 구현 (모듈 의존성 제거) + +function isLoggedIn() { + const token = localStorage.getItem('token'); + return token && token !== 'undefined' && token !== 'null'; +} + +function getUser() { + const user = localStorage.getItem('user'); + return user ? JSON.parse(user) : null; +} + +function clearAuthData() { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + localStorage.removeItem('userPageAccess'); // 페이지 권한 캐시도 삭제 +} + +/** + * 현재 페이지의 page_key를 URL 경로로부터 추출 + * 예: /pages/work/tbm.html -> work.tbm + * /pages/admin/accounts.html -> admin.accounts + * /pages/dashboard.html -> dashboard + */ +function getCurrentPageKey() { + const path = window.location.pathname; + + // /pages/로 시작하는지 확인 + if (!path.startsWith('/pages/')) { + return null; + } + + // /pages/ 이후 경로 추출 + const pagePath = path.substring(7); // '/pages/' 제거 + + // .html 제거 + const withoutExt = pagePath.replace('.html', ''); + + // 슬래시를 점으로 변환 + const pageKey = withoutExt.replace(/\//g, '.'); + + return pageKey; +} + +/** + * 사용자의 페이지 접근 권한 확인 (캐시 활용) + */ +async function checkPageAccess(pageKey) { + const currentUser = getUser(); + + // Admin은 모든 페이지 접근 가능 + if (currentUser.role === 'Admin' || currentUser.role === 'System Admin') { + return true; + } + + // 프로필 페이지는 모든 사용자 접근 가능 + if (pageKey && pageKey.startsWith('profile.')) { + return true; + } + + // 대시보드는 모든 사용자 접근 가능 + if (pageKey === 'dashboard') { + return true; + } + + try { + // 캐시된 권한 확인 + const cached = localStorage.getItem('userPageAccess'); + let accessiblePages = null; + + if (cached) { + const cacheData = JSON.parse(cached); + // 캐시가 5분 이내인 경우 사용 + if (Date.now() - cacheData.timestamp < 5 * 60 * 1000) { + accessiblePages = cacheData.pages; + } + } + + // 캐시가 없으면 API 호출 + if (!accessiblePages) { + const response = await fetch(`${window.API_BASE_URL}/users/${currentUser.user_id}/page-access`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + } + }); + + if (!response.ok) { + console.error('페이지 권한 조회 실패:', response.status); + return false; + } + + const data = await response.json(); + accessiblePages = data.data.pageAccess || []; + + // 캐시 저장 + localStorage.setItem('userPageAccess', JSON.stringify({ + pages: accessiblePages, + timestamp: Date.now() + })); + } + + // 해당 페이지에 대한 접근 권한 확인 + const pageAccess = accessiblePages.find(p => p.page_key === pageKey); + return pageAccess && pageAccess.can_access === 1; + } catch (error) { + console.error('페이지 권한 체크 오류:', error); + return false; + } +} + +// 즉시 실행 함수로 스코프를 보호하고 로직을 실행 +(async function() { + if (!isLoggedIn()) { + console.log('🚨 인증되지 않은 사용자. 로그인 페이지로 이동합니다.'); + clearAuthData(); // 만약을 위해 한번 더 정리 + window.location.href = '/index.html'; + return; // 이후 코드 실행 방지 + } + + const currentUser = getUser(); + + // 사용자 정보가 유효한지 확인 (토큰은 있지만 유저 정보가 깨졌을 경우) + if (!currentUser || !currentUser.username) { + console.error('🚨 사용자 정보가 유효하지 않습니다. 강제 로그아웃 처리합니다.'); + clearAuthData(); + window.location.href = '/index.html'; + return; + } + + const userRole = currentUser.role || currentUser.access_level || '사용자'; + console.log(`✅ ${currentUser.username}(${userRole})님 인증 성공.`); + + // 페이지 접근 권한 체크 (Admin은 건너뛰기) + if (currentUser.role !== 'Admin' && currentUser.role !== 'System Admin') { + const pageKey = getCurrentPageKey(); + + if (pageKey) { + console.log(`🔍 페이지 권한 체크: ${pageKey}`); + const hasAccess = await checkPageAccess(pageKey); + + if (!hasAccess) { + console.error(`🚫 페이지 접근 권한이 없습니다: ${pageKey}`); + alert('이 페이지에 접근할 권한이 없습니다.'); + window.location.href = '/pages/dashboard.html'; + return; + } + + console.log(`✅ 페이지 접근 권한 확인됨: ${pageKey}`); + } + } + + // 역할 기반 메뉴 제어 로직은 각 컴포넌트 로더(load-navbar.js 등)로 이전함. + // 전역 변수 할당(window.currentUser) 제거. +})(); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/auth.js b/deploy/tkfb-package/web-ui/js/auth.js new file mode 100644 index 0000000..7a8e6e5 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/auth.js @@ -0,0 +1,76 @@ +// js/auth.js + +/** + * JWT 토큰을 디코딩하여 페이로드(내용)를 반환합니다. + * @param {string} token - JWT 토큰 + * @returns {object|null} - 디코딩된 페이로드 객체 또는 파싱 실패 시 null + */ +export function parseJwt(token) { + try { + // 토큰의 두 번째 부분(payload)을 base64 디코딩하고 JSON으로 파싱 + return JSON.parse(atob(token.split('.')[1])); + } catch (e) { + console.error("잘못된 토큰입니다.", e); + return null; + } +} + +/** + * localStorage에서 인증 토큰을 가져옵니다. + * @returns {string|null} - 저장된 토큰 또는 토큰이 없을 경우 null + */ +export function getToken() { + return localStorage.getItem('token'); +} + +/** + * localStorage에서 사용자 정보를 가져옵니다. + * @returns {object|null} - 저장된 사용자 객체 또는 정보가 없을 경우 null + */ +export function getUser() { + const user = localStorage.getItem('user'); + try { + return user ? JSON.parse(user) : null; + } catch(e) { + console.error("사용자 정보를 파싱하는 데 실패했습니다.", e); + return null; + } +} + +/** + * 로그인 성공 후 토큰과 사용자 정보를 localStorage에 저장합니다. + * @param {string} token - 서버에서 받은 JWT 토큰 + * @param {object} user - 서버에서 받은 사용자 정보 객체 + */ +export function saveAuthData(token, user) { + localStorage.setItem('token', token); + localStorage.setItem('user', JSON.stringify(user)); +} + +/** + * 로그아웃 시 localStorage에서 인증 정보를 제거합니다. + */ +export function clearAuthData() { + localStorage.removeItem('token'); + localStorage.removeItem('user'); +} + +/** + * 현재 사용자가 로그인 상태인지 확인합니다. + * @returns {boolean} - 로그인 상태이면 true, 아니면 false + */ +export function isLoggedIn() { + const token = getToken(); + if (!token) { + return false; + } + + // 선택 사항: 토큰 만료 여부 확인 로직 추가 가능 + // const payload = parseJwt(token); + // if (payload && payload.exp * 1000 > Date.now()) { + // return true; + // } + // return false; + + return !!token; +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/calendar.js b/deploy/tkfb-package/web-ui/js/calendar.js new file mode 100644 index 0000000..d5c591b --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/calendar.js @@ -0,0 +1,59 @@ +// ✅ /js/calendar.js +export function renderCalendar(containerId, onDateSelect) { + const container = document.getElementById(containerId); + if (!container) return; + + let currentDate = new Date(); + let selectedDateStr = ''; + + function drawCalendar(date) { + container.innerHTML = ''; + const year = date.getFullYear(); + const month = date.getMonth(); + const firstDay = new Date(year, month, 1).getDay(); + const lastDate = new Date(year, month + 1, 0).getDate(); + + const nav = document.createElement('div'); + nav.className = 'nav'; + const prev = document.createElement('button'); + prev.textContent = '◀'; + prev.addEventListener('click', () => { + currentDate = new Date(year, month - 1, 1); + drawCalendar(currentDate); + }); + const title = document.createElement('div'); + title.innerHTML = `${year}년 ${month + 1}월`; + const next = document.createElement('button'); + next.textContent = '▶'; + next.addEventListener('click', () => { + currentDate = new Date(year, month + 1, 1); + drawCalendar(currentDate); + }); + nav.append(prev, title, next); + container.appendChild(nav); + + ['일','월','화','수','목','금','토'].forEach(day => { + const el = document.createElement('div'); + el.innerHTML = `${day}`; + container.appendChild(el); + }); + + for (let i = 0; i < firstDay; i++) container.appendChild(document.createElement('div')); + + for (let i = 1; i <= lastDate; i++) { + const btn = document.createElement('button'); + const ymd = `${year}-${String(month + 1).padStart(2, '0')}-${String(i).padStart(2, '0')}`; + btn.textContent = i; + btn.className = (ymd === selectedDateStr) ? 'selected-date' : ''; + btn.addEventListener('click', () => { + selectedDateStr = ymd; + drawCalendar(currentDate); + onDateSelect(ymd); + }); + container.appendChild(btn); + } + } + + drawCalendar(currentDate); +} + diff --git a/deploy/tkfb-package/web-ui/js/change-password.js b/deploy/tkfb-package/web-ui/js/change-password.js new file mode 100644 index 0000000..4858a9e --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/change-password.js @@ -0,0 +1,211 @@ +// js/change-password.js +// 개인 비밀번호 변경 페이지 JavaScript + +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +const token = ensureAuthenticated(); + +// DOM 요소 +const form = document.getElementById('changePasswordForm'); +const messageArea = document.getElementById('message-area'); +const submitBtn = document.getElementById('submitBtn'); +const resetBtn = document.getElementById('resetBtn'); + +// 비밀번호 토글 기능 +document.querySelectorAll('.password-toggle').forEach(button => { + button.addEventListener('click', function() { + const targetId = this.getAttribute('data-target'); + const input = document.getElementById(targetId); + + if (input) { + const isPassword = input.type === 'password'; + input.type = isPassword ? 'text' : 'password'; + this.textContent = isPassword ? '👁️‍🗨️' : '👁️'; + } + }); +}); + +// 초기화 버튼 +resetBtn?.addEventListener('click', () => { + form.reset(); + clearMessages(); + document.getElementById('passwordStrength').innerHTML = ''; +}); + +// 메시지 표시 함수 +function showMessage(type, message) { + messageArea.innerHTML = ` +
+ ${type === 'error' ? '❌' : '✅'} ${message} +
+ `; + + // 에러 메시지는 5초 후 자동 제거 + if (type === 'error') { + setTimeout(clearMessages, 5000); + } +} + +function clearMessages() { + messageArea.innerHTML = ''; +} + +// 비밀번호 강도 체크 +async function checkPasswordStrength(password) { + if (!password) { + document.getElementById('passwordStrength').innerHTML = ''; + return; + } + + try { + const res = await fetch(`${API}/auth/check-password-strength`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ password }) + }); + + const result = await res.json(); + updatePasswordStrengthUI(result); + } catch (error) { + console.error('Password strength check error:', error); + } +} + +// 비밀번호 강도 UI 업데이트 +function updatePasswordStrengthUI(strength) { + const container = document.getElementById('passwordStrength'); + if (!container) return; + + const colors = { + 0: '#f44336', + 1: '#ff9800', + 2: '#ffc107', + 3: '#4caf50', + 4: '#2196f3' + }; + + const strengthText = strength.strengthText || '비밀번호를 입력하세요'; + const color = colors[strength.strength] || '#ccc'; + const percentage = (strength.score / strength.maxScore) * 100; + + container.innerHTML = ` +
+
+ + ${strengthText} + + + ${strength.score}/${strength.maxScore} + +
+
+
+
+ ${strength.feedback && strength.feedback.length > 0 ? ` +
    + ${strength.feedback.map(f => `
  • ${f}
  • `).join('')} +
+ ` : ''} +
+ `; +} + +// 비밀번호 입력 이벤트 +let strengthCheckTimer; +document.getElementById('newPassword')?.addEventListener('input', (e) => { + clearTimeout(strengthCheckTimer); + strengthCheckTimer = setTimeout(() => { + checkPasswordStrength(e.target.value); + }, 300); +}); + +// 폼 제출 +form?.addEventListener('submit', async (e) => { + e.preventDefault(); + clearMessages(); + + const currentPassword = document.getElementById('currentPassword').value; + const newPassword = document.getElementById('newPassword').value; + const confirmPassword = document.getElementById('confirmPassword').value; + + // 유효성 검사 + if (!currentPassword || !newPassword || !confirmPassword) { + showMessage('error', '모든 필드를 입력해주세요.'); + return; + } + + if (newPassword !== confirmPassword) { + showMessage('error', '새 비밀번호가 일치하지 않습니다.'); + return; + } + + if (newPassword.length < 6) { + showMessage('error', '비밀번호는 최소 6자 이상이어야 합니다.'); + return; + } + + if (currentPassword === newPassword) { + showMessage('error', '새 비밀번호는 현재 비밀번호와 달라야 합니다.'); + return; + } + + // 버튼 상태 변경 + const originalText = submitBtn.innerHTML; + submitBtn.disabled = true; + submitBtn.innerHTML = '처리 중...'; + + try { + const res = await fetch(`${API}/auth/change-password`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + currentPassword, + newPassword + }) + }); + + const result = await res.json(); + + if (res.ok && result.success) { + showMessage('success', '비밀번호가 성공적으로 변경되었습니다.'); + form.reset(); + document.getElementById('passwordStrength').innerHTML = ''; + + // 카운트다운 시작 + let countdown = 3; + const countdownInterval = setInterval(() => { + showMessage('success', + `비밀번호가 변경되었습니다. ${countdown}초 후 로그인 페이지로 이동합니다.` + ); + countdown--; + + if (countdown < 0) { + clearInterval(countdownInterval); + localStorage.removeItem('token'); + localStorage.removeItem('user'); + window.location.href = '/index.html'; + } + }, 1000); + + } else { + const errorMessage = result.error || '비밀번호 변경에 실패했습니다.'; + showMessage('error', errorMessage); + } + } catch (error) { + console.error('Password change error:', error); + showMessage('error', '서버와의 연결에 실패했습니다. 잠시 후 다시 시도해주세요.'); + } finally { + submitBtn.disabled = false; + submitBtn.innerHTML = originalText; + } +}); + +// 페이지 로드 시 현재 사용자 정보 표시 +document.addEventListener('DOMContentLoaded', () => { + const user = JSON.parse(localStorage.getItem('user') || '{}'); + console.log('🔐 비밀번호 변경 페이지 로드됨'); + console.log('👤 현재 사용자:', user.username || 'Unknown'); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/common/security.js b/deploy/tkfb-package/web-ui/js/common/security.js new file mode 100644 index 0000000..19304c4 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/common/security.js @@ -0,0 +1,259 @@ +/** + * Security Utilities - 보안 관련 유틸리티 함수 + * + * XSS 방지, 입력값 검증, 안전한 DOM 조작을 위한 함수 모음 + * + * @author TK-FB-Project + * @since 2026-02-04 + */ + +(function(global) { + 'use strict'; + + const SecurityUtils = { + /** + * HTML 특수문자 이스케이프 (XSS 방지) + * innerHTML에 사용자 입력을 삽입할 때 반드시 사용 + * + * @param {string} str - 이스케이프할 문자열 + * @returns {string} 이스케이프된 문자열 + * + * @example + * element.innerHTML = `${SecurityUtils.escapeHtml(userInput)}`; + */ + escapeHtml: function(str) { + if (str === null || str === undefined) return ''; + if (typeof str !== 'string') str = String(str); + + const htmlEntities = { + '&': '&', + '<': '<', + '>': '>', + '"': '"', + "'": ''', + '/': '/', + '`': '`', + '=': '=' + }; + + return str.replace(/[&<>"'`=\/]/g, function(char) { + return htmlEntities[char]; + }); + }, + + /** + * URL 파라미터 이스케이프 + * URL에 사용자 입력을 포함할 때 사용 + * + * @param {string} str - 이스케이프할 문자열 + * @returns {string} URL 인코딩된 문자열 + */ + escapeUrl: function(str) { + if (str === null || str === undefined) return ''; + return encodeURIComponent(String(str)); + }, + + /** + * JavaScript 문자열 이스케이프 + * 동적 JavaScript 생성 시 사용 (권장하지 않음) + * + * @param {string} str - 이스케이프할 문자열 + * @returns {string} 이스케이프된 문자열 + */ + escapeJs: function(str) { + if (str === null || str === undefined) return ''; + return String(str) + .replace(/\\/g, '\\\\') + .replace(/'/g, "\\'") + .replace(/"/g, '\\"') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/\t/g, '\\t'); + }, + + /** + * 안전한 텍스트 설정 + * innerHTML 대신 textContent 사용 권장 + * + * @param {Element} element - DOM 요소 + * @param {string} text - 설정할 텍스트 + */ + setTextSafe: function(element, text) { + if (element && element.nodeType === 1) { + element.textContent = text; + } + }, + + /** + * 안전한 HTML 삽입 + * 사용자 입력이 포함된 HTML을 삽입할 때 사용 + * + * @param {Element} element - DOM 요소 + * @param {string} template - HTML 템플릿 ({{변수}} 형식) + * @param {Object} data - 삽입할 데이터 (자동 이스케이프됨) + * + * @example + * SecurityUtils.setHtmlSafe(div, '{{name}}', { name: userInput }); + */ + setHtmlSafe: function(element, template, data) { + if (!element || element.nodeType !== 1) return; + + const self = this; + const safeHtml = template.replace(/\{\{(\w+)\}\}/g, function(match, key) { + return data.hasOwnProperty(key) ? self.escapeHtml(data[key]) : ''; + }); + + element.innerHTML = safeHtml; + }, + + /** + * 입력값 검증 - 숫자 + * + * @param {any} value - 검증할 값 + * @param {Object} options - 옵션 { min, max, allowFloat } + * @returns {number|null} 유효한 숫자 또는 null + */ + validateNumber: function(value, options) { + options = options || {}; + const num = options.allowFloat ? parseFloat(value) : parseInt(value, 10); + + if (isNaN(num)) return null; + if (options.min !== undefined && num < options.min) return null; + if (options.max !== undefined && num > options.max) return null; + + return num; + }, + + /** + * 입력값 검증 - 이메일 + * + * @param {string} email - 검증할 이메일 + * @returns {boolean} 유효 여부 + */ + validateEmail: function(email) { + if (!email || typeof email !== 'string') return false; + const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; + return emailRegex.test(email); + }, + + /** + * 입력값 검증 - 길이 + * + * @param {string} str - 검증할 문자열 + * @param {Object} options - 옵션 { min, max } + * @returns {boolean} 유효 여부 + */ + validateLength: function(str, options) { + options = options || {}; + if (!str || typeof str !== 'string') return false; + + const len = str.length; + if (options.min !== undefined && len < options.min) return false; + if (options.max !== undefined && len > options.max) return false; + + return true; + }, + + /** + * 안전한 JSON 파싱 + * + * @param {string} jsonString - 파싱할 JSON 문자열 + * @param {any} defaultValue - 파싱 실패 시 기본값 + * @returns {any} 파싱된 객체 또는 기본값 + */ + parseJsonSafe: function(jsonString, defaultValue) { + defaultValue = defaultValue === undefined ? null : defaultValue; + try { + return JSON.parse(jsonString); + } catch (e) { + console.warn('[SecurityUtils] JSON 파싱 실패:', e.message); + return defaultValue; + } + }, + + /** + * localStorage에서 안전하게 데이터 가져오기 + * + * @param {string} key - 키 + * @param {any} defaultValue - 기본값 + * @returns {any} 저장된 값 또는 기본값 + */ + getStorageSafe: function(key, defaultValue) { + try { + const item = localStorage.getItem(key); + if (item === null) return defaultValue; + return this.parseJsonSafe(item, defaultValue); + } catch (e) { + console.warn('[SecurityUtils] localStorage 접근 실패:', e.message); + return defaultValue; + } + }, + + /** + * URL 파라미터 안전하게 가져오기 + * + * @param {string} name - 파라미터 이름 + * @param {string} defaultValue - 기본값 + * @returns {string} 파라미터 값 (이스케이프됨) + */ + getUrlParamSafe: function(name, defaultValue) { + defaultValue = defaultValue === undefined ? '' : defaultValue; + try { + const urlParams = new URLSearchParams(window.location.search); + const value = urlParams.get(name); + return value !== null ? value : defaultValue; + } catch (e) { + return defaultValue; + } + }, + + /** + * ID 파라미터 안전하게 가져오기 (숫자 검증) + * + * @param {string} name - 파라미터 이름 + * @returns {number|null} 유효한 ID 또는 null + */ + getIdParamSafe: function(name) { + const value = this.getUrlParamSafe(name); + return this.validateNumber(value, { min: 1 }); + }, + + /** + * Content Security Policy 위반 리포터 + * + * @param {string} reportUri - 리포트 전송 URL + */ + enableCspReporting: function(reportUri) { + document.addEventListener('securitypolicyviolation', function(e) { + console.error('[CSP Violation]', { + blockedUri: e.blockedURI, + violatedDirective: e.violatedDirective, + originalPolicy: e.originalPolicy + }); + + if (reportUri) { + fetch(reportUri, { + method: 'POST', + body: JSON.stringify({ + blocked_uri: e.blockedURI, + violated_directive: e.violatedDirective, + document_uri: e.documentURI, + timestamp: new Date().toISOString() + }), + headers: { 'Content-Type': 'application/json' } + }).catch(function() {}); + } + }); + } + }; + + // 전역 노출 + global.SecurityUtils = SecurityUtils; + + // 편의를 위한 단축 함수 + global.escapeHtml = SecurityUtils.escapeHtml.bind(SecurityUtils); + global.escapeUrl = SecurityUtils.escapeUrl.bind(SecurityUtils); + + console.log('[Module] common/security.js 로드 완료'); + +})(typeof window !== 'undefined' ? window : this); diff --git a/deploy/tkfb-package/web-ui/js/component-loader.js b/deploy/tkfb-package/web-ui/js/component-loader.js new file mode 100644 index 0000000..97eca11 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/component-loader.js @@ -0,0 +1,81 @@ +// /js/component-loader.js +import { config } from './config.js'; + +// 캐시 버전 (컴포넌트 변경 시 증가) +const CACHE_VERSION = 'v4'; + +/** + * 컴포넌트 HTML을 캐시에서 가져오거나 fetch + */ +async function getComponentHtml(componentName, componentPath) { + const cacheKey = `component_${componentName}_${CACHE_VERSION}`; + + // 캐시에서 먼저 확인 + const cached = sessionStorage.getItem(cacheKey); + if (cached) { + return cached; + } + + // 캐시 없으면 fetch + const response = await fetch(componentPath); + if (!response.ok) { + throw new Error(`컴포넌트 파일을 불러올 수 없습니다: ${response.statusText}`); + } + const htmlText = await response.text(); + + // 캐시에 저장 + try { + sessionStorage.setItem(cacheKey, htmlText); + } catch (e) { + // sessionStorage 용량 초과 시 무시 + } + + return htmlText; +} + +/** + * 공용 HTML 컴포넌트를 페이지의 특정 위치에 동적으로 로드합니다. + * @param {string} componentName - 로드할 컴포넌트의 이름 (e.g., 'sidebar', 'navbar'). config.js의 components 객체에 정의된 키와 일치해야 합니다. + * @param {string} containerSelector - 컴포넌트가 삽입될 DOM 요소의 CSS 선택자 (e.g., '#sidebar-container'). + * @param {function(Document): void} [domProcessor=null] - DOM에 삽입하기 전에 로드된 HTML(Document)을 조작하는 선택적 함수. + * (e.g., 역할 기반 메뉴 필터링) + */ +export async function loadComponent(componentName, containerSelector, domProcessor = null) { + const container = document.querySelector(containerSelector); + if (!container) { + console.warn(`⚠️ 컴포넌트를 삽입할 컨테이너를 찾을 수 없습니다: ${containerSelector} (선택사항일 수 있음)`); + return; + } + + const componentPath = config.components[componentName]; + if (!componentPath) { + console.error(`🔴 설정 파일(config.js)에서 '${componentName}' 컴포넌트의 경로를 찾을 수 없습니다.`); + container.innerHTML = `

${componentName} 로딩 실패

`; + return; + } + + try { + const htmlText = await getComponentHtml(componentName, componentPath); + + if (domProcessor) { + // 1. 텍스트를 가상 DOM으로 파싱 + const parser = new DOMParser(); + const doc = parser.parseFromString(htmlText, 'text/html'); + + // 2. DOM 프로세서(콜백)를 실행하여 DOM 조작 + await domProcessor(doc); + + // 3. 조작된 HTML을 실제 DOM에 삽입 + container.innerHTML = doc.body.innerHTML; + } else { + // DOM 조작이 필요 없는 경우, 바로 삽입 + container.innerHTML = htmlText; + } + + console.log(`✅ '${componentName}' 컴포넌트 로딩 완료: ${containerSelector}`); + + } catch (error) { + console.error(`🔴 '${componentName}' 컴포넌트 로딩 실패:`, error); + container.innerHTML = `

${componentName} 로딩에 실패했습니다. 관리자에게 문의하세요.

`; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/config.js b/deploy/tkfb-package/web-ui/js/config.js new file mode 100644 index 0000000..9fc26a9 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/config.js @@ -0,0 +1,33 @@ +// /js/config.js - Synology NAS 배포용 +// 이 파일을 web-ui/js/config.js로 복사하세요 + +export const config = { + // API 관련 설정 + api: { + // Synology NAS Docker 환경에서 사용하는 API 서버 포트 + port: 3005, + // API의 기본 경로 + path: '/api', + }, + + // 페이지 경로 설정 + paths: { + loginPage: '/index.html', + dashboard: '/pages/dashboard.html', + defaultDashboard: '/pages/dashboard.html', + systemDashboard: '/pages/dashboard.html', + groupLeaderDashboard: '/pages/dashboard.html', + }, + + // 공용 컴포넌트 경로 설정 + components: { + sidebar: '/components/sidebar.html', + 'sidebar-nav': '/components/sidebar-nav.html', + navbar: '/components/navbar.html', + }, + + // 애플리케이션 관련 기타 설정 + app: { + tokenRefreshInterval: 5 * 60 * 1000, + } +}; diff --git a/deploy/tkfb-package/web-ui/js/daily-issue-api.js b/deploy/tkfb-package/web-ui/js/daily-issue-api.js new file mode 100644 index 0000000..8a0e95b --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-issue-api.js @@ -0,0 +1,71 @@ +// /js/daily-issue-api.js +import { apiGet, apiPost } from './api-helper.js'; + +/** + * 이슈 보고서 작성을 위해 필요한 초기 데이터(프로젝트, 이슈 유형)를 가져옵니다. + * @returns {Promise<{projects: Array, issueTypes: Array}>} + */ +export async function getInitialData() { + try { + const [projects, issueTypes] = await Promise.all([ + apiGet('/projects'), + apiGet('/issue-types') + ]); + return { projects, issueTypes }; + } catch (error) { + console.error('이슈 보고서 초기 데이터 로딩 실패:', error); + throw error; + } +} + +/** + * 특정 날짜에 근무한 작업자 목록을 가져옵니다. + * @param {string} date - 조회할 날짜 (YYYY-MM-DD) + * @returns {Promise} - 작업자 목록 + */ +export async function getWorkersByDate(date) { + try { + // 백엔드에 해당 날짜의 작업자 목록을 요청하는 API가 있다고 가정합니다. + // (예: /api/workers?work_date=YYYY-MM-DD) + // 현재는 기존 로직을 최대한 활용하여 구현합니다. + let workers = []; + const reports = await apiGet(`/daily-work-reports?date=${date}`); + + if (reports && reports.length > 0) { + const workerMap = new Map(); + reports.forEach(r => { + if (!workerMap.has(r.worker_id)) { + workerMap.set(r.worker_id, { worker_id: r.worker_id, worker_name: r.worker_name }); + } + }); + workers = Array.from(workerMap.values()); + } else { + // 보고서가 없으면 전체 작업자 목록을 가져옵니다. + const allWorkers = await apiGet('/workers'); + + // 활성화된 작업자만 필터링 + workers = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + } + return workers.sort((a, b) => a.worker_name.localeCompare(b.worker_name)); + } catch (error) { + console.error(`${date}의 작업자 목록 로딩 실패:`, error); + throw error; + } +} + +/** + * 작성된 이슈 보고서 데이터를 서버에 전송합니다. + * @param {object} issueData - 전송할 이슈 데이터 + * @returns {Promise} - 서버 응답 결과 + */ +export async function createIssueReport(issueData) { + try { + const result = await apiPost('/issue-reports', issueData); + return result; + } catch (error) { + console.error('이슈 보고서 생성 요청 실패:', error); + throw error; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/daily-issue-ui.js b/deploy/tkfb-package/web-ui/js/daily-issue-ui.js new file mode 100644 index 0000000..c125ea8 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-issue-ui.js @@ -0,0 +1,103 @@ +// /js/daily-issue-ui.js + +const DOM = { + dateSelect: document.getElementById('dateSelect'), + projectSelect: document.getElementById('projectSelect'), + issueTypeSelect: document.getElementById('issueTypeSelect'), + timeStart: document.getElementById('timeStart'), + timeEnd: document.getElementById('timeEnd'), + workerList: document.getElementById('workerList'), + form: document.getElementById('issueForm'), + submitBtn: document.getElementById('submitBtn'), +}; + +function createOption(value, text) { + const option = document.createElement('option'); + option.value = value; + option.textContent = text; + return option; +} + +export function populateProjects(projects) { + DOM.projectSelect.innerHTML = ''; + if (Array.isArray(projects)) { + projects.forEach(p => DOM.projectSelect.appendChild(createOption(p.project_id, p.project_name))); + } +} + +export function populateIssueTypes(issueTypes) { + DOM.issueTypeSelect.innerHTML = ''; + if (Array.isArray(issueTypes)) { + issueTypes.forEach(t => DOM.issueTypeSelect.appendChild(createOption(t.issue_type_id, `${t.category}:${t.subcategory}`))); + } +} + +export function populateTimeOptions() { + for (let h = 0; h < 24; h++) { + for (let m of [0, 30]) { + const time = `${String(h).padStart(2, '0')}:${m === 0 ? '00' : '30'}`; + DOM.timeStart.appendChild(createOption(time, time)); + DOM.timeEnd.appendChild(createOption(time, time.replace('00:00', '24:00'))); + } + } + DOM.timeEnd.value = "24:00"; // 기본값 설정 +} + +export function renderWorkerList(workers) { + DOM.workerList.innerHTML = ''; + if (!Array.isArray(workers) || workers.length === 0) { + DOM.workerList.textContent = '선택 가능한 작업자가 없습니다.'; + return; + } + workers.forEach(worker => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'btn'; + btn.textContent = worker.worker_name; + btn.dataset.id = worker.worker_id; + btn.addEventListener('click', () => btn.classList.toggle('selected')); + DOM.workerList.appendChild(btn); + }); +} + +export function getFormData() { + const selectedWorkers = [...DOM.workerList.querySelectorAll('.btn.selected')].map(b => b.dataset.id); + + if (selectedWorkers.length === 0) { + alert('작업자를 한 명 이상 선택해주세요.'); + return null; + } + if (DOM.timeEnd.value <= DOM.timeStart.value) { + alert('종료 시간은 시작 시간보다 이후여야 합니다.'); + return null; + } + + const formData = new FormData(DOM.form); + const data = { + date: formData.get('dateSelect'), // input name 속성이 없어 직접 가져옴 + project_id: DOM.projectSelect.value, + issue_type_id: DOM.issueTypeSelect.value, + start_time: DOM.timeStart.value, + end_time: DOM.timeEnd.value, + worker_ids: selectedWorkers, // worker_id -> worker_ids 로 명확하게 변경 + }; + + for (const key in data) { + if (!data[key] || (Array.isArray(data[key]) && data[key].length === 0)) { + alert('모든 필수 항목을 입력해주세요.'); + return null; + } + } + + return data; +} + +export function setSubmitButtonState(isLoading) { + if (isLoading) { + DOM.submitBtn.disabled = true; + DOM.submitBtn.textContent = '등록 중...'; + } else { + DOM.submitBtn.disabled = false; + DOM.submitBtn.textContent = '등록'; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/daily-issue.js b/deploy/tkfb-package/web-ui/js/daily-issue.js new file mode 100644 index 0000000..f7f024b --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-issue.js @@ -0,0 +1,89 @@ +// /js/daily-issue.js + +import { getInitialData, getWorkersByDate, createIssueReport } from './daily-issue-api.js'; +import { + populateProjects, + populateIssueTypes, + populateTimeOptions, + renderWorkerList, + getFormData, + setSubmitButtonState +} from './daily-issue-ui.js'; + +const dateSelect = document.getElementById('dateSelect'); +const form = document.getElementById('issueForm'); + +/** + * 날짜가 변경될 때마다 해당 날짜의 작업자 목록을 다시 불러옵니다. + */ +async function handleDateChange() { + const selectedDate = dateSelect.value; + if (!selectedDate) { + document.getElementById('workerList').textContent = '날짜를 먼저 선택하세요.'; + return; + } + + document.getElementById('workerList').textContent = '작업자 목록을 불러오는 중...'; + try { + const workers = await getWorkersByDate(selectedDate); + renderWorkerList(workers); + } catch (error) { + document.getElementById('workerList').textContent = '작업자 목록 로딩에 실패했습니다.'; + } +} + +/** + * 폼 제출 이벤트를 처리합니다. + */ +async function handleSubmit(event) { + event.preventDefault(); + const issueData = getFormData(); + + if (!issueData) return; // 유효성 검사 실패 + + setSubmitButtonState(true); + try { + const result = await createIssueReport(issueData); + if (result.success) { + alert('✅ 이슈가 성공적으로 등록되었습니다.'); + form.reset(); // 폼 초기화 + dateSelect.value = new Date().toISOString().split('T')[0]; // 날짜 오늘로 리셋 + handleDateChange(); // 작업자 목록 새로고침 + } else { + throw new Error(result.error || '알 수 없는 오류가 발생했습니다.'); + } + } catch (error) { + alert(`🚨 등록 실패: ${error.message}`); + } finally { + setSubmitButtonState(false); + } +} + +/** + * 페이지 초기화 함수 + */ +async function initializePage() { + // 오늘 날짜 기본 설정 + dateSelect.value = new Date().toISOString().split('T')[0]; + + populateTimeOptions(); + + // 프로젝트, 이슈유형, 작업자 목록을 병렬로 로드 + try { + const [initialData] = await Promise.all([ + getInitialData(), + handleDateChange() // 초기 작업자 목록 로드 + ]); + populateProjects(initialData.projects); + populateIssueTypes(initialData.issueTypes); + } catch (error) { + alert('페이지 초기화 중 오류가 발생했습니다. 새로고침 해주세요.'); + } + + // 이벤트 리스너 설정 + dateSelect.addEventListener('change', handleDateChange); + form.addEventListener('submit', handleSubmit); +} + +// DOM이 로드되면 페이지 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializePage); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/daily-patrol.js b/deploy/tkfb-package/web-ui/js/daily-patrol.js new file mode 100644 index 0000000..cec5220 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-patrol.js @@ -0,0 +1,1249 @@ +// daily-patrol.js - 일일순회점검 페이지 JavaScript + +// 전역 상태 +let currentSession = null; +let categories = []; // 공장(대분류) 목록 +let workplaces = []; // 작업장 목록 +let checklistItems = []; // 체크리스트 항목 +let checkRecords = {}; // 체크 기록 (workplace_id -> records) +let selectedWorkplace = null; +let itemTypes = []; // 물품 유형 +let workplaceItems = []; // 현재 작업장 물품 +let isItemEditMode = false; +let workplaceDetail = null; // 작업장 상세 정보 + +// XSS 방지를 위한 HTML 이스케이프 함수 +function escapeHtml(str) { + if (str === null || str === undefined) return ''; + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +// 이미지 URL 헬퍼 함수 (정적 파일용 - /api 경로 제외) +function getImageUrl(path) { + if (!path) return ''; + // 이미 http로 시작하면 그대로 반환 + if (path.startsWith('http')) return path; + // API_BASE_URL에서 /api 제거하여 정적 파일 서버 URL 생성 + // /uploads 경로는 인증 없이 접근 가능한 정적 파일 경로 + const staticUrl = window.API_BASE_URL.replace(/\/api$/, ''); + return staticUrl + path; +} + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', async () => { + await waitForAxiosConfig(); + initializePage(); +}); + +// axios 설정 대기 +function waitForAxiosConfig() { + return new Promise((resolve) => { + const check = setInterval(() => { + if (axios.defaults.baseURL) { + clearInterval(check); + resolve(); + } + }, 50); + setTimeout(() => { + clearInterval(check); + resolve(); + }, 5000); + }); +} + +// 자동 날짜/시간대 결정 +function getAutoPatrolDateTime() { + const now = new Date(); + const patrolDate = now.toISOString().slice(0, 10); + const hour = now.getHours(); + // 오전(~12시), 오후(12시~) + const patrolTime = hour < 12 ? 'morning' : 'afternoon'; + return { patrolDate, patrolTime }; +} + +// 페이지 초기화 +async function initializePage() { + // 데이터 로드 + await Promise.all([ + loadCategories(), + loadItemTypes(), + loadTodayStatus() + ]); + + // 저장된 세션 상태 복원 (구역 상세에서 돌아온 경우) + await restoreSessionState(); +} + +// 세션 상태 저장 (페이지 이동 전) +function saveSessionState() { + if (currentSession) { + const state = { + session: currentSession, + categoryId: currentSession.category_id, + checkRecords: checkRecords, + timestamp: Date.now() + }; + sessionStorage.setItem('patrolSessionState', JSON.stringify(state)); + } +} + +// 세션 상태 복원 +async function restoreSessionState() { + const savedState = sessionStorage.getItem('patrolSessionState'); + if (!savedState) return; + + try { + const state = JSON.parse(savedState); + // 5분 이내의 상태만 복원 + if (Date.now() - state.timestamp > 5 * 60 * 1000) { + sessionStorage.removeItem('patrolSessionState'); + return; + } + + // categories가 비어있으면 복원 불가 + if (!categories || categories.length === 0) { + console.log('카테고리 목록이 없어 세션 복원 불가'); + sessionStorage.removeItem('patrolSessionState'); + return; + } + + // 해당 카테고리가 존재하는지 확인 + const category = categories.find(c => c.category_id == state.categoryId); + if (!category) { + console.log('저장된 카테고리를 찾을 수 없음:', state.categoryId); + sessionStorage.removeItem('patrolSessionState'); + return; + } + + // 세션 복원 + currentSession = state.session; + checkRecords = state.checkRecords || {}; + + // 작업장 목록 로드 + await loadWorkplaces(state.categoryId); + + // 체크리스트 항목 로드 + await loadChecklistItems(state.categoryId); + + // UI 표시 + document.getElementById('startPatrolBtn').style.display = 'none'; + document.getElementById('factorySelectionArea').style.display = 'none'; + document.getElementById('patrolArea').style.display = 'block'; + renderSessionInfo(); + renderWorkplaceMap(); + + console.log('세션 상태 복원 완료:', state.categoryId); + + // 복원 후 저장 상태 삭제 + sessionStorage.removeItem('patrolSessionState'); + } catch (error) { + console.error('세션 상태 복원 실패:', error); + sessionStorage.removeItem('patrolSessionState'); + } +} + +// 공장(대분류) 목록 로드 +async function loadCategories() { + try { + const response = await axios.get('/workplaces/categories'); + if (response.data.success) { + categories = response.data.data; + } + } catch (error) { + console.error('공장 목록 로드 실패:', error); + } +} + +// 공장 선택 화면 표시 +function showFactorySelection() { + const { patrolDate, patrolTime } = getAutoPatrolDateTime(); + const timeLabel = patrolTime === 'morning' ? '오전' : '오후'; + const dateObj = new Date(patrolDate); + const dateLabel = dateObj.toLocaleDateString('ko-KR', { month: 'long', day: 'numeric', weekday: 'short' }); + + // 세션 정보 표시 + document.getElementById('patrolSessionInfo').textContent = `${dateLabel} ${timeLabel} 순회점검`; + + // 공장 카드 렌더링 + const container = document.getElementById('factoryCardsContainer'); + container.innerHTML = categories.map(c => ` +
+
+ ${c.layout_image ? `${escapeHtml(c.category_name)}` : '🏭'} +
+
${escapeHtml(c.category_name)}
+
+ `).join(''); + + // 시작 버튼 숨기고 공장 선택 영역 표시 + document.getElementById('startPatrolBtn').style.display = 'none'; + document.getElementById('factorySelectionArea').style.display = 'block'; +} + +// 공장 선택 후 점검 시작 +async function selectFactory(categoryId) { + const { patrolDate, patrolTime } = getAutoPatrolDateTime(); + + try { + // 세션 생성 또는 조회 + const response = await axios.post('/patrol/sessions', { + patrol_date: patrolDate, + patrol_time: patrolTime, + category_id: categoryId + }); + + if (response.data.success) { + currentSession = response.data.data; + currentSession.patrol_date = patrolDate; + currentSession.patrol_time = patrolTime; + currentSession.category_id = categoryId; + + // 작업장 목록 로드 + await loadWorkplaces(categoryId); + + // 체크리스트 항목 로드 + await loadChecklistItems(categoryId); + + // 공장 선택 영역 숨기고 점검 영역 표시 + document.getElementById('factorySelectionArea').style.display = 'none'; + document.getElementById('patrolArea').style.display = 'block'; + renderSessionInfo(); + renderWorkplaceMap(); + } + } catch (error) { + console.error('순회점검 시작 실패:', error); + alert('순회점검을 시작할 수 없습니다.'); + } +} + +// 물품 유형 로드 +async function loadItemTypes() { + try { + const response = await axios.get('/patrol/item-types'); + if (response.data.success) { + itemTypes = response.data.data; + renderItemTypesSelect(); + renderItemsLegend(); + } + } catch (error) { + console.error('물품 유형 로드 실패:', error); + } +} + +// 오늘 점검 현황 로드 +async function loadTodayStatus() { + try { + const response = await axios.get('/patrol/today-status'); + if (response.data.success) { + renderTodayStatus(response.data.data); + } + } catch (error) { + console.error('오늘 현황 로드 실패:', error); + } +} + +// 오늘 점검 현황 렌더링 +function renderTodayStatus(statusList) { + const container = document.getElementById('todayStatusSummary'); + if (!statusList || statusList.length === 0) { + container.innerHTML = ` +
+
오전
+
미점검
+
+
+
오후
+
미점검
+
+ `; + return; + } + + const morning = statusList.find(s => s.patrol_time === 'morning'); + const afternoon = statusList.find(s => s.patrol_time === 'afternoon'); + + container.innerHTML = ` +
+
오전
+
+ ${morning ? (morning.status === 'completed' ? '완료' : '진행중') : '미점검'} +
+ ${morning ? `
${escapeHtml(morning.inspector_name || '')}
` : ''} +
+
+
오후
+
+ ${afternoon ? (afternoon.status === 'completed' ? '완료' : '진행중') : '미점검'} +
+ ${afternoon ? `
${escapeHtml(afternoon.inspector_name || '')}
` : ''} +
+ `; +} + + +// 작업장 목록 로드 +async function loadWorkplaces(categoryId) { + try { + // 작업장 목록 로드 + const response = await axios.get(`/workplaces?category_id=${categoryId}`); + if (response.data.success) { + workplaces = response.data.data; + } + + // 지도 영역(좌표) 로드 + try { + const regionsResponse = await axios.get(`/workplaces/categories/${categoryId}/map-regions`); + if (regionsResponse.data.success && regionsResponse.data.data) { + // 작업장에 좌표 정보 병합 + const regions = regionsResponse.data.data; + workplaces = workplaces.map(wp => { + const region = regions.find(r => r.workplace_id === wp.workplace_id); + if (region) { + // x_start, y_start를 x_percent, y_percent로 매핑 + return { + ...wp, + x_percent: region.x_start, + y_percent: region.y_start, + x_end: region.x_end, + y_end: region.y_end + }; + } + return wp; + }); + } + } catch (regError) { + console.log('지도 영역 로드 스킵:', regError.message); + } + } catch (error) { + console.error('작업장 목록 로드 실패:', error); + } +} + +// 체크리스트 항목 로드 +async function loadChecklistItems(categoryId) { + try { + const response = await axios.get(`/patrol/checklist?category_id=${categoryId}`); + if (response.data.success) { + checklistItems = response.data.data.items; + } + } catch (error) { + console.error('체크리스트 항목 로드 실패:', error); + } +} + +// 세션 정보 렌더링 +function renderSessionInfo() { + const container = document.getElementById('sessionInfo'); + const category = categories.find(c => c.category_id == currentSession.category_id); + const checkedCount = Object.values(checkRecords).flat().filter(r => r.is_checked).length; + const totalCount = workplaces.length * checklistItems.length; + const progress = totalCount > 0 ? Math.round(checkedCount / totalCount * 100) : 0; + + container.innerHTML = ` +
+
+ 점검일자 + ${escapeHtml(formatDate(currentSession.patrol_date))} +
+
+ 시간대 + ${currentSession.patrol_time === 'morning' ? '오전' : '오후'} +
+
+ 공장 + ${escapeHtml(category?.category_name || '')} +
+
+
+
+
+
+ ${parseInt(progress) || 0}% +
+ `; +} + +// 작업장 지도/목록 렌더링 +function renderWorkplaceMap() { + const mapContainer = document.getElementById('patrolMapContainer'); + const listContainer = document.getElementById('workplaceListContainer'); + const category = categories.find(c => c.category_id == currentSession.category_id); + + // 지도 이미지가 있으면 지도 표시 + if (category?.layout_image) { + mapContainer.innerHTML = `${escapeHtml(category.category_name)} 지도`; + mapContainer.style.display = 'block'; + + // 좌표가 있는 작업장만 마커 추가 + const hasMarkers = workplaces.some(wp => wp.x_percent !== undefined && wp.y_percent !== undefined); + + // 마커 위치 정보를 먼저 계산 + const markerData = workplaces + .filter(wp => wp.x_percent !== undefined && wp.y_percent !== undefined) + .map(wp => { + let centerX = parseFloat(wp.x_percent) || 0; + let centerY = parseFloat(wp.y_percent) || 0; + if (wp.x_end && wp.y_end) { + centerX = (parseFloat(wp.x_percent) + parseFloat(wp.x_end)) / 2; + centerY = (parseFloat(wp.y_percent) + parseFloat(wp.y_end)) / 2; + } + return { wp, centerX, centerY }; + }); + + // y좌표 기준 정렬 (아래에 있을수록 나중에 추가 = 위에 표시) + markerData.sort((a, b) => a.centerY - b.centerY); + + markerData.forEach((data, index) => { + const { wp, centerX, centerY } = data; + const marker = document.createElement('div'); + marker.className = 'workplace-marker'; + + // 밀집도 체크 - 근처에 다른 마커가 있으면 compact 클래스 추가 + const nearbyMarkers = markerData.filter(other => + other !== data && + Math.abs(other.centerX - centerX) < 12 && + Math.abs(other.centerY - centerY) < 12 + ); + if (nearbyMarkers.length > 0) { + marker.classList.add('compact'); + } + + marker.style.left = `${centerX}%`; + marker.style.top = `${centerY}%`; + // y좌표가 클수록 (아래쪽일수록) z-index가 높아서 위에 표시 + marker.style.zIndex = Math.floor(centerY) + 10; + marker.textContent = wp.workplace_name; + marker.dataset.workplaceId = wp.workplace_id; + marker.onclick = () => goToZoneDetail(wp.workplace_id); + + // 점검 상태에 따른 스타일 + const records = checkRecords[wp.workplace_id]; + if (records && records.some(r => r.is_checked)) { + marker.classList.add(records.every(r => r.is_checked) ? 'completed' : 'in-progress'); + } + + mapContainer.appendChild(marker); + }); + + // 좌표가 없는 작업장이 있으면 카드 목록도 표시 + const hasWorkplacesWithoutCoords = workplaces.some(wp => wp.x_percent === undefined || wp.y_percent === undefined); + if (!hasMarkers || hasWorkplacesWithoutCoords) { + listContainer.style.display = 'grid'; + renderWorkplaceCards(listContainer); + } else { + listContainer.style.display = 'none'; + } + } else { + // 지도 없으면 카드 목록으로 표시 + mapContainer.style.display = 'none'; + listContainer.style.display = 'grid'; + renderWorkplaceCards(listContainer); + } +} + +// 구역 상세 페이지로 이동 +function goToZoneDetail(workplaceId) { + // 현재 세션 상태 저장 + saveSessionState(); + window.location.href = `/pages/inspection/zone-detail.html?id=${workplaceId}`; +} + +// 작업장 카드 렌더링 +function renderWorkplaceCards(container) { + container.innerHTML = workplaces.map(wp => { + const records = checkRecords[wp.workplace_id]; + const isCompleted = records && records.length > 0 && records.every(r => r.is_checked); + const isInProgress = records && records.some(r => r.is_checked); + const workplaceId = parseInt(wp.workplace_id) || 0; + + return ` +
+
${escapeHtml(wp.workplace_name)}
+
+ ${isCompleted ? '점검완료' : (isInProgress ? '점검중' : '미점검')} +
+
+ `; + }).join(''); +} + +// 작업장 선택 +async function selectWorkplace(workplaceId) { + selectedWorkplace = workplaces.find(w => w.workplace_id === workplaceId); + + // 마커/카드 선택 상태 업데이트 + document.querySelectorAll('.workplace-marker, .workplace-card').forEach(el => { + el.classList.remove('selected'); + if (el.dataset.workplaceId == workplaceId) { + el.classList.add('selected'); + } + }); + + // 기존 체크 기록 로드 + if (!checkRecords[workplaceId]) { + try { + const response = await axios.get(`/patrol/sessions/${currentSession.session_id}/records?workplace_id=${workplaceId}`); + if (response.data.success) { + checkRecords[workplaceId] = response.data.data; + } + } catch (error) { + console.error('체크 기록 로드 실패:', error); + checkRecords[workplaceId] = []; + } + } + + // 체크리스트 렌더링 + renderChecklist(workplaceId); + + // 물품 현황 로드 및 표시 + await loadWorkplaceItems(workplaceId); + + // 작업장 상세 정보 로드 (신고, TBM, 출입 등) + await loadWorkplaceDetail(workplaceId); + + // 액션 버튼 표시 + document.getElementById('checklistActions').style.display = 'flex'; +} + +// 체크리스트 렌더링 +function renderChecklist(workplaceId) { + const header = document.getElementById('checklistHeader'); + const content = document.getElementById('checklistContent'); + const workplace = workplaces.find(w => w.workplace_id === workplaceId); + + header.innerHTML = ` +

${escapeHtml(workplace?.workplace_name || '')} 체크리스트

+

각 항목을 점검하고 체크해주세요

+ `; + + // 카테고리별 그룹화 + const grouped = {}; + checklistItems.forEach(item => { + if (!grouped[item.check_category]) { + grouped[item.check_category] = []; + } + grouped[item.check_category].push(item); + }); + + const records = checkRecords[workplaceId] || []; + + content.innerHTML = Object.entries(grouped).map(([category, items]) => ` +
+
${escapeHtml(getCategoryName(category))}
+ ${items.map(item => { + const record = records.find(r => r.check_item_id === item.item_id); + const isChecked = record?.is_checked; + const checkResult = record?.check_result; + const itemId = parseInt(item.item_id) || 0; + const wpId = parseInt(workplaceId) || 0; + + return ` +
+
+ ${isChecked ? '✓' : ''} +
+
+
+ ${escapeHtml(item.check_item)} + ${item.is_required ? '*' : ''} +
+ ${isChecked ? ` +
+ + + +
+ ` : ''} +
+
+ `; + }).join('')} +
+ `).join(''); +} + +// 카테고리명 변환 +function getCategoryName(code) { + const names = { + 'SAFETY': '안전', + 'ORGANIZATION': '정리정돈', + 'EQUIPMENT': '설비', + 'ENVIRONMENT': '환경' + }; + return names[code] || code; +} + +// 체크 항목 토글 +function toggleCheckItem(workplaceId, itemId) { + if (!checkRecords[workplaceId]) { + checkRecords[workplaceId] = []; + } + + const records = checkRecords[workplaceId]; + const existingIndex = records.findIndex(r => r.check_item_id === itemId); + + if (existingIndex >= 0) { + records[existingIndex].is_checked = !records[existingIndex].is_checked; + if (!records[existingIndex].is_checked) { + records[existingIndex].check_result = null; + } + } else { + records.push({ + check_item_id: itemId, + is_checked: true, + check_result: 'good', + note: null + }); + } + + renderChecklist(workplaceId); + renderWorkplaceMap(); + renderSessionInfo(); +} + +// 체크 결과 설정 +function setCheckResult(workplaceId, itemId, result) { + const records = checkRecords[workplaceId]; + const record = records.find(r => r.check_item_id === itemId); + if (record) { + record.check_result = result; + renderChecklist(workplaceId); + } +} + +// 임시 저장 +async function saveChecklistDraft() { + if (!selectedWorkplace) return; + + try { + const records = checkRecords[selectedWorkplace.workplace_id] || []; + await axios.post(`/patrol/sessions/${currentSession.session_id}/records/batch`, { + workplace_id: selectedWorkplace.workplace_id, + records: records + }); + alert('임시 저장되었습니다.'); + } catch (error) { + console.error('임시 저장 실패:', error); + alert('저장에 실패했습니다.'); + } +} + +// 저장 후 다음 +async function saveChecklist() { + if (!selectedWorkplace) return; + + try { + const records = checkRecords[selectedWorkplace.workplace_id] || []; + await axios.post(`/patrol/sessions/${currentSession.session_id}/records/batch`, { + workplace_id: selectedWorkplace.workplace_id, + records: records + }); + + // 다음 미점검 작업장으로 이동 + const currentIndex = workplaces.findIndex(w => w.workplace_id === selectedWorkplace.workplace_id); + const nextWorkplace = workplaces.slice(currentIndex + 1).find(w => { + const records = checkRecords[w.workplace_id]; + return !records || records.length === 0 || !records.every(r => r.is_checked); + }); + + if (nextWorkplace) { + selectWorkplace(nextWorkplace.workplace_id); + } else { + alert('모든 작업장 점검이 완료되었습니다!'); + } + } catch (error) { + console.error('저장 실패:', error); + alert('저장에 실패했습니다.'); + } +} + +// 순회점검 완료 +async function completePatrol() { + if (!currentSession) return; + + // 미점검 작업장 확인 + const uncheckedCount = workplaces.filter(w => { + const records = checkRecords[w.workplace_id]; + return !records || records.length === 0; + }).length; + + if (uncheckedCount > 0) { + if (!confirm(`아직 ${uncheckedCount}개 작업장이 미점검 상태입니다. 그래도 완료하시겠습니까?`)) { + return; + } + } + + try { + const notes = document.getElementById('patrolNotes').value; + if (notes) { + await axios.patch(`/patrol/sessions/${currentSession.session_id}/notes`, { notes }); + } + + await axios.patch(`/patrol/sessions/${currentSession.session_id}/complete`); + + alert('순회점검이 완료되었습니다.'); + location.reload(); + } catch (error) { + console.error('순회점검 완료 실패:', error); + alert('순회점검 완료에 실패했습니다.'); + } +} + +// ==================== 물품 현황 ==================== + +// 작업장 물품 로드 +async function loadWorkplaceItems(workplaceId) { + try { + const response = await axios.get(`/patrol/workplaces/${workplaceId}/items`); + if (response.data.success) { + workplaceItems = response.data.data; + renderItemsSection(workplaceId); + } + } catch (error) { + console.error('물품 로드 실패:', error); + workplaceItems = []; + } +} + +// 물품 섹션 렌더링 +function renderItemsSection(workplaceId) { + const section = document.getElementById('itemsSection'); + const workplace = workplaces.find(w => w.workplace_id === workplaceId); + const container = document.getElementById('itemsMapContainer'); + + document.getElementById('selectedWorkplaceName').textContent = workplace?.workplace_name || ''; + + // 작업장 레이아웃 이미지가 있으면 표시 + if (workplace?.layout_image) { + container.innerHTML = `${escapeHtml(workplace.workplace_name)}`; + + // 물품 마커 추가 + workplaceItems.forEach(item => { + if (item.x_percent && item.y_percent) { + const marker = document.createElement('div'); + // item_type은 화이트리스트로 검증 + const safeItemType = ['container', 'plate', 'material', 'tool', 'other'].includes(item.item_type) ? item.item_type : 'other'; + marker.className = `item-marker ${safeItemType}`; + marker.style.left = `${parseFloat(item.x_percent) || 0}%`; + marker.style.top = `${parseFloat(item.y_percent) || 0}%`; + marker.style.width = `${parseFloat(item.width_percent) || 5}%`; + marker.style.height = `${parseFloat(item.height_percent) || 5}%`; + marker.textContent = item.icon || getItemTypeIcon(item.item_type); // textContent 사용 + marker.title = `${item.item_name || item.type_name} (${parseInt(item.quantity) || 0}개)`; + marker.dataset.itemId = item.item_id; + marker.onclick = () => openItemModal(item); + container.appendChild(marker); + } + }); + } else { + container.innerHTML = '

작업장 레이아웃 이미지가 없습니다.

'; + } + + section.style.display = 'block'; +} + +// 물품 유형 아이콘 +function getItemTypeIcon(typeCode) { + const icons = { + 'container': '📦', + 'plate': '🔲', + 'material': '🧱', + 'tool': '🔧', + 'other': '📍' + }; + return icons[typeCode] || '📍'; +} + +// 물품 유형 셀렉트 렌더링 +function renderItemTypesSelect() { + const select = document.getElementById('itemType'); + if (!select) return; + select.innerHTML = itemTypes.map(t => + `` + ).join(''); +} + +// 물품 범례 렌더링 +function renderItemsLegend() { + const container = document.getElementById('itemsLegend'); + if (!container) return; + // 색상 값 검증 (hex color만 허용) + const isValidColor = (color) => /^#[0-9A-Fa-f]{3,6}$/.test(color); + container.innerHTML = itemTypes.map(t => { + const safeColor = isValidColor(t.color) ? t.color : '#888888'; + return ` +
+
+ ${escapeHtml(t.icon)} +
+ ${escapeHtml(t.type_name)} +
+ `; + }).join(''); +} + +// 편집 모드 토글 +function toggleItemEditMode() { + isItemEditMode = !isItemEditMode; + document.getElementById('itemEditModeText').textContent = isItemEditMode ? '편집모드 종료' : '편집모드'; + + if (isItemEditMode) { + // 지도 클릭으로 물품 추가 + const container = document.getElementById('itemsMapContainer'); + container.style.cursor = 'crosshair'; + container.onclick = (e) => { + if (e.target === container || e.target.tagName === 'IMG') { + const rect = container.getBoundingClientRect(); + const x = ((e.clientX - rect.left) / rect.width * 100).toFixed(2); + const y = ((e.clientY - rect.top) / rect.height * 100).toFixed(2); + openItemModal(null, x, y); + } + }; + } else { + const container = document.getElementById('itemsMapContainer'); + container.style.cursor = 'default'; + container.onclick = null; + } +} + +// 물품 모달 열기 +function openItemModal(item = null, x = null, y = null) { + const modal = document.getElementById('itemModal'); + const title = document.getElementById('itemModalTitle'); + const deleteBtn = document.getElementById('deleteItemBtn'); + + if (item) { + title.textContent = '물품 수정'; + document.getElementById('itemId').value = item.item_id; + document.getElementById('itemType').value = item.item_type; + document.getElementById('itemName').value = item.item_name || ''; + document.getElementById('itemQuantity').value = item.quantity || 1; + deleteBtn.style.display = 'inline-block'; + } else { + title.textContent = '물품 추가'; + document.getElementById('itemForm').reset(); + document.getElementById('itemId').value = ''; + document.getElementById('itemId').dataset.x = x; + document.getElementById('itemId').dataset.y = y; + deleteBtn.style.display = 'none'; + } + + modal.style.display = 'flex'; +} + +// 물품 모달 닫기 +function closeItemModal() { + document.getElementById('itemModal').style.display = 'none'; +} + +// 물품 저장 +async function saveItem() { + if (!selectedWorkplace) return; + + const itemId = document.getElementById('itemId').value; + const data = { + item_type: document.getElementById('itemType').value, + item_name: document.getElementById('itemName').value, + quantity: parseInt(document.getElementById('itemQuantity').value) || 1, + patrol_session_id: currentSession?.session_id + }; + + // 새 물품일 경우 위치 추가 + if (!itemId) { + data.x_percent = parseFloat(document.getElementById('itemId').dataset.x); + data.y_percent = parseFloat(document.getElementById('itemId').dataset.y); + data.width_percent = 5; + data.height_percent = 5; + } + + try { + if (itemId) { + await axios.put(`/patrol/items/${itemId}`, data); + } else { + await axios.post(`/patrol/workplaces/${selectedWorkplace.workplace_id}/items`, data); + } + + closeItemModal(); + await loadWorkplaceItems(selectedWorkplace.workplace_id); + } catch (error) { + console.error('물품 저장 실패:', error); + alert('물품 저장에 실패했습니다.'); + } +} + +// 물품 삭제 +async function deleteItem() { + const itemId = document.getElementById('itemId').value; + if (!itemId) return; + + if (!confirm('이 물품을 삭제하시겠습니까?')) return; + + try { + await axios.delete(`/patrol/items/${itemId}`); + closeItemModal(); + await loadWorkplaceItems(selectedWorkplace.workplace_id); + } catch (error) { + console.error('물품 삭제 실패:', error); + alert('물품 삭제에 실패했습니다.'); + } +} + +// 유틸리티 함수 +function formatDate(dateStr) { + if (!dateStr) return ''; + const date = new Date(dateStr); + return date.toLocaleDateString('ko-KR', { year: 'numeric', month: 'long', day: 'numeric', weekday: 'short' }); +} + +// ESC 키로 모달 닫기 +document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + closeItemModal(); + closeWorkplaceDetailPanel(); + } +}); + +// ==================== 작업장 상세 정보 패널 ==================== + +// 작업장 상세 정보 로드 +async function loadWorkplaceDetail(workplaceId) { + try { + const today = new Date().toISOString().slice(0, 10); + const response = await axios.get(`/patrol/workplaces/${workplaceId}/detail?date=${today}`); + if (response.data.success) { + workplaceDetail = response.data.data; + renderWorkplaceDetailPanel(); + } + } catch (error) { + console.error('작업장 상세 정보 로드 실패:', error); + // 에러 발생 시에도 기본 패널 표시 + workplaceDetail = null; + renderWorkplaceDetailPanel(); + } +} + +// 상세 정보 패널 렌더링 +function renderWorkplaceDetailPanel() { + let panel = document.getElementById('workplaceDetailPanel'); + if (!panel) { + panel = document.createElement('div'); + panel.id = 'workplaceDetailPanel'; + panel.className = 'workplace-detail-panel'; + document.body.appendChild(panel); + } + + if (!workplaceDetail || !selectedWorkplace) { + panel.style.display = 'none'; + return; + } + + const { workplace, equipments, repairRequests, workIssues, visitRecords, tbmSessions, recentPatrol, summary } = workplaceDetail; + + panel.innerHTML = ` +
+
+

${escapeHtml(workplace.workplace_name)}

+ ${escapeHtml(workplace.category_name || '')} +
+ +
+ +
+
+ ${summary.equipmentCount} + 설비 +
+
+ ${summary.pendingRepairs} + 수리요청 +
+
+ ${summary.openIssues} + 미해결 신고 +
+
+ ${summary.todayVisitors} + 금일 방문자 +
+
+ ${summary.todayTbmSessions} + 금일 TBM +
+
+ +
+ + + + +
+ +
+ +
+ ${renderIssuesTab(workIssues)} +
+ + +
+ ${renderEquipmentTab(equipments, repairRequests)} +
+ + +
+ ${renderVisitsTab(visitRecords)} +
+ + +
+ ${renderTbmTab(tbmSessions)} +
+
+ `; + + panel.style.display = 'flex'; +} + +// 신고/부적합 탭 렌더링 +function renderIssuesTab(workIssues) { + if (!workIssues.all.length) { + return `
최근 30일간 신고 내역이 없습니다.
`; + } + + const safetyIssues = workIssues.safety; + const nonconformityIssues = workIssues.nonconformity; + + let html = ''; + + if (safetyIssues.length > 0) { + html += ` +
+

🛡️ 안전 신고 (${safetyIssues.length})

+ ${safetyIssues.map(issue => renderIssueItem(issue)).join('')} +
+ `; + } + + if (nonconformityIssues.length > 0) { + html += ` +
+

⚠️ 부적합 사항 (${nonconformityIssues.length})

+ ${nonconformityIssues.map(issue => renderIssueItem(issue)).join('')} +
+ `; + } + + return html || `
신고 내역이 없습니다.
`; +} + +// 신고 항목 렌더링 +function renderIssueItem(issue) { + const statusColors = { + 'pending': 'pending', + 'received': 'info', + 'in_progress': 'warning', + 'completed': 'success', + 'closed': 'muted' + }; + const statusLabels = { + 'pending': '대기', + 'received': '접수', + 'in_progress': '처리중', + 'completed': '완료', + 'closed': '종료' + }; + const severityLabels = { + 'low': '경미', + 'medium': '보통', + 'high': '중요', + 'critical': '긴급' + }; + + return ` +
+
+ ${escapeHtml(issue.title)} + ${statusLabels[issue.status] || issue.status} +
+
+ ${escapeHtml(issue.category_name || '')} + ${severityLabels[issue.severity] || ''} + ${formatDateTime(issue.created_at)} +
+ ${issue.description ? `
${escapeHtml(issue.description).slice(0, 100)}${issue.description.length > 100 ? '...' : ''}
` : ''} +
신고자: ${escapeHtml(issue.reporter_name || '익명')}
+
+ `; +} + +// 설비 탭 렌더링 +function renderEquipmentTab(equipments, repairRequests) { + let html = ''; + + // 수리 요청 먼저 표시 + if (repairRequests.length > 0) { + html += ` +
+

🔧 수리 요청 (${repairRequests.length})

+ ${repairRequests.map(req => ` +
+
+ ${escapeHtml(req.equipment_name)} (${escapeHtml(req.equipment_code)}) + ${getPriorityLabel(req.priority)} +
+
${escapeHtml(req.repair_category)}
+
${escapeHtml(req.description || '')}
+
${formatDate(req.request_date)}
+
+ `).join('')} +
+ `; + } + + // 설비 목록 + if (equipments.length > 0) { + html += ` +
+

📦 설비 현황 (${equipments.length})

+
+ ${equipments.map(eq => ` +
+ ${escapeHtml(eq.equipment_name)} + ${escapeHtml(eq.equipment_code)} + ${getEquipmentStatusLabel(eq.status)} +
+ `).join('')} +
+
+ `; + } else { + html += `
등록된 설비가 없습니다.
`; + } + + return html; +} + +// 출입 탭 렌더링 +function renderVisitsTab(visitRecords) { + if (!visitRecords.length) { + return `
금일 승인된 방문자가 없습니다.
`; + } + + return ` +
+ ${visitRecords.map(visit => ` +
+
+ ${escapeHtml(visit.visitor_name)} + ${escapeHtml(visit.visitor_company || '')} +
+
${escapeHtml(visit.purpose_name || visit.visit_purpose || '')}
+
+ 🕐 ${escapeHtml(visit.visit_time_from || '')} ~ ${escapeHtml(visit.visit_time_to || '')} +
+ ${visit.companion_count > 0 ? `
동행 ${visit.companion_count}명
` : ''} + ${visit.vehicle_number ? `
🚗 ${escapeHtml(visit.vehicle_number)}
` : ''} +
+ `).join('')} +
+ `; +} + +// TBM 탭 렌더링 +function renderTbmTab(tbmSessions) { + if (!tbmSessions.length) { + return `
금일 TBM 세션이 없습니다.
`; + } + + return ` +
+ ${tbmSessions.map(tbm => ` +
+
+ ${escapeHtml(tbm.task_name || tbm.work_type_name || '작업')} + ${getTbmStatusLabel(tbm.status)} +
+
📍 ${escapeHtml(tbm.work_location || '')}
+
👷 ${escapeHtml(tbm.leader_name || tbm.leader_worker_name || '')}
+ ${tbm.work_content ? `
작업내용: ${escapeHtml(tbm.work_content).slice(0, 80)}...
` : ''} + ${tbm.team && tbm.team.length > 0 ? ` +
+ 팀원 (${tbm.team.length}명): + ${tbm.team.map(m => escapeHtml(m.worker_name)).join(', ')} +
+ ` : ''} + ${tbm.safety_measures ? `
⚠️ ${escapeHtml(tbm.safety_measures).slice(0, 60)}...
` : ''} +
+ `).join('')} +
+ `; +} + +// 탭 전환 +function switchDetailTab(tabName) { + // 탭 버튼 활성화 + document.querySelectorAll('.detail-tab').forEach(tab => { + tab.classList.toggle('active', tab.dataset.tab === tabName); + }); + // 탭 콘텐츠 표시 + document.querySelectorAll('.detail-tab-content').forEach(content => { + content.classList.toggle('active', content.id === `tab-${tabName}`); + }); +} + +// 상세 패널 닫기 +function closeWorkplaceDetailPanel() { + const panel = document.getElementById('workplaceDetailPanel'); + if (panel) { + panel.style.display = 'none'; + } + workplaceDetail = null; +} + +// 헬퍼 함수들 +function getPriorityLabel(priority) { + const labels = { 'emergency': '긴급', 'high': '높음', 'normal': '보통', 'low': '낮음' }; + return labels[priority] || priority; +} + +function getEquipmentStatusLabel(status) { + const labels = { + 'active': '정상', + 'inactive': '비활성', + 'repair_needed': '수리필요', + 'under_repair': '수리중', + 'disposed': '폐기' + }; + return labels[status] || status; +} + +function getTbmStatusLabel(status) { + const labels = { 'draft': '작성중', 'in_progress': '진행중', 'completed': '완료' }; + return labels[status] || status; +} + +function formatDateTime(dateStr) { + if (!dateStr) return ''; + const date = new Date(dateStr); + return date.toLocaleString('ko-KR', { month: 'numeric', day: 'numeric', hour: '2-digit', minute: '2-digit' }); +} diff --git a/deploy/tkfb-package/web-ui/js/daily-work-report.js b/deploy/tkfb-package/web-ui/js/daily-work-report.js new file mode 100644 index 0000000..836f133 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-work-report.js @@ -0,0 +1,4106 @@ +// daily-work-report.js - 브라우저 호환 버전 + +// ================================================================= +// 🌐 API 설정 (window 객체에서 가져오기) +// ================================================================= +// API 설정은 api-config.js에서 window 객체에 설정됨 + +// 전역 변수 +let workTypes = []; +let workStatusTypes = []; +let errorTypes = []; // 레거시 호환용 +let issueCategories = []; // 신고 카테고리 (nonconformity) +let issueItems = []; // 신고 아이템 +let workers = []; +let projects = []; +let selectedWorkers = new Set(); +let workEntryCounter = 0; +let currentStep = 1; +let editingWorkId = null; // 수정 중인 작업 ID +let incompleteTbms = []; // 미완료 TBM 작업 목록 +let currentTab = 'tbm'; // 현재 활성 탭 + +// 부적합 원인 관리 +let currentDefectIndex = null; // 현재 편집 중인 행 인덱스 +let tempDefects = {}; // 임시 부적합 원인 저장 { index: [{ error_type_id, defect_hours, note }] } + +// 작업장소 지도 관련 변수 +let mapCanvas = null; +let mapCtx = null; +let mapImage = null; +let mapRegions = []; +let selectedWorkplace = null; +let selectedWorkplaceName = null; +let selectedWorkplaceCategory = null; +let selectedWorkplaceCategoryName = null; + +// 시간 선택 관련 변수 +let currentEditingField = null; // { index, type: 'total' | 'error' } +let currentTimeValue = 0; + +// 당일 신고 리마인더 관련 변수 +let dailyIssuesCache = {}; // { 'YYYY-MM-DD': [issues] } - 날짜별 신고 캐시 + +// ================================================================= +// TBM 작업보고 관련 함수 +// ================================================================= + +/** + * 탭 전환 함수 + */ +window.switchTab = function(tab) { + currentTab = tab; + const tbmBtn = document.getElementById('tbmReportTab'); + const completedBtn = document.getElementById('completedReportTab'); + const tbmSection = document.getElementById('tbmReportSection'); + const completedSection = document.getElementById('completedReportSection'); + + // 모든 탭 버튼 비활성화 + tbmBtn.classList.remove('active'); + completedBtn.classList.remove('active'); + + // 모든 섹션 숨기기 + tbmSection.style.display = 'none'; + completedSection.style.display = 'none'; + + // 선택된 탭 활성화 + if (tab === 'tbm') { + tbmBtn.classList.add('active'); + tbmSection.style.display = 'block'; + loadIncompleteTbms(); // TBM 목록 로드 + } else if (tab === 'completed') { + completedBtn.classList.add('active'); + completedSection.style.display = 'block'; + + // 오늘 날짜로 초기화 + document.getElementById('completedReportDate').value = getKoreaToday(); + loadCompletedReports(); + } +}; + +/** + * 미완료 TBM 작업 로드 + */ +async function loadIncompleteTbms() { + try { + const response = await window.apiCall('/tbm/sessions/incomplete-reports'); + + if (!response.success) { + throw new Error(response.message || '미완료 TBM 조회 실패'); + } + + let data = response.data || []; + + // 사용자 권한 확인 및 필터링 + const user = getUser(); + if (user && user.role !== 'Admin' && user.access_level !== 'system') { + // 일반 사용자: 자신이 생성한 세션만 표시 + const userId = user.user_id; + data = data.filter(tbm => tbm.created_by === userId); + } + // 관리자는 모든 데이터 표시 + + incompleteTbms = data; + + // 각 세션 날짜에 대해 관련 신고 조회 + await loadDailyIssuesForTbms(); + + renderTbmWorkList(); + } catch (error) { + console.error('미완료 TBM 로드 오류:', error); + showMessage('TBM 작업 목록을 불러오는 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * TBM 세션들에 대한 당일 신고 조회 + * - 각 세션 날짜별로 관련 신고를 가져와서 캐시에 저장 + */ +async function loadDailyIssuesForTbms() { + if (!incompleteTbms || incompleteTbms.length === 0) { + console.log('[작업보고서] 미완료 TBM 없음, 신고 조회 건너뜀'); + return; + } + + console.log('[작업보고서] TBM 세션 수:', incompleteTbms.length); + + // 세션별로 고유한 날짜 + 작업장 조합 수집 + const sessionKeys = new Set(); + incompleteTbms.forEach(tbm => { + const dateStr = formatDateForApi(tbm.session_date); + console.log('[작업보고서] TBM 세션 날짜:', tbm.session_date, '→ 변환:', dateStr); + if (dateStr) { + // 날짜_작업장ID_프로젝트ID 형태로 키 생성 + const key = `${dateStr}_${tbm.workplace_id || 0}_${tbm.project_id || 0}`; + sessionKeys.add(key); + } + }); + + // 각 날짜에 대해 신고 조회 + const uniqueDates = [...new Set([...sessionKeys].map(k => k.split('_')[0]))]; + console.log('[작업보고서] 조회할 날짜들:', uniqueDates); + + for (const dateStr of uniqueDates) { + if (dailyIssuesCache[dateStr]) { + console.log(`[작업보고서] 캐시 사용 (${dateStr}):`, dailyIssuesCache[dateStr].length, '건'); + continue; + } + + try { + console.log(`[작업보고서] 신고 API 호출: /work-issues?start_date=${dateStr}&end_date=${dateStr}`); + const response = await window.apiCall(`/work-issues?start_date=${dateStr}&end_date=${dateStr}`); + if (response.success) { + dailyIssuesCache[dateStr] = response.data || []; + console.log(`[작업보고서] 신고 로드 완료 (${dateStr}):`, dailyIssuesCache[dateStr].length, '건'); + } else { + console.warn(`[작업보고서] 신고 API 실패:`, response); + dailyIssuesCache[dateStr] = []; + } + } catch (error) { + console.error(`[작업보고서] 신고 조회 오류 (${dateStr}):`, error); + dailyIssuesCache[dateStr] = []; + } + } + + console.log('[작업보고서] 전체 신고 캐시:', dailyIssuesCache); +} + +/** + * 특정 날짜의 모든 신고 반환 (작업장소 관계없이) + * - 참고용으로 해당 날짜에 발생한 모든 신고를 표시 + * @param {string} dateStr - 날짜 (YYYY-MM-DD) + * @param {number} workplaceId - 작업장소 ID (현재 미사용, 향후 하이라이트 용도) + * @param {number} projectId - 프로젝트 ID (현재 미사용) + * @returns {Array} 해당 날짜의 모든 신고 목록 + */ +function getRelatedIssues(dateStr, workplaceId, projectId) { + const issues = dailyIssuesCache[dateStr] || []; + + // 해당 날짜의 모든 신고를 반환 (작업장소 필터 제거) + // 사용자가 참고하여 관련 여부를 직접 판단하도록 함 + return issues; +} + +/** + * 날짜를 API 형식(YYYY-MM-DD)으로 변환 - 로컬 시간대 기준 + */ +function formatDateForApi(date) { + if (!date) return null; + + let dateObj; + if (date instanceof Date) { + dateObj = date; + } else if (typeof date === 'string') { + // 문자열인 경우 Date 객체로 변환 + dateObj = new Date(date); + } else { + return null; + } + + // 로컬 시간대 기준으로 날짜 추출 (UTC 변환 방지) + const year = dateObj.getFullYear(); + const month = String(dateObj.getMonth() + 1).padStart(2, '0'); + const day = String(dateObj.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; +} + +/** + * 사용자 정보 가져오기 (auth-check.js와 동일한 로직) + */ +function getUser() { + const user = localStorage.getItem('user'); + return user ? JSON.parse(user) : null; +} + +/** + * TBM 작업 목록 렌더링 (날짜별 > 세션별 그룹화) + * - 날짜별로 접기/펼치기 가능 + * - 날짜 헤더에 이슈 요약 표시 + */ +function renderTbmWorkList() { + const container = document.getElementById('tbmWorkList'); + + // 1단계: 날짜별로 그룹화 + const byDate = {}; + if (incompleteTbms && incompleteTbms.length > 0) { + incompleteTbms.forEach((tbm, index) => { + const dateStr = formatDateForApi(tbm.session_date); + if (!byDate[dateStr]) { + byDate[dateStr] = { + date: tbm.session_date, + sessions: {} + }; + } + // 2단계: 날짜 내에서 세션별로 그룹화 + const sessionKey = `${tbm.session_id}_${dateStr}`; + if (!byDate[dateStr].sessions[sessionKey]) { + byDate[dateStr].sessions[sessionKey] = { + session_id: tbm.session_id, + session_date: tbm.session_date, + created_by_name: tbm.created_by_name, + items: [] + }; + } + byDate[dateStr].sessions[sessionKey].items.push({ ...tbm, originalIndex: index }); + }); + } + + // 날짜 정렬 (최신순) + const sortedDates = Object.keys(byDate).sort((a, b) => new Date(b) - new Date(a)); + + // 레거시 호환: 기존 groupedTbms 구조도 유지 + const groupedTbms = {}; + sortedDates.forEach(dateStr => { + Object.assign(groupedTbms, byDate[dateStr].sessions); + }); + + let html = ` +
+

작업보고서 목록

+ +
+ `; + + // 수동 입력 섹션 먼저 추가 (맨 위) + html += ` +
+
+
+ 수동 입력 + TBM에 없는 작업을 추가로 입력할 수 있습니다 +
+ +
+
+ + + + + + + + + + + + + + + + + +
작업자날짜프로젝트공정작업작업장소작업시간부적합제출
+
+
+ `; + + // 날짜별로 테이블 생성 (접기/펼치기 가능) + sortedDates.forEach((dateStr, dateIndex) => { + const dateData = byDate[dateStr]; + const sessions = Object.values(dateData.sessions); + const totalWorkers = sessions.reduce((sum, s) => sum + s.items.length, 0); + + // 해당 날짜의 모든 신고 조회 + const relatedIssues = getRelatedIssues(dateStr); + const nonconformityCount = relatedIssues.filter(i => i.category_type === 'nonconformity').length; + const safetyCount = relatedIssues.filter(i => i.category_type === 'safety').length; + const hasIssues = relatedIssues.length > 0; + + // 요일 계산 + const dayNames = ['일', '월', '화', '수', '목', '금', '토']; + const dayOfWeek = dayNames[new Date(dateStr).getDay()]; + + // 오늘 날짜인지 확인 + const today = formatDateForApi(new Date()); + const isToday = dateStr === today; + + // 날짜 그룹 시작 (기본적으로 오늘만 펼침) + const isExpanded = isToday || dateIndex === 0; + + html += ` +
+
+
+ ${isExpanded ? '▼' : '▶'} + ${formatDate(dateData.date)} (${dayOfWeek}) + ${isToday ? '오늘' : ''} +
+
+ 세션 ${sessions.length}개 + 작업자 ${totalWorkers}명 +
+
+ ${hasIssues ? ` +
+ ${nonconformityCount > 0 ? `부적합 ${nonconformityCount}` : ''} + ${safetyCount > 0 ? `안전 ${safetyCount}` : ''} +
+ ` : '신고 없음'} +
+
+ +
+ `; + + // 신고 리마인더 HTML 생성 (날짜 그룹 내부) + if (hasIssues) { + html += ` +
+
+ ⚠️ + 당일 신고된 문제 + ${relatedIssues.length}건 +
+
+ ${relatedIssues.slice(0, 5).map(issue => { + // 아이템명과 추가설명 조합 + let itemText = issue.issue_item_name || ''; + if (issue.additional_description) { + itemText = itemText ? `${itemText} - ${issue.additional_description}` : issue.additional_description; + } + return ` +
+ ${issue.category_type === 'safety' ? '안전' : '부적합'} + ${issue.issue_category_name || ''} + ${itemText || '-'} + ${issue.workplace_name || issue.custom_location || ''} + ${getStatusLabel(issue.status)} +
+ `}).join('')} + ${relatedIssues.length > 5 ? `
외 ${relatedIssues.length - 5}건 더 있음
` : ''} +
+
+ 💡 위 문제로 인해 작업이 지연되었다면, 아래에서 부적합 시간을 추가해주세요. +
+
+ `; + } + + // 해당 날짜의 각 세션별로 테이블 생성 + sessions.forEach(group => { + const key = `${group.session_id}_${dateStr}`; + + html += ` +
+
+ TBM 세션 + 작성자: ${group.created_by_name} + ${group.items.length}명 +
+
+ + + + + + + + + + + + + + + ${group.items.map(tbm => { + const index = tbm.originalIndex; + // 이 작업자의 작업장소와 관련된 이슈가 있는지 확인 (부적합 버튼 강조용) + const hasRelatedIssue = relatedIssues.some(issue => { + if (issue.category_type !== 'nonconformity') return false; + // 작업장소 매칭 + if (tbm.workplace_id && issue.workplace_id) { + return tbm.workplace_id === issue.workplace_id; + } + if (tbm.workplace_name && (issue.workplace_name || issue.custom_location)) { + const issueLocation = issue.workplace_name || issue.custom_location || ''; + return issueLocation.includes(tbm.workplace_name) || tbm.workplace_name.includes(issueLocation); + } + return false; + }); + return ` + + + + + + + + + + + + + + `; + }).join('')} + +
작업자프로젝트공정작업작업장소작업시간부적합제출
+
+ ${tbm.worker_name || '작업자'} +
${tbm.job_type || '-'}
+
+
${tbm.project_name || '-'}${tbm.work_type_name || '-'}${tbm.task_name || '-'} +
+
${tbm.category_name || ''}
+
${tbm.workplace_name || '-'}
+
+
+ +
+ 시간 선택 +
+
+ + + + + +
+
+
+ +
+
+ `; + }); + + // 날짜 그룹 닫기 + html += ` +
+
+ `; + }); + + container.innerHTML = html; +} + +/** + * 날짜 그룹 접기/펼치기 토글 + */ +window.toggleDateGroup = function(dateStr) { + const group = document.querySelector(`.date-group[data-date="${dateStr}"]`); + if (!group) return; + + const content = group.querySelector('.date-group-content'); + const icon = group.querySelector('.date-toggle-icon'); + const isExpanded = group.classList.contains('expanded'); + + if (isExpanded) { + group.classList.remove('expanded'); + group.classList.add('collapsed'); + content.style.display = 'none'; + icon.textContent = '▶'; + } else { + group.classList.remove('collapsed'); + group.classList.add('expanded'); + content.style.display = 'block'; + icon.textContent = '▼'; + } +}; + +/** + * 부적합 시간 입력 처리 + */ +window.calculateRegularHours = function(index) { + const errorInput = document.getElementById(`errorHours_${index}`); + const errorTypeSelect = document.getElementById(`errorType_${index}`); + const errorTypeNone = document.getElementById(`errorTypeNone_${index}`); + + const errorHours = parseFloat(errorInput.value) || 0; + + // 부적합 시간이 있으면 원인 선택 표시 + if (errorHours > 0) { + errorTypeSelect.style.display = 'inline-block'; + if (errorTypeNone) errorTypeNone.style.display = 'none'; + } else { + errorTypeSelect.style.display = 'none'; + if (errorTypeNone) errorTypeNone.style.display = 'inline'; + } +}; + +/** + * TBM 작업보고서 제출 + */ +window.submitTbmWorkReport = async function(index) { + const tbm = incompleteTbms[index]; + + const totalHours = parseFloat(document.getElementById(`totalHours_${index}`).value); + const defects = tempDefects[index] || []; + + // 총 부적합 시간 계산 + const errorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0); + // item_id를 error_type_id로 사용 (issue_report_items.item_id) + const errorTypeId = defects.length > 0 ? (defects[0].error_type_id || defects[0].item_id || null) : null; + + // 필수 필드 검증 + if (!totalHours || totalHours <= 0) { + showMessage('작업시간을 입력해주세요.', 'error'); + return; + } + + if (errorHours > totalHours) { + showMessage('부적합 처리 시간은 총 작업시간을 초과할 수 없습니다.', 'error'); + return; + } + + // 부적합 원인 유효성 검사 (issue_report_id 또는 category_id 또는 error_type_id 필요) + console.log('🔍 부적합 검증 시작:', defects.map(d => ({ + defect_hours: d.defect_hours, + category_id: d.category_id, + item_id: d.item_id, + error_type_id: d.error_type_id, + issue_report_id: d.issue_report_id, + _saved: d._saved + }))); + + const invalidDefects = defects.filter(d => d.defect_hours > 0 && !d.error_type_id && !d.issue_report_id && !d.category_id && !d.item_id); + if (invalidDefects.length > 0) { + console.error('❌ 유효하지 않은 부적합:', invalidDefects); + showMessage('부적합 시간이 있는 항목은 원인을 선택해주세요.', 'error'); + return; + } + + // 날짜를 YYYY-MM-DD 형식으로 변환 + const reportDate = tbm.session_date instanceof Date + ? tbm.session_date.toISOString().split('T')[0] + : (typeof tbm.session_date === 'string' && tbm.session_date.includes('T') + ? tbm.session_date.split('T')[0] + : tbm.session_date); + + const reportData = { + tbm_assignment_id: tbm.assignment_id, + tbm_session_id: tbm.session_id, + worker_id: tbm.worker_id, + project_id: tbm.project_id, + work_type_id: tbm.task_id, // task_id를 work_type_id 컬럼에 저장 (직접 작업보고서와 일관성 유지) + report_date: reportDate, + start_time: null, + end_time: null, + total_hours: totalHours, + error_hours: errorHours, + error_type_id: errorTypeId, + work_status_id: errorHours > 0 ? 2 : 1 + }; + + console.log('🔍 TBM 제출 데이터:', JSON.stringify(reportData, null, 2)); + console.log('🔍 부적합 원인:', defects); + + try { + const response = await window.apiCall('/daily-work-reports/from-tbm', 'POST', reportData); + + if (!response.success) { + throw new Error(response.message || '작업보고서 제출 실패'); + } + + // 부적합 원인이 있으면 저장 (이슈 기반 또는 레거시) + if (defects.length > 0 && response.data?.report_id) { + const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0); + console.log('📋 부적합 원인 필터링:', { + 전체: defects.length, + 유효: validDefects.length, + validDefects: validDefects.map(d => ({ + category_id: d.category_id, + item_id: d.item_id, + defect_hours: d.defect_hours, + _saved: d._saved + })) + }); + + if (validDefects.length > 0) { + // 내부 플래그 제거 (백엔드 전송용) + const defectsToSend = validDefects.map(d => ({ + issue_report_id: d.issue_report_id || null, + category_id: d.category_id || null, + item_id: d.item_id || null, + error_type_id: d.error_type_id || null, + defect_hours: d.defect_hours, + note: d.note || '' + })); + + console.log('📤 부적합 저장 요청:', defectsToSend); + + const defectResponse = await window.apiCall(`/daily-work-reports/${response.data.report_id}/defects`, 'PUT', { + defects: defectsToSend + }); + + if (!defectResponse.success) { + console.error('❌ 부적합 저장 실패:', defectResponse); + showMessage('작업보고서는 저장되었으나 부적합 원인 저장에 실패했습니다.', 'warning'); + } else { + console.log('✅ 부적합 저장 성공:', defectResponse); + } + } else { + console.log('⚠️ 유효한 부적합 항목이 없어 저장 건너뜀'); + } + } + + showSaveResultModal( + 'success', + '작업보고서 제출 완료', + `${tbm.worker_name}의 작업보고서가 성공적으로 제출되었습니다.`, + response.data.tbm_completed ? + '모든 팀원의 작업보고서가 제출되어 TBM이 완료되었습니다.' : + response.data.completion_status + ); + + // 임시 부적합 데이터 삭제 + delete tempDefects[index]; + + // 목록 새로고침 + await loadIncompleteTbms(); + } catch (error) { + console.error('TBM 작업보고서 제출 오류:', error); + showSaveResultModal('error', '제출 실패', error.message); + } +}; + +/** + * TBM 세션 일괄제출 + */ +window.batchSubmitTbmSession = async function(sessionKey) { + // 해당 세션의 모든 항목 가져오기 + const sessionRows = document.querySelectorAll(`tr[data-session-key="${sessionKey}"]`); + + if (sessionRows.length === 0) { + showMessage('제출할 항목이 없습니다.', 'error'); + return; + } + + // 1단계: 모든 항목 검증 + const validationErrors = []; + const itemsToSubmit = []; + + sessionRows.forEach((row, rowIndex) => { + const index = parseInt(row.getAttribute('data-index')); + const tbm = incompleteTbms[index]; + + const totalHours = parseFloat(document.getElementById(`totalHours_${index}`)?.value); + const errorHours = parseFloat(document.getElementById(`errorHours_${index}`)?.value) || 0; + const errorTypeId = document.getElementById(`errorType_${index}`)?.value; + + // 검증 + if (!totalHours || totalHours <= 0) { + validationErrors.push(`${tbm.worker_name}: 작업시간 미입력`); + return; + } + + if (errorHours > totalHours) { + validationErrors.push(`${tbm.worker_name}: 부적합 시간이 총 작업시간 초과`); + return; + } + + if (errorHours > 0 && !errorTypeId) { + validationErrors.push(`${tbm.worker_name}: 부적합 원인 미선택`); + return; + } + + // 검증 통과한 항목 저장 + const reportDate = tbm.session_date instanceof Date + ? tbm.session_date.toISOString().split('T')[0] + : (typeof tbm.session_date === 'string' && tbm.session_date.includes('T') + ? tbm.session_date.split('T')[0] + : tbm.session_date); + + itemsToSubmit.push({ + index, + tbm, + data: { + tbm_assignment_id: tbm.assignment_id, + tbm_session_id: tbm.session_id, + worker_id: tbm.worker_id, + project_id: tbm.project_id, + work_type_id: tbm.task_id, // task_id를 work_type_id 컬럼에 저장 (일관성 유지) + report_date: reportDate, + start_time: null, + end_time: null, + total_hours: totalHours, + error_hours: errorHours, + error_type_id: errorTypeId || null, + work_status_id: errorHours > 0 ? 2 : 1 + } + }); + }); + + // 검증 실패가 하나라도 있으면 전체 중단 + if (validationErrors.length > 0) { + showSaveResultModal( + 'error', + '일괄제출 검증 실패', + '모든 항목이 유효해야 제출할 수 있습니다.', + validationErrors + ); + return; + } + + // 2단계: 모든 항목 제출 + const submitBtn = event.target; + submitBtn.disabled = true; + submitBtn.textContent = '제출 중...'; + + const results = { + success: [], + failed: [] + }; + + try { + for (const item of itemsToSubmit) { + try { + const response = await window.apiCall('/daily-work-reports/from-tbm', 'POST', item.data); + + if (response.success) { + results.success.push(item.tbm.worker_name); + } else { + results.failed.push(`${item.tbm.worker_name}: ${response.message}`); + } + } catch (error) { + results.failed.push(`${item.tbm.worker_name}: ${error.message}`); + } + } + + // 결과 표시 + const totalCount = itemsToSubmit.length; + const successCount = results.success.length; + const failedCount = results.failed.length; + + if (failedCount === 0) { + // 모두 성공 + showSaveResultModal( + 'success', + '일괄제출 완료', + `${totalCount}건의 작업보고서가 모두 성공적으로 제출되었습니다.`, + results.success.map(name => `✓ ${name}`) + ); + } else if (successCount === 0) { + // 모두 실패 + showSaveResultModal( + 'error', + '일괄제출 실패', + `${totalCount}건의 작업보고서가 모두 실패했습니다.`, + results.failed.map(msg => `✗ ${msg}`) + ); + } else { + // 일부 성공, 일부 실패 + const details = [ + ...results.success.map(name => `✓ ${name} - 성공`), + ...results.failed.map(msg => `✗ ${msg}`) + ]; + showSaveResultModal( + 'warning', + '일괄제출 부분 완료', + `성공: ${successCount}건 / 실패: ${failedCount}건`, + details + ); + } + + // 목록 새로고침 + await loadIncompleteTbms(); + } catch (error) { + console.error('일괄제출 오류:', error); + showSaveResultModal('error', '일괄제출 오류', error.message); + } finally { + submitBtn.disabled = false; + submitBtn.textContent = `📤 이 세션 일괄제출 (${sessionRows.length}건)`; + } +}; + +/** + * 수동 작업 추가 + */ +window.addManualWorkRow = function() { + const tbody = document.getElementById('manualWorkTableBody'); + if (!tbody) { + showMessage('수동 입력 테이블을 찾을 수 없습니다.', 'error'); + return; + } + + const manualIndex = `manual_${workEntryCounter++}`; + + const newRow = document.createElement('tr'); + newRow.setAttribute('data-index', manualIndex); + newRow.setAttribute('data-type', 'manual'); + + newRow.innerHTML = ` + + + + + + + + + + + + + + + + + + +
+
+ 🗺️ + 작업장소 +
+
+ 클릭하여 선택 +
+
+ + + +
+ 시간 선택 +
+ + + + + + + + + + + `; + + tbody.appendChild(newRow); + + // 부적합 인라인 영역 행 추가 + const defectRow = document.createElement('tr'); + defectRow.className = 'defect-row'; + defectRow.id = `defectRow_${manualIndex}`; + defectRow.style.display = 'none'; + defectRow.innerHTML = ` + +
+
+ +
+ +
+ + `; + tbody.appendChild(defectRow); + + showMessage('새 작업 행이 추가되었습니다. 정보를 입력하고 제출하세요.', 'info'); +}; + +/** + * 수동 작업 행 제거 + */ +window.removeManualWorkRow = function(manualIndex) { + const row = document.querySelector(`tr[data-index="${manualIndex}"]`); + const defectRow = document.getElementById(`defectRow_${manualIndex}`); + if (row) { + row.remove(); + } + if (defectRow) { + defectRow.remove(); + } + // 임시 부적합 데이터도 삭제 + delete tempDefects[manualIndex]; +}; + +/** + * 공정 선택 시 작업 목록 로드 + */ +window.loadTasksForWorkType = async function(manualIndex) { + const workTypeId = document.getElementById(`workType_${manualIndex}`).value; + const taskSelect = document.getElementById(`task_${manualIndex}`); + + if (!workTypeId) { + taskSelect.disabled = true; + taskSelect.innerHTML = ''; + return; + } + + try { + // 해당 공정의 작업 목록 조회 + const response = await window.apiCall(`/tasks?work_type_id=${workTypeId}`); + const tasks = response.success ? response.data : (Array.isArray(response) ? response : []); + + if (tasks && tasks.length > 0) { + taskSelect.disabled = false; + taskSelect.innerHTML = ` + + ${tasks.map(task => ``).join('')} + `; + } else { + taskSelect.disabled = true; + taskSelect.innerHTML = ''; + } + } catch (error) { + console.error('작업 목록 로드 오류:', error); + taskSelect.disabled = true; + taskSelect.innerHTML = ''; + } +}; + +/** + * 수동 입력 부적합 시간 토글 + */ +window.toggleManualErrorType = function(manualIndex) { + const errorInput = document.getElementById(`errorHours_${manualIndex}`); + const errorTypeSelect = document.getElementById(`errorType_${manualIndex}`); + const errorTypeNone = document.getElementById(`errorTypeNone_${manualIndex}`); + + const errorHours = parseFloat(errorInput.value) || 0; + + if (errorHours > 0) { + errorTypeSelect.style.display = 'inline-block'; + if (errorTypeNone) errorTypeNone.style.display = 'none'; + } else { + errorTypeSelect.style.display = 'none'; + if (errorTypeNone) errorTypeNone.style.display = 'inline'; + } +}; + +/** + * 수동 입력용 작업장소 선택 모달 열기 + */ +window.openWorkplaceMapForManual = async function(manualIndex) { + window.currentManualIndex = manualIndex; + + // 변수 초기화 + selectedWorkplace = null; + selectedWorkplaceName = null; + selectedWorkplaceCategory = null; + selectedWorkplaceCategoryName = null; + + try { + // 작업장소 카테고리 로드 + const categoriesResponse = await window.apiCall('/workplaces/categories'); + const categories = categoriesResponse.success ? categoriesResponse.data : categoriesResponse; + + // 작업장소 모달 표시 + const modal = document.getElementById('workplaceModal'); + const categoryList = document.getElementById('workplaceCategoryList'); + + categoryList.innerHTML = categories.map(cat => { + const safeId = parseInt(cat.category_id) || 0; + const safeName = escapeHtml(cat.category_name); + const safeImage = escapeHtml(cat.layout_image || ''); + return ` + + `; + }).join('') + ` + + `; + + // 카테고리 선택 화면 표시 + document.getElementById('categorySelectionArea').style.display = 'block'; + document.getElementById('workplaceSelectionArea').style.display = 'none'; + + modal.style.display = 'flex'; + } catch (error) { + console.error('작업장소 카테고리 로드 오류:', error); + showMessage('작업장소 목록을 불러오는 중 오류가 발생했습니다.', 'error'); + } +}; + +/** + * 작업장소 카테고리 선택 + */ +window.selectWorkplaceCategory = async function(categoryId, categoryName, layoutImage) { + selectedWorkplaceCategory = categoryId; + selectedWorkplaceCategoryName = categoryName; + + try { + // 타이틀 업데이트 + document.getElementById('selectedCategoryTitle').textContent = `${categoryName} - 작업장 선택`; + + // 카테고리 화면 숨기고 작업장 선택 화면 표시 + document.getElementById('categorySelectionArea').style.display = 'none'; + document.getElementById('workplaceSelectionArea').style.display = 'block'; + + // 해당 카테고리의 작업장소 로드 + const workplacesResponse = await window.apiCall(`/workplaces?category_id=${categoryId}`); + const workplaces = workplacesResponse.success ? workplacesResponse.data : workplacesResponse; + + // 지도 또는 리스트 로드 + if (layoutImage && layoutImage !== '') { + // 지도가 있는 경우 - 지도 영역 표시 + await loadWorkplaceMap(categoryId, layoutImage, workplaces); + document.getElementById('layoutMapArea').style.display = 'block'; + } else { + // 지도가 없는 경우 - 리스트만 표시 + document.getElementById('layoutMapArea').style.display = 'none'; + } + + // 리스트 항상 표시 + const workplaceListArea = document.getElementById('workplaceListArea'); + workplaceListArea.innerHTML = workplaces.map(wp => { + const safeId = parseInt(wp.workplace_id) || 0; + const safeName = escapeHtml(wp.workplace_name); + return ` + + `; + }).join(''); + + } catch (error) { + console.error('작업장소 로드 오류:', error); + showMessage('작업장소를 불러오는 중 오류가 발생했습니다.', 'error'); + } +}; + +/** + * 작업장소 지도 로드 + */ +async function loadWorkplaceMap(categoryId, layoutImagePath, workplaces) { + try { + mapCanvas = document.getElementById('workplaceMapCanvas'); + if (!mapCanvas) return; + + mapCtx = mapCanvas.getContext('2d'); + + // 이미지 URL 생성 + const baseUrl = window.API_BASE_URL || 'http://localhost:20005'; + const apiBaseUrl = baseUrl.replace('/api', ''); // /api 제거 + const fullImageUrl = layoutImagePath.startsWith('http') + ? layoutImagePath + : `${apiBaseUrl}${layoutImagePath}`; + + console.log('🖼️ 이미지 로드 시도:', fullImageUrl); + + // 지도 영역 데이터 로드 + const regionsResponse = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`); + if (regionsResponse && regionsResponse.success) { + mapRegions = regionsResponse.data || []; + } else { + mapRegions = []; + } + + // 이미지 로드 + mapImage = new Image(); + mapImage.crossOrigin = 'anonymous'; + + mapImage.onload = function() { + // 캔버스 크기 설정 (최대 너비 800px) + const maxWidth = 800; + const scale = mapImage.width > maxWidth ? maxWidth / mapImage.width : 1; + + mapCanvas.width = mapImage.width * scale; + mapCanvas.height = mapImage.height * scale; + + // 이미지와 영역 그리기 + drawWorkplaceMap(); + + // 클릭 이벤트 리스너 추가 + mapCanvas.onclick = handleMapClick; + + console.log(`✅ 작업장 지도 로드 완료: ${mapRegions.length}개 영역`); + }; + + mapImage.onerror = function() { + console.error('❌ 지도 이미지 로드 실패'); + document.getElementById('layoutMapArea').style.display = 'none'; + showMessage('지도를 불러올 수 없어 리스트로 표시합니다.', 'warning'); + }; + + mapImage.src = fullImageUrl; + + } catch (error) { + console.error('❌ 작업장 지도 로드 오류:', error); + document.getElementById('layoutMapArea').style.display = 'none'; + } +} + +/** + * 지도 그리기 + */ +function drawWorkplaceMap() { + if (!mapCanvas || !mapCtx || !mapImage) return; + + // 이미지 그리기 + mapCtx.drawImage(mapImage, 0, 0, mapCanvas.width, mapCanvas.height); + + // 각 영역 그리기 + mapRegions.forEach((region) => { + // 퍼센트를 픽셀로 변환 + const x1 = (region.x_start / 100) * mapCanvas.width; + const y1 = (region.y_start / 100) * mapCanvas.height; + const x2 = (region.x_end / 100) * mapCanvas.width; + const y2 = (region.y_end / 100) * mapCanvas.height; + + const width = x2 - x1; + const height = y2 - y1; + + // 선택된 영역인지 확인 + const isSelected = region.workplace_id === selectedWorkplace; + + // 영역 테두리 + mapCtx.strokeStyle = isSelected ? '#3b82f6' : '#10b981'; + mapCtx.lineWidth = isSelected ? 4 : 2; + mapCtx.strokeRect(x1, y1, width, height); + + // 영역 배경 (반투명) + mapCtx.fillStyle = isSelected ? 'rgba(59, 130, 246, 0.25)' : 'rgba(16, 185, 129, 0.15)'; + mapCtx.fillRect(x1, y1, width, height); + + // 작업장 이름 표시 + if (region.workplace_name) { + mapCtx.font = 'bold 14px sans-serif'; + + // 텍스트 배경 + const textMetrics = mapCtx.measureText(region.workplace_name); + const textPadding = 6; + mapCtx.fillStyle = isSelected ? 'rgba(59, 130, 246, 0.95)' : 'rgba(16, 185, 129, 0.95)'; + mapCtx.fillRect(x1 + 5, y1 + 5, textMetrics.width + textPadding * 2, 24); + + // 텍스트 + mapCtx.fillStyle = '#ffffff'; + mapCtx.fillText(region.workplace_name, x1 + 5 + textPadding, y1 + 22); + } + }); +} + +/** + * 지도 클릭 이벤트 처리 + */ +function handleMapClick(event) { + if (!mapCanvas || mapRegions.length === 0) return; + + const rect = mapCanvas.getBoundingClientRect(); + const x = event.clientX - rect.left; + const y = event.clientY - rect.top; + + // 클릭한 위치에 있는 영역 찾기 + for (let i = mapRegions.length - 1; i >= 0; i--) { + const region = mapRegions[i]; + const x1 = (region.x_start / 100) * mapCanvas.width; + const y1 = (region.y_start / 100) * mapCanvas.height; + const x2 = (region.x_end / 100) * mapCanvas.width; + const y2 = (region.y_end / 100) * mapCanvas.height; + + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { + // 영역 클릭됨 + selectWorkplaceFromList(region.workplace_id, region.workplace_name); + return; + } + } +} + +/** + * 리스트에서 작업장소 선택 + */ +window.selectWorkplaceFromList = function(workplaceId, workplaceName) { + selectedWorkplace = workplaceId; + selectedWorkplaceName = workplaceName; + + // 지도 다시 그리기 (선택 효과 표시) + if (mapCanvas && mapCtx && mapImage) { + drawWorkplaceMap(); + } + + // 리스트 버튼 업데이트 + document.querySelectorAll('[id^="workplace-"]').forEach(btn => { + if (btn.id === `workplace-${workplaceId}`) { + btn.classList.remove('btn-secondary'); + btn.classList.add('btn-primary'); + } else { + btn.classList.remove('btn-primary'); + btn.classList.add('btn-secondary'); + } + }); + + // 선택 완료 버튼 활성화 + document.getElementById('confirmWorkplaceBtn').disabled = false; +}; + +/** + * 작업장소 선택 완료 + */ +window.confirmWorkplaceSelection = function() { + const manualIndex = window.currentManualIndex; + + if (!selectedWorkplace || !selectedWorkplaceCategory) { + showMessage('작업장소를 선택해주세요.', 'error'); + return; + } + + document.getElementById(`workplaceCategory_${manualIndex}`).value = selectedWorkplaceCategory; + document.getElementById(`workplace_${manualIndex}`).value = selectedWorkplace; + + const displayDiv = document.getElementById(`workplaceDisplay_${manualIndex}`); + if (displayDiv) { + displayDiv.innerHTML = ` +
+ + 작업장소 선택됨 +
+
+
🏭 ${escapeHtml(selectedWorkplaceCategoryName)}
+
📍 ${escapeHtml(selectedWorkplaceName)}
+
+ `; + displayDiv.style.background = '#ecfdf5'; + displayDiv.style.borderColor = '#10b981'; + } + + // 모달 닫기 + closeWorkplaceModal(); + showMessage('작업장소가 선택되었습니다.', 'success'); +}; + +/** + * 작업장소 모달 닫기 + */ +window.closeWorkplaceModal = function() { + document.getElementById('workplaceModal').style.display = 'none'; + + // 초기화 + selectedWorkplace = null; + selectedWorkplaceName = null; + mapCanvas = null; + mapCtx = null; + mapImage = null; + mapRegions = []; +}; + +/** + * 외부 작업장소 선택 (외근/연차/휴무 등) + */ +window.selectExternalWorkplace = function() { + const manualIndex = window.currentManualIndex; + + // 외부 작업장소 ID는 0 또는 특별한 값으로 설정 (DB에 저장시 처리 필요) + const externalCategoryId = 0; + const externalCategoryName = '외부'; + const externalWorkplaceId = 0; + const externalWorkplaceName = '외부 (외근/연차/휴무)'; + + // hidden input에 값 설정 + document.getElementById(`workplaceCategory_${manualIndex}`).value = externalCategoryId; + document.getElementById(`workplace_${manualIndex}`).value = externalWorkplaceId; + + // 선택 결과 표시 + const displayDiv = document.getElementById(`workplaceDisplay_${manualIndex}`); + if (displayDiv) { + displayDiv.innerHTML = ` +
+ + 외부 선택됨 +
+
+
🌐 ${escapeHtml(externalWorkplaceName)}
+
+ `; + displayDiv.style.background = '#f0f9ff'; + displayDiv.style.borderColor = '#0ea5e9'; + } + + // 모달 닫기 + document.getElementById('workplaceModal').style.display = 'none'; + showMessage('외부 작업장소가 선택되었습니다.', 'success'); +}; + +/** + * 수동 작업보고서 제출 + */ +window.submitManualWorkReport = async function(manualIndex) { + const workerId = document.getElementById(`worker_${manualIndex}`).value; + const reportDate = document.getElementById(`date_${manualIndex}`).value; + const projectId = document.getElementById(`project_${manualIndex}`).value; + const workTypeId = document.getElementById(`workType_${manualIndex}`).value; + const taskId = document.getElementById(`task_${manualIndex}`).value; + const workplaceCategoryId = document.getElementById(`workplaceCategory_${manualIndex}`).value; + const workplaceId = document.getElementById(`workplace_${manualIndex}`).value; + const totalHours = parseFloat(document.getElementById(`totalHours_${manualIndex}`).value); + + // 부적합 원인 가져오기 + const defects = tempDefects[manualIndex] || []; + const errorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0); + // item_id를 error_type_id로 사용 (issue_report_items.item_id) + const errorTypeId = defects.length > 0 ? (defects[0].error_type_id || defects[0].item_id || null) : null; + + // 필수 필드 검증 + if (!workerId) { + showMessage('작업자를 선택해주세요.', 'error'); + return; + } + if (!reportDate) { + showMessage('작업 날짜를 입력해주세요.', 'error'); + return; + } + if (!projectId) { + showMessage('프로젝트를 선택해주세요.', 'error'); + return; + } + if (!workTypeId) { + showMessage('공정을 선택해주세요.', 'error'); + return; + } + if (!taskId) { + showMessage('작업을 선택해주세요.', 'error'); + return; + } + if (workplaceId === '' || workplaceId === null || workplaceId === undefined) { + showMessage('작업장소를 선택해주세요.', 'error'); + return; + } + if (!totalHours || totalHours <= 0) { + showMessage('작업시간을 입력해주세요.', 'error'); + return; + } + + if (errorHours > totalHours) { + showMessage('부적합 처리 시간은 총 작업시간을 초과할 수 없습니다.', 'error'); + return; + } + + // 부적합 원인 유효성 검사 (issue_report_id 또는 error_type_id 필요) + const invalidDefects = defects.filter(d => d.defect_hours > 0 && !d.error_type_id && !d.issue_report_id && !d.category_id && !d.item_id); + if (invalidDefects.length > 0) { + showMessage('부적합 시간이 있는 항목은 원인을 선택해주세요.', 'error'); + return; + } + + // 서비스 레이어가 기대하는 형식으로 변환 + // 주의: 서비스에서 task_id를 work_type_id 컬럼에 매핑함 + const reportData = { + report_date: reportDate, + worker_id: parseInt(workerId), + work_entries: [{ + project_id: parseInt(projectId), + task_id: parseInt(taskId), // 서비스에서 work_type_id로 매핑됨 + work_hours: totalHours, + work_status_id: errorHours > 0 ? 2 : 1, + error_type_id: errorTypeId ? parseInt(errorTypeId) : null + }] + }; + + try { + // 429 오류 재시도 로직 포함 + let response; + let retries = 3; + for (let i = 0; i < retries; i++) { + try { + response = await window.apiCall('/daily-work-reports', 'POST', reportData); + break; + } catch (err) { + if ((err.message?.includes('429') || err.message?.includes('너무 많은 요청')) && i < retries - 1) { + const waitTime = (i + 1) * 2000; + showMessage(`서버가 바쁩니다. ${waitTime/1000}초 후 재시도...`, 'loading'); + await new Promise(r => setTimeout(r, waitTime)); + continue; + } + throw err; + } + } + + if (!response.success) { + throw new Error(response.message || '작업보고서 제출 실패'); + } + + // 부적합 원인이 있으면 저장 (이슈 기반 또는 레거시) + const reportId = response.data?.inserted_ids?.[0] || response.data?.workReport_ids?.[0]; + if (defects.length > 0 && reportId) { + const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0); + if (validDefects.length > 0) { + await window.apiCall(`/daily-work-reports/${reportId}/defects`, 'PUT', { + defects: validDefects + }); + } + } + + // 행 제거 (부적합 임시 데이터도 함께 삭제됨) + removeManualWorkRow(manualIndex); + + showMessage('작업보고서가 제출되었습니다.', 'success'); + + // 남은 행이 없으면 완료 메시지 + const remainingRows = document.querySelectorAll('#manualWorkTableBody tr[data-index]'); + if (remainingRows.length === 0) { + showSaveResultModal( + 'success', + '작업보고서 제출 완료', + '모든 작업보고서가 성공적으로 제출되었습니다.' + ); + } + } catch (error) { + console.error('수동 작업보고서 제출 오류:', error); + showMessage('제출 실패: ' + error.message, 'error'); + } +}; + +/** + * 딜레이 함수 + */ +const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); + +/** + * API 호출 (429 재시도 포함) + */ +async function apiCallWithRetry(url, method, data, maxRetries = 3) { + for (let attempt = 1; attempt <= maxRetries; attempt++) { + try { + const response = await window.apiCall(url, method, data); + return response; + } catch (error) { + // 429 Rate Limit 오류인 경우 재시도 + if (error.message && error.message.includes('429') || error.message.includes('너무 많은 요청')) { + if (attempt < maxRetries) { + const waitTime = attempt * 2000; // 2초, 4초, 6초 대기 + console.log(`Rate limit 도달. ${waitTime/1000}초 후 재시도... (${attempt}/${maxRetries})`); + await delay(waitTime); + continue; + } + } + throw error; + } + } +} + +/** + * 수동 작업보고서 일괄 제출 + */ +window.submitAllManualWorkReports = async function() { + const rows = document.querySelectorAll('#manualWorkTableBody tr[data-index]'); + + if (rows.length === 0) { + showMessage('제출할 작업보고서가 없습니다.', 'error'); + return; + } + + // 확인 다이얼로그 + if (!confirm(`${rows.length}개의 작업보고서를 일괄 제출하시겠습니까?`)) { + return; + } + + let successCount = 0; + let failCount = 0; + const errors = []; + let currentIndex = 0; + + showMessage(`작업보고서 제출 중... (0/${rows.length})`, 'loading'); + + // 각 행을 순차적으로 제출 (딜레이 포함) + for (const row of rows) { + currentIndex++; + const manualIndex = row.dataset.index; + + // Rate Limit 방지를 위한 딜레이 (1초) + if (currentIndex > 1) { + await delay(1000); + } + + showMessage(`작업보고서 제출 중... (${currentIndex}/${rows.length})`, 'loading'); + + try { + const workerId = document.getElementById(`worker_${manualIndex}`).value; + const reportDate = document.getElementById(`date_${manualIndex}`).value; + const projectId = document.getElementById(`project_${manualIndex}`).value; + const workTypeId = document.getElementById(`workType_${manualIndex}`).value; + const taskId = document.getElementById(`task_${manualIndex}`).value; + const workplaceCategoryId = document.getElementById(`workplaceCategory_${manualIndex}`).value; + const workplaceId = document.getElementById(`workplace_${manualIndex}`).value; + const totalHours = parseFloat(document.getElementById(`totalHours_${manualIndex}`).value); + + // 부적합 원인 가져오기 + const defects = tempDefects[manualIndex] || []; + const errorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0); + // item_id를 error_type_id로 사용 (issue_report_items.item_id) + const errorTypeId = defects.length > 0 ? (defects[0].error_type_id || defects[0].item_id || null) : null; + + // 필수 필드 검증 + if (!workerId || !reportDate || !projectId || !workTypeId || !taskId || !totalHours || totalHours <= 0) { + errors.push(`행 ${manualIndex}: 필수 항목 누락`); + failCount++; + continue; + } + + if (workplaceId === '' || workplaceId === null || workplaceId === undefined) { + errors.push(`행 ${manualIndex}: 작업장소 미선택`); + failCount++; + continue; + } + + // 서비스 레이어가 기대하는 형식으로 변환 + const reportData = { + report_date: reportDate, + worker_id: parseInt(workerId), + work_entries: [{ + project_id: parseInt(projectId), + task_id: parseInt(taskId), + work_hours: totalHours, + work_status_id: errorHours > 0 ? 2 : 1, + error_type_id: errorTypeId ? parseInt(errorTypeId) : null + }] + }; + + const response = await apiCallWithRetry('/daily-work-reports', 'POST', reportData); + + if (!response.success) { + throw new Error(response.message || '작업보고서 제출 실패'); + } + + // 부적합 원인이 있으면 저장 + const reportId = response.data?.inserted_ids?.[0] || response.data?.workReport_ids?.[0]; + if (defects.length > 0 && reportId) { + const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0); + if (validDefects.length > 0) { + await apiCallWithRetry(`/daily-work-reports/${reportId}/defects`, 'PUT', { + defects: validDefects + }); + } + } + + // 성공 - 행 제거 + removeManualWorkRow(manualIndex); + successCount++; + + } catch (error) { + console.error(`행 ${manualIndex} 제출 오류:`, error); + errors.push(`행 ${manualIndex}: ${error.message}`); + failCount++; + } + } + + // 로딩 메시지 숨기기 + hideMessage(); + + // 결과 표시 + let resultMessage = `성공: ${successCount}건`; + if (failCount > 0) { + resultMessage += `, 실패: ${failCount}건`; + } + + if (failCount > 0 && errors.length > 0) { + showSaveResultModal( + 'warning', + '일괄 제출 완료 (일부 실패)', + `${resultMessage}\n\n실패 원인:\n${errors.slice(0, 5).join('\n')}${errors.length > 5 ? `\n... 외 ${errors.length - 5}건` : ''}` + ); + } else { + showSaveResultModal( + 'success', + '일괄 제출 완료', + resultMessage + ); + } +}; + +/** + * 날짜 포맷 함수 + */ +function formatDate(dateString) { + if (!dateString) return ''; + const date = new Date(dateString); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +/** + * 신고 상태 라벨 반환 + */ +function getStatusLabel(status) { + const labels = { + 'reported': '신고됨', + 'received': '접수됨', + 'in_progress': '처리중', + 'completed': '완료', + 'closed': '종료' + }; + return labels[status] || status || '-'; +} + +/** + * 작성 완료된 작업보고서 로드 + */ +window.loadCompletedReports = async function() { + try { + const selectedDate = document.getElementById('completedReportDate').value; + if (!selectedDate) { + showMessage('날짜를 선택해주세요.', 'error'); + return; + } + + // 해당 날짜의 작업보고서 조회 + const response = await window.apiCall(`/daily-work-reports?date=${selectedDate}`); + + console.log('완료된 보고서 API 응답:', response); + + // API 응답이 배열인지 객체인지 확인 + let reports = []; + if (Array.isArray(response)) { + reports = response; + } else if (response.success && response.data) { + reports = Array.isArray(response.data) ? response.data : []; + } else if (response.data) { + reports = Array.isArray(response.data) ? response.data : []; + } + + renderCompletedReports(reports); + } catch (error) { + console.error('완료된 보고서 로드 오류:', error); + showMessage('작업보고서를 불러오는 중 오류가 발생했습니다.', 'error'); + } +}; + +/** + * 완료된 보고서 목록 렌더링 + */ +function renderCompletedReports(reports) { + const container = document.getElementById('completedReportsList'); + + if (!reports || reports.length === 0) { + container.innerHTML = '

작성된 작업보고서가 없습니다.

'; + return; + } + + const html = reports.map(report => ` +
+
+
+

${escapeHtml(report.worker_name || '작업자')}

+ ${report.tbm_session_id ? 'TBM 연동' : '수동 입력'} +
+ ${escapeHtml(formatDate(report.report_date))} +
+ +
+
+ 프로젝트: + ${escapeHtml(report.project_name || '-')} +
+
+ 공정: + ${escapeHtml(report.work_type_name || '-')} +
+
+ 작업: + ${escapeHtml(report.task_name || '-')} +
+
+ 작업시간: + ${parseFloat(report.total_hours || report.work_hours || 0)}시간 +
+ ${report.regular_hours !== undefined && report.regular_hours !== null ? ` +
+ 정규 시간: + ${parseFloat(report.regular_hours)}시간 +
+ ` : ''} + ${report.error_hours && report.error_hours > 0 ? ` +
+ 부적합 처리: + ${parseFloat(report.error_hours)}시간 +
+
+ 부적합 원인: + ${escapeHtml(report.error_type_name || '-')} +
+ ` : ''} +
+ 작성자: + ${escapeHtml(report.created_by_name || '-')} +
+ ${report.start_time && report.end_time ? ` +
+ 작업 시간: + ${escapeHtml(report.start_time)} ~ ${escapeHtml(report.end_time)} +
+ ` : ''} +
+
+ + +
+
+ `).join(''); + + container.innerHTML = html; +} + +/** + * 작업보고서 수정 모달 열기 + */ +window.openEditReportModal = function(report) { + // 수정 모달이 없으면 동적 생성 + let modal = document.getElementById('editReportModal'); + if (!modal) { + modal = document.createElement('div'); + modal.id = 'editReportModal'; + modal.className = 'modal-overlay'; + modal.style.cssText = 'display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; background-color: rgba(0, 0, 0, 0.5); z-index: 1003; align-items: center; justify-content: center;'; + modal.innerHTML = ` + + `; + document.body.appendChild(modal); + } + + // 폼에 데이터 채우기 + document.getElementById('editReportId').value = report.id; + document.getElementById('editWorkerName').value = report.worker_name || '작업자'; + document.getElementById('editProjectId').value = report.project_id || ''; + document.getElementById('editWorkHours').value = report.work_hours || report.total_hours || 0; + document.getElementById('editWorkStatusId').value = report.work_status_id || 1; + + // 공정 선택 후 작업 목록 로드 + const workTypeSelect = document.getElementById('editWorkTypeId'); + + // work_type_id가 실제로는 task_id를 저장하고 있으므로, task에서 work_type을 찾아야 함 + // 일단 task 기반으로 찾기 시도 + loadTasksForEdit().then(() => { + const taskSelect = document.getElementById('editTaskId'); + // work_type_id 컬럼에 저장된 값이 실제로는 task_id + if (report.work_type_id) { + taskSelect.value = report.work_type_id; + } + }); + + modal.style.display = 'flex'; +}; + +/** + * 수정 모달용 작업 목록 로드 + */ +window.loadTasksForEdit = async function() { + const workTypeId = document.getElementById('editWorkTypeId').value; + const taskSelect = document.getElementById('editTaskId'); + + if (!workTypeId) { + taskSelect.innerHTML = ''; + return; + } + + try { + const response = await window.apiCall(`/tasks?work_type_id=${workTypeId}`); + const tasks = response.data || response || []; + + taskSelect.innerHTML = '' + + tasks.map(t => ``).join(''); + } catch (error) { + console.error('작업 목록 로드 오류:', error); + taskSelect.innerHTML = ''; + } +}; + +/** + * 수정 모달 닫기 + */ +window.closeEditReportModal = function() { + const modal = document.getElementById('editReportModal'); + if (modal) { + modal.style.display = 'none'; + } +}; + +/** + * 수정된 보고서 저장 + */ +window.saveEditedReport = async function() { + const reportId = document.getElementById('editReportId').value; + const projectId = document.getElementById('editProjectId').value; + const taskId = document.getElementById('editTaskId').value; + const workHours = parseFloat(document.getElementById('editWorkHours').value); + const workStatusId = document.getElementById('editWorkStatusId').value; + + if (!projectId || !taskId || !workHours) { + showMessage('필수 항목을 모두 입력해주세요.', 'error'); + return; + } + + try { + const updateData = { + project_id: parseInt(projectId), + work_type_id: parseInt(taskId), // task_id가 work_type_id 컬럼에 저장됨 + work_hours: workHours, + work_status_id: parseInt(workStatusId) + }; + + const response = await window.apiCall(`/daily-work-reports/${reportId}`, 'PUT', updateData); + + if (response.success) { + showMessage('작업보고서가 수정되었습니다.', 'success'); + closeEditReportModal(); + loadCompletedReports(); // 목록 새로고침 + } else { + throw new Error(response.message || '수정 실패'); + } + } catch (error) { + console.error('작업보고서 수정 오류:', error); + showMessage('수정 실패: ' + error.message, 'error'); + } +}; + +/** + * 작업보고서 삭제 + */ +window.deleteWorkReport = async function(reportId) { + if (!confirm('이 작업보고서를 삭제하시겠습니까?')) { + return; + } + + try { + const response = await window.apiCall(`/daily-work-reports/${reportId}`, 'DELETE'); + + if (response.success) { + showMessage('작업보고서가 삭제되었습니다.', 'success'); + loadCompletedReports(); // 목록 새로고침 + } else { + throw new Error(response.message || '삭제 실패'); + } + } catch (error) { + console.error('작업보고서 삭제 오류:', error); + showMessage('삭제 실패: ' + error.message, 'error'); + } +}; + +// ================================================================= +// 기존 함수들 +// ================================================================= + +// 한국 시간 기준 오늘 날짜 가져오기 +function getKoreaToday() { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const day = String(today.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +// 현재 로그인한 사용자 정보 가져오기 +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + console.log('토큰에서 추출한 사용자 정보:', payload); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + + try { + const userInfo = localStorage.getItem('user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + if (userInfo) { + const parsed = JSON.parse(userInfo); + console.log('localStorage에서 가져온 사용자 정보:', parsed); + return parsed; + } + } catch (error) { + console.log('localStorage에서 사용자 정보 가져오기 실패:', error); + } + + return null; +} + +// 메시지 표시 +function showMessage(message, type = 'info') { + const container = document.getElementById('message-container'); + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => { + hideMessage(); + }, 5000); + } +} + +function hideMessage() { + document.getElementById('message-container').innerHTML = ''; +} + +// 저장 결과 모달 표시 +function showSaveResultModal(type, title, message, details = null) { + const modal = document.getElementById('saveResultModal'); + const titleElement = document.getElementById('resultModalTitle'); + const contentElement = document.getElementById('resultModalContent'); + + // 아이콘 설정 + let icon = ''; + switch (type) { + case 'success': + icon = '✅'; + break; + case 'error': + icon = '❌'; + break; + case 'warning': + icon = '⚠️'; + break; + default: + icon = 'ℹ️'; + } + + // 모달 내용 구성 + let content = ` +
${icon}
+

${title}

+

${message}

+ `; + + // 상세 정보가 있으면 추가 + if (details) { + if (Array.isArray(details) && details.length > 0) { + content += ` +
+

상세 정보:

+
    + ${details.map(detail => `
  • ${detail}
  • `).join('')} +
+
+ `; + } else if (typeof details === 'string') { + content += ` +
+

${details}

+
+ `; + } + } + + titleElement.textContent = '저장 결과'; + contentElement.innerHTML = content; + modal.style.display = 'flex'; + + // ESC 키로 닫기 + document.addEventListener('keydown', function (e) { + if (e.key === 'Escape') { + closeSaveResultModal(); + } + }); + + // 배경 클릭으로 닫기 + modal.addEventListener('click', function (e) { + if (e.target === modal) { + closeSaveResultModal(); + } + }); +} + +// 저장 결과 모달 닫기 +function closeSaveResultModal() { + const modal = document.getElementById('saveResultModal'); + modal.style.display = 'none'; + + // 이벤트 리스너 제거 + document.removeEventListener('keydown', closeSaveResultModal); +} + +// 전역에서 접근 가능하도록 window에 할당 +window.closeSaveResultModal = closeSaveResultModal; + +// 단계 이동 +function goToStep(stepNumber) { + for (let i = 1; i <= 3; i++) { + const step = document.getElementById(`step${i}`); + if (step) { + step.classList.remove('active', 'completed'); + if (i < stepNumber) { + step.classList.add('completed'); + const stepNum = step.querySelector('.step-number'); + if (stepNum) stepNum.classList.add('completed'); + } else if (i === stepNumber) { + step.classList.add('active'); + } + } + } + + // 진행 단계 표시 업데이트 + updateProgressSteps(stepNumber); + + currentStep = stepNumber; +} + +// 진행 단계 표시 업데이트 +function updateProgressSteps(currentStepNumber) { + for (let i = 1; i <= 3; i++) { + const progressStep = document.getElementById(`progressStep${i}`); + if (progressStep) { + progressStep.classList.remove('active', 'completed'); + + if (i < currentStepNumber) { + progressStep.classList.add('completed'); + } else if (i === currentStepNumber) { + progressStep.classList.add('active'); + } + } + } +} + +// 초기 데이터 로드 (통합 API 사용) +async function loadData() { + try { + showMessage('데이터를 불러오는 중...', 'loading'); + + console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩 시작...'); + await loadWorkers(); + await loadProjects(); + await loadWorkTypes(); + await loadWorkStatusTypes(); + await loadErrorTypes(); + + console.log('로드된 작업자 수:', workers.length); + console.log('로드된 프로젝트 수:', projects.length); + console.log('작업 유형 수:', workTypes.length); + + hideMessage(); + + } catch (error) { + console.error('데이터 로드 실패:', error); + showMessage('데이터 로드 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +async function loadWorkers() { + try { + console.log('Workers API 호출 중... (통합 API 사용)'); + // 생산팀 소속 작업자만 조회 + const data = await window.apiCall(`/workers?limit=1000&department_id=1`); + const allWorkers = Array.isArray(data) ? data : (data.data || data.workers || []); + + // 작업 보고서에 표시할 작업자만 필터링 + // 퇴사자만 제외 (계정 여부와 무관하게 재직자는 모두 표시) + workers = allWorkers.filter(worker => { + const notResigned = worker.employment_status !== 'resigned'; + return notResigned; + }); + + console.log(`✅ Workers 로드 성공: ${workers.length}명 (전체: ${allWorkers.length}명)`); + console.log(`📊 필터링 조건: employment_status≠resigned (퇴사자만 제외)`); + } catch (error) { + console.error('작업자 로딩 오류:', error); + throw error; + } +} + +async function loadProjects() { + try { + console.log('Projects API 호출 중... (활성 프로젝트만)'); + const data = await window.apiCall(`/projects/active/list`); + projects = Array.isArray(data) ? data : (data.data || data.projects || []); + console.log('✅ 활성 프로젝트 로드 성공:', projects.length); + } catch (error) { + console.error('프로젝트 로딩 오류:', error); + throw error; + } +} + +async function loadWorkTypes() { + try { + const response = await window.apiCall(`/daily-work-reports/work-types`); + const data = response.data || response; + if (Array.isArray(data) && data.length > 0) { + workTypes = data; + console.log('✅ 작업 유형 API 사용 (통합 설정):', workTypes.length + '개'); + return; + } + throw new Error('API 실패'); + } catch (error) { + console.log('⚠️ 작업 유형 API 사용 불가, 기본값 사용:', error.message); + workTypes = [ + { id: 1, name: 'Base' }, + { id: 2, name: 'Vessel' }, + { id: 3, name: 'Piping' } + ]; + } +} + +async function loadWorkStatusTypes() { + try { + const response = await window.apiCall(`/daily-work-reports/work-status-types`); + const data = response.data || response; + if (Array.isArray(data) && data.length > 0) { + workStatusTypes = data; + console.log('✅ 업무 상태 유형 API 사용 (통합 설정):', workStatusTypes.length + '개'); + return; + } + throw new Error('API 실패'); + } catch (error) { + console.log('⚠️ 업무 상태 유형 API 사용 불가, 기본값 사용'); + workStatusTypes = [ + { id: 1, name: '정규' }, + { id: 2, name: '에러' } + ]; + } +} + +async function loadErrorTypes() { + // 레거시 에러 유형 로드 (호환성) + try { + const response = await window.apiCall(`/daily-work-reports/error-types`); + const data = response.data || response; + if (Array.isArray(data) && data.length > 0) { + errorTypes = data; + } + } catch (error) { + errorTypes = []; + } + + // 신고 카테고리 로드 (부적합 유형만) + try { + const catResponse = await window.apiCall('/work-issues/categories/type/nonconformity'); + if (catResponse && catResponse.success && Array.isArray(catResponse.data)) { + issueCategories = catResponse.data; + console.log(`✅ 부적합 카테고리 ${issueCategories.length}개 로드`); + + // 모든 아이템 로드 + const itemResponse = await window.apiCall('/work-issues/items'); + if (itemResponse && itemResponse.success && Array.isArray(itemResponse.data)) { + // 부적합 카테고리의 아이템만 필터링 + const categoryIds = issueCategories.map(c => c.category_id); + issueItems = itemResponse.data.filter(item => categoryIds.includes(item.category_id)); + console.log(`✅ 부적합 아이템 ${issueItems.length}개 로드`); + } + } + } catch (error) { + console.log('⚠️ 신고 카테고리 로드 실패:', error); + issueCategories = []; + issueItems = []; + } +} + +// TBM 팀 구성 자동 불러오기 +async function loadTbmTeamForDate(date) { + try { + console.log('🛠️ TBM 팀 구성 조회 중:', date); + const response = await window.apiCall(`/tbm/sessions/date/${date}`); + + if (response && response.success && response.data && response.data.length > 0) { + // 가장 최근 세션 선택 (진행중인 세션 우선) + const draftSessions = response.data.filter(s => s.status === 'draft'); + const targetSession = draftSessions.length > 0 ? draftSessions[0] : response.data[0]; + + if (targetSession) { + // 팀 구성 조회 + const teamRes = await window.apiCall(`/tbm/sessions/${targetSession.session_id}/team`); + if (teamRes && teamRes.success && teamRes.data) { + const teamWorkerIds = teamRes.data.map(m => m.worker_id); + console.log(`✅ TBM 팀 구성 로드 성공: ${teamWorkerIds.length}명`); + return teamWorkerIds; + } + } + } + + console.log('ℹ️ 해당 날짜의 TBM 팀 구성이 없습니다.'); + return []; + } catch (error) { + console.error('❌ TBM 팀 구성 조회 오류:', error); + return []; + } +} + +// 작업자 그리드 생성 +async function populateWorkerGrid() { + const grid = document.getElementById('workerGrid'); + grid.innerHTML = ''; + + // 선택된 날짜의 TBM 팀 구성 불러오기 + const reportDate = document.getElementById('reportDate').value; + let tbmWorkerIds = []; + + if (reportDate) { + tbmWorkerIds = await loadTbmTeamForDate(reportDate); + } + + // TBM 팀 구성이 있으면 안내 메시지 표시 + if (tbmWorkerIds.length > 0) { + const infoDiv = document.createElement('div'); + infoDiv.style.cssText = ` + padding: 1rem; + background: #eff6ff; + border: 1px solid #3b82f6; + border-radius: 0.5rem; + margin-bottom: 1rem; + color: #1e40af; + font-size: 0.875rem; + `; + infoDiv.innerHTML = ` + 🛠️ TBM 팀 구성 자동 적용
+ 오늘 TBM에서 구성된 팀원 ${tbmWorkerIds.length}명이 자동으로 선택되었습니다. + `; + grid.appendChild(infoDiv); + } + + workers.forEach(worker => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'worker-card'; + btn.textContent = worker.worker_name; + btn.dataset.id = worker.worker_id; + + // TBM 팀 구성에 포함된 작업자는 자동 선택 + if (tbmWorkerIds.includes(worker.worker_id)) { + btn.classList.add('selected'); + selectedWorkers.add(worker.worker_id); + } + + btn.addEventListener('click', () => { + toggleWorkerSelection(worker.worker_id, btn); + }); + + grid.appendChild(btn); + }); + + // 자동 선택된 작업자가 있으면 다음 단계 버튼 활성화 + const nextBtn = document.getElementById('nextStep2'); + if (nextBtn) { + nextBtn.disabled = selectedWorkers.size === 0; + } +} + +// 작업자 선택 토글 +function toggleWorkerSelection(workerId, btnElement) { + if (selectedWorkers.has(workerId)) { + selectedWorkers.delete(workerId); + btnElement.classList.remove('selected'); + } else { + selectedWorkers.add(workerId); + btnElement.classList.add('selected'); + } + + const nextBtn = document.getElementById('nextStep2'); + nextBtn.disabled = selectedWorkers.size === 0; +} + +// 작업 항목 추가 +function addWorkEntry() { + console.log('🔧 addWorkEntry 함수 호출됨'); + const container = document.getElementById('workEntriesList'); + console.log('🔧 컨테이너:', container); + workEntryCounter++; + console.log('🔧 작업 항목 카운터:', workEntryCounter); + + const entryDiv = document.createElement('div'); + entryDiv.className = 'work-entry'; + entryDiv.dataset.id = workEntryCounter; + console.log('🔧 생성된 작업 항목 div:', entryDiv); + + entryDiv.innerHTML = ` +
+
작업 항목 #${workEntryCounter}
+ +
+ +
+
+
+ 🏗️ + 프로젝트 +
+ +
+ +
+
+ ⚙️ + 작업 유형 +
+ +
+
+ +
+
+
+ 📊 + 업무 상태 +
+ +
+
+ +
+
+ ⚠️ + 에러 유형 +
+ +
+ +
+
+ + 작업 시간 (시간) +
+ +
+ + + + + +
+
+ `; + + container.appendChild(entryDiv); + console.log('🔧 작업 항목이 컨테이너에 추가됨'); + console.log('🔧 현재 컨테이너 내용:', container.innerHTML.length, '문자'); + console.log('🔧 현재 .work-entry 개수:', container.querySelectorAll('.work-entry').length); + + setupWorkEntryEvents(entryDiv); + console.log('🔧 이벤트 설정 완료'); +} + +// 작업 항목 이벤트 설정 +function setupWorkEntryEvents(entryDiv) { + const timeInput = entryDiv.querySelector('.time-input'); + const workStatusSelect = entryDiv.querySelector('.work-status-select'); + const errorTypeSection = entryDiv.querySelector('.error-type-section'); + const errorTypeSelect = entryDiv.querySelector('.error-type-select'); + + // 시간 입력 이벤트 + timeInput.addEventListener('input', updateTotalHours); + + // 빠른 시간 버튼 이벤트 + entryDiv.querySelectorAll('.quick-time-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + e.preventDefault(); + timeInput.value = btn.dataset.hours; + updateTotalHours(); + + // 버튼 클릭 효과 + btn.style.transform = 'scale(0.95)'; + setTimeout(() => { + btn.style.transform = ''; + }, 150); + }); + }); + + // 업무 상태 변경 시 에러 유형 섹션 토글 + workStatusSelect.addEventListener('change', (e) => { + const isError = e.target.value === '2'; // 에러 상태 ID가 2라고 가정 + + if (isError) { + errorTypeSection.classList.add('visible'); + errorTypeSelect.required = true; + + // 에러 상태일 때 시각적 피드백 + errorTypeSection.style.animation = 'slideDown 0.4s ease-out'; + } else { + errorTypeSection.classList.remove('visible'); + errorTypeSelect.required = false; + errorTypeSelect.value = ''; + } + }); + + // 폼 필드 포커스 효과 + entryDiv.querySelectorAll('.form-field-group').forEach(group => { + const input = group.querySelector('select, input'); + if (input) { + input.addEventListener('focus', () => { + group.classList.add('focused'); + }); + + input.addEventListener('blur', () => { + group.classList.remove('focused'); + }); + } + }); +} + +// 작업 항목 제거 +function removeWorkEntry(id) { + console.log('🗑️ removeWorkEntry 호출됨, id:', id); + const entry = document.querySelector(`.work-entry[data-id="${id}"]`); + console.log('🗑️ 찾은 entry:', entry); + if (entry) { + entry.remove(); + updateTotalHours(); + console.log('✅ 작업 항목 삭제 완료'); + } else { + console.log('❌ 작업 항목을 찾을 수 없음'); + } +} + +// 총 시간 업데이트 +function updateTotalHours() { + const timeInputs = document.querySelectorAll('.time-input'); + let total = 0; + + timeInputs.forEach(input => { + const value = parseFloat(input.value) || 0; + total += value; + }); + + const display = document.getElementById('totalHoursDisplay'); + display.textContent = `총 작업시간: ${total}시간`; + + if (total > 24) { + display.style.background = 'linear-gradient(135deg, #e74c3c 0%, #c0392b 100%)'; + display.textContent += ' ⚠️ 24시간 초과'; + } else { + display.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'; + } +} + +// 저장 함수 (통합 API 사용) +async function saveWorkReport() { + const reportDate = document.getElementById('reportDate').value; + + if (!reportDate || selectedWorkers.size === 0) { + showSaveResultModal( + 'error', + '입력 오류', + '날짜와 작업자를 선택해주세요.' + ); + return; + } + + const entries = document.querySelectorAll('.work-entry'); + console.log('🔍 찾은 작업 항목들:', entries); + console.log('🔍 작업 항목 개수:', entries.length); + + if (entries.length === 0) { + showSaveResultModal( + 'error', + '작업 항목 없음', + '최소 하나의 작업을 추가해주세요.' + ); + return; + } + + const newWorkEntries = []; + console.log('🔍 작업 항목 수집 시작...'); + + for (const entry of entries) { + console.log('🔍 작업 항목 처리 중:', entry); + + const projectSelect = entry.querySelector('.project-select'); + const workTypeSelect = entry.querySelector('.work-type-select'); + const workStatusSelect = entry.querySelector('.work-status-select'); + const errorTypeSelect = entry.querySelector('.error-type-select'); + const timeInput = entry.querySelector('.time-input'); + + console.log('🔍 선택된 요소들:', { + projectSelect, + workTypeSelect, + workStatusSelect, + errorTypeSelect, + timeInput + }); + + const projectId = projectSelect?.value; + const workTypeId = workTypeSelect?.value; + const workStatusId = workStatusSelect?.value; + const errorTypeId = errorTypeSelect?.value; + const workHours = timeInput?.value; + + console.log('🔍 수집된 값들:', { + projectId, + workTypeId, + workStatusId, + errorTypeId, + workHours + }); + + if (!projectId || !workTypeId || !workStatusId || !workHours) { + showSaveResultModal( + 'error', + '입력 오류', + '모든 작업 항목을 완성해주세요.' + ); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showSaveResultModal( + 'error', + '입력 오류', + '에러 상태인 경우 에러 유형을 선택해주세요.' + ); + return; + } + + const workEntry = { + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: errorTypeId ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours) + }; + + console.log('🔍 생성된 작업 항목:', workEntry); + console.log('🔍 작업 항목 상세:', { + project_id: workEntry.project_id, + work_type_id: workEntry.work_type_id, + work_status_id: workEntry.work_status_id, + error_type_id: workEntry.error_type_id, + work_hours: workEntry.work_hours + }); + newWorkEntries.push(workEntry); + } + + console.log('🔍 최종 수집된 작업 항목들:', newWorkEntries); + console.log('🔍 총 작업 항목 개수:', newWorkEntries.length); + + try { + const submitBtn = document.getElementById('submitBtn'); + submitBtn.disabled = true; + submitBtn.textContent = '💾 저장 중...'; + + const currentUser = getCurrentUser(); + let totalSaved = 0; + let totalFailed = 0; + const failureDetails = []; + + for (const workerId of selectedWorkers) { + const workerName = workers.find(w => w.worker_id == workerId)?.worker_name || '알 수 없음'; + + // 서버가 기대하는 work_entries 배열 형태로 전송 + const requestData = { + report_date: reportDate, + worker_id: parseInt(workerId), + work_entries: newWorkEntries.map(entry => ({ + project_id: entry.project_id, + task_id: entry.work_type_id, // 서버에서 task_id로 기대 + work_hours: entry.work_hours, + work_status_id: entry.work_status_id, + error_type_id: entry.error_type_id + })), + created_by: currentUser?.user_id || currentUser?.id + }; + + console.log('🔄 배열 형태로 전송:', requestData); + console.log('🔄 work_entries:', requestData.work_entries); + console.log('🔄 work_entries[0] 상세:', requestData.work_entries[0]); + console.log('🔄 전송 데이터 JSON:', JSON.stringify(requestData, null, 2)); + + try { + const result = await window.apiCall(`/daily-work-reports`, 'POST', requestData); + + console.log('✅ 저장 성공:', result); + totalSaved++; + } catch (error) { + console.error('❌ 저장 실패:', error); + totalFailed++; + + failureDetails.push(`${workerName}: ${error.message}`); + } + } + + // 결과 모달 표시 + if (totalSaved > 0 && totalFailed === 0) { + showSaveResultModal( + 'success', + '저장 완료!', + `${totalSaved}명의 작업보고서가 성공적으로 저장되었습니다.` + ); + } else if (totalSaved > 0 && totalFailed > 0) { + showSaveResultModal( + 'warning', + '부분 저장 완료', + `${totalSaved}명은 성공했지만 ${totalFailed}명은 실패했습니다.`, + failureDetails + ); + } else { + showSaveResultModal( + 'error', + '저장 실패', + '모든 작업보고서 저장이 실패했습니다.', + failureDetails + ); + } + + if (totalSaved > 0) { + setTimeout(() => { + refreshTodayWorkers(); + resetForm(); + }, 2000); + } + + } catch (error) { + console.error('저장 오류:', error); + showSaveResultModal( + 'error', + '저장 오류', + '저장 중 예기치 못한 오류가 발생했습니다.', + [error.message] + ); + } finally { + const submitBtn = document.getElementById('submitBtn'); + submitBtn.disabled = false; + submitBtn.textContent = '💾 작업보고서 저장'; + } +} + +// 폼 초기화 +function resetForm() { + goToStep(1); + + selectedWorkers.clear(); + document.querySelectorAll('.worker-card.selected').forEach(btn => { + btn.classList.remove('selected'); + }); + + const container = document.getElementById('workEntriesList'); + container.innerHTML = ''; + + workEntryCounter = 0; + updateTotalHours(); + + document.getElementById('nextStep2').disabled = true; +} + +// 당일 작업자 현황 로드 (본인 입력분만) - 통합 API 사용 +async function loadTodayWorkers() { + const section = document.getElementById('dailyWorkersSection'); + const content = document.getElementById('dailyWorkersContent'); + + if (!section || !content) { + console.log('당일 현황 섹션이 HTML에 없습니다.'); + return; + } + + try { + const today = getKoreaToday(); + const currentUser = getCurrentUser(); + + content.innerHTML = '
📊 내가 입력한 오늘의 작업 현황을 불러오는 중... (통합 API)
'; + section.style.display = 'block'; + + // 본인이 입력한 데이터만 조회 (통합 API 사용) + let queryParams = `date=${today}`; + if (currentUser?.user_id) { + queryParams += `&created_by=${currentUser.user_id}`; + } else if (currentUser?.id) { + queryParams += `&created_by=${currentUser.id}`; + } + + console.log(`🔒 본인 입력분만 조회 (통합 API): ${API}/daily-work-reports?${queryParams}`); + + const rawData = await window.apiCall(`/daily-work-reports?${queryParams}`); + console.log('📊 당일 작업 데이터 (통합 API):', rawData); + + let data = []; + if (Array.isArray(rawData)) { + data = rawData; + } else if (rawData?.data) { + data = rawData.data; + } + + displayMyDailyWorkers(data, today); + + } catch (error) { + console.error('당일 작업자 로드 오류:', error); + content.innerHTML = ` +
+ ❌ 오늘의 작업 현황을 불러올 수 없습니다.
+ ${error.message} +
+ `; + } +} + +// 본인 입력 작업자 현황 표시 (수정/삭제 기능 포함) +function displayMyDailyWorkers(data, date) { + const content = document.getElementById('dailyWorkersContent'); + + if (!Array.isArray(data) || data.length === 0) { + content.innerHTML = ` +
+ 📝 내가 오늘(${date}) 입력한 작업이 없습니다.
+ 새로운 작업을 추가해보세요! +
+ `; + return; + } + + // 작업자별로 데이터 그룹화 + const workerGroups = {}; + data.forEach(work => { + const workerName = work.worker_name || '미지정'; + if (!workerGroups[workerName]) { + workerGroups[workerName] = []; + } + workerGroups[workerName].push(work); + }); + + const totalWorkers = Object.keys(workerGroups).length; + const totalWorks = data.length; + + const headerHtml = ` +
+

📊 내가 입력한 오늘(${escapeHtml(date)}) 작업 현황 - 총 ${parseInt(totalWorkers) || 0}명, ${parseInt(totalWorks) || 0}개 작업

+ +
+ `; + + const workersHtml = Object.entries(workerGroups).map(([workerName, works]) => { + const totalHours = works.reduce((sum, work) => { + return sum + parseFloat(work.work_hours || 0); + }, 0); + + // 개별 작업 항목들 (수정/삭제 버튼 포함) + const individualWorksHtml = works.map((work) => { + const projectName = escapeHtml(work.project_name || '미지정'); + const workTypeName = escapeHtml(work.work_type_name || '미지정'); + const workStatusName = escapeHtml(work.work_status_name || '미지정'); + const workHours = parseFloat(work.work_hours || 0); + const errorTypeName = work.error_type_name ? escapeHtml(work.error_type_name) : null; + const workId = parseInt(work.id) || 0; + + return ` +
+
+
+
🏗️ 프로젝트
+
${projectName}
+
+
+
⚙️ 작업종류
+
${workTypeName}
+
+
+
📊 작업상태
+
${workStatusName}
+
+
+
⏰ 작업시간
+
${workHours}시간
+
+ ${errorTypeName ? ` +
+
❌ 에러유형
+
${errorTypeName}
+
+ ` : ''} +
+
+ + +
+
+ `; + }).join(''); + + return ` +
+
+
👤 ${escapeHtml(workerName)}
+
총 ${parseFloat(totalHours)}시간
+
+
+ ${individualWorksHtml} +
+
+ `; + }).join(''); + + content.innerHTML = headerHtml + '
' + workersHtml + '
'; +} + +// 작업 항목 수정 함수 (통합 API 사용) +async function editWorkItem(workId) { + try { + console.log('수정할 작업 ID:', workId); + + // 1. 기존 데이터 조회 (통합 API 사용) + showMessage('작업 정보를 불러오는 중... (통합 API)', 'loading'); + + const workData = await window.apiCall(`/daily-work-reports/${workId}`); + console.log('수정할 작업 데이터 (통합 API):', workData); + + // 2. 수정 모달 표시 + showEditModal(workData); + hideMessage(); + + } catch (error) { + console.error('작업 정보 조회 오류:', error); + showMessage('작업 정보를 불러올 수 없습니다: ' + error.message, 'error'); + } +} + +// 수정 모달 표시 +function showEditModal(workData) { + editingWorkId = workData.id; + + const modalHtml = ` +
+
+
+

✏️ 작업 수정

+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ `; + + document.body.insertAdjacentHTML('beforeend', modalHtml); + + // 업무 상태 변경 이벤트 + document.getElementById('editWorkStatus').addEventListener('change', (e) => { + const errorTypeGroup = document.getElementById('editErrorTypeGroup'); + if (e.target.value === '2') { + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + } + }); +} + +// 수정 모달 닫기 +function closeEditModal() { + const modal = document.getElementById('editModal'); + if (modal) { + modal.remove(); + } + editingWorkId = null; +} + +// 수정된 작업 저장 (통합 API 사용) +async function saveEditedWork() { + try { + const projectId = document.getElementById('editProject').value; + const workTypeId = document.getElementById('editWorkType').value; + const workStatusId = document.getElementById('editWorkStatus').value; + const errorTypeId = document.getElementById('editErrorType').value; + const workHours = document.getElementById('editWorkHours').value; + + if (!projectId || !workTypeId || !workStatusId || !workHours) { + showMessage('모든 필수 항목을 입력해주세요.', 'error'); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showMessage('에러 상태인 경우 에러 유형을 선택해주세요.', 'error'); + return; + } + + const updateData = { + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: errorTypeId ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours) + }; + + showMessage('작업을 수정하는 중... (통합 API)', 'loading'); + + const result = await window.apiCall(`/daily-work-reports/${editingWorkId}`, { + method: 'PUT', + body: JSON.stringify(updateData) + }); + + console.log('✅ 수정 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); + + closeEditModal(); + refreshTodayWorkers(); + + } catch (error) { + console.error('❌ 수정 실패:', error); + showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 작업 항목 삭제 함수 (통합 API 사용) +async function deleteWorkItem(workId) { + if (!confirm('정말로 이 작업을 삭제하시겠습니까?\n삭제된 작업은 복구할 수 없습니다.')) { + return; + } + + try { + console.log('삭제할 작업 ID:', workId); + + showMessage('작업을 삭제하는 중... (통합 API)', 'loading'); + + // 개별 항목 삭제 API 호출 (본인 작성분만 삭제 가능) - 통합 API 사용 + const result = await window.apiCall(`/daily-work-reports/my-entry/${workId}`, { + method: 'DELETE' + }); + + console.log('✅ 삭제 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); + + // 화면 새로고침 + refreshTodayWorkers(); + + } catch (error) { + console.error('❌ 삭제 실패:', error); + showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 오늘 현황 새로고침 +function refreshTodayWorkers() { + loadTodayWorkers(); +} + +// 이벤트 리스너 설정 (이제 테이블 기반 UI를 사용하므로 별도 리스너 불필요) +function setupEventListeners() { + // 기존 단계별 입력 UI 제거됨 + // 모든 이벤트는 onclick 핸들러로 직접 처리 +} + +// 초기화 +async function init() { + try { + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + showMessage('로그인이 필요합니다.', 'error'); + localStorage.removeItem('token'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + await loadData(); + setupEventListeners(); + + // TBM 작업 목록 로드 (기본 탭) + await loadIncompleteTbms(); + + console.log('✅ 시스템 초기화 완료 (통합 API 설정 적용)'); + + } catch (error) { + console.error('초기화 오류:', error); + showMessage('초기화 중 오류가 발생했습니다.', 'error'); + } +} + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', init); + +// 전역 함수로 노출 +window.removeWorkEntry = removeWorkEntry; +window.refreshTodayWorkers = refreshTodayWorkers; +window.editWorkItem = editWorkItem; +window.deleteWorkItem = deleteWorkItem; +window.closeEditModal = closeEditModal; +window.saveEditedWork = saveEditedWork; +// ================================================================= +// 시간 선택 팝오버 관련 함수 +// ================================================================= + +/** + * 시간 포맷팅 함수 + */ +function formatHours(hours) { + const h = Math.floor(hours); + const m = (hours % 1) * 60; + if (m === 0) return `${h}시간`; + return `${h}시간 ${m}분`; +} + +/** + * 시간 선택 팝오버 열기 + */ +window.openTimePicker = function(index, type) { + currentEditingField = { index, type }; + + // 현재 값 가져오기 + const inputId = type === 'total' ? `totalHours_${index}` : `errorHours_${index}`; + const hiddenInput = document.getElementById(inputId); + currentTimeValue = parseFloat(hiddenInput?.value) || 0; + + // 팝오버 표시 + const overlay = document.getElementById('timePickerOverlay'); + const title = document.getElementById('timePickerTitle'); + + title.textContent = type === 'total' ? '작업시간 선택' : '부적합 시간 선택'; + updateTimeDisplay(); + + overlay.style.display = 'flex'; + + // ESC 키로 닫기 + document.addEventListener('keydown', handleEscapeKey); +}; + +/** + * ESC 키 핸들러 + */ +function handleEscapeKey(e) { + if (e.key === 'Escape') { + closeTimePicker(); + } +} + +/** + * 시간 값 설정 + */ +window.setTimeValue = function(hours) { + currentTimeValue = hours; + updateTimeDisplay(); +}; + +/** + * 시간 조정 (±30분) + */ +window.adjustTime = function(delta) { + currentTimeValue = Math.max(0, Math.min(24, currentTimeValue + delta)); + updateTimeDisplay(); +}; + +/** + * 시간 표시 업데이트 + */ +function updateTimeDisplay() { + const display = document.getElementById('currentTimeDisplay'); + if (display) { + display.textContent = formatHours(currentTimeValue); + } +} + +/** + * 시간 선택 확인 + */ +window.confirmTimeSelection = function() { + if (!currentEditingField) return; + + const { index, type, defectIndex, issueReportId } = currentEditingField; + + // 이슈 기반 부적합 시간 선택인 경우 + if (type === 'issueDefect') { + if (tempDefects[index] && tempDefects[index][defectIndex] !== undefined) { + tempDefects[index][defectIndex].defect_hours = currentTimeValue; + + // 시간 표시 업데이트 + const timeDisplay = document.getElementById(`issueDefectTime_${index}_${issueReportId}`); + if (timeDisplay) { + timeDisplay.textContent = currentTimeValue; + } + + // 요약 및 hidden 필드 업데이트 + updateDefectSummary(index); + updateHiddenDefectFields(index); + } + closeTimePicker(); + return; + } + + // 레거시 부적합 시간 선택인 경우 + if (type === 'defect') { + if (tempDefects[index] && tempDefects[index][defectIndex] !== undefined) { + tempDefects[index][defectIndex].defect_hours = currentTimeValue; + + // 시간 표시 업데이트 + const timeDisplay = document.getElementById(`defectTime_${index}_${defectIndex}`); + if (timeDisplay) { + timeDisplay.textContent = currentTimeValue; + } + + // 요약 및 hidden 필드 업데이트 + updateDefectSummary(index); + updateHiddenDefectFields(index); + } + closeTimePicker(); + return; + } + + // 기존 total/error 시간 선택 + const inputId = type === 'total' ? `totalHours_${index}` : `errorHours_${index}`; + const displayId = type === 'total' ? `totalHoursDisplay_${index}` : `errorHoursDisplay_${index}`; + + // hidden input 값 설정 + const hiddenInput = document.getElementById(inputId); + if (hiddenInput) { + hiddenInput.value = currentTimeValue; + } + + // 표시 영역 업데이트 + const displayDiv = document.getElementById(displayId); + if (displayDiv) { + displayDiv.textContent = formatHours(currentTimeValue); + displayDiv.classList.remove('placeholder'); + displayDiv.classList.add('has-value'); + } + + // 부적합 시간 입력 시 에러 타입 토글 (기존 방식 - 이제 사용안함) + if (type === 'error') { + if (index.toString().startsWith('manual_')) { + toggleManualErrorType(index); + } else { + calculateRegularHours(index); + } + } + + closeTimePicker(); +}; + +/** + * 시간 선택 팝오버 닫기 + */ +window.closeTimePicker = function() { + const overlay = document.getElementById('timePickerOverlay'); + if (overlay) { + overlay.style.display = 'none'; + } + + currentEditingField = null; + currentTimeValue = 0; + + // ESC 키 리스너 제거 + document.removeEventListener('keydown', handleEscapeKey); +}; + +// ================================================================= +// 부적합 원인 관리 (인라인 방식) +// ================================================================= + +/** + * 부적합 영역 토글 + * - 신고된 이슈 목록 표시 + */ +window.toggleDefectArea = function(index) { + const defectRow = document.getElementById(`defectRow_${index}`); + if (!defectRow) return; + + const isVisible = defectRow.style.display !== 'none'; + + if (isVisible) { + // 숨기기 + defectRow.style.display = 'none'; + } else { + // 보이기 - 부적합 원인이 없으면 자동으로 하나 추가 + if (!tempDefects[index] || tempDefects[index].length === 0) { + tempDefects[index] = [{ + issue_report_id: null, + category_id: null, + item_id: null, + error_type_id: '', // 레거시 호환 + defect_hours: 0, + note: '' + }]; + } + renderInlineDefectList(index); + defectRow.style.display = ''; + } +}; + +/** + * 인라인 부적합 목록 렌더링 + * - 해당 날짜에 신고된 이슈 목록을 표시 + * - 이슈 선택 → 시간 입력 방식 + */ +function renderInlineDefectList(index) { + const listContainer = document.getElementById(`defectList_${index}`); + if (!listContainer) return; + + // 해당 TBM의 날짜 가져오기 + const tbm = incompleteTbms[index]; + const dateStr = tbm ? formatDateForApi(tbm.session_date) : null; + const issues = dateStr ? (dailyIssuesCache[dateStr] || []) : []; + + // 작업장소 정보 가져오기 + const workerWorkplaceId = tbm?.workplace_id; + const workerWorkplaceName = tbm?.workplace_name; + + // 부적합 유형 + 작업장소 일치하는 것만 필터링 + const nonconformityIssues = issues.filter(i => { + // 부적합 유형만 + if (i.category_type !== 'nonconformity') return false; + + // 작업장소 매칭 (workplace_id 우선, 없으면 이름 비교) + if (workerWorkplaceId && i.workplace_id) { + return i.workplace_id === workerWorkplaceId; + } + if (workerWorkplaceName && (i.workplace_name || i.custom_location)) { + const issueLocation = i.workplace_name || i.custom_location || ''; + return issueLocation.includes(workerWorkplaceName) || workerWorkplaceName.includes(issueLocation); + } + // 작업장소 정보가 없으면 포함하지 않음 + return false; + }); + + const defects = tempDefects[index] || []; + + console.log(`📝 [renderInlineDefectList] index=${index}, 부적합 수=${defects.length}`, defects); + + // 이슈가 있으면 이슈 선택 UI, 없으면 레거시 UI + if (nonconformityIssues.length > 0) { + // 이슈 선택 방식 UI + let html = ` +
+
+ 📋 ${escapeHtml(workerWorkplaceName || '작업장소')} 관련 부적합 + ${parseInt(nonconformityIssues.length) || 0}건 +
+
+ `; + + nonconformityIssues.forEach(issue => { + // 이 이슈가 이미 선택되었는지 확인 + const existingDefect = defects.find(d => d.issue_report_id == issue.report_id); + const isSelected = !!existingDefect; + const defectHours = existingDefect?.defect_hours || 0; + + // 아이템명과 추가설명 조합 + let itemText = issue.issue_item_name || ''; + if (issue.additional_description) { + itemText = itemText ? `${itemText} - ${issue.additional_description}` : issue.additional_description; + } + + const safeReportId = parseInt(issue.report_id) || 0; + html += ` +
+
+ +
+
+ ${escapeHtml(issue.issue_category_name || '부적합')} + ${escapeHtml(itemText || '-')} + ${escapeHtml(issue.workplace_name || issue.custom_location || '')} +
+
+
+ ${parseFloat(defectHours) || 0} + 시간 +
+
+
+ `; + }); + + html += ` +
+
+ `; + + // 레거시 방식도 추가 (기타 부적합 추가 버튼) + html += ` +
+
+ ${renderLegacyDefects(index, defects)} +
+
+ + +
+ +
+ `; + + listContainer.innerHTML = html; + } else { + // 이슈가 없으면 레거시 UI (error_types 선택) + const noIssueMsg = workerWorkplaceName + ? `${escapeHtml(workerWorkplaceName)}에 신고된 부적합이 없습니다.` + : '신고된 부적합이 없습니다.'; + listContainer.innerHTML = ` +
+ ${noIssueMsg} +
+
+ ${renderLegacyDefects(index, defects)} +
+
+ + +
+ + `; + } + + updateDefectSummary(index); +} + +/** + * 레거시 부적합 렌더링 (저장된 항목 + 입력 중인 항목 분리) + */ +function renderLegacyDefects(index, defects) { + // issue_report_id가 없는 직접 입력 부적합 + const legacyDefects = defects.filter(d => !d.issue_report_id); + + if (legacyDefects.length === 0) return ''; + + // 저장된 항목과 입력 중인 항목 분리 + const savedDefects = legacyDefects.filter(d => d._saved); + const editingDefects = legacyDefects.filter(d => !d._saved); + + let html = ''; + + // 저장된 부적합 표시 (위쪽) + if (savedDefects.length > 0) { + html += `
+
+ 저장된 부적합 + ${savedDefects.length}건 +
+
`; + + savedDefects.forEach(defect => { + const defectIndex = defects.indexOf(defect); + const categoryName = defect.category_id + ? (issueCategories.find(c => c.category_id == defect.category_id)?.category_name || '미분류') + : '미분류'; + const itemName = defect.item_id + ? (issueItems.find(i => i.item_id == defect.item_id)?.item_name || '') + : ''; + + const displayText = itemName + ? `${categoryName} → ${itemName}` + : categoryName; + + html += ` +
+
+ ${categoryName} + ${itemName}${defect.note ? ' - ' + defect.note : ''} +
+
+ ${defect.defect_hours || 0}시간 + + +
+
+ `; + }); + + html += `
`; + } + + // 입력 중인 부적합 표시 (아래쪽) + if (editingDefects.length > 0) { + html += `
`; + + editingDefects.forEach(defect => { + const defectIndex = defects.indexOf(defect); + html += renderDefectInputForm(index, defect, defectIndex); + }); + + html += `
`; + } + + return html; +} + +/** + * 부적합 입력 폼 렌더링 (단일 항목) + */ +function renderDefectInputForm(index, defect, defectIndex) { + // 대분류 (카테고리) 옵션 + const categoryOptions = issueCategories.map(cat => + `` + ).join(''); + + // 소분류 (아이템) 옵션 - 선택된 카테고리의 아이템만 + const filteredItems = defect.category_id + ? issueItems.filter(item => item.category_id == defect.category_id) + : []; + const itemOptions = filteredItems.map(item => + `` + ).join(''); + + // 카테고리명/아이템명 표시 (미리보기용) + const categoryName = defect.category_id + ? (issueCategories.find(c => c.category_id == defect.category_id)?.category_name || '') + : ''; + const itemName = defect.item_id + ? (issueItems.find(i => i.item_id == defect.item_id)?.item_name || '') + : ''; + + return ` +
+
+ +
+ +
+ +
+
+ + +
+ +
+ +
+
+ + +
+ +
+ ${defect.defect_hours || 0} + 시간 +
+
+ + + +
+ + +
+ +
+ + + ${(categoryName || itemName) ? ` +
+ + ${categoryName}${itemName ? ' → ' + itemName : ''}${defect.note ? ' → ' + defect.note : ''} + +
+ ` : ''} +
+ `; +} + +/** + * 대분류 선택 변경 + */ +window.onDefectCategoryChange = async function(index, defectIndex, value) { + if (!tempDefects[index] || !tempDefects[index][defectIndex]) return; + + const defect = tempDefects[index][defectIndex]; + + if (value === '__new__') { + // 새 카테고리 추가 모달 + const newName = prompt('새 대분류(카테고리) 이름을 입력하세요:'); + if (newName && newName.trim()) { + try { + const response = await window.apiCall('/work-issues/categories', 'POST', { + category_name: newName.trim(), + category_type: 'nonconformity', + severity: 'medium' + }); + + if (response.success) { + // 카테고리 목록 새로고침 + await loadErrorTypes(); + // 새로 생성된 카테고리 선택 + const newCat = issueCategories.find(c => c.category_name === newName.trim()); + if (newCat) { + defect.category_id = newCat.category_id; + defect.item_id = null; + } + } else { + alert('카테고리 추가 실패: ' + (response.error || '알 수 없는 오류')); + defect.category_id = null; + } + } catch (e) { + alert('카테고리 추가 중 오류: ' + e.message); + defect.category_id = null; + } + } else { + // 취소 시 이전 값 유지 + defect.category_id = defect.category_id || null; + } + } else if (value) { + defect.category_id = parseInt(value); + defect.item_id = null; // 카테고리 변경 시 소분류 초기화 + } else { + defect.category_id = null; + defect.item_id = null; + } + + renderInlineDefectList(index); + updateHiddenDefectFields(index); +}; + +/** + * 소분류 선택 변경 + */ +window.onDefectItemChange = async function(index, defectIndex, value) { + if (!tempDefects[index] || !tempDefects[index][defectIndex]) return; + + const defect = tempDefects[index][defectIndex]; + + if (value === '__new__') { + // 새 아이템 추가 모달 + const newName = prompt('새 소분류(항목) 이름을 입력하세요:'); + if (newName && newName.trim() && defect.category_id) { + try { + const response = await window.apiCall('/work-issues/items', 'POST', { + category_id: defect.category_id, + item_name: newName.trim(), + severity: 'medium' + }); + + if (response.success) { + // 아이템 목록 새로고침 + await loadErrorTypes(); + // 새로 생성된 아이템 선택 + const newItem = issueItems.find(i => i.item_name === newName.trim() && i.category_id == defect.category_id); + if (newItem) { + defect.item_id = newItem.item_id; + } + } else { + alert('항목 추가 실패: ' + (response.error || '알 수 없는 오류')); + } + } catch (e) { + alert('항목 추가 중 오류: ' + e.message); + } + } + } else if (value) { + defect.item_id = parseInt(value); + } else { + defect.item_id = null; + } + + renderInlineDefectList(index); + updateHiddenDefectFields(index); +}; + +/** + * 이슈 부적합 토글 (체크박스) + */ +window.toggleIssueDefect = function(index, issueReportId, isChecked) { + if (!tempDefects[index]) { + tempDefects[index] = []; + } + + if (isChecked) { + // 이슈 부적합 추가 + tempDefects[index].push({ + issue_report_id: issueReportId, + error_type_id: null, // 이슈 기반이므로 null + defect_hours: 0, + note: '' + }); + } else { + // 이슈 부적합 제거 + const idx = tempDefects[index].findIndex(d => d.issue_report_id == issueReportId); + if (idx !== -1) { + tempDefects[index].splice(idx, 1); + } + } + + renderInlineDefectList(index); + updateHiddenDefectFields(index); +}; + +/** + * 이슈 부적합 시간 선택기 열기 + */ +window.openIssueDefectTimePicker = function(index, issueReportId) { + // 해당 이슈의 defect 찾기 + const defects = tempDefects[index] || []; + const defectIndex = defects.findIndex(d => d.issue_report_id == issueReportId); + + if (defectIndex === -1) return; + + currentEditingField = { index, type: 'issueDefect', issueReportId, defectIndex }; + currentTimeValue = defects[defectIndex]?.defect_hours || 0; + + // 팝오버 표시 + const overlay = document.getElementById('timePickerOverlay'); + const title = document.getElementById('timePickerTitle'); + + title.textContent = '부적합 시간 선택'; + updateTimeDisplay(); + + overlay.style.display = 'flex'; + + // ESC 키로 닫기 + document.addEventListener('keydown', handleEscapeKey); +}; + +/** + * 레거시 부적합 추가 (error_types 기반) + */ +window.addLegacyDefect = function(index) { + if (!tempDefects[index]) { + tempDefects[index] = []; + } + + tempDefects[index].push({ + issue_report_id: null, + category_id: null, + item_id: null, + error_type_id: '', // 레거시 호환 + defect_hours: 0, + note: '' + }); + + renderInlineDefectList(index); +}; + +/** + * 부적합 카테고리/아이템 선택 업데이트 (레거시 호환) + * @deprecated onDefectCategoryChange, onDefectItemChange 사용 권장 + */ +window.updateDefectCategory = function(index, defectIndex, value) { + // 레거시 호환 - 새 함수로 리다이렉트 + if (value && value.startsWith('cat_')) { + onDefectCategoryChange(index, defectIndex, value.replace('cat_', '')); + } else if (value && value.startsWith('item_')) { + const itemId = parseInt(value.replace('item_', '')); + const item = issueItems.find(i => i.item_id === itemId); + if (item) { + if (!tempDefects[index]?.[defectIndex]) return; + tempDefects[index][defectIndex].category_id = item.category_id; + tempDefects[index][defectIndex].item_id = itemId; + renderInlineDefectList(index); + updateHiddenDefectFields(index); + } + } +}; + +/** + * 인라인 부적합 추가 (레거시 호환) + */ +window.addInlineDefect = function(index) { + addLegacyDefect(index); +}; + +/** + * 부적합 저장 확인 (유효성 검사 후 저장 상태로 변경) + */ +window.saveDefectsConfirm = function(index) { + const defects = tempDefects[index] || []; + // 입력 중인 항목만 (저장되지 않은 항목) + const editingDefects = defects.filter(d => !d.issue_report_id && !d._saved); + + if (editingDefects.length === 0) { + alert('저장할 부적합 항목이 없습니다.\n"+ 부적합 추가" 버튼을 눌러 항목을 추가하세요.'); + return; + } + + // 유효성 검사 + const invalidDefects = []; + editingDefects.forEach((defect, i) => { + const errors = []; + if (!defect.category_id) { + errors.push('대분류'); + } + if (!defect.defect_hours || defect.defect_hours <= 0) { + errors.push('시간'); + } + if (errors.length > 0) { + invalidDefects.push({ index: i + 1, errors }); + } + }); + + if (invalidDefects.length > 0) { + const errorMsg = invalidDefects.map(d => + `${d.index}번째 항목: ${d.errors.join(', ')} 미입력` + ).join('\n'); + alert(`입력이 완료되지 않은 항목이 있습니다.\n\n${errorMsg}`); + return; + } + + // 모든 입력 중인 항목을 저장 상태로 변경 + editingDefects.forEach(defect => { + defect._saved = true; + }); + + // UI 다시 렌더링 + renderInlineDefectList(index); + updateHiddenDefectFields(index); + updateDefectSummary(index); + + console.log(`[부적합 저장] index=${index}, 저장된 항목 수=${editingDefects.length}`); +}; + +/** + * 저장된 부적합 수정 (저장 상태 해제하여 입력 폼으로 이동) + */ +window.editSavedDefect = function(index, defectIndex) { + if (!tempDefects[index] || !tempDefects[index][defectIndex]) return; + + // 원래 저장 상태였음을 기록 (취소 시 복원용) + tempDefects[index][defectIndex]._originalSaved = true; + tempDefects[index][defectIndex]._saved = false; + + // UI 다시 렌더링 + renderInlineDefectList(index); +}; + +/** + * 저장된 부적합 삭제 + */ +window.deleteSavedDefect = function(index, defectIndex) { + if (!tempDefects[index] || !tempDefects[index][defectIndex]) return; + + if (!confirm('이 부적합 항목을 삭제하시겠습니까?')) return; + + tempDefects[index].splice(defectIndex, 1); + + // UI 다시 렌더링 + renderInlineDefectList(index); + updateHiddenDefectFields(index); + updateDefectSummary(index); +}; + +/** + * 부적합 입력 취소 (저장되지 않은 항목 삭제) + */ +window.cancelDefectEdit = function(index, defectIndex) { + if (!tempDefects[index] || !tempDefects[index][defectIndex]) return; + + const defect = tempDefects[index][defectIndex]; + + // 원래 저장된 항목이었으면 저장 상태로 복원, 아니면 삭제 + if (defect._originalSaved) { + defect._saved = true; + delete defect._originalSaved; + } else { + tempDefects[index].splice(defectIndex, 1); + } + + // UI 다시 렌더링 + renderInlineDefectList(index); + updateHiddenDefectFields(index); + updateDefectSummary(index); +}; + +/** + * 인라인 부적합 수정 + */ +window.updateInlineDefect = function(index, defectIndex, field, value) { + if (tempDefects[index] && tempDefects[index][defectIndex]) { + if (field === 'defect_hours') { + tempDefects[index][defectIndex][field] = parseFloat(value) || 0; + } else { + tempDefects[index][defectIndex][field] = value; + } + updateDefectSummary(index); + updateHiddenDefectFields(index); + } +}; + +/** + * 인라인 부적합 삭제 + */ +window.removeInlineDefect = function(index, defectIndex) { + if (tempDefects[index]) { + tempDefects[index].splice(defectIndex, 1); + + // UI 다시 렌더링 (항상 - 빈 상태도 표시) + renderInlineDefectList(index); + updateDefectSummary(index); + updateHiddenDefectFields(index); + } +}; + +/** + * 부적합 시간 선택기 열기 (시간 선택 팝오버 재사용) + */ +window.openDefectTimePicker = function(index, defectIndex) { + currentEditingField = { index, type: 'defect', defectIndex }; + + // 현재 값 가져오기 + const defects = tempDefects[index] || []; + currentTimeValue = defects[defectIndex]?.defect_hours || 0; + + // 팝오버 표시 + const overlay = document.getElementById('timePickerOverlay'); + const title = document.getElementById('timePickerTitle'); + + title.textContent = '부적합 시간 선택'; + updateTimeDisplay(); + + overlay.style.display = 'flex'; + + // ESC 키로 닫기 + document.addEventListener('keydown', handleEscapeKey); +}; + +/** + * hidden input 필드 업데이트 + */ +function updateHiddenDefectFields(index) { + const defects = tempDefects[index] || []; + + // 총 부적합 시간 계산 + const totalErrorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0); + + // hidden input에 대표 error_type_id 저장 (첫 번째 값, item_id fallback) + const errorTypeInput = document.getElementById(`errorType_${index}`); + const errorTypeId = defects.length > 0 ? (defects[0].error_type_id || defects[0].item_id || null) : null; + if (errorTypeInput && errorTypeId) { + errorTypeInput.value = errorTypeId; + } else if (errorTypeInput) { + errorTypeInput.value = ''; + } + + // 부적합 시간 input 업데이트 + const errorHoursInput = document.getElementById(`errorHours_${index}`); + if (errorHoursInput) { + errorHoursInput.value = totalErrorHours; + } +} + +/** + * 부적합 요약 텍스트 업데이트 + * - 이슈 기반 부적합과 레거시 부적합 모두 포함 + */ +function updateDefectSummary(index) { + const summaryEl = document.getElementById(`defectSummary_${index}`); + const toggleBtn = document.getElementById(`defectToggle_${index}`); + if (!summaryEl) return; + + const defects = tempDefects[index] || []; + // 이슈 기반 또는 레거시 부적합 중 시간이 입력된 것만 유효 (item_id도 체크) + const validDefects = defects.filter(d => (d.issue_report_id || d.category_id || d.item_id || d.error_type_id) && d.defect_hours > 0); + + if (validDefects.length === 0) { + summaryEl.textContent = '없음'; + summaryEl.style.color = '#6b7280'; + if (toggleBtn) toggleBtn.classList.remove('has-defect'); + } else { + const totalHours = validDefects.reduce((sum, d) => sum + d.defect_hours, 0); + if (validDefects.length === 1) { + let typeName = '부적합'; + if (validDefects[0].issue_report_id) { + // 이슈 기반 - 이슈 캐시에서 이름 찾기 + const tbm = incompleteTbms[index]; + if (tbm) { + const dateStr = formatDateForApi(tbm.session_date); + const issues = dailyIssuesCache[dateStr] || []; + const issue = issues.find(i => i.report_id == validDefects[0].issue_report_id); + typeName = issue?.issue_item_name || issue?.issue_category_name || '부적합'; + } + } else if (validDefects[0].item_id) { + // 신규 방식 - issue_report_items에서 이름 찾기 + typeName = issueItems.find(i => i.item_id == validDefects[0].item_id)?.item_name || '부적합'; + } else if (validDefects[0].category_id) { + // 카테고리만 선택된 경우 + typeName = issueCategories.find(c => c.category_id == validDefects[0].category_id)?.category_name || '부적합'; + } else if (validDefects[0].error_type_id) { + // 레거시 - error_types에서 이름 찾기 또는 issue_report_items에서 찾기 + typeName = issueItems.find(i => i.item_id == validDefects[0].error_type_id)?.item_name || + errorTypes.find(et => et.id == validDefects[0].error_type_id)?.name || '부적합'; + } + summaryEl.textContent = `${typeName} ${totalHours}h`; + } else { + summaryEl.textContent = `${validDefects.length}건 ${totalHours}h`; + } + summaryEl.style.color = '#dc2626'; + if (toggleBtn) toggleBtn.classList.add('has-defect'); + } + + // hidden 필드도 업데이트 + updateHiddenDefectFields(index); +} diff --git a/deploy/tkfb-package/web-ui/js/daily-work-report/api.js b/deploy/tkfb-package/web-ui/js/daily-work-report/api.js new file mode 100644 index 0000000..55c2a7c --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-work-report/api.js @@ -0,0 +1,386 @@ +/** + * Daily Work Report - API Client + * 작업보고서 관련 모든 API 호출을 관리 + */ + +class DailyWorkReportAPI { + constructor() { + this.state = window.DailyWorkReportState; + console.log('[API] DailyWorkReportAPI 초기화'); + } + + /** + * 작업자 로드 (생산팀 소속) + */ + async loadWorkers() { + try { + console.log('[API] Workers 로딩 중...'); + const data = await window.apiCall('/workers?limit=1000&department_id=1'); + const allWorkers = Array.isArray(data) ? data : (data.data || data.workers || []); + + // 퇴사자만 제외 + const filtered = allWorkers.filter(worker => worker.employment_status !== 'resigned'); + + this.state.workers = filtered; + console.log(`[API] Workers 로드 완료: ${filtered.length}명`); + return filtered; + } catch (error) { + console.error('[API] 작업자 로딩 오류:', error); + throw error; + } + } + + /** + * 프로젝트 로드 (활성 프로젝트만) + */ + async loadProjects() { + try { + console.log('[API] Projects 로딩 중...'); + const data = await window.apiCall('/projects/active/list'); + const projects = Array.isArray(data) ? data : (data.data || data.projects || []); + + this.state.projects = projects; + console.log(`[API] Projects 로드 완료: ${projects.length}개`); + return projects; + } catch (error) { + console.error('[API] 프로젝트 로딩 오류:', error); + throw error; + } + } + + /** + * 작업 유형 로드 + */ + async loadWorkTypes() { + try { + const data = await window.apiCall('/daily-work-reports/work-types'); + if (Array.isArray(data) && data.length > 0) { + this.state.workTypes = data; + console.log('[API] 작업 유형 로드 완료:', data.length); + return data; + } + throw new Error('API 실패'); + } catch (error) { + console.log('[API] 작업 유형 API 사용 불가, 기본값 사용'); + this.state.workTypes = [ + { id: 1, name: 'Base' }, + { id: 2, name: 'Vessel' }, + { id: 3, name: 'Piping' } + ]; + return this.state.workTypes; + } + } + + /** + * 업무 상태 유형 로드 + */ + async loadWorkStatusTypes() { + try { + const data = await window.apiCall('/daily-work-reports/work-status-types'); + if (Array.isArray(data) && data.length > 0) { + this.state.workStatusTypes = data; + console.log('[API] 업무 상태 유형 로드 완료:', data.length); + return data; + } + throw new Error('API 실패'); + } catch (error) { + console.log('[API] 업무 상태 유형 API 사용 불가, 기본값 사용'); + this.state.workStatusTypes = [ + { id: 1, name: '정상', is_error: false }, + { id: 2, name: '부적합', is_error: true } + ]; + return this.state.workStatusTypes; + } + } + + /** + * 오류 유형 로드 (신고 카테고리/아이템) + */ + async loadErrorTypes() { + try { + // 1. 신고 카테고리 (nonconformity만) + const categoriesResponse = await window.apiCall('/work-issues/categories'); + if (categoriesResponse.success && categoriesResponse.data) { + this.state.issueCategories = categoriesResponse.data.filter( + c => c.category_type === 'nonconformity' + ); + console.log('[API] 신고 카테고리 로드:', this.state.issueCategories.length); + } + + // 2. 신고 아이템 전체 + const itemsResponse = await window.apiCall('/work-issues/items'); + if (itemsResponse.success && itemsResponse.data) { + // nonconformity 카테고리의 아이템만 필터링 + const nonconfCatIds = this.state.issueCategories.map(c => c.category_id); + this.state.issueItems = itemsResponse.data.filter( + item => nonconfCatIds.includes(item.category_id) + ); + console.log('[API] 신고 아이템 로드:', this.state.issueItems.length); + } + + // 레거시 호환: errorTypes에 카테고리 매핑 + this.state.errorTypes = this.state.issueCategories.map(cat => ({ + id: cat.category_id, + name: cat.category_name + })); + + } catch (error) { + console.error('[API] 오류 유형 로딩 오류:', error); + // 기본값 설정 + this.state.errorTypes = [ + { id: 1, name: '자재 부적합' }, + { id: 2, name: '도면 오류' }, + { id: 3, name: '장비 고장' } + ]; + } + } + + /** + * 미완료 TBM 세션 로드 + */ + async loadIncompleteTbms() { + try { + const response = await window.apiCall('/tbm/sessions/incomplete-reports'); + + if (!response.success) { + throw new Error(response.message || '미완료 TBM 조회 실패'); + } + + let data = response.data || []; + + // 사용자 권한 확인 및 필터링 + const user = this.state.getUser(); + if (user && user.role !== 'Admin' && user.access_level !== 'system') { + const userId = user.user_id; + data = data.filter(tbm => tbm.created_by === userId); + } + + this.state.incompleteTbms = data; + console.log('[API] 미완료 TBM 로드 완료:', data.length); + return data; + } catch (error) { + console.error('[API] 미완료 TBM 로드 오류:', error); + throw error; + } + } + + /** + * TBM 세션별 당일 신고 로드 + */ + async loadDailyIssuesForTbms() { + const tbms = this.state.incompleteTbms; + if (!tbms || tbms.length === 0) { + console.log('[API] 미완료 TBM 없음, 신고 조회 건너뜀'); + return; + } + + // 고유한 날짜 수집 + const uniqueDates = [...new Set(tbms.map(tbm => { + return window.DailyWorkReportUtils?.formatDateForApi(tbm.session_date) || + this.formatDateForApi(tbm.session_date); + }).filter(Boolean))]; + + console.log('[API] 조회할 날짜들:', uniqueDates); + + for (const dateStr of uniqueDates) { + if (this.state.dailyIssuesCache[dateStr]) { + console.log(`[API] 캐시 사용 (${dateStr})`); + continue; + } + + try { + const response = await window.apiCall(`/work-issues?start_date=${dateStr}&end_date=${dateStr}`); + if (response.success) { + this.state.setDailyIssuesCache(dateStr, response.data || []); + console.log(`[API] 신고 로드 완료 (${dateStr}):`, this.state.dailyIssuesCache[dateStr].length); + } else { + this.state.setDailyIssuesCache(dateStr, []); + } + } catch (error) { + console.error(`[API] 신고 조회 오류 (${dateStr}):`, error); + this.state.setDailyIssuesCache(dateStr, []); + } + } + } + + /** + * 완료된 작업보고서 조회 + */ + async loadCompletedReports(date) { + try { + const response = await window.apiCall(`/daily-work-reports/v2/reports?date=${date}`); + if (response.success) { + console.log(`[API] 완료 보고서 로드 (${date}):`, response.data?.length || 0); + return response.data || []; + } + throw new Error(response.message || '조회 실패'); + } catch (error) { + console.error('[API] 완료 보고서 로드 오류:', error); + throw error; + } + } + + /** + * TBM 작업보고서 제출 + */ + async submitTbmWorkReport(reportData) { + try { + const response = await window.apiCall('/daily-work-reports/from-tbm', 'POST', reportData); + if (!response.success) { + throw new Error(response.message || '제출 실패'); + } + console.log('[API] TBM 작업보고서 제출 완료:', response); + return response; + } catch (error) { + console.error('[API] TBM 작업보고서 제출 오류:', error); + throw error; + } + } + + /** + * 수동 작업보고서 제출 + */ + async submitManualWorkReport(reportData) { + try { + const response = await window.apiCall('/daily-work-reports/v2/reports', 'POST', reportData); + if (!response.success) { + throw new Error(response.message || '제출 실패'); + } + console.log('[API] 수동 작업보고서 제출 완료:', response); + return response; + } catch (error) { + console.error('[API] 수동 작업보고서 제출 오류:', error); + throw error; + } + } + + /** + * 작업보고서 삭제 + */ + async deleteWorkReport(reportId) { + try { + const response = await window.apiCall(`/daily-work-reports/v2/reports/${reportId}`, 'DELETE'); + if (!response.success) { + throw new Error(response.message || '삭제 실패'); + } + console.log('[API] 작업보고서 삭제 완료:', reportId); + return response; + } catch (error) { + console.error('[API] 작업보고서 삭제 오류:', error); + throw error; + } + } + + /** + * 작업보고서 수정 + */ + async updateWorkReport(reportId, updateData) { + try { + const response = await window.apiCall(`/daily-work-reports/v2/reports/${reportId}`, 'PUT', updateData); + if (!response.success) { + throw new Error(response.message || '수정 실패'); + } + console.log('[API] 작업보고서 수정 완료:', reportId); + return response; + } catch (error) { + console.error('[API] 작업보고서 수정 오류:', error); + throw error; + } + } + + /** + * 신고 카테고리 추가 + */ + async addIssueCategory(categoryData) { + try { + const response = await window.apiCall('/work-issues/categories', 'POST', categoryData); + if (response.success) { + await this.loadErrorTypes(); // 목록 새로고침 + } + return response; + } catch (error) { + console.error('[API] 카테고리 추가 오류:', error); + throw error; + } + } + + /** + * 신고 아이템 추가 + */ + async addIssueItem(itemData) { + try { + const response = await window.apiCall('/work-issues/items', 'POST', itemData); + if (response.success) { + await this.loadErrorTypes(); // 목록 새로고침 + } + return response; + } catch (error) { + console.error('[API] 아이템 추가 오류:', error); + throw error; + } + } + + /** + * 모든 기본 데이터 로드 + */ + async loadAllData() { + console.log('[API] 모든 기본 데이터 로딩 시작...'); + + await Promise.all([ + this.loadWorkers(), + this.loadProjects(), + this.loadWorkTypes(), + this.loadWorkStatusTypes(), + this.loadErrorTypes() + ]); + + console.log('[API] 모든 기본 데이터 로딩 완료'); + } + + // 유틸리티: 날짜 형식 변환 (API 형식) + formatDateForApi(date) { + if (!date) return null; + + let dateObj; + if (date instanceof Date) { + dateObj = date; + } else if (typeof date === 'string') { + dateObj = new Date(date); + } else { + return null; + } + + const year = dateObj.getFullYear(); + const month = String(dateObj.getMonth() + 1).padStart(2, '0'); + const day = String(dateObj.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; + } +} + +// 전역 인스턴스 생성 +window.DailyWorkReportAPI = new DailyWorkReportAPI(); + +// 하위 호환성: 기존 함수들 +window.loadWorkers = () => window.DailyWorkReportAPI.loadWorkers(); +window.loadProjects = () => window.DailyWorkReportAPI.loadProjects(); +window.loadWorkTypes = () => window.DailyWorkReportAPI.loadWorkTypes(); +window.loadWorkStatusTypes = () => window.DailyWorkReportAPI.loadWorkStatusTypes(); +window.loadErrorTypes = () => window.DailyWorkReportAPI.loadErrorTypes(); +window.loadIncompleteTbms = () => window.DailyWorkReportAPI.loadIncompleteTbms(); +window.loadDailyIssuesForTbms = () => window.DailyWorkReportAPI.loadDailyIssuesForTbms(); +window.loadCompletedReports = () => window.DailyWorkReportAPI.loadCompletedReports( + document.getElementById('completedReportDate')?.value +); + +// 통합 데이터 로드 함수 +window.loadData = async () => { + try { + window.showMessage?.('데이터를 불러오는 중...', 'loading'); + await window.DailyWorkReportAPI.loadAllData(); + window.hideMessage?.(); + } catch (error) { + console.error('[API] 데이터 로드 실패:', error); + window.showMessage?.('데이터 로드 중 오류가 발생했습니다: ' + error.message, 'error'); + } +}; diff --git a/deploy/tkfb-package/web-ui/js/daily-work-report/index.js b/deploy/tkfb-package/web-ui/js/daily-work-report/index.js new file mode 100644 index 0000000..03184dd --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-work-report/index.js @@ -0,0 +1,318 @@ +/** + * Daily Work Report - Module Loader + * 작업보고서 모듈을 초기화하고 연결하는 메인 진입점 + * + * 로드 순서: + * 1. state.js - 전역 상태 관리 + * 2. utils.js - 유틸리티 함수 + * 3. api.js - API 클라이언트 + * 4. index.js - 이 파일 (메인 컨트롤러) + */ + +class DailyWorkReportController { + constructor() { + this.state = window.DailyWorkReportState; + this.api = window.DailyWorkReportAPI; + this.utils = window.DailyWorkReportUtils; + this.initialized = false; + + console.log('[Controller] DailyWorkReportController 생성'); + } + + /** + * 초기화 + */ + async init() { + if (this.initialized) { + console.log('[Controller] 이미 초기화됨'); + return; + } + + console.log('[Controller] 초기화 시작...'); + + try { + // 이벤트 리스너 설정 + this.setupEventListeners(); + + // 기본 데이터 로드 + await this.api.loadAllData(); + + // TBM 탭이 기본 + await this.switchTab('tbm'); + + this.initialized = true; + console.log('[Controller] 초기화 완료'); + + } catch (error) { + console.error('[Controller] 초기화 실패:', error); + window.showMessage?.('초기화 중 오류가 발생했습니다: ' + error.message, 'error'); + } + } + + /** + * 이벤트 리스너 설정 + */ + setupEventListeners() { + // 탭 버튼 + const tbmBtn = document.getElementById('tbmReportTab'); + const completedBtn = document.getElementById('completedReportTab'); + + if (tbmBtn) { + tbmBtn.addEventListener('click', () => this.switchTab('tbm')); + } + if (completedBtn) { + completedBtn.addEventListener('click', () => this.switchTab('completed')); + } + + // 완료 보고서 날짜 변경 + const completedDateInput = document.getElementById('completedReportDate'); + if (completedDateInput) { + completedDateInput.addEventListener('change', () => this.loadCompletedReports()); + } + + console.log('[Controller] 이벤트 리스너 설정 완료'); + } + + /** + * 탭 전환 + */ + async switchTab(tab) { + this.state.setCurrentTab(tab); + + const tbmBtn = document.getElementById('tbmReportTab'); + const completedBtn = document.getElementById('completedReportTab'); + const tbmSection = document.getElementById('tbmReportSection'); + const completedSection = document.getElementById('completedReportSection'); + + // 모든 탭 버튼 비활성화 + tbmBtn?.classList.remove('active'); + completedBtn?.classList.remove('active'); + + // 모든 섹션 숨기기 + if (tbmSection) tbmSection.style.display = 'none'; + if (completedSection) completedSection.style.display = 'none'; + + // 선택된 탭 활성화 + if (tab === 'tbm') { + tbmBtn?.classList.add('active'); + if (tbmSection) tbmSection.style.display = 'block'; + await this.loadTbmData(); + } else if (tab === 'completed') { + completedBtn?.classList.add('active'); + if (completedSection) completedSection.style.display = 'block'; + + // 오늘 날짜로 초기화 + const dateInput = document.getElementById('completedReportDate'); + if (dateInput) { + dateInput.value = this.utils.getKoreaToday(); + } + await this.loadCompletedReports(); + } + } + + /** + * TBM 데이터 로드 + */ + async loadTbmData() { + try { + await this.api.loadIncompleteTbms(); + await this.api.loadDailyIssuesForTbms(); + + // 렌더링은 기존 함수 사용 (점진적 마이그레이션) + if (typeof window.renderTbmWorkList === 'function') { + window.renderTbmWorkList(); + } + } catch (error) { + console.error('[Controller] TBM 데이터 로드 오류:', error); + window.showMessage?.('TBM 데이터를 불러오는 중 오류가 발생했습니다.', 'error'); + } + } + + /** + * 완료 보고서 로드 + */ + async loadCompletedReports() { + try { + const dateInput = document.getElementById('completedReportDate'); + const date = dateInput?.value || this.utils.getKoreaToday(); + + const reports = await this.api.loadCompletedReports(date); + + // 렌더링은 기존 함수 사용 + if (typeof window.renderCompletedReports === 'function') { + window.renderCompletedReports(reports); + } + } catch (error) { + console.error('[Controller] 완료 보고서 로드 오류:', error); + window.showMessage?.('완료 보고서를 불러오는 중 오류가 발생했습니다.', 'error'); + } + } + + /** + * TBM 작업보고서 제출 + */ + async submitTbmWorkReport(index) { + try { + const tbm = this.state.incompleteTbms[index]; + if (!tbm) { + throw new Error('TBM 데이터를 찾을 수 없습니다.'); + } + + // 유효성 검사 + const totalHoursInput = document.getElementById(`totalHours_${index}`); + const totalHours = parseFloat(totalHoursInput?.value); + + if (!totalHours || totalHours <= 0) { + window.showMessage?.('작업시간을 입력해주세요.', 'warning'); + return; + } + + // 부적합 시간 계산 + const defects = this.state.tempDefects[index] || []; + const errorHours = defects.reduce((sum, d) => sum + (parseFloat(d.defect_hours) || 0), 0); + const regularHours = totalHours - errorHours; + + if (regularHours < 0) { + window.showMessage?.('부적합 시간이 총 작업시간을 초과할 수 없습니다.', 'warning'); + return; + } + + // API 데이터 구성 + const user = this.state.getCurrentUser(); + const reportData = { + tbm_session_id: tbm.session_id, + tbm_assignment_id: tbm.assignment_id, + worker_id: tbm.worker_id, + project_id: tbm.project_id, + work_type_id: tbm.work_type_id, + report_date: this.utils.formatDateForApi(tbm.session_date), + total_hours: totalHours, + regular_hours: regularHours, + error_hours: errorHours, + work_status_id: errorHours > 0 ? 2 : 1, + created_by: user?.user_id || user?.id, + defects: defects.map(d => ({ + category_id: d.category_id, + item_id: d.item_id, + issue_report_id: d.issue_report_id, + defect_hours: d.defect_hours, + note: d.note + })) + }; + + const result = await this.api.submitTbmWorkReport(reportData); + + window.showSaveResultModal?.( + 'success', + '제출 완료', + `${tbm.worker_name}의 작업보고서가 제출되었습니다.` + ); + + // 목록 새로고침 + await this.loadTbmData(); + + } catch (error) { + console.error('[Controller] 제출 오류:', error); + window.showSaveResultModal?.( + 'error', + '제출 실패', + error.message || '작업보고서 제출 중 오류가 발생했습니다.' + ); + } + } + + /** + * 세션 일괄 제출 + */ + async batchSubmitSession(sessionKey) { + const rows = document.querySelectorAll(`tr[data-session-key="${sessionKey}"][data-type="tbm"]`); + const indices = []; + + rows.forEach(row => { + const index = parseInt(row.dataset.index); + const totalHoursInput = document.getElementById(`totalHours_${index}`); + if (totalHoursInput?.value && parseFloat(totalHoursInput.value) > 0) { + indices.push(index); + } + }); + + if (indices.length === 0) { + window.showMessage?.('제출할 항목이 없습니다. 작업시간을 입력해주세요.', 'warning'); + return; + } + + const confirmed = confirm(`${indices.length}건의 작업보고서를 일괄 제출하시겠습니까?`); + if (!confirmed) return; + + let successCount = 0; + let failCount = 0; + + for (const index of indices) { + try { + await this.submitTbmWorkReport(index); + successCount++; + } catch (error) { + failCount++; + console.error(`[Controller] 일괄 제출 오류 (index: ${index}):`, error); + } + } + + if (failCount === 0) { + window.showSaveResultModal?.('success', '일괄 제출 완료', `${successCount}건이 성공적으로 제출되었습니다.`); + } else { + window.showSaveResultModal?.('warning', '일괄 제출 부분 완료', `성공: ${successCount}건, 실패: ${failCount}건`); + } + } + + /** + * 상태 디버그 + */ + debug() { + console.log('[Controller] 상태 디버그:'); + this.state.debug(); + } +} + +// 전역 인스턴스 생성 +window.DailyWorkReportController = new DailyWorkReportController(); + +// 하위 호환성: 기존 전역 함수들 +window.switchTab = (tab) => window.DailyWorkReportController.switchTab(tab); +window.submitTbmWorkReport = (index) => window.DailyWorkReportController.submitTbmWorkReport(index); +window.batchSubmitTbmSession = (sessionKey) => window.DailyWorkReportController.batchSubmitSession(sessionKey); + +// 사용자 정보 함수 +window.getUser = () => window.DailyWorkReportState.getUser(); +window.getCurrentUser = () => window.DailyWorkReportState.getCurrentUser(); + +// 날짜 그룹 토글 (UI 함수) +window.toggleDateGroup = function(dateStr) { + const group = document.querySelector(`.date-group[data-date="${dateStr}"]`); + if (!group) return; + + const isExpanded = group.classList.contains('expanded'); + const content = group.querySelector('.date-group-content'); + const icon = group.querySelector('.date-toggle-icon'); + + if (isExpanded) { + group.classList.remove('expanded'); + group.classList.add('collapsed'); + if (content) content.style.display = 'none'; + if (icon) icon.textContent = '▶'; + } else { + group.classList.remove('collapsed'); + group.classList.add('expanded'); + if (content) content.style.display = 'block'; + if (icon) icon.textContent = '▼'; + } +}; + +// DOMContentLoaded 이벤트에서 초기화 +document.addEventListener('DOMContentLoaded', () => { + // 약간의 지연 후 초기화 (다른 스크립트 로드 대기) + setTimeout(() => { + window.DailyWorkReportController.init(); + }, 100); +}); + +console.log('[Module] daily-work-report/index.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/daily-work-report/state.js b/deploy/tkfb-package/web-ui/js/daily-work-report/state.js new file mode 100644 index 0000000..ea9b9cb --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-work-report/state.js @@ -0,0 +1,342 @@ +/** + * Daily Work Report - State Manager + * 작업보고서 페이지의 전역 상태 관리 + */ + +class DailyWorkReportState { + constructor() { + // 마스터 데이터 + this.workTypes = []; + this.workStatusTypes = []; + this.errorTypes = []; // 레거시 호환용 + this.issueCategories = []; // 신고 카테고리 (nonconformity) + this.issueItems = []; // 신고 아이템 + this.workers = []; + this.projects = []; + + // UI 상태 + this.selectedWorkers = new Set(); + this.workEntryCounter = 0; + this.currentStep = 1; + this.editingWorkId = null; + this.currentTab = 'tbm'; + + // TBM 관련 + this.incompleteTbms = []; + + // 부적합 원인 관리 + this.currentDefectIndex = null; + this.tempDefects = {}; // { index: [{ error_type_id, defect_hours, note }] } + + // 작업장소 지도 관련 + this.mapCanvas = null; + this.mapCtx = null; + this.mapImage = null; + this.mapRegions = []; + this.selectedWorkplace = null; + this.selectedWorkplaceName = null; + this.selectedWorkplaceCategory = null; + this.selectedWorkplaceCategoryName = null; + + // 시간 선택 관련 + this.currentEditingField = null; // { index, type: 'total' | 'error' } + this.currentTimeValue = 0; + + // 캐시 + this.dailyIssuesCache = {}; // { 'YYYY-MM-DD': [issues] } + + // 리스너 + this.listeners = new Map(); + + console.log('[State] DailyWorkReportState 초기화 완료'); + } + + /** + * 상태 업데이트 + */ + update(key, value) { + const prevValue = this[key]; + this[key] = value; + this.notifyListeners(key, value, prevValue); + } + + /** + * 리스너 등록 + */ + subscribe(key, callback) { + if (!this.listeners.has(key)) { + this.listeners.set(key, []); + } + this.listeners.get(key).push(callback); + } + + /** + * 리스너에게 알림 + */ + notifyListeners(key, newValue, prevValue) { + const keyListeners = this.listeners.get(key) || []; + keyListeners.forEach(callback => { + try { + callback(newValue, prevValue); + } catch (error) { + console.error(`[State] 리스너 오류 (${key}):`, error); + } + }); + } + + /** + * 현재 사용자 정보 가져오기 + */ + getUser() { + const user = localStorage.getItem('user'); + return user ? JSON.parse(user) : null; + } + + /** + * 토큰에서 사용자 정보 추출 + */ + getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + return payload; + } + } catch (error) { + console.log('[State] 토큰에서 사용자 정보 추출 실패:', error); + } + + try { + const userInfo = localStorage.getItem('user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + if (userInfo) { + return JSON.parse(userInfo); + } + } catch (error) { + console.log('[State] localStorage에서 사용자 정보 가져오기 실패:', error); + } + + return null; + } + + /** + * 선택된 작업자 토글 + */ + toggleWorkerSelection(workerId) { + if (this.selectedWorkers.has(workerId)) { + this.selectedWorkers.delete(workerId); + } else { + this.selectedWorkers.add(workerId); + } + this.notifyListeners('selectedWorkers', this.selectedWorkers, null); + } + + /** + * 작업자 전체 선택/해제 + */ + selectAllWorkers(select = true) { + if (select) { + this.workers.forEach(w => this.selectedWorkers.add(w.worker_id)); + } else { + this.selectedWorkers.clear(); + } + this.notifyListeners('selectedWorkers', this.selectedWorkers, null); + } + + /** + * 작업 항목 카운터 증가 + */ + incrementWorkEntryCounter() { + this.workEntryCounter++; + return this.workEntryCounter; + } + + /** + * 탭 변경 + */ + setCurrentTab(tab) { + const prevTab = this.currentTab; + this.currentTab = tab; + this.notifyListeners('currentTab', tab, prevTab); + } + + /** + * 부적합 임시 저장소 초기화 + */ + initTempDefects(index) { + if (!this.tempDefects[index]) { + this.tempDefects[index] = []; + } + } + + /** + * 부적합 추가 + */ + addTempDefect(index, defect) { + this.initTempDefects(index); + this.tempDefects[index].push(defect); + this.notifyListeners('tempDefects', this.tempDefects, null); + } + + /** + * 부적합 업데이트 + */ + updateTempDefect(index, defectIndex, field, value) { + if (this.tempDefects[index] && this.tempDefects[index][defectIndex]) { + this.tempDefects[index][defectIndex][field] = value; + this.notifyListeners('tempDefects', this.tempDefects, null); + } + } + + /** + * 부적합 삭제 + */ + removeTempDefect(index, defectIndex) { + if (this.tempDefects[index]) { + this.tempDefects[index].splice(defectIndex, 1); + this.notifyListeners('tempDefects', this.tempDefects, null); + } + } + + /** + * 일일 이슈 캐시 설정 + */ + setDailyIssuesCache(dateStr, issues) { + this.dailyIssuesCache[dateStr] = issues; + } + + /** + * 일일 이슈 캐시 조회 + */ + getDailyIssuesCache(dateStr) { + return this.dailyIssuesCache[dateStr] || []; + } + + /** + * 상태 초기화 + */ + reset() { + this.selectedWorkers.clear(); + this.workEntryCounter = 0; + this.currentStep = 1; + this.editingWorkId = null; + this.tempDefects = {}; + this.currentDefectIndex = null; + this.dailyIssuesCache = {}; + } + + /** + * 디버그 출력 + */ + debug() { + console.log('[State] 현재 상태:', { + workTypes: this.workTypes.length, + workers: this.workers.length, + projects: this.projects.length, + selectedWorkers: this.selectedWorkers.size, + currentTab: this.currentTab, + incompleteTbms: this.incompleteTbms.length, + tempDefects: Object.keys(this.tempDefects).length + }); + } +} + +// 전역 인스턴스 생성 +window.DailyWorkReportState = new DailyWorkReportState(); + +// 하위 호환성을 위한 전역 변수 프록시 +const stateProxy = window.DailyWorkReportState; + +// 기존 전역 변수들과 호환 +Object.defineProperties(window, { + workTypes: { + get: () => stateProxy.workTypes, + set: (v) => { stateProxy.workTypes = v; } + }, + workStatusTypes: { + get: () => stateProxy.workStatusTypes, + set: (v) => { stateProxy.workStatusTypes = v; } + }, + errorTypes: { + get: () => stateProxy.errorTypes, + set: (v) => { stateProxy.errorTypes = v; } + }, + issueCategories: { + get: () => stateProxy.issueCategories, + set: (v) => { stateProxy.issueCategories = v; } + }, + issueItems: { + get: () => stateProxy.issueItems, + set: (v) => { stateProxy.issueItems = v; } + }, + workers: { + get: () => stateProxy.workers, + set: (v) => { stateProxy.workers = v; } + }, + projects: { + get: () => stateProxy.projects, + set: (v) => { stateProxy.projects = v; } + }, + selectedWorkers: { + get: () => stateProxy.selectedWorkers, + set: (v) => { stateProxy.selectedWorkers = v; } + }, + incompleteTbms: { + get: () => stateProxy.incompleteTbms, + set: (v) => { stateProxy.incompleteTbms = v; } + }, + tempDefects: { + get: () => stateProxy.tempDefects, + set: (v) => { stateProxy.tempDefects = v; } + }, + dailyIssuesCache: { + get: () => stateProxy.dailyIssuesCache, + set: (v) => { stateProxy.dailyIssuesCache = v; } + }, + currentTab: { + get: () => stateProxy.currentTab, + set: (v) => { stateProxy.currentTab = v; } + }, + currentStep: { + get: () => stateProxy.currentStep, + set: (v) => { stateProxy.currentStep = v; } + }, + editingWorkId: { + get: () => stateProxy.editingWorkId, + set: (v) => { stateProxy.editingWorkId = v; } + }, + workEntryCounter: { + get: () => stateProxy.workEntryCounter, + set: (v) => { stateProxy.workEntryCounter = v; } + }, + currentDefectIndex: { + get: () => stateProxy.currentDefectIndex, + set: (v) => { stateProxy.currentDefectIndex = v; } + }, + currentEditingField: { + get: () => stateProxy.currentEditingField, + set: (v) => { stateProxy.currentEditingField = v; } + }, + currentTimeValue: { + get: () => stateProxy.currentTimeValue, + set: (v) => { stateProxy.currentTimeValue = v; } + }, + selectedWorkplace: { + get: () => stateProxy.selectedWorkplace, + set: (v) => { stateProxy.selectedWorkplace = v; } + }, + selectedWorkplaceName: { + get: () => stateProxy.selectedWorkplaceName, + set: (v) => { stateProxy.selectedWorkplaceName = v; } + }, + selectedWorkplaceCategory: { + get: () => stateProxy.selectedWorkplaceCategory, + set: (v) => { stateProxy.selectedWorkplaceCategory = v; } + }, + selectedWorkplaceCategoryName: { + get: () => stateProxy.selectedWorkplaceCategoryName, + set: (v) => { stateProxy.selectedWorkplaceCategoryName = v; } + } +}); diff --git a/deploy/tkfb-package/web-ui/js/daily-work-report/utils.js b/deploy/tkfb-package/web-ui/js/daily-work-report/utils.js new file mode 100644 index 0000000..c6c4db8 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/daily-work-report/utils.js @@ -0,0 +1,470 @@ +/** + * Daily Work Report - Utilities + * 작업보고서 관련 유틸리티 함수들 + */ + +class DailyWorkReportUtils { + constructor() { + console.log('[Utils] DailyWorkReportUtils 초기화'); + } + + /** + * 한국 시간 기준 오늘 날짜 (YYYY-MM-DD) + */ + getKoreaToday() { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const day = String(today.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; + } + + /** + * 날짜를 API 형식(YYYY-MM-DD)으로 변환 + */ + formatDateForApi(date) { + if (!date) return null; + + let dateObj; + if (date instanceof Date) { + dateObj = date; + } else if (typeof date === 'string') { + dateObj = new Date(date); + } else { + return null; + } + + const year = dateObj.getFullYear(); + const month = String(dateObj.getMonth() + 1).padStart(2, '0'); + const day = String(dateObj.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; + } + + /** + * 날짜 포맷팅 (표시용) + */ + formatDate(date) { + if (!date) return '-'; + + let dateObj; + if (date instanceof Date) { + dateObj = date; + } else if (typeof date === 'string') { + dateObj = new Date(date); + } else { + return '-'; + } + + const year = dateObj.getFullYear(); + const month = String(dateObj.getMonth() + 1).padStart(2, '0'); + const day = String(dateObj.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; + } + + /** + * 시간 포맷팅 (HH:mm) + */ + formatTime(time) { + if (!time) return '-'; + if (typeof time === 'string' && time.includes(':')) { + return time.substring(0, 5); + } + return time; + } + + /** + * 상태 라벨 반환 + */ + getStatusLabel(status) { + const labels = { + 'pending': '접수', + 'in_progress': '처리중', + 'resolved': '해결', + 'completed': '완료', + 'closed': '종료' + }; + return labels[status] || status || '-'; + } + + /** + * 숫자 포맷팅 (천 단위 콤마) + */ + formatNumber(num) { + if (num === null || num === undefined) return '0'; + return num.toLocaleString('ko-KR'); + } + + /** + * 소수점 자리수 포맷팅 + */ + formatDecimal(num, decimals = 1) { + if (num === null || num === undefined) return '0'; + return Number(num).toFixed(decimals); + } + + /** + * 요일 반환 + */ + getDayOfWeek(date) { + const days = ['일', '월', '화', '수', '목', '금', '토']; + const dateObj = date instanceof Date ? date : new Date(date); + return days[dateObj.getDay()]; + } + + /** + * 오늘인지 확인 + */ + isToday(date) { + const today = this.getKoreaToday(); + const targetDate = this.formatDateForApi(date); + return today === targetDate; + } + + /** + * 두 날짜 사이 일수 계산 + */ + daysBetween(date1, date2) { + const d1 = new Date(date1); + const d2 = new Date(date2); + const diffTime = Math.abs(d2 - d1); + return Math.ceil(diffTime / (1000 * 60 * 60 * 24)); + } + + /** + * 디바운스 함수 + */ + debounce(func, wait) { + let timeout; + return function executedFunction(...args) { + const later = () => { + clearTimeout(timeout); + func(...args); + }; + clearTimeout(timeout); + timeout = setTimeout(later, wait); + }; + } + + /** + * 쓰로틀 함수 + */ + throttle(func, limit) { + let inThrottle; + return function(...args) { + if (!inThrottle) { + func.apply(this, args); + inThrottle = true; + setTimeout(() => inThrottle = false, limit); + } + }; + } + + /** + * HTML 이스케이프 + */ + escapeHtml(text) { + if (!text) return ''; + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } + + /** + * 객체 깊은 복사 + */ + deepClone(obj) { + return JSON.parse(JSON.stringify(obj)); + } + + /** + * 빈 값 확인 + */ + isEmpty(value) { + if (value === null || value === undefined) return true; + if (typeof value === 'string') return value.trim() === ''; + if (Array.isArray(value)) return value.length === 0; + if (typeof value === 'object') return Object.keys(value).length === 0; + return false; + } + + /** + * 숫자 유효성 검사 + */ + isValidNumber(value) { + return !isNaN(value) && isFinite(value); + } + + /** + * 시간 유효성 검사 (0-24) + */ + isValidHours(hours) { + const num = parseFloat(hours); + return this.isValidNumber(num) && num >= 0 && num <= 24; + } + + /** + * 쿼리 스트링 파싱 + */ + parseQueryString(queryString) { + const params = new URLSearchParams(queryString); + const result = {}; + for (const [key, value] of params) { + result[key] = value; + } + return result; + } + + /** + * 쿼리 스트링 생성 + */ + buildQueryString(params) { + return new URLSearchParams(params).toString(); + } + + /** + * 로컬 스토리지 안전하게 가져오기 + */ + getLocalStorage(key, defaultValue = null) { + try { + const item = localStorage.getItem(key); + return item ? JSON.parse(item) : defaultValue; + } catch (error) { + console.error('[Utils] localStorage 읽기 오류:', error); + return defaultValue; + } + } + + /** + * 로컬 스토리지 안전하게 저장하기 + */ + setLocalStorage(key, value) { + try { + localStorage.setItem(key, JSON.stringify(value)); + return true; + } catch (error) { + console.error('[Utils] localStorage 저장 오류:', error); + return false; + } + } + + /** + * 배열 그룹화 + */ + groupBy(array, key) { + return array.reduce((result, item) => { + const groupKey = typeof key === 'function' ? key(item) : item[key]; + if (!result[groupKey]) { + result[groupKey] = []; + } + result[groupKey].push(item); + return result; + }, {}); + } + + /** + * 배열 정렬 (다중 키) + */ + sortBy(array, ...keys) { + return [...array].sort((a, b) => { + for (const key of keys) { + const direction = key.startsWith('-') ? -1 : 1; + const actualKey = key.replace(/^-/, ''); + const aVal = a[actualKey]; + const bVal = b[actualKey]; + + if (aVal < bVal) return -1 * direction; + if (aVal > bVal) return 1 * direction; + } + return 0; + }); + } + + /** + * UUID 생성 + */ + generateUUID() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + const r = Math.random() * 16 | 0; + const v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } +} + +// 전역 인스턴스 생성 +window.DailyWorkReportUtils = new DailyWorkReportUtils(); + +// 하위 호환성: 기존 함수들 +window.getKoreaToday = () => window.DailyWorkReportUtils.getKoreaToday(); +window.formatDateForApi = (date) => window.DailyWorkReportUtils.formatDateForApi(date); +window.formatDate = (date) => window.DailyWorkReportUtils.formatDate(date); +window.getStatusLabel = (status) => window.DailyWorkReportUtils.getStatusLabel(status); + +// 메시지 표시 함수들 +window.showMessage = function(message, type = 'info') { + const container = document.getElementById('message-container'); + if (!container) { + console.log(`[Message] ${type}: ${message}`); + return; + } + + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => window.hideMessage(), 5000); + } +}; + +window.hideMessage = function() { + const container = document.getElementById('message-container'); + if (container) { + container.innerHTML = ''; + } +}; + +// 저장 결과 모달 +window.showSaveResultModal = function(type, title, message, details = null) { + const modal = document.getElementById('saveResultModal'); + const titleElement = document.getElementById('resultModalTitle'); + const contentElement = document.getElementById('resultModalContent'); + + if (!modal || !contentElement) { + alert(`${title}\n\n${message}`); + return; + } + + const icons = { + success: '✅', + error: '❌', + warning: '⚠️', + info: 'ℹ️' + }; + + let content = ` +
${icons[type] || icons.info}
+

${title}

+

${message}

+ `; + + if (details) { + if (Array.isArray(details) && details.length > 0) { + content += ` +
+

상세 정보:

+
    ${details.map(d => `
  • ${d}
  • `).join('')}
+
+ `; + } else if (typeof details === 'string') { + content += `

${details}

`; + } + } + + if (titleElement) titleElement.textContent = '저장 결과'; + contentElement.innerHTML = content; + modal.style.display = 'flex'; + + // ESC 키로 닫기 + const escHandler = (e) => { + if (e.key === 'Escape') { + window.closeSaveResultModal(); + document.removeEventListener('keydown', escHandler); + } + }; + document.addEventListener('keydown', escHandler); + + // 배경 클릭으로 닫기 + modal.onclick = (e) => { + if (e.target === modal) { + window.closeSaveResultModal(); + } + }; +}; + +window.closeSaveResultModal = function() { + const modal = document.getElementById('saveResultModal'); + if (modal) { + modal.style.display = 'none'; + } +}; + +// 단계 이동 함수 +window.goToStep = function(stepNumber) { + const state = window.DailyWorkReportState; + + for (let i = 1; i <= 3; i++) { + const step = document.getElementById(`step${i}`); + if (step) { + step.classList.remove('active', 'completed'); + if (i < stepNumber) { + step.classList.add('completed'); + const stepNum = step.querySelector('.step-number'); + if (stepNum) stepNum.classList.add('completed'); + } else if (i === stepNumber) { + step.classList.add('active'); + } + } + } + + window.updateProgressSteps(stepNumber); + state.currentStep = stepNumber; +}; + +window.updateProgressSteps = function(currentStepNumber) { + for (let i = 1; i <= 3; i++) { + const progressStep = document.getElementById(`progressStep${i}`); + if (progressStep) { + progressStep.classList.remove('active', 'completed'); + if (i < currentStepNumber) { + progressStep.classList.add('completed'); + } else if (i === currentStepNumber) { + progressStep.classList.add('active'); + } + } + } +}; + +// 토스트 메시지 (간단 버전) +window.showToast = function(message, type = 'info', duration = 3000) { + console.log(`[Toast] ${type}: ${message}`); + + // 기존 토스트 제거 + const existingToast = document.querySelector('.toast-message'); + if (existingToast) { + existingToast.remove(); + } + + // 새 토스트 생성 + const toast = document.createElement('div'); + toast.className = `toast-message toast-${type}`; + toast.textContent = message; + toast.style.cssText = ` + position: fixed; + bottom: 20px; + right: 20px; + padding: 12px 20px; + border-radius: 8px; + color: white; + font-size: 14px; + z-index: 10000; + animation: slideIn 0.3s ease; + background-color: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : type === 'warning' ? '#f59e0b' : '#3b82f6'}; + `; + + document.body.appendChild(toast); + + setTimeout(() => { + toast.style.animation = 'slideOut 0.3s ease'; + setTimeout(() => toast.remove(), 300); + }, duration); +}; + +// 확인 다이얼로그 +window.showConfirmDialog = function(message, onConfirm, onCancel) { + if (confirm(message)) { + onConfirm?.(); + } else { + onCancel?.(); + } +}; diff --git a/deploy/tkfb-package/web-ui/js/department-management.js b/deploy/tkfb-package/web-ui/js/department-management.js new file mode 100644 index 0000000..5207204 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/department-management.js @@ -0,0 +1,339 @@ +// department-management.js +// 부서 관리 페이지 JavaScript + +let departments = []; +let selectedDepartmentId = null; +let selectedWorkers = new Set(); + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', async () => { + await waitForApiConfig(); + await loadDepartments(); +}); + +// API 설정 로드 대기 +async function waitForApiConfig() { + let retryCount = 0; + while (!window.apiCall && retryCount < 50) { + await new Promise(resolve => setTimeout(resolve, 100)); + retryCount++; + } + if (!window.apiCall) { + console.error('API 설정 로드 실패'); + } +} + +// 부서 목록 로드 +async function loadDepartments() { + try { + const result = await window.apiCall('/departments'); + + if (result.success) { + departments = result.data; + renderDepartmentList(); + updateMoveToDepartmentSelect(); + } + } catch (error) { + console.error('부서 목록 로드 실패:', error); + } +} + +// 부서 목록 렌더링 +function renderDepartmentList() { + const container = document.getElementById('departmentList'); + + if (departments.length === 0) { + container.innerHTML = ` +
+ 등록된 부서가 없습니다.
+ +
+ `; + return; + } + + container.innerHTML = departments.map(dept => ` +
+
+ ${dept.department_name} + ${dept.worker_count || 0}명 +
+
+ + +
+
+ `).join(''); +} + +// 부서 선택 +async function selectDepartment(departmentId) { + selectedDepartmentId = departmentId; + selectedWorkers.clear(); + updateBulkActions(); + renderDepartmentList(); + + const dept = departments.find(d => d.department_id === departmentId); + document.getElementById('workerListTitle').textContent = `${dept.department_name} 작업자`; + document.getElementById('addWorkerBtn').style.display = 'inline-flex'; + + await loadWorkers(departmentId); +} + +// 부서별 작업자 로드 +async function loadWorkers(departmentId) { + try { + const result = await window.apiCall(`/departments/${departmentId}/workers`); + + if (result.success) { + renderWorkerList(result.data); + } + } catch (error) { + console.error('작업자 목록 로드 실패:', error); + } +} + +// 작업자 목록 렌더링 +function renderWorkerList(workers) { + const container = document.getElementById('workerList'); + + if (workers.length === 0) { + container.innerHTML = ` +
+ 이 부서에 소속된 작업자가 없습니다. +
+ `; + return; + } + + container.innerHTML = workers.map(worker => ` +
+
+ +
${worker.worker_name.charAt(0)}
+
+ ${worker.worker_name} + ${getJobTypeName(worker.job_type)} +
+
+
+ `).join(''); +} + +// 직책 한글 변환 +function getJobTypeName(jobType) { + const names = { + leader: '그룹장', + worker: '작업자', + admin: '관리자' + }; + return names[jobType] || jobType || '-'; +} + +// 작업자 선택 토글 +function toggleWorkerSelection(workerId) { + if (selectedWorkers.has(workerId)) { + selectedWorkers.delete(workerId); + } else { + selectedWorkers.add(workerId); + } + updateBulkActions(); + + // 선택 상태 업데이트 + const card = document.querySelector(`.worker-card[onclick*="${workerId}"]`); + if (card) { + card.classList.toggle('selected', selectedWorkers.has(workerId)); + const checkbox = card.querySelector('input[type="checkbox"]'); + if (checkbox) checkbox.checked = selectedWorkers.has(workerId); + } +} + +// 일괄 작업 영역 업데이트 +function updateBulkActions() { + const bulkActions = document.getElementById('bulkActions'); + const selectedCount = document.getElementById('selectedCount'); + + if (selectedWorkers.size > 0) { + bulkActions.classList.add('visible'); + selectedCount.textContent = selectedWorkers.size; + } else { + bulkActions.classList.remove('visible'); + } +} + +// 이동 대상 부서 선택 업데이트 +function updateMoveToDepartmentSelect() { + const select = document.getElementById('moveToDepartment'); + select.innerHTML = '' + + departments.map(d => ``).join(''); +} + +// 선택한 작업자 이동 +async function moveSelectedWorkers() { + const targetDepartmentId = document.getElementById('moveToDepartment').value; + + if (!targetDepartmentId) { + alert('이동할 부서를 선택하세요.'); + return; + } + + if (selectedWorkers.size === 0) { + alert('이동할 작업자를 선택하세요.'); + return; + } + + if (parseInt(targetDepartmentId) === selectedDepartmentId) { + alert('같은 부서로는 이동할 수 없습니다.'); + return; + } + + try { + const result = await window.apiCall('/departments/move-workers', 'POST', { + workerIds: Array.from(selectedWorkers), + departmentId: parseInt(targetDepartmentId) + }); + + if (result.success) { + alert(result.message); + selectedWorkers.clear(); + updateBulkActions(); + document.getElementById('moveToDepartment').value = ''; + await loadDepartments(); + await loadWorkers(selectedDepartmentId); + } else { + alert(result.error || '이동 실패'); + } + } catch (error) { + console.error('작업자 이동 실패:', error); + alert('작업자 이동에 실패했습니다.'); + } +} + +// 부서 모달 열기 +function openDepartmentModal(departmentId = null) { + const modal = document.getElementById('departmentModal'); + const title = document.getElementById('departmentModalTitle'); + const form = document.getElementById('departmentForm'); + + // 상위 부서 선택 옵션 업데이트 + const parentSelect = document.getElementById('parentDepartment'); + parentSelect.innerHTML = '' + + departments + .filter(d => d.department_id !== departmentId) + .map(d => ``) + .join(''); + + if (departmentId) { + const dept = departments.find(d => d.department_id === departmentId); + title.textContent = '부서 수정'; + document.getElementById('departmentId').value = dept.department_id; + document.getElementById('departmentName').value = dept.department_name; + document.getElementById('parentDepartment').value = dept.parent_id || ''; + document.getElementById('departmentDescription').value = dept.description || ''; + document.getElementById('displayOrder').value = dept.display_order || 0; + document.getElementById('isActive').checked = dept.is_active; + } else { + title.textContent = '새 부서 등록'; + form.reset(); + document.getElementById('departmentId').value = ''; + document.getElementById('isActive').checked = true; + } + + modal.classList.add('show'); +} + +// 부서 모달 닫기 +function closeDepartmentModal() { + document.getElementById('departmentModal').classList.remove('show'); +} + +// 부서 저장 +async function saveDepartment(event) { + event.preventDefault(); + + const departmentId = document.getElementById('departmentId').value; + const data = { + department_name: document.getElementById('departmentName').value, + parent_id: document.getElementById('parentDepartment').value || null, + description: document.getElementById('departmentDescription').value, + display_order: parseInt(document.getElementById('displayOrder').value) || 0, + is_active: document.getElementById('isActive').checked + }; + + try { + const url = departmentId ? `/departments/${departmentId}` : '/departments'; + const method = departmentId ? 'PUT' : 'POST'; + + const result = await window.apiCall(url, method, data); + + if (result.success) { + alert(result.message); + closeDepartmentModal(); + await loadDepartments(); + } else { + alert(result.error || '저장 실패'); + } + } catch (error) { + console.error('부서 저장 실패:', error); + alert('부서 저장에 실패했습니다.'); + } +} + +// 부서 수정 +function editDepartment(departmentId) { + openDepartmentModal(departmentId); +} + +// 부서 삭제 +async function deleteDepartment(departmentId) { + const dept = departments.find(d => d.department_id === departmentId); + + if (!confirm(`"${dept.department_name}" 부서를 삭제하시겠습니까?\n\n소속 작업자가 있거나 하위 부서가 있으면 삭제할 수 없습니다.`)) { + return; + } + + try { + const result = await window.apiCall(`/departments/${departmentId}`, 'DELETE'); + + if (result.success) { + alert('부서가 삭제되었습니다.'); + if (selectedDepartmentId === departmentId) { + selectedDepartmentId = null; + document.getElementById('workerListTitle').textContent = '부서를 선택하세요'; + document.getElementById('addWorkerBtn').style.display = 'none'; + document.getElementById('workerList').innerHTML = ` +
+ 왼쪽에서 부서를 선택하면 해당 부서의 작업자가 표시됩니다. +
+ `; + } + await loadDepartments(); + } else { + alert(result.error || '삭제 실패'); + } + } catch (error) { + console.error('부서 삭제 실패:', error); + alert('부서 삭제에 실패했습니다.'); + } +} + +// 작업자 추가 모달 (작업자 관리 페이지로 이동) +function openAddWorkerModal() { + alert('작업자 관리 페이지에서 작업자를 등록한 후 이 페이지에서 부서를 배정하세요.'); + // window.location.href = '/pages/admin/workers.html'; +} diff --git a/deploy/tkfb-package/web-ui/js/equipment-detail.js b/deploy/tkfb-package/web-ui/js/equipment-detail.js new file mode 100644 index 0000000..6080674 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/equipment-detail.js @@ -0,0 +1,803 @@ +/** + * equipment-detail.js - 설비 상세 페이지 스크립트 + */ + +// 전역 변수 +let currentEquipment = null; +let equipmentId = null; +let workplaces = []; +let factories = []; +let selectedMovePosition = null; +let repairPhotoBases = []; + +// 상태 라벨 +const STATUS_LABELS = { + active: '정상 가동', + maintenance: '점검 중', + repair_needed: '수리 필요', + inactive: '비활성', + external: '외부 반출', + repair_external: '수리 외주' +}; + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', () => { + // URL에서 equipment_id 추출 + const urlParams = new URLSearchParams(window.location.search); + equipmentId = urlParams.get('id'); + + if (!equipmentId) { + alert('설비 ID가 필요합니다.'); + goBack(); + return; + } + + // API 설정 후 데이터 로드 + waitForApiConfig().then(() => { + loadEquipmentData(); + loadFactories(); + loadRepairCategories(); + }); +}); + +// API 설정 대기 +function waitForApiConfig() { + return new Promise(resolve => { + const check = setInterval(() => { + if (window.API_BASE_URL) { + clearInterval(check); + resolve(); + } + }, 50); + }); +} + +// 뒤로가기 +function goBack() { + if (document.referrer && document.referrer.includes(window.location.host)) { + history.back(); + } else { + window.location.href = '/pages/admin/equipments.html'; + } +} + +// ========================================== +// 설비 데이터 로드 +// ========================================== + +async function loadEquipmentData() { + try { + const response = await axios.get(`/equipments/${equipmentId}`); + if (response.data.success) { + currentEquipment = response.data.data; + renderEquipmentInfo(); + loadPhotos(); + loadRepairHistory(); + loadExternalLogs(); + loadMoveLogs(); + } + } catch (error) { + console.error('설비 정보 로드 실패:', error); + alert('설비 정보를 불러오는데 실패했습니다.'); + } +} + +function renderEquipmentInfo() { + const eq = currentEquipment; + + // 헤더 + document.getElementById('equipmentTitle').textContent = `[${eq.equipment_code}] ${eq.equipment_name}`; + document.getElementById('equipmentMeta').textContent = `${eq.model_name || '-'} | ${eq.manufacturer || '-'}`; + + // 상태 배지 + const statusBadge = document.getElementById('equipmentStatus'); + statusBadge.textContent = STATUS_LABELS[eq.status] || eq.status; + statusBadge.className = `eq-status-badge ${eq.status}`; + + // 기본 정보 카드 + document.getElementById('equipmentInfoCard').innerHTML = ` +
+
+ 관리번호 + ${escapeHtml(eq.equipment_code || '-')} +
+
+ 설비명 + ${escapeHtml(eq.equipment_name || '-')} +
+
+ 모델명 + ${escapeHtml(eq.model_name || '-')} +
+
+ 규격 + ${escapeHtml(eq.specifications || '-')} +
+
+ 제조사 + ${escapeHtml(eq.manufacturer || '-')} +
+
+ 구입처 + ${escapeHtml(eq.supplier || '-')} +
+
+ 구입일 + ${eq.installation_date ? formatDate(eq.installation_date) : '-'} +
+
+ 구입가격 + ${eq.purchase_price ? Number(eq.purchase_price).toLocaleString() + '원' : '-'} +
+
+ 시리얼번호 + ${escapeHtml(eq.serial_number || '-')} +
+
+ 설비유형 + ${escapeHtml(eq.equipment_type || '-')} +
+
+ `; + + // 위치 정보 + const originalLocation = eq.workplace_name + ? `${eq.category_name || ''} > ${eq.workplace_name}` + : '미배정'; + document.getElementById('originalLocation').textContent = originalLocation; + + if (eq.is_temporarily_moved && eq.current_workplace_id) { + document.getElementById('currentLocationRow').style.display = 'flex'; + // 현재 위치 작업장 이름 로드 필요 + loadCurrentWorkplaceName(eq.current_workplace_id); + } + + // 지도 미리보기 (작업장 지도 표시) + renderMapPreview(); +} + +async function loadCurrentWorkplaceName(workplaceId) { + try { + const response = await axios.get(`/workplaces/${workplaceId}`); + if (response.data.success) { + const wp = response.data.data; + document.getElementById('currentLocation').textContent = `${wp.category_name || ''} > ${wp.workplace_name}`; + } + } catch (error) { + console.error('현재 위치 로드 실패:', error); + } +} + +function renderMapPreview() { + const eq = currentEquipment; + const mapPreview = document.getElementById('mapPreview'); + + if (!eq.workplace_id) { + mapPreview.innerHTML = '
위치 미배정
'; + return; + } + + // 작업장 지도 정보 로드 + axios.get(`/workplaces/${eq.workplace_id}`).then(response => { + if (response.data.success && response.data.data.map_image_url) { + const wp = response.data.data; + const xPercent = eq.is_temporarily_moved ? eq.current_map_x_percent : eq.map_x_percent; + const yPercent = eq.is_temporarily_moved ? eq.current_map_y_percent : eq.map_y_percent; + + mapPreview.innerHTML = ` + 작업장 지도 +
+ `; + } else { + mapPreview.innerHTML = '
지도 없음
'; + } + }).catch(() => { + mapPreview.innerHTML = '
지도 로드 실패
'; + }); +} + +// ========================================== +// 사진 관리 +// ========================================== + +async function loadPhotos() { + try { + const response = await axios.get(`/equipments/${equipmentId}/photos`); + if (response.data.success) { + renderPhotos(response.data.data); + } + } catch (error) { + console.error('사진 로드 실패:', error); + } +} + +function renderPhotos(photos) { + const grid = document.getElementById('photoGrid'); + + if (!photos || photos.length === 0) { + grid.innerHTML = '
등록된 사진이 없습니다
'; + return; + } + + grid.innerHTML = photos.map(photo => { + const safePhotoId = parseInt(photo.photo_id) || 0; + const safePhotoPath = encodeURI(photo.photo_path || ''); + const safeDescription = escapeHtml(photo.description || '설비 사진'); + return ` +
+ ${safeDescription} + +
+ `; + }).join(''); +} + +function openPhotoModal() { + document.getElementById('photoInput').value = ''; + document.getElementById('photoDescription').value = ''; + document.getElementById('photoPreviewContainer').style.display = 'none'; + document.getElementById('photoModal').style.display = 'flex'; +} + +function closePhotoModal() { + document.getElementById('photoModal').style.display = 'none'; +} + +function previewPhoto(event) { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = e => { + document.getElementById('photoPreview').src = e.target.result; + document.getElementById('photoPreviewContainer').style.display = 'block'; + }; + reader.readAsDataURL(file); + } +} + +async function uploadPhoto() { + const fileInput = document.getElementById('photoInput'); + const description = document.getElementById('photoDescription').value; + + if (!fileInput.files[0]) { + alert('사진을 선택하세요.'); + return; + } + + const reader = new FileReader(); + reader.onload = async e => { + try { + const response = await axios.post(`/equipments/${equipmentId}/photos`, { + photo_base64: e.target.result, + description: description + }); + + if (response.data.success) { + closePhotoModal(); + loadPhotos(); + alert('사진이 추가되었습니다.'); + } + } catch (error) { + console.error('사진 업로드 실패:', error); + alert('사진 업로드에 실패했습니다.'); + } + }; + reader.readAsDataURL(fileInput.files[0]); +} + +async function deletePhoto(photoId) { + if (!confirm('이 사진을 삭제하시겠습니까?')) return; + + try { + const response = await axios.delete(`/equipments/photos/${photoId}`); + if (response.data.success) { + loadPhotos(); + } + } catch (error) { + console.error('사진 삭제 실패:', error); + alert('사진 삭제에 실패했습니다.'); + } +} + +function viewPhoto(url) { + document.getElementById('photoViewImage').src = url; + document.getElementById('photoViewModal').style.display = 'flex'; +} + +function closePhotoView() { + document.getElementById('photoViewModal').style.display = 'none'; +} + +// ========================================== +// 임시 이동 +// ========================================== + +async function loadFactories() { + try { + const response = await axios.get('/workplace-categories'); + if (response.data.success) { + factories = response.data.data; + } + } catch (error) { + console.error('공장 목록 로드 실패:', error); + } +} + +function openMoveModal() { + // 공장 선택 초기화 + const factorySelect = document.getElementById('moveFactorySelect'); + factorySelect.innerHTML = ''; + factories.forEach(f => { + const safeCategoryId = parseInt(f.category_id) || 0; + factorySelect.innerHTML += ``; + }); + + document.getElementById('moveWorkplaceSelect').innerHTML = ''; + document.getElementById('moveStep2').style.display = 'none'; + document.getElementById('moveStep1').style.display = 'block'; + document.getElementById('moveConfirmBtn').disabled = true; + document.getElementById('moveReason').value = ''; + selectedMovePosition = null; + + document.getElementById('moveModal').style.display = 'flex'; +} + +function closeMoveModal() { + document.getElementById('moveModal').style.display = 'none'; +} + +async function loadMoveWorkplaces() { + const categoryId = document.getElementById('moveFactorySelect').value; + const workplaceSelect = document.getElementById('moveWorkplaceSelect'); + + workplaceSelect.innerHTML = ''; + + if (!categoryId) return; + + try { + const response = await axios.get(`/workplaces?category_id=${categoryId}`); + if (response.data.success) { + workplaces = response.data.data; + workplaces.forEach(wp => { + if (wp.map_image_url) { + const safeWorkplaceId = parseInt(wp.workplace_id) || 0; + workplaceSelect.innerHTML += ``; + } + }); + } + } catch (error) { + console.error('작업장 로드 실패:', error); + } +} + +function loadMoveMap() { + const workplaceId = document.getElementById('moveWorkplaceSelect').value; + + if (!workplaceId) { + document.getElementById('moveStep2').style.display = 'none'; + return; + } + + const workplace = workplaces.find(wp => wp.workplace_id == workplaceId); + if (!workplace || !workplace.map_image_url) { + alert('선택한 작업장에 지도가 없습니다.'); + return; + } + + const container = document.getElementById('moveMapContainer'); + container.innerHTML = ``; + + document.getElementById('moveStep2').style.display = 'block'; +} + +function onMoveMapClick(event) { + const img = event.target; + const rect = img.getBoundingClientRect(); + const x = ((event.clientX - rect.left) / rect.width) * 100; + const y = ((event.clientY - rect.top) / rect.height) * 100; + + selectedMovePosition = { x, y }; + + // 기존 마커 제거 + const container = document.getElementById('moveMapContainer'); + const existingMarker = container.querySelector('.move-marker'); + if (existingMarker) existingMarker.remove(); + + // 새 마커 추가 + const marker = document.createElement('div'); + marker.className = 'move-marker'; + marker.style.left = x + '%'; + marker.style.top = y + '%'; + container.appendChild(marker); + + document.getElementById('moveConfirmBtn').disabled = false; +} + +async function confirmMove() { + const targetWorkplaceId = document.getElementById('moveWorkplaceSelect').value; + const reason = document.getElementById('moveReason').value; + + if (!targetWorkplaceId || !selectedMovePosition) { + alert('이동할 위치를 선택하세요.'); + return; + } + + try { + const response = await axios.post(`/equipments/${equipmentId}/move`, { + target_workplace_id: targetWorkplaceId, + target_x_percent: selectedMovePosition.x.toFixed(2), + target_y_percent: selectedMovePosition.y.toFixed(2), + from_workplace_id: currentEquipment.workplace_id, + from_x_percent: currentEquipment.map_x_percent, + from_y_percent: currentEquipment.map_y_percent, + reason: reason + }); + + if (response.data.success) { + closeMoveModal(); + loadEquipmentData(); + loadMoveLogs(); + alert('설비가 임시 이동되었습니다.'); + } + } catch (error) { + console.error('이동 실패:', error); + alert('설비 이동에 실패했습니다.'); + } +} + +async function returnToOriginal() { + if (!confirm('설비를 원래 위치로 복귀시키겠습니까?')) return; + + try { + const response = await axios.post(`/equipments/${equipmentId}/return`); + if (response.data.success) { + loadEquipmentData(); + loadMoveLogs(); + alert('설비가 원위치로 복귀되었습니다.'); + } + } catch (error) { + console.error('복귀 실패:', error); + alert('설비 복귀에 실패했습니다.'); + } +} + +// ========================================== +// 수리 신청 +// ========================================== + +let repairCategories = []; + +async function loadRepairCategories() { + try { + const response = await axios.get('/equipments/repair-categories'); + if (response.data.success) { + repairCategories = response.data.data; + } + } catch (error) { + console.error('수리 항목 로드 실패:', error); + } +} + +function openRepairModal() { + const select = document.getElementById('repairItemSelect'); + select.innerHTML = ''; + repairCategories.forEach(item => { + const safeItemId = parseInt(item.item_id) || 0; + select.innerHTML += ``; + }); + + document.getElementById('repairDescription').value = ''; + document.getElementById('repairPhotoInput').value = ''; + document.getElementById('repairPhotoPreviews').innerHTML = ''; + repairPhotoBases = []; + + document.getElementById('repairModal').style.display = 'flex'; +} + +function closeRepairModal() { + document.getElementById('repairModal').style.display = 'none'; +} + +function previewRepairPhotos(event) { + const files = event.target.files; + const previewContainer = document.getElementById('repairPhotoPreviews'); + previewContainer.innerHTML = ''; + repairPhotoBases = []; + + Array.from(files).forEach(file => { + const reader = new FileReader(); + reader.onload = e => { + repairPhotoBases.push(e.target.result); + const img = document.createElement('img'); + img.src = e.target.result; + img.className = 'repair-photo-preview'; + previewContainer.appendChild(img); + }; + reader.readAsDataURL(file); + }); +} + +async function submitRepairRequest() { + const itemId = document.getElementById('repairItemSelect').value; + const description = document.getElementById('repairDescription').value; + + if (!description) { + alert('수리 내용을 입력하세요.'); + return; + } + + try { + const response = await axios.post(`/equipments/${equipmentId}/repair-request`, { + item_id: itemId || null, + description: description, + photo_base64_list: repairPhotoBases, + workplace_id: currentEquipment.workplace_id + }); + + if (response.data.success) { + closeRepairModal(); + loadEquipmentData(); + loadRepairHistory(); + alert('수리 신청이 접수되었습니다.'); + } + } catch (error) { + console.error('수리 신청 실패:', error); + alert('수리 신청에 실패했습니다.'); + } +} + +async function loadRepairHistory() { + try { + const response = await axios.get(`/equipments/${equipmentId}/repair-history`); + if (response.data.success) { + renderRepairHistory(response.data.data); + } + } catch (error) { + console.error('수리 이력 로드 실패:', error); + } +} + +function renderRepairHistory(history) { + const container = document.getElementById('repairHistory'); + + if (!history || history.length === 0) { + container.innerHTML = '
수리 이력이 없습니다
'; + return; + } + + const validStatuses = ['pending', 'in_progress', 'completed', 'closed']; + container.innerHTML = history.map(h => { + const safeStatus = validStatuses.includes(h.status) ? h.status : 'pending'; + return ` +
+ ${formatDate(h.created_at)} +
+
${escapeHtml(h.item_name || '수리 요청')}
+
${escapeHtml(h.description || '-')}
+
+ ${getRepairStatusLabel(h.status)} +
+ `; + }).join(''); +} + +function getRepairStatusLabel(status) { + const labels = { + pending: '대기중', + in_progress: '처리중', + completed: '완료', + closed: '종료' + }; + return labels[status] || status; +} + +// ========================================== +// 외부 반출 +// ========================================== + +function openExportModal() { + document.getElementById('exportDate').value = new Date().toISOString().slice(0, 10); + document.getElementById('expectedReturnDate').value = ''; + document.getElementById('exportDestination').value = ''; + document.getElementById('exportReason').value = ''; + document.getElementById('exportNotes').value = ''; + document.getElementById('isRepairExport').checked = false; + + document.getElementById('exportModal').style.display = 'flex'; +} + +function closeExportModal() { + document.getElementById('exportModal').style.display = 'none'; +} + +function toggleRepairFields() { + // 현재는 특별한 필드 차이 없음 +} + +async function submitExport() { + const exportDate = document.getElementById('exportDate').value; + const expectedReturnDate = document.getElementById('expectedReturnDate').value; + const destination = document.getElementById('exportDestination').value; + const reason = document.getElementById('exportReason').value; + const notes = document.getElementById('exportNotes').value; + const isRepair = document.getElementById('isRepairExport').checked; + + if (!exportDate) { + alert('반출일을 입력하세요.'); + return; + } + + try { + const response = await axios.post(`/equipments/${equipmentId}/export`, { + export_date: exportDate, + expected_return_date: expectedReturnDate || null, + destination: destination, + reason: reason, + notes: notes, + is_repair: isRepair + }); + + if (response.data.success) { + closeExportModal(); + loadEquipmentData(); + loadExternalLogs(); + alert('외부 반출이 등록되었습니다.'); + } + } catch (error) { + console.error('반출 등록 실패:', error); + alert('반출 등록에 실패했습니다.'); + } +} + +async function loadExternalLogs() { + try { + const response = await axios.get(`/equipments/${equipmentId}/external-logs`); + if (response.data.success) { + renderExternalLogs(response.data.data); + } + } catch (error) { + console.error('외부반출 이력 로드 실패:', error); + } +} + +function renderExternalLogs(logs) { + const container = document.getElementById('externalHistory'); + + if (!logs || logs.length === 0) { + container.innerHTML = '
외부반출 이력이 없습니다
'; + return; + } + + container.innerHTML = logs.map(log => { + const dateRange = log.actual_return_date + ? `${formatDate(log.export_date)} ~ ${formatDate(log.actual_return_date)}` + : `${formatDate(log.export_date)} ~ (미반입)`; + + const isReturned = !!log.actual_return_date; + const statusClass = isReturned ? 'returned' : 'exported'; + const statusLabel = isReturned ? '반입완료' : '반출중'; + const safeLogId = parseInt(log.log_id) || 0; + + return ` +
+ ${dateRange} +
+
${escapeHtml(log.destination || '외부')}
+
${escapeHtml(log.reason || '-')}
+
+ ${statusLabel} + ${!isReturned ? `` : ''} +
+ `; + }).join(''); +} + +function openReturnModal(logId) { + document.getElementById('returnLogId').value = logId; + document.getElementById('returnDate').value = new Date().toISOString().slice(0, 10); + document.getElementById('returnStatus').value = 'active'; + document.getElementById('returnNotes').value = ''; + + document.getElementById('returnModal').style.display = 'flex'; +} + +function closeReturnModal() { + document.getElementById('returnModal').style.display = 'none'; +} + +async function submitReturn() { + const logId = document.getElementById('returnLogId').value; + const returnDate = document.getElementById('returnDate').value; + const newStatus = document.getElementById('returnStatus').value; + const notes = document.getElementById('returnNotes').value; + + if (!returnDate) { + alert('반입일을 입력하세요.'); + return; + } + + try { + const response = await axios.post(`/equipments/external-logs/${logId}/return`, { + return_date: returnDate, + new_status: newStatus, + notes: notes + }); + + if (response.data.success) { + closeReturnModal(); + loadEquipmentData(); + loadExternalLogs(); + alert('반입 처리가 완료되었습니다.'); + } + } catch (error) { + console.error('반입 처리 실패:', error); + alert('반입 처리에 실패했습니다.'); + } +} + +// ========================================== +// 이동 이력 +// ========================================== + +async function loadMoveLogs() { + try { + const response = await axios.get(`/equipments/${equipmentId}/move-logs`); + if (response.data.success) { + renderMoveLogs(response.data.data); + } + } catch (error) { + console.error('이동 이력 로드 실패:', error); + } +} + +function renderMoveLogs(logs) { + const container = document.getElementById('moveHistory'); + + if (!logs || logs.length === 0) { + container.innerHTML = '
이동 이력이 없습니다
'; + return; + } + + container.innerHTML = logs.map(log => { + const typeLabel = log.move_type === 'temporary' ? '임시이동' : '복귀'; + const location = log.move_type === 'temporary' + ? escapeHtml(log.to_workplace_name || '-') + : '원위치 복귀'; + + return ` +
+ ${formatDateTime(log.moved_at)} +
+
${typeLabel}: ${location}
+
${escapeHtml(log.reason || '-')} (${escapeHtml(log.moved_by_name || '시스템')})
+
+
+ `; + }).join(''); +} + +// ========================================== +// 유틸리티 +// ========================================== + +function formatDate(dateStr) { + if (!dateStr) return '-'; + const date = new Date(dateStr); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }).replace(/\. /g, '-').replace('.', ''); +} + +function formatDateTime(dateStr) { + if (!dateStr) return '-'; + const date = new Date(dateStr); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); +} diff --git a/deploy/tkfb-package/web-ui/js/equipment-management.js b/deploy/tkfb-package/web-ui/js/equipment-management.js new file mode 100644 index 0000000..941a64f --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/equipment-management.js @@ -0,0 +1,469 @@ +// equipment-management.js +// 설비 관리 페이지 JavaScript + +let equipments = []; +let allEquipments = []; // 필터링 전 전체 데이터 +let workplaces = []; +let equipmentTypes = []; +let currentEquipment = null; + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', async () => { + await waitForAxiosConfig(); + await loadInitialData(); +}); + +// axios 설정 대기 함수 +function waitForAxiosConfig() { + return new Promise((resolve) => { + const check = setInterval(() => { + if (axios.defaults.baseURL) { + clearInterval(check); + resolve(); + } + }, 50); + setTimeout(() => { + clearInterval(check); + if (!axios.defaults.baseURL) { + console.error('Axios 설정 시간 초과'); + } + resolve(); + }, 5000); + }); +} + +// 초기 데이터 로드 +async function loadInitialData() { + try { + await Promise.all([ + loadEquipments(), + loadWorkplaces(), + loadEquipmentTypes() + ]); + } catch (error) { + console.error('초기 데이터 로드 실패:', error); + alert('데이터를 불러오는데 실패했습니다.'); + } +} + +// 설비 목록 로드 +async function loadEquipments() { + try { + const response = await axios.get('/equipments'); + if (response.data.success) { + allEquipments = response.data.data; + equipments = [...allEquipments]; + renderStats(); + renderEquipmentList(); + } + } catch (error) { + console.error('설비 목록 로드 실패:', error); + throw error; + } +} + +// 작업장 목록 로드 +async function loadWorkplaces() { + try { + const response = await axios.get('/workplaces'); + if (response.data.success) { + workplaces = response.data.data; + populateWorkplaceFilters(); + } + } catch (error) { + console.error('작업장 목록 로드 실패:', error); + } +} + +// 설비 유형 목록 로드 +async function loadEquipmentTypes() { + try { + const response = await axios.get('/equipments/types'); + if (response.data.success) { + equipmentTypes = response.data.data; + populateTypeFilter(); + } + } catch (error) { + console.error('설비 유형 로드 실패:', error); + } +} + +// 통계 렌더링 +function renderStats() { + const container = document.getElementById('statsSection'); + if (!container) return; + + const totalCount = allEquipments.length; + const activeCount = allEquipments.filter(e => e.status === 'active').length; + const maintenanceCount = allEquipments.filter(e => e.status === 'maintenance').length; + const inactiveCount = allEquipments.filter(e => e.status === 'inactive').length; + + const totalValue = allEquipments.reduce((sum, e) => sum + (Number(e.purchase_price) || 0), 0); + const avgValue = totalCount > 0 ? totalValue / totalCount : 0; + + container.innerHTML = ` +
+
전체 설비
+
${totalCount}대
+
총 자산가치 ${formatPriceShort(totalValue)}
+
+
+
활성
+
${activeCount}대
+
${totalCount > 0 ? Math.round(activeCount / totalCount * 100) : 0}%
+
+
+
정비중
+
${maintenanceCount}대
+
${totalCount > 0 ? Math.round(maintenanceCount / totalCount * 100) : 0}%
+
+
+
비활성
+
${inactiveCount}대
+
${totalCount > 0 ? Math.round(inactiveCount / totalCount * 100) : 0}%
+
+
+
평균 구입가
+
${formatPriceShort(avgValue)}
+
설비당 평균
+
+ `; +} + +// 작업장 필터 채우기 +function populateWorkplaceFilters() { + const filterWorkplace = document.getElementById('filterWorkplace'); + const modalWorkplace = document.getElementById('workplaceId'); + + const workplaceOptions = workplaces.map(w => { + const safeId = parseInt(w.workplace_id) || 0; + const categoryName = escapeHtml(w.category_name || ''); + const workplaceName = escapeHtml(w.workplace_name || ''); + const label = categoryName ? categoryName + ' - ' + workplaceName : workplaceName; + return ``; + }).join(''); + + if (filterWorkplace) filterWorkplace.innerHTML = '' + workplaceOptions; + if (modalWorkplace) modalWorkplace.innerHTML = '' + workplaceOptions; +} + +// 설비 유형 필터 채우기 +function populateTypeFilter() { + const filterType = document.getElementById('filterType'); + if (!filterType) return; + + const typeOptions = equipmentTypes.map(type => { + const safeType = escapeHtml(type || ''); + return ``; + }).join(''); + filterType.innerHTML = '' + typeOptions; +} + +// 설비 목록 렌더링 +function renderEquipmentList() { + const container = document.getElementById('equipmentList'); + + if (equipments.length === 0) { + container.innerHTML = ` +
+

등록된 설비가 없습니다.

+ +
+ `; + return; + } + + const tableHTML = ` +
+ 검색 결과 ${equipments.length}건 +
+
+ + + + + + + + + + + + + + + + + ${equipments.map(eq => { + const safeId = parseInt(eq.equipment_id) || 0; + const safeCode = escapeHtml(eq.equipment_code || '-'); + const safeName = escapeHtml(eq.equipment_name || '-'); + const safeModel = escapeHtml(eq.model_name || '-'); + const safeSpec = escapeHtml(eq.specifications || '-'); + const safeManufacturer = escapeHtml(eq.manufacturer || '-'); + const safeSupplier = escapeHtml(eq.supplier || '-'); + const validStatuses = ['active', 'maintenance', 'inactive']; + const safeStatus = validStatuses.includes(eq.status) ? eq.status : 'inactive'; + return ` + + + + + + + + + + + + + `; + }).join('')} + +
관리번호설비명모델명규격제조사구입처구입가격구입일자상태관리
${safeCode}${safeName}${safeModel}${safeSpec}${safeManufacturer}${safeSupplier}${eq.purchase_price ? formatPrice(eq.purchase_price) : '-'}${eq.installation_date ? formatDate(eq.installation_date) : '-'} + + ${getStatusText(eq.status)} + + +
+ + +
+
+
+ `; + + container.innerHTML = tableHTML; +} + +// 상태 텍스트 변환 +function getStatusText(status) { + const statusMap = { + 'active': '활성', + 'maintenance': '정비중', + 'inactive': '비활성' + }; + return statusMap[status] || status || '-'; +} + +// 가격 포맷팅 (전체) +function formatPrice(price) { + if (!price) return '-'; + return Number(price).toLocaleString('ko-KR') + '원'; +} + +// 가격 포맷팅 (축약) +function formatPriceShort(price) { + if (!price) return '0원'; + const num = Number(price); + if (num >= 100000000) { + return (num / 100000000).toFixed(1).replace(/\.0$/, '') + '억원'; + } else if (num >= 10000) { + return (num / 10000).toFixed(0) + '만원'; + } + return num.toLocaleString('ko-KR') + '원'; +} + +// 날짜 포맷팅 +function formatDate(dateStr) { + if (!dateStr) return '-'; + const date = new Date(dateStr); + return date.toLocaleDateString('ko-KR', { year: 'numeric', month: '2-digit', day: '2-digit' }); +} + +// 필터링 +function filterEquipments() { + const workplaceFilter = document.getElementById('filterWorkplace').value; + const typeFilter = document.getElementById('filterType').value; + const statusFilter = document.getElementById('filterStatus').value; + const searchTerm = document.getElementById('searchInput').value.toLowerCase(); + + equipments = allEquipments.filter(e => { + if (workplaceFilter && e.workplace_id != workplaceFilter) return false; + if (typeFilter && e.equipment_type !== typeFilter) return false; + if (statusFilter && e.status !== statusFilter) return false; + if (searchTerm) { + const searchFields = [ + e.equipment_name, + e.equipment_code, + e.manufacturer, + e.supplier, + e.model_name + ].map(f => (f || '').toLowerCase()); + if (!searchFields.some(f => f.includes(searchTerm))) return false; + } + return true; + }); + + renderEquipmentList(); +} + +// 설비 추가 모달 열기 +async function openEquipmentModal(equipmentId = null) { + currentEquipment = equipmentId; + const modal = document.getElementById('equipmentModal'); + const modalTitle = document.getElementById('modalTitle'); + const form = document.getElementById('equipmentForm'); + + form.reset(); + document.getElementById('equipmentId').value = ''; + + if (equipmentId) { + modalTitle.textContent = '설비 수정'; + loadEquipmentData(equipmentId); + } else { + modalTitle.textContent = '설비 추가'; + // 새 설비일 경우 다음 관리번호 자동 생성 + await loadNextEquipmentCode(); + } + + modal.style.display = 'flex'; +} + +// 다음 관리번호 로드 +async function loadNextEquipmentCode() { + try { + console.log('📋 다음 관리번호 조회 중...'); + const response = await axios.get('/equipments/next-code'); + console.log('📋 다음 관리번호 응답:', response.data); + if (response.data.success) { + document.getElementById('equipmentCode').value = response.data.data.next_code; + console.log('✅ 다음 관리번호 설정:', response.data.data.next_code); + } + } catch (error) { + console.error('❌ 다음 관리번호 조회 실패:', error); + console.error('❌ 에러 상세:', error.response?.data || error.message); + // 오류 시 기본값으로 빈 값 유지 (사용자가 직접 입력) + } +} + +// 설비 데이터 로드 (수정용) +async function loadEquipmentData(equipmentId) { + try { + const response = await axios.get(`/equipments/${equipmentId}`); + if (response.data.success) { + const eq = response.data.data; + + document.getElementById('equipmentId').value = eq.equipment_id; + document.getElementById('equipmentCode').value = eq.equipment_code || ''; + document.getElementById('equipmentName').value = eq.equipment_name || ''; + document.getElementById('equipmentType').value = eq.equipment_type || ''; + document.getElementById('workplaceId').value = eq.workplace_id || ''; + document.getElementById('manufacturer').value = eq.manufacturer || ''; + document.getElementById('supplier').value = eq.supplier || ''; + document.getElementById('purchasePrice').value = eq.purchase_price || ''; + document.getElementById('modelName').value = eq.model_name || ''; + document.getElementById('serialNumber').value = eq.serial_number || ''; + document.getElementById('installationDate').value = eq.installation_date ? eq.installation_date.split('T')[0] : ''; + document.getElementById('equipmentStatus').value = eq.status || 'active'; + document.getElementById('specifications').value = eq.specifications || ''; + document.getElementById('notes').value = eq.notes || ''; + } + } catch (error) { + console.error('설비 데이터 로드 실패:', error); + alert('설비 정보를 불러오는데 실패했습니다.'); + } +} + +// 설비 모달 닫기 +function closeEquipmentModal() { + document.getElementById('equipmentModal').style.display = 'none'; + currentEquipment = null; +} + +// 설비 저장 +async function saveEquipment() { + const equipmentId = document.getElementById('equipmentId').value; + const equipmentData = { + equipment_code: document.getElementById('equipmentCode').value.trim(), + equipment_name: document.getElementById('equipmentName').value.trim(), + equipment_type: document.getElementById('equipmentType').value.trim() || null, + workplace_id: document.getElementById('workplaceId').value || null, + manufacturer: document.getElementById('manufacturer').value.trim() || null, + supplier: document.getElementById('supplier').value.trim() || null, + purchase_price: document.getElementById('purchasePrice').value || null, + model_name: document.getElementById('modelName').value.trim() || null, + serial_number: document.getElementById('serialNumber').value.trim() || null, + installation_date: document.getElementById('installationDate').value || null, + status: document.getElementById('equipmentStatus').value, + specifications: document.getElementById('specifications').value.trim() || null, + notes: document.getElementById('notes').value.trim() || null + }; + + if (!equipmentData.equipment_code) { + alert('관리번호를 입력해주세요.'); + return; + } + + if (!equipmentData.equipment_name) { + alert('설비명을 입력해주세요.'); + return; + } + + try { + let response; + if (equipmentId) { + response = await axios.put(`/equipments/${equipmentId}`, equipmentData); + } else { + response = await axios.post('/equipments', equipmentData); + } + + if (response.data.success) { + alert(equipmentId ? '설비가 수정되었습니다.' : '설비가 추가되었습니다.'); + closeEquipmentModal(); + await loadEquipments(); + await loadEquipmentTypes(); + } + } catch (error) { + console.error('설비 저장 실패:', error); + if (error.response?.data?.message) { + alert(error.response.data.message); + } else { + alert('설비 저장 중 오류가 발생했습니다.'); + } + } +} + +// 설비 수정 +function editEquipment(equipmentId) { + openEquipmentModal(equipmentId); +} + +// 설비 삭제 +async function deleteEquipment(equipmentId) { + const equipment = allEquipments.find(e => e.equipment_id === equipmentId); + if (!equipment) return; + + if (!confirm(`'${equipment.equipment_name}' 설비를 삭제하시겠습니까?`)) { + return; + } + + try { + const response = await axios.delete(`/equipments/${equipmentId}`); + if (response.data.success) { + alert('설비가 삭제되었습니다.'); + await loadEquipments(); + } + } catch (error) { + console.error('설비 삭제 실패:', error); + alert('설비 삭제 중 오류가 발생했습니다.'); + } +} + +// ESC 키로 모달 닫기 +document.addEventListener('keydown', (e) => { + if (e.key === 'Escape') { + closeEquipmentModal(); + } +}); + +// 모달 외부 클릭 시 닫기 +document.getElementById('equipmentModal')?.addEventListener('click', (e) => { + if (e.target.id === 'equipmentModal') { + closeEquipmentModal(); + } +}); diff --git a/deploy/tkfb-package/web-ui/js/factory-upload.js b/deploy/tkfb-package/web-ui/js/factory-upload.js new file mode 100644 index 0000000..e2288ce --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/factory-upload.js @@ -0,0 +1,49 @@ +import { API, getAuthHeaders } from '/js/api-config.js'; + +document.getElementById('uploadForm').addEventListener('submit', async (e) => { + e.preventDefault(); + const formData = new FormData(e.target); + + try { + // FormData를 사용할 때는 Content-Type을 설정하지 않음 (자동 설정됨) + const token = localStorage.getItem('token'); + const res = await fetch(`${API}/factoryinfo`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}` + }, + body: formData + }); + + if (!res.ok) { + const error = await res.json(); + throw new Error(error.message || '등록 실패'); + } + + alert('등록 완료!'); + location.reload(); + } catch (err) { + console.error(err); + alert('등록 실패: ' + err.message); + } +}); + +// 파일 선택 시 미리보기 (선택사항) +const fileInput = document.querySelector('input[name="map_image"]'); +if (fileInput) { + fileInput.addEventListener('change', function(e) { + const file = e.target.files[0]; + + if (file && file.type.startsWith('image/')) { + // 미리보기 요소가 있을 경우에만 동작 + const preview = document.getElementById('file-preview'); + if (preview) { + const reader = new FileReader(); + reader.onload = function(e) { + preview.innerHTML = `미리보기`; + }; + reader.readAsDataURL(file); + } + } + }); +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/factory-view.js b/deploy/tkfb-package/web-ui/js/factory-view.js new file mode 100644 index 0000000..00a6b9c --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/factory-view.js @@ -0,0 +1,38 @@ +import { API, getAuthHeaders } from '/js/api-config.js'; + +(async () => { + const pathParts = location.pathname.split('/'); + const id = pathParts[pathParts.length - 1]; + + try { + const res = await fetch(`${API}/factoryinfo/${id}`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error('조회 실패'); + } + + const data = await res.json(); + + // DOM 요소가 존재하는지 확인 후 설정 + const nameEl = document.getElementById('factoryName'); + if (nameEl) nameEl.textContent = data.factory_name; + + const addressEl = document.getElementById('factoryAddress'); + if (addressEl) addressEl.textContent = '📍 ' + data.address; + + const imageEl = document.getElementById('factoryImage'); + if (imageEl) imageEl.src = data.map_image_url; + + const descEl = document.getElementById('factoryDescription'); + if (descEl) descEl.textContent = data.description; + + } catch (err) { + console.error(err); + const container = document.querySelector('.container'); + if (container) { + container.innerHTML = '

공장 정보를 불러올 수 없습니다.

'; + } + } +})(); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/group-leader-dashboard.js b/deploy/tkfb-package/web-ui/js/group-leader-dashboard.js new file mode 100644 index 0000000..0b1c01a --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/group-leader-dashboard.js @@ -0,0 +1,157 @@ +// /js/group-leader-dashboard.js +// 그룹장 전용 대시보드 - 실시간 근태 및 작업 현황 (Real Data Version) +import { apiCall } from './api-config.js'; + +console.log('📊 그룹장 대시보드 스크립트 로딩 (Live Data)'); + +// 상태별 스타일/텍스트 매핑 +const STATUS_MAP = { + 'incomplete': { text: '미제출', class: 'status-incomplete', icon: '❌', color: '#ff5252' }, + 'partial': { text: '작성중', class: 'status-warning', icon: '📝', color: '#ff9800' }, + 'complete': { text: '제출완료', class: 'status-success', icon: '✅', color: '#4caf50' }, + 'overtime': { text: '초과근무', class: 'status-info', icon: '🌙', color: '#673ab7' }, + 'vacation': { text: '휴가', class: 'status-vacation', icon: '🏖️', color: '#2196f3' } +}; + +// 현재 선택된 날짜 +let currentSelectedDate = new Date().toISOString().split('T')[0]; + +/** + * 📅 날짜 초기화 및 이벤트 리스너 등록 + */ +function initDateSelector() { + const dateInput = document.getElementById('selectedDate'); + const refreshBtn = document.getElementById('refreshBtn'); + + if (dateInput) { + dateInput.value = currentSelectedDate; + dateInput.addEventListener('change', (e) => { + currentSelectedDate = e.target.value; + loadDailyWorkStatus(); + }); + } + + if (refreshBtn) { + refreshBtn.addEventListener('click', () => { + loadDailyWorkStatus(); + showToast('데이터를 새로고침했습니다.', 'success'); + }); + } +} + +/** + * 🔄 일일 근태 현황 로드 (API 호출) + */ +async function loadDailyWorkStatus() { + const container = document.getElementById('workStatusContainer'); + if (!container) return; + + // 로딩 표시 + container.innerHTML = ` +
+
+

작업 현황을 불러오는 중...

+
+ `; + + try { + const result = await apiCall(`/attendance/daily-status?date=${currentSelectedDate}`); + const workers = result.data || []; + + renderWorkStatus(workers); + updateSummaryStats(workers); + + } catch (error) { + console.error('현황 로드 오류:', error); + container.innerHTML = ` +
+

⚠️ 데이터를 불러오는데 실패했습니다.

+ +
+ `; + } +} + +/** + * 📊 통계 요약 업데이트 + */ +function updateSummaryStats(workers) { + // 요약 카드가 있다면 업데이트 (현재 HTML에는 없으므로 생략 가능하거나 동적으로 추가) + // 여기서는 콘솔에만 로그 + const stats = workers.reduce((acc, w) => { + acc[w.status] = (acc[w.status] || 0) + 1; + return acc; + }, {}); + console.log('Daily Stats:', stats); +} + +/** + * 🎨 현황 리스트 렌더링 + */ +function renderWorkStatus(workers) { + const container = document.getElementById('workStatusContainer'); + if (!container) return; + + if (workers.length === 0) { + container.innerHTML = '
등록된 작업자가 없습니다.
'; + return; + } + + // 상태 우선순위 정렬 (미제출 -> 작성중 -> 완료) + const sortOrder = ['incomplete', 'partial', 'vacation', 'complete', 'overtime']; + workers.sort((a, b) => { + return sortOrder.indexOf(a.status) - sortOrder.indexOf(b.status) || a.worker_name.localeCompare(b.worker_name); + }); + + const html = ` +
+ ${workers.map(worker => { + const statusInfo = STATUS_MAP[worker.status] || { text: worker.status, class: '', icon: '❓', color: '#999' }; + + return ` +
+
+ ${worker.worker_name} + ${worker.job_type || '-'} +
+ +
+
+ ${statusInfo.icon} ${statusInfo.text} +
+
+ ${worker.total_work_hours > 0 ? worker.total_work_hours + '시간' : '-'} +
+
+ + ${worker.status === 'incomplete' ? ` + + ` : ''} +
+ `; + }).join('')} +
+ `; + + container.innerHTML = html; +} + +// 🍞 토스트 메시지 (기존 modern-dashboard.js에 있다면 중복 주의, 없으면 사용) +function showToast(message, type = 'info') { + if (window.showToast) { + window.showToast(message, type); + } else { + alert(message); + } +} + +// 초기화 +document.addEventListener('DOMContentLoaded', () => { + initDateSelector(); + loadDailyWorkStatus(); +}); + +// 전역 노출 대신 모듈로 내보내기 +export { loadDailyWorkStatus as refreshTeamStatus }; \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/issue-category-manage.js b/deploy/tkfb-package/web-ui/js/issue-category-manage.js new file mode 100644 index 0000000..b6e0fed --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/issue-category-manage.js @@ -0,0 +1,421 @@ +/** + * 신고 카테고리 관리 JavaScript + */ + +import { API, getAuthHeaders } from '/js/api-config.js'; + +let currentType = 'nonconformity'; +let categories = []; +let items = []; + +// 초기화 +document.addEventListener('DOMContentLoaded', async () => { + await loadCategories(); +}); + +/** + * 유형 탭 전환 + */ +window.switchType = async function(type) { + currentType = type; + + // 탭 상태 업데이트 + document.querySelectorAll('.type-tab').forEach(tab => { + tab.classList.toggle('active', tab.dataset.type === type); + }); + + await loadCategories(); +}; + +/** + * 카테고리 로드 + */ +async function loadCategories() { + const container = document.getElementById('categoryList'); + container.innerHTML = '
카테고리를 불러오는 중...
'; + + try { + const response = await fetch(`${API}/work-issues/categories/type/${currentType}`, { + headers: getAuthHeaders() + }); + + if (!response.ok) throw new Error('카테고리 조회 실패'); + + const data = await response.json(); + + if (data.success && data.data) { + categories = data.data; + + // 항목도 로드 + const itemsResponse = await fetch(`${API}/work-issues/items`, { + headers: getAuthHeaders() + }); + + if (itemsResponse.ok) { + const itemsData = await itemsResponse.json(); + if (itemsData.success) { + items = itemsData.data || []; + } + } + + renderCategories(); + } else { + container.innerHTML = '
카테고리가 없습니다.
'; + } + } catch (error) { + console.error('카테고리 로드 실패:', error); + container.innerHTML = '
카테고리를 불러오지 못했습니다.
'; + } +} + +/** + * 카테고리 렌더링 + */ +function renderCategories() { + const container = document.getElementById('categoryList'); + + if (categories.length === 0) { + container.innerHTML = '
등록된 카테고리가 없습니다.
'; + return; + } + + const severityLabel = { + low: '낮음', + medium: '보통', + high: '높음', + critical: '심각' + }; + + container.innerHTML = categories.map(cat => { + const catItems = items.filter(item => item.category_id === cat.category_id); + + return ` +
+
+
${cat.category_name}
+
+ ${severityLabel[cat.severity] || '보통'} + ${catItems.length}개 항목 + +
+
+
+
+ ${catItems.length > 0 ? catItems.map(item => ` +
+
+
${item.item_name}
+ ${item.description ? `
${item.description}
` : ''} +
+
+ ${severityLabel[item.severity] || '보통'} + +
+
+ `).join('') : '
등록된 항목이 없습니다.
'} +
+
+ + + +
+
+
+ `; + }).join(''); +} + +/** + * 카테고리 토글 + */ +window.toggleCategory = function(categoryId) { + const section = document.querySelector(`.category-section[data-category-id="${categoryId}"]`); + if (section) { + section.classList.toggle('expanded'); + } +}; + +/** + * 카테고리 모달 열기 + */ +window.openCategoryModal = function(categoryId = null) { + const modal = document.getElementById('categoryModal'); + const title = document.getElementById('categoryModalTitle'); + const deleteBtn = document.getElementById('deleteCategoryBtn'); + + document.getElementById('categoryId').value = ''; + document.getElementById('categoryName').value = ''; + document.getElementById('categoryDescription').value = ''; + document.getElementById('categorySeverity').value = 'medium'; + + if (categoryId) { + const category = categories.find(c => c.category_id === categoryId); + if (category) { + title.textContent = '카테고리 수정'; + document.getElementById('categoryId').value = category.category_id; + document.getElementById('categoryName').value = category.category_name; + document.getElementById('categoryDescription').value = category.description || ''; + document.getElementById('categorySeverity').value = category.severity || 'medium'; + deleteBtn.style.display = 'block'; + } + } else { + title.textContent = '새 카테고리'; + deleteBtn.style.display = 'none'; + } + + modal.style.display = 'flex'; +}; + +/** + * 카테고리 모달 닫기 + */ +window.closeCategoryModal = function() { + document.getElementById('categoryModal').style.display = 'none'; +}; + +/** + * 카테고리 저장 + */ +window.saveCategory = async function() { + const categoryId = document.getElementById('categoryId').value; + const name = document.getElementById('categoryName').value.trim(); + const description = document.getElementById('categoryDescription').value.trim(); + const severity = document.getElementById('categorySeverity').value; + + if (!name) { + alert('카테고리 이름을 입력하세요.'); + return; + } + + try { + const url = categoryId + ? `${API}/work-issues/categories/${categoryId}` + : `${API}/work-issues/categories`; + + const response = await fetch(url, { + method: categoryId ? 'PUT' : 'POST', + headers: { + ...getAuthHeaders(), + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + category_name: name, + category_type: currentType, + description, + severity + }) + }); + + const data = await response.json(); + + if (response.ok && data.success) { + alert(categoryId ? '카테고리가 수정되었습니다.' : '카테고리가 추가되었습니다.'); + closeCategoryModal(); + await loadCategories(); + } else { + throw new Error(data.error || '저장 실패'); + } + } catch (error) { + console.error('카테고리 저장 실패:', error); + alert('카테고리 저장에 실패했습니다: ' + error.message); + } +}; + +/** + * 카테고리 삭제 + */ +window.deleteCategory = async function() { + const categoryId = document.getElementById('categoryId').value; + + if (!categoryId) return; + + const catItems = items.filter(item => item.category_id == categoryId); + if (catItems.length > 0) { + alert(`이 카테고리에 ${catItems.length}개의 항목이 있습니다. 먼저 항목을 삭제하세요.`); + return; + } + + if (!confirm('이 카테고리를 삭제하시겠습니까?')) return; + + try { + const response = await fetch(`${API}/work-issues/categories/${categoryId}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + + const data = await response.json(); + + if (response.ok && data.success) { + alert('카테고리가 삭제되었습니다.'); + closeCategoryModal(); + await loadCategories(); + } else { + throw new Error(data.error || '삭제 실패'); + } + } catch (error) { + console.error('카테고리 삭제 실패:', error); + alert('카테고리 삭제에 실패했습니다: ' + error.message); + } +}; + +/** + * 항목 모달 열기 + */ +window.openItemModal = function(categoryId, itemId = null) { + const modal = document.getElementById('itemModal'); + const title = document.getElementById('itemModalTitle'); + const deleteBtn = document.getElementById('deleteItemBtn'); + + document.getElementById('itemId').value = ''; + document.getElementById('itemCategoryId').value = categoryId; + document.getElementById('itemName').value = ''; + document.getElementById('itemDescription').value = ''; + document.getElementById('itemSeverity').value = 'medium'; + + if (itemId) { + const item = items.find(i => i.item_id === itemId); + if (item) { + title.textContent = '항목 수정'; + document.getElementById('itemId').value = item.item_id; + document.getElementById('itemName').value = item.item_name; + document.getElementById('itemDescription').value = item.description || ''; + document.getElementById('itemSeverity').value = item.severity || 'medium'; + deleteBtn.style.display = 'block'; + } + } else { + const category = categories.find(c => c.category_id === categoryId); + title.textContent = `새 항목 (${category?.category_name || ''})`; + deleteBtn.style.display = 'none'; + } + + modal.style.display = 'flex'; +}; + +/** + * 항목 모달 닫기 + */ +window.closeItemModal = function() { + document.getElementById('itemModal').style.display = 'none'; +}; + +/** + * 항목 저장 + */ +window.saveItem = async function() { + const itemId = document.getElementById('itemId').value; + const categoryId = document.getElementById('itemCategoryId').value; + const name = document.getElementById('itemName').value.trim(); + const description = document.getElementById('itemDescription').value.trim(); + const severity = document.getElementById('itemSeverity').value; + + if (!name) { + alert('항목 이름을 입력하세요.'); + return; + } + + try { + const url = itemId + ? `${API}/work-issues/items/${itemId}` + : `${API}/work-issues/items`; + + const response = await fetch(url, { + method: itemId ? 'PUT' : 'POST', + headers: { + ...getAuthHeaders(), + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + category_id: categoryId, + item_name: name, + description, + severity + }) + }); + + const data = await response.json(); + + if (response.ok && data.success) { + alert(itemId ? '항목이 수정되었습니다.' : '항목이 추가되었습니다.'); + closeItemModal(); + await loadCategories(); + } else { + throw new Error(data.error || '저장 실패'); + } + } catch (error) { + console.error('항목 저장 실패:', error); + alert('항목 저장에 실패했습니다: ' + error.message); + } +}; + +/** + * 항목 삭제 + */ +window.deleteItem = async function() { + const itemId = document.getElementById('itemId').value; + + if (!itemId) return; + if (!confirm('이 항목을 삭제하시겠습니까?')) return; + + try { + const response = await fetch(`${API}/work-issues/items/${itemId}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + + const data = await response.json(); + + if (response.ok && data.success) { + alert('항목이 삭제되었습니다.'); + closeItemModal(); + await loadCategories(); + } else { + throw new Error(data.error || '삭제 실패'); + } + } catch (error) { + console.error('항목 삭제 실패:', error); + alert('항목 삭제에 실패했습니다: ' + error.message); + } +}; + +/** + * 빠른 항목 추가 + */ +window.quickAddItem = async function(categoryId) { + const input = document.getElementById(`newItemName_${categoryId}`); + const name = input.value.trim(); + + if (!name) { + alert('항목 이름을 입력하세요.'); + input.focus(); + return; + } + + try { + const response = await fetch(`${API}/work-issues/items`, { + method: 'POST', + headers: { + ...getAuthHeaders(), + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + category_id: categoryId, + item_name: name, + severity: 'medium' + }) + }); + + const data = await response.json(); + + if (response.ok && data.success) { + input.value = ''; + await loadCategories(); + // 카테고리 펼침 유지 + toggleCategory(categoryId); + } else { + throw new Error(data.error || '추가 실패'); + } + } catch (error) { + console.error('항목 추가 실패:', error); + alert('항목 추가에 실패했습니다: ' + error.message); + } +}; diff --git a/deploy/tkfb-package/web-ui/js/issue-detail.js b/deploy/tkfb-package/web-ui/js/issue-detail.js new file mode 100644 index 0000000..e089bbe --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/issue-detail.js @@ -0,0 +1,690 @@ +/** + * 신고 상세 페이지 JavaScript + */ + +const API_BASE = window.API_BASE_URL || 'http://localhost:20005/api'; + +let reportId = null; +let reportData = null; +let currentUser = null; + +// 상태 한글명 +const statusNames = { + reported: '신고', + received: '접수', + in_progress: '처리중', + completed: '완료', + closed: '종료' +}; + +// 유형 한글명 +const typeNames = { + nonconformity: '부적합', + safety: '안전' +}; + +// 심각도 한글명 +const severityNames = { + critical: '심각', + high: '높음', + medium: '보통', + low: '낮음' +}; + +// 초기화 +document.addEventListener('DOMContentLoaded', async () => { + // URL에서 ID 가져오기 + const urlParams = new URLSearchParams(window.location.search); + reportId = urlParams.get('id'); + + if (!reportId) { + alert('신고 ID가 없습니다.'); + goBackToList(); + return; + } + + // 현재 사용자 정보 로드 + await loadCurrentUser(); + + // 상세 데이터 로드 + await loadReportDetail(); +}); + +/** + * 현재 사용자 정보 로드 + */ +async function loadCurrentUser() { + try { + const response = await fetch(`${API_BASE}/users/me`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (response.ok) { + const data = await response.json(); + currentUser = data.data; + } + } catch (error) { + console.error('사용자 정보 로드 실패:', error); + } +} + +/** + * 신고 상세 로드 + */ +async function loadReportDetail() { + try { + const response = await fetch(`${API_BASE}/work-issues/${reportId}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) { + throw new Error('신고를 찾을 수 없습니다.'); + } + + const data = await response.json(); + if (!data.success) { + throw new Error(data.error || '데이터 조회 실패'); + } + + reportData = data.data; + renderDetail(); + await loadStatusLogs(); + + } catch (error) { + console.error('상세 로드 실패:', error); + alert(error.message); + goBackToList(); + } +} + +/** + * 상세 정보 렌더링 + */ +function renderDetail() { + const d = reportData; + + // 헤더 + document.getElementById('reportId').textContent = `#${d.report_id}`; + document.getElementById('reportTitle').textContent = d.issue_item_name || d.issue_category_name || '신고'; + + // 상태 배지 + const statusBadge = document.getElementById('statusBadge'); + statusBadge.className = `status-badge ${d.status}`; + statusBadge.textContent = statusNames[d.status] || d.status; + + // 기본 정보 + renderBasicInfo(d); + + // 신고 내용 + renderIssueContent(d); + + // 사진 + renderPhotos(d); + + // 처리 정보 + renderProcessInfo(d); + + // 액션 버튼 + renderActionButtons(d); +} + +/** + * 기본 정보 렌더링 + */ +function renderBasicInfo(d) { + const container = document.getElementById('basicInfo'); + + const formatDate = (dateStr) => { + if (!dateStr) return '-'; + const date = new Date(dateStr); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); + }; + + const validTypes = ['nonconformity', 'safety']; + const safeType = validTypes.includes(d.category_type) ? d.category_type : ''; + const reporterName = escapeHtml(d.reporter_full_name || d.reporter_name || '-'); + const locationText = escapeHtml(d.custom_location || d.workplace_name || '-'); + const factoryText = d.factory_name ? ` (${escapeHtml(d.factory_name)})` : ''; + + container.innerHTML = ` +
+
신고 유형
+
+ ${typeNames[d.category_type] || escapeHtml(d.category_type || '-')} +
+
+
+
신고일시
+
${formatDate(d.report_date)}
+
+
+
신고자
+
${reporterName}
+
+
+
위치
+
${locationText}${factoryText}
+
+ `; +} + +/** + * 신고 내용 렌더링 + */ +function renderIssueContent(d) { + const container = document.getElementById('issueContent'); + + const validSeverities = ['critical', 'high', 'medium', 'low']; + const safeSeverity = validSeverities.includes(d.severity) ? d.severity : ''; + + let html = ` +
+
+
카테고리
+
${escapeHtml(d.issue_category_name || '-')}
+
+
+
항목
+
+ ${escapeHtml(d.issue_item_name || '-')} + ${d.severity ? `${severityNames[d.severity] || escapeHtml(d.severity)}` : ''} +
+
+
+ `; + + if (d.additional_description) { + html += ` +
+ ${escapeHtml(d.additional_description)} +
+ `; + } + + container.innerHTML = html; +} + +/** + * 사진 렌더링 + */ +function renderPhotos(d) { + const section = document.getElementById('photoSection'); + const gallery = document.getElementById('photoGallery'); + + const photos = [d.photo_path1, d.photo_path2, d.photo_path3, d.photo_path4, d.photo_path5].filter(Boolean); + + if (photos.length === 0) { + section.style.display = 'none'; + return; + } + + section.style.display = 'block'; + + const baseUrl = (API_BASE).replace('/api', ''); + + gallery.innerHTML = photos.map(photo => { + const fullUrl = photo.startsWith('http') ? photo : `${baseUrl}${photo}`; + return ` +
+ 첨부 사진 +
+ `; + }).join(''); +} + +/** + * 처리 정보 렌더링 + */ +function renderProcessInfo(d) { + const section = document.getElementById('processSection'); + const container = document.getElementById('processInfo'); + + // 담당자 배정 또는 처리 정보가 있는 경우만 표시 + if (!d.assigned_user_id && !d.resolution_notes) { + section.style.display = 'none'; + return; + } + + section.style.display = 'block'; + + const formatDate = (dateStr) => { + if (!dateStr) return '-'; + const date = new Date(dateStr); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); + }; + + let html = '
'; + + if (d.assigned_user_id) { + html += ` +
+
담당자
+
${escapeHtml(d.assigned_full_name || d.assigned_user_name || '-')}
+
+
+
담당 부서
+
${escapeHtml(d.assigned_department || '-')}
+
+ `; + } + + if (d.resolved_at) { + html += ` +
+
처리 완료일
+
${formatDate(d.resolved_at)}
+
+
+
처리자
+
${escapeHtml(d.resolved_by_name || '-')}
+
+ `; + } + + html += '
'; + + if (d.resolution_notes) { + html += ` +
+
처리 내용
+
${escapeHtml(d.resolution_notes)}
+
+ `; + } + + container.innerHTML = html; +} + +/** + * 액션 버튼 렌더링 + */ +function renderActionButtons(d) { + const container = document.getElementById('actionButtons'); + + if (!currentUser) { + container.innerHTML = ''; + return; + } + + const isAdmin = ['admin', 'system', 'support_team'].includes(currentUser.access_level); + const isOwner = d.reporter_id === currentUser.user_id; + const isAssignee = d.assigned_user_id === currentUser.user_id; + + let buttons = []; + + // 관리자 권한 버튼 + if (isAdmin) { + if (d.status === 'reported') { + buttons.push(``); + } + + if (d.status === 'received' || d.status === 'in_progress') { + buttons.push(``); + } + + if (d.status === 'received') { + buttons.push(``); + } + + if (d.status === 'in_progress') { + buttons.push(``); + } + + if (d.status === 'completed') { + buttons.push(``); + } + } + + // 담당자 버튼 + if (isAssignee && !isAdmin) { + if (d.status === 'received') { + buttons.push(``); + } + + if (d.status === 'in_progress') { + buttons.push(``); + } + } + + // 신고자 버튼 (수정/삭제는 reported 상태에서만) + if (isOwner && d.status === 'reported') { + buttons.push(``); + } + + container.innerHTML = buttons.join(''); +} + +/** + * 상태 변경 이력 로드 + */ +async function loadStatusLogs() { + try { + const response = await fetch(`${API_BASE}/work-issues/${reportId}/status-logs`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) return; + + const data = await response.json(); + if (data.success && data.data) { + renderStatusTimeline(data.data); + } + } catch (error) { + console.error('상태 이력 로드 실패:', error); + } +} + +/** + * 상태 타임라인 렌더링 + */ +function renderStatusTimeline(logs) { + const container = document.getElementById('statusTimeline'); + + if (!logs || logs.length === 0) { + container.innerHTML = '

상태 변경 이력이 없습니다.

'; + return; + } + + const formatDate = (dateStr) => { + const date = new Date(dateStr); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); + }; + + container.innerHTML = logs.map(log => ` +
+
+ ${log.previous_status ? `${statusNames[log.previous_status] || escapeHtml(log.previous_status)} → ` : ''}${statusNames[log.new_status] || escapeHtml(log.new_status)} +
+
+ ${escapeHtml(log.changed_by_full_name || log.changed_by_name || '-')} | ${formatDate(log.changed_at)} + ${log.change_reason ? `
${escapeHtml(log.change_reason)}` : ''} +
+
+ `).join(''); +} + +// ==================== 액션 함수 ==================== + +/** + * 신고 접수 + */ +async function receiveReport() { + if (!confirm('이 신고를 접수하시겠습니까?')) return; + + try { + const response = await fetch(`${API_BASE}/work-issues/${reportId}/receive`, { + method: 'POST', + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + const data = await response.json(); + + if (data.success) { + alert('신고가 접수되었습니다.'); + location.reload(); + } else { + throw new Error(data.error || '접수 실패'); + } + } catch (error) { + alert('접수 실패: ' + error.message); + } +} + +/** + * 처리 시작 + */ +async function startProcessing() { + if (!confirm('처리를 시작하시겠습니까?')) return; + + try { + const response = await fetch(`${API_BASE}/work-issues/${reportId}/start`, { + method: 'POST', + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + const data = await response.json(); + + if (data.success) { + alert('처리가 시작되었습니다.'); + location.reload(); + } else { + throw new Error(data.error || '처리 시작 실패'); + } + } catch (error) { + alert('처리 시작 실패: ' + error.message); + } +} + +/** + * 신고 종료 + */ +async function closeReport() { + if (!confirm('이 신고를 종료하시겠습니까?')) return; + + try { + const response = await fetch(`${API_BASE}/work-issues/${reportId}/close`, { + method: 'POST', + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + const data = await response.json(); + + if (data.success) { + alert('신고가 종료되었습니다.'); + location.reload(); + } else { + throw new Error(data.error || '종료 실패'); + } + } catch (error) { + alert('종료 실패: ' + error.message); + } +} + +/** + * 신고 삭제 + */ +async function deleteReport() { + if (!confirm('정말 이 신고를 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.')) return; + + try { + const response = await fetch(`${API_BASE}/work-issues/${reportId}`, { + method: 'DELETE', + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + const data = await response.json(); + + if (data.success) { + alert('신고가 삭제되었습니다.'); + goBackToList(); + } else { + throw new Error(data.error || '삭제 실패'); + } + } catch (error) { + alert('삭제 실패: ' + error.message); + } +} + +// ==================== 담당자 배정 모달 ==================== + +async function openAssignModal() { + // 사용자 목록 로드 + try { + const response = await fetch(`${API_BASE}/users`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (response.ok) { + const data = await response.json(); + const select = document.getElementById('assignUser'); + select.innerHTML = ''; + + if (data.success && data.data) { + data.data.forEach(user => { + const safeUserId = parseInt(user.user_id) || 0; + select.innerHTML += ``; + }); + } + } + } catch (error) { + console.error('사용자 목록 로드 실패:', error); + } + + document.getElementById('assignModal').classList.add('visible'); +} + +function closeAssignModal() { + document.getElementById('assignModal').classList.remove('visible'); +} + +async function submitAssign() { + const department = document.getElementById('assignDepartment').value; + const userId = document.getElementById('assignUser').value; + + if (!userId) { + alert('담당자를 선택해주세요.'); + return; + } + + try { + const response = await fetch(`${API_BASE}/work-issues/${reportId}/assign`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + }, + body: JSON.stringify({ + assigned_department: department, + assigned_user_id: parseInt(userId) + }) + }); + + const data = await response.json(); + + if (data.success) { + alert('담당자가 배정되었습니다.'); + closeAssignModal(); + location.reload(); + } else { + throw new Error(data.error || '배정 실패'); + } + } catch (error) { + alert('담당자 배정 실패: ' + error.message); + } +} + +// ==================== 처리 완료 모달 ==================== + +function openCompleteModal() { + document.getElementById('completeModal').classList.add('visible'); +} + +function closeCompleteModal() { + document.getElementById('completeModal').classList.remove('visible'); +} + +async function submitComplete() { + const notes = document.getElementById('resolutionNotes').value; + + if (!notes.trim()) { + alert('처리 내용을 입력해주세요.'); + return; + } + + try { + const response = await fetch(`${API_BASE}/work-issues/${reportId}/complete`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + }, + body: JSON.stringify({ + resolution_notes: notes + }) + }); + + const data = await response.json(); + + if (data.success) { + alert('처리가 완료되었습니다.'); + closeCompleteModal(); + location.reload(); + } else { + throw new Error(data.error || '완료 처리 실패'); + } + } catch (error) { + alert('처리 완료 실패: ' + error.message); + } +} + +// ==================== 사진 모달 ==================== + +function openPhotoModal(src) { + document.getElementById('photoModalImg').src = src; + document.getElementById('photoModal').classList.add('visible'); +} + +function closePhotoModal() { + document.getElementById('photoModal').classList.remove('visible'); +} + +// ==================== 유틸리티 ==================== + +function escapeHtml(text) { + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; +} + +/** + * 목록으로 돌아가기 + */ +function goBackToList() { + const urlParams = new URLSearchParams(window.location.search); + const from = urlParams.get('from'); + + if (from === 'nonconformity') { + window.location.href = '/pages/work/nonconformity.html'; + } else if (from === 'safety') { + window.location.href = '/pages/safety/report-status.html'; + } else { + if (window.history.length > 1) { + window.history.back(); + } else { + window.location.href = '/pages/safety/report-status.html'; + } + } +} + +// 전역 함수 노출 +window.goBackToList = goBackToList; +window.receiveReport = receiveReport; +window.startProcessing = startProcessing; +window.closeReport = closeReport; +window.deleteReport = deleteReport; +window.openAssignModal = openAssignModal; +window.closeAssignModal = closeAssignModal; +window.submitAssign = submitAssign; +window.openCompleteModal = openCompleteModal; +window.closeCompleteModal = closeCompleteModal; +window.submitComplete = submitComplete; +window.openPhotoModal = openPhotoModal; +window.closePhotoModal = closePhotoModal; diff --git a/deploy/tkfb-package/web-ui/js/issue-report.js b/deploy/tkfb-package/web-ui/js/issue-report.js new file mode 100644 index 0000000..f9a6330 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/issue-report.js @@ -0,0 +1,926 @@ +/** + * 신고 등록 페이지 JavaScript + * URL 파라미터 ?type=nonconformity 또는 ?type=safety로 유형 사전 선택 지원 + */ + +// API 설정 +const API_BASE = window.API_BASE_URL || 'http://localhost:20005/api'; + +// 상태 변수 +let selectedFactoryId = null; +let selectedWorkplaceId = null; +let selectedWorkplaceName = null; +let selectedType = null; // 'nonconformity' | 'safety' +let selectedCategoryId = null; +let selectedCategoryName = null; +let selectedItemId = null; +let selectedTbmSessionId = null; +let selectedVisitRequestId = null; +let photos = [null, null, null, null, null]; +let customItemName = null; // 직접 입력한 항목명 + +// 지도 관련 변수 +let canvas, ctx, canvasImage; +let mapRegions = []; +let todayWorkers = []; +let todayVisitors = []; + +// DOM 요소 +let factorySelect, issueMapCanvas; +let photoInput, currentPhotoIndex; + +// 초기화 +document.addEventListener('DOMContentLoaded', async () => { + factorySelect = document.getElementById('factorySelect'); + issueMapCanvas = document.getElementById('issueMapCanvas'); + photoInput = document.getElementById('photoInput'); + + canvas = issueMapCanvas; + ctx = canvas.getContext('2d'); + + // 이벤트 리스너 설정 + setupEventListeners(); + + // 공장 목록 로드 + await loadFactories(); + + // URL 파라미터에서 유형 확인 및 자동 선택 + const urlParams = new URLSearchParams(window.location.search); + const preselectedType = urlParams.get('type'); + if (preselectedType === 'nonconformity' || preselectedType === 'safety') { + onTypeSelect(preselectedType); + } +}); + +/** + * 이벤트 리스너 설정 + */ +function setupEventListeners() { + // 공장 선택 + factorySelect.addEventListener('change', onFactoryChange); + + // 지도 클릭 + canvas.addEventListener('click', onMapClick); + + // 기타 위치 토글 + document.getElementById('useCustomLocation').addEventListener('change', (e) => { + const customInput = document.getElementById('customLocationInput'); + customInput.classList.toggle('visible', e.target.checked); + + if (e.target.checked) { + // 지도 선택 초기화 + selectedWorkplaceId = null; + selectedWorkplaceName = null; + selectedTbmSessionId = null; + selectedVisitRequestId = null; + updateLocationInfo(); + } + }); + + // 유형 버튼 클릭 + document.querySelectorAll('.type-btn').forEach(btn => { + btn.addEventListener('click', () => onTypeSelect(btn.dataset.type)); + }); + + // 사진 슬롯 클릭 + document.querySelectorAll('.photo-slot').forEach(slot => { + slot.addEventListener('click', (e) => { + if (e.target.classList.contains('remove-btn')) return; + currentPhotoIndex = parseInt(slot.dataset.index); + photoInput.click(); + }); + }); + + // 사진 삭제 버튼 + document.querySelectorAll('.photo-slot .remove-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + e.stopPropagation(); + const slot = btn.closest('.photo-slot'); + const index = parseInt(slot.dataset.index); + removePhoto(index); + }); + }); + + // 사진 선택 + photoInput.addEventListener('change', onPhotoSelect); +} + +/** + * 공장 목록 로드 + */ +async function loadFactories() { + try { + const response = await fetch(`${API_BASE}/workplaces/categories/active/list`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) throw new Error('공장 목록 조회 실패'); + + const data = await response.json(); + if (data.success && data.data) { + data.data.forEach(factory => { + const option = document.createElement('option'); + option.value = factory.category_id; + option.textContent = factory.category_name; + factorySelect.appendChild(option); + }); + + // 첫 번째 공장 자동 선택 + if (data.data.length > 0) { + factorySelect.value = data.data[0].category_id; + onFactoryChange(); + } + } + } catch (error) { + console.error('공장 목록 로드 실패:', error); + } +} + +/** + * 공장 변경 시 + */ +async function onFactoryChange() { + selectedFactoryId = factorySelect.value; + if (!selectedFactoryId) return; + + // 위치 선택 초기화 + selectedWorkplaceId = null; + selectedWorkplaceName = null; + selectedTbmSessionId = null; + selectedVisitRequestId = null; + updateLocationInfo(); + + // 지도 데이터 로드 + await Promise.all([ + loadMapImage(), + loadMapRegions(), + loadTodayData() + ]); + + renderMap(); +} + +/** + * 배치도 이미지 로드 + */ +async function loadMapImage() { + try { + const response = await fetch(`${API_BASE}/workplaces/categories`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) return; + + const data = await response.json(); + if (data.success && data.data) { + const selectedCategory = data.data.find(c => c.category_id == selectedFactoryId); + if (selectedCategory && selectedCategory.layout_image) { + const baseUrl = (window.API_BASE_URL || 'http://localhost:20005').replace('/api', ''); + const fullImageUrl = selectedCategory.layout_image.startsWith('http') + ? selectedCategory.layout_image + : `${baseUrl}${selectedCategory.layout_image}`; + + canvasImage = new Image(); + canvasImage.onload = () => renderMap(); + canvasImage.src = fullImageUrl; + } + } + } catch (error) { + console.error('배치도 이미지 로드 실패:', error); + } +} + +/** + * 지도 영역 로드 + */ +async function loadMapRegions() { + try { + const response = await fetch(`${API_BASE}/workplaces/categories/${selectedFactoryId}/map-regions`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) return; + + const data = await response.json(); + if (data.success) { + mapRegions = data.data || []; + } + } catch (error) { + console.error('지도 영역 로드 실패:', error); + } +} + +/** + * 오늘 TBM/출입신청 데이터 로드 + */ +async function loadTodayData() { + // 로컬 시간대 기준으로 오늘 날짜 구하기 (UTC가 아닌 한국 시간 기준) + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const day = String(now.getDate()).padStart(2, '0'); + const today = `${year}-${month}-${day}`; + + console.log('[신고페이지] 조회 날짜 (로컬):', today); + + try { + // TBM 세션 로드 + const tbmResponse = await fetch(`${API_BASE}/tbm/sessions/date/${today}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (tbmResponse.ok) { + const tbmData = await tbmResponse.json(); + const sessions = tbmData.data || []; + + // TBM 세션 데이터를 가공하여 member_count 계산 + todayWorkers = sessions.map(session => { + const memberCount = session.team_member_count || 0; + const leaderCount = session.leader_id ? 1 : 0; + return { + ...session, + member_count: memberCount + leaderCount + }; + }); + + console.log('[신고페이지] 로드된 TBM 작업:', todayWorkers.length, '건'); + } + + // 출입 신청 로드 + const visitResponse = await fetch(`${API_BASE}/workplace-visits/requests`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (visitResponse.ok) { + const visitData = await visitResponse.json(); + todayVisitors = (visitData.data || []).filter(v => { + // 로컬 날짜로 비교 + const visitDateObj = new Date(v.visit_date); + const visitYear = visitDateObj.getFullYear(); + const visitMonth = String(visitDateObj.getMonth() + 1).padStart(2, '0'); + const visitDay = String(visitDateObj.getDate()).padStart(2, '0'); + const visitDate = `${visitYear}-${visitMonth}-${visitDay}`; + + return visitDate === today && + (v.status === 'approved' || v.status === 'training_completed'); + }); + + console.log('[신고페이지] 로드된 방문자:', todayVisitors.length, '건'); + } + } catch (error) { + console.error('오늘 데이터 로드 실패:', error); + } +} + +/** + * 둥근 모서리 사각형 그리기 (Canvas roundRect 폴리필) + */ +function drawRoundRect(ctx, x, y, width, height, radius) { + ctx.beginPath(); + ctx.moveTo(x + radius, y); + ctx.lineTo(x + width - radius, y); + ctx.quadraticCurveTo(x + width, y, x + width, y + radius); + ctx.lineTo(x + width, y + height - radius); + ctx.quadraticCurveTo(x + width, y + height, x + width - radius, y + height); + ctx.lineTo(x + radius, y + height); + ctx.quadraticCurveTo(x, y + height, x, y + height - radius); + ctx.lineTo(x, y + radius); + ctx.quadraticCurveTo(x, y, x + radius, y); + ctx.closePath(); +} + +/** + * 지도 렌더링 + */ +function renderMap() { + if (!canvas || !ctx) return; + + // 컨테이너 너비 가져오기 + const container = canvas.parentElement; + const containerWidth = container.clientWidth - 2; // border 고려 + const maxWidth = Math.min(containerWidth, 800); + + // 이미지가 로드된 경우 이미지 비율에 맞춰 캔버스 크기 설정 + if (canvasImage && canvasImage.complete && canvasImage.naturalWidth > 0) { + const imgWidth = canvasImage.naturalWidth; + const imgHeight = canvasImage.naturalHeight; + + // 스케일 계산 (maxWidth에 맞춤) + const scale = imgWidth > maxWidth ? maxWidth / imgWidth : 1; + + canvas.width = imgWidth * scale; + canvas.height = imgHeight * scale; + + // 이미지 그리기 + ctx.drawImage(canvasImage, 0, 0, canvas.width, canvas.height); + } else { + // 이미지가 없는 경우 기본 크기 + canvas.width = maxWidth; + canvas.height = 400; + + // 배경 그리기 + ctx.fillStyle = '#f3f4f6'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + // 이미지 없음 안내 + ctx.fillStyle = '#9ca3af'; + ctx.font = '14px sans-serif'; + ctx.textAlign = 'center'; + ctx.fillText('배치도 이미지가 없습니다', canvas.width / 2, canvas.height / 2); + } + + // 작업장 영역 그리기 (퍼센트 좌표 사용) + mapRegions.forEach(region => { + const workers = todayWorkers.filter(w => w.workplace_id === region.workplace_id); + const visitors = todayVisitors.filter(v => v.workplace_id === region.workplace_id); + + const workerCount = workers.reduce((sum, w) => sum + (w.member_count || 0), 0); + const visitorCount = visitors.reduce((sum, v) => sum + (v.visitor_count || 0), 0); + + drawWorkplaceRegion(region, workerCount, visitorCount); + }); +} + +/** + * 작업장 영역 그리기 + */ +function drawWorkplaceRegion(region, workerCount, visitorCount) { + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + const width = x2 - x1; + const height = y2 - y1; + + // 선택된 작업장 하이라이트 + const isSelected = region.workplace_id === selectedWorkplaceId; + + // 색상 결정 (더 진하게 조정) + let fillColor, strokeColor, textColor; + if (isSelected) { + fillColor = 'rgba(34, 197, 94, 0.5)'; // 초록색 (선택됨) + strokeColor = 'rgb(22, 163, 74)'; + textColor = '#15803d'; + } else if (workerCount > 0 && visitorCount > 0) { + fillColor = 'rgba(34, 197, 94, 0.4)'; // 초록색 (작업+방문) + strokeColor = 'rgb(22, 163, 74)'; + textColor = '#166534'; + } else if (workerCount > 0) { + fillColor = 'rgba(59, 130, 246, 0.4)'; // 파란색 (작업만) + strokeColor = 'rgb(37, 99, 235)'; + textColor = '#1e40af'; + } else if (visitorCount > 0) { + fillColor = 'rgba(168, 85, 247, 0.4)'; // 보라색 (방문만) + strokeColor = 'rgb(147, 51, 234)'; + textColor = '#7c3aed'; + } else { + fillColor = 'rgba(107, 114, 128, 0.35)'; // 회색 (없음) - 더 진하게 + strokeColor = 'rgb(75, 85, 99)'; + textColor = '#374151'; + } + + ctx.fillStyle = fillColor; + ctx.strokeStyle = strokeColor; + ctx.lineWidth = isSelected ? 4 : 2.5; + + ctx.beginPath(); + ctx.rect(x1, y1, width, height); + ctx.fill(); + ctx.stroke(); + + // 작업장명 표시 (배경 추가로 가독성 향상) + const centerX = x1 + width / 2; + const centerY = y1 + height / 2; + + // 텍스트 배경 + ctx.font = 'bold 13px sans-serif'; + const textMetrics = ctx.measureText(region.workplace_name); + const textWidth = textMetrics.width + 12; + const textHeight = 20; + + ctx.fillStyle = 'rgba(255, 255, 255, 0.9)'; + drawRoundRect(ctx, centerX - textWidth / 2, centerY - textHeight / 2, textWidth, textHeight, 4); + ctx.fill(); + + // 텍스트 + ctx.fillStyle = textColor; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(region.workplace_name, centerX, centerY); + + // 인원수 표시 + const total = workerCount + visitorCount; + if (total > 0) { + // 인원수 배경 + ctx.font = 'bold 12px sans-serif'; + const countText = `${total}명`; + const countMetrics = ctx.measureText(countText); + const countWidth = countMetrics.width + 10; + const countHeight = 18; + + ctx.fillStyle = strokeColor; + drawRoundRect(ctx, centerX - countWidth / 2, centerY + 12, countWidth, countHeight, 4); + ctx.fill(); + + ctx.fillStyle = '#ffffff'; + ctx.fillText(countText, centerX, centerY + 21); + } +} + +/** + * 지도 클릭 처리 + */ +function onMapClick(e) { + const rect = canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + // 클릭된 영역 찾기 + for (const region of mapRegions) { + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { + selectWorkplace(region); + return; + } + } +} + +/** + * 작업장 선택 + */ +function selectWorkplace(region) { + // 기타 위치 체크박스 해제 + document.getElementById('useCustomLocation').checked = false; + document.getElementById('customLocationInput').classList.remove('visible'); + + selectedWorkplaceId = region.workplace_id; + selectedWorkplaceName = region.workplace_name; + + // 해당 작업장의 TBM/출입신청 확인 + const workers = todayWorkers.filter(w => w.workplace_id === region.workplace_id); + const visitors = todayVisitors.filter(v => v.workplace_id === region.workplace_id); + + if (workers.length > 0 || visitors.length > 0) { + // 작업 선택 모달 표시 + showWorkSelectionModal(workers, visitors); + } else { + selectedTbmSessionId = null; + selectedVisitRequestId = null; + } + + updateLocationInfo(); + renderMap(); + updateStepStatus(); +} + +/** + * 작업 선택 모달 표시 + */ +function showWorkSelectionModal(workers, visitors) { + const modal = document.getElementById('workSelectionModal'); + const optionsList = document.getElementById('workOptionsList'); + + optionsList.innerHTML = ''; + + // TBM 작업 옵션 + workers.forEach(w => { + const option = document.createElement('div'); + option.className = 'work-option'; + const safeTaskName = escapeHtml(w.task_name || '작업'); + const safeProjectName = escapeHtml(w.project_name || ''); + const memberCount = parseInt(w.member_count) || 0; + option.innerHTML = ` +
TBM: ${safeTaskName}
+
${safeProjectName} - ${memberCount}명
+ `; + option.onclick = () => { + selectedTbmSessionId = w.session_id; + selectedVisitRequestId = null; + closeWorkModal(); + updateLocationInfo(); + }; + optionsList.appendChild(option); + }); + + // 출입신청 옵션 + visitors.forEach(v => { + const option = document.createElement('div'); + option.className = 'work-option'; + const safeCompany = escapeHtml(v.visitor_company || '-'); + const safePurpose = escapeHtml(v.purpose_name || '방문'); + const visitorCount = parseInt(v.visitor_count) || 0; + option.innerHTML = ` +
출입: ${safeCompany}
+
${safePurpose} - ${visitorCount}명
+ `; + option.onclick = () => { + selectedVisitRequestId = v.request_id; + selectedTbmSessionId = null; + closeWorkModal(); + updateLocationInfo(); + }; + optionsList.appendChild(option); + }); + + modal.classList.add('visible'); +} + +/** + * 작업 선택 모달 닫기 + */ +function closeWorkModal() { + document.getElementById('workSelectionModal').classList.remove('visible'); +} + +/** + * 선택된 위치 정보 업데이트 + */ +function updateLocationInfo() { + const infoBox = document.getElementById('selectedLocationInfo'); + const customLocation = document.getElementById('customLocation').value; + const useCustom = document.getElementById('useCustomLocation').checked; + + if (useCustom && customLocation) { + infoBox.classList.remove('empty'); + infoBox.innerHTML = `선택된 위치: ${escapeHtml(customLocation)}`; + } else if (selectedWorkplaceName) { + infoBox.classList.remove('empty'); + let html = `선택된 위치: ${escapeHtml(selectedWorkplaceName)}`; + + if (selectedTbmSessionId) { + const worker = todayWorkers.find(w => w.session_id === selectedTbmSessionId); + if (worker) { + html += `
연결 작업: ${escapeHtml(worker.task_name || '-')} (TBM)`; + } + } else if (selectedVisitRequestId) { + const visitor = todayVisitors.find(v => v.request_id === selectedVisitRequestId); + if (visitor) { + html += `
연결 작업: ${escapeHtml(visitor.visitor_company || '-')} (출입)`; + } + } + + infoBox.innerHTML = html; + } else { + infoBox.classList.add('empty'); + infoBox.textContent = '지도에서 작업장을 클릭하여 위치를 선택하세요'; + } +} + +/** + * 유형 선택 + */ +function onTypeSelect(type) { + selectedType = type; + selectedCategoryId = null; + selectedCategoryName = null; + selectedItemId = null; + + // 버튼 상태 업데이트 + document.querySelectorAll('.type-btn').forEach(btn => { + btn.classList.toggle('selected', btn.dataset.type === type); + }); + + // 카테고리 로드 + loadCategories(type); + updateStepStatus(); +} + +/** + * 카테고리 로드 + */ +async function loadCategories(type) { + try { + const response = await fetch(`${API_BASE}/work-issues/categories/type/${type}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) throw new Error('카테고리 조회 실패'); + + const data = await response.json(); + if (data.success && data.data) { + renderCategories(data.data); + } + } catch (error) { + console.error('카테고리 로드 실패:', error); + } +} + +/** + * 카테고리 렌더링 + */ +function renderCategories(categories) { + const container = document.getElementById('categoryContainer'); + const grid = document.getElementById('categoryGrid'); + + grid.innerHTML = ''; + + categories.forEach(cat => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'category-btn'; + btn.textContent = cat.category_name; + btn.onclick = () => onCategorySelect(cat); + grid.appendChild(btn); + }); + + container.style.display = 'block'; +} + +/** + * 카테고리 선택 + */ +function onCategorySelect(category) { + selectedCategoryId = category.category_id; + selectedCategoryName = category.category_name; + selectedItemId = null; + + // 버튼 상태 업데이트 + document.querySelectorAll('.category-btn').forEach(btn => { + btn.classList.toggle('selected', btn.textContent === category.category_name); + }); + + // 항목 로드 + loadItems(category.category_id); + updateStepStatus(); +} + +/** + * 항목 로드 + */ +async function loadItems(categoryId) { + try { + const response = await fetch(`${API_BASE}/work-issues/items/category/${categoryId}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) throw new Error('항목 조회 실패'); + + const data = await response.json(); + if (data.success && data.data) { + renderItems(data.data); + } + } catch (error) { + console.error('항목 로드 실패:', error); + } +} + +/** + * 항목 렌더링 + */ +function renderItems(items) { + const grid = document.getElementById('itemGrid'); + grid.innerHTML = ''; + + // 기존 항목들 렌더링 + items.forEach(item => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'item-btn'; + btn.textContent = item.item_name; + btn.dataset.severity = item.severity; + btn.onclick = () => onItemSelect(item, btn); + grid.appendChild(btn); + }); + + // 직접 입력 버튼 추가 + const customBtn = document.createElement('button'); + customBtn.type = 'button'; + customBtn.className = 'item-btn custom-input-btn'; + customBtn.textContent = '+ 직접 입력'; + customBtn.onclick = () => showCustomItemInput(); + grid.appendChild(customBtn); + + // 직접 입력 영역 숨기기 + document.getElementById('customItemInput').style.display = 'none'; + document.getElementById('customItemName').value = ''; + customItemName = null; +} + +/** + * 항목 선택 + */ +function onItemSelect(item, btn) { + // 단일 선택 (기존 선택 해제) + document.querySelectorAll('.item-btn').forEach(b => b.classList.remove('selected')); + btn.classList.add('selected'); + + selectedItemId = item.item_id; + customItemName = null; // 기존 항목 선택 시 직접 입력 초기화 + document.getElementById('customItemInput').style.display = 'none'; + updateStepStatus(); +} + +/** + * 직접 입력 영역 표시 + */ +function showCustomItemInput() { + // 기존 선택 해제 + document.querySelectorAll('.item-btn').forEach(b => b.classList.remove('selected')); + document.querySelector('.custom-input-btn').classList.add('selected'); + + selectedItemId = null; + + // 입력 영역 표시 + document.getElementById('customItemInput').style.display = 'flex'; + document.getElementById('customItemName').focus(); +} + +/** + * 직접 입력 확인 + */ +function confirmCustomItem() { + const input = document.getElementById('customItemName'); + const value = input.value.trim(); + + if (!value) { + alert('항목명을 입력해주세요.'); + input.focus(); + return; + } + + customItemName = value; + selectedItemId = null; // 커스텀 항목이므로 ID는 null + + // 입력 완료 표시 + const customBtn = document.querySelector('.custom-input-btn'); + customBtn.textContent = `✓ ${value}`; + customBtn.classList.add('selected'); + + updateStepStatus(); +} + +/** + * 직접 입력 취소 + */ +function cancelCustomItem() { + document.getElementById('customItemInput').style.display = 'none'; + document.getElementById('customItemName').value = ''; + customItemName = null; + + // 직접 입력 버튼 원상복구 + const customBtn = document.querySelector('.custom-input-btn'); + customBtn.textContent = '+ 직접 입력'; + customBtn.classList.remove('selected'); + + updateStepStatus(); +} + +/** + * 사진 선택 + */ +function onPhotoSelect(e) { + const file = e.target.files[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = (event) => { + photos[currentPhotoIndex] = event.target.result; + updatePhotoSlot(currentPhotoIndex); + updateStepStatus(); // 제출 버튼 상태 업데이트 + }; + reader.readAsDataURL(file); + + // 입력 초기화 + e.target.value = ''; +} + +/** + * 사진 슬롯 업데이트 + */ +function updatePhotoSlot(index) { + const slot = document.querySelector(`.photo-slot[data-index="${index}"]`); + + if (photos[index]) { + slot.classList.add('has-photo'); + let img = slot.querySelector('img'); + if (!img) { + img = document.createElement('img'); + slot.insertBefore(img, slot.firstChild); + } + img.src = photos[index]; + } else { + slot.classList.remove('has-photo'); + const img = slot.querySelector('img'); + if (img) img.remove(); + } +} + +/** + * 사진 삭제 + */ +function removePhoto(index) { + photos[index] = null; + updatePhotoSlot(index); + updateStepStatus(); // 제출 버튼 상태 업데이트 +} + +/** + * 단계 상태 업데이트 + */ +function updateStepStatus() { + const steps = document.querySelectorAll('.step'); + const customLocation = document.getElementById('customLocation').value; + const useCustom = document.getElementById('useCustomLocation').checked; + + // Step 1: 위치 + const step1Complete = (useCustom && customLocation) || selectedWorkplaceId; + steps[0].classList.toggle('completed', step1Complete); + steps[1].classList.toggle('active', step1Complete); + + // Step 2: 유형 + const step2Complete = selectedType && selectedCategoryId; + steps[1].classList.toggle('completed', step2Complete); + steps[2].classList.toggle('active', step2Complete); + + // Step 3: 항목 (기존 항목 선택 또는 직접 입력) + const step3Complete = selectedItemId || customItemName; + steps[2].classList.toggle('completed', step3Complete); + steps[3].classList.toggle('active', step3Complete); + + // 제출 버튼 활성화 + const submitBtn = document.getElementById('submitBtn'); + const hasPhoto = photos.some(p => p !== null); + submitBtn.disabled = !(step1Complete && step2Complete && step3Complete && hasPhoto); +} + +/** + * 신고 제출 + */ +async function submitReport() { + const submitBtn = document.getElementById('submitBtn'); + submitBtn.disabled = true; + submitBtn.textContent = '제출 중...'; + + try { + const useCustom = document.getElementById('useCustomLocation').checked; + const customLocation = document.getElementById('customLocation').value; + const additionalDescription = document.getElementById('additionalDescription').value; + + const requestBody = { + factory_category_id: useCustom ? null : selectedFactoryId, + workplace_id: useCustom ? null : selectedWorkplaceId, + custom_location: useCustom ? customLocation : null, + tbm_session_id: selectedTbmSessionId, + visit_request_id: selectedVisitRequestId, + issue_category_id: selectedCategoryId, + issue_item_id: selectedItemId, + custom_item_name: customItemName, // 직접 입력한 항목명 + additional_description: additionalDescription || null, + photos: photos.filter(p => p !== null) + }; + + const response = await fetch(`${API_BASE}/work-issues`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + }, + body: JSON.stringify(requestBody) + }); + + const data = await response.json(); + + if (data.success) { + alert('신고가 등록되었습니다.'); + // 유형에 따라 다른 페이지로 리다이렉트 + if (selectedType === 'nonconformity') { + window.location.href = '/pages/work/nonconformity.html'; + } else if (selectedType === 'safety') { + window.location.href = '/pages/safety/report-status.html'; + } else { + // 기본: 뒤로가기 + history.back(); + } + } else { + throw new Error(data.error || '신고 등록 실패'); + } + } catch (error) { + console.error('신고 제출 실패:', error); + alert('신고 등록에 실패했습니다: ' + error.message); + } finally { + submitBtn.disabled = false; + submitBtn.textContent = '신고 제출'; + } +} + +// 기타 위치 입력 시 위치 정보 업데이트 +document.addEventListener('DOMContentLoaded', () => { + const customLocationInput = document.getElementById('customLocation'); + if (customLocationInput) { + customLocationInput.addEventListener('input', () => { + updateLocationInfo(); + updateStepStatus(); + }); + } +}); + +// 전역 함수 노출 (HTML onclick에서 호출용) +window.closeWorkModal = closeWorkModal; +window.submitReport = submitReport; +window.showCustomItemInput = showCustomItemInput; +window.confirmCustomItem = confirmCustomItem; +window.cancelCustomItem = cancelCustomItem; diff --git a/deploy/tkfb-package/web-ui/js/load-navbar.js b/deploy/tkfb-package/web-ui/js/load-navbar.js new file mode 100644 index 0000000..efbcf60 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/load-navbar.js @@ -0,0 +1,442 @@ +// /js/load-navbar.js +import { getUser, clearAuthData } from './auth.js'; +import { loadComponent } from './component-loader.js'; +import { config } from './config.js'; + +// 역할 이름을 한글로 변환하는 맵 +const ROLE_NAMES = { + 'system admin': '시스템 관리자', + 'admin': '관리자', + 'system': '시스템 관리자', + 'leader': '그룹장', + 'user': '작업자', + 'support': '지원팀', + 'default': '사용자', +}; + +/** + * 네비게이션 바 DOM을 사용자 정보와 역할에 맞게 수정하는 프로세서입니다. + * @param {Document} doc - 파싱된 HTML 문서 객체 + */ +async function processNavbarDom(doc) { + const currentUser = getUser(); + if (!currentUser) return; + + // 1. 역할 및 페이지 권한 기반 메뉴 필터링 + await filterMenuByPageAccess(doc, currentUser); + + // 2. 사용자 정보 채우기 + populateUserInfo(doc, currentUser); +} + +/** + * 사용자의 페이지 접근 권한에 따라 메뉴 항목을 필터링합니다. + * @param {Document} doc - 파싱된 HTML 문서 객체 + * @param {object} currentUser - 현재 사용자 객체 + */ +async function filterMenuByPageAccess(doc, currentUser) { + const userRole = (currentUser.role || '').toLowerCase(); + + // Admin은 모든 메뉴 표시 + .admin-only 요소 활성화 + if (userRole === 'admin' || userRole === 'system admin') { + doc.querySelectorAll('.admin-only').forEach(el => el.classList.add('visible')); + return; + } + + try { + // 사용자의 페이지 접근 권한 조회 + const cached = localStorage.getItem('userPageAccess'); + let accessiblePages = null; + + if (cached) { + const cacheData = JSON.parse(cached); + // 캐시가 5분 이내인 경우 사용 + if (Date.now() - cacheData.timestamp < 5 * 60 * 1000) { + accessiblePages = cacheData.pages; + } + } + + // 캐시가 없으면 API 호출 + if (!accessiblePages) { + const response = await fetch(`${window.API_BASE_URL}/users/${currentUser.user_id}/page-access`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + } + }); + + if (!response.ok) { + console.error('페이지 권한 조회 실패:', response.status); + return; + } + + const data = await response.json(); + accessiblePages = data.data.pageAccess || []; + + // 캐시 저장 + localStorage.setItem('userPageAccess', JSON.stringify({ + pages: accessiblePages, + timestamp: Date.now() + })); + } + + // 접근 가능한 페이지 키 목록 + const accessiblePageKeys = accessiblePages + .filter(p => p.can_access === 1) + .map(p => p.page_key); + + // 메뉴 항목에 data-page-key 속성이 있으면 해당 권한 체크 + const menuItems = doc.querySelectorAll('[data-page-key]'); + menuItems.forEach(item => { + const pageKey = item.getAttribute('data-page-key'); + + // 대시보드와 프로필 페이지는 모든 사용자 접근 가능 + if (pageKey === 'dashboard' || pageKey.startsWith('profile.')) { + return; + } + + // 권한이 없으면 메뉴 항목 제거 + if (!accessiblePageKeys.includes(pageKey)) { + item.remove(); + } + }); + + // Admin 전용 메뉴는 무조건 제거 + doc.querySelectorAll('.admin-only').forEach(el => el.remove()); + + } catch (error) { + console.error('메뉴 필터링 오류:', error); + } +} + +/** + * 네비게이션 바에 사용자 정보를 채웁니다. + * @param {Document} doc - 파싱된 HTML 문서 객체 + * @param {object} user - 현재 사용자 객체 + */ +function populateUserInfo(doc, user) { + const displayName = user.name || user.username; + // 대소문자 구분 없이 처리 + const roleLower = (user.role || '').toLowerCase(); + const roleName = ROLE_NAMES[roleLower] || ROLE_NAMES.default; + + const elements = { + 'userName': displayName, + 'userRole': roleName, + 'userInitial': displayName.charAt(0), + }; + + for (const id in elements) { + const el = doc.getElementById(id); + if (el) el.textContent = elements[id]; + } + + // 메인 대시보드 URL 설정 + const dashboardBtn = doc.getElementById('dashboardBtn'); + if (dashboardBtn) { + dashboardBtn.href = '/pages/dashboard.html'; + } +} + +/** + * 네비게이션 바와 관련된 모든 이벤트를 설정합니다. + */ +function setupNavbarEvents() { + const logoutButton = document.getElementById('logoutBtn'); + if (logoutButton) { + logoutButton.addEventListener('click', () => { + if (confirm('로그아웃 하시겠습니까?')) { + clearAuthData(); + window.location.href = config.paths.loginPage; + } + }); + } +} + +/** + * 현재 날짜와 시간을 업데이트하는 함수 + */ +function updateDateTime() { + const now = new Date(); + + // 시간 업데이트 (시 분 초 형식으로 고정) + const timeElement = document.getElementById('timeValue'); + if (timeElement) { + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + timeElement.textContent = `${hours}시 ${minutes}분 ${seconds}초`; + } + + // 날짜 업데이트 + const dateElement = document.getElementById('dateValue'); + if (dateElement) { + const days = ['일', '월', '화', '수', '목', '금', '토']; + const month = now.getMonth() + 1; + const date = now.getDate(); + const day = days[now.getDay()]; + dateElement.textContent = `${month}월 ${date}일 (${day})`; + } +} + +// 날씨 아이콘 매핑 +const WEATHER_ICONS = { + clear: '☀️', + rain: '🌧️', + snow: '❄️', + heat: '🔥', + cold: '🥶', + wind: '💨', + fog: '🌫️', + dust: '😷', + cloudy: '⛅', + overcast: '☁️' +}; + +// 날씨 조건명 +const WEATHER_NAMES = { + clear: '맑음', + rain: '비', + snow: '눈', + heat: '폭염', + cold: '한파', + wind: '강풍', + fog: '안개', + dust: '미세먼지', + cloudy: '구름많음', + overcast: '흐림' +}; + +/** + * 날씨 정보를 가져와서 업데이트하는 함수 + */ +async function updateWeather() { + try { + const token = localStorage.getItem('token'); + if (!token) return; + + const response = await fetch(`${window.API_BASE_URL}/tbm/weather/current`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + } + }); + + if (!response.ok) { + throw new Error('날씨 API 호출 실패'); + } + + const result = await response.json(); + + if (result.success && result.data) { + const { temperature, conditions, weatherData } = result.data; + + // 온도 표시 + const tempElement = document.getElementById('weatherTemp'); + if (tempElement && temperature !== null && temperature !== undefined) { + tempElement.textContent = `${Math.round(temperature)}°C`; + } + + // 날씨 아이콘 및 설명 + const iconElement = document.getElementById('weatherIcon'); + const descElement = document.getElementById('weatherDesc'); + + if (conditions && conditions.length > 0) { + const primaryCondition = conditions[0]; + if (iconElement) { + iconElement.textContent = WEATHER_ICONS[primaryCondition] || '🌤️'; + } + if (descElement) { + descElement.textContent = WEATHER_NAMES[primaryCondition] || '맑음'; + } + } else { + if (iconElement) iconElement.textContent = '☀️'; + if (descElement) descElement.textContent = '맑음'; + } + + // 날씨 섹션 표시 + const weatherSection = document.getElementById('weatherSection'); + if (weatherSection) { + weatherSection.style.opacity = '1'; + } + } + } catch (error) { + console.warn('날씨 정보 로드 실패:', error.message); + // 실패해도 기본값 표시 + const descElement = document.getElementById('weatherDesc'); + if (descElement) { + descElement.textContent = '날씨 정보 없음'; + } + } +} + +// ========================================== +// 알림 시스템 +// ========================================== + +/** + * 알림 관련 이벤트 설정 + */ +function setupNotificationEvents() { + const notificationBtn = document.getElementById('notificationBtn'); + const notificationDropdown = document.getElementById('notificationDropdown'); + const notificationWrapper = document.getElementById('notificationWrapper'); + + if (notificationBtn) { + notificationBtn.addEventListener('click', (e) => { + e.stopPropagation(); + notificationDropdown?.classList.toggle('show'); + }); + } + + // 외부 클릭시 드롭다운 닫기 + document.addEventListener('click', (e) => { + if (notificationWrapper && notificationDropdown && !notificationWrapper.contains(e.target)) { + notificationDropdown.classList.remove('show'); + } + }); +} + +/** + * 알림 목록 로드 + */ +async function loadNotifications() { + try { + const token = localStorage.getItem('token'); + if (!token) return; + + const response = await fetch(`${window.API_BASE_URL}/notifications/unread`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${token}` + } + }); + + if (!response.ok) return; + + const result = await response.json(); + if (result.success) { + const notifications = result.data || []; + updateNotificationBadge(notifications.length); + renderNotificationList(notifications); + } + } catch (error) { + console.warn('알림 로드 오류:', error.message); + } +} + +/** + * 배지 업데이트 + */ +function updateNotificationBadge(count) { + const badge = document.getElementById('notificationBadge'); + const btn = document.getElementById('notificationBtn'); + if (!badge) return; + + if (count > 0) { + badge.textContent = count > 99 ? '99+' : count; + badge.style.display = 'flex'; + btn?.classList.add('has-notifications'); + } else { + badge.style.display = 'none'; + btn?.classList.remove('has-notifications'); + } +} + +/** + * 알림 목록 렌더링 + */ +function renderNotificationList(notifications) { + const list = document.getElementById('notificationList'); + if (!list) return; + + if (notifications.length === 0) { + list.innerHTML = '
새 알림이 없습니다.
'; + return; + } + + const NOTIF_ICONS = { + repair: '🔧', + safety: '⚠️', + system: '📢', + equipment: '🔩', + maintenance: '🛠️' + }; + + list.innerHTML = notifications.slice(0, 5).map(n => ` +
+
+ ${NOTIF_ICONS[n.type] || '🔔'} +
+
+
${escapeHtml(n.title)}
+
${escapeHtml(n.message || '')}
+
+
${formatTimeAgo(n.created_at)}
+
+ `).join(''); + + // 클릭 이벤트 추가 + list.querySelectorAll('.notification-item').forEach(item => { + item.addEventListener('click', () => { + const linkUrl = item.dataset.url; + // 수리 알림은 클릭해도 읽음 처리 안함 (수리 처리 페이지에서 확인 처리) + window.location.href = linkUrl || '/pages/admin/notifications.html'; + }); + }); +} + +/** + * 시간 포맷팅 + */ +function formatTimeAgo(dateString) { + const date = new Date(dateString); + const now = new Date(); + const diffMs = now - date; + const diffMins = Math.floor(diffMs / 60000); + const diffHours = Math.floor(diffMs / 3600000); + const diffDays = Math.floor(diffMs / 86400000); + + if (diffMins < 1) return '방금 전'; + if (diffMins < 60) return `${diffMins}분 전`; + if (diffHours < 24) return `${diffHours}시간 전`; + if (diffDays < 7) return `${diffDays}일 전`; + return date.toLocaleDateString('ko-KR', { month: 'short', day: 'numeric' }); +} + +/** + * HTML 이스케이프 + */ +function escapeHtml(text) { + if (!text) return ''; + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; +} + +// 메인 로직: DOMContentLoaded 시 실행 +document.addEventListener('DOMContentLoaded', async () => { + if (getUser()) { + // 1. 컴포넌트 로드 및 DOM 수정 + await loadComponent('navbar', '#navbar-container', processNavbarDom); + + // 2. DOM에 삽입된 후에 이벤트 리스너 설정 + setupNavbarEvents(); + + // 3. 실시간 날짜/시간 업데이트 시작 + updateDateTime(); + setInterval(updateDateTime, 1000); + + // 4. 날씨 정보 로드 (10분마다 갱신) + updateWeather(); + setInterval(updateWeather, 10 * 60 * 1000); + + // 5. 알림 이벤트 설정 및 로드 (30초마다 갱신) + setupNotificationEvents(); + loadNotifications(); + setInterval(loadNotifications, 30000); + } +}); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/load-sections.js b/deploy/tkfb-package/web-ui/js/load-sections.js new file mode 100644 index 0000000..6b735ff --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/load-sections.js @@ -0,0 +1,104 @@ +// /js/load-sections.js +import { getUser } from './auth.js'; +import { apiGet } from './api-helper.js'; + +// 역할에 따라 불러올 섹션 HTML 파일을 매핑합니다. +const SECTION_MAP = { + admin: '/components/sections/admin-sections.html', + system: '/components/sections/admin-sections.html', // system도 admin과 동일한 섹션을 사용 + leader: '/components/sections/leader-sections.html', + user: '/components/sections/user-sections.html', + default: '/components/sections/user-sections.html', // 역할이 없는 경우 기본값 +}; + +/** + * API를 통해 대시보드 통계 데이터를 가져옵니다. + * @returns {Promise} 통계 데이터 또는 에러 시 null + */ +async function fetchDashboardStats() { + try { + const today = new Date().toISOString().split('T')[0]; + // 실제 백엔드 엔드포인트는 /api/dashboard/stats 와 같은 형태로 구현될 수 있습니다. + const stats = await apiGet(`/workreports?start=${today}&end=${today}`); + // 필요한 데이터 형태로 가공 (예시) + return { + today_reports_count: stats.length, + today_workers_count: new Set(stats.map(d => d.worker_id)).size, + }; + } catch (error) { + console.error('대시보드 통계 데이터 로드 실패:', error); + return null; + } +} + +/** + * 가상 DOM에 통계 데이터를 채워 넣습니다. + * @param {Document} doc - 파싱된 HTML 문서 객체 + * @param {object} stats - 통계 데이터 + */ +function populateStatsData(doc, stats) { + if (!stats) return; + + const todayStatsEl = doc.getElementById('today-stats'); + if (todayStatsEl) { + todayStatsEl.innerHTML = ` +

📝 오늘 등록된 작업: ${stats.today_reports_count}건

+

👥 참여 작업자: ${stats.today_workers_count}명

+ `; + } +} + +/** + * 메인 로직: 페이지에 역할별 섹션을 로드하고 내용을 채웁니다. + */ +async function initializeSections() { + const mainContainer = document.querySelector('main[id$="-sections"]'); + if (!mainContainer) { + console.error('섹션을 담을 메인 컨테이너를 찾을 수 없습니다.'); + return; + } + mainContainer.innerHTML = '
콘텐츠를 불러오는 중...
'; + + const currentUser = getUser(); + if (!currentUser) { + mainContainer.innerHTML = '
사용자 정보를 찾을 수 없습니다.
'; + return; + } + + const sectionFile = SECTION_MAP[currentUser.role] || SECTION_MAP.default; + + try { + // 1. 역할에 맞는 HTML 템플릿과 동적 데이터를 동시에 로드 (Promise.all 활용) + const [htmlResponse, statsData] = await Promise.all([ + fetch(sectionFile), + fetchDashboardStats() + ]); + + if (!htmlResponse.ok) { + throw new Error(`섹션 파일(${sectionFile})을 불러오는 데 실패했습니다.`); + } + const htmlText = await htmlResponse.text(); + + // 2. 텍스트를 가상 DOM으로 파싱 + const parser = new DOMParser(); + const doc = parser.parseFromString(htmlText, 'text/html'); + + // 3. (필요 시) 역할 기반으로 가상 DOM 필터링 - 현재는 파일 자체가 역할별로 나뉘어 불필요 + // filterByRole(doc, currentUser.role); + + // 4. 가상 DOM에 동적 데이터 채우기 + populateStatsData(doc, statsData); + + // 5. 모든 수정이 완료된 HTML을 실제 DOM에 한 번에 삽입 + mainContainer.innerHTML = doc.body.innerHTML; + + console.log(`✅ ${currentUser.role} 역할의 섹션 로딩 완료.`); + + } catch (error) { + console.error('섹션 로딩 중 오류 발생:', error); + mainContainer.innerHTML = `
콘텐츠 로딩에 실패했습니다: ${error.message}
`; + } +} + +// DOM이 로드되면 섹션 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializeSections); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/load-sidebar.js b/deploy/tkfb-package/web-ui/js/load-sidebar.js new file mode 100644 index 0000000..037b7b8 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/load-sidebar.js @@ -0,0 +1,209 @@ +// /js/load-sidebar.js +// 사이드바 네비게이션 로더 및 컨트롤러 + +import { getUser } from './auth.js'; +import { loadComponent } from './component-loader.js'; + +/** + * 사이드바 DOM을 사용자 권한에 맞게 처리 + */ +async function processSidebarDom(doc) { + const currentUser = getUser(); + if (!currentUser) return; + + const userRole = (currentUser.role || '').toLowerCase(); + const accessLevel = (currentUser.access_level || '').toLowerCase(); + // role 또는 access_level로 관리자 확인 + const isAdmin = userRole === 'admin' || userRole === 'system admin' || userRole === 'system' || + accessLevel === 'admin' || accessLevel === 'system'; + + // 1. 관리자 전용 메뉴 표시/숨김 + if (isAdmin) { + doc.querySelectorAll('.admin-only').forEach(el => el.classList.add('visible')); + } else { + // 비관리자: 페이지 접근 권한에 따라 메뉴 필터링 + await filterMenuByPageAccess(doc, currentUser); + } + + // 2. 현재 페이지 활성화 + highlightCurrentPage(doc); + + // 3. 저장된 상태 복원 + restoreSidebarState(doc); +} + +/** + * 사용자의 페이지 접근 권한에 따라 메뉴 필터링 + */ +async function filterMenuByPageAccess(doc, currentUser) { + try { + const cached = localStorage.getItem('userPageAccess'); + let accessiblePages = null; + + if (cached) { + const cacheData = JSON.parse(cached); + if (Date.now() - cacheData.timestamp < 5 * 60 * 1000) { + accessiblePages = cacheData.pages; + } + } + + if (!accessiblePages) { + const response = await fetch(`${window.API_BASE_URL}/users/${currentUser.user_id}/page-access`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + } + }); + + if (!response.ok) return; + + const data = await response.json(); + accessiblePages = data.data.pageAccess || []; + + localStorage.setItem('userPageAccess', JSON.stringify({ + pages: accessiblePages, + timestamp: Date.now() + })); + } + + const accessiblePageKeys = accessiblePages + .filter(p => p.can_access === 1) + .map(p => p.page_key); + + // 메뉴 항목 필터링 + const menuItems = doc.querySelectorAll('[data-page-key]'); + menuItems.forEach(item => { + const pageKey = item.getAttribute('data-page-key'); + + // 대시보드와 프로필은 항상 표시 + if (pageKey === 'dashboard' || pageKey.startsWith('profile.')) { + return; + } + + // 권한 없으면 숨김 + if (!accessiblePageKeys.includes(pageKey)) { + item.style.display = 'none'; + } + }); + + // 관리자 전용 카테고리 제거 + doc.querySelectorAll('.nav-category.admin-only').forEach(el => el.remove()); + + } catch (error) { + console.error('사이드바 메뉴 필터링 오류:', error); + } +} + +/** + * 현재 페이지 하이라이트 + */ +function highlightCurrentPage(doc) { + const currentPath = window.location.pathname; + + doc.querySelectorAll('.nav-item').forEach(item => { + const href = item.getAttribute('href'); + if (href && currentPath.includes(href.replace(/^\//, ''))) { + item.classList.add('active'); + + // 부모 카테고리 열기 + const category = item.closest('.nav-category'); + if (category) { + category.classList.add('expanded'); + } + } + }); +} + +/** + * 사이드바 상태 복원 (기본값: 접힌 상태) + */ +function restoreSidebarState(doc) { + const isCollapsed = localStorage.getItem('sidebarCollapsed') !== 'false'; + const sidebar = doc.querySelector('.sidebar-nav'); + + if (isCollapsed && sidebar) { + sidebar.classList.add('collapsed'); + document.body.classList.add('sidebar-collapsed'); + } + + // 확장된 카테고리 복원 + const expandedCategories = JSON.parse(localStorage.getItem('sidebarExpanded') || '[]'); + expandedCategories.forEach(category => { + const el = doc.querySelector(`[data-category="${category}"]`); + if (el) el.classList.add('expanded'); + }); +} + +/** + * 사이드바 이벤트 설정 + */ +function setupSidebarEvents() { + const sidebar = document.getElementById('sidebarNav'); + const toggle = document.getElementById('sidebarToggle'); + + if (!sidebar || !toggle) return; + + // 토글 버튼 클릭 + toggle.addEventListener('click', () => { + sidebar.classList.toggle('collapsed'); + document.body.classList.toggle('sidebar-collapsed'); + + localStorage.setItem('sidebarCollapsed', sidebar.classList.contains('collapsed')); + }); + + // 카테고리 헤더 클릭 + sidebar.querySelectorAll('.nav-category-header').forEach(header => { + header.addEventListener('click', () => { + const category = header.closest('.nav-category'); + category.classList.toggle('expanded'); + + // 상태 저장 + const expanded = []; + sidebar.querySelectorAll('.nav-category.expanded').forEach(cat => { + const categoryName = cat.getAttribute('data-category'); + if (categoryName) expanded.push(categoryName); + }); + localStorage.setItem('sidebarExpanded', JSON.stringify(expanded)); + }); + }); + + // 링크 프리페치 - 마우스 올리면 미리 로드 + const prefetchedUrls = new Set(); + sidebar.querySelectorAll('a.nav-item').forEach(link => { + link.addEventListener('mouseenter', () => { + const href = link.getAttribute('href'); + if (href && !prefetchedUrls.has(href) && !href.startsWith('#')) { + prefetchedUrls.add(href); + const prefetchLink = document.createElement('link'); + prefetchLink.rel = 'prefetch'; + prefetchLink.href = href; + document.head.appendChild(prefetchLink); + } + }, { once: true }); + }); +} + +/** + * 사이드바 초기화 + */ +async function initSidebar() { + // 사이드바 컨테이너가 없으면 생성 + let container = document.getElementById('sidebar-container'); + if (!container) { + container = document.createElement('div'); + container.id = 'sidebar-container'; + document.body.prepend(container); + } + + if (getUser()) { + await loadComponent('sidebar-nav', '#sidebar-container', processSidebarDom); + document.body.classList.add('has-sidebar'); + setupSidebarEvents(); + } +} + +// DOMContentLoaded 시 초기화 +document.addEventListener('DOMContentLoaded', initSidebar); + +export { initSidebar }; \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/login.js b/deploy/tkfb-package/web-ui/js/login.js new file mode 100644 index 0000000..8dedb51 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/login.js @@ -0,0 +1,49 @@ +// /js/login.js +import { saveAuthData, clearAuthData } from './auth.js'; +import { redirectToDefaultDashboard } from './navigation.js'; +// api-helper.js가 ES6 모듈로 변환되면 import를 사용해야 합니다. +// import { login } from './api-helper.js'; + +document.getElementById('loginForm').addEventListener('submit', async function (e) { + e.preventDefault(); + + const username = document.getElementById('username').value; + const password = document.getElementById('password').value; + const errorDiv = document.getElementById('error'); + + const submitBtn = e.target.querySelector('button[type="submit"]'); + const originalText = submitBtn.textContent; + + // 로딩 상태 시작 + submitBtn.disabled = true; + submitBtn.textContent = '로그인 중...'; + errorDiv.style.display = 'none'; + + try { + // 현재는 window 객체를 통해 호출하지만, 향후 모듈화 필요 + const result = await window.login(username, password); + + if (result.success && result.data && result.data.token) { + // auth.js에서 가져온 함수로 인증 정보 저장 + saveAuthData(result.data.token, result.data.user); + + // navigation.js를 통해 리디렉션 + redirectToDefaultDashboard(result.data.redirectUrl); + + } else { + // api-helper가 에러를 throw하므로 이 블록은 실행될 가능성이 낮음 + clearAuthData(); + errorDiv.textContent = result.error || '로그인에 실패했습니다.'; + errorDiv.style.display = 'block'; + } + } catch (err) { + console.error('로그인 오류:', err); + clearAuthData(); + errorDiv.textContent = err.message || '서버 연결에 실패했습니다.'; + errorDiv.style.display = 'block'; + } finally { + // 로딩 상태 해제 + submitBtn.disabled = false; + submitBtn.textContent = originalText; + } +}); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/manage-issue.js b/deploy/tkfb-package/web-ui/js/manage-issue.js new file mode 100644 index 0000000..dba6317 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/manage-issue.js @@ -0,0 +1,86 @@ +import { API, getAuthHeaders } from '/js/api-config.js'; + +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key]; + tr.appendChild(td); + }); + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + return tr; +} + +const form = document.getElementById('issueTypeForm'); +form?.addEventListener('submit', async e => { + e.preventDefault(); + const body = { + category: document.getElementById('category').value, + subcategory: document.getElementById('subcategory').value + }; + try { + const res = await fetch(`${API}/issue-types`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(body) + }); + const result = await res.json(); + if (res.ok && result.success) { + alert('✅ 등록 완료'); + form.reset(); + loadIssueTypes(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +async function loadIssueTypes() { + const tbody = document.getElementById('issueTypeTableBody'); + tbody.innerHTML = '불러오는 중...'; + try { + const res = await fetch(`${API}/issue-types`, { + headers: getAuthHeaders() + }); + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + list.forEach(item => { + const row = createRow(item, ['issue_type_id', 'category', 'subcategory'], async t => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/issue-types/${t.issue_type_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + loadIssueTypes(); + } else { + alert('삭제 실패'); + } + } catch (err) { + alert('삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +document.addEventListener('DOMContentLoaded', () => { + loadIssueTypes(); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/manage-pipespec.js b/deploy/tkfb-package/web-ui/js/manage-pipespec.js new file mode 100644 index 0000000..cceabb4 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/manage-pipespec.js @@ -0,0 +1,93 @@ +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +ensureAuthenticated(); + +// 행 생성 +function createRow(item, delHandler) { + const tr = document.createElement('tr'); + const label = `${item.material} / ${item.diameter_in} / ${item.schedule}`; + tr.innerHTML = ` + ${item.spec_id} + ${label} + + `; + tr.querySelector('.btn-delete').onclick = () => delHandler(item); + return tr; +} + +// 등록 +document.getElementById('specForm')?.addEventListener('submit', async e => { + e.preventDefault(); + const material = document.getElementById('material').value.trim(); + const diameter = document.getElementById('diameter_in').value.trim(); + const schedule = document.getElementById('schedule').value.trim(); + + if (!material || !diameter || !schedule) { + return alert('모든 항목을 입력하세요.'); + } + + try { + const res = await fetch(`${API}/pipespecs`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ material, diameter_in: diameter, schedule }) + }); + const result = await res.json(); + if (res.ok && result.success) { + alert('✅ 등록 완료'); + e.target.reset(); + loadSpecs(); + } else { + alert('❌ 실패: ' + (result.error || '등록 실패')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +// 불러오기 +async function loadSpecs() { + const tbody = document.getElementById('specTableBody'); + tbody.innerHTML = '불러오는 중...'; + try { + const res = await fetch(`${API}/pipespecs`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + list.forEach(item => { + const row = createRow(item, async (spec) => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/pipespecs/${spec.spec_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + loadSpecs(); + } else { + alert('삭제 실패'); + } + } catch (err) { + alert('삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +window.addEventListener('DOMContentLoaded', loadSpecs); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/manage-project.js b/deploy/tkfb-package/web-ui/js/manage-project.js new file mode 100644 index 0000000..93d6ebd --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/manage-project.js @@ -0,0 +1,90 @@ +// /js/manage-project.js + +// The ensureAuthenticated, API, and getAuthHeaders functions are now handled by the global api-helper.js + +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key]; + tr.appendChild(td); + }); + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + return tr; +} + +const projectForm = document.getElementById('projectForm'); +projectForm?.addEventListener('submit', async e => { + e.preventDefault(); + const body = { + job_no: document.getElementById('job_no').value.trim(), + project_name: document.getElementById('project_name').value.trim(), + contract_date: document.getElementById('contract_date').value, + due_date: document.getElementById('due_date').value, + delivery_method: document.getElementById('delivery_method').value.trim(), + site: document.getElementById('site').value.trim(), + pm: document.getElementById('pm').value.trim() + }; + + if (!body.project_name || !body.job_no) { + return alert('필수 항목을 입력하세요.'); + } + + try { + const result = await apiPost('/projects', body); + if (result.success) { + alert('✅ 등록 완료'); + projectForm.reset(); + loadProjects(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +async function loadProjects() { + const tbody = document.getElementById('projectTableBody'); + tbody.innerHTML = '불러오는 중...'; + try { + const result = await apiGet('/projects'); + + tbody.innerHTML = ''; + + if (result.success && Array.isArray(result.data)) { + result.data.forEach(item => { + const row = createRow(item, [ + 'project_id', 'job_no', 'project_name', 'contract_date', + 'due_date', 'delivery_method', 'site', 'pm' + ], async p => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await apiDelete(`/projects/${p.project_id}`); + if (delRes.success) { + alert('✅ 삭제 완료'); + loadProjects(); + } else { + alert('❌ 삭제 실패: ' + (delRes.error || '알 수 없는 오류')); + } + } catch (err) { + alert('🚨 삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +window.addEventListener('DOMContentLoaded', loadProjects); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/manage-user.js b/deploy/tkfb-package/web-ui/js/manage-user.js new file mode 100644 index 0000000..99c671e --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/manage-user.js @@ -0,0 +1,512 @@ +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +const token = ensureAuthenticated(); + +const accessLabels = { + worker: '작업자', + group_leader: '그룹장', + support_team: '지원팀', + admin: '관리자', + system: '시스템' +}; + +// 현재 사용자 정보 가져오기 +const currentUser = JSON.parse(localStorage.getItem('user') || '{}'); +const isSystemUser = currentUser.access_level === 'system'; + +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key] || '-'; + tr.appendChild(td); + }); + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + return tr; +} + +// 내 비밀번호 변경 +const myPasswordForm = document.getElementById('myPasswordForm'); +myPasswordForm?.addEventListener('submit', async e => { + e.preventDefault(); + + const currentPassword = document.getElementById('currentPassword').value; + const newPassword = document.getElementById('newPassword').value; + const confirmPassword = document.getElementById('confirmPassword').value; + + // 새 비밀번호 확인 + if (newPassword !== confirmPassword) { + alert('❌ 새 비밀번호가 일치하지 않습니다.'); + return; + } + + // 비밀번호 강도 검사 + if (newPassword.length < 6) { + alert('❌ 비밀번호는 최소 6자 이상이어야 합니다.'); + return; + } + + try { + const res = await fetch(`${API}/auth/change-password`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + currentPassword, + newPassword + }) + }); + + const result = await res.json(); + + if (res.ok && result.success) { + showToast('✅ 비밀번호가 변경되었습니다.'); + myPasswordForm.reset(); + + // 3초 후 로그인 페이지로 이동 + setTimeout(() => { + alert('비밀번호가 변경되어 다시 로그인해주세요.'); + localStorage.removeItem('token'); + localStorage.removeItem('user'); + window.location.href = '/index.html'; + }, 2000); + } else { + alert('❌ 비밀번호 변경 실패: ' + (result.error || '현재 비밀번호가 올바르지 않습니다.')); + } + } catch (error) { + console.error('Password change error:', error); + alert('🚨 서버 오류: ' + error.message); + } +}); + +// 시스템 권한자만 볼 수 있는 사용자 비밀번호 변경 섹션 +if (isSystemUser) { + const systemCard = document.getElementById('systemPasswordChangeCard'); + if (systemCard) { + systemCard.style.display = 'block'; + } + + // 사용자 비밀번호 변경 (시스템 권한자) + const userPasswordForm = document.getElementById('userPasswordForm'); + userPasswordForm?.addEventListener('submit', async e => { + e.preventDefault(); + + const targetUserId = document.getElementById('targetUserId').value; + const newPassword = document.getElementById('targetNewPassword').value; + + if (!targetUserId) { + alert('❌ 사용자를 선택해주세요.'); + return; + } + + if (newPassword.length < 6) { + alert('❌ 비밀번호는 최소 6자 이상이어야 합니다.'); + return; + } + + if (!confirm('정말로 이 사용자의 비밀번호를 변경하시겠습니까?')) { + return; + } + + try { + const res = await fetch(`${API}/auth/admin/change-password`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + userId: targetUserId, + newPassword + }) + }); + + const result = await res.json(); + + if (res.ok && result.success) { + showToast('✅ 사용자 비밀번호가 변경되었습니다.'); + userPasswordForm.reset(); + } else { + alert('❌ 비밀번호 변경 실패: ' + (result.error || '권한이 없습니다.')); + } + } catch (error) { + console.error('Admin password change error:', error); + alert('🚨 서버 오류: ' + error.message); + } + }); +} + +// 사용자 등록 +const userForm = document.getElementById('userForm'); +userForm?.addEventListener('submit', async e => { + e.preventDefault(); + const body = { + username: document.getElementById('username').value.trim(), + password: document.getElementById('password').value.trim(), + name: document.getElementById('name').value.trim(), + access_level: document.getElementById('access_level').value, + worker_id: document.getElementById('worker_id').value || null + }; + + try { + const res = await fetch(`${API}/auth/register`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(body) + }); + const result = await res.json(); + if (res.ok && result.success) { + showToast('✅ 등록 완료'); + userForm.reset(); + loadUsers(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (error) { + console.error('Registration error:', error); + alert('🚨 서버 오류: ' + error.message); + } +}); + +async function loadUsers() { + const tbody = document.getElementById('userTableBody'); + tbody.innerHTML = '불러오는 중...'; + + try { + const res = await fetch(`${API}/auth/users`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const list = await res.json(); + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + // 시스템 권한자용 사용자 선택 옵션도 업데이트 + if (isSystemUser) { + const targetUserSelect = document.getElementById('targetUserId'); + if (targetUserSelect) { + targetUserSelect.innerHTML = ''; + list.forEach(user => { + // 본인은 제외 + if (user.user_id !== currentUser.user_id) { + const opt = document.createElement('option'); + opt.value = user.user_id; + opt.textContent = `${user.name} (${user.username})`; + targetUserSelect.appendChild(opt); + } + }); + } + } + + list.forEach(item => { + item.access_level = accessLabels[item.access_level] || item.access_level; + item.worker_id = item.worker_id || '-'; + + // 행 생성 + const tr = document.createElement('tr'); + + // 데이터 컬럼 + ['user_id', 'username', 'name', 'access_level', 'worker_id'].forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key] || '-'; + tr.appendChild(td); + }); + + // 작업 컬럼 (페이지 권한 버튼 + 삭제 버튼) + const actionTd = document.createElement('td'); + + // 페이지 권한 버튼 (Admin/System이 아닌 경우에만) + if (item.access_level !== '관리자' && item.access_level !== '시스템') { + const pageAccessBtn = document.createElement('button'); + pageAccessBtn.textContent = '페이지 권한'; + pageAccessBtn.className = 'btn btn-info btn-sm'; + pageAccessBtn.style.marginRight = '5px'; + pageAccessBtn.onclick = () => openPageAccessModal(item.user_id, item.username, item.name); + actionTd.appendChild(pageAccessBtn); + } + + // 삭제 버튼 + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = async () => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/auth/users/${item.user_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + showToast('✅ 삭제 완료'); + loadUsers(); + } else { + alert('❌ 삭제 실패'); + } + } catch (error) { + alert('🚨 삭제 중 오류 발생'); + } + }; + actionTd.appendChild(delBtn); + + tr.appendChild(actionTd); + tbody.appendChild(tr); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (error) { + console.error('Load users error:', error); + tbody.innerHTML = '로드 실패: ' + error.message + ''; + } +} + +async function loadWorkerOptions() { + const select = document.getElementById('worker_id'); + if (!select) return; + + try { + const res = await fetch(`${API}/workers`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const allWorkers = await res.json(); + + // 활성화된 작업자만 필터링 + const workers = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + + if (Array.isArray(workers)) { + workers.forEach(w => { + const opt = document.createElement('option'); + opt.value = w.worker_id; + opt.textContent = `${w.worker_name} (${w.worker_id})`; + select.appendChild(opt); + }); + } + } catch (error) { + console.warn('작업자 목록 불러오기 실패:', error); + } +} + +function showToast(message) { + const toast = document.createElement('div'); + toast.textContent = message; + toast.style.position = 'fixed'; + toast.style.bottom = '30px'; + toast.style.left = '50%'; + toast.style.transform = 'translateX(-50%)'; + toast.style.background = '#323232'; + toast.style.color = '#fff'; + toast.style.padding = '10px 20px'; + toast.style.borderRadius = '6px'; + toast.style.fontSize = '14px'; + toast.style.zIndex = 9999; + document.body.appendChild(toast); + setTimeout(() => toast.remove(), 2000); +} + +// ========== 페이지 접근 권한 관리 ========== + +let currentEditingUserId = null; +let currentUserPageAccess = []; + +/** + * 페이지 권한 관리 모달 열기 + */ +async function openPageAccessModal(userId, username, name) { + currentEditingUserId = userId; + + const modal = document.getElementById('pageAccessModal'); + const modalUserInfo = document.getElementById('modalUserInfo'); + const modalUserRole = document.getElementById('modalUserRole'); + + modalUserInfo.textContent = `${name} (${username})`; + modalUserRole.textContent = `사용자 ID: ${userId}`; + + try { + // 사용자의 페이지 접근 권한 조회 + const res = await fetch(`${API}/users/${userId}/page-access`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error('페이지 접근 권한을 불러오는데 실패했습니다.'); + } + + const result = await res.json(); + if (result.success) { + currentUserPageAccess = result.data.pageAccess; + renderPageAccessList(result.data.pageAccess); + modal.style.display = 'block'; + } else { + throw new Error(result.error || '데이터 로드 실패'); + } + } catch (error) { + console.error('페이지 권한 로드 오류:', error); + alert('❌ 페이지 권한을 불러오는데 실패했습니다: ' + error.message); + } +} + +/** + * 페이지 접근 권한 목록 렌더링 + */ +function renderPageAccessList(pageAccess) { + const categories = { + dashboard: document.getElementById('dashboardPageList'), + management: document.getElementById('managementPageList'), + common: document.getElementById('commonPageList') + }; + + // 카테고리별로 초기화 + Object.values(categories).forEach(el => { + if (el) el.innerHTML = ''; + }); + + // 카테고리별로 그룹화 + const grouped = pageAccess.reduce((acc, page) => { + if (!acc[page.category]) acc[page.category] = []; + acc[page.category].push(page); + return acc; + }, {}); + + // 각 카테고리별로 렌더링 + Object.keys(grouped).forEach(category => { + const container = categories[category]; + if (!container) return; + + grouped[category].forEach(page => { + const pageItem = document.createElement('div'); + pageItem.className = 'page-item'; + + const checkbox = document.createElement('input'); + checkbox.type = 'checkbox'; + checkbox.id = `page_${page.page_id}`; + checkbox.checked = page.can_access === 1 || page.can_access === true; + checkbox.dataset.pageId = page.page_id; + + const label = document.createElement('label'); + label.htmlFor = `page_${page.page_id}`; + label.textContent = page.page_name; + + const pathSpan = document.createElement('span'); + pathSpan.className = 'page-path'; + pathSpan.textContent = page.page_path; + + pageItem.appendChild(checkbox); + pageItem.appendChild(label); + pageItem.appendChild(pathSpan); + + container.appendChild(pageItem); + }); + }); +} + +/** + * 페이지 권한 변경 사항 저장 + */ +async function savePageAccessChanges() { + if (!currentEditingUserId) { + alert('사용자 정보가 없습니다.'); + return; + } + + // 모든 체크박스 상태 가져오기 + const checkboxes = document.querySelectorAll('.page-item input[type="checkbox"]'); + const pageAccessUpdates = {}; + + checkboxes.forEach(checkbox => { + const pageId = parseInt(checkbox.dataset.pageId); + const canAccess = checkbox.checked; + pageAccessUpdates[pageId] = canAccess; + }); + + try { + // 변경된 페이지 권한을 서버로 전송 + const pageIds = Object.keys(pageAccessUpdates).map(id => parseInt(id)); + const canAccessValues = pageIds.map(id => pageAccessUpdates[id]); + + // 접근 가능한 페이지 + const accessiblePages = pageIds.filter((id, index) => canAccessValues[index]); + // 접근 불가능한 페이지 + const inaccessiblePages = pageIds.filter((id, index) => !canAccessValues[index]); + + // 접근 가능 페이지 업데이트 + if (accessiblePages.length > 0) { + await fetch(`${API}/users/${currentEditingUserId}/page-access`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + pageIds: accessiblePages, + canAccess: true + }) + }); + } + + // 접근 불가능 페이지 업데이트 + if (inaccessiblePages.length > 0) { + await fetch(`${API}/users/${currentEditingUserId}/page-access`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify({ + pageIds: inaccessiblePages, + canAccess: false + }) + }); + } + + showToast('✅ 페이지 접근 권한이 저장되었습니다.'); + closePageAccessModal(); + } catch (error) { + console.error('페이지 권한 저장 오류:', error); + alert('❌ 페이지 권한 저장에 실패했습니다: ' + error.message); + } +} + +/** + * 페이지 권한 관리 모달 닫기 + */ +function closePageAccessModal() { + const modal = document.getElementById('pageAccessModal'); + modal.style.display = 'none'; + currentEditingUserId = null; + currentUserPageAccess = []; +} + +// 모달 닫기 버튼 이벤트 +document.addEventListener('DOMContentLoaded', () => { + const modal = document.getElementById('pageAccessModal'); + const closeBtn = modal?.querySelector('.close'); + + if (closeBtn) { + closeBtn.onclick = closePageAccessModal; + } + + // 모달 외부 클릭 시 닫기 + window.onclick = (event) => { + if (event.target === modal) { + closePageAccessModal(); + } + }; +}); + +// 전역 함수로 노출 +window.openPageAccessModal = openPageAccessModal; +window.closePageAccessModal = closePageAccessModal; +window.savePageAccessChanges = savePageAccessChanges; + +window.addEventListener('DOMContentLoaded', () => { + loadUsers(); + loadWorkerOptions(); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/manage-worker.js b/deploy/tkfb-package/web-ui/js/manage-worker.js new file mode 100644 index 0000000..bb44577 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/manage-worker.js @@ -0,0 +1,111 @@ +// /js/manage-worker.js + +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +ensureAuthenticated(); + +// ✅ 테이블 행 생성 +function createRow(item, cols, delHandler) { + const tr = document.createElement('tr'); + cols.forEach(key => { + const td = document.createElement('td'); + td.textContent = item[key] || '-'; + tr.appendChild(td); + }); + + const delBtn = document.createElement('button'); + delBtn.textContent = '삭제'; + delBtn.className = 'btn-delete'; + delBtn.onclick = () => delHandler(item); + + const td = document.createElement('td'); + td.appendChild(delBtn); + tr.appendChild(td); + + return tr; +} + +// ✅ 작업자 등록 +const workerForm = document.getElementById('workerForm'); +workerForm?.addEventListener('submit', async e => { + e.preventDefault(); + + const body = { + worker_name: document.getElementById('workerName').value.trim(), + position: document.getElementById('position').value.trim() + }; + + if (!body.worker_name || !body.position) { + return alert('모든 필드를 입력해주세요.'); + } + + try { + const res = await fetch(`${API}/workers`, { + method: 'POST', + headers: getAuthHeaders(), + body: JSON.stringify(body) + }); + const result = await res.json(); + + if (res.ok && result.success) { + alert('✅ 등록 완료'); + workerForm.reset(); + loadWorkers(); + } else { + alert('❌ 실패: ' + (result.error || '알 수 없는 오류')); + } + } catch (err) { + alert('🚨 서버 오류: ' + err.message); + } +}); + +// ✅ 작업자 목록 불러오기 +async function loadWorkers() { + const tbody = document.getElementById('workerTableBody'); + tbody.innerHTML = '불러오는 중...'; + + try { + const res = await fetch(`${API}/workers`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const response = await res.json(); + const list = response.data || response; // 새로운 API 응답 구조 지원 + tbody.innerHTML = ''; + + if (Array.isArray(list)) { + list.forEach(item => { + const row = createRow(item, ['worker_id', 'worker_name', 'position'], async w => { + if (!confirm('삭제하시겠습니까?')) return; + try { + const delRes = await fetch(`${API}/workers/${w.worker_id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + if (delRes.ok) { + alert('✅ 삭제 완료'); + loadWorkers(); + } else { + alert('❌ 삭제 실패'); + } + } catch (err) { + alert('🚨 삭제 중 오류: ' + err.message); + } + }); + tbody.appendChild(row); + }); + } else { + tbody.innerHTML = '데이터 형식 오류'; + } + } catch (err) { + tbody.innerHTML = '로드 실패: ' + err.message + ''; + } +} + +// ✅ 초기 로딩 +window.addEventListener('DOMContentLoaded', loadWorkers); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/management-dashboard.js b/deploy/tkfb-package/web-ui/js/management-dashboard.js new file mode 100644 index 0000000..161aa78 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/management-dashboard.js @@ -0,0 +1,960 @@ +// management-dashboard.js - 관리자 대시보드 전용 스크립트 + +// ================================================================= +// 🌐 통합 API 설정 import +// ================================================================= +import { API, getAuthHeaders, apiCall } from '/js/api-config.js'; + +// 전역 변수 +let workers = []; +let workData = []; +let filteredWorkData = []; +let currentDate = ''; +let currentUser = null; + +// 권한 레벨 매핑 +const ACCESS_LEVELS = { + worker: 1, + group_leader: 2, + support_team: 3, + admin: 4, + system: 5 +}; + +// 한국 시간 기준 오늘 날짜 가져오기 +function getKoreaToday() { + const today = new Date(); + const year = today.getFullYear(); + const month = String(today.getMonth() + 1).padStart(2, '0'); + const day = String(today.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +// 현재 로그인한 사용자 정보 가져오기 +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + console.log('토큰에서 추출한 사용자 정보:', payload); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + + try { + const userInfo = localStorage.getItem('user') || localStorage.getItem('userInfo') || localStorage.getItem('currentUser'); + if (userInfo) { + const parsed = JSON.parse(userInfo); + console.log('localStorage에서 가져온 사용자 정보:', parsed); + return parsed; + } + } catch (error) { + console.log('localStorage에서 사용자 정보 가져오기 실패:', error); + } + + return null; +} + +// 권한 체크 함수 +function checkPermission() { + currentUser = getCurrentUser(); + + if (!currentUser) { + showMessage('로그인이 필요합니다.', 'error'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return false; + } + + const userAccessLevel = currentUser.access_level; + const accessLevelValue = ACCESS_LEVELS[userAccessLevel] || 0; + + console.log('사용자 권한 체크:', { + username: currentUser.username || currentUser.name, + access_level: userAccessLevel, + level_value: accessLevelValue, + required_level: ACCESS_LEVELS.group_leader + }); + + if (accessLevelValue < ACCESS_LEVELS.group_leader) { + showMessage('그룹장 이상의 권한이 필요합니다. 현재 권한: ' + userAccessLevel, 'error'); + setTimeout(() => { + window.location.href = '/'; + }, 3000); + return false; + } + + return true; +} + +// 메시지 표시 +function showMessage(message, type = 'info') { + const container = document.getElementById('message-container'); + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => { + hideMessage(); + }, 5000); + } +} + +function hideMessage() { + document.getElementById('message-container').innerHTML = ''; +} + +// 로딩 표시 +function showLoading() { + document.getElementById('loadingSpinner').style.display = 'flex'; + document.getElementById('summarySection').style.display = 'none'; + document.getElementById('actionBar').style.display = 'none'; + document.getElementById('workersSection').style.display = 'none'; + document.getElementById('noDataMessage').style.display = 'none'; +} + +function hideLoading() { + document.getElementById('loadingSpinner').style.display = 'none'; +} + +// 작업자 데이터 로드 +async function loadWorkers() { + try { + console.log('작업자 데이터 로딩 중... (통합 API)'); + const data = await apiCall(`${API}/workers`); + const allWorkers = Array.isArray(data) ? data : (data.data || data.workers || []); + + // 활성화된 작업자만 필터링 + workers = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + + console.log(`✅ 작업자 로드 성공: ${workers.length}명 (전체: ${allWorkers.length}명)`); + } catch (error) { + console.error('작업자 로딩 오류:', error); + throw error; + } +} + +// 특정 날짜의 작업 데이터 로드 (개선된 버전) +async function loadWorkData(date) { + try { + console.log(`${date} 날짜의 작업 데이터 로딩 중... (통합 API)`); + + // 1차: view_all=true로 전체 데이터 시도 + let queryParams = `date=${date}&view_all=true`; + console.log(`🔍 1차 시도: ${API}/daily-work-reports?${queryParams}`); + + let data = await apiCall(`${API}/daily-work-reports?${queryParams}`); + workData = Array.isArray(data) ? data : (data.data || []); + + // 데이터가 없으면 다른 방법들 시도 + if (workData.length === 0) { + console.log('⚠️ view_all로 데이터 없음, 다른 방법 시도...'); + + // 2차: admin=true로 시도 + queryParams = `date=${date}&admin=true`; + console.log(`🔍 2차 시도: ${API}/daily-work-reports?${queryParams}`); + + data = await apiCall(`${API}/daily-work-reports?${queryParams}`); + workData = Array.isArray(data) ? data : (data.data || []); + + if (workData.length === 0) { + // 3차: 날짜 경로 파라미터로 시도 + console.log(`🔍 3차 시도: ${API}/daily-work-reports/date/${date}`); + + data = await apiCall(`${API}/daily-work-reports/date/${date}`); + workData = Array.isArray(data) ? data : (data.data || []); + + if (workData.length === 0) { + // 4차: 기본 파라미터만으로 시도 + console.log(`🔍 4차 시도: ${API}/daily-work-reports?date=${date}`); + + data = await apiCall(`${API}/daily-work-reports?date=${date}`); + workData = Array.isArray(data) ? data : (data.data || []); + } + } + } + + console.log(`✅ 최종 작업 데이터 로드 결과: ${workData.length}개`); + + // 디버깅을 위한 상세 로그 + if (workData.length > 0) { + console.log('📊 로드된 데이터 샘플:', workData.slice(0, 3)); + const uniqueWorkers = [...new Set(workData.map(w => w.worker_name))]; + console.log('👥 데이터에 포함된 작업자들:', uniqueWorkers); + } else { + console.log('❌ 해당 날짜에 작업 데이터가 없거나 접근 권한이 없습니다.'); + } + + return workData; + } catch (error) { + console.error('작업 데이터 로딩 오류:', error); + + // 에러 시에도 빈 배열 반환하여 앱이 중단되지 않도록 + workData = []; + + // 구체적인 에러 정보 표시 + if (error.message.includes('403')) { + console.log('🔒 권한 부족으로 인한 접근 제한'); + throw new Error('해당 날짜의 데이터에 접근할 권한이 없습니다.'); + } else if (error.message.includes('404')) { + console.log('📭 해당 날짜에 데이터 없음'); + throw new Error('해당 날짜에 입력된 작업 데이터가 없습니다.'); + } else { + throw error; + } + } +} + +// 대시보드 데이터 로드 +async function loadDashboardData() { + const selectedDate = document.getElementById('selectedDate').value; + + if (!selectedDate) { + showMessage('날짜를 선택해주세요.', 'error'); + return; + } + + currentDate = selectedDate; + showLoading(); + hideMessage(); + + try { + // 병렬로 데이터 로드 + await Promise.all([ + loadWorkers(), + loadWorkData(selectedDate) + ]); + + // 데이터 분석 및 표시 + const dashboardData = analyzeDashboardData(); + displayDashboard(dashboardData); + + hideLoading(); + + } catch (error) { + console.error('대시보드 데이터 로드 실패:', error); + hideLoading(); + showMessage('데이터를 불러오는 중 오류가 발생했습니다: ' + error.message, 'error'); + + // 에러 시 데이터 없음 메시지 표시 + document.getElementById('noDataMessage').style.display = 'block'; + } +} + +// 대시보드 데이터 분석 (개선된 버전) +function analyzeDashboardData() { + console.log('대시보드 데이터 분석 시작'); + + // 작업자별 데이터 그룹화 + const workerWorkData = {}; + workData.forEach(work => { + const workerId = work.worker_id; + if (!workerWorkData[workerId]) { + workerWorkData[workerId] = []; + } + workerWorkData[workerId].push(work); + }); + + // 전체 통계 계산 + const totalWorkers = workers.length; + const workersWithData = Object.keys(workerWorkData).length; + const workersWithoutData = totalWorkers - workersWithData; + const totalHours = workData.reduce((sum, work) => sum + parseFloat(work.work_hours || 0), 0); + const totalEntries = workData.length; + const errorCount = workData.filter(work => work.work_status_id === 2).length; + + // 작업자별 상세 분석 (개선된 버전) + const workerAnalysis = workers.map(worker => { + const workerWorks = workerWorkData[worker.worker_id] || []; + const workerHours = workerWorks.reduce((sum, work) => sum + parseFloat(work.work_hours || 0), 0); + + // 작업 유형 분석 (실제 이름으로) + const workTypes = [...new Set(workerWorks.map(work => work.work_type_name).filter(Boolean))]; + + // 프로젝트 분석 + const workerProjects = [...new Set(workerWorks.map(work => work.project_name).filter(Boolean))]; + + // 기여자 분석 + const workerContributors = [...new Set(workerWorks.map(work => work.created_by_name).filter(Boolean))]; + + // 상태 결정 (더 세밀한 기준) + let status = 'missing'; + if (workerWorks.length > 0) { + if (workerHours >= 6) { + status = 'completed'; // 6시간 이상을 완료로 간주 + } else { + status = 'partial'; // 1시간 이상이지만 6시간 미만은 부분입력 + } + } + + // 최근 업데이트 시간 + const lastUpdate = workerWorks.length > 0 + ? new Date(Math.max(...workerWorks.map(work => new Date(work.created_at)))) + : null; + + return { + ...worker, + status, + totalHours: Math.round(workerHours * 10) / 10, // 소수점 1자리로 반올림 + entryCount: workerWorks.length, + workTypes, // 작업 유형 배열 (실제 이름) + projects: workerProjects, + contributors: workerContributors, + lastUpdate, + works: workerWorks + }; + }); + + const summary = { + totalWorkers, + completedWorkers: workerAnalysis.filter(w => w.status === 'completed').length, + missingWorkers: workerAnalysis.filter(w => w.status === 'missing').length, + partialWorkers: workerAnalysis.filter(w => w.status === 'partial').length, + totalHours: Math.round(totalHours * 10) / 10, + totalEntries, + errorCount + }; + + console.log('대시보드 분석 결과:', { summary, workerAnalysis }); + + return { + summary, + workers: workerAnalysis, + date: currentDate + }; +} + +// 대시보드 표시 +function displayDashboard(data) { + displaySummary(data.summary); + displayWorkers(data.workers); + + // 섹션 표시 + document.getElementById('summarySection').style.display = 'block'; + document.getElementById('actionBar').style.display = 'flex'; + document.getElementById('workersSection').style.display = 'block'; + + // 필터링 설정 + filteredWorkData = data.workers; + setupFiltering(); + + console.log('✅ 대시보드 표시 완료'); +} + +// 요약 섹션 표시 +function displaySummary(summary) { + document.getElementById('totalWorkers').textContent = summary.totalWorkers; + document.getElementById('completedWorkers').textContent = summary.completedWorkers; + document.getElementById('missingWorkers').textContent = summary.missingWorkers; + document.getElementById('totalHours').textContent = summary.totalHours + 'h'; + document.getElementById('totalEntries').textContent = summary.totalEntries; + document.getElementById('errorCount').textContent = summary.errorCount; +} + +// 작업자 목록 표시 (테이블 형태로 개선) +function displayWorkers(workersData) { + const tableBody = document.getElementById('workersTableBody'); + tableBody.innerHTML = ''; + + if (workersData.length === 0) { + tableBody.innerHTML = ` + + 표시할 작업자가 없습니다. + + `; + return; + } + + workersData.forEach(worker => { + const row = createWorkerRow(worker); + tableBody.appendChild(row); + }); +} + +// 작업자 테이블 행 생성 (개선된 버전) +function createWorkerRow(worker) { + const row = document.createElement('tr'); + + const statusText = { + completed: '✅ 완료', + missing: '❌ 미입력', + partial: '⚠️ 부분입력' + }; + + const statusClass = { + completed: 'completed', + missing: 'missing', + partial: 'partial' + }; + + // 작업 유형 태그 생성 (실제 이름으로) + const workTypeTags = worker.workTypes && worker.workTypes.length > 0 + ? worker.workTypes.map(type => `${type}`).join('') + : '없음'; + + // 프로젝트 태그 생성 + const projectTags = worker.projects && worker.projects.length > 0 + ? worker.projects.map(project => `${project}`).join('') + : '없음'; + + // 기여자 태그 생성 + const contributorTags = worker.contributors && worker.contributors.length > 0 + ? worker.contributors.map(contributor => `${contributor}`).join('') + : '없음'; + + // 시간에 따른 스타일 클래스 + let hoursClass = 'zero'; + if (worker.totalHours > 0) { + hoursClass = worker.totalHours >= 6 ? 'full' : 'partial'; + } + + // 업데이트 시간 포맷팅 및 스타일 + let updateTimeText = '없음'; + let updateClass = ''; + if (worker.lastUpdate) { + const now = new Date(); + const diff = now - worker.lastUpdate; + const hours = diff / (1000 * 60 * 60); + + updateTimeText = formatDateTime(worker.lastUpdate); + updateClass = hours < 1 ? 'recent' : hours > 24 ? 'old' : ''; + } + + row.innerHTML = ` + +
+ 👤 ${worker.worker_name} +
+ + + ${statusText[worker.status]} + + +
${worker.totalHours}h
+ + + ${worker.entryCount}개 + + +
${workTypeTags}
+ + +
${projectTags}
+ + +
${contributorTags}
+ + +
${updateTimeText}
+ + + + + `; + + return row; +} + +// 날짜/시간 포맷팅 +function formatDateTime(date) { + const d = new Date(date); + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + const hours = String(d.getHours()).padStart(2, '0'); + const minutes = String(d.getMinutes()).padStart(2, '0'); + + return `${year}-${month}-${day} ${hours}:${minutes}`; +} + +// 작업자 상세 모달 표시 (안전한 버전) +function showWorkerDetailSafe(workerId) { + // 현재 분석된 데이터에서 해당 작업자 찾기 + const worker = filteredWorkData.find(w => w.worker_id == workerId); + if (!worker) { + showMessage('작업자 정보를 찾을 수 없습니다.', 'error'); + return; + } + + showWorkerDetail(worker); +} + +// 작업자 상세 모달 표시 (개선된 버전) +function showWorkerDetail(worker) { + const modal = document.getElementById('workerDetailModal'); + const modalTitle = document.getElementById('modalWorkerName'); + const modalBody = document.getElementById('modalWorkerDetails'); + + modalTitle.textContent = `👤 ${worker.worker_name} 상세 현황`; + + let detailHtml = ` +
+

📊 기본 정보

+

작업자명: ${worker.worker_name}

+

총 작업시간: ${worker.totalHours}시간

+

작업 항목 수: ${worker.entryCount}개

+

상태: ${worker.status === 'completed' ? '✅ 완료' : worker.status === 'missing' ? '❌ 미입력' : '⚠️ 부분입력'}

+

작업 유형: ${worker.workTypes && worker.workTypes.length > 0 ? worker.workTypes.join(', ') : '없음'}

+
+ `; + + if (worker.works && worker.works.length > 0) { + detailHtml += ` +
+

🔧 작업 내역

+
+ `; + + worker.works.forEach((work, index) => { + detailHtml += ` +
+
+

작업 ${index + 1}

+
+ + +
+
+

프로젝트: ${work.project_name || '미지정'}

+

작업 유형: ${work.work_type_name || '미지정'}

+

작업 시간: ${work.work_hours}시간

+

상태: ${work.work_status_name || '미지정'}

+ ${work.error_type_name ? `

에러 유형: ${work.error_type_name}

` : ''} +

입력자: ${work.created_by_name || '미지정'}

+

입력 시간: ${formatDateTime(work.created_at)}

+
+ `; + }); + + detailHtml += ` +
+
+ `; + } else { + detailHtml += ` +
+

📭 작업 내역

+

입력된 작업이 없습니다.

+
+ `; + } + + if (worker.contributors && worker.contributors.length > 0) { + detailHtml += ` +
+

👥 기여자

+

${worker.contributors.join(', ')}

+
+ `; + } + + modalBody.innerHTML = detailHtml; + modal.style.display = 'flex'; +} + +// 작업 항목 수정 함수 (통합 API 사용) +async function editWorkItem(workId) { + try { + console.log('수정할 작업 ID:', workId); + + // 현재 작업 데이터에서 해당 작업 찾기 + let workData = null; + for (const worker of filteredWorkData) { + if (worker.works) { + workData = worker.works.find(work => work.id == workId); + if (workData) break; + } + } + + if (!workData) { + showMessage('수정할 작업을 찾을 수 없습니다.', 'error'); + return; + } + + // 필요한 마스터 데이터 로드 + await loadMasterDataForEdit(); + + // 수정 모달 표시 + showEditModal(workData); + + } catch (error) { + console.error('작업 정보 조회 오류:', error); + showMessage('작업 정보를 불러올 수 없습니다: ' + error.message, 'error'); + } +} + +// 수정용 마스터 데이터 로드 +async function loadMasterDataForEdit() { + try { + if (!window.projects || window.projects.length === 0) { + const projectData = await apiCall(`${API}/projects`); + window.projects = Array.isArray(projectData) ? projectData : (projectData.projects || []); + } + + if (!window.workTypes || window.workTypes.length === 0) { + const workTypeData = await apiCall(`${API}/daily-work-reports/work-types`); + window.workTypes = Array.isArray(workTypeData) ? workTypeData : []; + } + + if (!window.workStatusTypes || window.workStatusTypes.length === 0) { + const statusData = await apiCall(`${API}/daily-work-reports/work-status-types`); + window.workStatusTypes = Array.isArray(statusData) ? statusData : []; + } + + if (!window.errorTypes || window.errorTypes.length === 0) { + const errorData = await apiCall(`${API}/daily-work-reports/error-types`); + window.errorTypes = Array.isArray(errorData) ? errorData : []; + } + + } catch (error) { + console.error('마스터 데이터 로드 오류:', error); + + // 기본값 설정 + window.projects = window.projects || []; + window.workTypes = window.workTypes || [ + {id: 1, name: 'Base'}, + {id: 2, name: 'Vessel'}, + {id: 3, name: 'Piping'} + ]; + window.workStatusTypes = window.workStatusTypes || [ + {id: 1, name: '정규'}, + {id: 2, name: '에러'} + ]; + window.errorTypes = window.errorTypes || [ + {id: 1, name: '설계미스'}, + {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, + {id: 4, name: '작업 불량'} + ]; + } +} + +// 수정 모달 표시 +function showEditModal(workData) { + // 기존 상세 모달 닫기 + closeWorkerDetailModal(); + + const modalHtml = ` +
+
+
+

✏️ 작업 수정

+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ `; + + document.body.insertAdjacentHTML('beforeend', modalHtml); + + // 업무 상태 변경 이벤트 + document.getElementById('editWorkStatus').addEventListener('change', (e) => { + const errorTypeGroup = document.getElementById('editErrorTypeGroup'); + if (e.target.value === '2') { + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + } + }); +} + +// 수정 모달 닫기 +function closeEditModal() { + const modal = document.getElementById('editModal'); + if (modal) { + modal.remove(); + } +} + +// 수정된 작업 저장 (통합 API 사용) +async function saveEditedWork(workId) { + try { + const projectId = document.getElementById('editProject').value; + const workTypeId = document.getElementById('editWorkType').value; + const workStatusId = document.getElementById('editWorkStatus').value; + const errorTypeId = document.getElementById('editErrorType').value; + const workHours = document.getElementById('editWorkHours').value; + + if (!projectId || !workTypeId || !workStatusId || !workHours) { + showMessage('모든 필수 항목을 입력해주세요.', 'error'); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showMessage('에러 상태인 경우 에러 유형을 선택해주세요.', 'error'); + return; + } + + const updateData = { + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: errorTypeId ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours) + }; + + showMessage('작업을 수정하는 중... (통합 API)', 'loading'); + + const result = await apiCall(`${API}/daily-work-reports/${workId}`, { + method: 'PUT', + body: JSON.stringify(updateData) + }); + + console.log('✅ 수정 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); + + closeEditModal(); + closeWorkerDetailModal(); + + // 데이터 새로고침 + await loadDashboardData(); + + } catch (error) { + console.error('❌ 수정 실패:', error); + showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 작업 항목 삭제 함수 (통합 API 사용) +async function deleteWorkItem(workId) { + if (!confirm('정말로 이 작업을 삭제하시겠습니까?\n삭제된 작업은 복구할 수 없습니다.')) { + return; + } + + try { + console.log('삭제할 작업 ID:', workId); + + showMessage('작업을 삭제하는 중... (통합 API)', 'loading'); + + // 개별 항목 삭제 API 호출 - 통합 API 사용 + const result = await apiCall(`${API}/daily-work-reports/${workId}`, { + method: 'DELETE' + }); + + console.log('✅ 삭제 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); + + closeWorkerDetailModal(); + + // 데이터 새로고침 + await loadDashboardData(); + + } catch (error) { + console.error('❌ 삭제 실패:', error); + showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 작업자 상세 모달 닫기 +function closeWorkerDetailModal() { + document.getElementById('workerDetailModal').style.display = 'none'; +} + +// 필터링 설정 +function setupFiltering() { + const showOnlyMissingCheckbox = document.getElementById('showOnlyMissing'); + + showOnlyMissingCheckbox.addEventListener('change', (e) => { + if (e.target.checked) { + // 미입력자만 필터링 + const missingWorkers = filteredWorkData.filter(worker => worker.status === 'missing'); + displayWorkers(missingWorkers); + } else { + // 전체 표시 + displayWorkers(filteredWorkData); + } + }); +} + +// 엑셀 다운로드 (개선된 버전) +function exportToExcel() { + try { + // CSV 형태로 데이터 구성 (개선된 버전) + let csvContent = "작업자명,상태,총시간,작업항목수,작업유형,프로젝트,기여자,최근업데이트\n"; + + filteredWorkData.forEach(worker => { + const statusText = { + completed: '완료', + missing: '미입력', + partial: '부분입력' + }; + + const workTypes = worker.workTypes && worker.workTypes.length > 0 ? worker.workTypes.join('; ') : '없음'; + const projects = worker.projects && worker.projects.length > 0 ? worker.projects.join('; ') : '없음'; + const contributors = worker.contributors && worker.contributors.length > 0 ? worker.contributors.join('; ') : '없음'; + const lastUpdate = worker.lastUpdate ? formatDateTime(worker.lastUpdate) : '없음'; + + csvContent += `"${worker.worker_name}","${statusText[worker.status]}","${worker.totalHours}","${worker.entryCount}","${workTypes}","${projects}","${contributors}","${lastUpdate}"\n`; + }); + + // UTF-8 BOM 추가 (한글 깨짐 방지) + const BOM = '\uFEFF'; + const blob = new Blob([BOM + csvContent], { type: 'text/csv;charset=utf-8;' }); + const link = document.createElement('a'); + const url = URL.createObjectURL(blob); + + link.setAttribute('href', url); + link.setAttribute('download', `작업현황_${currentDate}.csv`); + link.style.visibility = 'hidden'; + + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + + showMessage('✅ 엑셀 파일이 다운로드되었습니다!', 'success'); + + } catch (error) { + console.error('엑셀 다운로드 오류:', error); + showMessage('엑셀 다운로드 중 오류가 발생했습니다.', 'error'); + } +} + +// 새로고침 +function refreshData() { + loadDashboardData(); +} + +// 이벤트 리스너 설정 +function setupEventListeners() { + document.getElementById('loadDataBtn').addEventListener('click', loadDashboardData); + document.getElementById('refreshBtn').addEventListener('click', refreshData); + document.getElementById('exportBtn').addEventListener('click', exportToExcel); + + // 엔터키로 조회 + document.getElementById('selectedDate').addEventListener('keypress', (e) => { + if (e.key === 'Enter') { + loadDashboardData(); + } + }); +} + +// 초기화 +async function init() { + try { + // 권한 체크 + if (!checkPermission()) { + return; + } + + // 권한 체크 메시지 숨기기 + document.getElementById('permission-check-message').style.display = 'none'; + + // 오늘 날짜 설정 + document.getElementById('selectedDate').value = getKoreaToday(); + + // 이벤트 리스너 설정 + setupEventListeners(); + + console.log('✅ 관리자 대시보드 초기화 완료 (통합 API 설정 적용)'); + + // 자동으로 오늘 데이터 로드 + loadDashboardData(); + + } catch (error) { + console.error('초기화 오류:', error); + showMessage('초기화 중 오류가 발생했습니다.', 'error'); + } +} + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', () => { + // 권한 체크 메시지 표시 + document.getElementById('permission-check-message').style.display = 'block'; + + // 토큰 확인 + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + showMessage('로그인이 필요합니다.', 'error'); + localStorage.removeItem('token'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + // 초기화 실행 + init(); +}); + +// 전역 함수로 노출 +window.closeWorkerDetailModal = closeWorkerDetailModal; +window.refreshData = refreshData; +window.showWorkerDetailSafe = showWorkerDetailSafe; +window.showWorkerDetail = showWorkerDetail; +window.editWorkItem = editWorkItem; +window.deleteWorkItem = deleteWorkItem; +window.closeEditModal = closeEditModal; +window.saveEditedWork = saveEditedWork; \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/modern-dashboard.js b/deploy/tkfb-package/web-ui/js/modern-dashboard.js new file mode 100644 index 0000000..319a80b --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/modern-dashboard.js @@ -0,0 +1,1398 @@ +// ✅ modern-dashboard.js - 모던 대시보드 JavaScript + +// API 설정 및 함수들은 api-config.js에서 로드됨 +// window.API, window.apiCall, window.getAuthHeaders 사용 + +// 인증 관련 함수들 +function getAuthData() { + const token = localStorage.getItem('token'); + const user = localStorage.getItem('user'); + return { + token, + user: user ? JSON.parse(user) : null + }; +} + +// 전역 변수 +let currentUser = null; +let workersData = []; +let workData = []; +let selectedDate = new Date().toISOString().split('T')[0]; + +// 모달 관련 변수 +let currentModalWorker = null; +let modalWorkTypes = []; +let modalWorkStatusTypes = []; +let modalErrorTypes = []; +let modalProjects = []; +let modalExistingWork = []; + +// DOM 요소 +const elements = { + currentTime: document.getElementById('currentTime'), + timeValue: document.getElementById('timeValue'), + userName: document.getElementById('userName'), + userRole: document.getElementById('userRole'), + userInitial: document.getElementById('userInitial'), + selectedDate: document.getElementById('selectedDate'), // 작업장 현황으로 교체되어 없을 수 있음 + refreshBtn: document.getElementById('refreshBtn'), // 작업장 현황으로 교체되어 없을 수 있음 + logoutBtn: document.getElementById('logoutBtn'), + + // 요약 카드 + todayWorkers: document.getElementById('todayWorkers'), + totalHours: document.getElementById('totalHours'), + activeProjects: document.getElementById('activeProjects'), + errorCount: document.getElementById('errorCount'), + + // 컨테이너 + workStatusContainer: document.getElementById('workStatusContainer'), // 작업장 현황으로 교체되어 없을 수 있음 + workersContainer: document.getElementById('workersContainer'), + toastContainer: document.getElementById('toastContainer') +}; + +// ========== 초기화 ========== // +document.addEventListener('DOMContentLoaded', async () => { + // API 함수가 로드될 때까지 기다림 + let retryCount = 0; + const maxRetries = 50; // 5초 대기 + + while (!window.apiCall && retryCount < maxRetries) { + await new Promise(resolve => setTimeout(resolve, 100)); + retryCount++; + } + + if (!window.apiCall) { + console.error('❌ API 함수를 로드할 수 없습니다.'); + showToast('시스템을 초기화할 수 없습니다. 페이지를 새로고침해주세요.', 'error'); + return; + } + + try { + await initializeDashboard(); + } catch (error) { + console.error('대시보드 초기화 오류:', error); + showToast('대시보드를 불러오는 중 오류가 발생했습니다.', 'error'); + } +}); + +async function initializeDashboard() { + console.log('🚀 모던 대시보드 초기화 시작'); + + // 사용자 정보 설정 + setupUserInfo(); + + // 시간 업데이트 시작 + updateCurrentTime(); + setInterval(updateCurrentTime, 1000); + + // 날짜 설정 (요소가 있을 때만) + if (elements.selectedDate) { + elements.selectedDate.value = selectedDate; + } + + // 이벤트 리스너 설정 + setupEventListeners(); + + // 데이터 로드 (작업 현황 컨테이너가 있을 때만) + if (elements.workStatusContainer) { + await loadDashboardData(); + } + + // 관리자 권한 확인 + checkAdminAccess(); + + // TBM 페이지 접근 권한 확인 + checkTbmPageAccess(); + + console.log('✅ 모던 대시보드 초기화 완료'); +} + +// ========== 사용자 정보 설정 ========== // +// navbar/sidebar는 app-init.js에서 공통 처리하므로 여기서는 currentUser만 설정 +function setupUserInfo() { + const authData = getAuthData(); + if (authData && authData.user) { + currentUser = authData.user; + console.log('👤 사용자 정보 로드 완료:', currentUser.name, currentUser.role); + } +} + +// ========== 시간 업데이트 ========== // +function updateCurrentTime() { + // Navbar 컴포넌트가 시간을 처리하므로 여기서는 timeValue가 있을 때만 업데이트 + if (elements.timeValue) { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + elements.timeValue.textContent = `${hours}시 ${minutes}분 ${seconds}초`; + } +} + +// ========== 이벤트 리스너 ========== // +function setupEventListeners() { + // 날짜 변경 (요소가 있을 때만) + if (elements.selectedDate) { + elements.selectedDate.addEventListener('change', (e) => { + selectedDate = e.target.value; + loadDashboardData(); + }); + } + + // 새로고침 버튼 (요소가 있을 때만) + if (elements.refreshBtn) { + elements.refreshBtn.addEventListener('click', () => { + loadDashboardData(); + showToast('데이터를 새로고침했습니다.', 'success'); + }); + } + + // 로그아웃 버튼 (navbar 컴포넌트가 이미 처리하므로 버튼이 있을 때만) + if (elements.logoutBtn) { + elements.logoutBtn.addEventListener('click', () => { + if (confirm('로그아웃하시겠습니까?')) { + localStorage.clear(); + window.location.href = '/index.html'; + } + }); + } + + // 뷰 컨트롤 버튼들 + const listViewBtn = document.getElementById('listViewBtn'); + const cardViewBtn = document.getElementById('cardViewBtn'); + + if (listViewBtn) { + listViewBtn.addEventListener('click', () => { + displayWorkers(workersData, 'list'); + updateViewButtons('list'); + }); + } + + if (cardViewBtn) { + cardViewBtn.addEventListener('click', () => { + displayWorkers(workersData, 'card'); + updateViewButtons('card'); + }); + } +} + +// ========== 데이터 로드 ========== // +async function loadDashboardData() { + console.log('📊 대시보드 데이터 로딩 시작'); + + try { + // 로딩 상태 표시 + showLoadingState(); + + // 병렬로 데이터 로드 + const [workersResult, workResult] = await Promise.all([ + loadWorkers(), + loadWorkData(selectedDate) + ]); + + // 요약 데이터 업데이트 + updateSummaryCards(); + + // 작업 현황 표시 + displayWorkStatus(); + + // 작업자 현황 표시 + displayWorkers(workersData, 'card'); + + console.log('✅ 대시보드 데이터 로딩 완료'); + + } catch (error) { + console.error('❌ 대시보드 데이터 로딩 오류:', error); + showErrorState(); + showToast('데이터를 불러오는 중 오류가 발생했습니다.', 'error'); + } +} + +async function loadWorkers() { + try { + console.log('👥 작업자 데이터 로딩...'); + const response = await window.apiCall('/workers'); + const allWorkers = Array.isArray(response) ? response : (response.data || []); + + // 활성화된 작업자만 필터링 + workersData = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + + console.log(`✅ 작업자 ${workersData.length}명 로드 완료 (전체: ${allWorkers.length}명)`); + return workersData; + } catch (error) { + console.error('작업자 데이터 로딩 오류:', error); + workersData = []; + throw error; + } +} + +async function loadWorkData(date) { + try { + console.log(`📋 ${date} 작업 데이터 로딩...`); + const response = await window.apiCall(`/daily-work-reports?date=${date}&view_all=true`); + workData = Array.isArray(response) ? response : (response.data || []); + console.log(`✅ 작업 데이터 ${workData.length}건 로드 완료`); + return workData; + } catch (error) { + console.error('작업 데이터 로딩 오류:', error); + workData = []; + throw error; + } +} + +// ========== 요약 카드 업데이트 ========== // +function updateSummaryCards() { + // 오늘 작업자 수 + const todayWorkersCount = new Set(workData.map(w => w.worker_id)).size; + updateSummaryCard(elements.todayWorkers, todayWorkersCount, '명'); + + // 총 작업 시간 + const totalHours = workData.reduce((sum, work) => sum + parseFloat(work.work_hours || 0), 0); + updateSummaryCard(elements.totalHours, totalHours.toFixed(1), '시간'); + + // 진행 중인 프로젝트 + const activeProjectsCount = new Set(workData.map(w => w.project_id)).size; + updateSummaryCard(elements.activeProjects, activeProjectsCount, '개'); + + // 오류 발생 건수 + const errorCount = workData.filter(w => w.work_status_id === 2).length; + updateSummaryCard(elements.errorCount, errorCount, '건'); +} + +function updateSummaryCard(element, value, unit) { + if (element) { + const numberElement = element.querySelector('.value-number'); + const unitElement = element.querySelector('.value-unit'); + + if (numberElement) numberElement.textContent = value; + if (unitElement) unitElement.textContent = unit; + } +} + +// ========== SVG 아이콘 정의 ========== // +const SVG_ICONS = { + complete: ` + + `, + + overtime: ` + + + `, + + vacation: ` + + + `, + + partial: ` + + `, + + incomplete: ` + + + + `, + + warning: ` + + + + ` +}; + +// ========== 작업 현황 표시 (작업자 중심) ========== // +function displayWorkStatus() { + const tableBody = document.getElementById('workStatusTableBody'); + if (!tableBody) return; + + // 모든 작업자 데이터 가져오기 (작업이 없는 작업자도 포함) + const allWorkers = workersData || []; + + if (allWorkers.length === 0) { + tableBody.innerHTML = ` + + +

등록된 작업자가 없습니다

+ + + `; + return; + } + + // 작업자별 상황 분석 + const workerStatusList = allWorkers.map(worker => { + const todayWork = workData.filter(w => w.worker_id === worker.worker_id); + const totalHours = todayWork.reduce((sum, w) => sum + parseFloat(w.work_hours || 0), 0); + + // 휴가/연차 제외한 실제 작업시간 계산 + const actualWorkHours = todayWork + .filter(w => w.project_id !== 13) // 연차/휴무 프로젝트 제외 + .reduce((sum, w) => sum + parseFloat(w.work_hours || 0), 0); + + const hasError = todayWork.some(w => w.work_status_id === 2); + + // 정규 작업과 에러 작업 건수 분리 + const regularWorkCount = todayWork.filter(w => w.project_id !== 13 && w.work_status_id !== 2).length; + const errorWorkCount = todayWork.filter(w => w.project_id !== 13 && w.work_status_id === 2).length; + + // 상태 판단 로직 (개선된 버전) + let status = 'incomplete'; + let statusText = '미입력'; + let statusBadge = '미입력'; + let statusClass = 'incomplete'; + let vacationType = null; + + // 휴가 처리된 경우 확인 (프로젝트 ID 13 = "연차/휴무" 또는 설명에 휴가 키워드) + const hasVacationRecord = todayWork.some(w => + w.project_id === 13 || // 연차/휴무 프로젝트 + (w.description && ( + w.description.includes('연차') || + w.description.includes('반차') || + w.description.includes('휴가') + )) + ); + + // 연차/휴무 프로젝트의 시간 계산 + const vacationHours = todayWork + .filter(w => w.project_id === 13) + .reduce((sum, w) => sum + parseFloat(w.work_hours || 0), 0); + + if (totalHours > 12) { + status = 'overtime-warning'; + statusText = '초과근무 확인필요'; + statusBadge = '확인필요'; + statusClass = 'warning'; + } else if (hasVacationRecord && vacationHours > 0) { + // 연차/휴무 시간에 따른 상태 결정 + if (vacationHours === 8) { + status = 'vacation-full'; + statusText = '연차'; + statusBadge = '연차'; + statusClass = 'vacation'; + } else if (vacationHours === 6) { + status = 'vacation-half-half'; + statusText = '조퇴'; + statusBadge = '조퇴'; + statusClass = 'vacation'; + } else if (vacationHours === 4) { + status = 'vacation-half'; + statusText = '반차'; + statusBadge = '반차'; + statusClass = 'vacation'; + } else if (vacationHours === 2) { + status = 'vacation-quarter'; + statusText = '반반차'; + statusBadge = '반반차'; + statusClass = 'vacation'; + } + } else if (totalHours > 8) { + // 8시간 초과 - 연장근로 + status = 'overtime'; + statusText = '연장근로'; + statusBadge = '연장근로'; + statusClass = 'overtime'; + } else if (totalHours === 8) { + // 정확히 8시간 - 정시근로 + status = 'complete'; + statusText = '정시근로'; + statusBadge = '정시근로'; + statusClass = 'success'; + } else if (totalHours > 0) { + // 0시간 초과 8시간 미만 - 부분 입력 + status = 'partial'; + statusText = '부분 입력'; + statusBadge = '부분입력'; + statusClass = 'info'; + + // 휴가 처리 필요 여부 판단 + if (totalHours === 0) { + vacationType = 'full'; + } else if (totalHours === 4) { + vacationType = 'half'; + } else if (totalHours === 6) { + vacationType = 'half-half'; // 2시간 더 추가해서 조퇴 처리 + } + } else { + // 0시간 - 미입력 + status = 'incomplete'; + statusText = '미입력'; + statusBadge = '미입력'; + statusClass = 'incomplete'; + vacationType = 'full'; + } + + return { + ...worker, + todayWork, + totalHours, + actualWorkHours, + regularWorkCount, + errorWorkCount, + hasError, + status, + statusText, + statusBadge, + statusClass, + vacationType + }; + }); + + // 테이블 행 렌더링 + tableBody.innerHTML = workerStatusList.map(worker => { + // 상태에 따른 SVG 아이콘 선택 + let iconKey = 'incomplete'; + if (worker.status === 'overtime-warning') iconKey = 'warning'; + else if (worker.status.startsWith('vacation')) iconKey = 'vacation'; + else if (worker.status === 'overtime') iconKey = 'overtime'; + else if (worker.status === 'complete') iconKey = 'complete'; + else if (worker.status === 'partial') iconKey = 'partial'; + + return ` + + +
+ ${worker.worker_name.charAt(0)} +
+
+
${worker.worker_name}
+
${worker.job_type || '작업자'}
+
+ + + + + ${SVG_ICONS[iconKey]} + ${worker.statusBadge} + + + + + ${worker.actualWorkHours.toFixed(1)}h + + + +
+ + 정규: + ${worker.regularWorkCount}건 + + ${worker.errorWorkCount > 0 ? ` + + 에러: + ${worker.errorWorkCount}건 + + ` : ''} +
+ + + +
+ + ${worker.vacationType ? ` + + ` : ''} + ${worker.status === 'overtime-warning' ? ` + + ` : ''} +
+ + + `; + }).join(''); +} + +function groupWorkDataByProject() { + const groups = {}; + workData.forEach(work => { + const projectName = work.project_name || '미지정 프로젝트'; + if (!groups[projectName]) { + groups[projectName] = []; + } + groups[projectName].push(work); + }); + return groups; +} + +// ========== 작업자 현황 표시 ========== // +function displayWorkers(workers, viewType = 'card') { + if (!elements.workersContainer) return; + + if (workers.length === 0) { + elements.workersContainer.innerHTML = ` +
+
👥
+

작업자 데이터가 없습니다

+

등록된 작업자가 없습니다.

+
+ `; + return; + } + + if (viewType === 'list') { + displayWorkersAsList(workers); + } else { + displayWorkersAsCards(workers); + } +} + +function displayWorkersAsCards(workers) { + elements.workersContainer.innerHTML = ` +
+ ${workers.map(worker => { + const todayWork = workData.filter(w => w.worker_id === worker.worker_id); + const totalHours = todayWork.reduce((sum, w) => sum + parseFloat(w.work_hours || 0), 0); + + // 휴가/연차 제외한 실제 작업시간 계산 + const actualWorkHours = todayWork + .filter(w => w.project_id !== 13) // 연차/휴무 프로젝트 제외 + .reduce((sum, w) => sum + parseFloat(w.work_hours || 0), 0); + + const hasError = todayWork.some(w => w.work_status_id === 2); + + // 정규 작업과 에러 작업 건수 분리 + const regularWorkCount = todayWork.filter(w => w.project_id !== 13 && w.work_status_id !== 2).length; + const errorWorkCount = todayWork.filter(w => w.project_id !== 13 && w.work_status_id === 2).length; + + return ` +
+
+
+
+ ${worker.worker_name.charAt(0)} +
+
+

${worker.worker_name}

+

${worker.job_type || '작업자'}

+
+
+ +
+
+
+
+ 작업시간 + ${actualWorkHours.toFixed(1)}h +
+
+ 정규 + ${regularWorkCount}건 +
+ ${errorWorkCount > 0 ? ` +
+ 에러 + ${errorWorkCount}건 +
+ ` : ''} +
+
+
+ `; + }).join('')} +
+ `; +} + +function displayWorkersAsList(workers) { + elements.workersContainer.innerHTML = ` +
+ + + + + + + + + + + + ${workers.map(worker => { + const todayWork = workData.filter(w => w.worker_id === worker.worker_id); + const totalHours = todayWork.reduce((sum, w) => sum + parseFloat(w.work_hours || 0), 0); + const hasError = todayWork.some(w => w.work_status_id === 2); + + return ` + + + + + + + + `; + }).join('')} + +
작업자직종오늘 작업작업 시간상태
+
+
+ ${worker.worker_name.charAt(0)} +
+ ${worker.worker_name} +
+
${worker.job_type || '작업자'}${todayWork.length}건${totalHours.toFixed(1)}시간 + + ${todayWork.length > 0 ? '작업 중' : '대기'} + + ${hasError ? '오류' : ''} +
+
+ `; +} + +// ========== 뷰 버튼 업데이트 ========== // +function updateViewButtons(activeView) { + const listBtn = document.getElementById('listViewBtn'); + const cardBtn = document.getElementById('cardViewBtn'); + + if (listBtn && cardBtn) { + listBtn.classList.toggle('btn-primary', activeView === 'list'); + listBtn.classList.toggle('btn-secondary', activeView !== 'list'); + + cardBtn.classList.toggle('btn-primary', activeView === 'card'); + cardBtn.classList.toggle('btn-secondary', activeView !== 'card'); + } +} + +// ========== 관리자 권한 확인 ========== // +function checkAdminAccess() { + const adminElements = document.querySelectorAll('.admin-only'); + const isFullAdmin = currentUser && ['admin', 'system'].includes(currentUser.access_level); + const isGroupLeader = currentUser && currentUser.access_level === 'group_leader'; + + console.log(`🔐 권한 확인: 사용자=${currentUser?.username}, 역할=${currentUser.access_level}, 전체관리자=${isFullAdmin}, 그룹리더=${isGroupLeader}`); + + adminElements.forEach(element => { + const href = element.getAttribute('href'); + + // 작업 분석: 전체 관리자만 접근 가능 + if (href && href.includes('work-analysis.html')) { + if (isFullAdmin) { + element.style.display = ''; + element.classList.add('visible'); + } else { + element.style.display = 'none'; + element.classList.remove('visible'); + } + } + // 작업 관리: 전체 관리자 + 그룹 리더 접근 가능 + else if (href && href.includes('work-management.html')) { + if (isFullAdmin || isGroupLeader) { + element.style.display = ''; + element.classList.add('visible'); + } else { + element.style.display = 'none'; + element.classList.remove('visible'); + } + } + // 기타 관리자 전용 메뉴: 전체 관리자만 접근 가능 + else { + if (isFullAdmin) { + element.style.display = ''; + element.classList.add('visible'); + } else { + element.style.display = 'none'; + element.classList.remove('visible'); + } + } + }); +} + +// ========== TBM 페이지 접근 권한 확인 ========== // +async function checkTbmPageAccess() { + try { + if (!currentUser || !currentUser.user_id) { + console.log('⚠️ TBM 페이지 권한 확인: 사용자 정보 없음'); + return; + } + + const tbmQuickAction = document.getElementById('tbmQuickAction'); + if (!tbmQuickAction) { + console.log('⚠️ TBM 빠른 작업 버튼 요소를 찾을 수 없습니다'); + return; + } + + console.log('🛠️ TBM 페이지 권한 확인 중...', { role: currentUser.role, access_level: currentUser.access_level }); + + // Admin은 모든 페이지 접근 가능 + if (currentUser.role === 'Admin' || currentUser.role === 'System Admin' || currentUser.access_level === 'admin' || currentUser.access_level === 'system') { + tbmQuickAction.style.display = 'block'; + console.log('✅ Admin 사용자 - TBM 빠른 작업 버튼 표시'); + return; + } + + // 일반 사용자는 페이지 접근 권한 조회 + const response = await window.apiCall(`/users/${currentUser.user_id}/page-access`); + + if (response && response.success) { + const pageAccess = response.data?.pageAccess || []; + + // 'work.tbm' 페이지 접근 권한 확인 (마이그레이션에서 work.tbm으로 등록함) + const tbmPage = pageAccess.find(p => p.page_key === 'work.tbm'); + + if (tbmPage && tbmPage.can_access) { + tbmQuickAction.style.display = 'block'; + console.log('✅ TBM 페이지 접근 권한 있음 - 빠른 작업 버튼 표시'); + } else { + console.log('❌ TBM 페이지 접근 권한 없음 - 빠른 작업 버튼 숨김'); + } + } else { + console.log('⚠️ TBM 페이지 권한 확인 실패'); + } + } catch (error) { + console.error('❌ TBM 페이지 권한 확인 오류:', error); + } +} + +// ========== 상태 표시 ========== // +function showLoadingState() { + const loadingHTML = ` +
+
+

데이터를 불러오는 중...

+
+ `; + + if (elements.workStatusContainer) { + elements.workStatusContainer.innerHTML = loadingHTML; + } + + if (elements.workersContainer) { + elements.workersContainer.innerHTML = loadingHTML; + } +} + +function showErrorState() { + const errorHTML = ` +
+
⚠️
+

데이터를 불러올 수 없습니다

+

네트워크 연결을 확인하고 다시 시도해주세요.

+ +
+ `; + + if (elements.workStatusContainer) { + elements.workStatusContainer.innerHTML = errorHTML; + } + + if (elements.workersContainer) { + elements.workersContainer.innerHTML = errorHTML; + } +} + +// ========== 토스트 알림 ========== // +function showToast(message, type = 'info', duration = 3000) { + if (!elements.toastContainer) return; + + const toast = document.createElement('div'); + toast.className = `toast ${type}`; + + const iconMap = { + success: '✅', + error: '❌', + warning: '⚠️', + info: 'ℹ️' + }; + + toast.innerHTML = ` +
${iconMap[type] || 'ℹ️'}
+
${message}
+ + `; + + elements.toastContainer.appendChild(toast); + + // 자동 제거 + setTimeout(() => { + if (toast.parentElement) { + toast.remove(); + } + }, duration); +} + +// ========== 작업자 관련 액션 함수들 ========== // +function openWorkerModal(workerId, workerName) { + console.log(`📝 ${workerName}(ID: ${workerId}) 작업 보고서 모달 열기`); + + // 모달 데이터 설정 + currentModalWorker = { + id: workerId, + name: workerName, + date: selectedDate + }; + + // 모달 표시 + showWorkerModal(); +} + +function handleVacation(workerId, vacationType) { + console.log(`🏖️ 작업자 ${workerId} 휴가 처리: ${vacationType}`); + + const vacationNames = { + 'full': '연차', + 'half': '반차', + 'half-half': '반반차' + }; + + const vacationHours = { + 'full': 8, + 'half': 4, + 'half-half': 2 + }; + + if (confirm(`${vacationNames[vacationType]} 처리하시겠습니까?\n(${vacationHours[vacationType]}시간으로 자동 입력됩니다)`)) { + // 휴가 처리 API 호출 + processVacation(workerId, vacationType, vacationHours[vacationType]); + } +} + +async function processVacation(workerId, vacationType, hours) { + try { + showToast(`휴가 처리 중...`, 'info'); + + // 휴가용 작업 보고서 생성 (특별한 작업 유형으로) + const vacationReport = { + report_date: selectedDate, + worker_id: workerId, + project_id: 1, // 기본 프로젝트 (휴가용) + work_type_id: 999, // 휴가 전용 작업 유형 (DB에 추가 필요) + work_status_id: 1, // 정상 상태 + error_type_id: null, + work_hours: hours, + created_by: currentUser?.user_id || 1 + }; + + const response = await window.apiCall('/daily-work-reports', 'POST', vacationReport); + + showToast(`휴가 처리가 완료되었습니다.`, 'success'); + await loadDashboardData(); // 데이터 새로고침 + + } catch (error) { + console.error('휴가 처리 오류:', error); + showToast(`휴가 처리 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +function confirmOvertime(workerId) { + console.log(`⚠️ 작업자 ${workerId} 초과근무 확인`); + + if (confirm('12시간을 초과한 작업시간이 정상적인 입력인지 확인하시겠습니까?')) { + // 초과근무 확인 처리 + processOvertimeConfirmation(workerId); + } +} + +async function processOvertimeConfirmation(workerId) { + try { + showToast('초과근무 승인 처리 중...', 'info'); + + // 새로운 근태 관리 API 사용 + const overtimeData = { + worker_id: workerId, + date: selectedDate + }; + + const response = await window.apiCall('/attendance/overtime/approve', 'POST', overtimeData); + + if (response.success) { + showToast('초과근무가 정상으로 승인되었습니다.', 'success'); + await loadDashboardData(); // 데이터 새로고침 + } else { + throw new Error(response.message || '초과근무 승인에 실패했습니다.'); + } + + } catch (error) { + console.error('초과근무 승인 오류:', error); + showToast(`초과근무 승인 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +// ========== 모달 시스템 ========== // +function showWorkerModal() { + // 모달이 없으면 생성 + if (!document.getElementById('workerModal')) { + createWorkerModal(); + } + + // 모달 데이터 로드 및 표시 + loadModalData(); + document.getElementById('workerModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; // 배경 스크롤 방지 +} + +function hideWorkerModal() { + document.getElementById('workerModal').style.display = 'none'; + document.body.style.overflow = 'auto'; // 배경 스크롤 복원 + resetModalForm(); +} + +function createWorkerModal() { + const modalHTML = ` + + `; + + document.body.insertAdjacentHTML('beforeend', modalHTML); + setupModalEventListeners(); +} + +function setupModalEventListeners() { + // 모달 외부 클릭 시 닫기 + document.getElementById('workerModal').addEventListener('click', (e) => { + if (e.target.id === 'workerModal') { + hideWorkerModal(); + } + }); + + // 새 작업 추가/취소 버튼 + document.getElementById('modalAddWorkBtn').addEventListener('click', showModalNewWorkForm); + document.getElementById('modalCancelWorkBtn').addEventListener('click', hideModalNewWorkForm); + document.getElementById('modalSaveWorkBtn').addEventListener('click', saveModalNewWork); + + // 업무 상태 변경 시 에러 유형 토글 + document.getElementById('modalWorkStatusSelect').addEventListener('change', toggleModalErrorType); + + // 빠른 시간 버튼 + document.querySelectorAll('.modal-time-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + document.getElementById('modalWorkHours').value = e.target.dataset.hours; + }); + }); + + // 휴가 처리 버튼 + document.querySelectorAll('.modal-vacation-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + const vacationType = e.target.dataset.type; + handleModalVacation(vacationType); + }); + }); +} + +async function loadModalData() { + if (!currentModalWorker) return; + + try { + // 모달 헤더 업데이트 + document.getElementById('modalTitle').textContent = `${currentModalWorker.name} 작업 보고서`; + document.getElementById('modalWorkerName').textContent = currentModalWorker.name; + document.getElementById('modalWorkerDate').textContent = currentModalWorker.date; + document.getElementById('modalWorkerInitial').textContent = currentModalWorker.name.charAt(0); + + // 병렬로 데이터 로드 + await Promise.all([ + loadModalExistingWork(), + loadModalDropdownData() + ]); + + // UI 업데이트 + updateModalSummary(); + renderModalExistingWork(); + populateModalDropdowns(); + + } catch (error) { + console.error('모달 데이터 로드 오류:', error); + showToast('데이터 로드 중 오류가 발생했습니다.', 'error'); + } +} + +async function loadModalExistingWork() { + try { + const response = await window.apiCall(`/daily-work-reports?date=${currentModalWorker.date}&worker_id=${currentModalWorker.id}`); + modalExistingWork = Array.isArray(response) ? response : (response.data || []); + } catch (error) { + console.error('기존 작업 로드 오류:', error); + modalExistingWork = []; + } +} + +async function loadModalDropdownData() { + try { + const [projectsRes, workTypesRes, workStatusRes, errorTypesRes] = await Promise.all([ + window.apiCall('/projects/active/list'), + window.apiCall('/daily-work-reports/work-types'), + window.apiCall('/daily-work-reports/work-status-types'), + window.apiCall('/daily-work-reports/error-types') + ]); + + modalProjects = Array.isArray(projectsRes) ? projectsRes : (projectsRes.data || []); + modalWorkTypes = Array.isArray(workTypesRes) ? workTypesRes : (workTypesRes.data || []); + modalWorkStatusTypes = Array.isArray(workStatusRes) ? workStatusRes : (workStatusRes.data || []); + modalErrorTypes = Array.isArray(errorTypesRes) ? errorTypesRes : (errorTypesRes.data || []); + } catch (error) { + console.error('드롭다운 데이터 로드 오류:', error); + } +} + +function updateModalSummary() { + const totalHours = modalExistingWork.reduce((sum, work) => sum + parseFloat(work.work_hours || 0), 0); + const workCount = modalExistingWork.length; + + document.getElementById('modalTotalHours').textContent = `${totalHours.toFixed(1)}h`; + document.getElementById('modalWorkCount').textContent = `${workCount}건`; + + // 12시간 초과 경고 + if (totalHours > 12) { + document.getElementById('modalTotalHours').classList.add('warning'); + } else { + document.getElementById('modalTotalHours').classList.remove('warning'); + } +} + +function renderModalExistingWork() { + const container = document.getElementById('modalExistingWork'); + + if (modalExistingWork.length === 0) { + container.innerHTML = ` + + `; + return; + } + + container.innerHTML = modalExistingWork.map(work => ` + + `).join(''); +} + +function populateModalDropdowns() { + // 프로젝트 드롭다운 + const projectSelect = document.getElementById('modalProjectSelect'); + projectSelect.innerHTML = ''; + modalProjects.forEach(project => { + projectSelect.innerHTML += ``; + }); + + // 작업 유형 드롭다운 + const workTypeSelect = document.getElementById('modalWorkTypeSelect'); + workTypeSelect.innerHTML = ''; + modalWorkTypes.forEach(type => { + workTypeSelect.innerHTML += ``; + }); + + // 작업 상태 드롭다운 + const workStatusSelect = document.getElementById('modalWorkStatusSelect'); + workStatusSelect.innerHTML = ''; + modalWorkStatusTypes.forEach(status => { + workStatusSelect.innerHTML += ``; + }); + + // 에러 유형 드롭다운 + const errorTypeSelect = document.getElementById('modalErrorTypeSelect'); + errorTypeSelect.innerHTML = ''; + modalErrorTypes.forEach(error => { + errorTypeSelect.innerHTML += ``; + }); +} + +function showModalNewWorkForm() { + document.getElementById('modalNewWorkSection').style.display = 'block'; + document.getElementById('modalAddWorkBtn').style.display = 'none'; +} + +function hideModalNewWorkForm() { + document.getElementById('modalNewWorkSection').style.display = 'none'; + document.getElementById('modalAddWorkBtn').style.display = 'block'; + resetModalForm(); +} + +function resetModalForm() { + document.getElementById('modalProjectSelect').value = ''; + document.getElementById('modalWorkTypeSelect').value = ''; + document.getElementById('modalWorkStatusSelect').value = ''; + document.getElementById('modalErrorTypeSelect').value = ''; + document.getElementById('modalWorkHours').value = '1.00'; + document.getElementById('modalErrorTypeGroup').style.display = 'none'; +} + +function toggleModalErrorType() { + const workStatusSelect = document.getElementById('modalWorkStatusSelect'); + const errorTypeGroup = document.getElementById('modalErrorTypeGroup'); + + if (workStatusSelect.value === '2') { // 에러 상태 + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + document.getElementById('modalErrorTypeSelect').value = ''; + } +} + +async function saveModalNewWork() { + try { + const projectId = document.getElementById('modalProjectSelect').value; + const workTypeId = document.getElementById('modalWorkTypeSelect').value; + const workStatusId = document.getElementById('modalWorkStatusSelect').value; + const errorTypeId = document.getElementById('modalErrorTypeSelect').value; + const workHours = document.getElementById('modalWorkHours').value; + + // 유효성 검사 + if (!projectId || !workTypeId || !workStatusId || !workHours) { + showToast('모든 필수 필드를 입력해주세요.', 'error'); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showToast('에러 상태일 때는 에러 유형을 선택해야 합니다.', 'error'); + return; + } + + const workData = { + report_date: currentModalWorker.date, + worker_id: currentModalWorker.id, + work_entries: [{ + project_id: parseInt(projectId), + task_id: parseInt(workTypeId), // work_type_id를 task_id로 매핑 + work_hours: parseFloat(workHours), + work_status_id: parseInt(workStatusId), + error_type_id: workStatusId === '2' ? parseInt(errorTypeId) : null, + description: '' // 기본 설명 + }] + }; + + console.log('📤 전송할 작업 데이터:', workData); + console.log('📋 현재 사용자:', currentUser); + + await window.apiCall('/daily-work-reports', 'POST', workData); + + showToast('작업이 성공적으로 저장되었습니다.', 'success'); + + // 데이터 새로고침 + await loadModalExistingWork(); + updateModalSummary(); + renderModalExistingWork(); + hideModalNewWorkForm(); + + // 대시보드 데이터도 새로고침 + await loadDashboardData(); + + } catch (error) { + console.error('작업 저장 오류:', error); + showToast(`작업 저장 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +async function deleteModalWork(workId) { + if (!confirm('이 작업을 삭제하시겠습니까?')) { + return; + } + + try { + await window.apiCall(`/daily-work-reports/${workId}`, 'DELETE'); + + showToast('작업이 성공적으로 삭제되었습니다.', 'success'); + + // 데이터 새로고침 + await loadModalExistingWork(); + updateModalSummary(); + renderModalExistingWork(); + + // 대시보드 데이터도 새로고침 + await loadDashboardData(); + + } catch (error) { + console.error('작업 삭제 오류:', error); + showToast(`작업 삭제 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +async function handleModalVacation(vacationType) { + const vacationTypeMap = { + 'full': { code: 'ANNUAL_FULL', name: '연차', hours: 8 }, + 'half': { code: 'ANNUAL_HALF', name: '반차', hours: 4 }, + 'half-half': { code: 'ANNUAL_QUARTER', name: '반반차', hours: 2 } + }; + + const vacation = vacationTypeMap[vacationType]; + if (!vacation) return; + + if (!confirm(`${vacation.name} 처리하시겠습니까?\n(${vacation.hours}시간으로 자동 입력됩니다)`)) { + return; + } + + try { + // 새로운 근태 관리 API 사용 + const vacationData = { + worker_id: currentModalWorker.id, + date: currentModalWorker.date, + vacation_type: vacation.code + }; + + const response = await window.apiCall('/attendance/vacation', 'POST', vacationData); + + if (response.success) { + showToast(`${vacation.name} 처리가 완료되었습니다.`, 'success'); + + // 데이터 새로고침 + await loadModalExistingWork(); + updateModalSummary(); + renderModalExistingWork(); + + // 대시보드 데이터도 새로고침 + await loadDashboardData(); + } else { + throw new Error(response.message || '휴가 처리에 실패했습니다.'); + } + + } catch (error) { + console.error('휴가 처리 오류:', error); + showToast(`휴가 처리 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +// ========== 전역 함수 (HTML에서 호출) ========== // +window.loadDashboardData = loadDashboardData; +window.showToast = showToast; +window.updateSummaryCards = updateSummaryCards; +window.displayWorkers = displayWorkers; +window.openWorkerModal = openWorkerModal; +window.hideWorkerModal = hideWorkerModal; +window.deleteModalWork = deleteModalWork; +window.handleVacation = handleVacation; +window.confirmOvertime = confirmOvertime; diff --git a/deploy/tkfb-package/web-ui/js/my-attendance.js b/deploy/tkfb-package/web-ui/js/my-attendance.js new file mode 100644 index 0000000..efe5825 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/my-attendance.js @@ -0,0 +1,390 @@ +/** + * 나의 출근 현황 페이지 + * 본인의 출근 기록과 근태 현황을 조회하고 표시합니다 + */ + +// 전역 상태 +let currentYear = new Date().getFullYear(); +let currentMonth = new Date().getMonth() + 1; +let attendanceData = []; +let vacationBalance = null; +let monthlyStats = null; + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', () => { + initializePage(); +}); + +/** + * 페이지 초기화 + */ +function initializePage() { + initializeYearMonthSelects(); + setupEventListeners(); + loadAttendanceData(); +} + +/** + * 년도/월 선택 옵션 초기화 + */ +function initializeYearMonthSelects() { + const yearSelect = document.getElementById('yearSelect'); + const monthSelect = document.getElementById('monthSelect'); + + // 년도 옵션 (현재 년도 기준 ±2년) + const currentYearValue = new Date().getFullYear(); + for (let year = currentYearValue - 2; year <= currentYearValue + 2; year++) { + const option = document.createElement('option'); + option.value = year; + option.textContent = `${year}년`; + if (year === currentYear) option.selected = true; + yearSelect.appendChild(option); + } + + // 월 옵션 + for (let month = 1; month <= 12; month++) { + const option = document.createElement('option'); + option.value = month; + option.textContent = `${month}월`; + if (month === currentMonth) option.selected = true; + monthSelect.appendChild(option); + } +} + +/** + * 이벤트 리스너 설정 + */ +function setupEventListeners() { + // 조회 버튼 + document.getElementById('loadAttendance').addEventListener('click', () => { + currentYear = parseInt(document.getElementById('yearSelect').value); + currentMonth = parseInt(document.getElementById('monthSelect').value); + loadAttendanceData(); + }); + + // 탭 전환 + document.querySelectorAll('.tab-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + const tabName = e.currentTarget.dataset.tab; + switchTab(tabName); + }); + }); + + // 달력 네비게이션 + document.getElementById('prevMonth').addEventListener('click', () => { + changeMonth(-1); + }); + + document.getElementById('nextMonth').addEventListener('click', () => { + changeMonth(1); + }); +} + +/** + * 출근 데이터 로드 + */ +async function loadAttendanceData() { + try { + showLoading(); + + // 병렬로 데이터 로드 + const [attendanceRes, vacationRes, statsRes] = await Promise.all([ + window.apiGet(`/users/me/attendance-records?year=${currentYear}&month=${currentMonth}`), + window.apiGet(`/users/me/vacation-balance?year=${currentYear}`), + window.apiGet(`/users/me/monthly-stats?year=${currentYear}&month=${currentMonth}`) + ]); + + attendanceData = attendanceRes.data || attendanceRes || []; + vacationBalance = vacationRes.data || vacationRes; + monthlyStats = statsRes.data || statsRes; + + // UI 업데이트 + updateStats(); + renderTable(); + renderCalendar(); + + } catch (error) { + console.error('출근 데이터 로드 실패:', error); + showError('출근 데이터를 불러오는데 실패했습니다.'); + } +} + +/** + * 통계 업데이트 + */ +function updateStats() { + // 총 근무시간 (API는 month_hours 반환) + const totalHours = monthlyStats?.month_hours || monthlyStats?.total_work_hours || 0; + document.getElementById('totalHours').textContent = `${totalHours}시간`; + + // 근무일수 + const totalDays = monthlyStats?.work_days || 0; + document.getElementById('totalDays').textContent = `${totalDays}일`; + + // 잔여 연차 + const remaining = vacationBalance?.remaining_annual_leave || + (vacationBalance?.total_annual_leave || 0) - (vacationBalance?.used_annual_leave || 0); + document.getElementById('remainingLeave').textContent = `${remaining}일`; +} + +/** + * 테이블 렌더링 + */ +function renderTable() { + const tbody = document.getElementById('attendanceTableBody'); + tbody.innerHTML = ''; + + if (!attendanceData || attendanceData.length === 0) { + tbody.innerHTML = '출근 기록이 없습니다.'; + return; + } + + attendanceData.forEach(record => { + const tr = document.createElement('tr'); + tr.className = `attendance-row ${getStatusClass(record.attendance_type_code || record.type_code)}`; + tr.onclick = () => showDetailModal(record); + + const date = new Date(record.record_date); + const dayOfWeek = ['일', '월', '화', '수', '목', '금', '토'][date.getDay()]; + + tr.innerHTML = ` + ${formatDate(record.record_date)} + ${dayOfWeek} + ${record.check_in_time || '-'} + ${record.check_out_time || '-'} + ${record.total_work_hours ? `${record.total_work_hours}h` : '-'} + ${getStatusText(record)} + ${record.notes || '-'} + `; + + tbody.appendChild(tr); + }); +} + +/** + * 달력 렌더링 + */ +function renderCalendar() { + const calendarTitle = document.getElementById('calendarTitle'); + const calendarGrid = document.getElementById('calendarGrid'); + + calendarTitle.textContent = `${currentYear}년 ${currentMonth}월`; + + // 달력 그리드 초기화 + calendarGrid.innerHTML = ''; + + // 요일 헤더 + const weekdays = ['일', '월', '화', '수', '목', '금', '토']; + weekdays.forEach(day => { + const dayHeader = document.createElement('div'); + dayHeader.className = 'calendar-day-header'; + dayHeader.textContent = day; + calendarGrid.appendChild(dayHeader); + }); + + // 해당 월의 첫날과 마지막 날 + const firstDay = new Date(currentYear, currentMonth - 1, 1); + const lastDay = new Date(currentYear, currentMonth, 0); + const daysInMonth = lastDay.getDate(); + const startDayOfWeek = firstDay.getDay(); + + // 출근 데이터를 날짜별로 매핑 + const attendanceMap = {}; + if (attendanceData) { + attendanceData.forEach(record => { + const date = new Date(record.record_date); + const day = date.getDate(); + attendanceMap[day] = record; + }); + } + + // 빈 칸 (이전 달) + for (let i = 0; i < startDayOfWeek; i++) { + const emptyCell = document.createElement('div'); + emptyCell.className = 'calendar-day empty'; + calendarGrid.appendChild(emptyCell); + } + + // 날짜 칸 + for (let day = 1; day <= daysInMonth; day++) { + const dayCell = document.createElement('div'); + dayCell.className = 'calendar-day'; + + const record = attendanceMap[day]; + if (record) { + dayCell.classList.add('has-record', getStatusClass(record.attendance_type_code || record.type_code)); + dayCell.onclick = () => showDetailModal(record); + } + + dayCell.innerHTML = ` +
${day}
+ ${record ? `
${getStatusIcon(record)}
` : ''} + `; + + calendarGrid.appendChild(dayCell); + } +} + +/** + * 탭 전환 + */ +function switchTab(tabName) { + // 탭 버튼 활성화 토글 + document.querySelectorAll('.tab-btn').forEach(btn => { + btn.classList.toggle('active', btn.dataset.tab === tabName); + }); + + // 탭 컨텐츠 토글 + document.querySelectorAll('.tab-content').forEach(content => { + content.classList.remove('active'); + }); + + if (tabName === 'list') { + document.getElementById('listView').classList.add('active'); + } else if (tabName === 'calendar') { + document.getElementById('calendarView').classList.add('active'); + } +} + +/** + * 월 변경 + */ +function changeMonth(offset) { + currentMonth += offset; + + if (currentMonth < 1) { + currentMonth = 12; + currentYear--; + } else if (currentMonth > 12) { + currentMonth = 1; + currentYear++; + } + + // Select 박스 업데이트 + document.getElementById('yearSelect').value = currentYear; + document.getElementById('monthSelect').value = currentMonth; + + loadAttendanceData(); +} + +/** + * 상세 모달 표시 + */ +function showDetailModal(record) { + const modal = document.getElementById('detailModal'); + const modalBody = document.getElementById('modalBody'); + const modalTitle = document.getElementById('modalTitle'); + + const date = new Date(record.record_date); + modalTitle.textContent = `${formatDate(record.record_date)} 출근 상세`; + + modalBody.innerHTML = ` +
+
+ +
${formatDate(record.record_date)}
+
+
+ +
${getStatusText(record)}
+
+
+ +
${record.check_in_time || '기록 없음'}
+
+
+ +
${record.check_out_time || '기록 없음'}
+
+
+ +
${record.total_work_hours ? `${record.total_work_hours} 시간` : '계산 불가'}
+
+ ${record.vacation_type_name ? ` +
+ +
${record.vacation_type_name}
+
+ ` : ''} + ${record.notes ? ` +
+ +
${record.notes}
+
+ ` : ''} +
+ `; + + modal.style.display = 'block'; +} + +/** + * 모달 닫기 + */ +function closeDetailModal() { + document.getElementById('detailModal').style.display = 'none'; +} + +// 모달 외부 클릭 시 닫기 +window.onclick = function(event) { + const modal = document.getElementById('detailModal'); + if (event.target === modal) { + closeDetailModal(); + } +}; + +/** + * 유틸리티 함수들 + */ + +function formatDate(dateString) { + const date = new Date(dateString); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${month}/${day}`; +} + +function getStatusClass(typeCode) { + const typeMap = { + 'NORMAL': 'normal', + 'LATE': 'late', + 'EARLY_LEAVE': 'early', + 'ABSENT': 'absent', + 'VACATION': 'vacation' + }; + return typeMap[typeCode] || 'normal'; +} + +function getStatusText(record) { + if (record.vacation_type_name) { + return record.vacation_type_name; + } + return record.attendance_type_name || record.type_name || '정상'; +} + +function getStatusIcon(record) { + const typeCode = record.attendance_type_code || record.type_code; + const iconMap = { + 'NORMAL': '✓', + 'LATE': '⚠', + 'EARLY_LEAVE': '⏰', + 'ABSENT': '✗', + 'VACATION': '🌴' + }; + return iconMap[typeCode] || '✓'; +} + +function showLoading() { + const tbody = document.getElementById('attendanceTableBody'); + tbody.innerHTML = '데이터를 불러오는 중...'; +} + +function showError(message) { + const tbody = document.getElementById('attendanceTableBody'); + tbody.innerHTML = `${message}`; + + // 통계 초기화 + document.getElementById('totalHours').textContent = '-'; + document.getElementById('totalDays').textContent = '-'; + document.getElementById('remainingLeave').textContent = '-'; +} diff --git a/deploy/tkfb-package/web-ui/js/my-dashboard.js b/deploy/tkfb-package/web-ui/js/my-dashboard.js new file mode 100644 index 0000000..c61a5f5 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/my-dashboard.js @@ -0,0 +1,189 @@ +// My Dashboard - 나의 대시보드 JavaScript + +import './api-config.js'; + +// 전역 변수 +let currentYear = new Date().getFullYear(); +let currentMonth = new Date().getMonth() + 1; + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', async () => { + console.log('📊 나의 대시보드 초기화 시작'); + + await loadUserInfo(); + await loadVacationBalance(); + await loadMonthlyCalendar(); + await loadWorkHoursStats(); + await loadRecentReports(); + + console.log('✅ 나의 대시보드 초기화 완료'); +}); + +// 사용자 정보 로드 +async function loadUserInfo() { + try { + const response = await apiCall('/users/me', 'GET'); + const user = response.data || response; + + document.getElementById('userName').textContent = user.name || '사용자'; + document.getElementById('department').textContent = user.department || '-'; + document.getElementById('jobType').textContent = user.job_type || '-'; + document.getElementById('hireDate').textContent = user.hire_date || '-'; + } catch (error) { + console.error('사용자 정보 로드 실패:', error); + } +} + +// 연차 정보 로드 +async function loadVacationBalance() { + try { + const response = await apiCall('/users/me/vacation-balance', 'GET'); + const balance = response.data || response; + + const total = balance.total_annual_leave || 15; + const used = balance.used_annual_leave || 0; + const remaining = total - used; + + document.getElementById('totalLeave').textContent = total; + document.getElementById('usedLeave').textContent = used; + document.getElementById('remainingLeave').textContent = remaining; + + // 프로그레스 바 업데이트 + const percentage = (used / total) * 100; + document.getElementById('vacationProgress').style.width = `${percentage}%`; + } catch (error) { + console.error('연차 정보 로드 실패:', error); + } +} + +// 월별 캘린더 로드 +async function loadMonthlyCalendar() { + try { + const response = await apiCall( + `/users/me/attendance-records?year=${currentYear}&month=${currentMonth}`, + 'GET' + ); + const records = response.data || response; + + renderCalendar(currentYear, currentMonth, records); + document.getElementById('currentMonth').textContent = `${currentYear}년 ${currentMonth}월`; + } catch (error) { + console.error('캘린더 로드 실패:', error); + renderCalendar(currentYear, currentMonth, []); + } +} + +// 캘린더 렌더링 +function renderCalendar(year, month, records) { + const calendar = document.getElementById('calendar'); + const firstDay = new Date(year, month - 1, 1).getDay(); + const daysInMonth = new Date(year, month, 0).getDate(); + + let html = ''; + + // 요일 헤더 + const weekdays = ['일', '월', '화', '수', '목', '금', '토']; + weekdays.forEach(day => { + html += `
${day}
`; + }); + + // 빈 칸 + for (let i = 0; i < firstDay; i++) { + html += '
'; + } + + // 날짜 + for (let day = 1; day <= daysInMonth; day++) { + const dateStr = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`; + const record = Array.isArray(records) ? records.find(r => r.record_date === dateStr) : null; + + let statusClass = ''; + if (record) { + const typeCode = record.attendance_type_code || record.type_code || ''; + statusClass = typeCode.toLowerCase(); + } + + html += ` +
+ ${day} +
+ `; + } + + calendar.innerHTML = html; +} + +// 근무 시간 통계 로드 +async function loadWorkHoursStats() { + try { + const response = await apiCall( + `/users/me/monthly-stats?year=${currentYear}&month=${currentMonth}`, + 'GET' + ); + const stats = response.data || response; + + document.getElementById('monthHours').textContent = stats.month_hours || 0; + document.getElementById('workDays').textContent = stats.work_days || 0; + } catch (error) { + console.error('근무 시간 통계 로드 실패:', error); + } +} + +// 최근 작업 보고서 로드 +async function loadRecentReports() { + try { + const endDate = new Date().toISOString().split('T')[0]; + const startDate = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) + .toISOString().split('T')[0]; + + const response = await apiCall( + `/users/me/work-reports?startDate=${startDate}&endDate=${endDate}`, + 'GET' + ); + const reports = response.data || response; + + const list = document.getElementById('recentReportsList'); + + if (!Array.isArray(reports) || reports.length === 0) { + list.innerHTML = '

최근 7일간의 작업 보고서가 없습니다.

'; + return; + } + + list.innerHTML = reports.map(r => ` +
+ ${r.report_date} + ${r.project_name || 'N/A'} + ${r.work_hours}시간 +
+ `).join(''); + } catch (error) { + console.error('최근 작업 보고서 로드 실패:', error); + } +} + +// 이전 달 +function previousMonth() { + currentMonth--; + if (currentMonth < 1) { + currentMonth = 12; + currentYear--; + } + loadMonthlyCalendar(); + loadWorkHoursStats(); +} + +// 다음 달 +function nextMonth() { + currentMonth++; + if (currentMonth > 12) { + currentMonth = 1; + currentYear++; + } + loadMonthlyCalendar(); + loadWorkHoursStats(); +} + +// 전역 함수 노출 +window.previousMonth = previousMonth; +window.nextMonth = nextMonth; +window.loadMonthlyCalendar = loadMonthlyCalendar; diff --git a/deploy/tkfb-package/web-ui/js/my-profile.js b/deploy/tkfb-package/web-ui/js/my-profile.js new file mode 100644 index 0000000..222ab99 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/my-profile.js @@ -0,0 +1,122 @@ +// js/my-profile.js +// 내 프로필 페이지 JavaScript + +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +const token = ensureAuthenticated(); + +// 권한 레벨 한글 매핑 +const accessLevelMap = { + worker: '작업자', + group_leader: '그룹장', + support_team: '지원팀', + admin: '관리자', + system: '시스템 관리자' +}; + +// 프로필 데이터 로드 +async function loadProfile() { + try { + // 먼저 로컬 스토리지에서 기본 정보 표시 + const storedUser = JSON.parse(localStorage.getItem('user') || '{}'); + if (storedUser) { + updateProfileUI(storedUser); + } + + // API에서 최신 정보 가져오기 + const res = await fetch(`${API}/auth/me`, { + headers: getAuthHeaders() + }); + + if (!res.ok) { + throw new Error(`HTTP error! status: ${res.status}`); + } + + const userData = await res.json(); + + // 로컬 스토리지 업데이트 + const updatedUser = { + ...storedUser, + ...userData + }; + localStorage.setItem('user', JSON.stringify(updatedUser)); + + // UI 업데이트 + updateProfileUI(userData); + + } catch (error) { + console.error('프로필 로딩 실패:', error); + showError('프로필 정보를 불러오는데 실패했습니다.'); + } +} + +// 프로필 UI 업데이트 +function updateProfileUI(user) { + // 헤더 정보 + const avatar = document.getElementById('profileAvatar'); + if (avatar && user.name) { + // 이름의 첫 글자를 아바타로 사용 + const initial = user.name.charAt(0).toUpperCase(); + if (initial.match(/[A-Z가-힣]/)) { + avatar.textContent = initial; + } + } + + document.getElementById('profileName').textContent = user.name || user.username || '사용자'; + document.getElementById('profileRole').textContent = accessLevelMap[user.access_level] || user.access_level || '역할 미지정'; + + // 기본 정보 + document.getElementById('userId').textContent = user.user_id || '-'; + document.getElementById('username').textContent = user.username || '-'; + document.getElementById('fullName').textContent = user.name || '-'; + document.getElementById('accessLevel').textContent = accessLevelMap[user.access_level] || user.access_level || '-'; + document.getElementById('workerId').textContent = user.worker_id || '연결되지 않음'; + + // 날짜 포맷팅 + if (user.created_at) { + const createdDate = new Date(user.created_at); + document.getElementById('createdAt').textContent = formatDate(createdDate); + } + + if (user.last_login_at) { + const lastLoginDate = new Date(user.last_login_at); + document.getElementById('lastLogin').textContent = formatDateTime(lastLoginDate); + } else { + document.getElementById('lastLogin').textContent = '첫 로그인'; + } + + // 이메일 + document.getElementById('email').textContent = user.email || '등록되지 않음'; +} + +// 날짜 포맷팅 함수 +function formatDate(date) { + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: 'long', + day: 'numeric' + }); +} + +function formatDateTime(date) { + return date.toLocaleString('ko-KR', { + year: 'numeric', + month: 'long', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); +} + +// 에러 표시 +function showError(message) { + // 간단한 알림으로 처리 + alert('❌ ' + message); +} + +// 페이지 로드 시 실행 +document.addEventListener('DOMContentLoaded', () => { + console.log('👤 프로필 페이지 로드됨'); + loadProfile(); +}); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/navigation.js b/deploy/tkfb-package/web-ui/js/navigation.js new file mode 100644 index 0000000..18d0012 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/navigation.js @@ -0,0 +1,55 @@ +// /js/navigation.js +import { config } from './config.js'; + +/** + * 지정된 URL로 페이지를 리디렉션합니다. + * @param {string} url - 이동할 URL + */ +function redirect(url) { + window.location.href = url; +} + +/** + * 로그인 페이지로 리디렉션합니다. + */ +export function redirectToLogin() { + console.log(`🔄 로그인 페이지로 이동합니다: ${config.paths.loginPage}`); + redirect(config.paths.loginPage); +} + +/** + * 사용자의 기본 대시보드 페이지로 리디렉션합니다. + * 백엔드가 지정한 URL이 있으면 그곳으로, 없으면 기본 URL로 이동합니다. + * @param {string} [backendRedirectUrl=null] - 백엔드에서 전달받은 리디렉션 URL + */ +export function redirectToDefaultDashboard(backendRedirectUrl = null) { + const destination = backendRedirectUrl || config.paths.defaultDashboard; + console.log(`🔄 대시보드로 이동합니다: ${destination}`); + + // 부드러운 화면 전환 효과 + document.body.style.transition = 'opacity 0.3s ease-out'; + document.body.style.opacity = '0'; + + setTimeout(() => { + redirect(destination); + }, 300); +} + +/** + * 시스템 대시보드 페이지로 리디렉션합니다. + */ +export function redirectToSystemDashboard() { + console.log(`🔄 시스템 대시보드로 이동합니다: ${config.paths.systemDashboard}`); + redirect(config.paths.systemDashboard); +} + +/** + * 그룹 리더 대시보드 페이지로 리디렉션합니다. + */ +export function redirectToGroupLeaderDashboard() { + console.log(`🔄 그룹 리더 대시보드로 이동합니다: ${config.paths.groupLeaderDashboard}`); + redirect(config.paths.groupLeaderDashboard); +} + +// 필요에 따라 더 많은 리디렉션 함수를 추가할 수 있습니다. +// export function redirectToUserProfile() { ... } \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/nonconformity-list.js b/deploy/tkfb-package/web-ui/js/nonconformity-list.js new file mode 100644 index 0000000..b3a1402 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/nonconformity-list.js @@ -0,0 +1,222 @@ +/** + * 부적합 현황 페이지 JavaScript + * category_type=nonconformity 고정 필터 + */ + +const API_BASE = window.API_BASE_URL || 'http://localhost:20005/api'; +const CATEGORY_TYPE = 'nonconformity'; + +// 상태 한글 변환 +const STATUS_LABELS = { + reported: '신고', + received: '접수', + in_progress: '처리중', + completed: '완료', + closed: '종료' +}; + +// DOM 요소 +let issueList; +let filterStatus, filterStartDate, filterEndDate; + +// 초기화 +document.addEventListener('DOMContentLoaded', async () => { + issueList = document.getElementById('issueList'); + filterStatus = document.getElementById('filterStatus'); + filterStartDate = document.getElementById('filterStartDate'); + filterEndDate = document.getElementById('filterEndDate'); + + // 필터 이벤트 리스너 + filterStatus.addEventListener('change', loadIssues); + filterStartDate.addEventListener('change', loadIssues); + filterEndDate.addEventListener('change', loadIssues); + + // 데이터 로드 + await Promise.all([loadStats(), loadIssues()]); +}); + +/** + * 통계 로드 (부적합만) + */ +async function loadStats() { + try { + const response = await fetch(`${API_BASE}/work-issues/stats/summary?category_type=${CATEGORY_TYPE}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) { + document.getElementById('statsGrid').style.display = 'none'; + return; + } + + const data = await response.json(); + if (data.success && data.data) { + document.getElementById('statReported').textContent = data.data.reported || 0; + document.getElementById('statReceived').textContent = data.data.received || 0; + document.getElementById('statProgress').textContent = data.data.in_progress || 0; + document.getElementById('statCompleted').textContent = data.data.completed || 0; + } + } catch (error) { + console.error('통계 로드 실패:', error); + document.getElementById('statsGrid').style.display = 'none'; + } +} + +/** + * 부적합 목록 로드 + */ +async function loadIssues() { + try { + // 필터 파라미터 구성 (category_type 고정) + const params = new URLSearchParams(); + params.append('category_type', CATEGORY_TYPE); + + if (filterStatus.value) params.append('status', filterStatus.value); + if (filterStartDate.value) params.append('start_date', filterStartDate.value); + if (filterEndDate.value) params.append('end_date', filterEndDate.value); + + const response = await fetch(`${API_BASE}/work-issues?${params.toString()}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) throw new Error('목록 조회 실패'); + + const data = await response.json(); + if (data.success) { + renderIssues(data.data || []); + } + } catch (error) { + console.error('부적합 목록 로드 실패:', error); + issueList.innerHTML = ` +
+
목록을 불러올 수 없습니다
+

잠시 후 다시 시도해주세요.

+
+ `; + } +} + +/** + * 부적합 목록 렌더링 + */ +function renderIssues(issues) { + if (issues.length === 0) { + issueList.innerHTML = ` +
+
등록된 부적합 신고가 없습니다
+

새로운 부적합을 신고하려면 '부적합 신고' 버튼을 클릭하세요.

+
+ `; + return; + } + + const baseUrl = (window.API_BASE_URL || 'http://localhost:20005').replace('/api', ''); + + issueList.innerHTML = issues.map(issue => { + const reportDate = new Date(issue.report_date).toLocaleString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); + + // 위치 정보 (escaped) + let location = escapeHtml(issue.custom_location || ''); + if (issue.factory_name) { + location = escapeHtml(issue.factory_name); + if (issue.workplace_name) { + location += ` - ${escapeHtml(issue.workplace_name)}`; + } + } + + // 신고 제목 (항목명 또는 카테고리명) + const title = escapeHtml(issue.issue_item_name || issue.issue_category_name || '부적합 신고'); + const categoryName = escapeHtml(issue.issue_category_name || '부적합'); + + // 사진 목록 + const photos = [ + issue.photo_path1, + issue.photo_path2, + issue.photo_path3, + issue.photo_path4, + issue.photo_path5 + ].filter(Boolean); + + // 안전한 값들 + const safeReportId = parseInt(issue.report_id) || 0; + const validStatuses = ['reported', 'received', 'in_progress', 'completed', 'closed']; + const safeStatus = validStatuses.includes(issue.status) ? issue.status : 'reported'; + const reporterName = escapeHtml(issue.reporter_full_name || issue.reporter_name || '-'); + const assignedName = issue.assigned_full_name ? escapeHtml(issue.assigned_full_name) : ''; + + return ` +
+
+ #${safeReportId} + ${STATUS_LABELS[issue.status] || escapeHtml(issue.status || '-')} +
+ +
+ ${categoryName} + ${title} +
+ +
+ + + + + + ${reporterName} + + + + + + + + + ${reportDate} + + ${location ? ` + + + + + + ${location} + + ` : ''} + ${assignedName ? ` + + + + + + + + 담당: ${assignedName} + + ` : ''} +
+ + ${photos.length > 0 ? ` +
+ ${photos.slice(0, 3).map(p => ` + 신고 사진 + `).join('')} + ${photos.length > 3 ? `+${photos.length - 3}` : ''} +
+ ` : ''} +
+ `; + }).join(''); +} + +/** + * 상세 보기 + */ +function viewIssue(reportId) { + window.location.href = `/pages/safety/issue-detail.html?id=${reportId}&from=nonconformity`; +} diff --git a/deploy/tkfb-package/web-ui/js/page-access-cache.js b/deploy/tkfb-package/web-ui/js/page-access-cache.js new file mode 100644 index 0000000..bc1cfc2 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/page-access-cache.js @@ -0,0 +1,119 @@ +// /js/page-access-cache.js +// 페이지 권한 캐시 - 중복 API 호출 방지 + +const CACHE_KEY = 'userPageAccess'; +const CACHE_DURATION = 10 * 60 * 1000; // 10분 + +// 진행 중인 API 호출 Promise (중복 방지) +let fetchPromise = null; + +/** + * 페이지 접근 권한 데이터 가져오기 (캐시 우선) + * @param {object} currentUser - 현재 사용자 객체 + * @returns {Promise} 접근 가능한 페이지 목록 + */ +export async function getPageAccess(currentUser) { + if (!currentUser || !currentUser.user_id) { + return null; + } + + // 1. 캐시 확인 + const cached = localStorage.getItem(CACHE_KEY); + if (cached) { + try { + const cacheData = JSON.parse(cached); + if (Date.now() - cacheData.timestamp < CACHE_DURATION) { + return cacheData.pages; + } + } catch (e) { + localStorage.removeItem(CACHE_KEY); + } + } + + // 2. 이미 API 호출 중이면 기존 Promise 반환 + if (fetchPromise) { + return fetchPromise; + } + + // 3. 새로운 API 호출 + fetchPromise = (async () => { + try { + const response = await fetch(`${window.API_BASE_URL}/users/${currentUser.user_id}/page-access`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + } + }); + + if (!response.ok) { + console.error('페이지 권한 조회 실패:', response.status); + return null; + } + + const data = await response.json(); + const accessiblePages = data.data.pageAccess || []; + + // 캐시 저장 + localStorage.setItem(CACHE_KEY, JSON.stringify({ + pages: accessiblePages, + timestamp: Date.now() + })); + + return accessiblePages; + } catch (error) { + console.error('페이지 권한 조회 오류:', error); + return null; + } finally { + fetchPromise = null; + } + })(); + + return fetchPromise; +} + +/** + * 특정 페이지에 대한 접근 권한 확인 + * @param {string} pageKey - 페이지 키 + * @param {object} currentUser - 현재 사용자 객체 + * @returns {Promise} + */ +export async function hasPageAccess(pageKey, currentUser) { + // Admin은 모든 페이지 접근 가능 + if (currentUser.role === 'Admin' || currentUser.role === 'System Admin') { + return true; + } + + // 대시보드, 프로필은 모든 사용자 접근 가능 + if (pageKey === 'dashboard' || (pageKey && pageKey.startsWith('profile.'))) { + return true; + } + + const pages = await getPageAccess(currentUser); + if (!pages) return false; + + const pageAccess = pages.find(p => p.page_key === pageKey); + return pageAccess && pageAccess.can_access === 1; +} + +/** + * 접근 가능한 페이지 키 목록 반환 + * @param {object} currentUser + * @returns {Promise} + */ +export async function getAccessiblePageKeys(currentUser) { + const pages = await getPageAccess(currentUser); + if (!pages) return []; + + return pages + .filter(p => p.can_access === 1) + .map(p => p.page_key); +} + +/** + * 캐시 초기화 + */ +export function clearPageAccessCache() { + localStorage.removeItem(CACHE_KEY); + fetchPromise = null; +} diff --git a/deploy/tkfb-package/web-ui/js/project-analysis-api.js b/deploy/tkfb-package/web-ui/js/project-analysis-api.js new file mode 100644 index 0000000..4ee5910 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/project-analysis-api.js @@ -0,0 +1,43 @@ +// /js/project-analysis-api.js +import { apiGet } from './api-helper.js'; + +/** + * 분석 페이지에 필요한 모든 초기 데이터(마스터 데이터)를 병렬로 가져옵니다. + * 이 데이터는 필터 옵션을 채우는 데 사용됩니다. + * @returns {Promise<{workers: Array, projects: Array, tasks: Array}>} + */ +export async function getMasterData() { + try { + const [allWorkers, projects, tasks] = await Promise.all([ + apiGet('/workers'), + apiGet('/projects'), + apiGet('/tasks') + ]); + + // 활성화된 작업자만 필터링 + const workers = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + + return { workers, projects, tasks }; + } catch (error) { + console.error('마스터 데이터 로딩 실패:', error); + throw new Error('필터링에 필요한 데이터를 불러오는 데 실패했습니다.'); + } +} + +/** + * 지정된 기간의 모든 분석 데이터를 백엔드에서 직접 가져옵니다. + * @param {string} startDate - 시작일 (YYYY-MM-DD) + * @param {string} endDate - 종료일 (YYYY-MM-DD) + * @returns {Promise} - 요약, 집계, 상세 데이터가 모두 포함된 분석 결과 객체 + */ +export async function getAnalysisReport(startDate, endDate) { + try { + const analysisData = await apiGet(`/analysis?startDate=${startDate}&endDate=${endDate}`); + return analysisData; + } catch (error) { + console.error('분석 보고서 데이터 로딩 실패:', error); + throw new Error(`분석 데이터를 불러오는 데 실패했습니다: ${error.message}`); + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/project-analysis-ui.js b/deploy/tkfb-package/web-ui/js/project-analysis-ui.js new file mode 100644 index 0000000..75c49e6 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/project-analysis-ui.js @@ -0,0 +1,170 @@ +// /js/project-analysis-ui.js + +const DOM = { + // 기간 설정 + startDate: document.getElementById('startDate'), + endDate: document.getElementById('endDate'), + // 카드 및 필터 + analysisCard: document.getElementById('analysisCard'), + summaryCards: document.getElementById('summaryCards'), + projectFilter: document.getElementById('projectFilter'), + workerFilter: document.getElementById('workerFilter'), + taskFilter: document.getElementById('taskFilter'), + // 탭 + tabButtons: document.querySelectorAll('.tab-button'), + tabContents: document.querySelectorAll('.analysis-content'), + // 테이블 본문 + projectTableBody: document.getElementById('projectTableBody'), + workerTableBody: document.getElementById('workerTableBody'), + taskTableBody: document.getElementById('taskTableBody'), + detailTableBody: document.getElementById('detailTableBody'), +}; + +/** + * 날짜 input 값을 YYYY-MM-DD 형식의 문자열로 반환 + * @param {Date} date - 날짜 객체 + * @returns {string} - 포맷된 날짜 문자열 + */ +const formatDate = (date) => date.toISOString().split('T')[0]; + +/** + * UI상의 날짜 선택기를 기본값(이번 달)으로 설정합니다. + */ +export function setDefaultDates() { + const now = new Date(); + const firstDay = new Date(now.getFullYear(), now.getMonth(), 1); + const lastDay = new Date(now.getFullYear(), now.getMonth() + 1, 0); + DOM.startDate.value = formatDate(firstDay); + DOM.endDate.value = formatDate(lastDay); +} + +/** + * 분석 실행 전후의 UI 상태를 관리합니다 (로딩 표시 등) + * @param {'loading' | 'data' | 'no-data' | 'error'} state - UI 상태 + */ +export function setUIState(state) { + const projectCols = 5; + const detailCols = 8; + const messages = { + loading: '📊 데이터 분석 중...', + 'no-data': '해당 기간에 분석할 데이터가 없습니다.', + error: '오류가 발생했습니다. 다시 시도해주세요.', + }; + + if (state === 'data') { + DOM.analysisCard.style.display = 'block'; + } else { + const message = messages[state]; + const html = `${message}`; + const detailHtml = `${message}`; + DOM.projectTableBody.innerHTML = html; + DOM.workerTableBody.innerHTML = html; + DOM.taskTableBody.innerHTML = html; + DOM.detailTableBody.innerHTML = detailHtml; + DOM.summaryCards.innerHTML = ''; + DOM.analysisCard.style.display = 'block'; + } +} + + +/** + * 마스터 데이터를 기반으로 필터 옵션을 채웁니다. + * @param {{workers: Array, projects: Array, tasks: Array}} masterData - 마스터 데이터 + */ +export function updateFilterOptions(masterData) { + const createOptions = (items, key, value) => { + let html = ''; + items.forEach(item => { + html += ``; + }); + return html; + }; + DOM.projectFilter.innerHTML = createOptions(masterData.projects, 'project_id', 'project_name'); + DOM.workerFilter.innerHTML = createOptions(masterData.workers, 'worker_id', 'worker_name'); + DOM.taskFilter.innerHTML = createOptions(masterData.tasks, 'task_id', 'category'); +} + +/** + * 요약 카드 데이터를 렌더링합니다. + * @param {object} summary - 요약 데이터 + */ +export function renderSummary(summary) { + DOM.summaryCards.innerHTML = ` +

총 투입 시간

${(summary.totalHours || 0).toFixed(1)}h
+

참여 프로젝트

${summary.totalProjects || 0}개
+

참여 인원

${summary.totalWorkers || 0}명
+

작업 분류

${summary.totalTasks || 0}개
+ `; +} + +/** + * 집계된 데이터를 받아 테이블을 렌더링하는 범용 함수 + * @param {HTMLElement} tableBodyEl - 렌더링할 테이블의 tbody 요소 + * @param {Array} data - 집계된 데이터 배열 + * @param {function} rowRenderer - 각 행을 렌더링하는 함수 + */ +function renderTable(tableBodyEl, data, rowRenderer) { + if (!data || data.length === 0) { + tableBodyEl.innerHTML = '데이터가 없습니다'; + return; + } + tableBodyEl.innerHTML = data.map(rowRenderer).join(''); +} + +/** + * 집계된 데이터를 기반으로 모든 분석 테이블을 렌더링합니다. + * @param {object} analysis - 프로젝트/작업자/작업별 집계 데이터 + */ +export function renderAnalysisTables(analysis) { + renderTable(DOM.projectTableBody, analysis.byProject, (p, i) => ` + ${i + 1}${p.name}${p.hours}h + ${p.percentage}%${p.participants}명`); + + renderTable(DOM.workerTableBody, analysis.byWorker, (w, i) => ` + ${i + 1}${w.name}${w.hours}h + ${w.percentage}%${w.participants}개`); + + renderTable(DOM.taskTableBody, analysis.byTask, (t, i) => ` + ${i + 1}${t.name}${t.hours}h + ${t.percentage}%${t.participants}명`); +} + +/** + * 상세 내역 테이블을 렌더링합니다. + * @param {Array} detailData - 필터링된 상세 데이터 + */ +export function renderDetailTable(detailData) { + if (!detailData || detailData.length === 0) { + DOM.detailTableBody.innerHTML = '데이터가 없습니다'; + return; + } + DOM.detailTableBody.innerHTML = detailData.map((item, index) => ` + ${index + 1}${formatDate(new Date(item.date))} + ${item.project_name} + ${item.worker_name}${item.task_category} + ${item.work_details || '정상근무'} + ${item.work_hours}h + ${(item.memo || '-').substring(0, 20)}` + ).join(''); +} + +/** + * 탭 UI를 제어합니다. + * @param {string} tabName - 활성화할 탭의 이름 + */ +export function switchTab(tabName) { + DOM.tabButtons.forEach(btn => btn.classList.toggle('active', btn.dataset.tab === tabName)); + DOM.tabContents.forEach(content => content.classList.toggle('active', content.id === `${tabName}Tab`)); +} + +/** + * 사용자로부터 현재 필터 값을 가져옵니다. + * @returns {{project: string, worker: string, task: string}} + */ +export function getCurrentFilters() { + return { + project: DOM.projectFilter.value, + worker: DOM.workerFilter.value, + task: DOM.taskFilter.value, + }; +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/project-analysis.js b/deploy/tkfb-package/web-ui/js/project-analysis.js new file mode 100644 index 0000000..fcad431 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/project-analysis.js @@ -0,0 +1,106 @@ +// /js/project-analysis.js +import { getMasterData, getAnalysisReport } from './project-analysis-api.js'; +import { + setDefaultDates, + setUIState, + updateFilterOptions, + renderSummary, + renderAnalysisTables, + renderDetailTable, + switchTab, +} from './project-analysis-ui.js'; + +// DOM 요소 참조 (이벤트 리스너 설정용) +const DOM = { + startDate: document.getElementById('startDate'), + endDate: document.getElementById('endDate'), + analyzeBtn: document.getElementById('analyzeBtn'), + quickMonthBtn: document.getElementById('quickMonth'), + quickLastMonthBtn: document.getElementById('quickLastMonth'), + // 필터 버튼은 현재 아무 기능도 하지 않으므로 주석 처리 또는 제거 가능 + // applyFilterBtn: document.getElementById('applyFilter'), + tabButtons: document.querySelectorAll('.tab-button'), +}; + +/** + * 분석 실행 버튼 클릭 이벤트 핸들러 + */ +async function handleAnalysis() { + const startDate = DOM.startDate.value; + const endDate = DOM.endDate.value; + + if (!startDate || !endDate || startDate > endDate) { + alert('올바른 분석 기간을 설정해주세요.'); + return; + } + + setUIState('loading'); + try { + const analysisResult = await getAnalysisReport(startDate, endDate); + + if (!analysisResult.summary.totalHours) { + setUIState('no-data'); + return; + } + + renderSummary(analysisResult.summary); + renderAnalysisTables(analysisResult); + renderDetailTable(analysisResult.details); + setUIState('data'); + + } catch (error) { + console.error('분석 처리 중 오류:', error); + setUIState('error'); + alert(error.message); + } +} + +/** + * 빠른 날짜 설정 버튼 핸들러 + */ +function handleQuickDate(monthType) { + const now = new Date(); + const year = now.getFullYear(); + const month = now.getMonth(); + const firstDay = monthType === 'this' ? new Date(year, month, 1) : new Date(year, month - 1, 1); + const lastDay = monthType === 'this' ? new Date(year, month + 1, 0) : new Date(year, month, 0); + + DOM.startDate.value = firstDay.toISOString().split('T')[0]; + DOM.endDate.value = lastDay.toISOString().split('T')[0]; +} + +/** + * 이벤트 리스너 설정 + */ +function setupEventListeners() { + DOM.analyzeBtn.addEventListener('click', handleAnalysis); + DOM.quickMonthBtn.addEventListener('click', () => handleQuickDate('this')); + DOM.quickLastMonthBtn.addEventListener('click', () => handleQuickDate('last')); + + DOM.tabButtons.forEach(btn => { + btn.addEventListener('click', () => switchTab(btn.dataset.tab)); + }); + + // 프론트엔드 필터링은 제거되었으므로 관련 이벤트 리스너는 주석 처리합니다. + // DOM.applyFilterBtn.addEventListener('click', ...); +} + +/** + * 페이지 초기화 함수 + */ +async function initialize() { + setDefaultDates(); + setupEventListeners(); + + try { + const masterData = await getMasterData(); + updateFilterOptions(masterData); + await handleAnalysis(); + } catch (error) { + alert(error.message); + setUIState('error'); + } +} + +// 초기화 실행 +document.addEventListener('DOMContentLoaded', initialize); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/project-management.js b/deploy/tkfb-package/web-ui/js/project-management.js new file mode 100644 index 0000000..b6fbe26 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/project-management.js @@ -0,0 +1,625 @@ +// 프로젝트 관리 페이지 JavaScript + +// 전역 변수 +let allProjects = []; +let filteredProjects = []; +let currentEditingProject = null; +let currentStatusFilter = 'all'; // 'all', 'active', 'inactive' + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', function() { + console.log('📁 프로젝트 관리 페이지 초기화 시작'); + + initializePage(); + loadProjects(); +}); + +// 페이지 초기화 +function initializePage() { + // 시간 업데이트 시작 + updateCurrentTime(); + setInterval(updateCurrentTime, 1000); + + // 사용자 정보 업데이트 + updateUserInfo(); + + // 프로필 메뉴 토글 + setupProfileMenu(); + + // 로그아웃 버튼 + setupLogoutButton(); + + // 검색 입력 이벤트 + setupSearchInput(); +} + +// 현재 시간 업데이트 (시 분 초 형식으로 고정) +function updateCurrentTime() { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + const timeString = `${hours}시 ${minutes}분 ${seconds}초`; + + const timeElement = document.getElementById('timeValue'); + if (timeElement) { + timeElement.textContent = timeString; + } +} + +// navbar/sidebar는 app-init.js에서 공통 처리 +function updateUserInfo() { + // app-init.js가 navbar 사용자 정보를 처리 +} + +// 프로필 메뉴 설정 +function setupProfileMenu() { + const userProfile = document.getElementById('userProfile'); + const profileMenu = document.getElementById('profileMenu'); + + if (userProfile && profileMenu) { + userProfile.addEventListener('click', function(e) { + e.stopPropagation(); + const isVisible = profileMenu.style.display === 'block'; + profileMenu.style.display = isVisible ? 'none' : 'block'; + }); + + // 외부 클릭 시 메뉴 닫기 + document.addEventListener('click', function() { + profileMenu.style.display = 'none'; + }); + } +} + +// 로그아웃 버튼 설정 +function setupLogoutButton() { + const logoutBtn = document.getElementById('logoutBtn'); + if (logoutBtn) { + logoutBtn.addEventListener('click', function() { + if (confirm('로그아웃 하시겠습니까?')) { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + localStorage.removeItem('userInfo'); + window.location.href = '/index.html'; + } + }); + } +} + +// 검색 입력 설정 +function setupSearchInput() { + const searchInput = document.getElementById('searchInput'); + if (searchInput) { + searchInput.addEventListener('input', function() { + searchProjects(); + }); + + searchInput.addEventListener('keypress', function(e) { + if (e.key === 'Enter') { + searchProjects(); + } + }); + } +} + +// 프로젝트 목록 로드 +async function loadProjects() { + try { + console.log('📊 프로젝트 목록 로딩 시작'); + + const response = await apiCall('/projects', 'GET'); + + console.log('📊 API 응답 구조:', response); + + // API 응답이 { success: true, data: [...] } 형태인 경우 처리 + let projectData = []; + if (response && response.success && Array.isArray(response.data)) { + projectData = response.data; + } else if (Array.isArray(response)) { + projectData = response; + } else { + console.warn('프로젝트 데이터가 배열이 아닙니다:', response); + projectData = []; + } + + allProjects = projectData; + + console.log(`✅ 프로젝트 ${allProjects.length}개 로드 완료`); + + // 초기 필터 적용 + applyAllFilters(); + updateStatCardActiveState(); + + } catch (error) { + console.error('프로젝트 로딩 오류:', error); + showToast('프로젝트 목록을 불러오는데 실패했습니다.', 'error'); + allProjects = []; + filteredProjects = []; + renderProjects(); + } +} + +// 프로젝트 목록 렌더링 +function renderProjects() { + const projectsGrid = document.getElementById('projectsGrid'); + const emptyState = document.getElementById('emptyState'); + + if (!projectsGrid || !emptyState) return; + + if (filteredProjects.length === 0) { + projectsGrid.style.display = 'none'; + emptyState.style.display = 'block'; + return; + } + + projectsGrid.style.display = 'grid'; + emptyState.style.display = 'none'; + + const projectsHtml = filteredProjects.map(project => { + // 프로젝트 상태 아이콘 및 텍스트 + const statusMap = { + 'planning': { icon: '📋', text: '계획', color: '#6b7280' }, + 'active': { icon: '🚀', text: '진행중', color: '#10b981' }, + 'completed': { icon: '✅', text: '완료', color: '#3b82f6' }, + 'cancelled': { icon: '❌', text: '취소', color: '#ef4444' } + }; + + const validStatuses = ['planning', 'active', 'completed', 'cancelled']; + const safeProjectStatus = validStatuses.includes(project.project_status) ? project.project_status : 'active'; + const status = statusMap[safeProjectStatus]; + // is_active 값 처리 (DB에서 0/1로 오는 경우 대비) + const isInactive = project.is_active === 0 || project.is_active === false || project.is_active === 'false'; + + // XSS 방지를 위한 안전한 값 + const safeProjectId = parseInt(project.project_id) || 0; + const safeJobNo = escapeHtml(project.job_no || 'Job No. 없음'); + const safeProjectName = escapeHtml(project.project_name || '-'); + const safePm = escapeHtml(project.pm || '-'); + const safeSite = escapeHtml(project.site || '-'); + + console.log('🎨 카드 렌더링:', { + project_id: project.project_id, + project_name: project.project_name, + is_active_raw: project.is_active, + isInactive: isInactive + }); + + return ` +
+ ${isInactive ? '
🚫 비활성화됨
' : ''} +
+
+
${safeJobNo}
+

+ ${safeProjectName} + ${isInactive ? '(비활성)' : ''} +

+
+
+ 상태 + ${status.icon} ${status.text} +
+
+ 계약일 + ${project.contract_date ? formatDate(project.contract_date) : '-'} +
+
+ 납기일 + ${project.due_date ? formatDate(project.due_date) : '-'} +
+
+ PM + ${safePm} +
+
+ 현장 + ${safeSite} +
+ ${isInactive ? '
⚠️ 작업보고서에서 숨김
' : ''} +
+
+
+ + +
+
+
+ `; + }).join(''); + + projectsGrid.innerHTML = projectsHtml; +} + +// 프로젝트 통계 업데이트 +function updateProjectStats() { + const activeProjects = filteredProjects.filter(p => p.is_active === 1 || p.is_active === true); + const inactiveProjects = filteredProjects.filter(p => p.is_active === 0 || p.is_active === false); + + const activeProjectsElement = document.getElementById('activeProjects'); + const inactiveProjectsElement = document.getElementById('inactiveProjects'); + const totalProjectsElement = document.getElementById('totalProjects'); + + if (activeProjectsElement) { + activeProjectsElement.textContent = activeProjects.length; + } + + if (inactiveProjectsElement) { + inactiveProjectsElement.textContent = inactiveProjects.length; + } + + if (totalProjectsElement) { + totalProjectsElement.textContent = filteredProjects.length; + } + + console.log('📊 프로젝트 통계:', { + 전체: filteredProjects.length, + 활성: activeProjects.length, + 비활성: inactiveProjects.length + }); +} + +// 날짜 포맷팅 +function formatDate(dateString) { + if (!dateString) return ''; + + const date = new Date(dateString); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }); +} + +// 상태별 필터링 +function filterByStatus(status) { + currentStatusFilter = status; + + // 통계 카드 활성화 상태 업데이트 + updateStatCardActiveState(); + + // 필터링 적용 + applyAllFilters(); + + console.log(`🔍 상태 필터 적용: ${status}`); +} + +// 통계 카드 활성화 상태 업데이트 +function updateStatCardActiveState() { + // 모든 통계 카드에서 active 클래스 제거 + document.querySelectorAll('.stat-item').forEach(item => { + item.classList.remove('active'); + }); + + // 현재 선택된 필터에 active 클래스 추가 + const activeCard = document.querySelector(`.${currentStatusFilter === 'active' ? 'active-stat' : + currentStatusFilter === 'inactive' ? 'inactive-stat' : 'total-stat'}`); + if (activeCard) { + activeCard.classList.add('active'); + } +} + +// 모든 필터 적용 (검색 + 상태) +function applyAllFilters() { + const searchInput = document.getElementById('searchInput'); + const searchTerm = searchInput ? searchInput.value.toLowerCase().trim() : ''; + + // 1단계: 상태 필터링 + let statusFiltered = [...allProjects]; + if (currentStatusFilter === 'active') { + statusFiltered = allProjects.filter(p => p.is_active === 1 || p.is_active === true); + } else if (currentStatusFilter === 'inactive') { + statusFiltered = allProjects.filter(p => p.is_active === 0 || p.is_active === false); + } + + // 2단계: 검색 필터링 + if (!searchTerm) { + filteredProjects = statusFiltered; + } else { + filteredProjects = statusFiltered.filter(project => + project.project_name.toLowerCase().includes(searchTerm) || + (project.job_no && project.job_no.toLowerCase().includes(searchTerm)) || + (project.pm && project.pm.toLowerCase().includes(searchTerm)) || + (project.site && project.site.toLowerCase().includes(searchTerm)) + ); + } + + renderProjects(); + updateProjectStats(); +} + +// 프로젝트 검색 (기존 함수 수정) +function searchProjects() { + applyAllFilters(); +} + +// 프로젝트 필터링 +function filterProjects() { + const statusFilter = document.getElementById('statusFilter'); + const selectedStatus = statusFilter ? statusFilter.value : ''; + + // 현재는 상태 필드가 없으므로 기본 필터링만 적용 + searchProjects(); +} + +// 프로젝트 정렬 +function sortProjects() { + const sortBy = document.getElementById('sortBy'); + const sortField = sortBy ? sortBy.value : 'created_at'; + + filteredProjects.sort((a, b) => { + switch (sortField) { + case 'project_name': + return a.project_name.localeCompare(b.project_name); + case 'due_date': + if (!a.due_date && !b.due_date) return 0; + if (!a.due_date) return 1; + if (!b.due_date) return -1; + return new Date(a.due_date) - new Date(b.due_date); + case 'created_at': + default: + return new Date(b.created_at || 0) - new Date(a.created_at || 0); + } + }); + + renderProjects(); +} + +// 프로젝트 목록 새로고침 +async function refreshProjectList() { + const refreshBtn = document.querySelector('.btn-secondary'); + if (refreshBtn) { + const originalText = refreshBtn.innerHTML; + refreshBtn.innerHTML = '새로고침 중...'; + refreshBtn.disabled = true; + + await loadProjects(); + + refreshBtn.innerHTML = originalText; + refreshBtn.disabled = false; + } else { + await loadProjects(); + } + + showToast('프로젝트 목록이 새로고침되었습니다.', 'success'); +} + +// 프로젝트 모달 열기 +function openProjectModal(project = null) { + const modal = document.getElementById('projectModal'); + const modalTitle = document.getElementById('modalTitle'); + const deleteBtn = document.getElementById('deleteProjectBtn'); + + if (!modal) return; + + currentEditingProject = project; + + if (project) { + // 수정 모드 + modalTitle.textContent = '프로젝트 수정'; + deleteBtn.style.display = 'inline-flex'; + + // 폼에 데이터 채우기 + document.getElementById('projectId').value = project.project_id; + document.getElementById('jobNo').value = project.job_no || ''; + document.getElementById('projectName').value = project.project_name || ''; + document.getElementById('contractDate').value = project.contract_date || ''; + document.getElementById('dueDate').value = project.due_date || ''; + document.getElementById('deliveryMethod').value = project.delivery_method || ''; + document.getElementById('site').value = project.site || ''; + document.getElementById('pm').value = project.pm || ''; + document.getElementById('projectStatus').value = project.project_status || 'active'; + document.getElementById('completedDate').value = project.completed_date || ''; + // is_active 값 처리 (DB에서 0/1로 오는 경우 대비) + const isActiveValue = project.is_active === 1 || project.is_active === true || project.is_active === 'true'; + document.getElementById('isActive').checked = isActiveValue; + + console.log('🔧 프로젝트 로드:', { + project_id: project.project_id, + project_name: project.project_name, + is_active_raw: project.is_active, + is_active_processed: isActiveValue + }); + } else { + // 신규 등록 모드 + modalTitle.textContent = '새 프로젝트 등록'; + deleteBtn.style.display = 'none'; + + // 폼 초기화 + document.getElementById('projectForm').reset(); + document.getElementById('projectId').value = ''; + } + + modal.style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + // 첫 번째 입력 필드에 포커스 + setTimeout(() => { + const firstInput = document.getElementById('jobNo'); + if (firstInput) firstInput.focus(); + }, 100); +} + +// 프로젝트 모달 닫기 +function closeProjectModal() { + const modal = document.getElementById('projectModal'); + if (modal) { + modal.style.display = 'none'; + document.body.style.overflow = ''; + currentEditingProject = null; + } +} + +// 프로젝트 편집 +function editProject(projectId) { + const project = allProjects.find(p => p.project_id === projectId); + if (project) { + openProjectModal(project); + } else { + showToast('프로젝트를 찾을 수 없습니다.', 'error'); + } +} + +// 프로젝트 저장 +async function saveProject() { + try { + const form = document.getElementById('projectForm'); + const formData = new FormData(form); + + const projectData = { + job_no: document.getElementById('jobNo').value.trim(), + project_name: document.getElementById('projectName').value.trim(), + contract_date: document.getElementById('contractDate').value || null, + due_date: document.getElementById('dueDate').value || null, + delivery_method: document.getElementById('deliveryMethod').value || null, + site: document.getElementById('site').value.trim() || null, + pm: document.getElementById('pm').value.trim() || null, + project_status: document.getElementById('projectStatus').value || 'active', + completed_date: document.getElementById('completedDate').value || null, + is_active: document.getElementById('isActive').checked ? 1 : 0 + }; + + console.log('💾 저장할 프로젝트 데이터:', projectData); + + // 필수 필드 검증 + if (!projectData.job_no || !projectData.project_name) { + showToast('Job No.와 프로젝트명은 필수 입력 항목입니다.', 'error'); + return; + } + + const projectId = document.getElementById('projectId').value; + let response; + + if (projectId) { + // 수정 + response = await apiCall(`/projects/${projectId}`, 'PUT', projectData); + } else { + // 신규 등록 + response = await apiCall('/projects', 'POST', projectData); + } + + if (response && (response.success || response.project_id)) { + const action = projectId ? '수정' : '등록'; + showToast(`프로젝트가 성공적으로 ${action}되었습니다.`, 'success'); + + closeProjectModal(); + await loadProjects(); + } else { + throw new Error(response?.message || '저장에 실패했습니다.'); + } + + } catch (error) { + console.error('프로젝트 저장 오류:', error); + showToast(error.message || '프로젝트 저장 중 오류가 발생했습니다.', 'error'); + } +} + +// 프로젝트 삭제 확인 +function confirmDeleteProject(projectId) { + const project = allProjects.find(p => p.project_id === projectId); + if (!project) { + showToast('프로젝트를 찾을 수 없습니다.', 'error'); + return; + } + + if (confirm(`"${project.project_name}" 프로젝트를 정말 삭제하시겠습니까?\n\n⚠️ 삭제된 프로젝트는 복구할 수 없습니다.`)) { + deleteProjectById(projectId); + } +} + +// 프로젝트 삭제 (수정 모드에서) +function deleteProject() { + if (currentEditingProject) { + confirmDeleteProject(currentEditingProject.project_id); + } +} + +// 프로젝트 삭제 실행 +async function deleteProjectById(projectId) { + try { + const response = await apiCall(`/projects/${projectId}`, 'DELETE'); + + if (response && response.success) { + showToast('프로젝트가 성공적으로 삭제되었습니다.', 'success'); + + closeProjectModal(); + await loadProjects(); + } else { + throw new Error(response?.message || '삭제에 실패했습니다.'); + } + + } catch (error) { + console.error('프로젝트 삭제 오류:', error); + showToast(error.message || '프로젝트 삭제 중 오류가 발생했습니다.', 'error'); + } +} + +// 토스트 메시지 표시 +function showToast(message, type = 'info') { + // 기존 토스트 제거 + const existingToast = document.querySelector('.toast'); + if (existingToast) { + existingToast.remove(); + } + + // 새 토스트 생성 + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + + // 스타일 적용 + Object.assign(toast.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '12px 24px', + borderRadius: '8px', + color: 'white', + fontWeight: '500', + zIndex: '1000', + transform: 'translateX(100%)', + transition: 'transform 0.3s ease' + }); + + // 타입별 배경색 + const colors = { + success: '#10b981', + error: '#ef4444', + warning: '#f59e0b', + info: '#3b82f6' + }; + toast.style.backgroundColor = colors[type] || colors.info; + + document.body.appendChild(toast); + + // 애니메이션 + setTimeout(() => { + toast.style.transform = 'translateX(0)'; + }, 100); + + // 자동 제거 + setTimeout(() => { + toast.style.transform = 'translateX(100%)'; + setTimeout(() => { + if (toast.parentNode) { + toast.remove(); + } + }, 300); + }, 3000); +} + +// 전역 함수로 노출 +window.openProjectModal = openProjectModal; +window.closeProjectModal = closeProjectModal; +window.editProject = editProject; +window.saveProject = saveProject; +window.deleteProject = deleteProject; +window.confirmDeleteProject = confirmDeleteProject; +window.searchProjects = searchProjects; +window.filterProjects = filterProjects; +window.sortProjects = sortProjects; +window.refreshProjectList = refreshProjectList; +window.filterByStatus = filterByStatus; diff --git a/deploy/tkfb-package/web-ui/js/safety-checklist-manage.js b/deploy/tkfb-package/web-ui/js/safety-checklist-manage.js new file mode 100644 index 0000000..4529edb --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/safety-checklist-manage.js @@ -0,0 +1,718 @@ +/** + * 안전 체크리스트 관리 페이지 스크립트 + * + * 3가지 유형의 체크리스트 항목을 관리: + * 1. 기본 사항 - 항상 표시 + * 2. 날씨별 - 날씨 조건에 따라 표시 + * 3. 작업별 - 선택한 작업에 따라 표시 + * + * @since 2026-02-02 + */ + +import { apiCall } from './api-config.js'; + +// 전역 상태 +let allChecks = []; +let weatherConditions = []; +let workTypes = []; +let tasks = []; +let currentTab = 'basic'; +let editingCheckId = null; + +// 카테고리 정보 +const CATEGORIES = { + PPE: { name: 'PPE (개인보호장비)', icon: '🦺' }, + EQUIPMENT: { name: 'EQUIPMENT (장비점검)', icon: '🔧' }, + ENVIRONMENT: { name: 'ENVIRONMENT (작업환경)', icon: '🏗️' }, + EMERGENCY: { name: 'EMERGENCY (비상대응)', icon: '🚨' }, + WEATHER: { name: 'WEATHER (날씨)', icon: '🌤️' }, + TASK: { name: 'TASK (작업)', icon: '📋' } +}; + +// 날씨 아이콘 매핑 +const WEATHER_ICONS = { + clear: '☀️', + rain: '🌧️', + snow: '❄️', + heat: '🔥', + cold: '🥶', + wind: '💨', + fog: '🌫️', + dust: '😷' +}; + +/** + * 페이지 초기화 + */ +async function initPage() { + try { + console.log('📋 안전 체크리스트 관리 페이지 초기화...'); + + await Promise.all([ + loadAllChecks(), + loadWeatherConditions(), + loadWorkTypes() + ]); + + renderCurrentTab(); + console.log('✅ 초기화 완료. 체크항목:', allChecks.length, '개'); + } catch (error) { + console.error('초기화 실패:', error); + showToast('데이터를 불러오는데 실패했습니다.', 'error'); + } +} + +// DOMContentLoaded 이벤트 +document.addEventListener('DOMContentLoaded', initPage); + +/** + * 모든 안전 체크 항목 로드 + */ +async function loadAllChecks() { + try { + const response = await apiCall('/tbm/safety-checks'); + if (response && response.success) { + allChecks = response.data || []; + console.log('✅ 체크 항목 로드:', allChecks.length, '개'); + } else { + console.warn('체크 항목 응답 실패:', response); + allChecks = []; + } + } catch (error) { + console.error('체크 항목 로드 실패:', error); + allChecks = []; + } +} + +/** + * 날씨 조건 목록 로드 + */ +async function loadWeatherConditions() { + try { + const response = await apiCall('/tbm/weather/conditions'); + if (response && response.success) { + weatherConditions = response.data || []; + populateWeatherSelects(); + console.log('✅ 날씨 조건 로드:', weatherConditions.length, '개'); + } + } catch (error) { + console.error('날씨 조건 로드 실패:', error); + weatherConditions = []; + } +} + +/** + * 공정(작업 유형) 목록 로드 + */ +async function loadWorkTypes() { + try { + const response = await apiCall('/daily-work-reports/work-types'); + if (response && response.success) { + workTypes = response.data || []; + populateWorkTypeSelects(); + console.log('✅ 공정 목록 로드:', workTypes.length, '개'); + } + } catch (error) { + console.error('공정 목록 로드 실패:', error); + workTypes = []; + } +} + +/** + * 날씨 조건 셀렉트 박스 채우기 + */ +function populateWeatherSelects() { + const filterSelect = document.getElementById('weatherFilter'); + const modalSelect = document.getElementById('weatherCondition'); + + const options = weatherConditions.map(wc => + `` + ).join(''); + + if (filterSelect) { + filterSelect.innerHTML = `${options}`; + } + + if (modalSelect) { + modalSelect.innerHTML = options || ''; + } +} + +/** + * 공정 셀렉트 박스 채우기 + */ +function populateWorkTypeSelects() { + const filterSelect = document.getElementById('workTypeFilter'); + const modalSelect = document.getElementById('modalWorkType'); + + const options = workTypes.map(wt => + `` + ).join(''); + + if (filterSelect) { + filterSelect.innerHTML = `${options}`; + } + + if (modalSelect) { + modalSelect.innerHTML = `${options}`; + } +} + +/** + * 탭 전환 + */ +function switchTab(tabName) { + currentTab = tabName; + + // 탭 버튼 상태 업데이트 + document.querySelectorAll('.tab-btn').forEach(btn => { + btn.classList.toggle('active', btn.dataset.tab === tabName); + }); + + // 탭 콘텐츠 표시/숨김 + document.querySelectorAll('.tab-content').forEach(content => { + content.classList.toggle('active', content.id === `${tabName}Tab`); + }); + + renderCurrentTab(); +} + +/** + * 현재 탭 렌더링 + */ +function renderCurrentTab() { + switch (currentTab) { + case 'basic': + renderBasicChecks(); + break; + case 'weather': + renderWeatherChecks(); + break; + case 'task': + renderTaskChecks(); + break; + } +} + +/** + * 기본 체크 항목 렌더링 + */ +function renderBasicChecks() { + const container = document.getElementById('basicChecklistContainer'); + const basicChecks = allChecks.filter(c => c.check_type === 'basic'); + + console.log('기본 체크항목:', basicChecks.length, '개'); + + if (basicChecks.length === 0) { + container.innerHTML = renderEmptyState('기본 체크 항목이 없습니다.'); + return; + } + + // 카테고리별로 그룹화 + const grouped = groupByCategory(basicChecks); + + container.innerHTML = Object.entries(grouped).map(([category, items]) => + renderChecklistGroup(category, items) + ).join(''); +} + +/** + * 날씨별 체크 항목 렌더링 + */ +function renderWeatherChecks() { + const container = document.getElementById('weatherChecklistContainer'); + const filterValue = document.getElementById('weatherFilter')?.value; + + let weatherChecks = allChecks.filter(c => c.check_type === 'weather'); + + if (filterValue) { + weatherChecks = weatherChecks.filter(c => c.weather_condition === filterValue); + } + + if (weatherChecks.length === 0) { + container.innerHTML = renderEmptyState('날씨별 체크 항목이 없습니다.'); + return; + } + + // 날씨 조건별로 그룹화 + const grouped = groupByWeather(weatherChecks); + + container.innerHTML = Object.entries(grouped).map(([condition, items]) => { + const conditionInfo = weatherConditions.find(wc => wc.condition_code === condition); + const icon = WEATHER_ICONS[condition] || '🌤️'; + const name = conditionInfo?.condition_name || condition; + + return renderChecklistGroup(`${icon} ${name}`, items, condition); + }).join(''); +} + +/** + * 작업별 체크 항목 렌더링 + */ +function renderTaskChecks() { + const container = document.getElementById('taskChecklistContainer'); + const workTypeId = document.getElementById('workTypeFilter')?.value; + const taskId = document.getElementById('taskFilter')?.value; + + let taskChecks = allChecks.filter(c => c.check_type === 'task'); + + if (taskId) { + taskChecks = taskChecks.filter(c => c.task_id == taskId); + } else if (workTypeId && tasks.length > 0) { + const workTypeTasks = tasks.filter(t => t.work_type_id == workTypeId); + const taskIds = workTypeTasks.map(t => t.task_id); + taskChecks = taskChecks.filter(c => taskIds.includes(c.task_id)); + } + + if (taskChecks.length === 0) { + container.innerHTML = renderEmptyState('작업별 체크 항목이 없습니다.'); + return; + } + + // 작업별로 그룹화 + const grouped = groupByTask(taskChecks); + + container.innerHTML = Object.entries(grouped).map(([taskId, items]) => { + const task = tasks.find(t => t.task_id == taskId); + const taskName = task?.task_name || `작업 ${taskId}`; + + return renderChecklistGroup(`📋 ${taskName}`, items, null, taskId); + }).join(''); +} + +/** + * 카테고리별 그룹화 + */ +function groupByCategory(checks) { + return checks.reduce((acc, check) => { + const category = check.check_category || 'OTHER'; + if (!acc[category]) acc[category] = []; + acc[category].push(check); + return acc; + }, {}); +} + +/** + * 날씨 조건별 그룹화 + */ +function groupByWeather(checks) { + return checks.reduce((acc, check) => { + const condition = check.weather_condition || 'other'; + if (!acc[condition]) acc[condition] = []; + acc[condition].push(check); + return acc; + }, {}); +} + +/** + * 작업별 그룹화 + */ +function groupByTask(checks) { + return checks.reduce((acc, check) => { + const taskId = check.task_id || 0; + if (!acc[taskId]) acc[taskId] = []; + acc[taskId].push(check); + return acc; + }, {}); +} + +/** + * 체크리스트 그룹 렌더링 + */ +function renderChecklistGroup(title, items, weatherCondition = null, taskId = null) { + const categoryInfo = CATEGORIES[title] || { name: title, icon: '' }; + const displayTitle = categoryInfo.name !== title ? categoryInfo.name : title; + const icon = categoryInfo.icon || ''; + + // 표시 순서로 정렬 + items.sort((a, b) => (a.display_order || 0) - (b.display_order || 0)); + + return ` +
+
+
+ ${icon} + ${displayTitle} +
+ ${items.length}개 +
+
+ ${items.map(item => renderChecklistItem(item)).join('')} +
+
+ `; +} + +/** + * 체크리스트 항목 렌더링 + */ +function renderChecklistItem(item) { + const requiredBadge = item.is_required + ? '필수' + : '선택'; + + return ` +
+
+
${item.check_item}
+
+ ${requiredBadge} + ${item.description ? `${item.description}` : ''} +
+
+
+ + +
+
+ `; +} + +/** + * 빈 상태 렌더링 + */ +function renderEmptyState(message) { + return ` +
+
📋
+

${message}

+
+ `; +} + +/** + * 날씨 필터 변경 + */ +function filterByWeather() { + renderWeatherChecks(); +} + +/** + * 공정 필터 변경 + */ +async function filterByWorkType() { + const workTypeId = document.getElementById('workTypeFilter')?.value; + const taskSelect = document.getElementById('taskFilter'); + + // workTypeId가 없거나 빈 문자열이면 early return + if (!workTypeId || workTypeId === '' || workTypeId === 'undefined') { + if (taskSelect) { + taskSelect.innerHTML = ''; + } + tasks = []; + renderTaskChecks(); + return; + } + + try { + const response = await apiCall(`/tasks/work-type/${workTypeId}`); + if (response && response.success) { + tasks = response.data || []; + taskSelect.innerHTML = '' + + tasks.map(t => ``).join(''); + } + } catch (error) { + console.error('작업 목록 로드 실패:', error); + tasks = []; + } + + renderTaskChecks(); +} + +/** + * 작업 필터 변경 + */ +function filterByTask() { + renderTaskChecks(); +} + +/** + * 모달의 작업 목록 로드 + */ +async function loadModalTasks() { + const workTypeId = document.getElementById('modalWorkType')?.value; + const taskSelect = document.getElementById('modalTask'); + + // workTypeId가 없거나 빈 문자열이면 early return + if (!workTypeId || workTypeId === '' || workTypeId === 'undefined') { + if (taskSelect) { + taskSelect.innerHTML = ''; + } + return; + } + + try { + const response = await apiCall(`/tasks/work-type/${workTypeId}`); + if (response && response.success) { + const modalTasks = response.data || []; + taskSelect.innerHTML = '' + + modalTasks.map(t => ``).join(''); + } + } catch (error) { + console.error('작업 목록 로드 실패:', error); + } +} + +/** + * 조건부 필드 토글 + */ +function toggleConditionalFields() { + const checkType = document.querySelector('input[name="checkType"]:checked')?.value; + + document.getElementById('basicFields').classList.toggle('show', checkType === 'basic'); + document.getElementById('weatherFields').classList.toggle('show', checkType === 'weather'); + document.getElementById('taskFields').classList.toggle('show', checkType === 'task'); +} + +/** + * 추가 모달 열기 + */ +function openAddModal() { + editingCheckId = null; + document.getElementById('modalTitle').textContent = '체크 항목 추가'; + + // 폼 초기화 + document.getElementById('checkForm').reset(); + document.getElementById('checkId').value = ''; + + // 현재 탭에 맞는 유형 선택 + const typeRadio = document.querySelector(`input[name="checkType"][value="${currentTab}"]`); + if (typeRadio) { + typeRadio.checked = true; + } + + toggleConditionalFields(); + showModal(); +} + +/** + * 수정 모달 열기 + */ +async function openEditModal(checkId) { + editingCheckId = checkId; + const check = allChecks.find(c => c.check_id === checkId); + + if (!check) { + showToast('항목을 찾을 수 없습니다.', 'error'); + return; + } + + document.getElementById('modalTitle').textContent = '체크 항목 수정'; + document.getElementById('checkId').value = checkId; + + // 유형 선택 + const typeRadio = document.querySelector(`input[name="checkType"][value="${check.check_type}"]`); + if (typeRadio) { + typeRadio.checked = true; + } + + toggleConditionalFields(); + + // 카테고리 + if (check.check_type === 'basic') { + document.getElementById('checkCategory').value = check.check_category || 'PPE'; + } + + // 날씨 조건 + if (check.check_type === 'weather') { + document.getElementById('weatherCondition').value = check.weather_condition || ''; + } + + // 작업 + if (check.check_type === 'task' && check.task_id) { + // 먼저 공정 찾기 (task를 통해) + const task = tasks.find(t => t.task_id === check.task_id); + if (task) { + document.getElementById('modalWorkType').value = task.work_type_id; + await loadModalTasks(); + document.getElementById('modalTask').value = check.task_id; + } + } + + // 공통 필드 + document.getElementById('checkItem').value = check.check_item || ''; + document.getElementById('checkDescription').value = check.description || ''; + document.getElementById('isRequired').checked = check.is_required === 1 || check.is_required === true; + document.getElementById('displayOrder').value = check.display_order || 0; + + showModal(); +} + +/** + * 모달 표시 + */ +function showModal() { + document.getElementById('checkModal').style.display = 'flex'; +} + +/** + * 모달 닫기 + */ +function closeModal() { + document.getElementById('checkModal').style.display = 'none'; + editingCheckId = null; +} + +/** + * 체크 항목 저장 + */ +async function saveCheck() { + const checkType = document.querySelector('input[name="checkType"]:checked')?.value; + const checkItem = document.getElementById('checkItem').value.trim(); + + if (!checkItem) { + showToast('체크 항목을 입력해주세요.', 'error'); + return; + } + + const data = { + check_type: checkType, + check_item: checkItem, + description: document.getElementById('checkDescription').value.trim() || null, + is_required: document.getElementById('isRequired').checked, + display_order: parseInt(document.getElementById('displayOrder').value) || 0 + }; + + // 유형별 추가 데이터 + switch (checkType) { + case 'basic': + data.check_category = document.getElementById('checkCategory').value; + break; + case 'weather': + data.check_category = 'WEATHER'; + data.weather_condition = document.getElementById('weatherCondition').value; + if (!data.weather_condition) { + showToast('날씨 조건을 선택해주세요.', 'error'); + return; + } + break; + case 'task': + data.check_category = 'TASK'; + data.task_id = document.getElementById('modalTask').value; + if (!data.task_id) { + showToast('작업을 선택해주세요.', 'error'); + return; + } + break; + } + + try { + let response; + if (editingCheckId) { + // 수정 + response = await apiCall(`/tbm/safety-checks/${editingCheckId}`, 'PUT', data); + } else { + // 추가 + response = await apiCall('/tbm/safety-checks', 'POST', data); + } + + if (response && response.success) { + showToast(editingCheckId ? '항목이 수정되었습니다.' : '항목이 추가되었습니다.', 'success'); + closeModal(); + await loadAllChecks(); + renderCurrentTab(); + } else { + showToast(response?.message || '저장에 실패했습니다.', 'error'); + } + } catch (error) { + console.error('저장 실패:', error); + showToast('저장 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 삭제 확인 + */ +function confirmDelete(checkId) { + const check = allChecks.find(c => c.check_id === checkId); + + if (!check) { + showToast('항목을 찾을 수 없습니다.', 'error'); + return; + } + + if (confirm(`"${check.check_item}" 항목을 삭제하시겠습니까?`)) { + deleteCheck(checkId); + } +} + +/** + * 체크 항목 삭제 + */ +async function deleteCheck(checkId) { + try { + const response = await apiCall(`/tbm/safety-checks/${checkId}`, 'DELETE'); + + if (response && response.success) { + showToast('항목이 삭제되었습니다.', 'success'); + await loadAllChecks(); + renderCurrentTab(); + } else { + showToast(response?.message || '삭제에 실패했습니다.', 'error'); + } + } catch (error) { + console.error('삭제 실패:', error); + showToast('삭제 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 토스트 메시지 표시 + */ +function showToast(message, type = 'info') { + // 기존 토스트 제거 + const existingToast = document.querySelector('.toast-message'); + if (existingToast) { + existingToast.remove(); + } + + const toast = document.createElement('div'); + toast.className = `toast-message toast-${type}`; + toast.textContent = message; + toast.style.cssText = ` + position: fixed; + bottom: 20px; + left: 50%; + transform: translateX(-50%); + padding: 12px 24px; + border-radius: 8px; + font-size: 14px; + font-weight: 500; + z-index: 9999; + animation: fadeInUp 0.3s ease; + ${type === 'success' ? 'background: #10b981; color: white;' : ''} + ${type === 'error' ? 'background: #ef4444; color: white;' : ''} + ${type === 'info' ? 'background: #3b82f6; color: white;' : ''} + `; + + document.body.appendChild(toast); + + setTimeout(() => { + toast.style.animation = 'fadeOut 0.3s ease'; + setTimeout(() => toast.remove(), 300); + }, 3000); +} + +// 모달 외부 클릭 시 닫기 +document.getElementById('checkModal')?.addEventListener('click', function(e) { + if (e.target === this) { + closeModal(); + } +}); + +// HTML onclick에서 호출할 수 있도록 전역에 노출 +window.switchTab = switchTab; +window.openAddModal = openAddModal; +window.openEditModal = openEditModal; +window.closeModal = closeModal; +window.saveCheck = saveCheck; +window.confirmDelete = confirmDelete; +window.filterByWeather = filterByWeather; +window.filterByWorkType = filterByWorkType; +window.filterByTask = filterByTask; +window.loadModalTasks = loadModalTasks; +window.toggleConditionalFields = toggleConditionalFields; diff --git a/deploy/tkfb-package/web-ui/js/safety-management.js b/deploy/tkfb-package/web-ui/js/safety-management.js new file mode 100644 index 0000000..a6fc975 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/safety-management.js @@ -0,0 +1,447 @@ +// 안전관리 대시보드 JavaScript + +let currentStatus = 'pending'; +let requests = []; +let currentRejectRequestId = null; + +// ==================== Toast 알림 ==================== + +function showToast(message, type = 'info', duration = 3000) { + const toastContainer = document.getElementById('toastContainer') || createToastContainer(); + + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + + const iconMap = { + success: '✅', + error: '❌', + warning: '⚠️', + info: 'ℹ️' + }; + + toast.innerHTML = ` + ${iconMap[type] || 'ℹ️'} + ${message} + `; + + toastContainer.appendChild(toast); + + setTimeout(() => toast.classList.add('show'), 10); + + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => toast.remove(), 300); + }, duration); +} + +function createToastContainer() { + const container = document.createElement('div'); + container.id = 'toastContainer'; + container.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + z-index: 9999; + display: flex; + flex-direction: column; + gap: 10px; + `; + + document.body.appendChild(container); + + if (!document.getElementById('toastStyles')) { + const style = document.createElement('style'); + style.id = 'toastStyles'; + style.textContent = ` + .toast { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 20px; + background: white; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + opacity: 0; + transform: translateX(100px); + transition: all 0.3s ease; + min-width: 250px; + max-width: 400px; + } + .toast.show { + opacity: 1; + transform: translateX(0); + } + .toast-success { border-left: 4px solid #10b981; } + .toast-error { border-left: 4px solid #ef4444; } + .toast-warning { border-left: 4px solid #f59e0b; } + .toast-info { border-left: 4px solid #3b82f6; } + .toast-icon { font-size: 20px; } + .toast-message { font-size: 14px; color: #374151; } + `; + document.head.appendChild(style); + } + + return container; +} + +// ==================== 초기화 ==================== + +document.addEventListener('DOMContentLoaded', async () => { + await loadRequests(); + updateStats(); +}); + +// ==================== 데이터 로드 ==================== + +/** + * 출입 신청 목록 로드 + */ +async function loadRequests() { + try { + const filters = currentStatus === 'all' ? {} : { status: currentStatus }; + const queryString = new URLSearchParams(filters).toString(); + + const response = await window.apiCall(`/workplace-visits/requests?${queryString}`, 'GET'); + + if (response && response.success) { + requests = response.data || []; + renderRequestTable(); + updateStats(); + } + } catch (error) { + console.error('출입 신청 목록 로드 오류:', error); + showToast('출입 신청 목록을 불러오는데 실패했습니다.', 'error'); + } +} + +/** + * 통계 업데이트 + */ +async function updateStats() { + try { + const response = await window.apiCall('/workplace-visits/requests', 'GET'); + + if (response && response.success) { + const allRequests = response.data || []; + + const stats = { + pending: allRequests.filter(r => r.status === 'pending').length, + approved: allRequests.filter(r => r.status === 'approved').length, + training_completed: allRequests.filter(r => r.status === 'training_completed').length, + rejected: allRequests.filter(r => r.status === 'rejected').length + }; + + document.getElementById('statPending').textContent = stats.pending; + document.getElementById('statApproved').textContent = stats.approved; + document.getElementById('statTrainingCompleted').textContent = stats.training_completed; + document.getElementById('statRejected').textContent = stats.rejected; + } + } catch (error) { + console.error('통계 업데이트 오류:', error); + } +} + +/** + * 테이블 렌더링 + */ +function renderRequestTable() { + const container = document.getElementById('requestTableContainer'); + + if (requests.length === 0) { + container.innerHTML = ` +
+
📭
+

출입 신청이 없습니다

+

현재 ${getStatusText(currentStatus)} 상태의 신청이 없습니다.

+
+ `; + return; + } + + let html = ` + + + + + + + + + + + + + + + + `; + + requests.forEach(req => { + const statusText = { + 'pending': '승인 대기', + 'approved': '승인됨', + 'rejected': '반려됨', + 'training_completed': '교육 완료' + }[req.status] || req.status; + + html += ` + + + + + + + + + + + + `; + }); + + html += ` + +
신청일신청자방문자인원방문 작업장방문 일시목적상태작업
${new Date(req.created_at).toLocaleDateString()}${req.requester_full_name || req.requester_name}${req.visitor_company}${req.visitor_count}명${req.category_name} - ${req.workplace_name}${req.visit_date} ${req.visit_time}${req.purpose_name}${statusText} +
+ + ${req.status === 'pending' ? ` + + + ` : ''} + ${req.status === 'approved' ? ` + + ` : ''} +
+
+ `; + + container.innerHTML = html; +} + +/** + * 상태 텍스트 변환 + */ +function getStatusText(status) { + const map = { + 'pending': '승인 대기', + 'approved': '승인 완료', + 'rejected': '반려', + 'training_completed': '교육 완료', + 'all': '전체' + }; + return map[status] || status; +} + +// ==================== 탭 전환 ==================== + +/** + * 탭 전환 + */ +async function switchTab(status) { + currentStatus = status; + + // 탭 활성화 상태 변경 + document.querySelectorAll('.status-tab').forEach(tab => { + if (tab.dataset.status === status) { + tab.classList.add('active'); + } else { + tab.classList.remove('active'); + } + }); + + await loadRequests(); +} + +// ==================== 상세보기 ==================== + +/** + * 상세보기 모달 열기 + */ +async function viewDetail(requestId) { + try { + const response = await window.apiCall(`/workplace-visits/requests/${requestId}`, 'GET'); + + if (response && response.success) { + const req = response.data; + const statusText = { + 'pending': '승인 대기', + 'approved': '승인됨', + 'rejected': '반려됨', + 'training_completed': '교육 완료' + }[req.status] || req.status; + + let html = ` +
+
신청 번호
+
#${req.request_id}
+ +
신청일
+
${new Date(req.created_at).toLocaleString()}
+ +
신청자
+
${req.requester_full_name || req.requester_name}
+ +
방문자 소속
+
${req.visitor_company}
+ +
방문 인원
+
${req.visitor_count}명
+ +
방문 구역
+
${req.category_name}
+ +
방문 작업장
+
${req.workplace_name}
+ +
방문 날짜
+
${req.visit_date}
+ +
방문 시간
+
${req.visit_time}
+ +
방문 목적
+
${req.purpose_name}
+ +
상태
+
${statusText}
+
+ `; + + if (req.notes) { + html += ` +
+ 비고:
+ ${req.notes} +
+ `; + } + + if (req.rejection_reason) { + html += ` +
+ 반려 사유:
+ ${req.rejection_reason} +
+ `; + } + + if (req.approved_by) { + html += ` +
+ 처리 정보:
+ 처리자: ${req.approver_name || 'Unknown'}
+ 처리 시간: ${new Date(req.approved_at).toLocaleString()} +
+ `; + } + + document.getElementById('detailContent').innerHTML = html; + document.getElementById('detailModal').style.display = 'flex'; + } + } catch (error) { + console.error('상세 정보 로드 오류:', error); + showToast('상세 정보를 불러오는데 실패했습니다.', 'error'); + } +} + +/** + * 상세보기 모달 닫기 + */ +function closeDetailModal() { + document.getElementById('detailModal').style.display = 'none'; +} + +// ==================== 승인/반려 ==================== + +/** + * 승인 처리 + */ +async function approveRequest(requestId) { + if (!confirm('이 출입 신청을 승인하시겠습니까?')) { + return; + } + + try { + const response = await window.apiCall(`/workplace-visits/requests/${requestId}/approve`, 'PUT'); + + if (response && response.success) { + showToast('출입 신청이 승인되었습니다.', 'success'); + await loadRequests(); + updateStats(); + } else { + throw new Error(response?.message || '승인 실패'); + } + } catch (error) { + console.error('승인 처리 오류:', error); + showToast(error.message || '승인 처리 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 반려 모달 열기 + */ +function openRejectModal(requestId) { + currentRejectRequestId = requestId; + document.getElementById('rejectionReason').value = ''; + document.getElementById('rejectModal').style.display = 'flex'; +} + +/** + * 반려 모달 닫기 + */ +function closeRejectModal() { + currentRejectRequestId = null; + document.getElementById('rejectModal').style.display = 'none'; +} + +/** + * 반려 확정 + */ +async function confirmReject() { + const reason = document.getElementById('rejectionReason').value.trim(); + + if (!reason) { + showToast('반려 사유를 입력해주세요.', 'warning'); + return; + } + + try { + const response = await window.apiCall( + `/workplace-visits/requests/${currentRejectRequestId}/reject`, + 'PUT', + { rejection_reason: reason } + ); + + if (response && response.success) { + showToast('출입 신청이 반려되었습니다.', 'success'); + closeRejectModal(); + await loadRequests(); + updateStats(); + } else { + throw new Error(response?.message || '반려 실패'); + } + } catch (error) { + console.error('반려 처리 오류:', error); + showToast(error.message || '반려 처리 중 오류가 발생했습니다.', 'error'); + } +} + +// ==================== 안전교육 진행 ==================== + +/** + * 안전교육 진행 페이지로 이동 + */ +function startTraining(requestId) { + window.location.href = `/pages/safety/training-conduct.html?request_id=${requestId}`; +} + +// 전역 함수로 노출 +window.showToast = showToast; +window.switchTab = switchTab; +window.viewDetail = viewDetail; +window.closeDetailModal = closeDetailModal; +window.approveRequest = approveRequest; +window.openRejectModal = openRejectModal; +window.closeRejectModal = closeRejectModal; +window.confirmReject = confirmReject; +window.startTraining = startTraining; diff --git a/deploy/tkfb-package/web-ui/js/safety-report-list.js b/deploy/tkfb-package/web-ui/js/safety-report-list.js new file mode 100644 index 0000000..c442504 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/safety-report-list.js @@ -0,0 +1,222 @@ +/** + * 안전신고 현황 페이지 JavaScript + * category_type=safety 고정 필터 + */ + +const API_BASE = window.API_BASE_URL || 'http://localhost:20005/api'; +const CATEGORY_TYPE = 'safety'; + +// 상태 한글 변환 +const STATUS_LABELS = { + reported: '신고', + received: '접수', + in_progress: '처리중', + completed: '완료', + closed: '종료' +}; + +// DOM 요소 +let issueList; +let filterStatus, filterStartDate, filterEndDate; + +// 초기화 +document.addEventListener('DOMContentLoaded', async () => { + issueList = document.getElementById('issueList'); + filterStatus = document.getElementById('filterStatus'); + filterStartDate = document.getElementById('filterStartDate'); + filterEndDate = document.getElementById('filterEndDate'); + + // 필터 이벤트 리스너 + filterStatus.addEventListener('change', loadIssues); + filterStartDate.addEventListener('change', loadIssues); + filterEndDate.addEventListener('change', loadIssues); + + // 데이터 로드 + await Promise.all([loadStats(), loadIssues()]); +}); + +/** + * 통계 로드 (안전만) + */ +async function loadStats() { + try { + const response = await fetch(`${API_BASE}/work-issues/stats/summary?category_type=${CATEGORY_TYPE}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) { + document.getElementById('statsGrid').style.display = 'none'; + return; + } + + const data = await response.json(); + if (data.success && data.data) { + document.getElementById('statReported').textContent = data.data.reported || 0; + document.getElementById('statReceived').textContent = data.data.received || 0; + document.getElementById('statProgress').textContent = data.data.in_progress || 0; + document.getElementById('statCompleted').textContent = data.data.completed || 0; + } + } catch (error) { + console.error('통계 로드 실패:', error); + document.getElementById('statsGrid').style.display = 'none'; + } +} + +/** + * 안전신고 목록 로드 + */ +async function loadIssues() { + try { + // 필터 파라미터 구성 (category_type 고정) + const params = new URLSearchParams(); + params.append('category_type', CATEGORY_TYPE); + + if (filterStatus.value) params.append('status', filterStatus.value); + if (filterStartDate.value) params.append('start_date', filterStartDate.value); + if (filterEndDate.value) params.append('end_date', filterEndDate.value); + + const response = await fetch(`${API_BASE}/work-issues?${params.toString()}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) throw new Error('목록 조회 실패'); + + const data = await response.json(); + if (data.success) { + renderIssues(data.data || []); + } + } catch (error) { + console.error('안전신고 목록 로드 실패:', error); + issueList.innerHTML = ` +
+
목록을 불러올 수 없습니다
+

잠시 후 다시 시도해주세요.

+
+ `; + } +} + +/** + * 안전신고 목록 렌더링 + */ +function renderIssues(issues) { + if (issues.length === 0) { + issueList.innerHTML = ` +
+
등록된 안전 신고가 없습니다
+

새로운 안전 문제를 신고하려면 '안전 신고' 버튼을 클릭하세요.

+
+ `; + return; + } + + const baseUrl = (window.API_BASE_URL || 'http://localhost:20005').replace('/api', ''); + + issueList.innerHTML = issues.map(issue => { + const reportDate = new Date(issue.report_date).toLocaleString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit', + hour: '2-digit', + minute: '2-digit' + }); + + // 위치 정보 (escaped) + let location = escapeHtml(issue.custom_location || ''); + if (issue.factory_name) { + location = escapeHtml(issue.factory_name); + if (issue.workplace_name) { + location += ` - ${escapeHtml(issue.workplace_name)}`; + } + } + + // 신고 제목 (항목명 또는 카테고리명) + const title = escapeHtml(issue.issue_item_name || issue.issue_category_name || '안전 신고'); + const categoryName = escapeHtml(issue.issue_category_name || '안전'); + + // 사진 목록 + const photos = [ + issue.photo_path1, + issue.photo_path2, + issue.photo_path3, + issue.photo_path4, + issue.photo_path5 + ].filter(Boolean); + + // 안전한 값들 + const safeReportId = parseInt(issue.report_id) || 0; + const validStatuses = ['reported', 'received', 'in_progress', 'completed', 'closed']; + const safeStatus = validStatuses.includes(issue.status) ? issue.status : 'reported'; + const reporterName = escapeHtml(issue.reporter_full_name || issue.reporter_name || '-'); + const assignedName = issue.assigned_full_name ? escapeHtml(issue.assigned_full_name) : ''; + + return ` +
+
+ #${safeReportId} + ${STATUS_LABELS[issue.status] || escapeHtml(issue.status || '-')} +
+ +
+ ${categoryName} + ${title} +
+ +
+ + + + + + ${reporterName} + + + + + + + + + ${reportDate} + + ${location ? ` + + + + + + ${location} + + ` : ''} + ${assignedName ? ` + + + + + + + + 담당: ${assignedName} + + ` : ''} +
+ + ${photos.length > 0 ? ` +
+ ${photos.slice(0, 3).map(p => ` + 신고 사진 + `).join('')} + ${photos.length > 3 ? `+${photos.length - 3}` : ''} +
+ ` : ''} +
+ `; + }).join(''); +} + +/** + * 상세 보기 + */ +function viewIssue(reportId) { + window.location.href = `/pages/safety/issue-detail.html?id=${reportId}&from=safety`; +} diff --git a/deploy/tkfb-package/web-ui/js/safety-training-conduct.js b/deploy/tkfb-package/web-ui/js/safety-training-conduct.js new file mode 100644 index 0000000..23f5e20 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/safety-training-conduct.js @@ -0,0 +1,553 @@ +// 안전교육 진행 페이지 JavaScript + +let requestId = null; +let requestData = null; +let canvas = null; +let ctx = null; +let isDrawing = false; +let hasSignature = false; +let savedSignatures = []; // 저장된 서명 목록 + +// ==================== Toast 알림 ==================== + +function showToast(message, type = 'info', duration = 3000) { + const toastContainer = document.getElementById('toastContainer') || createToastContainer(); + + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + + const iconMap = { + success: '✅', + error: '❌', + warning: '⚠️', + info: 'ℹ️' + }; + + toast.innerHTML = ` + ${iconMap[type] || 'ℹ️'} + ${message} + `; + + toastContainer.appendChild(toast); + + setTimeout(() => toast.classList.add('show'), 10); + + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => toast.remove(), 300); + }, duration); +} + +function createToastContainer() { + const container = document.createElement('div'); + container.id = 'toastContainer'; + container.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + z-index: 9999; + display: flex; + flex-direction: column; + gap: 10px; + `; + + document.body.appendChild(container); + + if (!document.getElementById('toastStyles')) { + const style = document.createElement('style'); + style.id = 'toastStyles'; + style.textContent = ` + .toast { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 20px; + background: white; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + opacity: 0; + transform: translateX(100px); + transition: all 0.3s ease; + min-width: 250px; + max-width: 400px; + } + .toast.show { + opacity: 1; + transform: translateX(0); + } + .toast-success { border-left: 4px solid #10b981; } + .toast-error { border-left: 4px solid #ef4444; } + .toast-warning { border-left: 4px solid #f59e0b; } + .toast-info { border-left: 4px solid #3b82f6; } + .toast-icon { font-size: 20px; } + .toast-message { font-size: 14px; color: #374151; } + `; + document.head.appendChild(style); + } + + return container; +} + +// ==================== 초기화 ==================== + +document.addEventListener('DOMContentLoaded', async () => { + // URL 파라미터에서 request_id 가져오기 + const urlParams = new URLSearchParams(window.location.search); + requestId = urlParams.get('request_id'); + + if (!requestId) { + showToast('출입 신청 ID가 없습니다.', 'error'); + setTimeout(() => { + window.location.href = '/pages/safety/management.html'; + }, 2000); + return; + } + + // 서명 캔버스 초기화 + initSignatureCanvas(); + + // 현재 날짜 표시 + const today = new Date().toLocaleDateString('ko-KR'); + document.getElementById('signatureDate').textContent = today; + + // 출입 신청 정보 로드 + await loadRequestInfo(); +}); + +// ==================== 출입 신청 정보 로드 ==================== + +/** + * 출입 신청 정보 로드 + */ +async function loadRequestInfo() { + try { + const response = await window.apiCall(`/workplace-visits/requests/${requestId}`, 'GET'); + + if (response && response.success) { + requestData = response.data; + + // 상태 확인 - 승인됨 상태만 진행 가능 + if (requestData.status !== 'approved') { + showToast('이미 처리되었거나 승인되지 않은 신청입니다.', 'error'); + setTimeout(() => { + window.location.href = '/pages/safety/management.html'; + }, 2000); + return; + } + + renderRequestInfo(); + } else { + throw new Error(response?.message || '정보를 불러올 수 없습니다.'); + } + } catch (error) { + console.error('출입 신청 정보 로드 오류:', error); + showToast('출입 신청 정보를 불러오는데 실패했습니다.', 'error'); + } +} + +/** + * 출입 신청 정보 렌더링 + */ +function renderRequestInfo() { + const container = document.getElementById('requestInfo'); + + // 날짜 포맷 변환 + const visitDate = new Date(requestData.visit_date); + const formattedDate = visitDate.toLocaleDateString('ko-KR', { + year: 'numeric', + month: 'long', + day: 'numeric', + weekday: 'short' + }); + + const html = ` +
+
신청 번호
+
#${requestData.request_id}
+
+
+
신청자
+
${requestData.requester_full_name || requestData.requester_name}
+
+
+
방문자 소속
+
${requestData.visitor_company}
+
+
+
방문 인원
+
${requestData.visitor_count}명
+
+
+
방문 작업장
+
${requestData.category_name} - ${requestData.workplace_name}
+
+
+
방문 일시
+
${formattedDate} ${requestData.visit_time}
+
+
+
방문 목적
+
${requestData.purpose_name}
+
+ `; + + container.innerHTML = html; +} + +// ==================== 서명 캔버스 ==================== + +/** + * 서명 캔버스 초기화 + */ +function initSignatureCanvas() { + canvas = document.getElementById('signatureCanvas'); + ctx = canvas.getContext('2d'); + + // 캔버스 크기 설정 + const container = canvas.parentElement; + canvas.width = container.clientWidth - 4; // border 제외 + canvas.height = 300; + + // 그리기 설정 + ctx.strokeStyle = '#000'; + ctx.lineWidth = 2; + ctx.lineCap = 'round'; + ctx.lineJoin = 'round'; + + // 마우스 이벤트 + canvas.addEventListener('mousedown', startDrawing); + canvas.addEventListener('mousemove', draw); + canvas.addEventListener('mouseup', stopDrawing); + canvas.addEventListener('mouseout', stopDrawing); + + // 터치 이벤트 (모바일, Apple Pencil) + canvas.addEventListener('touchstart', handleTouchStart, { passive: false }); + canvas.addEventListener('touchmove', handleTouchMove, { passive: false }); + canvas.addEventListener('touchend', stopDrawing); + canvas.addEventListener('touchcancel', stopDrawing); + + // Pointer Events (Apple Pencil 최적화) + if (window.PointerEvent) { + canvas.addEventListener('pointerdown', handlePointerDown); + canvas.addEventListener('pointermove', handlePointerMove); + canvas.addEventListener('pointerup', stopDrawing); + canvas.addEventListener('pointercancel', stopDrawing); + } +} + +/** + * 그리기 시작 (마우스) + */ +function startDrawing(e) { + isDrawing = true; + hasSignature = true; + document.getElementById('signaturePlaceholder').style.display = 'none'; + + const rect = canvas.getBoundingClientRect(); + ctx.beginPath(); + ctx.moveTo(e.clientX - rect.left, e.clientY - rect.top); +} + +/** + * 그리기 (마우스) + */ +function draw(e) { + if (!isDrawing) return; + + const rect = canvas.getBoundingClientRect(); + ctx.lineTo(e.clientX - rect.left, e.clientY - rect.top); + ctx.stroke(); +} + +/** + * 그리기 중지 + */ +function stopDrawing() { + isDrawing = false; + ctx.beginPath(); +} + +/** + * 터치 시작 처리 + */ +function handleTouchStart(e) { + e.preventDefault(); + isDrawing = true; + hasSignature = true; + document.getElementById('signaturePlaceholder').style.display = 'none'; + + const touch = e.touches[0]; + const rect = canvas.getBoundingClientRect(); + ctx.beginPath(); + ctx.moveTo(touch.clientX - rect.left, touch.clientY - rect.top); +} + +/** + * 터치 이동 처리 + */ +function handleTouchMove(e) { + if (!isDrawing) return; + e.preventDefault(); + + const touch = e.touches[0]; + const rect = canvas.getBoundingClientRect(); + ctx.lineTo(touch.clientX - rect.left, touch.clientY - rect.top); + ctx.stroke(); +} + +/** + * Pointer 시작 처리 (Apple Pencil) + */ +function handlePointerDown(e) { + isDrawing = true; + hasSignature = true; + document.getElementById('signaturePlaceholder').style.display = 'none'; + + const rect = canvas.getBoundingClientRect(); + ctx.beginPath(); + ctx.moveTo(e.clientX - rect.left, e.clientY - rect.top); +} + +/** + * Pointer 이동 처리 (Apple Pencil) + */ +function handlePointerMove(e) { + if (!isDrawing) return; + + const rect = canvas.getBoundingClientRect(); + ctx.lineTo(e.clientX - rect.left, e.clientY - rect.top); + ctx.stroke(); +} + +/** + * 서명 지우기 + */ +function clearSignature() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + hasSignature = false; + document.getElementById('signaturePlaceholder').style.display = 'block'; +} + +/** + * 서명을 Base64로 변환 + */ +function getSignatureBase64() { + if (!hasSignature) { + return null; + } + return canvas.toDataURL('image/png'); +} + +/** + * 현재 서명 저장 + */ +function saveSignature() { + if (!hasSignature) { + showToast('서명이 없습니다. 이름과 서명을 작성해주세요.', 'warning'); + return; + } + + const signatureImage = getSignatureBase64(); + const now = new Date(); + + savedSignatures.push({ + id: Date.now(), + image: signatureImage, + timestamp: now.toLocaleString('ko-KR') + }); + + // 서명 카운트 업데이트 + document.getElementById('signatureCount').textContent = savedSignatures.length; + + // 캔버스 초기화 + clearSignature(); + + // 저장된 서명 목록 렌더링 + renderSavedSignatures(); + + // 교육 완료 버튼 활성화 + updateCompleteButton(); + + showToast('서명이 저장되었습니다.', 'success'); +} + +/** + * 저장된 서명 목록 렌더링 + */ +function renderSavedSignatures() { + const container = document.getElementById('savedSignatures'); + + if (savedSignatures.length === 0) { + container.innerHTML = ''; + return; + } + + let html = '

저장된 서명 목록

'; + + savedSignatures.forEach((sig, index) => { + html += ` +
+ 서명 ${index + 1} +
+
방문자 ${index + 1}
+
저장 시간: ${sig.timestamp}
+
+
+ +
+
+ `; + }); + + container.innerHTML = html; +} + +/** + * 서명 삭제 + */ +function deleteSignature(signatureId) { + if (!confirm('이 서명을 삭제하시겠습니까?')) { + return; + } + + savedSignatures = savedSignatures.filter(sig => sig.id !== signatureId); + + // 서명 카운트 업데이트 + document.getElementById('signatureCount').textContent = savedSignatures.length; + + // 목록 다시 렌더링 + renderSavedSignatures(); + + // 교육 완료 버튼 상태 업데이트 + updateCompleteButton(); + + showToast('서명이 삭제되었습니다.', 'success'); +} + +/** + * 교육 완료 버튼 활성화/비활성화 + */ +function updateCompleteButton() { + const completeBtn = document.getElementById('completeBtn'); + + // 체크리스트와 서명이 모두 있어야 활성화 + const checkboxes = document.querySelectorAll('input[name="safety-check"]'); + const checkedItems = Array.from(checkboxes).filter(cb => cb.checked); + const allChecked = checkedItems.length === checkboxes.length; + const hasSignatures = savedSignatures.length > 0; + + completeBtn.disabled = !(allChecked && hasSignatures); +} + +// ==================== 교육 완료 처리 ==================== + +/** + * 교육 완료 처리 + */ +async function completeTraining() { + // 체크리스트 검증 + const checkboxes = document.querySelectorAll('input[name="safety-check"]'); + const checkedItems = Array.from(checkboxes).filter(cb => cb.checked); + + if (checkedItems.length !== checkboxes.length) { + showToast('모든 안전교육 항목을 체크해주세요.', 'warning'); + return; + } + + // 서명 검증 + if (savedSignatures.length === 0) { + showToast('최소 1명 이상의 서명이 필요합니다.', 'warning'); + return; + } + + // 확인 + if (!confirm(`${savedSignatures.length}명의 방문자 안전교육을 완료하시겠습니까?\n완료 후에는 수정할 수 없습니다.`)) { + return; + } + + try { + // 교육 항목 수집 + const trainingItems = checkedItems.map(cb => cb.value).join(', '); + + // API 호출 + const userData = localStorage.getItem('user'); + const currentUser = userData ? JSON.parse(userData) : null; + + if (!currentUser) { + showToast('로그인 정보를 찾을 수 없습니다.', 'error'); + return; + } + + // 현재 시간 + const now = new Date(); + const currentTime = now.toTimeString().split(' ')[0]; // HH:MM:SS + const trainingDate = now.toISOString().split('T')[0]; // YYYY-MM-DD + + // 각 서명에 대해 개별적으로 API 호출 + let successCount = 0; + for (let i = 0; i < savedSignatures.length; i++) { + const sig = savedSignatures[i]; + + const payload = { + request_id: requestId, + conducted_by: currentUser.user_id, + training_date: trainingDate, + training_start_time: currentTime, + training_end_time: currentTime, + training_items: trainingItems, + visitor_name: `방문자 ${i + 1}`, // 순번으로 구분 + signature_image: sig.image, + notes: `교육 완료 - ${checkedItems.length}개 항목 (${i + 1}/${savedSignatures.length})` + }; + + const response = await window.apiCall( + '/workplace-visits/training', + 'POST', + payload + ); + + if (response && response.success) { + successCount++; + } else { + console.error(`서명 ${i + 1} 저장 실패:`, response); + } + } + + if (successCount === savedSignatures.length) { + showToast(`${successCount}명의 안전교육이 완료되었습니다.`, 'success'); + setTimeout(() => { + window.location.href = '/pages/safety/management.html'; + }, 1500); + } else if (successCount > 0) { + showToast(`${successCount}/${savedSignatures.length}명의 교육만 저장되었습니다.`, 'warning'); + } else { + throw new Error('교육 완료 처리 실패'); + } + } catch (error) { + console.error('교육 완료 처리 오류:', error); + showToast(error.message || '교육 완료 처리 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 뒤로 가기 + */ +function goBack() { + if (hasSignature || document.querySelector('input[name="safety-check"]:checked')) { + if (!confirm('작성 중인 내용이 있습니다. 정말 나가시겠습니까?')) { + return; + } + } + window.location.href = '/pages/safety/management.html'; +} + +// 전역 함수로 노출 +window.showToast = showToast; +window.clearSignature = clearSignature; +window.saveSignature = saveSignature; +window.deleteSignature = deleteSignature; +window.updateCompleteButton = updateCompleteButton; +window.completeTraining = completeTraining; +window.goBack = goBack; diff --git a/deploy/tkfb-package/web-ui/js/system-dashboard.js b/deploy/tkfb-package/web-ui/js/system-dashboard.js new file mode 100644 index 0000000..0d08f7c --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/system-dashboard.js @@ -0,0 +1,907 @@ +// System Dashboard JavaScript +console.log('🚀 system-dashboard.js loaded'); + +import { apiRequest } from './api-helper.js'; +import { getCurrentUser } from './auth.js'; + +console.log('📦 modules imported successfully'); + +// 전역 변수 +let systemData = { + users: [], + logs: [], + systemStatus: {} +}; + +// Initialize on page load +document.addEventListener('DOMContentLoaded', function() { + console.log('📄 DOM loaded, starting initialization'); + initializeSystemDashboard(); + setupEventListeners(); +}); + +// Setup event listeners +function setupEventListeners() { + // Add event listeners to all data-action buttons + const actionButtons = document.querySelectorAll('[data-action]'); + + actionButtons.forEach(button => { + const action = button.getAttribute('data-action'); + + switch(action) { + case 'account-management': + button.addEventListener('click', openAccountManagement); + console.log('✅ Account management button listener added'); + break; + case 'system-logs': + button.addEventListener('click', openSystemLogs); + console.log('✅ System logs button listener added'); + break; + case 'database-management': + button.addEventListener('click', openDatabaseManagement); + console.log('✅ Database management button listener added'); + break; + case 'system-settings': + button.addEventListener('click', openSystemSettings); + console.log('✅ System settings button listener added'); + break; + case 'backup-management': + button.addEventListener('click', openBackupManagement); + console.log('✅ Backup management button listener added'); + break; + case 'monitoring': + button.addEventListener('click', openMonitoring); + console.log('✅ Monitoring button listener added'); + break; + case 'close-modal': + button.addEventListener('click', () => closeModal('account-modal')); + console.log('✅ Modal close button listener added'); + break; + } + }); + + console.log(`🎯 Total ${actionButtons.length} event listeners setup completed`); +} + +// Initialize system dashboard +async function initializeSystemDashboard() { + try { + console.log('🚀 Starting system dashboard initialization...'); + + // Load user info + await loadUserInfo(); + console.log('✅ User info loaded'); + + // Load system status + await loadSystemStatus(); + console.log('✅ System status loaded'); + + // Load user statistics + await loadUserStats(); + console.log('✅ User statistics loaded'); + + // Load recent activities + await loadRecentActivities(); + console.log('✅ Recent activities loaded'); + + // Setup auto-refresh (every 30 seconds) + setInterval(refreshSystemStatus, 30000); + + console.log('🎉 System dashboard initialization completed'); + } catch (error) { + console.error('❌ System dashboard initialization error:', error); + showNotification('Error loading system dashboard', 'error'); + } +} + +// 사용자 정보 로드 +async function loadUserInfo() { + try { + const user = getCurrentUser(); + if (user && user.name) { + document.getElementById('user-name').textContent = user.name; + } + } catch (error) { + console.error('사용자 정보 로드 오류:', error); + } +} + +// 시스템 상태 로드 +async function loadSystemStatus() { + try { + // 서버 상태 확인 + const serverStatus = await checkServerStatus(); + updateServerStatus(serverStatus); + + // 데이터베이스 상태 확인 + const dbStatus = await checkDatabaseStatus(); + updateDatabaseStatus(dbStatus); + + // 시스템 알림 확인 + const alerts = await getSystemAlerts(); + updateSystemAlerts(alerts); + + } catch (error) { + console.error('시스템 상태 로드 오류:', error); + } +} + +// 서버 상태 확인 +async function checkServerStatus() { + try { + const response = await apiRequest('/api/system/status', 'GET'); + return response.success ? 'online' : 'offline'; + } catch (error) { + return 'offline'; + } +} + +// 데이터베이스 상태 확인 +async function checkDatabaseStatus() { + try { + const response = await apiRequest('/api/system/db-status', 'GET'); + return response; + } catch (error) { + return { status: 'error', connections: 0 }; + } +} + +// 시스템 알림 가져오기 +async function getSystemAlerts() { + try { + const response = await apiRequest('/api/system/alerts', 'GET'); + return response.alerts || []; + } catch (error) { + return []; + } +} + +// 서버 상태 업데이트 +function updateServerStatus(status) { + const serverCheckTime = document.getElementById('server-check-time'); + const statusElements = document.querySelectorAll('.status-value'); + + if (serverCheckTime) { + serverCheckTime.textContent = new Date().toLocaleTimeString('ko-KR'); + } + + // 서버 상태 표시 업데이트 로직 추가 +} + +// 데이터베이스 상태 업데이트 +function updateDatabaseStatus(dbStatus) { + const dbConnections = document.getElementById('db-connections'); + if (dbConnections && dbStatus.connections !== undefined) { + dbConnections.textContent = dbStatus.connections; + } +} + +// 시스템 알림 업데이트 +function updateSystemAlerts(alerts) { + const systemAlerts = document.getElementById('system-alerts'); + if (systemAlerts) { + systemAlerts.textContent = alerts.length; + systemAlerts.className = `status-value ${alerts.length > 0 ? 'warning' : 'online'}`; + } +} + +// 사용자 통계 로드 +async function loadUserStats() { + try { + const response = await apiRequest('/api/system/users/stats', 'GET'); + + if (response.success) { + const activeUsers = document.getElementById('active-users'); + const totalUsers = document.getElementById('total-users'); + + if (activeUsers) activeUsers.textContent = response.data.active || 0; + if (totalUsers) totalUsers.textContent = response.data.total || 0; + } + } catch (error) { + console.error('사용자 통계 로드 오류:', error); + } +} + +// 최근 활동 로드 +async function loadRecentActivities() { + try { + const response = await apiRequest('/api/system/recent-activities', 'GET'); + + if (response.success && response.data) { + displayRecentActivities(response.data); + } + } catch (error) { + console.error('최근 활동 로드 오류:', error); + displayDefaultActivities(); + } +} + +// 최근 활동 표시 +function displayRecentActivities(activities) { + const container = document.getElementById('recent-activities'); + + if (!container) return; + + if (!activities || activities.length === 0) { + container.innerHTML = '

최근 활동이 없습니다.

'; + return; + } + + const html = activities.map(activity => ` +
+
+ +
+
+

${activity.title}

+

${activity.description}

+
+
+ ${formatTimeAgo(activity.created_at)} +
+
+ `).join(''); + + container.innerHTML = html; +} + +// 기본 활동 표시 (데이터 로드 실패 시) +function displayDefaultActivities() { + const container = document.getElementById('recent-activities'); + if (!container) return; + + const defaultActivities = [ + { + type: 'system', + title: '시스템 시작', + description: '시스템이 정상적으로 시작되었습니다.', + created_at: new Date().toISOString() + } + ]; + + displayRecentActivities(defaultActivities); +} + +// 활동 타입에 따른 아이콘 반환 +function getActivityIcon(type) { + const icons = { + 'login': 'fa-sign-in-alt', + 'user_create': 'fa-user-plus', + 'user_update': 'fa-user-edit', + 'user_delete': 'fa-user-minus', + 'system': 'fa-cog', + 'database': 'fa-database', + 'backup': 'fa-download', + 'error': 'fa-exclamation-triangle' + }; + + return icons[type] || 'fa-info-circle'; +} + +// 시간 포맷팅 (몇 분 전, 몇 시간 전 등) +function formatTimeAgo(dateString) { + const now = new Date(); + const date = new Date(dateString); + const diffInSeconds = Math.floor((now - date) / 1000); + + if (diffInSeconds < 60) { + return '방금 전'; + } else if (diffInSeconds < 3600) { + return `${Math.floor(diffInSeconds / 60)}분 전`; + } else if (diffInSeconds < 86400) { + return `${Math.floor(diffInSeconds / 3600)}시간 전`; + } else { + return `${Math.floor(diffInSeconds / 86400)}일 전`; + } +} + +// 시스템 상태 새로고침 +async function refreshSystemStatus() { + try { + await loadSystemStatus(); + await loadUserStats(); + } catch (error) { + console.error('시스템 상태 새로고침 오류:', error); + } +} + +// Open account management +function openAccountManagement() { + console.log('🎯 Account management button clicked'); + const modal = document.getElementById('account-modal'); + const content = document.getElementById('account-management-content'); + + console.log('Modal element:', modal); + console.log('Content element:', content); + + if (modal && content) { + console.log('✅ Modal and content elements found, loading content...'); + // Load account management content + loadAccountManagementContent(content); + modal.style.display = 'block'; + console.log('✅ Modal displayed'); + } else { + console.error('❌ Modal or content element not found'); + } +} + +// 계정 관리 컨텐츠 로드 +async function loadAccountManagementContent(container) { + try { + container.innerHTML = ` +
+ 로딩 중... +
+ `; + + // 사용자 목록 로드 + const response = await apiRequest('/api/system/users', 'GET'); + + if (response.success) { + displayAccountManagement(container, response.data); + } else { + throw new Error(response.error || '사용자 목록을 불러올 수 없습니다.'); + } + } catch (error) { + console.error('계정 관리 컨텐츠 로드 오류:', error); + container.innerHTML = ` +
+ +

계정 정보를 불러오는 중 오류가 발생했습니다.

+ +
+ `; + } +} + +// 계정 관리 화면 표시 +function displayAccountManagement(container, users) { + const html = ` + + `; + + container.innerHTML = html; + systemData.users = users; +} + +// 사용자 테이블 행 생성 +function generateUsersTableRows(users) { + if (!users || users.length === 0) { + return '등록된 사용자가 없습니다.'; + } + + return users.map(user => ` + + ${user.user_id} + ${user.username} + ${user.name || '-'} + + + ${getRoleDisplayName(user.role)} + + + + + ${user.is_active ? '활성' : '비활성'} + + + ${user.last_login_at ? formatDate(user.last_login_at) : '없음'} + + + + + + `).join(''); +} + +// 권한 표시명 반환 +function getRoleDisplayName(role) { + const roleNames = { + 'system': '시스템', + 'admin': '관리자', + 'leader': '그룹장', + 'user': '사용자' + }; + return roleNames[role] || role; +} + +// 날짜 포맷팅 +function formatDate(dateString) { + if (!dateString) return '-'; + const date = new Date(dateString); + return date.toLocaleString('ko-KR'); +} + +// 시스템 로그 열기 +function openSystemLogs() { + console.log('시스템 로그 버튼 클릭됨'); + const modal = document.getElementById('account-modal'); + const content = document.getElementById('account-management-content'); + + if (modal && content) { + loadSystemLogsContent(content); + modal.style.display = 'block'; + } +} + +// 시스템 로그 컨텐츠 로드 +async function loadSystemLogsContent(container) { + try { + container.innerHTML = ` +
+

시스템 로그

+
+ + + +
+
+
+ 로그 로딩 중... +
+
+
+ `; + + // 로그 데이터 로드 + await loadLogsData(); + + } catch (error) { + console.error('시스템 로그 로드 오류:', error); + container.innerHTML = ` +
+ +

시스템 로그를 불러오는 중 오류가 발생했습니다.

+
+ `; + } +} + +// 로그 데이터 로드 +async function loadLogsData() { + try { + const response = await apiRequest('/api/system/logs/activity', 'GET'); + const logsContainer = document.querySelector('.logs-container'); + + if (response.success && response.data) { + displayLogs(response.data, logsContainer); + } else { + logsContainer.innerHTML = '

로그 데이터가 없습니다.

'; + } + } catch (error) { + console.error('로그 데이터 로드 오류:', error); + document.querySelector('.logs-container').innerHTML = '

로그 데이터를 불러올 수 없습니다.

'; + } +} + +// 로그 표시 +function displayLogs(logs, container) { + if (!logs || logs.length === 0) { + container.innerHTML = '

표시할 로그가 없습니다.

'; + return; + } + + const html = ` + + + + + + + + + + + ${logs.map(log => ` + + + + + + + `).join('')} + +
시간유형사용자내용
${formatDate(log.created_at)}${log.type}${log.username || '-'}${log.description}
+ `; + + container.innerHTML = html; +} + +// 로그 필터링 +function filterLogs() { + console.log('로그 필터링 실행'); + // 실제 구현은 추후 추가 + showNotification('로그 필터링 기능은 개발 중입니다.', 'info'); +} + +// 데이터베이스 관리 열기 +function openDatabaseManagement() { + console.log('데이터베이스 관리 버튼 클릭됨'); + showNotification('데이터베이스 관리 기능은 개발 중입니다.', 'info'); +} + +// 시스템 설정 열기 +function openSystemSettings() { + console.log('시스템 설정 버튼 클릭됨'); + showNotification('시스템 설정 기능은 개발 중입니다.', 'info'); +} + +// 백업 관리 열기 +function openBackupManagement() { + console.log('백업 관리 버튼 클릭됨'); + showNotification('백업 관리 기능은 개발 중입니다.', 'info'); +} + +// 모니터링 열기 +function openMonitoring() { + console.log('모니터링 버튼 클릭됨'); + showNotification('모니터링 기능은 개발 중입니다.', 'info'); +} + +// 모달 닫기 +function closeModal(modalId) { + const modal = document.getElementById(modalId); + if (modal) { + modal.style.display = 'none'; + } +} + +// 로그아웃 +function logout() { + if (confirm('로그아웃 하시겠습니까?')) { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + window.location.href = '/'; + } +} + +// 알림 표시 +function showNotification(message, type = 'info') { + // 간단한 알림 표시 (나중에 토스트 라이브러리로 교체 가능) + const notification = document.createElement('div'); + notification.className = `notification notification-${type}`; + notification.textContent = message; + + document.body.appendChild(notification); + + setTimeout(() => { + notification.remove(); + }, 5000); +} + +// 사용자 편집 +async function editUser(userId) { + try { + // 사용자 정보 가져오기 + const response = await apiRequest(`/api/system/users`, 'GET'); + if (!response.success) { + throw new Error('사용자 정보를 가져올 수 없습니다.'); + } + + const user = response.data.find(u => u.user_id === userId); + if (!user) { + throw new Error('해당 사용자를 찾을 수 없습니다.'); + } + + // 편집 폼 표시 + showUserEditForm(user); + + } catch (error) { + console.error('사용자 편집 오류:', error); + showNotification('사용자 정보를 불러오는 중 오류가 발생했습니다.', 'error'); + } +} + +// 사용자 편집 폼 표시 +function showUserEditForm(user) { + const formHtml = ` +
+

사용자 정보 수정

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ `; + + const container = document.getElementById('account-management-content'); + container.innerHTML = formHtml; + + // 폼 제출 이벤트 리스너 + document.getElementById('edit-user-form').addEventListener('submit', async (e) => { + e.preventDefault(); + await updateUser(user.user_id); + }); +} + +// 사용자 정보 업데이트 +async function updateUser(userId) { + try { + const formData = { + name: document.getElementById('edit-name').value, + email: document.getElementById('edit-email').value || null, + role: document.getElementById('edit-role').value, + access_level: document.getElementById('edit-role').value, + is_active: parseInt(document.getElementById('edit-is-active').value), + worker_id: document.getElementById('edit-worker-id').value || null + }; + + const response = await apiRequest(`/api/system/users/${userId}`, 'PUT', formData); + + if (response.success) { + showNotification('사용자 정보가 성공적으로 업데이트되었습니다.', 'success'); + closeModal('account-modal'); + // 계정 관리 다시 로드 + setTimeout(() => openAccountManagement(), 500); + } else { + throw new Error(response.error || '업데이트에 실패했습니다.'); + } + + } catch (error) { + console.error('사용자 업데이트 오류:', error); + showNotification('사용자 정보 업데이트 중 오류가 발생했습니다.', 'error'); + } +} + +// 사용자 삭제 +async function deleteUser(userId) { + try { + // 사용자 정보 가져오기 + const response = await apiRequest(`/api/system/users`, 'GET'); + if (!response.success) { + throw new Error('사용자 정보를 가져올 수 없습니다.'); + } + + const user = response.data.find(u => u.user_id === userId); + if (!user) { + throw new Error('해당 사용자를 찾을 수 없습니다.'); + } + + // 삭제 확인 + if (!confirm(`정말로 사용자 '${user.username}'를 삭제하시겠습니까?\n\n이 작업은 되돌릴 수 없습니다.`)) { + return; + } + + // 사용자 삭제 요청 + const deleteResponse = await apiRequest(`/api/system/users/${userId}`, 'DELETE'); + + if (deleteResponse.success) { + showNotification('사용자가 성공적으로 삭제되었습니다.', 'success'); + // 계정 관리 다시 로드 + setTimeout(() => { + const container = document.getElementById('account-management-content'); + if (container) { + loadAccountManagementContent(container); + } + }, 500); + } else { + throw new Error(deleteResponse.error || '삭제에 실패했습니다.'); + } + + } catch (error) { + console.error('사용자 삭제 오류:', error); + showNotification('사용자 삭제 중 오류가 발생했습니다.', 'error'); + } +} + +// 새 사용자 생성 폼 열기 +function openCreateUserForm() { + const formHtml = ` +
+

새 사용자 생성

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ `; + + const container = document.getElementById('account-management-content'); + container.innerHTML = formHtml; + + // 폼 제출 이벤트 리스너 + document.getElementById('create-user-form').addEventListener('submit', async (e) => { + e.preventDefault(); + await createUser(); + }); +} + +// 새 사용자 생성 +async function createUser() { + try { + const formData = { + username: document.getElementById('create-username').value, + password: document.getElementById('create-password').value, + name: document.getElementById('create-name').value, + email: document.getElementById('create-email').value || null, + role: document.getElementById('create-role').value, + access_level: document.getElementById('create-role').value, + worker_id: document.getElementById('create-worker-id').value || null + }; + + const response = await apiRequest('/api/system/users', 'POST', formData); + + if (response.success) { + showNotification('새 사용자가 성공적으로 생성되었습니다.', 'success'); + // 계정 관리 목록으로 돌아가기 + setTimeout(() => { + const container = document.getElementById('account-management-content'); + loadAccountManagementContent(container); + }, 500); + } else { + throw new Error(response.error || '사용자 생성에 실패했습니다.'); + } + + } catch (error) { + console.error('사용자 생성 오류:', error); + showNotification('사용자 생성 중 오류가 발생했습니다.', 'error'); + } +} + +// 사용자 필터링 +function filterUsers() { + const searchTerm = document.getElementById('user-search').value.toLowerCase(); + const roleFilter = document.getElementById('role-filter').value; + const rows = document.querySelectorAll('#users-tbody tr'); + + rows.forEach(row => { + const username = row.cells[1].textContent.toLowerCase(); + const name = row.cells[2].textContent.toLowerCase(); + const role = row.querySelector('.role-badge').textContent.toLowerCase(); + + const matchesSearch = username.includes(searchTerm) || name.includes(searchTerm); + const matchesRole = !roleFilter || role.includes(roleFilter); + + row.style.display = matchesSearch && matchesRole ? '' : 'none'; + }); +} + +// 모달 관련 함수들만 전역으로 노출 (동적으로 생성되는 HTML에서 사용) +window.closeModal = closeModal; +window.editUser = editUser; +window.deleteUser = deleteUser; +window.openCreateUserForm = openCreateUserForm; +window.filterUsers = filterUsers; +window.filterLogs = filterLogs; + +// 테스트용 전역 함수 +window.testFunction = function() { + console.log('🧪 테스트 함수 호출됨!'); + alert('테스트 함수가 정상적으로 작동합니다!'); +}; + +console.log('🌐 전역 함수들 노출 완료'); + +// 모달 외부 클릭 시 닫기 +window.onclick = function(event) { + const modals = document.querySelectorAll('.modal'); + modals.forEach(modal => { + if (event.target === modal) { + modal.style.display = 'none'; + } + }); +}; diff --git a/deploy/tkfb-package/web-ui/js/task-management.js b/deploy/tkfb-package/web-ui/js/task-management.js new file mode 100644 index 0000000..917ceb9 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/task-management.js @@ -0,0 +1,508 @@ +// task-management.js - 작업 관리 페이지 JavaScript + +// 전역 변수 +let workTypes = []; // 공정 목록 +let tasks = []; // 작업 목록 +let currentWorkTypeId = ''; // 현재 선택된 공정 ID +let currentEditingTask = null; + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', async () => { + console.log('📋 작업 관리 페이지 초기화'); + + // API 함수가 로드될 때까지 대기 + let retryCount = 0; + while (!window.apiCall && retryCount < 50) { + await new Promise(resolve => setTimeout(resolve, 100)); + retryCount++; + } + + if (!window.apiCall) { + showToast('시스템을 초기화할 수 없습니다. 페이지를 새로고침해주세요.', 'error'); + return; + } + + await loadAllData(); +}); + +// 전체 데이터 로드 +async function loadAllData() { + try { + // 공정 목록 로드 (work_types 조회 - 코드 관리 API 사용) + await loadWorkTypes(); + // 작업 목록 로드 + await loadTasks(); + } catch (error) { + console.error('❌ 데이터 로드 오류:', error); + showToast('데이터를 불러오는 중 오류가 발생했습니다.', 'error'); + } +} +window.loadAllData = loadAllData; + +// 공정 목록 로드 +async function loadWorkTypes() { + try { + // 작업 유형(공정) 목록 조회 + const response = await window.apiCall('/daily-work-reports/work-types'); + + if (response && response.success) { + workTypes = response.data || []; + } else { + workTypes = []; + } + + console.log('✅ 공정 목록 로드:', workTypes.length + '개'); + renderWorkTypeTabs(); + populateWorkTypeSelect(); + } catch (error) { + console.error('❌ 공정 목록 조회 오류:', error); + // API 오류 시에도 빈 배열로 처리 + workTypes = []; + renderWorkTypeTabs(); + } +} + +// 작업 목록 로드 +async function loadTasks() { + try { + const response = await window.apiCall('/tasks'); + + if (response && response.success) { + tasks = response.data || []; + console.log('✅ 작업 목록 로드:', tasks.length + '개'); + } else { + tasks = []; + } + + renderTasks(); + updateStatistics(); + } catch (error) { + console.error('❌ 작업 목록 조회 오류:', error); + showToast('작업 목록을 불러오는 중 오류가 발생했습니다.', 'error'); + tasks = []; + renderTasks(); + } +} + +// 공정 탭 렌더링 +function renderWorkTypeTabs() { + const tabsContainer = document.getElementById('workTypeTabs'); + + let tabsHtml = ` + + `; + + workTypes.forEach(workType => { + const count = tasks.filter(t => t.work_type_id === workType.id).length; + const isActive = currentWorkTypeId === workType.id; + + const safeId = parseInt(workType.id) || 0; + tabsHtml += ` + + `; + }); + + tabsContainer.innerHTML = tabsHtml; +} + +// 공정 전환 +function switchWorkType(workTypeId) { + currentWorkTypeId = workTypeId === '' ? '' : parseInt(workTypeId); + renderWorkTypeTabs(); + renderTasks(); + updateStatistics(); +} +window.switchWorkType = switchWorkType; + +// 작업 목록 렌더링 +function renderTasks() { + const grid = document.getElementById('taskGrid'); + + // 현재 선택된 공정으로 필터링 + let filteredTasks = tasks; + if (currentWorkTypeId !== '') { + filteredTasks = tasks.filter(t => t.work_type_id === currentWorkTypeId); + } + + if (filteredTasks.length === 0) { + grid.innerHTML = ` +
+
📋
+

등록된 작업이 없습니다

+

"작업 추가" 버튼을 눌러 새로운 작업을 등록하세요

+
+ `; + return; + } + + grid.innerHTML = filteredTasks.map(task => createTaskCard(task)).join(''); +} + +// 작업 카드 생성 +function createTaskCard(task) { + const statusBadge = task.is_active + ? '활성' + : '비활성'; + const safeTaskId = parseInt(task.task_id) || 0; + + return ` +
+
+

${escapeHtml(task.task_name)}

+ ${statusBadge} +
+ +
+
+ 소속 공정 + ${escapeHtml(task.work_type_name || '-')} +
+ ${task.category ? ` +
+ 카테고리 + ${escapeHtml(task.category)} +
+ ` : ''} +
+ + ${task.description ? ` +
+ ${escapeHtml(task.description)} +
+ ` : ''} + +
+ 등록: ${escapeHtml(formatDate(task.created_at))} +
+
+ `; +} + +// 통계 업데이트 +function updateStatistics() { + let filteredTasks = tasks; + if (currentWorkTypeId !== '') { + filteredTasks = tasks.filter(t => t.work_type_id === currentWorkTypeId); + } + + const activeCount = filteredTasks.filter(t => t.is_active).length; + + document.getElementById('totalCount').textContent = filteredTasks.length; + document.getElementById('activeCount').textContent = activeCount; +} + +// 새로고침 +function refreshTasks() { + loadAllData(); + showToast('데이터를 새로고침했습니다.', 'success'); +} +window.refreshTasks = refreshTasks; + +// ==================== 작업 모달 ==================== + +// 작업 모달 열기 (신규) +function openTaskModal() { + currentEditingTask = null; + document.getElementById('taskModalTitle').textContent = '작업 추가'; + document.getElementById('taskForm').reset(); + document.getElementById('taskId').value = ''; + document.getElementById('taskIsActive').checked = true; + + // 공정 선택 드롭다운 채우기 + populateWorkTypeSelect(); + + // 현재 선택된 공정이 있으면 자동 선택 + if (currentWorkTypeId !== '') { + document.getElementById('taskWorkTypeId').value = currentWorkTypeId; + } + + document.getElementById('deleteTaskBtn').style.display = 'none'; + document.getElementById('taskModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; +} +window.openTaskModal = openTaskModal; + +// 작업 편집 +async function editTask(taskId) { + try { + const response = await window.apiCall(`/tasks/${taskId}`); + + if (response && response.success) { + currentEditingTask = response.data; + + document.getElementById('taskModalTitle').textContent = '작업 수정'; + document.getElementById('taskId').value = currentEditingTask.task_id; + document.getElementById('taskWorkTypeId').value = currentEditingTask.work_type_id || ''; + document.getElementById('taskName').value = currentEditingTask.task_name; + document.getElementById('taskDescription').value = currentEditingTask.description || ''; + document.getElementById('taskIsActive').checked = currentEditingTask.is_active; + + document.getElementById('deleteTaskBtn').style.display = 'block'; + document.getElementById('taskModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; + } + } catch (error) { + console.error('❌ 작업 조회 오류:', error); + showToast('작업 정보를 불러올 수 없습니다.', 'error'); + } +} +window.editTask = editTask; + +// 작업 모달 닫기 +function closeTaskModal() { + document.getElementById('taskModal').style.display = 'none'; + document.body.style.overflow = 'auto'; + currentEditingTask = null; +} +window.closeTaskModal = closeTaskModal; + +// 공정 선택 드롭다운 채우기 +function populateWorkTypeSelect() { + const select = document.getElementById('taskWorkTypeId'); + + select.innerHTML = '' + + workTypes.map(wt => ` + + `).join(''); +} + +// 작업 저장 +async function saveTask() { + const taskId = document.getElementById('taskId').value; + const taskData = { + work_type_id: parseInt(document.getElementById('taskWorkTypeId').value) || null, + task_name: document.getElementById('taskName').value.trim(), + description: document.getElementById('taskDescription').value.trim() || null, + is_active: document.getElementById('taskIsActive').checked ? 1 : 0 + }; + + if (!taskData.task_name) { + showToast('작업명을 입력해주세요.', 'error'); + return; + } + + try { + let response; + if (taskId) { + // 수정 + response = await window.apiCall(`/tasks/${taskId}`, 'PUT', taskData); + } else { + // 신규 + response = await window.apiCall('/tasks', 'POST', taskData); + } + + if (response && response.success) { + showToast(taskId ? '작업이 수정되었습니다.' : '작업이 추가되었습니다.', 'success'); + closeTaskModal(); + await loadAllData(); + } else { + throw new Error(response.message || '저장에 실패했습니다.'); + } + } catch (error) { + console.error('❌ 작업 저장 오류:', error); + showToast('작업 저장 중 오류가 발생했습니다.', 'error'); + } +} +window.saveTask = saveTask; + +// 작업 삭제 +async function deleteTask() { + if (!currentEditingTask) return; + + if (!confirm(`"${currentEditingTask.task_name}" 작업을 삭제하시겠습니까?`)) { + return; + } + + try { + const response = await window.apiCall(`/tasks/${currentEditingTask.task_id}`, 'DELETE'); + + if (response && response.success) { + showToast('작업이 삭제되었습니다.', 'success'); + closeTaskModal(); + await loadAllData(); + } else { + throw new Error(response.message || '삭제에 실패했습니다.'); + } + } catch (error) { + console.error('❌ 작업 삭제 오류:', error); + showToast('작업 삭제 중 오류가 발생했습니다.', 'error'); + } +} +window.deleteTask = deleteTask; + +// ==================== 유틸리티 ==================== + +// 날짜 포맷 +function formatDate(dateString) { + if (!dateString) return '-'; + const date = new Date(dateString); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }); +} + +// 토스트 알림 +function showToast(message, type = 'info') { + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + toast.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + padding: 1rem 1.5rem; + background: ${type === 'success' ? '#10b981' : type === 'error' ? '#ef4444' : '#3b82f6'}; + color: white; + border-radius: 0.5rem; + box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); + z-index: 10000; + animation: slideIn 0.3s ease-out; + `; + + document.body.appendChild(toast); + + setTimeout(() => { + toast.style.animation = 'slideOut 0.3s ease-out'; + setTimeout(() => toast.remove(), 300); + }, 3000); +} + +// ==================== 공정 관리 ==================== + +let currentEditingWorkType = null; + +// 공정 모달 열기 (신규) +function openWorkTypeModal() { + currentEditingWorkType = null; + document.getElementById('workTypeModalTitle').textContent = '공정 추가'; + document.getElementById('workTypeId').value = ''; + document.getElementById('workTypeName').value = ''; + document.getElementById('workTypeCategory').value = ''; + document.getElementById('workTypeDescription').value = ''; + document.getElementById('deleteWorkTypeBtn').style.display = 'none'; + + document.getElementById('workTypeModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; +} +window.openWorkTypeModal = openWorkTypeModal; + +// 공정 수정 모달 열기 +async function editWorkType(workTypeId) { + try { + const workType = workTypes.find(wt => wt.id === workTypeId); + if (!workType) { + showToast('공정 정보를 찾을 수 없습니다.', 'error'); + return; + } + + currentEditingWorkType = workType; + document.getElementById('workTypeModalTitle').textContent = '공정 수정'; + document.getElementById('workTypeId').value = workType.id; + document.getElementById('workTypeName').value = workType.name || ''; + document.getElementById('workTypeCategory').value = workType.category || ''; + document.getElementById('workTypeDescription').value = workType.description || ''; + document.getElementById('deleteWorkTypeBtn').style.display = 'block'; + + document.getElementById('workTypeModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; + } catch (error) { + console.error('❌ 공정 조회 오류:', error); + showToast('공정 정보를 불러올 수 없습니다.', 'error'); + } +} +window.editWorkType = editWorkType; + +// 공정 모달 닫기 +function closeWorkTypeModal() { + document.getElementById('workTypeModal').style.display = 'none'; + document.body.style.overflow = 'auto'; + currentEditingWorkType = null; +} +window.closeWorkTypeModal = closeWorkTypeModal; + +// 공정 저장 +async function saveWorkType() { + const workTypeId = document.getElementById('workTypeId').value; + const workTypeData = { + name: document.getElementById('workTypeName').value.trim(), + category: document.getElementById('workTypeCategory').value.trim() || null, + description: document.getElementById('workTypeDescription').value.trim() || null + }; + + if (!workTypeData.name) { + showToast('공정명을 입력해주세요.', 'error'); + return; + } + + try { + let response; + if (workTypeId) { + // 수정 + response = await window.apiCall(`/daily-work-reports/work-types/${workTypeId}`, 'PUT', workTypeData); + } else { + // 신규 + response = await window.apiCall('/daily-work-reports/work-types', 'POST', workTypeData); + } + + if (response && response.success) { + showToast(workTypeId ? '공정이 수정되었습니다.' : '공정이 추가되었습니다.', 'success'); + closeWorkTypeModal(); + await loadAllData(); + } else { + throw new Error(response.message || '저장에 실패했습니다.'); + } + } catch (error) { + console.error('❌ 공정 저장 오류:', error); + showToast('공정 저장 중 오류가 발생했습니다.', 'error'); + } +} +window.saveWorkType = saveWorkType; + +// 공정 삭제 +async function deleteWorkType() { + if (!currentEditingWorkType) return; + + // 이 공정에 속한 작업이 있는지 확인 + const relatedTasks = tasks.filter(t => t.work_type_id === currentEditingWorkType.id); + if (relatedTasks.length > 0) { + showToast(`이 공정에 ${relatedTasks.length}개의 작업이 연결되어 있어 삭제할 수 없습니다.`, 'error'); + return; + } + + if (!confirm(`"${currentEditingWorkType.name}" 공정을 삭제하시겠습니까?`)) { + return; + } + + try { + const response = await window.apiCall(`/daily-work-reports/work-types/${currentEditingWorkType.id}`, 'DELETE'); + + if (response && response.success) { + showToast('공정이 삭제되었습니다.', 'success'); + closeWorkTypeModal(); + await loadAllData(); + } else { + throw new Error(response.message || '삭제에 실패했습니다.'); + } + } catch (error) { + console.error('❌ 공정 삭제 오류:', error); + showToast('공정 삭제 중 오류가 발생했습니다.', 'error'); + } +} +window.deleteWorkType = deleteWorkType; diff --git a/deploy/tkfb-package/web-ui/js/tbm.js b/deploy/tkfb-package/web-ui/js/tbm.js new file mode 100644 index 0000000..c0befbb --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/tbm.js @@ -0,0 +1,2570 @@ +// tbm.js - TBM 관리 페이지 JavaScript + +// 전역 변수 +let allSessions = []; +let todaySessions = []; +let allWorkers = []; +let allProjects = []; +let allWorkTypes = []; +let allTasks = []; +let allSafetyChecks = []; +let allWorkplaces = []; +let allWorkplaceCategories = []; +let currentUser = null; +let currentSessionId = null; +let selectedWorkers = new Set(); +let currentTab = 'tbm-input'; + +// 새로운 TBM 입력 방식 관련 변수 +let workerTaskList = []; // [{worker_id, worker_name, job_type, tasks: [{task_line_id, project_id, ...}]}] +let selectedWorkersInModal = new Set(); // 모달에서 선택된 작업자 ID 세트 +let currentEditingTaskLine = null; // 현재 편집 중인 작업 라인 정보 {workerIndex, taskIndex} +let selectedCategory = null; +let selectedWorkplace = null; +let selectedCategoryName = ''; +let selectedWorkplaceName = ''; +let isBulkMode = false; // 일괄 설정 모드인지 여부 +let bulkSelectedWorkers = new Set(); // 일괄 설정에서 선택된 작업자 인덱스 + +// TBM 관리 탭용 변수 +let loadedDaysCount = 7; // 처음에 로드할 일수 +let dateGroupedSessions = {}; // 날짜별로 그룹화된 세션 +let allLoadedSessions = []; // 전체 로드된 세션 + +// ==================== 유틸리티 함수 ==================== + +/** + * 서울 시간대(Asia/Seoul, UTC+9) 기준 오늘 날짜를 YYYY-MM-DD 형식으로 반환 + */ +function getTodayKST() { + const now = new Date(); + // 한국 시간대로 변환 (UTC+9) + const kstOffset = 9 * 60; // 9시간을 분 단위로 + const utc = now.getTime() + (now.getTimezoneOffset() * 60000); // UTC 시간 + const kstTime = new Date(utc + (kstOffset * 60000)); // KST 시간 + + const year = kstTime.getFullYear(); + const month = String(kstTime.getMonth() + 1).padStart(2, '0'); + const day = String(kstTime.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; +} + +/** + * ISO 날짜 문자열을 YYYY-MM-DD 형식으로 변환 + * @param {string} dateString - ISO 형식 날짜 문자열 또는 YYYY-MM-DD 형식 + * @returns {string} YYYY-MM-DD 형식 날짜 + */ +function formatDate(dateString) { + if (!dateString) return ''; + + // 이미 YYYY-MM-DD 형식이면 그대로 반환 + if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) { + return dateString; + } + + // ISO 형식 또는 다른 형식이면 변환 + const date = new Date(dateString); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; +} + +// ==================== 페이지 초기화 ==================== + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', async () => { + console.log('🛠️ TBM 관리 페이지 초기화'); + + // API 함수가 로드될 때까지 대기 + let retryCount = 0; + while (!window.apiCall && retryCount < 50) { + await new Promise(resolve => setTimeout(resolve, 100)); + retryCount++; + } + + if (!window.apiCall) { + showToast('시스템을 초기화할 수 없습니다. 페이지를 새로고침해주세요.', 'error'); + return; + } + + // 오늘 날짜 설정 (서울 시간대 기준) + const today = getTodayKST(); + const tbmDateEl = document.getElementById('tbmDate'); + const sessionDateEl = document.getElementById('sessionDate'); + if (tbmDateEl) tbmDateEl.value = today; + if (sessionDateEl) sessionDateEl.value = today; + + // 이벤트 리스너 설정 + setupEventListeners(); + + // 초기 데이터 로드 + await loadInitialData(); + await loadTodayOnlyTbm(); +}); + +// 이벤트 리스너 설정 +function setupEventListeners() { + // 날짜 선택기 제거됨 - 날짜별 그룹 뷰 사용 +} + +// 초기 데이터 로드 +async function loadInitialData() { + try { + // 현재 로그인한 사용자 정보 가져오기 + const userInfo = JSON.parse(localStorage.getItem('user') || '{}'); + currentUser = userInfo; + console.log('👤 로그인 사용자:', currentUser, 'worker_id:', currentUser?.worker_id); + + // 작업자 목록 로드 (생산팀 소속만) + const workersResponse = await window.apiCall('/workers?limit=1000&department_id=1'); + if (workersResponse) { + allWorkers = Array.isArray(workersResponse) ? workersResponse : (workersResponse.data || []); + // 활성 상태인 작업자만 필터링 + allWorkers = allWorkers.filter(w => w.status === 'active' && w.employment_status === 'employed'); + console.log('✅ 작업자 목록 로드:', allWorkers.length + '명'); + } + + // 프로젝트 목록 로드 (활성 프로젝트만) + const projectsResponse = await window.apiCall('/projects?is_active=1'); + if (projectsResponse) { + const projects = Array.isArray(projectsResponse) ? projectsResponse : (projectsResponse.data || []); + // 활성 프로젝트만 필터링 (is_active가 1 또는 true인 경우) + allProjects = projects.filter(p => p.is_active === 1 || p.is_active === true || p.is_active === '1'); + console.log('✅ 프로젝트 목록 로드:', allProjects.length + '개 (활성)'); + populateProjectSelect(); + } + + // 안전 체크리스트 로드 + const safetyResponse = await window.apiCall('/tbm/safety-checks'); + if (safetyResponse && safetyResponse.success) { + allSafetyChecks = safetyResponse.data; + console.log('✅ 안전 체크리스트 로드:', allSafetyChecks.length + '개'); + } + + // 공정(Work Types) 목록 로드 + const workTypesResponse = await window.apiCall('/daily-work-reports/work-types'); + if (workTypesResponse && workTypesResponse.success) { + allWorkTypes = workTypesResponse.data || []; + console.log('✅ 공정 목록 로드:', allWorkTypes.length + '개'); + } + + // 작업(Tasks) 목록 로드 + const tasksResponse = await window.apiCall('/tasks/active/list'); + if (tasksResponse && tasksResponse.success) { + allTasks = tasksResponse.data || []; + console.log('✅ 작업 목록 로드:', allTasks.length + '개'); + } + + // 작업장 목록 로드 + const workplacesResponse = await window.apiCall('/workplaces?is_active=true'); + if (workplacesResponse && workplacesResponse.success) { + allWorkplaces = workplacesResponse.data || []; + console.log('✅ 작업장 목록 로드:', allWorkplaces.length + '개'); + } + + // 작업장 카테고리 로드 + const categoriesResponse = await window.apiCall('/workplaces/categories/active/list'); + if (categoriesResponse && categoriesResponse.success) { + allWorkplaceCategories = categoriesResponse.data || []; + console.log('✅ 작업장 카테고리 로드:', allWorkplaceCategories.length + '개'); + } + + } catch (error) { + console.error('❌ 초기 데이터 로드 오류:', error); + showToast('데이터를 불러오는 중 오류가 발생했습니다.', 'error'); + } +} + +// ==================== 탭 전환 ==================== + +// 탭 전환 +function switchTbmTab(tabName) { + currentTab = tabName; + + // 탭 버튼 활성화 상태 변경 + document.querySelectorAll('.tbm-tab-btn').forEach(btn => { + if (btn.dataset.tab === tabName) { + btn.classList.add('active'); + } else { + btn.classList.remove('active'); + } + }); + + // 탭 컨텐츠 표시 변경 + document.querySelectorAll('.tbm-tab-content').forEach(content => { + content.classList.remove('active'); + }); + document.getElementById(`${tabName}-tab`).classList.add('active'); + + // 탭에 따라 데이터 로드 + if (tabName === 'tbm-input') { + loadTodayOnlyTbm(); + } else if (tabName === 'tbm-manage') { + loadRecentTbmGroupedByDate(); + } +} +window.switchTbmTab = switchTbmTab; + +// ==================== TBM 입력 탭 ==================== + +// 오늘의 TBM만 로드 (TBM 입력 탭용) +async function loadTodayOnlyTbm() { + const today = getTodayKST(); + + try { + const response = await window.apiCall(`/tbm/sessions/date/${today}`); + + if (response && response.success) { + todaySessions = response.data || []; + displayTodayTbmSessions(); + } else { + todaySessions = []; + displayTodayTbmSessions(); + } + } catch (error) { + console.error('❌ 오늘 TBM 조회 오류:', error); + showToast('오늘 TBM을 불러오는 중 오류가 발생했습니다.', 'error'); + todaySessions = []; + displayTodayTbmSessions(); + } +} +window.loadTodayOnlyTbm = loadTodayOnlyTbm; + +// 오늘의 TBM 세션 표시 +function displayTodayTbmSessions() { + const grid = document.getElementById('todayTbmGrid'); + const emptyState = document.getElementById('todayEmptyState'); + const todayTotalEl = document.getElementById('todayTotalSessions'); + const todayCompletedEl = document.getElementById('todayCompletedSessions'); + const todayActiveEl = document.getElementById('todayActiveSessions'); + + if (todaySessions.length === 0) { + grid.innerHTML = ''; + emptyState.style.display = 'flex'; + todayTotalEl.textContent = '0'; + todayCompletedEl.textContent = '0'; + todayActiveEl.textContent = '0'; + return; + } + + emptyState.style.display = 'none'; + + const completedCount = todaySessions.filter(s => s.status === 'completed').length; + const activeCount = todaySessions.filter(s => s.status === 'draft').length; + + todayTotalEl.textContent = todaySessions.length; + todayCompletedEl.textContent = completedCount; + todayActiveEl.textContent = activeCount; + + grid.innerHTML = todaySessions.map(session => createSessionCard(session)).join(''); +} + +// ==================== TBM 관리 탭 ==================== + +// 오늘 TBM 로드 (TBM 관리 탭용) - 레거시 호환 +async function loadTodayTbm() { + await loadRecentTbmGroupedByDate(); +} +window.loadTodayTbm = loadTodayTbm; + +// 전체 TBM 로드 - 레거시 호환 +async function loadAllTbm() { + loadedDaysCount = 30; // 30일치 로드 + await loadRecentTbmGroupedByDate(); +} +window.loadAllTbm = loadAllTbm; + +// ==================== 날짜별 그룹 TBM 로드 (새 기능) ==================== + +/** + * 사용자가 Admin인지 확인 + */ +function isAdminUser() { + if (!currentUser) return false; + return currentUser.role === 'Admin' || currentUser.role === 'System Admin'; +} + +/** + * 최근 TBM을 날짜별로 그룹화하여 로드 + */ +async function loadRecentTbmGroupedByDate() { + try { + const today = new Date(); + const dates = []; + + // 최근 N일의 날짜 생성 + for (let i = 0; i < loadedDaysCount; i++) { + const date = new Date(today); + date.setDate(date.getDate() - i); + const dateStr = date.toISOString().split('T')[0]; + dates.push(dateStr); + } + + // 각 날짜의 TBM 로드 + dateGroupedSessions = {}; + 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) { + let sessions = response.data; + + // admin이 아니면 본인이 작성한 TBM만 필터링 + if (!isAdminUser()) { + const userId = currentUser?.user_id; + const workerId = currentUser?.worker_id; + sessions = sessions.filter(s => { + return s.created_by === userId || + s.leader_id === workerId || + s.created_by_name === currentUser?.name; + }); + } + + if (sessions.length > 0) { + dateGroupedSessions[date] = sessions; + allLoadedSessions = allLoadedSessions.concat(sessions); + } + } + }); + + // 날짜별 그룹 표시 + displayTbmGroupedByDate(); + + // 뷰 모드 표시 + updateViewModeIndicator(); + + } catch (error) { + console.error('❌ TBM 날짜별 로드 오류:', error); + showToast('TBM을 불러오는 중 오류가 발생했습니다.', 'error'); + dateGroupedSessions = {}; + displayTbmGroupedByDate(); + } +} +window.loadRecentTbmGroupedByDate = loadRecentTbmGroupedByDate; + +/** + * 뷰 모드 표시 업데이트 + */ +function updateViewModeIndicator() { + const indicator = document.getElementById('viewModeIndicator'); + const text = document.getElementById('viewModeText'); + + if (indicator && text) { + if (isAdminUser()) { + indicator.style.display = 'none'; // Admin은 표시 안 함 (전체가 기본) + } else { + indicator.style.display = 'inline-flex'; + text.textContent = '내 TBM'; + } + } +} + +/** + * 날짜별 그룹으로 TBM 표시 + */ +function displayTbmGroupedByDate() { + const container = document.getElementById('tbmDateGroupsContainer'); + const emptyState = document.getElementById('emptyState'); + const totalSessionsEl = document.getElementById('totalSessions'); + const completedSessionsEl = document.getElementById('completedSessions'); + + if (!container) return; + + // 날짜별로 정렬 (최신순) + const sortedDates = Object.keys(dateGroupedSessions).sort((a, b) => new Date(b) - new Date(a)); + + if (sortedDates.length === 0 || allLoadedSessions.length === 0) { + container.innerHTML = ''; + if (emptyState) emptyState.style.display = 'flex'; + if (totalSessionsEl) totalSessionsEl.textContent = '0'; + if (completedSessionsEl) completedSessionsEl.textContent = '0'; + return; + } + + if (emptyState) emptyState.style.display = 'none'; + + // 통계 업데이트 + const completedCount = allLoadedSessions.filter(s => s.status === 'completed').length; + if (totalSessionsEl) totalSessionsEl.textContent = allLoadedSessions.length; + if (completedSessionsEl) completedSessionsEl.textContent = completedCount; + + // 날짜별 그룹 HTML 생성 + const today = getTodayKST(); + const dayNames = ['일', '월', '화', '수', '목', '금', '토']; + + container.innerHTML = sortedDates.map(date => { + const sessions = dateGroupedSessions[date]; + const dateObj = new Date(date + 'T00:00:00'); + const dayName = dayNames[dateObj.getDay()]; + const isToday = date === today; + + // 날짜 포맷팅 (YYYY-MM-DD → MM월 DD일) + const [year, month, day] = date.split('-'); + const displayDate = `${parseInt(month)}월 ${parseInt(day)}일`; + + return ` +
+
+ + ${displayDate} + ${dayName}요일 + ${isToday ? '오늘' : ''} + ${sessions.length}건 +
+
+
+ ${sessions.map(session => createSessionCard(session)).join('')} +
+
+
+ `; + }).join(''); +} + +// 날짜 그룹 토글 +function toggleDateGroup(date) { + const group = document.querySelector(`.tbm-date-group[data-date="${date}"]`); + if (group) { + group.classList.toggle('collapsed'); + } +} +window.toggleDateGroup = toggleDateGroup; + +/** + * 더 많은 날짜 로드 + */ +async function loadMoreTbmDays() { + loadedDaysCount += 7; // 7일씩 추가 + await loadRecentTbmGroupedByDate(); + showToast(`최근 ${loadedDaysCount}일의 TBM을 로드했습니다.`, 'success'); +} +window.loadMoreTbmDays = loadMoreTbmDays; + +// 특정 날짜의 TBM 세션 목록 로드 +async function loadTbmSessionsByDate(date) { + try { + const response = await window.apiCall(`/tbm/sessions/date/${date}`); + + if (response && response.success) { + allSessions = response.data || []; + displayTbmSessions(); + } else { + allSessions = []; + displayTbmSessions(); + } + } catch (error) { + console.error('❌ TBM 세션 조회 오류:', error); + showToast('TBM 세션을 불러오는 중 오류가 발생했습니다.', 'error'); + allSessions = []; + displayTbmSessions(); + } +} + +// TBM 세션 목록 표시 (관리 탭용) - 레거시 호환 (날짜별 그룹 뷰 사용) +function displayTbmSessions() { + // 새 날짜별 그룹 뷰로 리다이렉트 + if (allSessions.length > 0) { + // allSessions를 날짜별로 그룹화 + dateGroupedSessions = {}; + allSessions.forEach(session => { + const date = formatDate(session.session_date); + if (!dateGroupedSessions[date]) { + dateGroupedSessions[date] = []; + } + dateGroupedSessions[date].push(session); + }); + allLoadedSessions = allSessions; + } + displayTbmGroupedByDate(); +} + +// TBM 세션 카드 생성 (공통) +function createSessionCard(session) { + const statusBadge = { + 'draft': '진행중', + 'completed': '완료', + 'cancelled': '취소' + }[session.status] || ''; + + // 작업 책임자 표시 (leader_name이 있으면 표시, 없으면 created_by_name 표시) + const leaderName = escapeHtml(session.leader_name || session.created_by_name || '작업 책임자'); + const leaderRole = escapeHtml(session.leader_name + ? (session.leader_job_type || '작업자') + : '관리자'); + const safeSessionId = parseInt(session.session_id) || 0; + + return ` +
+
+
+
+

+ ${leaderName} + ${leaderRole} +

+
+ ${statusBadge} +
+
+ 📅 + ${escapeHtml(formatDate(session.session_date))} ${session.start_time ? '| ' + escapeHtml(session.start_time) : ''} +
+
+ +
+
+
+ 프로젝트 + ${escapeHtml(session.project_name || '-')} +
+
+ 공정 + ${escapeHtml(session.work_type_name || '-')} +
+
+ 작업장 + ${escapeHtml(session.work_location || '-')} +
+
+ 팀원 + ${parseInt(session.team_member_count) || 0}명 +
+
+
+ + ${session.status === 'draft' ? ` + + ` : ''} +
+ `; +} + +// 새 TBM 모달 열기 +function openNewTbmModal() { + currentSessionId = null; + workerTaskList = []; // 작업자 목록 초기화 + + document.getElementById('modalTitle').innerHTML = '📝 새 TBM 시작'; + document.getElementById('sessionId').value = ''; + document.getElementById('tbmForm').reset(); + + const today = getTodayKST(); + document.getElementById('sessionDate').value = today; + + // 날짜 표시 업데이트 + const [year, month, day] = today.split('-'); + const dayNames = ['일', '월', '화', '수', '목', '금', '토']; + const dateObj = new Date(today); + const dayName = dayNames[dateObj.getDay()]; + const sessionDateDisplay = document.getElementById('sessionDateDisplay'); + if (sessionDateDisplay) { + sessionDateDisplay.textContent = `${year}년 ${parseInt(month)}월 ${parseInt(day)}일 (${dayName})`; + } + + // 입력자 자동 설정 (readonly) + if (currentUser && currentUser.worker_id) { + const worker = allWorkers.find(w => w.worker_id === currentUser.worker_id); + if (worker) { + document.getElementById('leaderName').textContent = worker.worker_name; + document.getElementById('leaderId').value = worker.worker_id; + } + } else if (currentUser && currentUser.name) { + // 관리자: 이름만 표시 + document.getElementById('leaderName').textContent = currentUser.name; + document.getElementById('leaderId').value = ''; + } + + // 작업자 목록 UI 초기화 + renderWorkerTaskList(); + + document.getElementById('tbmModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; +} +window.openNewTbmModal = openNewTbmModal; + +// 입력자 선택 드롭다운 채우기 +function populateLeaderSelect() { + const leaderSelect = document.getElementById('leaderId'); + if (!leaderSelect) return; + + // 로그인한 사용자가 작업자와 연결되어 있는지 확인 + if (currentUser && currentUser.worker_id) { + // 작업자와 연결된 경우: 자동으로 선택하고 비활성화 + const worker = allWorkers.find(w => w.worker_id === currentUser.worker_id); + if (worker) { + const jobTypeText = worker.job_type ? ` (${escapeHtml(worker.job_type)})` : ''; + leaderSelect.innerHTML = ``; + leaderSelect.disabled = true; + console.log('✅ 입력자 자동 설정:', worker.worker_name); + } else { + // 작업자를 찾을 수 없는 경우 + leaderSelect.innerHTML = ''; + leaderSelect.disabled = true; + } + } else { + // 관리자 계정 (worker_id가 없음): 드롭다운으로 선택 가능 + const leaders = allWorkers.filter(w => + w.job_type === 'leader' || w.job_type === '그룹장' || w.job_type === 'admin' + ); + + leaderSelect.innerHTML = '' + + leaders.map(w => { + const jobTypeText = w.job_type ? ` (${escapeHtml(w.job_type)})` : ''; + return ``; + }).join(''); + leaderSelect.disabled = false; + console.log('✅ 관리자: 입력자 선택 가능'); + } +} + +// 프로젝트 선택 드롭다운 채우기 +function populateProjectSelect() { + const projectSelect = document.getElementById('projectId'); + if (!projectSelect) return; + + projectSelect.innerHTML = '' + + allProjects.map(p => ` + + `).join(''); +} + +// 공정(Work Type) 선택 드롭다운 채우기 +function populateWorkTypeSelect() { + const workTypeSelect = document.getElementById('workTypeId'); + if (!workTypeSelect) return; + + workTypeSelect.innerHTML = '' + + allWorkTypes.map(wt => ` + + `).join(''); +} + +// 작업장 선택 드롭다운 채우기 +function populateWorkplaceSelect() { + const workLocationSelect = document.getElementById('workLocation'); + if (!workLocationSelect) return; + + workLocationSelect.innerHTML = '' + + allWorkplaces.map(wp => ` + + `).join(''); +} + +// 작업(Task) 선택 드롭다운 채우기 (공정 선택 시 호출) +function loadTasksByWorkType() { + const workTypeId = document.getElementById('workTypeId').value; + const taskSelect = document.getElementById('taskId'); + + if (!taskSelect) return; + + if (!workTypeId) { + taskSelect.innerHTML = ''; + taskSelect.disabled = true; + return; + } + + // 선택한 공정에 해당하는 작업만 필터링 + const filteredTasks = allTasks.filter(task => + task.work_type_id === parseInt(workTypeId) + ); + + taskSelect.disabled = false; + taskSelect.innerHTML = '' + + filteredTasks.map(task => ` + + `).join(''); + + if (filteredTasks.length === 0) { + taskSelect.innerHTML = ''; + taskSelect.disabled = true; + } +} +window.loadTasksByWorkType = loadTasksByWorkType; + +// TBM 모달 닫기 +function closeTbmModal() { + document.getElementById('tbmModal').style.display = 'none'; + document.body.style.overflow = 'auto'; +} +window.closeTbmModal = closeTbmModal; + +// TBM 세션 저장 (작업자별 상세 정보 포함) +async function saveTbmSession() { + console.log('💾 TBM 저장 시작...'); + + let leaderId = parseInt(document.getElementById('leaderId').value); + + // 관리자 계정인 경우 leader_id를 null로 설정 + if (!leaderId || isNaN(leaderId)) { + if (!currentUser.worker_id) { + console.log('📝 관리자 계정: leader_id를 NULL로 설정'); + leaderId = null; + } else { + console.error('❌ 입력자 설정 오류'); + showToast('입력자 정보가 올바르지 않습니다.', 'error'); + return; + } + } + + const sessionData = { + session_date: document.getElementById('sessionDate').value, + leader_id: leaderId + }; + + console.log('📅 세션 데이터:', sessionData); + console.log('👥 작업자 리스트:', workerTaskList); + console.log('👤 현재 사용자:', currentUser); + + if (!sessionData.session_date) { + console.error('❌ 날짜 누락'); + showToast('TBM 날짜를 확인해주세요.', 'error'); + return; + } + + if (workerTaskList.length === 0) { + console.error('❌ 작업자 리스트가 비어있음'); + showToast('최소 1명 이상의 작업자를 추가해주세요.', 'error'); + return; + } + + // 필수 항목 검증 (공정, 작업, 작업장) + let hasError = false; + for (const workerData of workerTaskList) { + for (const taskLine of workerData.tasks) { + if (!taskLine.work_type_id || !taskLine.task_id || !taskLine.workplace_id) { + showToast(`${workerData.worker_name}의 공정, 작업, 작업장을 모두 선택해주세요.`, 'error'); + hasError = true; + break; + } + } + if (hasError) break; + } + if (hasError) return; + + // 작업자-작업 데이터를 평평하게 변환 + const members = []; + for (const workerData of workerTaskList) { + for (const taskLine of workerData.tasks) { + members.push({ + worker_id: workerData.worker_id, + project_id: taskLine.project_id || null, + work_type_id: taskLine.work_type_id, + task_id: taskLine.task_id, + workplace_category_id: taskLine.workplace_category_id || null, + workplace_id: taskLine.workplace_id, + work_detail: taskLine.work_detail || null, + is_present: taskLine.is_present !== undefined ? taskLine.is_present : true + }); + } + } + + console.log('📤 전송할 팀 데이터:', members); + + try { + const editingSessionId = document.getElementById('sessionId').value; + + if (editingSessionId) { + // 수정 모드: 기존 팀원 삭제 후 재등록 + console.log('📝 TBM 수정 모드:', editingSessionId); + + // 기존 팀원 삭제 + await window.apiCall(`/tbm/sessions/${editingSessionId}/team/clear`, 'DELETE'); + + // 새 팀원 일괄 추가 + const teamResponse = await window.apiCall( + `/tbm/sessions/${editingSessionId}/team/batch`, + 'POST', + { members } + ); + + if (teamResponse && teamResponse.success) { + showToast(`TBM이 수정되었습니다 (작업자 ${workerTaskList.length}명, 작업 ${members.length}건)`, 'success'); + closeTbmModal(); + + // 목록 새로고침 + if (currentTab === 'tbm-input') { + await loadTodayOnlyTbm(); + } else { + await loadTbmSessionsByDate(sessionData.session_date); + } + } else { + throw new Error(teamResponse.message || '팀원 수정에 실패했습니다.'); + } + } else { + // 생성 모드: 새 TBM 세션 생성 + console.log('✨ TBM 생성 모드'); + + const response = await window.apiCall('/tbm/sessions', 'POST', sessionData); + + if (response && response.success) { + const createdSessionId = response.data.session_id; + console.log('✅ TBM 세션 생성 완료:', createdSessionId); + + // 작업자 일괄 추가 + const teamResponse = await window.apiCall( + `/tbm/sessions/${createdSessionId}/team/batch`, + 'POST', + { members } + ); + + if (teamResponse && teamResponse.success) { + showToast(`TBM이 생성되었습니다 (작업자 ${workerTaskList.length}명, 작업 ${members.length}건)`, 'success'); + closeTbmModal(); + + // 목록 새로고침 + if (currentTab === 'tbm-input') { + await loadTodayOnlyTbm(); + } else { + await loadTbmSessionsByDate(sessionData.session_date); + } + } else { + throw new Error(teamResponse.message || '팀원 추가에 실패했습니다.'); + } + } else { + throw new Error(response.message || '저장에 실패했습니다.'); + } + } + } catch (error) { + console.error('❌ TBM 세션 저장 오류:', error); + showToast('TBM 세션 저장 중 오류가 발생했습니다.', 'error'); + } +} +window.saveTbmSession = saveTbmSession; + +// ==================== 작업자 관리 ==================== + +// UUID 생성 함수 +function generateUUID() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + const r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); +} + +// 작업자 카드 리스트 렌더링 +function renderWorkerTaskList() { + const listContainer = document.getElementById('workerTaskList'); + const emptyState = document.getElementById('workerListEmpty'); + + if (workerTaskList.length === 0) { + if (emptyState) emptyState.style.display = 'flex'; + listContainer.innerHTML = ''; + return; + } + + if (emptyState) emptyState.style.display = 'none'; + + listContainer.innerHTML = workerTaskList.map((workerData, workerIndex) => { + return ` +
+ +
+
+ 👤 ${escapeHtml(workerData.worker_name)} + + ${escapeHtml(workerData.job_type || '작업자')} + +
+ +
+ + + ${workerData.tasks.map((taskLine, taskIndex) => renderTaskLine(workerData, workerIndex, taskLine, taskIndex)).join('')} + + +
+ +
+
+ `; + }).join(''); +} + +// 작업 라인 렌더링 +function renderTaskLine(workerData, workerIndex, taskLine, taskIndex) { + const project = allProjects.find(p => p.project_id === taskLine.project_id); + const workType = allWorkTypes.find(wt => wt.id === taskLine.work_type_id); + const task = allTasks.find(t => t.task_id === taskLine.task_id); + const safeWorkerIndex = parseInt(workerIndex) || 0; + const safeTaskIndex = parseInt(taskIndex) || 0; + + const projectText = escapeHtml(project ? project.project_name : '프로젝트 선택'); + const workTypeText = escapeHtml(workType ? workType.name : '공정 선택 *'); + const taskText = escapeHtml(task ? task.task_name : '작업 선택 *'); + const workplaceText = taskLine.workplace_name + ? escapeHtml(`${taskLine.workplace_category_name || ''} → ${taskLine.workplace_name}`) + : '작업장 선택 *'; + + return ` +
+
+ + + + + + + + + + + +
+ + + ${workerData.tasks.length > 1 ? ` + + ` : ''} +
+ `; +} +window.renderWorkerTaskList = renderWorkerTaskList; + +// 작업자 선택 모달 열기 +function openWorkerSelectionModal() { + selectedWorkersInModal.clear(); + + const workerCardGrid = document.getElementById('workerCardGrid'); + if (!workerCardGrid) return; + + // 이미 추가된 작업자 ID 세트 + const addedWorkerIds = new Set(workerTaskList.map(w => w.worker_id)); + + workerCardGrid.innerHTML = allWorkers.map(worker => { + const isAdded = addedWorkerIds.has(worker.worker_id); + const safeWorkerId = parseInt(worker.worker_id) || 0; + return ` +
+
+ ${isAdded ? '✓' : '☐'} + ${escapeHtml(worker.worker_name)} +
+
+ ${escapeHtml(worker.job_type || '작업자')}${worker.department ? ' · ' + escapeHtml(worker.department) : ''} +
+ ${isAdded ? '
이미 추가됨
' : ''} +
+ `; + }).join(''); + + document.getElementById('workerSelectionModal').style.display = 'flex'; +} +window.openWorkerSelectionModal = openWorkerSelectionModal; + +// 작업자 선택 토글 +function toggleWorkerSelection(workerId) { + // 이미 추가된 작업자는 선택 불가 + const alreadyAdded = workerTaskList.some(w => w.worker_id === workerId); + if (alreadyAdded) return; + + const card = document.getElementById(`worker-card-${workerId}`); + if (!card) return; + + if (selectedWorkersInModal.has(workerId)) { + selectedWorkersInModal.delete(workerId); + card.style.borderColor = '#e5e7eb'; + card.style.background = 'white'; + card.innerHTML = card.innerHTML.replace('☑', '☐'); + } else { + selectedWorkersInModal.add(workerId); + card.style.borderColor = '#3b82f6'; + card.style.background = '#eff6ff'; + card.innerHTML = card.innerHTML.replace('☐', '☑'); + } +} +window.toggleWorkerSelection = toggleWorkerSelection; + +// 전체 선택 +function selectAllWorkersInModal() { + const addedWorkerIds = new Set(workerTaskList.map(w => w.worker_id)); + allWorkers.forEach(worker => { + if (!addedWorkerIds.has(worker.worker_id)) { + selectedWorkersInModal.add(worker.worker_id); + const card = document.getElementById(`worker-card-${worker.worker_id}`); + if (card) { + card.style.borderColor = '#3b82f6'; + card.style.background = '#eff6ff'; + card.innerHTML = card.innerHTML.replace('☐', '☑'); + } + } + }); +} +window.selectAllWorkersInModal = selectAllWorkersInModal; + +// 전체 해제 +function deselectAllWorkersInModal() { + selectedWorkersInModal.forEach(workerId => { + const card = document.getElementById(`worker-card-${workerId}`); + if (card) { + card.style.borderColor = '#e5e7eb'; + card.style.background = 'white'; + card.innerHTML = card.innerHTML.replace('☑', '☐'); + } + }); + selectedWorkersInModal.clear(); +} +window.deselectAllWorkersInModal = deselectAllWorkersInModal; + +// 작업자 선택 확정 +function confirmWorkerSelection() { + if (selectedWorkersInModal.size === 0) { + showToast('작업자를 선택해주세요.', 'error'); + return; + } + + selectedWorkersInModal.forEach(workerId => { + const worker = allWorkers.find(w => w.worker_id === workerId); + if (worker) { + workerTaskList.push({ + worker_id: worker.worker_id, + worker_name: worker.worker_name, + job_type: worker.job_type, + tasks: [ + { + task_line_id: generateUUID(), + project_id: null, + work_type_id: null, + task_id: null, + workplace_category_id: null, + workplace_id: null, + workplace_category_name: '', + workplace_name: '', + work_detail: null, + is_present: true + } + ] + }); + } + }); + + renderWorkerTaskList(); + closeWorkerSelectionModal(); + showToast(`${selectedWorkersInModal.size}명의 작업자가 추가되었습니다.`, 'success'); +} +window.confirmWorkerSelection = confirmWorkerSelection; + +// 작업자 선택 모달 닫기 +function closeWorkerSelectionModal() { + document.getElementById('workerSelectionModal').style.display = 'none'; + selectedWorkersInModal.clear(); +} +window.closeWorkerSelectionModal = closeWorkerSelectionModal; + +// 작업자에 작업 라인 추가 +function addTaskLineToWorker(workerIndex) { + workerTaskList[workerIndex].tasks.push({ + task_line_id: generateUUID(), + project_id: null, + work_type_id: null, + task_id: null, + workplace_category_id: null, + workplace_id: null, + workplace_category_name: '', + workplace_name: '', + work_detail: null, + is_present: true + }); + renderWorkerTaskList(); + showToast('작업 라인이 추가되었습니다.', 'success'); +} +window.addTaskLineToWorker = addTaskLineToWorker; + +// 작업 라인 제거 +function removeTaskLine(workerIndex, taskIndex) { + workerTaskList[workerIndex].tasks.splice(taskIndex, 1); + renderWorkerTaskList(); + showToast('작업 라인이 제거되었습니다.', 'info'); +} +window.removeTaskLine = removeTaskLine; + +// 작업자 제거 +function removeWorkerFromList(workerIndex) { + const workerName = workerTaskList[workerIndex].worker_name; + workerTaskList.splice(workerIndex, 1); + renderWorkerTaskList(); + showToast(`${workerName}이(가) 제거되었습니다.`, 'info'); +} +window.removeWorkerFromList = removeWorkerFromList; + +// ==================== 일괄 설정 ==================== + +// 일괄 설정 모달 열기 +function openBulkSettingModal() { + if (workerTaskList.length === 0) { + showToast('먼저 작업자를 선택해주세요.', 'error'); + return; + } + + // 작업자 선택 영역 초기화 + bulkSelectedWorkers.clear(); + renderBulkWorkerSelection(); + + // 작업 정보 초기화 + document.getElementById('bulkProjectId').value = ''; + document.getElementById('bulkWorkTypeId').value = ''; + document.getElementById('bulkTaskId').value = ''; + document.getElementById('bulkWorkplaceCategoryId').value = ''; + document.getElementById('bulkWorkplaceId').value = ''; + + document.getElementById('bulkProjectBtn').textContent = '📁 프로젝트 선택'; + document.getElementById('bulkProjectBtn').classList.remove('btn-primary'); + document.getElementById('bulkProjectBtn').classList.add('btn-secondary'); + + document.getElementById('bulkWorkTypeBtn').textContent = '⚙️ 공정 선택'; + document.getElementById('bulkWorkTypeBtn').classList.remove('btn-primary'); + document.getElementById('bulkWorkTypeBtn').classList.add('btn-secondary'); + + document.getElementById('bulkTaskBtn').textContent = '🔧 작업 선택'; + document.getElementById('bulkTaskBtn').classList.remove('btn-primary'); + document.getElementById('bulkTaskBtn').classList.add('btn-secondary'); + document.getElementById('bulkTaskBtn').disabled = true; + + document.getElementById('bulkWorkplaceBtn').textContent = '📍 작업장 선택'; + document.getElementById('bulkWorkplaceBtn').classList.remove('btn-primary'); + document.getElementById('bulkWorkplaceBtn').classList.add('btn-secondary'); + + document.getElementById('bulkSettingModal').style.display = 'flex'; +} +window.openBulkSettingModal = openBulkSettingModal; + +// 일괄 설정용 작업자 선택 영역 렌더링 +function renderBulkWorkerSelection() { + const container = document.getElementById('bulkWorkerSelection'); + if (!container) return; + + container.innerHTML = workerTaskList.map((workerData, index) => { + const isSelected = bulkSelectedWorkers.has(index); + return ` +
+ + + ${workerData.worker_name} + +
+ `; + }).join(''); +} +window.renderBulkWorkerSelection = renderBulkWorkerSelection; + +// 일괄 설정용 작업자 선택 토글 +function toggleBulkWorkerSelection(workerIndex) { + if (bulkSelectedWorkers.has(workerIndex)) { + bulkSelectedWorkers.delete(workerIndex); + } else { + bulkSelectedWorkers.add(workerIndex); + } + renderBulkWorkerSelection(); +} +window.toggleBulkWorkerSelection = toggleBulkWorkerSelection; + +// 일괄 설정용 전체 선택 +function selectAllForBulk() { + workerTaskList.forEach((_, index) => { + bulkSelectedWorkers.add(index); + }); + renderBulkWorkerSelection(); +} +window.selectAllForBulk = selectAllForBulk; + +// 일괄 설정용 전체 해제 +function deselectAllForBulk() { + bulkSelectedWorkers.clear(); + renderBulkWorkerSelection(); +} +window.deselectAllForBulk = deselectAllForBulk; + +// 일괄 설정 모달 닫기 +function closeBulkSettingModal() { + document.getElementById('bulkSettingModal').style.display = 'none'; + isBulkMode = false; +} +window.closeBulkSettingModal = closeBulkSettingModal; + +// 일괄 설정용 항목 선택 +function openBulkItemSelect(type) { + isBulkMode = true; + const modal = document.getElementById('itemSelectModal'); + const titleEl = document.getElementById('itemSelectModalTitle'); + const listEl = document.getElementById('itemSelectList'); + + let title = ''; + let items = []; + + if (type === 'project') { + title = '프로젝트 선택'; + // 활성 프로젝트만 표시 + const activeProjects = allProjects.filter(p => + p.is_active === 1 || p.is_active === true || p.is_active === '1' + ); + items = activeProjects.map(p => ({ + id: p.project_id, + name: p.project_name, + icon: '📁' + })); + } else if (type === 'workType') { + title = '공정 선택'; + items = allWorkTypes.map(wt => ({ + id: wt.id, + name: wt.name, + icon: '⚙️' + })); + } else if (type === 'task') { + title = '작업 선택'; + const currentWorkTypeId = parseInt(document.getElementById('bulkWorkTypeId').value); + if (!currentWorkTypeId) { + showToast('공정을 먼저 선택해주세요.', 'error'); + return; + } + const filteredTasks = allTasks.filter(t => t.work_type_id === currentWorkTypeId); + items = filteredTasks.map(t => ({ + id: t.task_id, + name: t.task_name, + icon: '🔧' + })); + } + + titleEl.textContent = title; + listEl.innerHTML = items.length > 0 ? items.map(item => ` + + `).join('') : '
선택 가능한 항목이 없습니다
'; + + modal.style.display = 'flex'; +} +window.openBulkItemSelect = openBulkItemSelect; + +// 일괄 설정용 항목 선택 처리 +function selectBulkItem(type, itemId, itemName) { + if (type === 'project') { + document.getElementById('bulkProjectId').value = itemId; + document.getElementById('bulkProjectBtn').textContent = `📁 ${itemName}`; + document.getElementById('bulkProjectBtn').classList.remove('btn-secondary'); + document.getElementById('bulkProjectBtn').classList.add('btn-primary'); + } else if (type === 'workType') { + document.getElementById('bulkWorkTypeId').value = itemId; + document.getElementById('bulkWorkTypeBtn').textContent = `⚙️ ${itemName}`; + document.getElementById('bulkWorkTypeBtn').classList.remove('btn-secondary'); + document.getElementById('bulkWorkTypeBtn').classList.add('btn-primary'); + + // 공정 변경 시 작업 초기화 + document.getElementById('bulkTaskId').value = ''; + document.getElementById('bulkTaskBtn').textContent = '🔧 작업 선택'; + document.getElementById('bulkTaskBtn').classList.remove('btn-primary'); + document.getElementById('bulkTaskBtn').classList.add('btn-secondary'); + document.getElementById('bulkTaskBtn').disabled = false; + } else if (type === 'task') { + document.getElementById('bulkTaskId').value = itemId; + document.getElementById('bulkTaskBtn').textContent = `🔧 ${itemName}`; + document.getElementById('bulkTaskBtn').classList.remove('btn-secondary'); + document.getElementById('bulkTaskBtn').classList.add('btn-primary'); + } + + closeItemSelectModal(); + isBulkMode = false; +} +window.selectBulkItem = selectBulkItem; + +// 일괄 설정용 작업장 선택 +function openBulkWorkplaceSelect() { + isBulkMode = true; + loadWorkplaceCategories(); + document.getElementById('workplaceSelectModal').style.display = 'flex'; +} +window.openBulkWorkplaceSelect = openBulkWorkplaceSelect; + +// 일괄 설정 적용 +function applyBulkSettings() { + if (bulkSelectedWorkers.size === 0) { + showToast('작업자를 선택해주세요.', 'error'); + return; + } + + const projectId = document.getElementById('bulkProjectId').value; + const workTypeId = document.getElementById('bulkWorkTypeId').value; + const taskId = document.getElementById('bulkTaskId').value; + const workplaceCategoryId = document.getElementById('bulkWorkplaceCategoryId').value; + const workplaceId = document.getElementById('bulkWorkplaceId').value; + + if (!workTypeId || !taskId || !workplaceId) { + showToast('공정, 작업, 작업장은 필수 항목입니다.', 'error'); + return; + } + + // 선택된 작업자들의 첫 번째 작업 라인에 적용 + let appliedCount = 0; + bulkSelectedWorkers.forEach(workerIndex => { + const workerData = workerTaskList[workerIndex]; + if (workerData && workerData.tasks.length > 0) { + workerData.tasks[0].project_id = projectId ? parseInt(projectId) : null; + workerData.tasks[0].work_type_id = parseInt(workTypeId); + workerData.tasks[0].task_id = parseInt(taskId); + workerData.tasks[0].workplace_category_id = workplaceCategoryId ? parseInt(workplaceCategoryId) : null; + workerData.tasks[0].workplace_id = parseInt(workplaceId); + workerData.tasks[0].workplace_category_name = selectedCategoryName; + workerData.tasks[0].workplace_name = selectedWorkplaceName; + appliedCount++; + } + }); + + renderWorkerTaskList(); + closeBulkSettingModal(); + showToast(`${appliedCount}명의 작업자에게 일괄 설정이 적용되었습니다.`, 'success'); +} +window.applyBulkSettings = applyBulkSettings; + +// ==================== 항목 선택 (프로젝트/공정/작업) ==================== + +// 항목 선택 모달 열기 +function openItemSelect(type, workerIndex, taskIndex) { + currentEditingTaskLine = { workerIndex, taskIndex }; + + const modal = document.getElementById('itemSelectModal'); + const titleEl = document.getElementById('itemSelectModalTitle'); + const listEl = document.getElementById('itemSelectList'); + + let title = ''; + let items = []; + + if (type === 'project') { + title = '프로젝트 선택'; + // 활성 프로젝트만 표시 + const activeProjects = allProjects.filter(p => + p.is_active === 1 || p.is_active === true || p.is_active === '1' + ); + items = activeProjects.map(p => ({ + id: p.project_id, + name: p.project_name, + icon: '📁' + })); + } else if (type === 'workType') { + title = '공정 선택'; + items = allWorkTypes.map(wt => ({ + id: wt.id, + name: wt.name, + icon: '⚙️' + })); + } else if (type === 'task') { + title = '작업 선택'; + const currentWorkTypeId = workerTaskList[workerIndex].tasks[taskIndex].work_type_id; + if (!currentWorkTypeId) { + showToast('공정을 먼저 선택해주세요.', 'error'); + return; + } + const filteredTasks = allTasks.filter(t => t.work_type_id === currentWorkTypeId); + items = filteredTasks.map(t => ({ + id: t.task_id, + name: t.task_name, + icon: '🔧' + })); + } + + titleEl.textContent = title; + listEl.innerHTML = items.length > 0 ? items.map(item => ` + + `).join('') : '
선택 가능한 항목이 없습니다
'; + + modal.style.display = 'flex'; +} +window.openItemSelect = openItemSelect; + +// 항목 선택 +function selectItem(type, itemId) { + // 일괄 모드면 여기서 처리하지 않음 + if (isBulkMode) return; + + if (!currentEditingTaskLine) return; + + const { workerIndex, taskIndex } = currentEditingTaskLine; + const taskLine = workerTaskList[workerIndex].tasks[taskIndex]; + + if (type === 'project') { + taskLine.project_id = itemId; + } else if (type === 'workType') { + taskLine.work_type_id = itemId; + // 공정 변경 시 작업 초기화 + taskLine.task_id = null; + } else if (type === 'task') { + taskLine.task_id = itemId; + } + + renderWorkerTaskList(); + closeItemSelectModal(); +} +window.selectItem = selectItem; + +// 항목 선택 모달 닫기 +function closeItemSelectModal() { + document.getElementById('itemSelectModal').style.display = 'none'; + currentEditingTaskLine = null; +} +window.closeItemSelectModal = closeItemSelectModal; + +// ==================== 작업장 2단계 선택 ==================== + +// 작업장 선택 모달 열기 (작업 라인용) +async function openWorkplaceSelect(workerIndex, taskIndex) { + currentEditingTaskLine = { workerIndex, taskIndex }; + await loadWorkplaceCategories(); + document.getElementById('workplaceSelectModal').style.display = 'flex'; +} +window.openWorkplaceSelect = openWorkplaceSelect; + +// 작업장 선택 모달 닫기 +function closeWorkplaceSelectModal() { + document.getElementById('workplaceSelectModal').style.display = 'none'; + document.getElementById('workplaceSelectionArea').style.display = 'none'; + document.getElementById('layoutMapArea').style.display = 'none'; + document.getElementById('workplaceList').style.display = 'none'; + currentEditingTaskLine = null; + selectedCategory = null; + selectedWorkplace = null; + selectedCategoryName = ''; + selectedWorkplaceName = ''; + mapCanvas = null; + mapCtx = null; + mapImage = null; + mapRegions = []; +} +window.closeWorkplaceSelectModal = closeWorkplaceSelectModal; + +// 공장 카테고리 로드 +async function loadWorkplaceCategories() { + const categoryList = document.getElementById('categoryList'); + if (!categoryList) return; + + if (allWorkplaceCategories.length === 0) { + categoryList.innerHTML = '
등록된 공장이 없습니다
'; + return; + } + + categoryList.innerHTML = allWorkplaceCategories.map(category => ` + + `).join(''); +} +window.loadWorkplaceCategories = loadWorkplaceCategories; + +// 공장 카테고리 선택 +async function selectCategory(categoryId, categoryName) { + selectedCategory = categoryId; + selectedCategoryName = categoryName; + selectedWorkplace = null; + selectedWorkplaceName = ''; + + // 카테고리 버튼 스타일 업데이트 + document.querySelectorAll('[id^="category-"]').forEach(btn => { + btn.classList.remove('btn-primary'); + btn.classList.add('btn-secondary'); + }); + const selectedBtn = document.getElementById(`category-${categoryId}`); + if (selectedBtn) { + selectedBtn.classList.remove('btn-secondary'); + selectedBtn.classList.add('btn-primary'); + } + + // 작업장 선택 영역 표시 + document.getElementById('workplaceSelectionArea').style.display = 'block'; + + // 해당 카테고리 정보 가져오기 + const category = allWorkplaceCategories.find(c => c.category_id === categoryId); + + // 지도 또는 리스트 로드 + if (category && category.layout_image) { + // 지도가 있는 경우 - 지도 영역 표시 + await loadWorkplaceMap(categoryId, category.layout_image); + document.getElementById('layoutMapArea').style.display = 'block'; + } else { + // 지도가 없는 경우 - 리스트만 표시 + document.getElementById('layoutMapArea').style.display = 'none'; + document.getElementById('workplaceList').style.display = 'flex'; + document.getElementById('toggleListBtn').style.display = 'none'; + } + + // 해당 카테고리의 작업장 리스트 로드 (오류 대비용) + await loadWorkplacesByCategory(categoryId); + + // 선택 완료 버튼 비활성화 (작업장 선택 필요) + document.getElementById('confirmWorkplaceBtn').disabled = true; +} +window.selectCategory = selectCategory; + +// 카테고리별 작업장 로드 +async function loadWorkplacesByCategory(categoryId) { + const workplaceList = document.getElementById('workplaceList'); + if (!workplaceList) return; + + try { + const response = await window.apiCall(`/workplaces?category_id=${categoryId}`); + if (!response || !response.success || !response.data || response.data.length === 0) { + workplaceList.innerHTML = '
등록된 작업장이 없습니다
'; + return; + } + + const workplaces = response.data; + workplaceList.innerHTML = workplaces.map(workplace => ` + + `).join(''); + } catch (error) { + console.error('❌ 작업장 로드 오류:', error); + workplaceList.innerHTML = '
작업장을 불러오는 중 오류가 발생했습니다
'; + } +} +window.loadWorkplacesByCategory = loadWorkplacesByCategory; + +// 작업장 선택 +function selectWorkplace(workplaceId, workplaceName) { + selectedWorkplace = workplaceId; + selectedWorkplaceName = workplaceName; + + // 작업장 버튼 스타일 업데이트 (리스트) + document.querySelectorAll('[id^="workplace-"]').forEach(btn => { + btn.classList.remove('btn-primary'); + btn.classList.add('btn-secondary'); + }); + const selectedBtn = document.getElementById(`workplace-${workplaceId}`); + if (selectedBtn) { + selectedBtn.classList.remove('btn-secondary'); + selectedBtn.classList.add('btn-primary'); + } + + // 지도 업데이트 (지도가 로드되어 있는 경우) + if (mapCanvas && mapCtx && mapImage) { + drawWorkplaceMap(); + } + + // 선택 완료 버튼 활성화 + document.getElementById('confirmWorkplaceBtn').disabled = false; +} +window.selectWorkplace = selectWorkplace; + +// 작업장 선택 확정 +function confirmWorkplaceSelection() { + if (!selectedCategory || !selectedWorkplace) { + showToast('공장과 작업장을 모두 선택해주세요.', 'error'); + return; + } + + // 일괄 모드인 경우 + if (isBulkMode) { + document.getElementById('bulkWorkplaceCategoryId').value = selectedCategory; + document.getElementById('bulkWorkplaceId').value = selectedWorkplace; + document.getElementById('bulkWorkplaceBtn').textContent = `📍 ${selectedCategoryName} → ${selectedWorkplaceName}`; + document.getElementById('bulkWorkplaceBtn').classList.remove('btn-secondary'); + document.getElementById('bulkWorkplaceBtn').classList.add('btn-primary'); + closeWorkplaceSelectModal(); + isBulkMode = false; + showToast('작업장이 선택되었습니다.', 'success'); + return; + } + + // 현재 편집 중인 작업 라인에 저장 + if (currentEditingTaskLine) { + const { workerIndex, taskIndex } = currentEditingTaskLine; + const taskLine = workerTaskList[workerIndex].tasks[taskIndex]; + taskLine.workplace_category_id = selectedCategory; + taskLine.workplace_id = selectedWorkplace; + taskLine.workplace_category_name = selectedCategoryName; + taskLine.workplace_name = selectedWorkplaceName; + renderWorkerTaskList(); + } + + closeWorkplaceSelectModal(); + showToast('작업장이 선택되었습니다.', 'success'); +} +window.confirmWorkplaceSelection = confirmWorkplaceSelection; + +// 리스트 토글 함수 +function toggleWorkplaceList() { + const list = document.getElementById('workplaceList'); + const icon = document.getElementById('toggleListIcon'); + const btn = document.getElementById('toggleListBtn'); + + if (list.style.display === 'none' || list.style.display === '') { + list.style.display = 'flex'; + icon.textContent = '▲'; + btn.textContent = ' 리스트 닫기'; + btn.insertBefore(icon, btn.firstChild); + } else { + list.style.display = 'none'; + icon.textContent = '▼'; + btn.textContent = ' 리스트 보기'; + btn.insertBefore(icon, btn.firstChild); + } +} +window.toggleWorkplaceList = toggleWorkplaceList; + +// 작업장 지도 로드 및 렌더링 +let mapRegions = []; // 현재 로드된 지도 영역들 +let mapCanvas = null; +let mapCtx = null; +let mapImage = null; + +async function loadWorkplaceMap(categoryId, layoutImagePath) { + try { + mapCanvas = document.getElementById('workplaceMapCanvas'); + if (!mapCanvas) return; + + mapCtx = mapCanvas.getContext('2d'); + + // 이미지 URL 생성 + const baseUrl = window.API_BASE_URL || 'http://localhost:20005'; + const apiBaseUrl = baseUrl.replace('/api', ''); // /api 제거 + const fullImageUrl = layoutImagePath.startsWith('http') + ? layoutImagePath + : `${apiBaseUrl}${layoutImagePath}`; + + console.log('🖼️ 이미지 로드 시도:', fullImageUrl); + + // 지도 영역 데이터 로드 + const regionsResponse = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`); + if (regionsResponse && regionsResponse.success) { + mapRegions = regionsResponse.data || []; + } else { + mapRegions = []; + } + + // 이미지 로드 + mapImage = new Image(); + mapImage.crossOrigin = 'anonymous'; + + mapImage.onload = function() { + // 캔버스 크기 설정 (최대 너비 800px) + const maxWidth = 800; + const scale = mapImage.width > maxWidth ? maxWidth / mapImage.width : 1; + + mapCanvas.width = mapImage.width * scale; + mapCanvas.height = mapImage.height * scale; + + // 이미지와 영역 그리기 + drawWorkplaceMap(); + + // 클릭 이벤트 리스너 추가 + mapCanvas.onclick = handleMapClick; + + console.log(`✅ 작업장 지도 로드 완료: ${mapRegions.length}개 영역`); + }; + + mapImage.onerror = function() { + console.error('❌ 지도 이미지 로드 실패'); + document.getElementById('layoutMapArea').style.display = 'none'; + document.getElementById('workplaceList').style.display = 'flex'; + document.getElementById('toggleListBtn').style.display = 'none'; + showToast('지도를 불러올 수 없어 리스트로 표시합니다.', 'warning'); + }; + + mapImage.src = fullImageUrl; + + } catch (error) { + console.error('❌ 작업장 지도 로드 오류:', error); + document.getElementById('layoutMapArea').style.display = 'none'; + document.getElementById('workplaceList').style.display = 'flex'; + } +} +window.loadWorkplaceMap = loadWorkplaceMap; + +// 지도 그리기 (이미지 + 영역 + 라벨) +function drawWorkplaceMap() { + if (!mapCanvas || !mapCtx || !mapImage) return; + + // 이미지 그리기 + mapCtx.drawImage(mapImage, 0, 0, mapCanvas.width, mapCanvas.height); + + // 각 영역 그리기 + mapRegions.forEach((region, index) => { + // 퍼센트를 픽셀로 변환 + const x1 = (region.x_start / 100) * mapCanvas.width; + const y1 = (region.y_start / 100) * mapCanvas.height; + const x2 = (region.x_end / 100) * mapCanvas.width; + const y2 = (region.y_end / 100) * mapCanvas.height; + + const width = x2 - x1; + const height = y2 - y1; + + // 선택된 영역인지 확인 + const isSelected = region.workplace_id === selectedWorkplace; + + // 영역 테두리 + mapCtx.strokeStyle = isSelected ? '#3b82f6' : '#10b981'; + mapCtx.lineWidth = isSelected ? 4 : 2; + mapCtx.strokeRect(x1, y1, width, height); + + // 영역 배경 (반투명) + mapCtx.fillStyle = isSelected ? 'rgba(59, 130, 246, 0.25)' : 'rgba(16, 185, 129, 0.15)'; + mapCtx.fillRect(x1, y1, width, height); + + // 작업장 이름 표시 + if (region.workplace_name) { + mapCtx.font = 'bold 14px sans-serif'; + + // 텍스트 배경 + const textMetrics = mapCtx.measureText(region.workplace_name); + const textPadding = 6; + mapCtx.fillStyle = isSelected ? 'rgba(59, 130, 246, 0.95)' : 'rgba(16, 185, 129, 0.95)'; + mapCtx.fillRect(x1 + 5, y1 + 5, textMetrics.width + textPadding * 2, 24); + + // 텍스트 + mapCtx.fillStyle = '#ffffff'; + mapCtx.fillText(region.workplace_name, x1 + 5 + textPadding, y1 + 22); + } + }); +} + +// 지도 클릭 이벤트 처리 +function handleMapClick(event) { + if (!mapCanvas || mapRegions.length === 0) return; + + const rect = mapCanvas.getBoundingClientRect(); + const x = event.clientX - rect.left; + const y = event.clientY - rect.top; + + // 클릭한 위치에 있는 영역 찾기 + for (let i = mapRegions.length - 1; i >= 0; i--) { + const region = mapRegions[i]; + const x1 = (region.x_start / 100) * mapCanvas.width; + const y1 = (region.y_start / 100) * mapCanvas.height; + const x2 = (region.x_end / 100) * mapCanvas.width; + const y2 = (region.y_end / 100) * mapCanvas.height; + + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { + // 영역 클릭됨 + selectWorkplace(region.workplace_id, region.workplace_name); + + // 지도 다시 그리기 (선택 효과 표시) + drawWorkplaceMap(); + + // 리스트에서도 동기화 + syncWorkplaceListSelection(region.workplace_id); + + return; + } + } +} + +// 리스트 선택 동기화 +function syncWorkplaceListSelection(workplaceId) { + // 리스트의 버튼들도 업데이트 + document.querySelectorAll('[id^="workplace-"]').forEach(btn => { + if (btn.id === `workplace-${workplaceId}`) { + btn.classList.remove('btn-secondary'); + btn.classList.add('btn-primary'); + } else { + btn.classList.remove('btn-primary'); + btn.classList.add('btn-secondary'); + } + }); +} +window.syncWorkplaceListSelection = syncWorkplaceListSelection; + +// ==================== 기존 팀 구성 모달 (백업) ==================== + +// 팀 구성 모달 열기 +// 팀 구성 수정 (TBM 수정 모달 열기) +async function openTeamCompositionModal(sessionId) { + currentSessionId = sessionId; + + try { + // 세션 정보 로드 + const sessionResponse = await window.apiCall(`/tbm/sessions/${sessionId}`); + if (!sessionResponse || !sessionResponse.success) { + showToast('TBM 정보를 불러올 수 없습니다.', 'error'); + return; + } + + const session = sessionResponse.data; // data는 이미 객체 + + // 팀원 정보 로드 + const teamResponse = await window.apiCall(`/tbm/sessions/${sessionId}/team`); + if (!teamResponse || !teamResponse.success) { + showToast('팀원 정보를 불러올 수 없습니다.', 'error'); + return; + } + + const teamMembers = teamResponse.data; + + // workerTaskList 구성 + workerTaskList = []; + const workerMap = new Map(); + + // 팀원별로 작업 그룹화 + teamMembers.forEach(member => { + if (!workerMap.has(member.worker_id)) { + workerMap.set(member.worker_id, { + worker_id: member.worker_id, + worker_name: member.worker_name, + job_type: member.job_type, + tasks: [] + }); + } + + workerMap.get(member.worker_id).tasks.push({ + task_line_id: generateUUID(), + project_id: member.project_id, + work_type_id: member.work_type_id, + task_id: member.task_id, + workplace_category_id: member.workplace_category_id, + workplace_id: member.workplace_id, + workplace_category_name: member.workplace_category_name, + workplace_name: member.workplace_name, + work_detail: member.work_detail, + is_present: member.is_present !== undefined ? member.is_present : true + }); + }); + + workerTaskList = Array.from(workerMap.values()); + + // 모달 열기 + document.getElementById('modalTitle').textContent = '팀 구성 수정'; + document.getElementById('sessionId').value = sessionId; + document.getElementById('sessionDate').value = session.session_date; + + // 입력자 표시 + if (session.leader_name) { + document.getElementById('leaderName').value = `${session.leader_name} (${session.leader_job_type || ''})`; + document.getElementById('leaderId').value = session.leader_id; + } else if (session.created_by_name) { + document.getElementById('leaderName').value = `${session.created_by_name} (관리자)`; + document.getElementById('leaderId').value = ''; + } + + renderWorkerTaskList(); + + document.getElementById('tbmModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + } catch (error) { + console.error('❌ 팀 구성 로드 오류:', error); + showToast('팀 구성을 불러오는 중 오류가 발생했습니다.', 'error'); + } +} +window.openTeamCompositionModal = openTeamCompositionModal; + +// 선택된 작업자 업데이트 +function updateSelectedWorkers() { + selectedWorkers.clear(); + + document.querySelectorAll('.worker-checkbox:checked').forEach(cb => { + selectedWorkers.add(parseInt(cb.dataset.workerId)); + }); + + const selectedCount = document.getElementById('selectedCount'); + const selectedList = document.getElementById('selectedWorkersList'); + + selectedCount.textContent = selectedWorkers.size; + + if (selectedWorkers.size === 0) { + selectedList.innerHTML = '

작업자를 선택해주세요

'; + } else { + const selectedWorkersArray = Array.from(selectedWorkers).map(id => { + const worker = allWorkers.find(w => w.worker_id === id); + return worker ? ` + + ${worker.worker_name} + + + ` : ''; + }); + selectedList.innerHTML = selectedWorkersArray.join(''); + } +} +window.updateSelectedWorkers = updateSelectedWorkers; + +// 작업자 제거 +function removeWorker(workerId) { + const checkbox = document.querySelector(`.worker-checkbox[data-worker-id="${workerId}"]`); + if (checkbox) { + checkbox.checked = false; + updateSelectedWorkers(); + } +} +window.removeWorker = removeWorker; + +// 전체 선택 +function selectAllWorkers() { + document.querySelectorAll('.worker-checkbox').forEach(cb => { + cb.checked = true; + }); + updateSelectedWorkers(); +} +window.selectAllWorkers = selectAllWorkers; + +// 전체 해제 +function deselectAllWorkers() { + document.querySelectorAll('.worker-checkbox').forEach(cb => { + cb.checked = false; + }); + updateSelectedWorkers(); +} +window.deselectAllWorkers = deselectAllWorkers; + +// 팀 구성 모달 닫기 +function closeTeamModal() { + document.getElementById('teamModal').style.display = 'none'; + document.body.style.overflow = 'auto'; +} +window.closeTeamModal = closeTeamModal; + +// 팀 구성 저장 +async function saveTeamComposition() { + if (selectedWorkers.size === 0) { + showToast('최소 1명 이상의 작업자를 선택해주세요.', 'error'); + return; + } + + const members = Array.from(selectedWorkers).map(workerId => ({ + worker_id: workerId + })); + + try { + const response = await window.apiCall( + `/tbm/sessions/${currentSessionId}/team/batch`, + 'POST', + { members } + ); + + if (response && response.success) { + showToast(`${selectedWorkers.size}명의 팀원이 추가되었습니다.`, 'success'); + closeTeamModal(); + + // 목록 새로고침 + if (currentTab === 'tbm-input') { + await loadTodayOnlyTbm(); + } else { + const date = document.getElementById('tbmDate').value; + await loadTbmSessionsByDate(date); + } + } else { + throw new Error(response.message || '저장에 실패했습니다.'); + } + } catch (error) { + console.error('❌ 팀 구성 저장 오류:', error); + showToast('팀 구성 저장 중 오류가 발생했습니다.', 'error'); + } +} +window.saveTeamComposition = saveTeamComposition; + +// 안전 체크 모달 열기 (기본 + 날씨별 + 작업별) +async function openSafetyCheckModal(sessionId) { + currentSessionId = sessionId; + + try { + // 필터링된 체크리스트 조회 (기본 + 날씨 + 작업별) + const response = await window.apiCall(`/tbm/sessions/${sessionId}/safety-checks/filtered`); + + if (!response || !response.success) { + throw new Error(response?.message || '체크리스트를 불러올 수 없습니다.'); + } + + const { basic, weather, task, weatherInfo } = response.data; + + const categoryNames = { + 'PPE': '개인 보호 장비', + 'EQUIPMENT': '장비 점검', + 'ENVIRONMENT': '작업 환경', + 'EMERGENCY': '비상 대응', + 'WEATHER': '날씨', + 'TASK': '작업' + }; + + const weatherIcons = { + clear: '☀️', rain: '🌧️', snow: '❄️', heat: '🔥', + cold: '🥶', wind: '💨', fog: '🌫️', dust: '😷' + }; + + const container = document.getElementById('safetyChecklistContainer'); + let html = ''; + + // 1. 기본 사항 섹션 + if (basic && basic.length > 0) { + const basicGrouped = groupChecksByCategory(basic); + html += ` +
+
+ 📋 기본 안전 사항 (${basic.length}개) +
+ ${renderCategoryGroups(basicGrouped, categoryNames)} +
+ `; + } + + // 2. 날씨별 섹션 + if (weather && weather.length > 0) { + const weatherConditions = weatherInfo?.weather_conditions || []; + const conditionNames = weatherConditions.map(c => { + const icon = weatherIcons[c] || '🌤️'; + return `${icon} ${getWeatherConditionName(c)}`; + }).join(', ') || '맑음'; + + html += ` +
+
+ 🌤️ 오늘 날씨 관련 (${conditionNames}) - ${weather.length}개 +
+ ${renderCheckItems(weather)} +
+ `; + } + + // 3. 작업별 섹션 + if (task && task.length > 0) { + const taskGrouped = groupChecksByTask(task); + html += ` +
+
+ 🔧 작업별 안전 사항 - ${task.length}개 +
+ ${renderTaskGroups(taskGrouped)} +
+ `; + } + + // 체크리스트가 없는 경우 + if ((!basic || basic.length === 0) && (!weather || weather.length === 0) && (!task || task.length === 0)) { + html = ` +
+
📋
+

등록된 안전 체크 항목이 없습니다.

+
+ `; + } + + container.innerHTML = html; + document.getElementById('safetyModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + } catch (error) { + console.error('❌ 안전 체크 조회 오류:', error); + showToast('안전 체크 정보를 불러오는 중 오류가 발생했습니다.', 'error'); + } +} +window.openSafetyCheckModal = openSafetyCheckModal; + +// 카테고리별 그룹화 +function groupChecksByCategory(checks) { + return checks.reduce((acc, check) => { + const category = check.check_category || 'OTHER'; + if (!acc[category]) acc[category] = []; + acc[category].push(check); + return acc; + }, {}); +} + +// 작업별 그룹화 +function groupChecksByTask(checks) { + return checks.reduce((acc, check) => { + const taskId = check.task_id || 0; + const taskName = check.task_name || '기타 작업'; + if (!acc[taskId]) acc[taskId] = { name: taskName, items: [] }; + acc[taskId].items.push(check); + return acc; + }, {}); +} + +// 날씨 조건명 반환 +function getWeatherConditionName(code) { + const names = { + clear: '맑음', rain: '비', snow: '눈', heat: '폭염', + cold: '한파', wind: '강풍', fog: '안개', dust: '미세먼지' + }; + return names[code] || code; +} + +// 카테고리 그룹 렌더링 +function renderCategoryGroups(grouped, categoryNames) { + return Object.keys(grouped).map(category => ` +
+
+ ${categoryNames[category] || category} +
+ ${renderCheckItems(grouped[category])} +
+ `).join(''); +} + +// 작업 그룹 렌더링 +function renderTaskGroups(grouped) { + return Object.values(grouped).map(group => ` +
+
+ 📋 ${group.name} +
+ ${renderCheckItems(group.items)} +
+ `).join(''); +} + +// 체크 항목 렌더링 +function renderCheckItems(items) { + return items.map(check => ` +
+ +
+ `).join(''); +} + +// 안전 체크 모달 닫기 +function closeSafetyModal() { + document.getElementById('safetyModal').style.display = 'none'; + document.body.style.overflow = 'auto'; +} +window.closeSafetyModal = closeSafetyModal; + +// 안전 체크리스트 저장 +async function saveSafetyChecklist() { + const records = []; + + document.querySelectorAll('.safety-check').forEach(cb => { + records.push({ + check_id: parseInt(cb.dataset.checkId), + is_checked: cb.checked + }); + }); + + try { + const response = await window.apiCall( + `/tbm/sessions/${currentSessionId}/safety`, + 'POST', + { records } + ); + + if (response && response.success) { + showToast('안전 체크가 완료되었습니다.', 'success'); + closeSafetyModal(); + } else { + throw new Error(response.message || '저장에 실패했습니다.'); + } + } catch (error) { + console.error('❌ 안전 체크 저장 오류:', error); + showToast('안전 체크 저장 중 오류가 발생했습니다.', 'error'); + } +} +window.saveSafetyChecklist = saveSafetyChecklist; + +// TBM 완료 모달 열기 +function openCompleteTbmModal(sessionId) { + currentSessionId = sessionId; + const now = new Date(); + const timeString = now.toTimeString().slice(0, 5); + document.getElementById('endTime').value = timeString; + + document.getElementById('completeModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; +} +window.openCompleteTbmModal = openCompleteTbmModal; + +// 완료 모달 닫기 +function closeCompleteModal() { + document.getElementById('completeModal').style.display = 'none'; + document.body.style.overflow = 'auto'; +} +window.closeCompleteModal = closeCompleteModal; + +// TBM 세션 완료 +async function completeTbmSession() { + const endTime = document.getElementById('endTime').value; + + try { + const response = await window.apiCall( + `/tbm/sessions/${currentSessionId}/complete`, + 'POST', + { end_time: endTime } + ); + + if (response && response.success) { + showToast('TBM이 완료되었습니다.', 'success'); + closeCompleteModal(); + + // 목록 새로고침 + if (currentTab === 'tbm-input') { + await loadTodayOnlyTbm(); + } else { + const date = document.getElementById('tbmDate').value; + await loadTbmSessionsByDate(date); + } + } else { + throw new Error(response.message || '완료 처리에 실패했습니다.'); + } + } catch (error) { + console.error('❌ TBM 완료 처리 오류:', error); + showToast('TBM 완료 처리 중 오류가 발생했습니다.', 'error'); + } +} +window.completeTbmSession = completeTbmSession; + +// TBM 세션 상세 보기 +async function viewTbmSession(sessionId) { + try { + // 세션 정보, 팀 구성, 안전 체크 동시 조회 + const [sessionRes, teamRes, safetyRes] = await Promise.all([ + window.apiCall(`/tbm/sessions/${sessionId}`), + window.apiCall(`/tbm/sessions/${sessionId}/team`), + window.apiCall(`/tbm/sessions/${sessionId}/safety`) + ]); + + const session = sessionRes?.data; + const team = teamRes?.data || []; + const safety = safetyRes?.data || []; + + if (!session) { + showToast('세션 정보를 불러올 수 없습니다.', 'error'); + return; + } + + // 기본 정보 표시 + const basicInfo = document.getElementById('detailBasicInfo'); + basicInfo.innerHTML = ` +
+
팀장
+
${session.leader_name}
+
+
+
날짜
+
${session.session_date}
+
+
+
프로젝트
+
${session.project_name || '-'}
+
+
+
작업 장소
+
${session.work_location || '-'}
+
+
+
작업 내용
+
${session.work_description || '-'}
+
+ ${session.safety_notes ? ` +
+
⚠️ 안전 특이사항
+
${session.safety_notes}
+
+ ` : ''} + `; + + // 팀 구성 표시 + const teamMembers = document.getElementById('detailTeamMembers'); + if (team.length === 0) { + teamMembers.innerHTML = '

등록된 팀원이 없습니다.

'; + } else { + teamMembers.innerHTML = team.map(member => ` +
+
${member.worker_name}
+
${member.job_type || ''}
+ ${member.is_present ? '' : '
결석
'} +
+ `).join(''); + } + + // 안전 체크 표시 + const safetyChecks = document.getElementById('detailSafetyChecks'); + if (safety.length === 0) { + safetyChecks.innerHTML = '

안전 체크 기록이 없습니다.

'; + } else { + // 카테고리별 그룹화 + const grouped = {}; + safety.forEach(check => { + if (!grouped[check.check_category]) { + grouped[check.check_category] = []; + } + grouped[check.check_category].push(check); + }); + + const categoryNames = { + 'PPE': '개인 보호 장비', + 'EQUIPMENT': '장비 점검', + 'ENVIRONMENT': '작업 환경', + 'EMERGENCY': '비상 대응' + }; + + safetyChecks.innerHTML = Object.keys(grouped).map(category => ` +
+
+ ${categoryNames[category] || category} +
+
+ ${grouped[category].map(check => ` +
+ ${check.is_checked ? '✅' : '❌'} + ${check.check_item} +
+ `).join('')} +
+
+ `).join(''); + } + + document.getElementById('detailModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + } catch (error) { + console.error('❌ TBM 상세 조회 오류:', error); + showToast('상세 정보를 불러오는 중 오류가 발생했습니다.', 'error'); + } +} +window.viewTbmSession = viewTbmSession; + +// 상세보기 모달 닫기 +function closeDetailModal() { + document.getElementById('detailModal').style.display = 'none'; + document.body.style.overflow = 'auto'; +} +window.closeDetailModal = closeDetailModal; + +// 작업 인계 모달 열기 +async function openHandoverModal(sessionId) { + currentSessionId = sessionId; + + // 세션 정보와 팀 구성 조회 + try { + const [sessionRes, teamRes] = await Promise.all([ + window.apiCall(`/tbm/sessions/${sessionId}`), + window.apiCall(`/tbm/sessions/${sessionId}/team`) + ]); + + const session = sessionRes?.data; + const team = teamRes?.data || []; + + if (!session) { + showToast('세션 정보를 불러올 수 없습니다.', 'error'); + return; + } + + // 현재 세션의 팀장을 제외한 리더 목록 + const toLeaderSelect = document.getElementById('toLeaderId'); + const otherLeaders = allWorkers.filter(w => + (w.job_type === 'leader' || w.job_type === '그룹장' || w.job_type === 'admin') && + w.worker_id !== session.leader_id + ); + + toLeaderSelect.innerHTML = '' + + otherLeaders.map(w => ` + + `).join(''); + + // 인계할 팀원 목록 + const handoverTeamList = document.getElementById('handoverTeamList'); + if (team.length === 0) { + handoverTeamList.innerHTML = '

팀 구성이 없습니다.

'; + } else { + handoverTeamList.innerHTML = team.map(member => ` + + `).join(''); + } + + // 기본값 설정 + document.getElementById('handoverSessionId').value = sessionId; + const today = getTodayKST(); + const now = new Date().toTimeString().slice(0, 5); + document.getElementById('handoverDate').value = today; + document.getElementById('handoverTime').value = now; + document.getElementById('handoverReason').value = ''; + document.getElementById('handoverNotes').value = ''; + + document.getElementById('handoverModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + } catch (error) { + console.error('❌ 인계 모달 열기 오류:', error); + showToast('인계 정보를 불러오는 중 오류가 발생했습니다.', 'error'); + } +} +window.openHandoverModal = openHandoverModal; + +// 인계 모달 닫기 +function closeHandoverModal() { + document.getElementById('handoverModal').style.display = 'none'; + document.body.style.overflow = 'auto'; +} +window.closeHandoverModal = closeHandoverModal; + +// 작업 인계 저장 +async function saveHandover() { + const sessionId = currentSessionId; + const toLeaderId = parseInt(document.getElementById('toLeaderId').value); + const reason = document.getElementById('handoverReason').value; + const handoverDate = document.getElementById('handoverDate').value; + const handoverTime = document.getElementById('handoverTime').value; + const handoverNotes = document.getElementById('handoverNotes').value; + + if (!toLeaderId || !reason || !handoverDate) { + showToast('필수 항목을 입력해주세요.', 'error'); + return; + } + + // 인계할 작업자 목록 + const workerIds = []; + document.querySelectorAll('.handover-worker-checkbox:checked').forEach(cb => { + workerIds.push(parseInt(cb.value)); + }); + + if (workerIds.length === 0) { + showToast('인계할 팀원을 최소 1명 이상 선택해주세요.', 'error'); + return; + } + + try { + // 세션 정보 조회 (from_leader_id 가져오기) + const sessionRes = await window.apiCall(`/tbm/sessions/${sessionId}`); + const fromLeaderId = sessionRes?.data?.leader_id; + + if (!fromLeaderId) { + showToast('세션 정보를 찾을 수 없습니다.', 'error'); + return; + } + + const handoverData = { + session_id: sessionId, + from_leader_id: fromLeaderId, + to_leader_id: toLeaderId, + handover_date: handoverDate, + handover_time: handoverTime, + reason: reason, + handover_notes: handoverNotes, + worker_ids: workerIds + }; + + const response = await window.apiCall('/tbm/handovers', 'POST', handoverData); + + if (response && response.success) { + showToast('작업 인계가 요청되었습니다.', 'success'); + closeHandoverModal(); + } else { + throw new Error(response.message || '인계 요청에 실패했습니다.'); + } + } catch (error) { + console.error('❌ 작업 인계 저장 오류:', error); + showToast('작업 인계 중 오류가 발생했습니다.', 'error'); + } +} +window.saveHandover = saveHandover; + +// 토스트 알림 +function showToast(message, type = 'info', duration = 3000) { + const container = document.getElementById('toastContainer'); + if (!container) return; + + const toast = document.createElement('div'); + toast.className = `toast ${type}`; + + const iconMap = { + success: '✅', + error: '❌', + warning: '⚠️', + info: 'ℹ️' + }; + + toast.innerHTML = ` +
${iconMap[type] || 'ℹ️'}
+
${message}
+ + `; + + toast.style.cssText = ` + display: flex; + align-items: center; + gap: 0.75rem; + padding: 1rem 1.25rem; + background: white; + border-radius: 0.5rem; + box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1); + margin-bottom: 0.75rem; + min-width: 300px; + animation: slideIn 0.3s ease-out; + `; + + container.appendChild(toast); + + setTimeout(() => { + if (toast.parentElement) { + toast.style.animation = 'slideOut 0.3s ease-out'; + setTimeout(() => toast.remove(), 300); + } + }, duration); +} diff --git a/deploy/tkfb-package/web-ui/js/tbm/api.js b/deploy/tkfb-package/web-ui/js/tbm/api.js new file mode 100644 index 0000000..f59f41c --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/tbm/api.js @@ -0,0 +1,489 @@ +/** + * 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('user') || '{}'); + this.state.currentUser = userInfo; + console.log('👤 로그인 사용자:', this.state.currentUser, 'worker_id:', this.state.currentUser?.worker_id); + + // 병렬로 데이터 로드 + await Promise.all([ + this.loadWorkers(), + this.loadProjects(), + this.loadSafetyChecks(), + this.loadWorkTypes(), + this.loadTasks(), + this.loadWorkplaces(), + this.loadWorkplaceCategories() + ]); + + console.log('✅ 초기 데이터 로드 완료'); + } 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; + console.log('✅ 작업자 목록 로드:', workers.length + '명'); + 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' + ); + console.log('✅ 프로젝트 목록 로드:', this.state.allProjects.length + '개 (활성)'); + 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; + console.log('✅ 안전 체크리스트 로드:', this.state.allSafetyChecks.length + '개'); + 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 || []; + console.log('✅ 공정 목록 로드:', this.state.allWorkTypes.length + '개'); + 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 || []; + console.log('✅ 작업 목록 로드:', this.state.allTasks.length + '개'); + 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 || []; + console.log('✅ 작업장 목록 로드:', this.state.allWorkplaces.length + '개'); + 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 || []; + console.log('✅ 작업장 카테고리 로드:', this.state.allWorkplaceCategories.length + '개'); + 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 = []; + } + console.log('✅ 오늘 TBM 로드:', this.state.todaySessions.length + '건'); + 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) { + let sessions = response.data; + + // admin이 아니면 본인이 작성한 TBM만 필터링 + if (!this.state.isAdminUser()) { + const userId = this.state.currentUser?.user_id; + const workerId = this.state.currentUser?.worker_id; + sessions = sessions.filter(s => { + return s.created_by === userId || + s.leader_id === workerId || + s.created_by_name === this.state.currentUser?.name; + }); + } + + if (sessions.length > 0) { + this.state.dateGroupedSessions[date] = sessions; + this.state.allLoadedSessions = this.state.allLoadedSessions.concat(sessions); + } + } + }); + + console.log('✅ 날짜별 TBM 로드 완료:', this.state.allLoadedSessions.length + '건'); + 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 || '세션 생성 실패'); + } + console.log('✅ TBM 세션 생성 완료:', response.data?.session_id); + 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) { + throw new Error(response?.message || '팀원 추가 실패'); + } + console.log('✅ TBM 팀원 추가 완료:', members.length + '명'); + 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 || '완료 처리 실패'); + } + console.log('✅ TBM 완료 처리:', sessionId); + 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 []; + } + } +} + +// 전역 인스턴스 생성 +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'); +}; + +console.log('[Module] tbm/api.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/tbm/index.js b/deploy/tkfb-package/web-ui/js/tbm/index.js new file mode 100644 index 0000000..a295074 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/tbm/index.js @@ -0,0 +1,325 @@ +/** + * TBM - Module Loader + * TBM 모듈을 초기화하고 연결하는 메인 진입점 + * + * 로드 순서: + * 1. state.js - 전역 상태 관리 + * 2. utils.js - 유틸리티 함수 + * 3. api.js - API 클라이언트 + * 4. index.js - 이 파일 (메인 컨트롤러) + */ + +class TbmController { + constructor() { + this.state = window.TbmState; + this.api = window.TbmAPI; + this.utils = window.TbmUtils; + this.initialized = false; + + console.log('[TbmController] 생성'); + } + + /** + * 초기화 + */ + async init() { + if (this.initialized) { + console.log('[TbmController] 이미 초기화됨'); + return; + } + + console.log('🛠️ TBM 관리 페이지 초기화'); + + // API 함수가 로드될 때까지 대기 + let retryCount = 0; + while (!window.apiCall && retryCount < 50) { + await new Promise(resolve => setTimeout(resolve, 100)); + retryCount++; + } + + if (!window.apiCall) { + window.showToast?.('시스템을 초기화할 수 없습니다. 페이지를 새로고침해주세요.', 'error'); + return; + } + + // 오늘 날짜 설정 (서울 시간대 기준) + const today = this.utils.getTodayKST(); + const tbmDateEl = document.getElementById('tbmDate'); + const sessionDateEl = document.getElementById('sessionDate'); + if (tbmDateEl) tbmDateEl.value = today; + if (sessionDateEl) sessionDateEl.value = today; + + // 이벤트 리스너 설정 + this.setupEventListeners(); + + // 초기 데이터 로드 + await this.api.loadInitialData(); + await this.api.loadTodayOnlyTbm(); + + // 렌더링 + this.displayTodayTbmSessions(); + + this.initialized = true; + console.log('[TbmController] 초기화 완료'); + } + + /** + * 이벤트 리스너 설정 + */ + setupEventListeners() { + // 탭 버튼들 + document.querySelectorAll('.tbm-tab-btn').forEach(btn => { + btn.addEventListener('click', () => { + const tabName = btn.dataset.tab; + if (tabName) this.switchTbmTab(tabName); + }); + }); + } + + /** + * 탭 전환 + */ + async switchTbmTab(tabName) { + this.state.setCurrentTab(tabName); + + // 탭 버튼 활성화 상태 변경 + document.querySelectorAll('.tbm-tab-btn').forEach(btn => { + if (btn.dataset.tab === tabName) { + btn.classList.add('active'); + } else { + btn.classList.remove('active'); + } + }); + + // 탭 컨텐츠 표시 변경 + document.querySelectorAll('.tbm-tab-content').forEach(content => { + content.classList.remove('active'); + }); + const tabContent = document.getElementById(`${tabName}-tab`); + if (tabContent) tabContent.classList.add('active'); + + // 탭에 따라 데이터 로드 + if (tabName === 'tbm-input') { + await this.api.loadTodayOnlyTbm(); + this.displayTodayTbmSessions(); + } else if (tabName === 'tbm-manage') { + await this.api.loadRecentTbmGroupedByDate(); + this.displayTbmGroupedByDate(); + this.updateViewModeIndicator(); + } + } + + /** + * 오늘의 TBM 세션 표시 + */ + displayTodayTbmSessions() { + const grid = document.getElementById('todayTbmGrid'); + const emptyState = document.getElementById('todayEmptyState'); + const todayTotalEl = document.getElementById('todayTotalSessions'); + const todayCompletedEl = document.getElementById('todayCompletedSessions'); + const todayActiveEl = document.getElementById('todayActiveSessions'); + + const sessions = this.state.todaySessions; + + if (sessions.length === 0) { + if (grid) grid.innerHTML = ''; + if (emptyState) emptyState.style.display = 'flex'; + if (todayTotalEl) todayTotalEl.textContent = '0'; + if (todayCompletedEl) todayCompletedEl.textContent = '0'; + if (todayActiveEl) todayActiveEl.textContent = '0'; + return; + } + + if (emptyState) emptyState.style.display = 'none'; + + const completedCount = sessions.filter(s => s.status === 'completed').length; + const activeCount = sessions.filter(s => s.status === 'draft').length; + + if (todayTotalEl) todayTotalEl.textContent = sessions.length; + if (todayCompletedEl) todayCompletedEl.textContent = completedCount; + if (todayActiveEl) todayActiveEl.textContent = activeCount; + + if (grid) { + grid.innerHTML = sessions.map(session => this.createSessionCard(session)).join(''); + } + } + + /** + * 날짜별 그룹으로 TBM 표시 + */ + displayTbmGroupedByDate() { + const container = document.getElementById('tbmDateGroupsContainer'); + const emptyState = document.getElementById('emptyState'); + const totalSessionsEl = document.getElementById('totalSessions'); + const completedSessionsEl = document.getElementById('completedSessions'); + + if (!container) return; + + const sortedDates = Object.keys(this.state.dateGroupedSessions).sort((a, b) => + new Date(b) - new Date(a) + ); + + if (sortedDates.length === 0 || this.state.allLoadedSessions.length === 0) { + container.innerHTML = ''; + if (emptyState) emptyState.style.display = 'flex'; + if (totalSessionsEl) totalSessionsEl.textContent = '0'; + if (completedSessionsEl) completedSessionsEl.textContent = '0'; + return; + } + + if (emptyState) emptyState.style.display = 'none'; + + // 통계 업데이트 + const completedCount = this.state.allLoadedSessions.filter(s => s.status === 'completed').length; + if (totalSessionsEl) totalSessionsEl.textContent = this.state.allLoadedSessions.length; + if (completedSessionsEl) completedSessionsEl.textContent = completedCount; + + // 날짜별 그룹 HTML 생성 + const today = this.utils.getTodayKST(); + const dayNames = ['일', '월', '화', '수', '목', '금', '토']; + + container.innerHTML = sortedDates.map(date => { + const sessions = this.state.dateGroupedSessions[date]; + const dateObj = new Date(date + 'T00:00:00'); + const dayName = dayNames[dateObj.getDay()]; + const isToday = date === today; + + const [year, month, day] = date.split('-'); + const displayDate = `${parseInt(month)}월 ${parseInt(day)}일`; + + return ` +
+
+ + ${displayDate} + ${dayName}요일 + ${isToday ? '오늘' : ''} + ${sessions.length}건 +
+
+
+ ${sessions.map(session => this.createSessionCard(session)).join('')} +
+
+
+ `; + }).join(''); + } + + /** + * 뷰 모드 표시 업데이트 + */ + updateViewModeIndicator() { + const indicator = document.getElementById('viewModeIndicator'); + const text = document.getElementById('viewModeText'); + + if (indicator && text) { + if (this.state.isAdminUser()) { + indicator.style.display = 'none'; + } else { + indicator.style.display = 'inline-flex'; + text.textContent = '내 TBM'; + } + } + } + + /** + * TBM 세션 카드 생성 + */ + createSessionCard(session) { + const statusBadge = this.utils.getStatusBadge(session.status); + + const leaderName = session.leader_name || session.created_by_name || '작업 책임자'; + const leaderRole = session.leader_name + ? (session.leader_job_type || '작업자') + : '관리자'; + + return ` +
+
+
+
+

+ ${leaderName} + ${leaderRole} +

+
+ ${statusBadge} +
+
+ 📅 + ${this.utils.formatDate(session.session_date)} ${session.start_time ? '| ' + session.start_time : ''} +
+
+ +
+
+
+ 프로젝트 + ${session.project_name || '-'} +
+
+ 공정 + ${session.work_type_name || '-'} +
+
+ 작업장 + ${session.work_location || '-'} +
+
+ 팀원 + ${session.team_member_count || 0}명 +
+
+
+ + ${session.status === 'draft' ? ` + + ` : ''} +
+ `; + } + + /** + * 디버그 + */ + debug() { + console.log('[TbmController] 상태 디버그:'); + this.state.debug(); + } +} + +// 전역 인스턴스 생성 +window.TbmController = new TbmController(); + +// 하위 호환성: 기존 전역 함수들 +window.switchTbmTab = (tabName) => window.TbmController.switchTbmTab(tabName); +window.displayTodayTbmSessions = () => window.TbmController.displayTodayTbmSessions(); +window.displayTbmGroupedByDate = () => window.TbmController.displayTbmGroupedByDate(); +window.displayTbmSessions = () => window.TbmController.displayTbmGroupedByDate(); +window.createSessionCard = (session) => window.TbmController.createSessionCard(session); +window.updateViewModeIndicator = () => window.TbmController.updateViewModeIndicator(); + +// 날짜 그룹 토글 +window.toggleDateGroup = function(date) { + const group = document.querySelector(`.tbm-date-group[data-date="${date}"]`); + if (group) { + group.classList.toggle('collapsed'); + } +}; + +// DOMContentLoaded 이벤트에서 초기화 +document.addEventListener('DOMContentLoaded', () => { + setTimeout(() => { + window.TbmController.init(); + }, 100); +}); + +console.log('[Module] tbm/index.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/tbm/state.js b/deploy/tkfb-package/web-ui/js/tbm/state.js new file mode 100644 index 0000000..aacdc9f --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/tbm/state.js @@ -0,0 +1,392 @@ +/** + * TBM - State Manager + * TBM 페이지의 전역 상태 관리 + */ + +class TbmState { + constructor() { + // 세션 데이터 + this.allSessions = []; + this.todaySessions = []; + this.dateGroupedSessions = {}; + this.allLoadedSessions = []; + this.loadedDaysCount = 7; + + // 마스터 데이터 + this.allWorkers = []; + this.allProjects = []; + this.allWorkTypes = []; + this.allTasks = []; + this.allSafetyChecks = []; + this.allWorkplaces = []; + this.allWorkplaceCategories = []; + + // 현재 상태 + this.currentUser = null; + this.currentSessionId = null; + this.currentTab = 'tbm-input'; + + // 작업자 관련 + this.selectedWorkers = new Set(); + this.workerTaskList = []; + this.selectedWorkersInModal = new Set(); + this.currentEditingTaskLine = null; + + // 작업장 선택 관련 + this.selectedCategory = null; + this.selectedWorkplace = null; + this.selectedCategoryName = ''; + this.selectedWorkplaceName = ''; + + // 일괄 설정 관련 + this.isBulkMode = false; + this.bulkSelectedWorkers = new Set(); + + // 지도 관련 + this.mapCanvas = null; + this.mapCtx = null; + this.mapImage = null; + this.mapRegions = []; + + // 리스너 + this.listeners = new Map(); + + console.log('[TbmState] 초기화 완료'); + } + + /** + * 상태 업데이트 + */ + update(key, value) { + const prevValue = this[key]; + this[key] = value; + this.notifyListeners(key, value, prevValue); + } + + /** + * 리스너 등록 + */ + subscribe(key, callback) { + if (!this.listeners.has(key)) { + this.listeners.set(key, []); + } + this.listeners.get(key).push(callback); + } + + /** + * 리스너 알림 + */ + notifyListeners(key, newValue, prevValue) { + const keyListeners = this.listeners.get(key) || []; + keyListeners.forEach(callback => { + try { + callback(newValue, prevValue); + } catch (error) { + console.error(`[TbmState] 리스너 오류 (${key}):`, error); + } + }); + } + + /** + * 현재 사용자 정보 가져오기 + */ + getUser() { + if (!this.currentUser) { + const userInfo = localStorage.getItem('user'); + this.currentUser = userInfo ? JSON.parse(userInfo) : null; + } + return this.currentUser; + } + + /** + * Admin 여부 확인 + */ + isAdminUser() { + const user = this.getUser(); + if (!user) return false; + return user.role === 'Admin' || user.role === 'System Admin'; + } + + /** + * 탭 변경 + */ + setCurrentTab(tab) { + const prevTab = this.currentTab; + this.currentTab = tab; + this.notifyListeners('currentTab', tab, prevTab); + } + + /** + * 작업자 목록에 추가 + */ + addWorkerToList(worker) { + this.workerTaskList.push({ + worker_id: worker.worker_id, + worker_name: worker.worker_name, + job_type: worker.job_type, + tasks: [this.createEmptyTaskLine()] + }); + this.notifyListeners('workerTaskList', this.workerTaskList, null); + } + + /** + * 빈 작업 라인 생성 + */ + createEmptyTaskLine() { + return { + task_line_id: this.generateUUID(), + project_id: null, + work_type_id: null, + task_id: null, + workplace_category_id: null, + workplace_id: null, + workplace_category_name: '', + workplace_name: '', + work_detail: null, + is_present: true + }; + } + + /** + * 작업자에 작업 라인 추가 + */ + addTaskLineToWorker(workerIndex) { + if (this.workerTaskList[workerIndex]) { + this.workerTaskList[workerIndex].tasks.push(this.createEmptyTaskLine()); + this.notifyListeners('workerTaskList', this.workerTaskList, null); + } + } + + /** + * 작업 라인 제거 + */ + removeTaskLine(workerIndex, taskIndex) { + if (this.workerTaskList[workerIndex]?.tasks) { + this.workerTaskList[workerIndex].tasks.splice(taskIndex, 1); + this.notifyListeners('workerTaskList', this.workerTaskList, null); + } + } + + /** + * 작업자 제거 + */ + removeWorkerFromList(workerIndex) { + const removed = this.workerTaskList.splice(workerIndex, 1); + this.notifyListeners('workerTaskList', this.workerTaskList, null); + return removed[0]; + } + + /** + * 작업장 선택 초기화 + */ + resetWorkplaceSelection() { + this.selectedCategory = null; + this.selectedWorkplace = null; + this.selectedCategoryName = ''; + this.selectedWorkplaceName = ''; + this.mapCanvas = null; + this.mapCtx = null; + this.mapImage = null; + this.mapRegions = []; + } + + /** + * 일괄 설정 초기화 + */ + resetBulkSettings() { + this.isBulkMode = false; + this.bulkSelectedWorkers.clear(); + } + + /** + * 날짜별 세션 그룹화 + */ + groupSessionsByDate(sessions) { + this.dateGroupedSessions = {}; + this.allLoadedSessions = []; + + sessions.forEach(session => { + const date = this.formatDate(session.session_date); + if (!this.dateGroupedSessions[date]) { + this.dateGroupedSessions[date] = []; + } + this.dateGroupedSessions[date].push(session); + this.allLoadedSessions.push(session); + }); + } + + /** + * 날짜 포맷팅 + */ + formatDate(dateString) { + if (!dateString) return ''; + if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) { + return dateString; + } + const date = new Date(dateString); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; + } + + /** + * UUID 생성 + */ + generateUUID() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + const r = Math.random() * 16 | 0; + const v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + + /** + * 상태 초기화 + */ + reset() { + this.workerTaskList = []; + this.selectedWorkers.clear(); + this.selectedWorkersInModal.clear(); + this.currentEditingTaskLine = null; + this.resetWorkplaceSelection(); + this.resetBulkSettings(); + } + + /** + * 디버그 출력 + */ + debug() { + console.log('[TbmState] 현재 상태:', { + allSessions: this.allSessions.length, + todaySessions: this.todaySessions.length, + allWorkers: this.allWorkers.length, + allProjects: this.allProjects.length, + workerTaskList: this.workerTaskList.length, + currentTab: this.currentTab + }); + } +} + +// 전역 인스턴스 생성 +window.TbmState = new TbmState(); + +// 하위 호환성을 위한 전역 변수 프록시 +const tbmStateProxy = window.TbmState; + +Object.defineProperties(window, { + allSessions: { + get: () => tbmStateProxy.allSessions, + set: (v) => { tbmStateProxy.allSessions = v; } + }, + todaySessions: { + get: () => tbmStateProxy.todaySessions, + set: (v) => { tbmStateProxy.todaySessions = v; } + }, + allWorkers: { + get: () => tbmStateProxy.allWorkers, + set: (v) => { tbmStateProxy.allWorkers = v; } + }, + allProjects: { + get: () => tbmStateProxy.allProjects, + set: (v) => { tbmStateProxy.allProjects = v; } + }, + allWorkTypes: { + get: () => tbmStateProxy.allWorkTypes, + set: (v) => { tbmStateProxy.allWorkTypes = v; } + }, + allTasks: { + get: () => tbmStateProxy.allTasks, + set: (v) => { tbmStateProxy.allTasks = v; } + }, + allSafetyChecks: { + get: () => tbmStateProxy.allSafetyChecks, + set: (v) => { tbmStateProxy.allSafetyChecks = v; } + }, + allWorkplaces: { + get: () => tbmStateProxy.allWorkplaces, + set: (v) => { tbmStateProxy.allWorkplaces = v; } + }, + allWorkplaceCategories: { + get: () => tbmStateProxy.allWorkplaceCategories, + set: (v) => { tbmStateProxy.allWorkplaceCategories = v; } + }, + currentUser: { + get: () => tbmStateProxy.currentUser, + set: (v) => { tbmStateProxy.currentUser = v; } + }, + currentSessionId: { + get: () => tbmStateProxy.currentSessionId, + set: (v) => { tbmStateProxy.currentSessionId = v; } + }, + selectedWorkers: { + get: () => tbmStateProxy.selectedWorkers, + set: (v) => { tbmStateProxy.selectedWorkers = v; } + }, + workerTaskList: { + get: () => tbmStateProxy.workerTaskList, + set: (v) => { tbmStateProxy.workerTaskList = v; } + }, + selectedWorkersInModal: { + get: () => tbmStateProxy.selectedWorkersInModal, + set: (v) => { tbmStateProxy.selectedWorkersInModal = v; } + }, + currentEditingTaskLine: { + get: () => tbmStateProxy.currentEditingTaskLine, + set: (v) => { tbmStateProxy.currentEditingTaskLine = v; } + }, + selectedCategory: { + get: () => tbmStateProxy.selectedCategory, + set: (v) => { tbmStateProxy.selectedCategory = v; } + }, + selectedWorkplace: { + get: () => tbmStateProxy.selectedWorkplace, + set: (v) => { tbmStateProxy.selectedWorkplace = v; } + }, + selectedCategoryName: { + get: () => tbmStateProxy.selectedCategoryName, + set: (v) => { tbmStateProxy.selectedCategoryName = v; } + }, + selectedWorkplaceName: { + get: () => tbmStateProxy.selectedWorkplaceName, + set: (v) => { tbmStateProxy.selectedWorkplaceName = v; } + }, + isBulkMode: { + get: () => tbmStateProxy.isBulkMode, + set: (v) => { tbmStateProxy.isBulkMode = v; } + }, + bulkSelectedWorkers: { + get: () => tbmStateProxy.bulkSelectedWorkers, + set: (v) => { tbmStateProxy.bulkSelectedWorkers = v; } + }, + dateGroupedSessions: { + get: () => tbmStateProxy.dateGroupedSessions, + set: (v) => { tbmStateProxy.dateGroupedSessions = v; } + }, + allLoadedSessions: { + get: () => tbmStateProxy.allLoadedSessions, + set: (v) => { tbmStateProxy.allLoadedSessions = v; } + }, + loadedDaysCount: { + get: () => tbmStateProxy.loadedDaysCount, + set: (v) => { tbmStateProxy.loadedDaysCount = v; } + }, + mapRegions: { + get: () => tbmStateProxy.mapRegions, + set: (v) => { tbmStateProxy.mapRegions = v; } + }, + mapCanvas: { + get: () => tbmStateProxy.mapCanvas, + set: (v) => { tbmStateProxy.mapCanvas = v; } + }, + mapCtx: { + get: () => tbmStateProxy.mapCtx, + set: (v) => { tbmStateProxy.mapCtx = v; } + }, + mapImage: { + get: () => tbmStateProxy.mapImage, + set: (v) => { tbmStateProxy.mapImage = v; } + } +}); + +console.log('[Module] tbm/state.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/tbm/utils.js b/deploy/tkfb-package/web-ui/js/tbm/utils.js new file mode 100644 index 0000000..7926a43 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/tbm/utils.js @@ -0,0 +1,253 @@ +/** + * TBM - Utilities + * TBM 관련 유틸리티 함수들 + */ + +class TbmUtils { + constructor() { + console.log('[TbmUtils] 초기화 완료'); + } + + /** + * 서울 시간대(Asia/Seoul, UTC+9) 기준 오늘 날짜를 YYYY-MM-DD 형식으로 반환 + */ + getTodayKST() { + const now = new Date(); + const kstOffset = 9 * 60; + const utc = now.getTime() + (now.getTimezoneOffset() * 60000); + const kstTime = new Date(utc + (kstOffset * 60000)); + + const year = kstTime.getFullYear(); + const month = String(kstTime.getMonth() + 1).padStart(2, '0'); + const day = String(kstTime.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; + } + + /** + * ISO 날짜 문자열을 YYYY-MM-DD 형식으로 변환 + */ + formatDate(dateString) { + if (!dateString) return ''; + + if (/^\d{4}-\d{2}-\d{2}$/.test(dateString)) { + return dateString; + } + + const date = new Date(dateString); + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; + } + + /** + * 날짜 표시용 포맷 (MM월 DD일) + */ + formatDateDisplay(dateString) { + if (!dateString) return ''; + const [year, month, day] = dateString.split('-'); + return `${parseInt(month)}월 ${parseInt(day)}일`; + } + + /** + * 날짜를 연/월/일/요일 형식으로 포맷 + */ + formatDateFull(dateString) { + if (!dateString) return ''; + const dayNames = ['일', '월', '화', '수', '목', '금', '토']; + const [year, month, day] = dateString.split('-'); + const dateObj = new Date(dateString); + const dayName = dayNames[dateObj.getDay()]; + return `${year}년 ${parseInt(month)}월 ${parseInt(day)}일 (${dayName})`; + } + + /** + * 요일 반환 + */ + getDayOfWeek(dateString) { + const dayNames = ['일', '월', '화', '수', '목', '금', '토']; + const dateObj = new Date(dateString + 'T00:00:00'); + return dayNames[dateObj.getDay()]; + } + + /** + * 오늘인지 확인 + */ + isToday(dateString) { + const today = this.getTodayKST(); + return this.formatDate(dateString) === today; + } + + /** + * 현재 시간을 HH:MM 형식으로 반환 + */ + getCurrentTime() { + return new Date().toTimeString().slice(0, 5); + } + + /** + * UUID 생성 + */ + generateUUID() { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + const r = Math.random() * 16 | 0; + const v = c === 'x' ? r : (r & 0x3 | 0x8); + return v.toString(16); + }); + } + + /** + * HTML 이스케이프 + */ + escapeHtml(text) { + if (!text) return ''; + const div = document.createElement('div'); + div.textContent = text; + return div.innerHTML; + } + + /** + * 날씨 조건명 반환 + */ + getWeatherConditionName(code) { + const names = { + clear: '맑음', + rain: '비', + snow: '눈', + heat: '폭염', + cold: '한파', + wind: '강풍', + fog: '안개', + dust: '미세먼지' + }; + return names[code] || code; + } + + /** + * 날씨 아이콘 반환 + */ + getWeatherIcon(code) { + const icons = { + clear: '☀️', + rain: '🌧️', + snow: '❄️', + heat: '🔥', + cold: '🥶', + wind: '💨', + fog: '🌫️', + dust: '😷' + }; + return icons[code] || '🌤️'; + } + + /** + * 카테고리명 반환 + */ + getCategoryName(category) { + const names = { + 'PPE': '개인 보호 장비', + 'EQUIPMENT': '장비 점검', + 'ENVIRONMENT': '작업 환경', + 'EMERGENCY': '비상 대응', + 'WEATHER': '날씨', + 'TASK': '작업' + }; + return names[category] || category; + } + + /** + * 상태 배지 HTML 반환 + */ + getStatusBadge(status) { + const badges = { + 'draft': '진행중', + 'completed': '완료', + 'cancelled': '취소' + }; + return badges[status] || ''; + } +} + +// 전역 인스턴스 생성 +window.TbmUtils = new TbmUtils(); + +// 하위 호환성: 기존 함수들 +window.getTodayKST = () => window.TbmUtils.getTodayKST(); +window.formatDate = (dateString) => window.TbmUtils.formatDate(dateString); + +// 토스트 알림 +window.showToast = function(message, type = 'info', duration = 3000) { + const container = document.getElementById('toastContainer'); + if (!container) { + console.log(`[Toast] ${type}: ${message}`); + return; + } + + const toast = document.createElement('div'); + toast.className = `toast ${type}`; + + const iconMap = { + success: '✅', + error: '❌', + warning: '⚠️', + info: 'ℹ️' + }; + + toast.innerHTML = ` +
${iconMap[type] || 'ℹ️'}
+
${message}
+ + `; + + toast.style.cssText = ` + display: flex; + align-items: center; + gap: 0.75rem; + padding: 1rem 1.25rem; + background: white; + border-radius: 0.5rem; + box-shadow: 0 10px 15px -3px rgb(0 0 0 / 0.1); + margin-bottom: 0.75rem; + min-width: 300px; + animation: slideIn 0.3s ease-out; + `; + + container.appendChild(toast); + + setTimeout(() => { + if (toast.parentElement) { + toast.style.animation = 'slideOut 0.3s ease-out'; + setTimeout(() => toast.remove(), 300); + } + }, duration); +}; + +// 카테고리별 그룹화 +window.groupChecksByCategory = function(checks) { + return checks.reduce((acc, check) => { + const category = check.check_category || 'OTHER'; + if (!acc[category]) acc[category] = []; + acc[category].push(check); + return acc; + }, {}); +}; + +// 작업별 그룹화 +window.groupChecksByTask = function(checks) { + return checks.reduce((acc, check) => { + const taskId = check.task_id || 0; + const taskName = check.task_name || '기타 작업'; + if (!acc[taskId]) acc[taskId] = { name: taskName, items: [] }; + acc[taskId].items.push(check); + return acc; + }, {}); +}; + +// Admin 사용자 확인 +window.isAdminUser = function() { + return window.TbmState?.isAdminUser() || false; +}; + +console.log('[Module] tbm/utils.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/user-dashboard.js b/deploy/tkfb-package/web-ui/js/user-dashboard.js new file mode 100644 index 0000000..fee8d7a --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/user-dashboard.js @@ -0,0 +1,93 @@ +// /js/user-dashboard.js +import { getUser } from './auth.js'; +import { apiGet } from './api-helper.js'; // 개선된 api-helper를 사용합니다. + +/** + * API를 호출하여 오늘의 작업 일정을 불러와 화면에 표시합니다. + */ +async function loadTodaySchedule() { + const scheduleContainer = document.getElementById('today-schedule'); + scheduleContainer.innerHTML = '

📅 오늘의 작업 일정을 불러오는 중...

'; + + try { + // 예시: /api/dashboard/today-schedule 엔드포인트에서 데이터를 가져옵니다. + // 실제 엔드포인트는 백엔드 구현에 따라 달라질 수 있습니다. + const scheduleData = await apiGet('/dashboard/today-schedule'); + + if (scheduleData && scheduleData.length > 0) { + const scheduleHtml = scheduleData.map(item => ` +
+ ${item.time} + ${item.task_name} + ${item.status_kor} +
+ `).join(''); + scheduleContainer.innerHTML = scheduleHtml; + } else { + scheduleContainer.innerHTML = '

오늘 예정된 작업이 없습니다.

'; + } + } catch (error) { + console.error('오늘의 작업 일정 로드 실패:', error); + scheduleContainer.innerHTML = '

일정 정보를 불러오는 데 실패했습니다.

'; + } +} + +/** + * API를 호출하여 현재 사용자의 작업 통계를 불러와 화면에 표시합니다. + */ +async function loadWorkStats() { + const statsContainer = document.getElementById('work-stats'); + statsContainer.innerHTML = '

📈 내 작업 현황을 불러오는 중...

'; + + try { + // 예시: /api/dashboard/my-stats 엔드포인트에서 데이터를 가져옵니다. + const statsData = await apiGet('/dashboard/my-stats'); + + if (statsData) { + const statsHtml = ` +
+ 이번 주 작업 시간: + ${statsData.weekly_hours || 0} 시간 +
+
+ 이번 달 작업 시간: + ${statsData.monthly_hours || 0} 시간 +
+
+ 완료한 작업 수: + ${statsData.completed_tasks || 0} 건 +
+ `; + statsContainer.innerHTML = statsHtml; + } else { + statsContainer.innerHTML = '

표시할 통계 정보가 없습니다.

'; + } + } catch (error) { + console.error('작업 통계 로드 실패:', error); + statsContainer.innerHTML = '

통계 정보를 불러오는 데 실패했습니다.

'; + } +} + +/** + * 환영 메시지를 사용자 이름으로 개인화합니다. + */ +function personalizeWelcome() { + // 전역 변수 대신 auth.js 모듈을 통해 사용자 정보를 가져옵니다. + const user = getUser(); + if (user) { + const welcomeEl = document.getElementById('welcome-message'); + if (welcomeEl) { + welcomeEl.textContent = `${user.name || user.username}님, 환영합니다! 오늘 하루도 안전하게 작업하세요.`; + } + } +} + +// 페이지 초기화 함수 +function initializeDashboard() { + personalizeWelcome(); + loadTodaySchedule(); + loadWorkStats(); +} + +// DOM이 로드되면 대시보드 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializeDashboard); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/vacation-allocation.js b/deploy/tkfb-package/web-ui/js/vacation-allocation.js new file mode 100644 index 0000000..cb2a04b --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/vacation-allocation.js @@ -0,0 +1,864 @@ +/** + * vacation-allocation.js + * 휴가 발생 입력 페이지 로직 + */ + +import { API_BASE_URL } from './api-config.js'; + +// 전역 변수 +let workers = []; +let vacationTypes = []; +let currentWorkerBalances = []; + +/** + * 페이지 초기화 + */ +document.addEventListener('DOMContentLoaded', async () => { + // 관리자 권한 체크 + const user = JSON.parse(localStorage.getItem('user') || '{}'); + console.log('Current user:', user); + console.log('Role ID:', user.role_id, 'Role:', user.role); + + // role이 'Admin'이거나 role_id가 1 또는 2인 경우 허용 + const isAdmin = user.role === 'Admin' || [1, 2].includes(user.role_id); + + if (!isAdmin) { + console.error('Access denied. User:', user); + alert('관리자만 접근할 수 있습니다'); + window.location.href = '/pages/dashboard.html'; + return; + } + + await loadInitialData(); + initializeYearSelectors(); + initializeTabNavigation(); + initializeEventListeners(); +}); + +/** + * 초기 데이터 로드 + */ +async function loadInitialData() { + await Promise.all([ + loadWorkers(), + loadVacationTypes() + ]); +} + +/** + * 작업자 목록 로드 + */ +async function loadWorkers() { + try { + const token = localStorage.getItem('token'); + console.log('Loading workers... Token:', token ? 'exists' : 'missing'); + + const response = await fetch(`${API_BASE_URL}/api/workers`, { + headers: { + 'Authorization': `Bearer ${token}` + } + }); + + console.log('Workers API Response status:', response.status); + + if (!response.ok) { + const errorData = await response.json(); + console.error('Workers API Error:', errorData); + throw new Error(errorData.message || '작업자 목록 로드 실패'); + } + + const result = await response.json(); + console.log('Workers data:', result); + workers = result.data || []; + + if (workers.length === 0) { + console.warn('No workers found in database'); + showToast('등록된 작업자가 없습니다', 'warning'); + return; + } + + // 개별 입력 탭 - 작업자 셀렉트 박스 + const selectWorker = document.getElementById('individualWorker'); + workers.forEach(worker => { + const option = document.createElement('option'); + option.value = worker.worker_id; + option.textContent = `${worker.worker_name} (${worker.employment_status === 'employed' ? '재직' : '퇴사'})`; + selectWorker.appendChild(option); + }); + console.log(`Loaded ${workers.length} workers successfully`); + } catch (error) { + console.error('작업자 로드 오류:', error); + showToast(`작업자 목록을 불러오는데 실패했습니다: ${error.message}`, 'error'); + } +} + +/** + * 휴가 유형 목록 로드 + */ +async function loadVacationTypes() { + try { + const token = localStorage.getItem('token'); + const response = await fetch(`${API_BASE_URL}/api/vacation-types`, { + headers: { + 'Authorization': `Bearer ${token}` + } + }); + + if (!response.ok) throw new Error('휴가 유형 로드 실패'); + + const result = await response.json(); + vacationTypes = result.data || []; + + // 개별 입력 탭 - 휴가 유형 셀렉트 박스 + const selectType = document.getElementById('individualVacationType'); + vacationTypes.forEach(type => { + const option = document.createElement('option'); + option.value = type.id; + option.textContent = `${type.type_name} ${type.is_special ? '(특별)' : ''}`; + selectType.appendChild(option); + }); + + // 특별 휴가 관리 탭 테이블 로드 + loadSpecialTypesTable(); + } catch (error) { + console.error('휴가 유형 로드 오류:', error); + showToast('휴가 유형을 불러오는데 실패했습니다', 'error'); + } +} + +/** + * 연도 셀렉터 초기화 + */ +function initializeYearSelectors() { + const currentYear = new Date().getFullYear(); + const yearSelectors = ['individualYear', 'bulkYear']; + + yearSelectors.forEach(selectorId => { + const select = document.getElementById(selectorId); + for (let year = currentYear - 1; year <= currentYear + 2; year++) { + const option = document.createElement('option'); + option.value = year; + option.textContent = `${year}년`; + if (year === currentYear) { + option.selected = true; + } + select.appendChild(option); + } + }); +} + +/** + * 탭 네비게이션 초기화 + */ +function initializeTabNavigation() { + const tabButtons = document.querySelectorAll('.tab-button'); + tabButtons.forEach(button => { + button.addEventListener('click', () => { + const tabName = button.dataset.tab; + switchTab(tabName); + }); + }); +} + +/** + * 탭 전환 + */ +function switchTab(tabName) { + // 탭 버튼 활성화 + document.querySelectorAll('.tab-button').forEach(btn => { + btn.classList.remove('active'); + }); + document.querySelector(`[data-tab="${tabName}"]`).classList.add('active'); + + // 탭 콘텐츠 표시 + document.querySelectorAll('.tab-content').forEach(content => { + content.classList.remove('active'); + }); + document.getElementById(`tab-${tabName}`).classList.add('active'); +} + +/** + * 이벤트 리스너 초기화 + */ +function initializeEventListeners() { + // === 탭 1: 개별 입력 === + document.getElementById('individualWorker').addEventListener('change', loadWorkerBalances); + document.getElementById('autoCalculateBtn').addEventListener('click', autoCalculateAnnualLeave); + document.getElementById('individualSubmitBtn').addEventListener('click', submitIndividualVacation); + document.getElementById('individualResetBtn').addEventListener('click', resetIndividualForm); + + // === 탭 2: 일괄 입력 === + document.getElementById('bulkPreviewBtn').addEventListener('click', previewBulkAllocation); + document.getElementById('bulkSubmitBtn').addEventListener('click', submitBulkAllocation); + + // === 탭 3: 특별 휴가 관리 === + document.getElementById('addSpecialTypeBtn').addEventListener('click', () => openVacationTypeModal()); + + // 모달 닫기 + document.querySelectorAll('.modal-close').forEach(btn => { + btn.addEventListener('click', closeModals); + }); + + // 모달 폼 제출 + document.getElementById('vacationTypeForm').addEventListener('submit', submitVacationType); + document.getElementById('editBalanceForm').addEventListener('submit', submitEditBalance); +} + +// ============================================================================= +// 탭 1: 개별 입력 +// ============================================================================= + +/** + * 작업자의 기존 휴가 잔액 로드 + */ +async function loadWorkerBalances() { + const workerId = document.getElementById('individualWorker').value; + const year = document.getElementById('individualYear').value; + + if (!workerId) { + document.getElementById('individualTableBody').innerHTML = ` +

작업자를 선택하세요

+ `; + return; + } + + try { + const token = localStorage.getItem('token'); + const response = await fetch(`${API_BASE_URL}/api/vacation-balances/worker/${workerId}/year/${year}`, { + headers: { + 'Authorization': `Bearer ${token}` + } + }); + + if (!response.ok) throw new Error('휴가 잔액 로드 실패'); + + const result = await response.json(); + currentWorkerBalances = result.data || []; + + updateWorkerBalancesTable(); + } catch (error) { + console.error('휴가 잔액 로드 오류:', error); + showToast('휴가 잔액을 불러오는데 실패했습니다', 'error'); + } +} + +/** + * 작업자 휴가 잔액 테이블 업데이트 + */ +function updateWorkerBalancesTable() { + const tbody = document.getElementById('individualTableBody'); + + if (currentWorkerBalances.length === 0) { + tbody.innerHTML = ` +

등록된 휴가가 없습니다

+ `; + return; + } + + tbody.innerHTML = currentWorkerBalances.map(balance => ` + + ${balance.worker_name || '-'} + ${balance.year} + ${balance.type_name} ${balance.is_special ? '특별' : ''} + ${balance.total_days}일 + ${balance.used_days}일 + ${balance.remaining_days}일 + ${balance.notes || '-'} + + + + + + `).join(''); +} + +/** + * 자동 계산 (연차만 해당) + */ +async function autoCalculateAnnualLeave() { + const workerId = document.getElementById('individualWorker').value; + const year = document.getElementById('individualYear').value; + const typeId = document.getElementById('individualVacationType').value; + + if (!workerId) { + showToast('작업자를 선택하세요', 'warning'); + return; + } + + // 선택한 휴가 유형이 ANNUAL인지 확인 + const selectedType = vacationTypes.find(t => t.id == typeId); + if (!selectedType || selectedType.type_code !== 'ANNUAL') { + showToast('연차(ANNUAL) 유형만 자동 계산이 가능합니다', 'warning'); + return; + } + + // 작업자의 입사일 조회 + const worker = workers.find(w => w.worker_id == workerId); + if (!worker || !worker.hire_date) { + showToast('작업자의 입사일 정보가 없습니다', 'error'); + return; + } + + try { + const token = localStorage.getItem('token'); + const response = await fetch(`${API_BASE_URL}/api/vacation-balances/auto-calculate`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + worker_id: workerId, + hire_date: worker.hire_date, + year: year + }) + }); + + const result = await response.json(); + + if (!response.ok) { + throw new Error(result.message || '자동 계산 실패'); + } + + // 계산 결과 표시 + const resultDiv = document.getElementById('autoCalculateResult'); + resultDiv.innerHTML = ` + 자동 계산 완료
+ 입사일: ${worker.hire_date}
+ 계산된 연차: ${result.data.calculated_days}일
+ 아래 "총 부여 일수"에 자동으로 입력됩니다. + `; + resultDiv.style.display = 'block'; + + // 폼에 자동 입력 + document.getElementById('individualTotalDays').value = result.data.calculated_days; + document.getElementById('individualNotes').value = `근속년수 기반 자동 계산 (입사일: ${worker.hire_date})`; + + showToast(result.message, 'success'); + + // 기존 데이터 새로고침 + await loadWorkerBalances(); + } catch (error) { + console.error('자동 계산 오류:', error); + showToast(error.message, 'error'); + } +} + +/** + * 개별 휴가 제출 + */ +async function submitIndividualVacation() { + const workerId = document.getElementById('individualWorker').value; + const year = document.getElementById('individualYear').value; + const typeId = document.getElementById('individualVacationType').value; + const totalDays = document.getElementById('individualTotalDays').value; + const usedDays = document.getElementById('individualUsedDays').value || 0; + const notes = document.getElementById('individualNotes').value; + + if (!workerId || !year || !typeId || !totalDays) { + showToast('필수 항목을 모두 입력하세요', 'warning'); + return; + } + + try { + const token = localStorage.getItem('token'); + const response = await fetch(`${API_BASE_URL}/api/vacation-balances`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + worker_id: workerId, + vacation_type_id: typeId, + year: year, + total_days: parseFloat(totalDays), + used_days: parseFloat(usedDays), + notes: notes + }) + }); + + const result = await response.json(); + + if (!response.ok) { + throw new Error(result.message || '저장 실패'); + } + + showToast('휴가가 등록되었습니다', 'success'); + resetIndividualForm(); + await loadWorkerBalances(); + } catch (error) { + console.error('휴가 등록 오류:', error); + showToast(error.message, 'error'); + } +} + +/** + * 개별 입력 폼 초기화 + */ +function resetIndividualForm() { + document.getElementById('individualVacationType').value = ''; + document.getElementById('individualTotalDays').value = ''; + document.getElementById('individualUsedDays').value = '0'; + document.getElementById('individualNotes').value = ''; + document.getElementById('autoCalculateResult').style.display = 'none'; +} + +/** + * 휴가 수정 (전역 함수로 노출) + */ +window.editBalance = function(balanceId) { + const balance = currentWorkerBalances.find(b => b.id === balanceId); + if (!balance) return; + + document.getElementById('editBalanceId').value = balance.id; + document.getElementById('editTotalDays').value = balance.total_days; + document.getElementById('editUsedDays').value = balance.used_days; + document.getElementById('editNotes').value = balance.notes || ''; + + document.getElementById('editBalanceModal').classList.add('active'); +}; + +/** + * 휴가 삭제 (전역 함수로 노출) + */ +window.deleteBalance = async function(balanceId) { + if (!confirm('정말 삭제하시겠습니까?')) return; + + try { + const token = localStorage.getItem('token'); + const response = await fetch(`${API_BASE_URL}/api/vacation-balances/${balanceId}`, { + method: 'DELETE', + headers: { + 'Authorization': `Bearer ${token}` + } + }); + + const result = await response.json(); + + if (!response.ok) { + throw new Error(result.message || '삭제 실패'); + } + + showToast('삭제되었습니다', 'success'); + await loadWorkerBalances(); + } catch (error) { + console.error('삭제 오류:', error); + showToast(error.message, 'error'); + } +}; + +/** + * 휴가 수정 제출 + */ +async function submitEditBalance(e) { + e.preventDefault(); + + const balanceId = document.getElementById('editBalanceId').value; + const totalDays = document.getElementById('editTotalDays').value; + const usedDays = document.getElementById('editUsedDays').value; + const notes = document.getElementById('editNotes').value; + + try { + const token = localStorage.getItem('token'); + const response = await fetch(`${API_BASE_URL}/api/vacation-balances/${balanceId}`, { + method: 'PUT', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + total_days: parseFloat(totalDays), + used_days: parseFloat(usedDays), + notes: notes + }) + }); + + const result = await response.json(); + + if (!response.ok) { + throw new Error(result.message || '수정 실패'); + } + + showToast('수정되었습니다', 'success'); + closeModals(); + await loadWorkerBalances(); + } catch (error) { + console.error('수정 오류:', error); + showToast(error.message, 'error'); + } +} + +// ============================================================================= +// 탭 2: 일괄 입력 +// ============================================================================= + +let bulkPreviewData = []; + +/** + * 일괄 할당 미리보기 + */ +async function previewBulkAllocation() { + const year = document.getElementById('bulkYear').value; + const employmentStatus = document.getElementById('bulkEmploymentStatus').value; + + // 필터링된 작업자 목록 + let targetWorkers = workers; + if (employmentStatus === 'employed') { + targetWorkers = workers.filter(w => w.employment_status === 'employed'); + } + + // ANNUAL 유형 찾기 + const annualType = vacationTypes.find(t => t.type_code === 'ANNUAL'); + if (!annualType) { + showToast('ANNUAL 휴가 유형이 없습니다', 'error'); + return; + } + + // 미리보기 데이터 생성 + bulkPreviewData = targetWorkers.map(worker => { + const hireDate = worker.hire_date; + if (!hireDate) { + return { + worker_id: worker.worker_id, + worker_name: worker.worker_name, + hire_date: '-', + years_worked: '-', + calculated_days: 0, + reason: '입사일 정보 없음', + status: 'error' + }; + } + + const calculatedDays = calculateAnnualLeaveDays(hireDate, year); + const yearsWorked = calculateYearsWorked(hireDate, year); + + return { + worker_id: worker.worker_id, + worker_name: worker.worker_name, + hire_date: hireDate, + years_worked: yearsWorked, + calculated_days: calculatedDays, + reason: getCalculationReason(yearsWorked, calculatedDays), + status: 'ready' + }; + }); + + updateBulkPreviewTable(); + document.getElementById('bulkPreviewSection').style.display = 'block'; + document.getElementById('bulkSubmitBtn').disabled = false; +} + +/** + * 연차 일수 계산 (한국 근로기준법) + */ +function calculateAnnualLeaveDays(hireDate, targetYear) { + const hire = new Date(hireDate); + const targetDate = new Date(targetYear, 0, 1); + + const monthsDiff = (targetDate.getFullYear() - hire.getFullYear()) * 12 + + (targetDate.getMonth() - hire.getMonth()); + + // 1년 미만: 월 1일 + if (monthsDiff < 12) { + return Math.floor(monthsDiff); + } + + // 1년 이상: 15일 기본 + 2년마다 1일 추가 (최대 25일) + const yearsWorked = Math.floor(monthsDiff / 12); + const additionalDays = Math.floor((yearsWorked - 1) / 2); + + return Math.min(15 + additionalDays, 25); +} + +/** + * 근속년수 계산 + */ +function calculateYearsWorked(hireDate, targetYear) { + const hire = new Date(hireDate); + const targetDate = new Date(targetYear, 0, 1); + + const monthsDiff = (targetDate.getFullYear() - hire.getFullYear()) * 12 + + (targetDate.getMonth() - hire.getMonth()); + + return (monthsDiff / 12).toFixed(1); +} + +/** + * 계산 근거 생성 + */ +function getCalculationReason(yearsWorked, days) { + const years = parseFloat(yearsWorked); + if (years < 1) { + return `입사 ${Math.floor(years * 12)}개월 (월 1일)`; + } + if (days === 25) { + return '최대 25일 (근속 3년 이상)'; + } + return `근속 ${Math.floor(years)}년 (15일 + ${days - 15}일)`; +} + +/** + * 일괄 미리보기 테이블 업데이트 + */ +function updateBulkPreviewTable() { + const tbody = document.getElementById('bulkPreviewTableBody'); + + tbody.innerHTML = bulkPreviewData.map(item => { + const statusBadge = item.status === 'error' + ? '오류' + : '준비'; + + return ` + + ${item.worker_name} + ${item.hire_date} + ${item.years_worked}년 + ${item.calculated_days}일 + ${item.reason} + ${statusBadge} + + `; + }).join(''); +} + +/** + * 일괄 할당 제출 + */ +async function submitBulkAllocation() { + const year = document.getElementById('bulkYear').value; + + // 오류가 없는 항목만 필터링 + const validItems = bulkPreviewData.filter(item => item.status !== 'error' && item.calculated_days > 0); + + if (validItems.length === 0) { + showToast('생성할 항목이 없습니다', 'warning'); + return; + } + + if (!confirm(`${validItems.length}명의 연차를 생성하시겠습니까?`)) { + return; + } + + // ANNUAL 유형 찾기 + const annualType = vacationTypes.find(t => t.type_code === 'ANNUAL'); + + let successCount = 0; + let failCount = 0; + + for (const item of validItems) { + try { + const token = localStorage.getItem('token'); + const response = await fetch(`${API_BASE_URL}/api/vacation-balances/auto-calculate`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ + worker_id: item.worker_id, + hire_date: item.hire_date, + year: year + }) + }); + + if (response.ok) { + successCount++; + } else { + failCount++; + } + } catch (error) { + failCount++; + } + } + + showToast(`완료: ${successCount}건 성공, ${failCount}건 실패`, successCount > 0 ? 'success' : 'error'); + + // 미리보기 초기화 + document.getElementById('bulkPreviewSection').style.display = 'none'; + document.getElementById('bulkSubmitBtn').disabled = true; + bulkPreviewData = []; +} + +// ============================================================================= +// 탭 3: 특별 휴가 관리 +// ============================================================================= + +/** + * 특별 휴가 유형 테이블 로드 + */ +function loadSpecialTypesTable() { + const tbody = document.getElementById('specialTypesTableBody'); + + if (vacationTypes.length === 0) { + tbody.innerHTML = ` +

등록된 휴가 유형이 없습니다

+ `; + return; + } + + tbody.innerHTML = vacationTypes.map(type => ` + + ${type.type_name} + ${type.type_code} + ${type.priority} + ${type.is_special ? '특별' : '-'} + ${type.is_system ? '시스템' : '-'} + ${type.description || '-'} + + + + + + `).join(''); +} + +/** + * 휴가 유형 모달 열기 + */ +function openVacationTypeModal(typeId = null) { + const modal = document.getElementById('vacationTypeModal'); + const form = document.getElementById('vacationTypeForm'); + form.reset(); + + if (typeId) { + const type = vacationTypes.find(t => t.id === typeId); + if (!type) return; + + document.getElementById('modalTitle').textContent = '휴가 유형 수정'; + document.getElementById('modalTypeId').value = type.id; + document.getElementById('modalTypeName').value = type.type_name; + document.getElementById('modalTypeCode').value = type.type_code; + document.getElementById('modalPriority').value = type.priority; + document.getElementById('modalIsSpecial').checked = type.is_special === 1; + document.getElementById('modalDescription').value = type.description || ''; + } else { + document.getElementById('modalTitle').textContent = '휴가 유형 추가'; + document.getElementById('modalTypeId').value = ''; + } + + modal.classList.add('active'); +} + +/** + * 휴가 유형 수정 (전역 함수) + */ +window.editVacationType = function(typeId) { + openVacationTypeModal(typeId); +}; + +/** + * 휴가 유형 삭제 (전역 함수) + */ +window.deleteVacationType = async function(typeId) { + if (!confirm('정말 삭제하시겠습니까?')) return; + + try { + const token = localStorage.getItem('token'); + const response = await fetch(`${API_BASE_URL}/api/vacation-types/${typeId}`, { + method: 'DELETE', + headers: { + 'Authorization': `Bearer ${token}` + } + }); + + const result = await response.json(); + + if (!response.ok) { + throw new Error(result.message || '삭제 실패'); + } + + showToast('삭제되었습니다', 'success'); + await loadVacationTypes(); + } catch (error) { + console.error('삭제 오류:', error); + showToast(error.message, 'error'); + } +}; + +/** + * 휴가 유형 제출 + */ +async function submitVacationType(e) { + e.preventDefault(); + + const typeId = document.getElementById('modalTypeId').value; + const typeName = document.getElementById('modalTypeName').value; + const typeCode = document.getElementById('modalTypeCode').value; + const priority = document.getElementById('modalPriority').value; + const isSpecial = document.getElementById('modalIsSpecial').checked ? 1 : 0; + const description = document.getElementById('modalDescription').value; + + const data = { + type_name: typeName, + type_code: typeCode.toUpperCase(), + priority: parseInt(priority), + is_special: isSpecial, + description: description + }; + + try { + const token = localStorage.getItem('token'); + const url = typeId + ? `${API_BASE_URL}/api/vacation-types/${typeId}` + : `${API_BASE_URL}/api/vacation-types`; + + const response = await fetch(url, { + method: typeId ? 'PUT' : 'POST', + headers: { + 'Authorization': `Bearer ${token}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify(data) + }); + + const result = await response.json(); + + if (!response.ok) { + throw new Error(result.message || '저장 실패'); + } + + showToast(typeId ? '수정되었습니다' : '추가되었습니다', 'success'); + closeModals(); + await loadVacationTypes(); + } catch (error) { + console.error('저장 오류:', error); + showToast(error.message, 'error'); + } +} + +// ============================================================================= +// 공통 함수 +// ============================================================================= + +/** + * 모달 닫기 + */ +function closeModals() { + document.querySelectorAll('.modal').forEach(modal => { + modal.classList.remove('active'); + }); +} + +/** + * 토스트 메시지 + */ +function showToast(message, type = 'info') { + const container = document.getElementById('toastContainer'); + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + + container.appendChild(toast); + + setTimeout(() => { + toast.classList.add('show'); + }, 10); + + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => { + container.removeChild(toast); + }, 300); + }, 3000); +} diff --git a/deploy/tkfb-package/web-ui/js/vacation-common.js b/deploy/tkfb-package/web-ui/js/vacation-common.js new file mode 100644 index 0000000..89a0d3e --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/vacation-common.js @@ -0,0 +1,241 @@ +/** + * 휴가 관리 공통 함수 + * 모든 휴가 관련 페이지에서 사용하는 공통 함수 모음 + */ + +// 전역 변수 +window.VacationCommon = { + workers: [], + vacationTypes: [], + currentUser: null +}; + +/** + * 작업자 목록 로드 + */ +async function loadWorkers() { + try { + const response = await axios.get('/workers?limit=100'); + if (response.data.success) { + window.VacationCommon.workers = response.data.data.filter(w => w.employment_status === 'employed'); + return window.VacationCommon.workers; + } + } catch (error) { + console.error('작업자 목록 로드 오류:', error); + throw error; + } +} + +/** + * 휴가 유형 목록 로드 + */ +async function loadVacationTypes() { + try { + const response = await axios.get('/attendance/vacation-types'); + if (response.data.success) { + window.VacationCommon.vacationTypes = response.data.data; + return window.VacationCommon.vacationTypes; + } + } catch (error) { + console.error('휴가 유형 로드 오류:', error); + throw error; + } +} + +/** + * 현재 사용자 정보 가져오기 + */ +function getCurrentUser() { + if (!window.VacationCommon.currentUser) { + window.VacationCommon.currentUser = JSON.parse(localStorage.getItem('user')); + } + return window.VacationCommon.currentUser; +} + +/** + * 휴가 신청 목록 렌더링 + */ +function renderVacationRequests(requests, containerId, showActions = false, actionType = 'approval') { + const container = document.getElementById(containerId); + + if (!requests || requests.length === 0) { + container.innerHTML = ` +
+

휴가 신청 내역이 없습니다.

+
+ `; + return; + } + + const tableHTML = ` + + + + + + + + + + + ${showActions ? '' : ''} + + + + ${requests.map(request => { + const validStatuses = ['pending', 'approved', 'rejected']; + const safeStatus = validStatuses.includes(request.status) ? request.status : 'pending'; + const statusClass = safeStatus === 'pending' ? 'status-pending' : + safeStatus === 'approved' ? 'status-approved' : 'status-rejected'; + const statusText = safeStatus === 'pending' ? '대기' : + safeStatus === 'approved' ? '승인' : '거부'; + const workerName = escapeHtml(request.worker_name || '알 수 없음'); + const typeName = escapeHtml(request.vacation_type_name || request.type_name || '알 수 없음'); + const reasonText = escapeHtml(request.reason || '-'); + const daysUsed = parseFloat(request.days_used) || 0; + + return ` + + + + + + + + + ${showActions ? renderActionButtons(request, actionType) : ''} + + `; + }).join('')} + +
작업자휴가 유형시작일종료일일수상태사유관리
${workerName}${typeName}${escapeHtml(request.start_date || '-')}${escapeHtml(request.end_date || '-')}${daysUsed}일 + + ${statusText} + + + ${reasonText} +
+ `; + + container.innerHTML = tableHTML; +} + +/** + * 액션 버튼 렌더링 + */ +function renderActionButtons(request, actionType) { + const safeRequestId = parseInt(request.request_id) || 0; + if (actionType === 'approval' && request.status === 'pending') { + return ` + +
+ + +
+ + `; + } else if (actionType === 'delete' && request.status === 'pending') { + return ` + + + + `; + } + return '-'; +} + +/** + * 휴가 신청 승인 + */ +async function approveVacationRequest(requestId) { + if (!confirm('이 휴가 신청을 승인하시겠습니까?')) { + return; + } + + try { + const response = await axios.patch(`/vacation-requests/${requestId}/approve`); + if (response.data.success) { + alert('휴가 신청이 승인되었습니다.'); + // 페이지 새로고침 이벤트 발생 + window.dispatchEvent(new Event('vacation-updated')); + return true; + } + } catch (error) { + console.error('승인 오류:', error); + alert(error.response?.data?.message || '승인 중 오류가 발생했습니다.'); + return false; + } +} + +/** + * 휴가 신청 거부 + */ +async function rejectVacationRequest(requestId) { + const reason = prompt('거부 사유를 입력하세요:'); + if (!reason) { + return; + } + + try { + const response = await axios.patch(`/vacation-requests/${requestId}/reject`, { + review_note: reason + }); + if (response.data.success) { + alert('휴가 신청이 거부되었습니다.'); + // 페이지 새로고침 이벤트 발생 + window.dispatchEvent(new Event('vacation-updated')); + return true; + } + } catch (error) { + console.error('거부 오류:', error); + alert(error.response?.data?.message || '거부 중 오류가 발생했습니다.'); + return false; + } +} + +/** + * 휴가 신청 삭제 + */ +async function deleteVacationRequest(requestId) { + if (!confirm('이 휴가 신청을 삭제하시겠습니까?')) { + return; + } + + try { + const response = await axios.delete(`/vacation-requests/${requestId}`); + if (response.data.success) { + alert('휴가 신청이 삭제되었습니다.'); + // 페이지 새로고침 이벤트 발생 + window.dispatchEvent(new Event('vacation-updated')); + return true; + } + } catch (error) { + console.error('삭제 오류:', error); + alert(error.response?.data?.message || '삭제 중 오류가 발생했습니다.'); + return false; + } +} + +/** + * axios 설정 대기 + */ +function waitForAxiosConfig() { + return new Promise((resolve) => { + const check = setInterval(() => { + if (axios.defaults.baseURL) { + clearInterval(check); + resolve(); + } + }, 50); + setTimeout(() => { + clearInterval(check); + resolve(); + }, 5000); + }); +} diff --git a/deploy/tkfb-package/web-ui/js/visit-request.js b/deploy/tkfb-package/web-ui/js/visit-request.js new file mode 100644 index 0000000..5fb6724 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/visit-request.js @@ -0,0 +1,531 @@ +// 출입 신청 페이지 JavaScript + +let categories = []; +let workplaces = []; +let mapRegions = []; +let visitPurposes = []; +let selectedWorkplace = null; +let selectedCategory = null; +let canvas = null; +let ctx = null; +let layoutImage = null; + +// ==================== Toast 알림 ==================== + +/** + * Toast 메시지 표시 + */ +function showToast(message, type = 'info', duration = 3000) { + const toastContainer = document.getElementById('toastContainer') || createToastContainer(); + + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + + const iconMap = { + success: '✅', + error: '❌', + warning: '⚠️', + info: 'ℹ️' + }; + + toast.innerHTML = ` + ${iconMap[type] || 'ℹ️'} + ${message} + `; + + toastContainer.appendChild(toast); + + // 애니메이션 + setTimeout(() => toast.classList.add('show'), 10); + + // 자동 제거 + setTimeout(() => { + toast.classList.remove('show'); + setTimeout(() => toast.remove(), 300); + }, duration); +} + +/** + * Toast 컨테이너 생성 + */ +function createToastContainer() { + const container = document.createElement('div'); + container.id = 'toastContainer'; + container.style.cssText = ` + position: fixed; + top: 20px; + right: 20px; + z-index: 9999; + display: flex; + flex-direction: column; + gap: 10px; + `; + + document.body.appendChild(container); + + // Toast 스타일 추가 + if (!document.getElementById('toastStyles')) { + const style = document.createElement('style'); + style.id = 'toastStyles'; + style.textContent = ` + .toast { + display: flex; + align-items: center; + gap: 12px; + padding: 12px 20px; + background: white; + border-radius: 8px; + box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15); + opacity: 0; + transform: translateX(100px); + transition: all 0.3s ease; + min-width: 250px; + max-width: 400px; + } + .toast.show { + opacity: 1; + transform: translateX(0); + } + .toast-success { border-left: 4px solid #10b981; } + .toast-error { border-left: 4px solid #ef4444; } + .toast-warning { border-left: 4px solid #f59e0b; } + .toast-info { border-left: 4px solid #3b82f6; } + .toast-icon { font-size: 20px; } + .toast-message { font-size: 14px; color: #374151; } + `; + document.head.appendChild(style); + } + + return container; +} + +// ==================== 초기화 ==================== + +document.addEventListener('DOMContentLoaded', async () => { + // 오늘 날짜 기본값 설정 + const today = new Date().toISOString().split('T')[0]; + document.getElementById('visitDate').value = today; + document.getElementById('visitDate').min = today; + + // 현재 시간 + 1시간 기본값 설정 + const now = new Date(); + now.setHours(now.getHours() + 1); + const timeString = now.toTimeString().slice(0, 5); + document.getElementById('visitTime').value = timeString; + + // 데이터 로드 + await loadCategories(); + await loadVisitPurposes(); + await loadMyRequests(); + + // 폼 제출 이벤트 + document.getElementById('visitRequestForm').addEventListener('submit', handleSubmit); + + // 캔버스 초기화 + canvas = document.getElementById('workplaceMapCanvas'); + ctx = canvas.getContext('2d'); +}); + +// ==================== 데이터 로드 ==================== + +/** + * 카테고리(공장) 목록 로드 + */ +async function loadCategories() { + try { + const response = await window.apiCall('/workplaces/categories', 'GET'); + if (response && response.success) { + categories = response.data || []; + + const categorySelect = document.getElementById('categorySelect'); + categorySelect.innerHTML = ''; + + categories.forEach(cat => { + if (cat.is_active) { + const option = document.createElement('option'); + option.value = cat.category_id; + option.textContent = cat.category_name; + categorySelect.appendChild(option); + } + }); + } + } catch (error) { + console.error('카테고리 로드 오류:', error); + window.showToast('카테고리 로드 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 방문 목적 목록 로드 + */ +async function loadVisitPurposes() { + try { + const response = await window.apiCall('/workplace-visits/purposes/active', 'GET'); + if (response && response.success) { + visitPurposes = response.data || []; + + const purposeSelect = document.getElementById('visitPurpose'); + purposeSelect.innerHTML = ''; + + visitPurposes.forEach(purpose => { + const option = document.createElement('option'); + option.value = purpose.purpose_id; + option.textContent = purpose.purpose_name; + purposeSelect.appendChild(option); + }); + } + } catch (error) { + console.error('방문 목적 로드 오류:', error); + window.showToast('방문 목적 로드 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 내 출입 신청 목록 로드 + */ +async function loadMyRequests() { + try { + // localStorage에서 사용자 정보 가져오기 + const userData = localStorage.getItem('user'); + const currentUser = userData ? JSON.parse(userData) : null; + + if (!currentUser || !currentUser.user_id) { + console.log('사용자 정보 없음'); + return; + } + + const response = await window.apiCall(`/workplace-visits/requests?requester_id=${currentUser.user_id}`, 'GET'); + + if (response && response.success) { + const requests = response.data || []; + renderMyRequests(requests); + } + } catch (error) { + console.error('내 신청 목록 로드 오류:', error); + } +} + +/** + * 내 신청 목록 렌더링 + */ +function renderMyRequests(requests) { + const listDiv = document.getElementById('myRequestsList'); + + if (requests.length === 0) { + listDiv.innerHTML = '

신청 내역이 없습니다

'; + return; + } + + let html = ''; + requests.forEach(req => { + const statusText = { + 'pending': '승인 대기', + 'approved': '승인됨', + 'rejected': '반려됨', + 'training_completed': '교육 완료' + }[req.status] || req.status; + + html += ` +
+
+

${req.visitor_company} (${req.visitor_count}명)

+ ${statusText} +
+
+
+ 방문 작업장 + ${req.category_name} - ${req.workplace_name} +
+
+ 방문 일시 + ${req.visit_date} ${req.visit_time} +
+
+ 방문 목적 + ${req.purpose_name} +
+
+ 신청일 + ${new Date(req.created_at).toLocaleDateString()} +
+
+ ${req.rejection_reason ? `

반려 사유: ${req.rejection_reason}

` : ''} + ${req.notes ? `

비고: ${req.notes}

` : ''} +
+ `; + }); + + listDiv.innerHTML = html; +} + +// ==================== 작업장 지도 모달 ==================== + +/** + * 지도 모달 열기 + */ +function openMapModal() { + document.getElementById('mapModal').style.display = 'flex'; + document.body.style.overflow = 'hidden'; +} + +/** + * 지도 모달 닫기 + */ +function closeMapModal() { + document.getElementById('mapModal').style.display = 'none'; + document.body.style.overflow = ''; +} + +/** + * 작업장 지도 로드 + */ +async function loadWorkplaceMap() { + const categoryId = document.getElementById('categorySelect').value; + if (!categoryId) { + document.getElementById('mapCanvasContainer').style.display = 'none'; + return; + } + + selectedCategory = categories.find(c => c.category_id == categoryId); + + try { + // 작업장 목록 로드 + const workplacesResponse = await window.apiCall(`/workplaces/categories/${categoryId}`, 'GET'); + if (workplacesResponse && workplacesResponse.success) { + workplaces = workplacesResponse.data || []; + } + + // 지도 영역 로드 + const regionsResponse = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`, 'GET'); + if (regionsResponse && regionsResponse.success) { + mapRegions = regionsResponse.data || []; + } + + // 레이아웃 이미지가 있으면 표시 + if (selectedCategory && selectedCategory.layout_image) { + // API_BASE_URL에서 /api 제거하고 이미지 경로 생성 + const baseUrl = (window.API_BASE_URL || 'http://localhost:20005').replace('/api', ''); + const fullImageUrl = selectedCategory.layout_image.startsWith('http') + ? selectedCategory.layout_image + : `${baseUrl}${selectedCategory.layout_image}`; + + console.log('이미지 URL:', fullImageUrl); + loadImageToCanvas(fullImageUrl); + document.getElementById('mapCanvasContainer').style.display = 'block'; + } else { + window.showToast('선택한 구역에 레이아웃 지도가 없습니다.', 'warning'); + document.getElementById('mapCanvasContainer').style.display = 'none'; + } + } catch (error) { + console.error('작업장 지도 로드 오류:', error); + window.showToast('작업장 지도 로드 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 이미지를 캔버스에 로드 + */ +function loadImageToCanvas(imagePath) { + const img = new Image(); + // crossOrigin 제거 - 같은 도메인이므로 불필요 + img.onload = function() { + // 캔버스 크기 설정 + const maxWidth = 800; + const scale = img.width > maxWidth ? maxWidth / img.width : 1; + + canvas.width = img.width * scale; + canvas.height = img.height * scale; + + // 이미지 그리기 + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + + layoutImage = img; + + // 영역 표시 + drawRegions(); + + // 클릭 이벤트 등록 + canvas.onclick = handleCanvasClick; + }; + img.onerror = function() { + window.showToast('지도 이미지를 불러올 수 없습니다.', 'error'); + }; + img.src = imagePath; +} + +/** + * 지도 영역 그리기 + */ +function drawRegions() { + mapRegions.forEach(region => { + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + // 영역 박스 + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 2; + ctx.strokeRect(x1, y1, x2 - x1, y2 - y1); + + ctx.fillStyle = 'rgba(16, 185, 129, 0.1)'; + ctx.fillRect(x1, y1, x2 - x1, y2 - y1); + + // 작업장 이름 + ctx.fillStyle = '#10b981'; + ctx.font = 'bold 14px sans-serif'; + ctx.fillText(region.workplace_name || '', x1 + 5, y1 + 20); + }); +} + +/** + * 캔버스 클릭 핸들러 + */ +function handleCanvasClick(event) { + const rect = canvas.getBoundingClientRect(); + const x = event.clientX - rect.left; + const y = event.clientY - rect.top; + + // 클릭한 위치의 영역 찾기 + for (const region of mapRegions) { + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { + // 작업장 선택 + selectWorkplace(region); + return; + } + } + + window.showToast('작업장 영역을 클릭해주세요.', 'warning'); +} + +/** + * 작업장 선택 + */ +function selectWorkplace(region) { + selectedWorkplace = { + workplace_id: region.workplace_id, + workplace_name: region.workplace_name, + category_id: selectedCategory.category_id, + category_name: selectedCategory.category_name + }; + + // 선택 표시 + const selectionDiv = document.getElementById('workplaceSelection'); + selectionDiv.classList.add('selected'); + selectionDiv.innerHTML = ` +
+
${selectedCategory.category_name} - ${region.workplace_name}
+ `; + + // 상세 정보 카드 표시 + const infoDiv = document.getElementById('selectedWorkplaceInfo'); + infoDiv.style.display = 'block'; + infoDiv.innerHTML = ` +
+
📍
+
+
${region.workplace_name}
+
${selectedCategory.category_name}
+
+ +
+ `; + + // 모달 닫기 + closeMapModal(); + + window.showToast(`${region.workplace_name} 작업장이 선택되었습니다.`, 'success'); +} + +/** + * 작업장 선택 초기화 + */ +function clearWorkplaceSelection() { + selectedWorkplace = null; + + const selectionDiv = document.getElementById('workplaceSelection'); + selectionDiv.classList.remove('selected'); + selectionDiv.innerHTML = ` +
📍
+
지도에서 작업장을 선택하세요
+ `; + + document.getElementById('selectedWorkplaceInfo').style.display = 'none'; +} + +// ==================== 폼 제출 ==================== + +/** + * 출입 신청 제출 + */ +async function handleSubmit(event) { + event.preventDefault(); + + if (!selectedWorkplace) { + window.showToast('작업장을 선택해주세요.', 'warning'); + openMapModal(); + return; + } + + const formData = { + visitor_company: document.getElementById('visitorCompany').value.trim(), + visitor_count: parseInt(document.getElementById('visitorCount').value), + category_id: selectedWorkplace.category_id, + workplace_id: selectedWorkplace.workplace_id, + visit_date: document.getElementById('visitDate').value, + visit_time: document.getElementById('visitTime').value, + purpose_id: parseInt(document.getElementById('visitPurpose').value), + notes: document.getElementById('notes').value.trim() || null + }; + + try { + const response = await window.apiCall('/workplace-visits/requests', 'POST', formData); + + if (response && response.success) { + window.showToast('출입 신청 및 안전교육 신청이 완료되었습니다. 안전관리자의 승인을 기다려주세요.', 'success'); + + // 폼 초기화 + resetForm(); + + // 내 신청 목록 새로고침 + await loadMyRequests(); + } else { + throw new Error(response?.message || '신청 실패'); + } + } catch (error) { + console.error('출입 신청 오류:', error); + window.showToast(error.message || '출입 신청 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 폼 초기화 + */ +function resetForm() { + document.getElementById('visitRequestForm').reset(); + clearWorkplaceSelection(); + + // 오늘 날짜와 시간 다시 설정 + const today = new Date().toISOString().split('T')[0]; + document.getElementById('visitDate').value = today; + + const now = new Date(); + now.setHours(now.getHours() + 1); + const timeString = now.toTimeString().slice(0, 5); + document.getElementById('visitTime').value = timeString; + + document.getElementById('visitorCount').value = 1; +} + +// 전역 함수로 노출 +window.showToast = showToast; +window.openMapModal = openMapModal; +window.closeMapModal = closeMapModal; +window.loadWorkplaceMap = loadWorkplaceMap; +window.clearWorkplaceSelection = clearWorkplaceSelection; +window.resetForm = resetForm; diff --git a/deploy/tkfb-package/web-ui/js/work-analysis.js b/deploy/tkfb-package/web-ui/js/work-analysis.js new file mode 100644 index 0000000..9b309d6 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-analysis.js @@ -0,0 +1,801 @@ +// 작업 분석 페이지 JavaScript + +// API 설정 import +import './api-config.js'; + +// 전역 변수 +let currentMode = 'period'; +let currentTab = 'worker'; +let analysisData = null; +let projectChart = null; +let errorByProjectChart = null; +let errorTimelineChart = null; + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', function() { + console.log('📈 작업 분석 페이지 초기화 시작'); + + initializePage(); + loadInitialData(); +}); + +// 페이지 초기화 +function initializePage() { + // 시간 업데이트 시작 + updateCurrentTime(); + setInterval(updateCurrentTime, 1000); + + // 사용자 정보 업데이트 + updateUserInfo(); + + // 프로필 메뉴 토글 + setupProfileMenu(); + + // 로그아웃 버튼 + setupLogoutButton(); + + // 기본 날짜 설정은 HTML에서 처리됨 (새로운 UI) + console.log('✅ 작업 분석 페이지 초기화 완료'); +} + +// 현재 시간 업데이트 (시 분 초 형식으로 고정) +function updateCurrentTime() { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + const timeString = `${hours}시 ${minutes}분 ${seconds}초`; + + const timeElement = document.getElementById('timeValue'); + if (timeElement) { + timeElement.textContent = timeString; + } +} + +// 사용자 정보 업데이트 - navbar/sidebar는 app-init.js에서 공통 처리 +function updateUserInfo() { + // app-init.js가 navbar 사용자 정보를 처리하므로 여기서는 아무것도 하지 않음 +} + +// 프로필 메뉴 설정 +function setupProfileMenu() { + const userProfile = document.getElementById('userProfile'); + const profileMenu = document.getElementById('profileMenu'); + + if (userProfile && profileMenu) { + userProfile.addEventListener('click', function(e) { + e.stopPropagation(); + const isVisible = profileMenu.style.display === 'block'; + profileMenu.style.display = isVisible ? 'none' : 'block'; + }); + + // 외부 클릭 시 메뉴 닫기 + document.addEventListener('click', function() { + profileMenu.style.display = 'none'; + }); + } +} + +// 로그아웃 버튼 설정 +function setupLogoutButton() { + const logoutBtn = document.getElementById('logoutBtn'); + if (logoutBtn) { + logoutBtn.addEventListener('click', function() { + if (confirm('로그아웃 하시겠습니까?')) { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + localStorage.removeItem('userInfo'); + window.location.href = '/index.html'; + } + }); + } +} + +// 초기 데이터 로드 +async function loadInitialData() { + try { + console.log('📊 초기 데이터 로딩 시작'); + + // 프로젝트 목록 로드 + const projects = await apiCall('/projects/active/list', 'GET'); + const projectData = Array.isArray(projects) ? projects : (projects.data || []); + + // 프로젝트 필터 옵션 업데이트 + updateProjectFilters(projectData); + + console.log('✅ 초기 데이터 로딩 완료'); + + } catch (error) { + console.error('초기 데이터 로딩 오류:', error); + showToast('초기 데이터를 불러오는데 실패했습니다.', 'error'); + } +} + +// 프로젝트 필터 업데이트 +function updateProjectFilters(projects) { + const projectFilter = document.getElementById('projectFilter'); + const projectModeSelect = document.getElementById('projectModeSelect'); + + if (projectFilter) { + projectFilter.innerHTML = ''; + projects.forEach(project => { + projectFilter.innerHTML += ``; + }); + } + + if (projectModeSelect) { + projectModeSelect.innerHTML = ''; + projects.forEach(project => { + projectModeSelect.innerHTML += ``; + }); + } +} + +// 분석 모드 전환 +function switchAnalysisMode(mode) { + currentMode = mode; + + // 탭 버튼 활성화 상태 변경 + document.querySelectorAll('.mode-tab').forEach(tab => { + tab.classList.remove('active'); + }); + document.querySelector(`[data-mode="${mode}"]`).classList.add('active'); + + // 모드 콘텐츠 표시/숨김 + document.querySelectorAll('.analysis-mode').forEach(content => { + content.classList.remove('active'); + }); + document.getElementById(`${mode}-mode`).classList.add('active'); + + console.log(`🔄 분석 모드 전환: ${mode}`); +} + +// 분석 탭 전환 +function switchAnalysisTab(tab) { + currentTab = tab; + + // 탭 버튼 활성화 상태 변경 + document.querySelectorAll('.analysis-tab').forEach(tabBtn => { + tabBtn.classList.remove('active'); + }); + document.querySelector(`[data-tab="${tab}"]`).classList.add('active'); + + // 탭 콘텐츠 표시/숨김 + document.querySelectorAll('.analysis-content').forEach(content => { + content.classList.remove('active'); + }); + document.getElementById(`${tab}-analysis`).classList.add('active'); + + console.log(`🔄 분석 탭 전환: ${tab}`); +} + +// 기간별 분석 로드 +async function loadPeriodAnalysis() { + const startDate = document.getElementById('startDate').value; + const endDate = document.getElementById('endDate').value; + const projectId = document.getElementById('projectFilter').value; + + if (!startDate || !endDate) { + showToast('시작일과 종료일을 모두 선택해주세요.', 'error'); + return; + } + + if (new Date(startDate) > new Date(endDate)) { + showToast('시작일이 종료일보다 늦을 수 없습니다.', 'error'); + return; + } + + showLoading(true); + + try { + console.log('📊 기간별 분석 데이터 로딩 시작'); + + // API 호출 파라미터 구성 + const params = new URLSearchParams({ + start: startDate, + end: endDate + }); + + if (projectId) { + params.append('project_id', projectId); + } + + // 여러 API를 병렬로 호출하여 종합 분석 데이터 구성 + console.log('📡 API 파라미터:', params.toString()); + + const [statsRes, workerStatsRes, projectStatsRes, errorAnalysisRes] = await Promise.all([ + apiCall(`/work-analysis/stats?${params}`, 'GET').catch(err => { + console.error('❌ stats API 오류:', err); + return { data: null }; + }), + apiCall(`/work-analysis/worker-stats?${params}`, 'GET').catch(err => { + console.error('❌ worker-stats API 오류:', err); + return { data: [] }; + }), + apiCall(`/work-analysis/project-stats?${params}`, 'GET').catch(err => { + console.error('❌ project-stats API 오류:', err); + return { data: [] }; + }), + apiCall(`/work-analysis/error-analysis?${params}`, 'GET').catch(err => { + console.error('❌ error-analysis API 오류:', err); + return { data: {} }; + }) + ]); + + console.log('📊 개별 API 응답:'); + console.log(' - stats:', statsRes); + console.log(' - worker-stats:', workerStatsRes); + console.log(' - project-stats:', projectStatsRes); + console.log(' - error-analysis:', errorAnalysisRes); + + // 종합 분석 데이터 구성 + analysisData = { + summary: statsRes.data || statsRes, + workerStats: workerStatsRes.data || workerStatsRes, + projectStats: projectStatsRes.data || projectStatsRes, + errorStats: errorAnalysisRes.data || errorAnalysisRes + }; + + console.log('📊 분석 데이터:', analysisData); + console.log('📊 요약 통계:', analysisData.summary); + console.log('👥 작업자 통계:', analysisData.workerStats); + console.log('📁 프로젝트 통계:', analysisData.projectStats); + console.log('⚠️ 오류 통계:', analysisData.errorStats); + + // 결과 표시 + displayPeriodAnalysis(analysisData); + + // 결과 섹션 표시 + document.getElementById('periodResults').style.display = 'block'; + + showToast('분석이 완료되었습니다.', 'success'); + + } catch (error) { + console.error('기간별 분석 오류:', error); + showToast('분석 중 오류가 발생했습니다.', 'error'); + } finally { + showLoading(false); + } +} + +// 기간별 분석 결과 표시 +function displayPeriodAnalysis(data) { + // 요약 통계 업데이트 + updateSummaryStats(data.summary || {}); + + // 작업자별 분석 표시 + displayWorkerAnalysis(data.workerStats || []); + + // 프로젝트별 분석 표시 + displayProjectAnalysis(data.projectStats || []); + + // 오류 분석 표시 (전체 분석 데이터도 함께 전달) + displayErrorAnalysis(data.errorStats || {}, data); +} + +// 요약 통계 업데이트 +function updateSummaryStats(summary) { + // API 응답 구조에 맞게 필드명 조정 + document.getElementById('totalHours').textContent = `${summary.totalHours || summary.total_hours || 0}h`; + document.getElementById('totalWorkers').textContent = `${summary.activeworkers || summary.activeWorkers || summary.total_workers || 0}명`; + document.getElementById('totalProjects').textContent = `${summary.activeProjects || summary.active_projects || summary.total_projects || 0}개`; + document.getElementById('errorRate').textContent = `${summary.errorRate || summary.error_rate || 0}%`; +} + +// 작업자별 분석 표시 +function displayWorkerAnalysis(workerStats) { + const grid = document.getElementById('workerAnalysisGrid'); + + console.log('👥 작업자 분석 데이터 확인:', workerStats); + console.log('👥 데이터 타입:', typeof workerStats); + console.log('👥 배열 여부:', Array.isArray(workerStats)); + console.log('👥 길이:', workerStats ? workerStats.length : 'undefined'); + + if (!workerStats || (Array.isArray(workerStats) && workerStats.length === 0)) { + console.log('👥 빈 데이터로 인한 empty-state 표시'); + grid.innerHTML = ` +
+
👥
+

분석할 작업자 데이터가 없습니다.

+

선택한 기간에 등록된 작업이 없습니다.

+
+ `; + return; + } + + let gridHtml = ''; + + workerStats.forEach(worker => { + const workerName = worker.worker_name || worker.name || '알 수 없음'; + const totalHours = worker.total_hours || worker.totalHours || 0; + + gridHtml += ` +
+
+
+
${workerName.charAt(0)}
+
${workerName}
+
+
${totalHours}h
+
+
+ `; + + // API 응답 구조에 따라 프로젝트 데이터 처리 + const projects = worker.projects || worker.project_details || []; + if (projects.length > 0) { + projects.forEach(project => { + const projectName = project.project_name || project.name || '프로젝트'; + gridHtml += ` +
+
${projectName}
+
+ `; + + const works = project.works || project.work_details || project.tasks || []; + if (works.length > 0) { + works.forEach(work => { + const workName = work.work_name || work.task_name || work.name || '작업'; + const workHours = work.hours || work.total_hours || work.work_hours || 0; + gridHtml += ` +
+
${workName}
+
${workHours}h
+
+ `; + }); + } else { + gridHtml += ` +
+
총 작업시간
+
${project.total_hours || project.hours || 0}h
+
+ `; + } + + gridHtml += ` +
+
+ `; + }); + } else { + gridHtml += ` +
+
전체 작업
+
+
+
총 작업시간
+
${totalHours}h
+
+
+
+ `; + } + + gridHtml += ` +
+
+ `; + }); + + grid.innerHTML = gridHtml; +} + +// 프로젝트별 분석 표시 +function displayProjectAnalysis(projectStats) { + const detailsContainer = document.getElementById('projectDetails'); + + console.log('📁 프로젝트 분석 데이터 확인:', projectStats); + console.log('📁 데이터 타입:', typeof projectStats); + console.log('📁 배열 여부:', Array.isArray(projectStats)); + console.log('📁 길이:', projectStats ? projectStats.length : 'undefined'); + + if (projectStats && projectStats.length > 0) { + console.log('📁 첫 번째 프로젝트 데이터:', projectStats[0]); + } + + if (!projectStats || projectStats.length === 0) { + console.log('📁 빈 데이터로 인한 empty-state 표시'); + detailsContainer.innerHTML = ` +
+
📁
+

분석할 프로젝트 데이터가 없습니다.

+
+ `; + return; + } + + // 프로젝트 상세 정보 표시 + let detailsHtml = ''; + + // 전체 시간 계산 (퍼센트 계산용) + const totalAllHours = projectStats.reduce((sum, p) => { + return sum + (p.totalHours || p.total_hours || p.hours || 0); + }, 0); + + projectStats.forEach(project => { + console.log('📁 개별 프로젝트 처리:', project); + + const projectName = project.project_name || project.name || project.projectName || '프로젝트'; + const totalHours = project.totalHours || project.total_hours || project.hours || 0; + + // 퍼센트 계산 + let percentage = project.percentage || project.percent || 0; + if (percentage === 0 && totalAllHours > 0) { + percentage = Math.round((totalHours / totalAllHours) * 100); + } + + detailsHtml += ` +
+
+
${projectName}
+
${percentage}%
+
+
${totalHours}시간
+
+ `; + }); + + detailsContainer.innerHTML = detailsHtml; + + // 차트 업데이트 + updateProjectChart(projectStats); +} + +// 프로젝트 차트 업데이트 +function updateProjectChart(projectStats) { + const ctx = document.getElementById('projectChart'); + + if (projectChart) { + projectChart.destroy(); + } + + const labels = projectStats.map(p => p.project_name || p.name || p.projectName || '프로젝트'); + const data = projectStats.map(p => p.totalHours || p.total_hours || p.hours || 0); + + console.log('📊 차트 라벨:', labels); + console.log('📊 차트 데이터:', data); + const colors = [ + '#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', + '#06b6d4', '#84cc16', '#f97316', '#ec4899', '#6366f1' + ]; + + projectChart = new Chart(ctx, { + type: 'doughnut', + data: { + labels: labels, + datasets: [{ + data: data, + backgroundColor: colors.slice(0, data.length), + borderWidth: 2, + borderColor: '#ffffff' + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + plugins: { + legend: { + position: 'bottom', + labels: { + padding: 20, + usePointStyle: true + } + } + } + } + }); +} + +// 오류 분석 표시 +function displayErrorAnalysis(errorStats, allData) { + console.log('⚠️ 오류 분석 데이터 확인:', errorStats); + console.log('⚠️ 데이터 타입:', typeof errorStats); + console.log('⚠️ 배열 여부:', Array.isArray(errorStats)); + + // errorStats가 배열인 경우 첫 번째 요소 사용 + let errorData = errorStats; + if (Array.isArray(errorStats) && errorStats.length > 0) { + errorData = errorStats[0]; + console.log('⚠️ 배열에서 첫 번째 요소 사용:', errorData); + } + + // 오류 요약 업데이트 - 실제 데이터 구조에 맞게 수정 + const errorHours = errorData.totalHours || errorData.total_hours || errorData.error_hours || 0; + + // 전체 작업 시간에서 오류 시간을 빼서 정규 시간 계산 + // 요약 통계에서 전체 시간을 가져와서 계산 + const totalHours = allData && allData.summary ? allData.summary.totalHours : 0; + const normalHours = Math.max(0, totalHours - errorHours); + + console.log('⚠️ 정규 시간:', normalHours, '오류 시간:', errorHours); + + document.getElementById('normalHours').textContent = `${normalHours}h`; + document.getElementById('errorHours').textContent = `${errorHours}h`; + + // 프로젝트별 에러율 차트 + if (errorStats.projectErrorRates) { + updateErrorByProjectChart(errorStats.projectErrorRates); + } + + // 일별 오류 추이 차트 + if (errorStats.dailyErrorTrend) { + updateErrorTimelineChart(errorStats.dailyErrorTrend); + } + + // 오류 유형별 분석 + if (errorStats.errorTypes) { + displayErrorTypes(errorStats.errorTypes); + } +} + +// 프로젝트별 에러율 차트 업데이트 +function updateErrorByProjectChart(projectErrorRates) { + const ctx = document.getElementById('errorByProjectChart'); + + if (errorByProjectChart) { + errorByProjectChart.destroy(); + } + + const labels = projectErrorRates.map(p => p.project_name); + const data = projectErrorRates.map(p => p.error_rate); + + errorByProjectChart = new Chart(ctx, { + type: 'bar', + data: { + labels: labels, + datasets: [{ + label: '에러율 (%)', + data: data, + backgroundColor: 'rgba(239, 68, 68, 0.8)', + borderColor: 'rgba(239, 68, 68, 1)', + borderWidth: 1 + }] + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + beginAtZero: true, + max: 100, + ticks: { + callback: function(value) { + return value + '%'; + } + } + } + }, + plugins: { + legend: { + display: false + } + } + } + }); +} + +// 일별 오류 추이 차트 업데이트 +function updateErrorTimelineChart(dailyErrorTrend) { + const ctx = document.getElementById('errorTimelineChart'); + + if (errorTimelineChart) { + errorTimelineChart.destroy(); + } + + const labels = dailyErrorTrend.map(d => formatDate(new Date(d.date))); + const errorData = dailyErrorTrend.map(d => d.error_count); + const totalData = dailyErrorTrend.map(d => d.total_count); + + errorTimelineChart = new Chart(ctx, { + type: 'line', + data: { + labels: labels, + datasets: [ + { + label: '총 작업', + data: totalData, + borderColor: 'rgba(59, 130, 246, 1)', + backgroundColor: 'rgba(59, 130, 246, 0.1)', + fill: true + }, + { + label: '오류 작업', + data: errorData, + borderColor: 'rgba(239, 68, 68, 1)', + backgroundColor: 'rgba(239, 68, 68, 0.1)', + fill: true + } + ] + }, + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + y: { + beginAtZero: true + } + }, + plugins: { + legend: { + position: 'top' + } + } + } + }); +} + +// 오류 유형별 분석 표시 +function displayErrorTypes(errorTypes) { + const container = document.getElementById('errorTypesAnalysis'); + + if (!errorTypes || errorTypes.length === 0) { + container.innerHTML = ` +
+
⚠️
+

오류 유형 데이터가 없습니다.

+
+ `; + return; + } + + let html = '

🔍 오류 유형별 상세 분석

'; + + errorTypes.forEach(errorType => { + html += ` +
+
+
⚠️
+
${errorType.error_name}
+
+
+
${errorType.count}건
+
${errorType.percentage}%
+
+
+ `; + }); + + container.innerHTML = html; +} + +// 프로젝트별 분석 로드 +async function loadProjectAnalysis() { + const projectId = document.getElementById('projectModeSelect').value; + const startDate = document.getElementById('projectStartDate').value; + const endDate = document.getElementById('projectEndDate').value; + + if (!projectId) { + showToast('프로젝트를 선택해주세요.', 'error'); + return; + } + + showLoading(true); + + try { + console.log('📁 프로젝트별 분석 데이터 로딩 시작'); + + // API 호출 파라미터 구성 + const params = new URLSearchParams({ + project_id: projectId + }); + + if (startDate) params.append('start', startDate); + if (endDate) params.append('end', endDate); + + // 프로젝트별 상세 분석 데이터 로드 + const response = await apiCall(`/work-analysis/project-worktype-analysis?${params}`, 'GET'); + const projectAnalysisData = response.data || response; + + console.log('📁 프로젝트 분석 데이터:', projectAnalysisData); + + // 결과 표시 + displayProjectModeAnalysis(projectAnalysisData); + + // 결과 섹션 표시 + document.getElementById('projectModeResults').style.display = 'block'; + + showToast('프로젝트 분석이 완료되었습니다.', 'success'); + + } catch (error) { + console.error('프로젝트별 분석 오류:', error); + showToast('프로젝트 분석 중 오류가 발생했습니다.', 'error'); + } finally { + showLoading(false); + } +} + +// 프로젝트별 분석 결과 표시 +function displayProjectModeAnalysis(data) { + const container = document.getElementById('projectModeResults'); + + // 프로젝트별 분석 결과 HTML 생성 + let html = ` +
+

📁 ${data.project_name} 분석 결과

+ +
+ `; + + container.innerHTML = html; +} + +// 로딩 상태 표시/숨김 +function showLoading(show) { + const overlay = document.getElementById('loadingOverlay'); + if (overlay) { + overlay.style.display = show ? 'flex' : 'none'; + } +} + +// 날짜 포맷팅 +function formatDate(date) { + if (!date) return ''; + + const d = new Date(date); + const year = d.getFullYear(); + const month = String(d.getMonth() + 1).padStart(2, '0'); + const day = String(d.getDate()).padStart(2, '0'); + + return `${year}-${month}-${day}`; +} + +// 토스트 메시지 표시 +function showToast(message, type = 'info') { + // 기존 토스트 제거 + const existingToast = document.querySelector('.toast'); + if (existingToast) { + existingToast.remove(); + } + + // 새 토스트 생성 + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + + // 스타일 적용 + Object.assign(toast.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '12px 24px', + borderRadius: '8px', + color: 'white', + fontWeight: '500', + zIndex: '10000', + transform: 'translateX(100%)', + transition: 'transform 0.3s ease' + }); + + // 타입별 배경색 + const colors = { + success: '#10b981', + error: '#ef4444', + warning: '#f59e0b', + info: '#3b82f6' + }; + toast.style.backgroundColor = colors[type] || colors.info; + + document.body.appendChild(toast); + + // 애니메이션 + setTimeout(() => { + toast.style.transform = 'translateX(0)'; + }, 100); + + // 자동 제거 + setTimeout(() => { + toast.style.transform = 'translateX(100%)'; + setTimeout(() => { + if (toast.parentNode) { + toast.remove(); + } + }, 300); + }, 3000); +} + +// 전역 함수로 노출 +window.switchAnalysisMode = switchAnalysisMode; +window.switchAnalysisTab = switchAnalysisTab; +window.loadPeriodAnalysis = loadPeriodAnalysis; +window.loadProjectAnalysis = loadProjectAnalysis; diff --git a/deploy/tkfb-package/web-ui/js/work-analysis/api-client.js b/deploy/tkfb-package/web-ui/js/work-analysis/api-client.js new file mode 100644 index 0000000..9ede593 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-analysis/api-client.js @@ -0,0 +1,231 @@ +/** + * Work Analysis API Client Module + * 작업 분석 관련 모든 API 호출을 관리하는 모듈 + */ + +class WorkAnalysisAPIClient { + constructor() { + this.baseURL = window.API_BASE_URL || 'http://localhost:20005/api'; + } + + /** + * 기본 API 호출 메서드 + * @param {string} endpoint - API 엔드포인트 + * @param {string} method - HTTP 메서드 + * @param {Object} data - 요청 데이터 + * @returns {Promise} API 응답 + */ + async apiCall(endpoint, method = 'GET', data = null) { + try { + const config = { + method, + headers: { + 'Content-Type': 'application/json', + } + }; + + if (data && method !== 'GET') { + config.body = JSON.stringify(data); + } + + console.log(`📡 API 호출: ${this.baseURL}${endpoint} (${method})`); + + const response = await fetch(`${this.baseURL}${endpoint}`, config); + const result = await response.json(); + + if (!response.ok) { + throw new Error(result.message || `HTTP ${response.status}`); + } + + console.log(`✅ API 성공: ${this.baseURL}${endpoint}`); + return result; + + } catch (error) { + console.error(`❌ API 실패: ${this.baseURL}${endpoint}`, error); + throw error; + } + } + + /** + * 날짜 범위 파라미터 생성 + * @param {string} startDate - 시작일 + * @param {string} endDate - 종료일 + * @param {Object} additionalParams - 추가 파라미터 + * @returns {URLSearchParams} URL 파라미터 + */ + createDateParams(startDate, endDate, additionalParams = {}) { + const params = new URLSearchParams({ + start: startDate, + end: endDate, + ...additionalParams + }); + return params; + } + + // ========== 기본 통계 API ========== + + /** + * 기본 통계 조회 + */ + async getBasicStats(startDate, endDate, projectId = null) { + console.log('🔍 getBasicStats 호출:', startDate, '~', endDate, projectId ? `(프로젝트: ${projectId})` : ''); + const params = this.createDateParams(startDate, endDate, + projectId ? { project_id: projectId } : {} + ); + console.log('🌐 API 요청 URL:', `/work-analysis/stats?${params}`); + return await this.apiCall(`/work-analysis/stats?${params}`); + } + + /** + * 일별 추이 조회 + */ + async getDailyTrend(startDate, endDate, projectId = null) { + const params = this.createDateParams(startDate, endDate, + projectId ? { project_id: projectId } : {} + ); + return await this.apiCall(`/work-analysis/daily-trend?${params}`); + } + + /** + * 작업자별 통계 조회 + */ + async getWorkerStats(startDate, endDate, projectId = null) { + const params = this.createDateParams(startDate, endDate, + projectId ? { project_id: projectId } : {} + ); + return await this.apiCall(`/work-analysis/worker-stats?${params}`); + } + + /** + * 프로젝트별 통계 조회 + */ + async getProjectStats(startDate, endDate) { + const params = this.createDateParams(startDate, endDate); + return await this.apiCall(`/work-analysis/project-stats?${params}`); + } + + // ========== 상세 분석 API ========== + + /** + * 프로젝트별-작업유형별 분석 + */ + async getProjectWorkTypeAnalysis(startDate, endDate, limit = 2000) { + const params = this.createDateParams(startDate, endDate, { limit }); + return await this.apiCall(`/work-analysis/project-worktype-analysis?${params}`); + } + + /** + * 최근 작업 데이터 조회 + */ + async getRecentWork(startDate, endDate, limit = 2000) { + const params = this.createDateParams(startDate, endDate, { limit }); + return await this.apiCall(`/work-analysis/recent-work?${params}`); + } + + /** + * 오류 분석 데이터 조회 + */ + async getErrorAnalysis(startDate, endDate) { + const params = this.createDateParams(startDate, endDate); + return await this.apiCall(`/work-analysis/error-analysis?${params}`); + } + + // ========== 배치 API 호출 ========== + + /** + * 여러 API를 병렬로 호출 + * @param {Array} apiCalls - API 호출 배열 + * @returns {Promise} 결과 배열 + */ + async batchCall(apiCalls) { + console.log('🔄 배치 API 호출 시작:', apiCalls.length, '개'); + + const promises = apiCalls.map(async ({ name, method, ...args }) => { + try { + const result = await this[method](...args); + return { name, success: true, data: result }; + } catch (error) { + console.warn(`⚠️ ${name} API 오류:`, error); + return { name, success: false, error: error.message, data: null }; + } + }); + + const results = await Promise.all(promises); + console.log('✅ 배치 API 호출 완료'); + + return results.reduce((acc, result) => { + acc[result.name] = result; + return acc; + }, {}); + } + + /** + * 차트 데이터를 위한 배치 호출 + */ + async getChartData(startDate, endDate, projectId = null) { + return await this.batchCall([ + { + name: 'dailyTrend', + method: 'getDailyTrend', + startDate, + endDate, + projectId + }, + { + name: 'workerStats', + method: 'getWorkerStats', + startDate, + endDate, + projectId + }, + { + name: 'projectStats', + method: 'getProjectStats', + startDate, + endDate + }, + { + name: 'errorAnalysis', + method: 'getErrorAnalysis', + startDate, + endDate + } + ]); + } + + /** + * 프로젝트 분포 분석을 위한 배치 호출 + */ + async getProjectDistributionData(startDate, endDate) { + return await this.batchCall([ + { + name: 'projectWorkType', + method: 'getProjectWorkTypeAnalysis', + startDate, + endDate + }, + { + name: 'workerStats', + method: 'getWorkerStats', + startDate, + endDate + }, + { + name: 'recentWork', + method: 'getRecentWork', + startDate, + endDate + } + ]); + } +} + +// 전역 인스턴스 생성 +window.WorkAnalysisAPI = new WorkAnalysisAPIClient(); + +// 하위 호환성을 위한 전역 함수 +window.apiCall = (endpoint, method, data) => { + return window.WorkAnalysisAPI.apiCall(endpoint, method, data); +}; + +// Export는 브라우저 환경에서 제거됨 diff --git a/deploy/tkfb-package/web-ui/js/work-analysis/chart-renderer.js b/deploy/tkfb-package/web-ui/js/work-analysis/chart-renderer.js new file mode 100644 index 0000000..f1d2911 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-analysis/chart-renderer.js @@ -0,0 +1,455 @@ +/** + * Work Analysis Chart Renderer Module + * 작업 분석 차트 렌더링을 담당하는 모듈 + */ + +class WorkAnalysisChartRenderer { + constructor() { + this.charts = new Map(); // 차트 인스턴스 관리 + this.dataProcessor = window.WorkAnalysisDataProcessor; + this.defaultColors = [ + '#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', + '#06b6d4', '#84cc16', '#f97316', '#ec4899', '#6366f1' + ]; + } + + // ========== 차트 관리 ========== + + /** + * 기존 차트 제거 + * @param {string} chartId - 차트 ID + */ + destroyChart(chartId) { + if (this.charts.has(chartId)) { + this.charts.get(chartId).destroy(); + this.charts.delete(chartId); + console.log('🗑️ 차트 제거:', chartId); + } + } + + /** + * 모든 차트 제거 + */ + destroyAllCharts() { + this.charts.forEach((chart, id) => { + chart.destroy(); + console.log('🗑️ 차트 제거:', id); + }); + this.charts.clear(); + } + + /** + * 차트 생성 및 등록 + * @param {string} chartId - 차트 ID + * @param {HTMLCanvasElement} canvas - 캔버스 요소 + * @param {Object} config - 차트 설정 + * @returns {Chart} 생성된 차트 인스턴스 + */ + createChart(chartId, canvas, config) { + // 기존 차트가 있으면 제거 + this.destroyChart(chartId); + + const chart = new Chart(canvas, config); + this.charts.set(chartId, chart); + + console.log('📊 차트 생성:', chartId); + return chart; + } + + // ========== 시계열 차트 ========== + + /** + * 시계열 차트 렌더링 (기간별 작업 현황) + * @param {string} startDate - 시작일 + * @param {string} endDate - 종료일 + * @param {string} projectId - 프로젝트 ID (선택사항) + */ + async renderTimeSeriesChart(startDate, endDate, projectId = '') { + console.log('📈 시계열 차트 렌더링 시작'); + + try { + const api = window.WorkAnalysisAPI; + const dailyTrendResponse = await api.getDailyTrend(startDate, endDate, projectId); + + if (!dailyTrendResponse.success || !dailyTrendResponse.data) { + throw new Error('일별 추이 데이터를 가져올 수 없습니다'); + } + + const canvas = document.getElementById('workStatusChart'); + if (!canvas) { + console.error('❌ workStatusChart 캔버스를 찾을 수 없습니다'); + return; + } + + const chartData = this.dataProcessor.processTimeSeriesData(dailyTrendResponse.data); + + const config = { + type: 'line', + data: chartData, + options: { + responsive: true, + maintainAspectRatio: false, + aspectRatio: 2, + scales: { + y: { + beginAtZero: true, + title: { + display: true, + text: '작업시간 (h)' + } + }, + y1: { + type: 'linear', + display: true, + position: 'right', + title: { + display: true, + text: '작업자 수 (명)' + }, + grid: { + drawOnChartArea: false, + }, + } + }, + plugins: { + title: { + display: true, + text: '일별 작업 현황' + }, + legend: { + display: true, + position: 'top' + } + } + } + }; + + this.createChart('workStatus', canvas, config); + console.log('✅ 시계열 차트 렌더링 완료'); + + } catch (error) { + console.error('❌ 시계열 차트 렌더링 실패:', error); + this._showChartError('workStatusChart', '시계열 차트를 불러올 수 없습니다'); + } + } + + // ========== 스택 바 차트 ========== + + /** + * 스택 바 차트 렌더링 (프로젝트별 → 작업유형별) + * @param {Array} projectData - 프로젝트 데이터 + */ + renderStackedBarChart(projectData) { + console.log('📊 스택 바 차트 렌더링 시작'); + + const canvas = document.getElementById('projectDistributionChart'); + if (!canvas) { + console.error('❌ projectDistributionChart 캔버스를 찾을 수 없습니다'); + return; + } + + if (!projectData || !projectData.projects || projectData.projects.length === 0) { + this._showChartError('projectDistributionChart', '프로젝트 데이터가 없습니다'); + return; + } + + // 데이터 변환 + const { labels, datasets } = this._processStackedBarData(projectData.projects); + + const config = { + type: 'bar', + data: { + labels, + datasets + }, + options: { + responsive: true, + maintainAspectRatio: false, + aspectRatio: 2, + scales: { + x: { + stacked: true, + title: { + display: true, + text: '프로젝트' + } + }, + y: { + stacked: true, + beginAtZero: true, + title: { + display: true, + text: '작업시간 (h)' + } + } + }, + plugins: { + title: { + display: true, + text: '프로젝트별 작업유형 분포' + }, + legend: { + display: true, + position: 'top' + }, + tooltip: { + mode: 'index', + intersect: false, + callbacks: { + title: function(context) { + return `${context[0].label}`; + }, + label: function(context) { + const workType = context.dataset.label; + const hours = context.parsed.y; + const percentage = ((hours / projectData.totalHours) * 100).toFixed(1); + return `${workType}: ${hours}h (${percentage}%)`; + } + } + } + } + } + }; + + this.createChart('projectDistribution', canvas, config); + console.log('✅ 스택 바 차트 렌더링 완료'); + } + + /** + * 스택 바 차트 데이터 처리 + */ + _processStackedBarData(projects) { + // 모든 작업유형 수집 + const allWorkTypes = new Set(); + projects.forEach(project => { + project.workTypes.forEach(wt => { + allWorkTypes.add(wt.work_type_name); + }); + }); + + const workTypeArray = Array.from(allWorkTypes); + const labels = projects.map(p => p.project_name); + + // 작업유형별 데이터셋 생성 + const datasets = workTypeArray.map((workTypeName, index) => { + const data = projects.map(project => { + const workType = project.workTypes.find(wt => wt.work_type_name === workTypeName); + return workType ? workType.totalHours : 0; + }); + + return { + label: workTypeName, + data, + backgroundColor: this.defaultColors[index % this.defaultColors.length], + borderColor: this.defaultColors[index % this.defaultColors.length], + borderWidth: 1 + }; + }); + + return { labels, datasets }; + } + + // ========== 도넛 차트 ========== + + /** + * 도넛 차트 렌더링 (작업자별 성과) + * @param {Array} workerData - 작업자 데이터 + */ + renderWorkerPerformanceChart(workerData) { + console.log('👤 작업자별 성과 차트 렌더링 시작'); + + const canvas = document.getElementById('workerPerformanceChart'); + if (!canvas) { + console.error('❌ workerPerformanceChart 캔버스를 찾을 수 없습니다'); + return; + } + + if (!workerData || workerData.length === 0) { + this._showChartError('workerPerformanceChart', '작업자 데이터가 없습니다'); + return; + } + + const chartData = this.dataProcessor.processDonutChartData( + workerData.map(worker => ({ + name: worker.worker_name, + hours: worker.totalHours + })) + ); + + const config = { + type: 'doughnut', + data: chartData, + options: { + responsive: true, + maintainAspectRatio: false, + aspectRatio: 1, + plugins: { + title: { + display: true, + text: '작업자별 작업시간 분포' + }, + legend: { + display: true, + position: 'right' + }, + tooltip: { + callbacks: { + label: function(context) { + const label = context.label; + const value = context.parsed; + const total = context.dataset.data.reduce((a, b) => a + b, 0); + const percentage = ((value / total) * 100).toFixed(1); + return `${label}: ${value}h (${percentage}%)`; + } + } + } + } + } + }; + + this.createChart('workerPerformance', canvas, config); + console.log('✅ 작업자별 성과 차트 렌더링 완료'); + } + + // ========== 오류 분석 차트 ========== + + /** + * 오류 분석 차트 렌더링 + * @param {Array} errorData - 오류 데이터 + */ + renderErrorAnalysisChart(errorData) { + console.log('⚠️ 오류 분석 차트 렌더링 시작'); + + const canvas = document.getElementById('errorAnalysisChart'); + if (!canvas) { + console.error('❌ errorAnalysisChart 캔버스를 찾을 수 없습니다'); + return; + } + + if (!errorData || errorData.length === 0) { + this._showChartError('errorAnalysisChart', '오류 데이터가 없습니다'); + return; + } + + // 오류가 있는 데이터만 필터링 + const errorItems = errorData.filter(item => + item.error_count > 0 || (item.errorDetails && item.errorDetails.length > 0) + ); + + if (errorItems.length === 0) { + this._showChartError('errorAnalysisChart', '오류가 발생한 항목이 없습니다'); + return; + } + + const chartData = this.dataProcessor.processDonutChartData( + errorItems.map(item => ({ + name: item.project_name || item.name, + hours: item.errorHours || item.error_count + })) + ); + + const config = { + type: 'doughnut', + data: chartData, + options: { + responsive: true, + maintainAspectRatio: false, + aspectRatio: 1, + plugins: { + title: { + display: true, + text: '프로젝트별 오류 분포' + }, + legend: { + display: true, + position: 'bottom' + }, + tooltip: { + callbacks: { + label: function(context) { + const label = context.label; + const value = context.parsed; + const total = context.dataset.data.reduce((a, b) => a + b, 0); + const percentage = ((value / total) * 100).toFixed(1); + return `${label}: ${value}h (${percentage}%)`; + } + } + } + } + } + }; + + this.createChart('errorAnalysis', canvas, config); + console.log('✅ 오류 분석 차트 렌더링 완료'); + } + + // ========== 유틸리티 ========== + + /** + * 차트 오류 표시 + * @param {string} canvasId - 캔버스 ID + * @param {string} message - 오류 메시지 + */ + _showChartError(canvasId, message) { + const canvas = document.getElementById(canvasId); + if (!canvas) return; + + const container = canvas.parentElement; + if (container) { + container.innerHTML = ` +
+
📊
+
차트를 표시할 수 없습니다
+
${message}
+
+ `; + } + } + + /** + * 차트 리사이즈 + */ + resizeCharts() { + this.charts.forEach((chart, id) => { + try { + chart.resize(); + console.log('📏 차트 리사이즈:', id); + } catch (error) { + console.warn('⚠️ 차트 리사이즈 실패:', id, error); + } + }); + } + + /** + * 차트 상태 확인 + */ + getChartStatus() { + const status = {}; + this.charts.forEach((chart, id) => { + status[id] = { + type: chart.config.type, + datasetCount: chart.data.datasets.length, + dataPointCount: chart.data.labels ? chart.data.labels.length : 0 + }; + }); + return status; + } +} + +// 전역 인스턴스 생성 +window.WorkAnalysisChartRenderer = new WorkAnalysisChartRenderer(); + +// 윈도우 리사이즈 이벤트 리스너 +window.addEventListener('resize', () => { + window.WorkAnalysisChartRenderer.resizeCharts(); +}); + +// Export는 브라우저 환경에서 제거됨 diff --git a/deploy/tkfb-package/web-ui/js/work-analysis/data-processor.js b/deploy/tkfb-package/web-ui/js/work-analysis/data-processor.js new file mode 100644 index 0000000..bd0e9c1 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-analysis/data-processor.js @@ -0,0 +1,355 @@ +/** + * Work Analysis Data Processor Module + * 작업 분석 데이터 가공 및 변환을 담당하는 모듈 + */ + +class WorkAnalysisDataProcessor { + + // ========== 유틸리티 함수 ========== + + /** + * 주말 여부 확인 + * @param {string} dateString - 날짜 문자열 + * @returns {boolean} 주말 여부 + */ + isWeekendDate(dateString) { + const date = new Date(dateString); + const dayOfWeek = date.getDay(); + return dayOfWeek === 0 || dayOfWeek === 6; // 일요일(0) 또는 토요일(6) + } + + /** + * 연차/휴무 프로젝트 여부 확인 + * @param {string} projectName - 프로젝트명 + * @returns {boolean} 연차/휴무 여부 + */ + isVacationProject(projectName) { + if (!projectName) return false; + const vacationKeywords = ['연차', '휴무', '휴가', '병가', '특별휴가']; + return vacationKeywords.some(keyword => projectName.includes(keyword)); + } + + /** + * 날짜 포맷팅 (간단한 형식) + * @param {string} dateString - 날짜 문자열 + * @returns {string} 포맷된 날짜 + */ + formatSimpleDate(dateString) { + if (!dateString) return ''; + return dateString.split('T')[0]; // 시간 부분 제거 + } + + // ========== 프로젝트 분포 데이터 처리 ========== + + /** + * 프로젝트별 데이터 집계 + * @param {Array} recentWorkData - 최근 작업 데이터 + * @returns {Object} 집계된 프로젝트 데이터 + */ + aggregateProjectData(recentWorkData) { + console.log('📊 프로젝트 데이터 집계 시작'); + + if (!recentWorkData || recentWorkData.length === 0) { + return { projects: [], totalHours: 0 }; + } + + const projectMap = new Map(); + let vacationData = null; + + recentWorkData.forEach(work => { + const isWeekend = this.isWeekendDate(work.report_date); + const isVacation = this.isVacationProject(work.project_name); + + // 주말 연차는 제외 + if (isWeekend && isVacation) { + console.log('🏖️ 주말 연차/휴무 제외:', work.report_date, work.project_name); + return; + } + + if (isVacation) { + // 연차/휴무 통합 처리 + if (!vacationData) { + vacationData = { + project_id: 'vacation', + project_name: '연차/휴무', + job_no: null, + totalHours: 0, + workTypes: new Map() + }; + } + this._addWorkToProject(vacationData, work, '연차/휴무'); + } else { + // 일반 프로젝트 처리 + const projectKey = work.project_id || 'unknown'; + + if (!projectMap.has(projectKey)) { + projectMap.set(projectKey, { + project_id: projectKey, + project_name: work.project_name || `프로젝트 ${projectKey}`, + job_no: work.job_no, + totalHours: 0, + workTypes: new Map() + }); + } + + const project = projectMap.get(projectKey); + this._addWorkToProject(project, work); + } + }); + + // 결과 배열 생성 + const projects = Array.from(projectMap.values()); + if (vacationData && vacationData.totalHours > 0) { + projects.push(vacationData); + } + + // 작업유형을 배열로 변환하고 정렬 + projects.forEach(project => { + project.workTypes = Array.from(project.workTypes.values()) + .sort((a, b) => b.totalHours - a.totalHours); + }); + + // 프로젝트를 총 시간 순으로 정렬 (연차/휴무는 맨 아래) + projects.sort((a, b) => { + if (a.project_id === 'vacation') return 1; + if (b.project_id === 'vacation') return -1; + return b.totalHours - a.totalHours; + }); + + const totalHours = projects.reduce((sum, p) => sum + p.totalHours, 0); + + console.log('✅ 프로젝트 데이터 집계 완료:', projects.length, '개 프로젝트'); + return { projects, totalHours }; + } + + /** + * 프로젝트에 작업 데이터 추가 (내부 헬퍼) + */ + _addWorkToProject(project, work, overrideWorkTypeName = null) { + const hours = parseFloat(work.work_hours) || 0; + project.totalHours += hours; + + const workTypeKey = work.work_type_id || 'unknown'; + const workTypeName = overrideWorkTypeName || work.work_type_name || `작업유형 ${workTypeKey}`; + + if (!project.workTypes.has(workTypeKey)) { + project.workTypes.set(workTypeKey, { + work_type_id: workTypeKey, + work_type_name: workTypeName, + totalHours: 0 + }); + } + + project.workTypes.get(workTypeKey).totalHours += hours; + } + + // ========== 오류 분석 데이터 처리 ========== + + /** + * 작업 형태별 오류 데이터 집계 + * @param {Array} recentWorkData - 최근 작업 데이터 + * @returns {Array} 집계된 오류 데이터 + */ + aggregateErrorData(recentWorkData) { + console.log('📊 오류 분석 데이터 집계 시작'); + + if (!recentWorkData || recentWorkData.length === 0) { + return []; + } + + const workTypeMap = new Map(); + let vacationData = null; + + recentWorkData.forEach(work => { + const isWeekend = this.isWeekendDate(work.report_date); + const isVacation = this.isVacationProject(work.project_name); + + // 주말 연차는 완전히 제외 + if (isWeekend && isVacation) { + console.log('🏖️ 주말 연차/휴무 제외:', work.report_date, work.project_name); + return; + } + + if (isVacation) { + // 모든 연차/휴무를 하나로 통합 + if (!vacationData) { + vacationData = { + project_id: 'vacation', + project_name: '연차/휴무', + job_no: null, + work_type_id: 'vacation', + work_type_name: '연차/휴무', + regularHours: 0, + errorHours: 0, + errorDetails: new Map(), + isVacation: true + }; + } + + this._addWorkToErrorData(vacationData, work); + } else { + // 일반 프로젝트 처리 + const workTypeKey = work.work_type_id || 'unknown'; + const combinedKey = `${work.project_id || 'unknown'}_${workTypeKey}`; + + if (!workTypeMap.has(combinedKey)) { + workTypeMap.set(combinedKey, { + project_id: work.project_id, + project_name: work.project_name || `프로젝트 ${work.project_id}`, + job_no: work.job_no, + work_type_id: workTypeKey, + work_type_name: work.work_type_name || `작업유형 ${workTypeKey}`, + regularHours: 0, + errorHours: 0, + errorDetails: new Map(), + isVacation: false + }); + } + + const workTypeData = workTypeMap.get(combinedKey); + this._addWorkToErrorData(workTypeData, work); + } + }); + + // 결과 배열 생성 + const result = Array.from(workTypeMap.values()); + + // 연차/휴무 데이터가 있으면 추가 + if (vacationData && (vacationData.regularHours > 0 || vacationData.errorHours > 0)) { + result.push(vacationData); + } + + // 최종 데이터 처리 + const processedResult = result.map(wt => ({ + ...wt, + totalHours: wt.regularHours + wt.errorHours, + errorRate: wt.regularHours + wt.errorHours > 0 ? + ((wt.errorHours / (wt.regularHours + wt.errorHours)) * 100).toFixed(1) : '0.0', + errorDetails: Array.from(wt.errorDetails.entries()).map(([type, hours]) => ({ + type, hours + })) + })).filter(wt => wt.totalHours > 0) // 시간이 있는 것만 표시 + .sort((a, b) => { + // 연차/휴무를 맨 아래로 + if (a.isVacation && !b.isVacation) return 1; + if (!a.isVacation && b.isVacation) return -1; + + // 같은 프로젝트 내에서는 오류 시간 순으로 정렬 + if (a.project_id === b.project_id) { + return b.errorHours - a.errorHours; + } + + // 다른 프로젝트는 프로젝트명 순으로 정렬 + return (a.project_name || '').localeCompare(b.project_name || ''); + }); + + console.log('✅ 오류 분석 데이터 집계 완료:', processedResult.length, '개 항목'); + return processedResult; + } + + /** + * 작업 데이터를 오류 분석 데이터에 추가 (내부 헬퍼) + */ + _addWorkToErrorData(workTypeData, work) { + const hours = parseFloat(work.work_hours) || 0; + + if (work.work_status === 'error' || work.error_type_id) { + workTypeData.errorHours += hours; + + // 오류 유형별 세분화 + const errorTypeName = work.error_type_name || work.error_description || '설계미스'; + if (!workTypeData.errorDetails.has(errorTypeName)) { + workTypeData.errorDetails.set(errorTypeName, 0); + } + workTypeData.errorDetails.set(errorTypeName, + workTypeData.errorDetails.get(errorTypeName) + hours + ); + } else { + workTypeData.regularHours += hours; + } + } + + // ========== 차트 데이터 처리 ========== + + /** + * 시계열 차트 데이터 변환 + * @param {Array} dailyData - 일별 데이터 + * @returns {Object} 차트 데이터 + */ + processTimeSeriesData(dailyData) { + if (!dailyData || dailyData.length === 0) { + return { labels: [], datasets: [] }; + } + + const labels = dailyData.map(item => this.formatSimpleDate(item.date)); + const hours = dailyData.map(item => item.total_hours || 0); + const workers = dailyData.map(item => item.worker_count || 0); + + return { + labels, + datasets: [ + { + label: '총 작업시간', + data: hours, + borderColor: '#3b82f6', + backgroundColor: 'rgba(59, 130, 246, 0.1)', + tension: 0.4 + }, + { + label: '참여 작업자 수', + data: workers, + borderColor: '#10b981', + backgroundColor: 'rgba(16, 185, 129, 0.1)', + tension: 0.4, + yAxisID: 'y1' + } + ] + }; + } + + /** + * 도넛 차트 데이터 변환 + * @param {Array} projectData - 프로젝트 데이터 + * @returns {Object} 차트 데이터 + */ + processDonutChartData(projectData) { + if (!projectData || projectData.length === 0) { + return { labels: [], datasets: [] }; + } + + const labels = projectData.map(item => item.project_name || item.name); + const data = projectData.map(item => item.total_hours || item.hours || 0); + const colors = this._generateColors(data.length); + + return { + labels, + datasets: [{ + data, + backgroundColor: colors, + borderWidth: 2, + borderColor: '#ffffff' + }] + }; + } + + /** + * 색상 생성 헬퍼 + */ + _generateColors(count) { + const baseColors = [ + '#3b82f6', '#10b981', '#f59e0b', '#ef4444', '#8b5cf6', + '#06b6d4', '#84cc16', '#f97316', '#ec4899', '#6366f1' + ]; + + const colors = []; + for (let i = 0; i < count; i++) { + colors.push(baseColors[i % baseColors.length]); + } + return colors; + } +} + +// 전역 인스턴스 생성 +window.WorkAnalysisDataProcessor = new WorkAnalysisDataProcessor(); + +// Export는 브라우저 환경에서 제거됨 diff --git a/deploy/tkfb-package/web-ui/js/work-analysis/main-controller.js b/deploy/tkfb-package/web-ui/js/work-analysis/main-controller.js new file mode 100644 index 0000000..9dd7074 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-analysis/main-controller.js @@ -0,0 +1,612 @@ +/** + * Work Analysis Main Controller Module + * 작업 분석 페이지의 메인 컨트롤러 - 모든 모듈을 조율하고 사용자 상호작용을 처리 + */ + +class WorkAnalysisMainController { + constructor() { + this.api = window.WorkAnalysisAPI; + this.state = window.WorkAnalysisState; + this.dataProcessor = window.WorkAnalysisDataProcessor; + this.tableRenderer = window.WorkAnalysisTableRenderer; + this.chartRenderer = window.WorkAnalysisChartRenderer; + + this.init(); + } + + /** + * 초기화 + */ + init() { + console.log('🚀 작업 분석 메인 컨트롤러 초기화'); + + this.setupEventListeners(); + this.setupStateListeners(); + this.initializeUI(); + + console.log('✅ 작업 분석 메인 컨트롤러 초기화 완료'); + } + + /** + * 이벤트 리스너 설정 + */ + setupEventListeners() { + // 기간 확정 버튼 + const confirmButton = document.getElementById('confirmPeriodBtn'); + if (confirmButton) { + confirmButton.addEventListener('click', () => this.handlePeriodConfirm()); + } + + // 분석 모드 탭 + document.querySelectorAll('[data-mode]').forEach(button => { + button.addEventListener('click', (e) => { + const mode = e.target.dataset.mode; + this.handleModeChange(mode); + }); + }); + + // 분석 탭 네비게이션 + document.querySelectorAll('[data-tab]').forEach(button => { + button.addEventListener('click', (e) => { + const tabId = e.target.dataset.tab; + this.handleTabChange(tabId); + }); + }); + + // 개별 분석 실행 버튼들 + this.setupAnalysisButtons(); + + // 날짜 입력 필드 + const startDateInput = document.getElementById('startDate'); + const endDateInput = document.getElementById('endDate'); + + if (startDateInput && endDateInput) { + [startDateInput, endDateInput].forEach(input => { + input.addEventListener('change', () => this.handleDateChange()); + }); + } + } + + /** + * 개별 분석 버튼 설정 + */ + setupAnalysisButtons() { + const buttons = [ + { selector: 'button[onclick*="analyzeWorkStatus"]', handler: () => this.analyzeWorkStatus() }, + { selector: 'button[onclick*="analyzeProjectDistribution"]', handler: () => this.analyzeProjectDistribution() }, + { selector: 'button[onclick*="analyzeWorkerPerformance"]', handler: () => this.analyzeWorkerPerformance() }, + { selector: 'button[onclick*="analyzeErrorAnalysis"]', handler: () => this.analyzeErrorAnalysis() } + ]; + + buttons.forEach(({ selector, handler }) => { + const button = document.querySelector(selector); + if (button) { + // 기존 onclick 제거하고 새 이벤트 리스너 추가 + button.removeAttribute('onclick'); + button.addEventListener('click', handler); + } + }); + } + + /** + * 상태 리스너 설정 + */ + setupStateListeners() { + // 기간 확정 상태 변경 시 UI 업데이트 + this.state.subscribe('periodConfirmed', (newState, prevState) => { + this.updateAnalysisButtons(newState.isAnalysisEnabled); + + if (newState.confirmedPeriod.confirmed && !prevState.confirmedPeriod.confirmed) { + this.showAnalysisTabs(); + } + }); + + // 로딩 상태 변경 시 UI 업데이트 + this.state.subscribe('loadingState', (newState) => { + if (newState.isLoading) { + this.showLoading(newState.loadingMessage); + } else { + this.hideLoading(); + } + }); + + // 탭 변경 시 UI 업데이트 + this.state.subscribe('tabChange', (newState) => { + this.updateActiveTab(newState.currentTab); + }); + + // 에러 발생 시 처리 + this.state.subscribe('errorOccurred', (newState) => { + if (newState.lastError) { + this.handleError(newState.lastError); + } + }); + } + + /** + * UI 초기화 + */ + initializeUI() { + // 기본 날짜 설정 + const currentState = this.state.getState(); + const startDateInput = document.getElementById('startDate'); + const endDateInput = document.getElementById('endDate'); + + if (startDateInput && currentState.confirmedPeriod.start) { + startDateInput.value = currentState.confirmedPeriod.start; + } + + if (endDateInput && currentState.confirmedPeriod.end) { + endDateInput.value = currentState.confirmedPeriod.end; + } + + // 분석 버튼 초기 상태 설정 + this.updateAnalysisButtons(false); + + // 분석 탭 숨김 + this.hideAnalysisTabs(); + } + + // ========== 이벤트 핸들러 ========== + + /** + * 기간 확정 처리 + */ + async handlePeriodConfirm() { + try { + const startDate = document.getElementById('startDate').value; + const endDate = document.getElementById('endDate').value; + + console.log('🔄 기간 확정 처리 시작:', startDate, '~', endDate); + + this.state.confirmPeriod(startDate, endDate); + + this.showToast('기간이 확정되었습니다', 'success'); + + console.log('✅ 기간 확정 완료 - 각 분석 버튼을 눌러서 데이터를 확인하세요'); + + } catch (error) { + console.error('❌ 기간 확정 처리 오류:', error); + this.state.setError(error); + this.showToast(error.message, 'error'); + } + } + + /** + * 분석 모드 변경 처리 + */ + handleModeChange(mode) { + try { + this.state.setAnalysisMode(mode); + this.updateModeButtons(mode); + + // 캐시 초기화 + this.state.clearCache(); + + } catch (error) { + this.state.setError(error); + } + } + + /** + * 탭 변경 처리 + */ + handleTabChange(tabId) { + this.state.setCurrentTab(tabId); + } + + /** + * 날짜 변경 처리 + */ + handleDateChange() { + // 날짜가 변경되면 기간 확정 상태 해제 + this.state.updateState({ + confirmedPeriod: { + ...this.state.getState().confirmedPeriod, + confirmed: false + }, + isAnalysisEnabled: false + }); + + this.updateAnalysisButtons(false); + this.hideAnalysisTabs(); + } + + // ========== 분석 실행 ========== + + /** + * 기본 통계 로드 + */ + async loadBasicStats() { + const currentState = this.state.getState(); + const { start, end } = currentState.confirmedPeriod; + + try { + console.log('📊 기본 통계 로딩 시작 - 기간:', start, '~', end); + this.state.startLoading('기본 통계를 로딩 중입니다...'); + + console.log('🌐 API 호출 전 - getBasicStats 호출...'); + const statsResponse = await this.api.getBasicStats(start, end); + + console.log('📊 기본 통계 API 응답:', statsResponse); + + if (statsResponse.success && statsResponse.data) { + const stats = statsResponse.data; + + // 정상/오류 시간 계산 + const totalHours = stats.totalHours || 0; + const errorReports = stats.errorRate || 0; + const errorHours = Math.round(totalHours * (errorReports / 100)); + const normalHours = totalHours - errorHours; + + const cardData = { + totalHours: totalHours, + normalHours: normalHours, + errorHours: errorHours, + workerCount: stats.activeWorkers || stats.activeworkers || 0, + errorRate: errorReports + }; + + this.state.setCache('basicStats', cardData); + this.updateResultCards(cardData); + + console.log('✅ 기본 통계 로딩 완료:', cardData); + } else { + // 기본값으로 카드 업데이트 + const defaultData = { + totalHours: 0, + normalHours: 0, + errorHours: 0, + workerCount: 0, + errorRate: 0 + }; + this.updateResultCards(defaultData); + console.warn('⚠️ 기본 통계 데이터가 없어서 기본값으로 설정'); + } + + } catch (error) { + console.error('❌ 기본 통계 로드 실패:', error); + // 에러 시에도 기본값으로 카드 업데이트 + const defaultData = { + totalHours: 0, + normalHours: 0, + errorHours: 0, + workerCount: 0, + errorRate: 0 + }; + this.updateResultCards(defaultData); + } finally { + this.state.stopLoading(); + } + } + + /** + * 기간별 작업 현황 분석 + */ + async analyzeWorkStatus() { + if (!this.state.canAnalyze()) { + this.showToast('기간을 먼저 확정해주세요', 'warning'); + return; + } + + const currentState = this.state.getState(); + const { start, end } = currentState.confirmedPeriod; + + try { + this.state.startLoading('기간별 작업 현황을 분석 중입니다...'); + + // 실제 API 호출 + const batchData = await this.api.batchCall([ + { + name: 'projectWorkType', + method: 'getProjectWorkTypeAnalysis', + startDate: start, + endDate: end + }, + { + name: 'workerStats', + method: 'getWorkerStats', + startDate: start, + endDate: end + }, + { + name: 'recentWork', + method: 'getRecentWork', + startDate: start, + endDate: end, + limit: 2000 + } + ]); + + console.log('🔍 기간별 작업 현황 API 응답:', batchData); + + // 데이터 처리 + const recentWorkData = batchData.recentWork?.success ? batchData.recentWork.data.data : []; + const workerData = batchData.workerStats?.success ? batchData.workerStats.data.data : []; + + const projectData = this.dataProcessor.aggregateProjectData(recentWorkData); + + // 테이블 렌더링 + this.tableRenderer.renderWorkStatusTable(projectData, workerData, recentWorkData); + + this.showToast('기간별 작업 현황 분석이 완료되었습니다', 'success'); + + } catch (error) { + console.error('❌ 기간별 작업 현황 분석 오류:', error); + this.state.setError(error); + this.showToast('기간별 작업 현황 분석에 실패했습니다', 'error'); + } finally { + this.state.stopLoading(); + } + } + + /** + * 프로젝트별 분포 분석 + */ + async analyzeProjectDistribution() { + if (!this.state.canAnalyze()) { + this.showToast('기간을 먼저 확정해주세요', 'warning'); + return; + } + + const currentState = this.state.getState(); + const { start, end } = currentState.confirmedPeriod; + + try { + this.state.startLoading('프로젝트별 분포를 분석 중입니다...'); + + // 실제 API 호출 + const distributionData = await this.api.getProjectDistributionData(start, end); + + console.log('🔍 프로젝트별 분포 API 응답:', distributionData); + + // 데이터 처리 + const recentWorkData = distributionData.recentWork?.success ? distributionData.recentWork.data.data : []; + const workerData = distributionData.workerStats?.success ? distributionData.workerStats.data.data : []; + + const projectData = this.dataProcessor.aggregateProjectData(recentWorkData); + + console.log('📊 취합된 프로젝트 데이터:', projectData); + + // 테이블 렌더링 + this.tableRenderer.renderProjectDistributionTable(projectData, workerData); + + this.showToast('프로젝트별 분포 분석이 완료되었습니다', 'success'); + + } catch (error) { + console.error('❌ 프로젝트별 분포 분석 오류:', error); + this.state.setError(error); + this.showToast('프로젝트별 분포 분석에 실패했습니다', 'error'); + } finally { + this.state.stopLoading(); + } + } + + /** + * 작업자별 성과 분석 + */ + async analyzeWorkerPerformance() { + if (!this.state.canAnalyze()) { + this.showToast('기간을 먼저 확정해주세요', 'warning'); + return; + } + + const currentState = this.state.getState(); + const { start, end } = currentState.confirmedPeriod; + + try { + this.state.startLoading('작업자별 성과를 분석 중입니다...'); + + const workerStatsResponse = await this.api.getWorkerStats(start, end); + + console.log('👤 작업자 통계 API 응답:', workerStatsResponse); + + if (workerStatsResponse.success && workerStatsResponse.data) { + this.chartRenderer.renderWorkerPerformanceChart(workerStatsResponse.data); + this.showToast('작업자별 성과 분석이 완료되었습니다', 'success'); + } else { + throw new Error('작업자 데이터를 가져올 수 없습니다'); + } + + } catch (error) { + console.error('❌ 작업자별 성과 분석 오류:', error); + this.state.setError(error); + this.showToast('작업자별 성과 분석에 실패했습니다', 'error'); + } finally { + this.state.stopLoading(); + } + } + + /** + * 오류 분석 + */ + async analyzeErrorAnalysis() { + if (!this.state.canAnalyze()) { + this.showToast('기간을 먼저 확정해주세요', 'warning'); + return; + } + + const currentState = this.state.getState(); + const { start, end } = currentState.confirmedPeriod; + + try { + this.state.startLoading('오류 분석을 진행 중입니다...'); + + // 병렬로 API 호출 + const [recentWorkResponse, errorAnalysisResponse] = await Promise.all([ + this.api.getRecentWork(start, end, 2000), + this.api.getErrorAnalysis(start, end) + ]); + + console.log('🔍 오류 분석 API 응답:', recentWorkResponse); + + if (recentWorkResponse.success && recentWorkResponse.data) { + this.tableRenderer.renderErrorAnalysisTable(recentWorkResponse.data); + this.showToast('오류 분석이 완료되었습니다', 'success'); + } else { + throw new Error('작업 데이터를 가져올 수 없습니다'); + } + + } catch (error) { + console.error('❌ 오류 분석 실패:', error); + this.state.setError(error); + this.showToast('오류 분석에 실패했습니다', 'error'); + } finally { + this.state.stopLoading(); + } + } + + // ========== UI 업데이트 ========== + + /** + * 결과 카드 업데이트 + */ + updateResultCards(stats) { + const cards = { + totalHours: stats.totalHours || 0, + normalHours: stats.normalHours || 0, + errorHours: stats.errorHours || 0, + workerCount: stats.activeWorkers || 0, + errorRate: stats.errorRate || 0 + }; + + Object.entries(cards).forEach(([key, value]) => { + const element = document.getElementById(key); + if (element) { + element.textContent = typeof value === 'number' ? + (key.includes('Rate') ? `${value}%` : value.toLocaleString()) : value; + } + }); + } + + /** + * 분석 버튼 상태 업데이트 + */ + updateAnalysisButtons(enabled) { + const buttons = document.querySelectorAll('.chart-analyze-btn'); + buttons.forEach(button => { + button.disabled = !enabled; + button.style.opacity = enabled ? '1' : '0.5'; + }); + } + + /** + * 분석 탭 표시 + */ + showAnalysisTabs() { + const tabNavigation = document.getElementById('analysisTabNavigation'); + if (tabNavigation) { + tabNavigation.style.display = 'block'; + } + } + + /** + * 분석 탭 숨김 + */ + hideAnalysisTabs() { + const tabNavigation = document.getElementById('analysisTabNavigation'); + if (tabNavigation) { + tabNavigation.style.display = 'none'; + } + } + + /** + * 활성 탭 업데이트 + */ + updateActiveTab(tabId) { + // 탭 버튼 업데이트 + document.querySelectorAll('.tab-button').forEach(button => { + button.classList.remove('active'); + if (button.dataset.tab === tabId) { + button.classList.add('active'); + } + }); + + // 탭 컨텐츠 업데이트 + document.querySelectorAll('.tab-content').forEach(content => { + content.classList.remove('active'); + if (content.id === `${tabId}-tab`) { + content.classList.add('active'); + } + }); + } + + /** + * 모드 버튼 업데이트 + */ + updateModeButtons(mode) { + document.querySelectorAll('[data-mode]').forEach(button => { + button.classList.remove('active'); + if (button.dataset.mode === mode) { + button.classList.add('active'); + } + }); + } + + /** + * 로딩 표시 + */ + showLoading(message = '분석 중입니다...') { + const loadingElement = document.getElementById('loadingState'); + if (loadingElement) { + const textElement = loadingElement.querySelector('.loading-text'); + if (textElement) { + textElement.textContent = message; + } + loadingElement.style.display = 'flex'; + } + } + + /** + * 로딩 숨김 + */ + hideLoading() { + const loadingElement = document.getElementById('loadingState'); + if (loadingElement) { + loadingElement.style.display = 'none'; + } + } + + /** + * 토스트 메시지 표시 + */ + showToast(message, type = 'info') { + console.log(`📢 ${type.toUpperCase()}: ${message}`); + + // 간단한 토스트 구현 (실제로는 더 정교한 토스트 라이브러리 사용 권장) + if (type === 'error') { + alert(`❌ ${message}`); + } else if (type === 'success') { + console.log(`✅ ${message}`); + } else if (type === 'warning') { + alert(`⚠️ ${message}`); + } + } + + /** + * 에러 처리 + */ + handleError(errorInfo) { + console.error('❌ 에러 발생:', errorInfo); + this.showToast(errorInfo.message, 'error'); + } + + // ========== 유틸리티 ========== + + /** + * 컨트롤러 상태 디버그 + */ + debug() { + console.log('🔍 메인 컨트롤러 상태:'); + console.log('- API 클라이언트:', this.api); + console.log('- 상태 관리자:', this.state.getState()); + console.log('- 차트 상태:', this.chartRenderer.getChartStatus()); + } +} + +// 전역 인스턴스 생성 및 초기화 +document.addEventListener('DOMContentLoaded', () => { + window.WorkAnalysisMainController = new WorkAnalysisMainController(); +}); + +// Export는 브라우저 환경에서 제거됨 diff --git a/deploy/tkfb-package/web-ui/js/work-analysis/module-loader.js b/deploy/tkfb-package/web-ui/js/work-analysis/module-loader.js new file mode 100644 index 0000000..b68ac64 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-analysis/module-loader.js @@ -0,0 +1,267 @@ +/** + * Work Analysis Module Loader + * 작업 분석 모듈들을 순서대로 로드하고 초기화하는 로더 + */ + +class WorkAnalysisModuleLoader { + constructor() { + this.modules = [ + { name: 'API Client', path: '/js/work-analysis/api-client.js', loaded: false }, + { name: 'Data Processor', path: '/js/work-analysis/data-processor.js', loaded: false }, + { name: 'State Manager', path: '/js/work-analysis/state-manager.js', loaded: false }, + { name: 'Table Renderer', path: '/js/work-analysis/table-renderer.js', loaded: false }, + { name: 'Chart Renderer', path: '/js/work-analysis/chart-renderer.js', loaded: false }, + { name: 'Main Controller', path: '/js/work-analysis/main-controller.js', loaded: false } + ]; + + this.loadingPromise = null; + } + + /** + * 모든 모듈 로드 + * @returns {Promise} 로딩 완료 Promise + */ + async loadAll() { + if (this.loadingPromise) { + return this.loadingPromise; + } + + this.loadingPromise = this._loadModules(); + return this.loadingPromise; + } + + /** + * 모듈들을 순차적으로 로드 + */ + async _loadModules() { + console.log('🚀 작업 분석 모듈 로딩 시작'); + + try { + // 의존성 순서대로 로드 + for (const module of this.modules) { + await this._loadModule(module); + } + + console.log('✅ 모든 작업 분석 모듈 로딩 완료'); + this._onAllModulesLoaded(); + + } catch (error) { + console.error('❌ 모듈 로딩 실패:', error); + this._onLoadingError(error); + throw error; + } + } + + /** + * 개별 모듈 로드 + * @param {Object} module - 모듈 정보 + */ + async _loadModule(module) { + return new Promise((resolve, reject) => { + console.log(`📦 로딩 중: ${module.name}`); + + const script = document.createElement('script'); + script.src = module.path; + script.type = 'text/javascript'; + + script.onload = () => { + module.loaded = true; + console.log(`✅ 로딩 완료: ${module.name}`); + resolve(); + }; + + script.onerror = (error) => { + console.error(`❌ 로딩 실패: ${module.name}`, error); + reject(new Error(`Failed to load ${module.name}: ${module.path}`)); + }; + + document.head.appendChild(script); + }); + } + + /** + * 모든 모듈 로딩 완료 시 호출 + */ + _onAllModulesLoaded() { + // 전역 변수 확인 + const requiredGlobals = [ + 'WorkAnalysisAPI', + 'WorkAnalysisDataProcessor', + 'WorkAnalysisState', + 'WorkAnalysisTableRenderer', + 'WorkAnalysisChartRenderer' + ]; + + const missingGlobals = requiredGlobals.filter(name => !window[name]); + + if (missingGlobals.length > 0) { + console.warn('⚠️ 일부 전역 객체가 누락됨:', missingGlobals); + } + + // 하위 호환성을 위한 전역 함수들 설정 + this._setupLegacyFunctions(); + + // 모듈 로딩 완료 이벤트 발생 + window.dispatchEvent(new CustomEvent('workAnalysisModulesLoaded', { + detail: { modules: this.modules } + })); + + console.log('🎉 작업 분석 시스템 준비 완료'); + } + + /** + * 하위 호환성을 위한 전역 함수 설정 + */ + _setupLegacyFunctions() { + // 기존 HTML에서 사용하던 함수들을 새 모듈 시스템으로 연결 + const legacyFunctions = { + // 기간 확정 + confirmPeriod: () => { + if (window.WorkAnalysisMainController) { + window.WorkAnalysisMainController.handlePeriodConfirm(); + } + }, + + // 분석 모드 변경 + switchAnalysisMode: (mode) => { + if (window.WorkAnalysisState) { + window.WorkAnalysisState.setAnalysisMode(mode); + } + }, + + // 탭 변경 + switchTab: (tabId) => { + if (window.WorkAnalysisState) { + window.WorkAnalysisState.setCurrentTab(tabId); + } + }, + + // 개별 분석 함수들 + analyzeWorkStatus: () => { + if (window.WorkAnalysisMainController) { + window.WorkAnalysisMainController.analyzeWorkStatus(); + } + }, + + analyzeProjectDistribution: () => { + if (window.WorkAnalysisMainController) { + window.WorkAnalysisMainController.analyzeProjectDistribution(); + } + }, + + analyzeWorkerPerformance: () => { + if (window.WorkAnalysisMainController) { + window.WorkAnalysisMainController.analyzeWorkerPerformance(); + } + }, + + analyzeErrorAnalysis: () => { + if (window.WorkAnalysisMainController) { + window.WorkAnalysisMainController.analyzeErrorAnalysis(); + } + } + }; + + // 전역 함수로 등록 + Object.assign(window, legacyFunctions); + + console.log('🔗 하위 호환성 함수 설정 완료'); + } + + /** + * 로딩 에러 처리 + */ + _onLoadingError(error) { + // 에러 UI 표시 + const container = document.querySelector('.analysis-container'); + if (container) { + const errorHTML = ` +
+
⚠️
+

모듈 로딩 실패

+

+ 작업 분석 시스템을 로드하는 중 오류가 발생했습니다.
+ 페이지를 새로고침하거나 관리자에게 문의하세요. +

+ +
+ 기술적 세부사항 +
${error.message}
+
+
+ `; + + container.innerHTML = errorHTML; + } + } + + /** + * 로딩 상태 확인 + * @returns {Object} 로딩 상태 정보 + */ + getLoadingStatus() { + const total = this.modules.length; + const loaded = this.modules.filter(m => m.loaded).length; + + return { + total, + loaded, + percentage: Math.round((loaded / total) * 100), + isComplete: loaded === total, + modules: this.modules.map(m => ({ + name: m.name, + loaded: m.loaded + })) + }; + } + + /** + * 특정 모듈 로딩 상태 확인 + * @param {string} moduleName - 모듈명 + * @returns {boolean} 로딩 완료 여부 + */ + isModuleLoaded(moduleName) { + const module = this.modules.find(m => m.name === moduleName); + return module ? module.loaded : false; + } +} + +// 전역 인스턴스 생성 +window.WorkAnalysisModuleLoader = new WorkAnalysisModuleLoader(); + +// 자동 로딩 시작 (DOM이 준비되면) +if (document.readyState === 'loading') { + document.addEventListener('DOMContentLoaded', () => { + window.WorkAnalysisModuleLoader.loadAll(); + }); +} else { + // DOM이 이미 준비된 경우 즉시 로딩 + window.WorkAnalysisModuleLoader.loadAll(); +} + +// Export는 브라우저 환경에서 제거됨 diff --git a/deploy/tkfb-package/web-ui/js/work-analysis/state-manager.js b/deploy/tkfb-package/web-ui/js/work-analysis/state-manager.js new file mode 100644 index 0000000..0668bdf --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-analysis/state-manager.js @@ -0,0 +1,382 @@ +/** + * Work Analysis State Manager Module + * 작업 분석 페이지의 상태 관리를 담당하는 모듈 + */ + +class WorkAnalysisStateManager { + constructor() { + this.state = { + // 분석 설정 + analysisMode: 'period', // 'period' | 'project' + confirmedPeriod: { + start: null, + end: null, + confirmed: false + }, + + // UI 상태 + currentTab: 'work-status', + isAnalysisEnabled: false, + isLoading: false, + + // 데이터 캐시 + cache: { + basicStats: null, + chartData: null, + projectDistribution: null, + errorAnalysis: null + }, + + // 에러 상태 + lastError: null + }; + + this.listeners = new Map(); + this.init(); + } + + /** + * 초기화 + */ + init() { + console.log('🔧 상태 관리자 초기화'); + + // 기본 날짜 설정 (현재 월) + const now = new Date(); + const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); + const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0); + + this.updateState({ + confirmedPeriod: { + start: this.formatDate(startOfMonth), + end: this.formatDate(endOfMonth), + confirmed: false + } + }); + } + + /** + * 상태 업데이트 + * @param {Object} updates - 업데이트할 상태 + */ + updateState(updates) { + const prevState = { ...this.state }; + this.state = { ...this.state, ...updates }; + + console.log('🔄 상태 업데이트:', updates); + + // 리스너들에게 상태 변경 알림 + this.notifyListeners(prevState, this.state); + } + + /** + * 상태 리스너 등록 + * @param {string} key - 리스너 키 + * @param {Function} callback - 콜백 함수 + */ + subscribe(key, callback) { + this.listeners.set(key, callback); + } + + /** + * 상태 리스너 제거 + * @param {string} key - 리스너 키 + */ + unsubscribe(key) { + this.listeners.delete(key); + } + + /** + * 리스너들에게 알림 + */ + notifyListeners(prevState, newState) { + this.listeners.forEach((callback, key) => { + try { + callback(newState, prevState); + } catch (error) { + console.error(`❌ 리스너 ${key} 오류:`, error); + } + }); + } + + // ========== 분석 설정 관리 ========== + + /** + * 분석 모드 변경 + * @param {string} mode - 분석 모드 ('period' | 'project') + */ + setAnalysisMode(mode) { + if (mode !== 'period' && mode !== 'project') { + throw new Error('유효하지 않은 분석 모드입니다.'); + } + + this.updateState({ + analysisMode: mode, + currentTab: 'work-status' // 모드 변경 시 첫 번째 탭으로 리셋 + }); + } + + /** + * 기간 확정 + * @param {string} startDate - 시작일 + * @param {string} endDate - 종료일 + */ + confirmPeriod(startDate, endDate) { + // 날짜 유효성 검사 + if (!startDate || !endDate) { + throw new Error('시작일과 종료일을 모두 입력해주세요.'); + } + + const start = new Date(startDate); + const end = new Date(endDate); + + if (start > end) { + throw new Error('시작일이 종료일보다 늦을 수 없습니다.'); + } + + // 최대 1년 제한 + const maxDays = 365; + const daysDiff = Math.ceil((end - start) / (1000 * 60 * 60 * 24)); + if (daysDiff > maxDays) { + throw new Error(`분석 기간은 최대 ${maxDays}일까지 가능합니다.`); + } + + this.updateState({ + confirmedPeriod: { + start: startDate, + end: endDate, + confirmed: true + }, + isAnalysisEnabled: true, + // 기간 변경 시 캐시 초기화 + cache: { + basicStats: null, + chartData: null, + projectDistribution: null, + errorAnalysis: null + } + }); + + console.log('✅ 기간 확정:', startDate, '~', endDate); + } + + /** + * 현재 탭 변경 + * @param {string} tabId - 탭 ID + */ + setCurrentTab(tabId) { + const validTabs = ['work-status', 'project-distribution', 'worker-performance', 'error-analysis']; + + if (!validTabs.includes(tabId)) { + console.warn('유효하지 않은 탭 ID:', tabId); + return; + } + + this.updateState({ currentTab: tabId }); + + // DOM 업데이트 직접 수행 + this.updateTabDOM(tabId); + + console.log('🔄 탭 전환:', tabId); + } + + /** + * 탭 DOM 업데이트 + * @param {string} tabId - 탭 ID + */ + updateTabDOM(tabId) { + // 탭 버튼 업데이트 + document.querySelectorAll('.tab-button').forEach(button => { + button.classList.remove('active'); + if (button.dataset.tab === tabId) { + button.classList.add('active'); + } + }); + + // 탭 컨텐츠 업데이트 + document.querySelectorAll('.tab-content').forEach(content => { + content.classList.remove('active'); + if (content.id === `${tabId}-tab`) { + content.classList.add('active'); + } + }); + } + + // ========== 로딩 상태 관리 ========== + + /** + * 로딩 시작 + * @param {string} message - 로딩 메시지 + */ + startLoading(message = '분석 중입니다...') { + this.updateState({ + isLoading: true, + loadingMessage: message + }); + } + + /** + * 로딩 종료 + */ + stopLoading() { + this.updateState({ + isLoading: false, + loadingMessage: null + }); + } + + // ========== 데이터 캐시 관리 ========== + + /** + * 캐시 데이터 저장 + * @param {string} key - 캐시 키 + * @param {*} data - 저장할 데이터 + */ + setCache(key, data) { + this.updateState({ + cache: { + ...this.state.cache, + [key]: { + data, + timestamp: Date.now() + } + } + }); + } + + /** + * 캐시 데이터 조회 + * @param {string} key - 캐시 키 + * @param {number} maxAge - 최대 유효 시간 (밀리초) + * @returns {*} 캐시된 데이터 또는 null + */ + getCache(key, maxAge = 5 * 60 * 1000) { // 기본 5분 + const cached = this.state.cache[key]; + + if (!cached) { + return null; + } + + const age = Date.now() - cached.timestamp; + if (age > maxAge) { + console.log('🗑️ 캐시 만료:', key); + return null; + } + + console.log('📦 캐시 히트:', key); + return cached.data; + } + + /** + * 캐시 초기화 + * @param {string} key - 특정 키만 초기화 (선택사항) + */ + clearCache(key = null) { + if (key) { + this.updateState({ + cache: { + ...this.state.cache, + [key]: null + } + }); + } else { + this.updateState({ + cache: { + basicStats: null, + chartData: null, + projectDistribution: null, + errorAnalysis: null + } + }); + } + } + + // ========== 에러 관리 ========== + + /** + * 에러 설정 + * @param {Error|string} error - 에러 객체 또는 메시지 + */ + setError(error) { + const errorInfo = { + message: error instanceof Error ? error.message : error, + timestamp: Date.now(), + stack: error instanceof Error ? error.stack : null + }; + + this.updateState({ + lastError: errorInfo, + isLoading: false + }); + + console.error('❌ 에러 발생:', errorInfo); + } + + /** + * 에러 초기화 + */ + clearError() { + this.updateState({ lastError: null }); + } + + // ========== 유틸리티 ========== + + /** + * 날짜 포맷팅 + * @param {Date} date - 날짜 객체 + * @returns {string} YYYY-MM-DD 형식 + */ + formatDate(date) { + return date.toISOString().split('T')[0]; + } + + /** + * 현재 상태 조회 + * @returns {Object} 현재 상태 + */ + getState() { + return { ...this.state }; + } + + /** + * 분석 가능 여부 확인 + * @returns {boolean} 분석 가능 여부 + */ + canAnalyze() { + return this.state.confirmedPeriod.confirmed && + this.state.confirmedPeriod.start && + this.state.confirmedPeriod.end && + !this.state.isLoading; + } + + /** + * 상태 디버그 정보 출력 + */ + debug() { + console.log('🔍 현재 상태:', this.state); + console.log('👂 등록된 리스너:', Array.from(this.listeners.keys())); + } +} + +// 전역 인스턴스 생성 +window.WorkAnalysisState = new WorkAnalysisStateManager(); + +// 하위 호환성을 위한 전역 변수들 +Object.defineProperty(window, 'currentAnalysisMode', { + get: () => window.WorkAnalysisState.state.analysisMode, + set: (value) => window.WorkAnalysisState.setAnalysisMode(value) +}); + +Object.defineProperty(window, 'confirmedStartDate', { + get: () => window.WorkAnalysisState.state.confirmedPeriod.start +}); + +Object.defineProperty(window, 'confirmedEndDate', { + get: () => window.WorkAnalysisState.state.confirmedPeriod.end +}); + +Object.defineProperty(window, 'isAnalysisEnabled', { + get: () => window.WorkAnalysisState.state.isAnalysisEnabled +}); + +// Export는 브라우저 환경에서 제거됨 diff --git a/deploy/tkfb-package/web-ui/js/work-analysis/table-renderer.js b/deploy/tkfb-package/web-ui/js/work-analysis/table-renderer.js new file mode 100644 index 0000000..6572f04 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-analysis/table-renderer.js @@ -0,0 +1,510 @@ +/** + * Work Analysis Table Renderer Module + * 작업 분석 테이블 렌더링을 담당하는 모듈 + */ + +class WorkAnalysisTableRenderer { + constructor() { + this.dataProcessor = window.WorkAnalysisDataProcessor; + } + + // ========== 프로젝트 분포 테이블 ========== + + /** + * 프로젝트 분포 테이블 렌더링 (Production Report 스타일) + * @param {Array} projectData - 프로젝트 데이터 + * @param {Array} workerData - 작업자 데이터 + */ + renderProjectDistributionTable(projectData, workerData) { + console.log('📋 프로젝트별 분포 테이블 렌더링 시작'); + + const tbody = document.getElementById('projectDistributionTableBody'); + const tfoot = document.getElementById('projectDistributionTableFooter'); + + if (!tbody) { + console.error('❌ projectDistributionTableBody 요소를 찾을 수 없습니다'); + return; + } + + // 프로젝트 데이터가 없으면 작업자 데이터로 대체 + if (!projectData || !projectData.projects || projectData.projects.length === 0) { + console.log('⚠️ 프로젝트 데이터가 없어서 작업자 데이터로 대체합니다.'); + this._renderFallbackTable(workerData, tbody, tfoot); + return; + } + + let tableRows = []; + let grandTotalHours = 0; + let grandTotalManDays = 0; + let grandTotalLaborCost = 0; + + // 공수당 인건비 (350,000원) + const manDayRate = 350000; + + // 먼저 전체 시간을 계산 (부하율 계산용) + projectData.projects.forEach(project => { + project.workTypes.forEach(workType => { + grandTotalHours += workType.totalHours; + }); + }); + + // 프로젝트별로 렌더링 + projectData.projects.forEach(project => { + const projectName = project.project_name || '알 수 없는 프로젝트'; + const jobNo = project.job_no || 'N/A'; + const workTypes = project.workTypes || []; + + if (workTypes.length === 0) { + // 작업유형이 없는 경우 + const projectHours = project.totalHours || 0; + const manDays = Math.round((projectHours / 8) * 100) / 100; + const laborCost = manDays * manDayRate; + const loadRate = grandTotalHours > 0 ? ((projectHours / grandTotalHours) * 100).toFixed(2) : '0.00'; + + grandTotalManDays += manDays; + grandTotalLaborCost += laborCost; + + const isVacation = project.project_id === 'vacation'; + const displayText = isVacation ? projectName : jobNo; + + tableRows.push(` + + ${displayText} + 데이터 없음 + ${manDays} + ${loadRate}% + ₩${laborCost.toLocaleString()} + + `); + } else { + // 작업유형별 렌더링 + workTypes.forEach((workType, index) => { + const isFirstWorkType = index === 0; + const rowspan = workTypes.length; + const workTypeHours = workType.totalHours || 0; + const manDays = Math.round((workTypeHours / 8) * 100) / 100; + const laborCost = manDays * manDayRate; + const loadRate = grandTotalHours > 0 ? ((workTypeHours / grandTotalHours) * 100).toFixed(2) : '0.00'; + + grandTotalManDays += manDays; + grandTotalLaborCost += laborCost; + + const isVacation = project.project_id === 'vacation'; + const displayText = isVacation ? projectName : jobNo; + + tableRows.push(` + + ${isFirstWorkType ? `${displayText}` : ''} + ${workType.work_type_name} + ${manDays} + ${loadRate}% + ₩${laborCost.toLocaleString()} + + `); + }); + + // 프로젝트 소계 행 추가 + const projectTotalHours = workTypes.reduce((sum, wt) => sum + (wt.totalHours || 0), 0); + const projectTotalManDays = Math.round((projectTotalHours / 8) * 100) / 100; + const projectTotalLaborCost = projectTotalManDays * manDayRate; + const projectLoadRate = grandTotalHours > 0 ? ((projectTotalHours / grandTotalHours) * 100).toFixed(2) : '0.00'; + + tableRows.push(` + + ${projectName} 소계 + ${projectTotalManDays} + ${projectLoadRate}% + ₩${projectTotalLaborCost.toLocaleString()} + + `); + } + }); + + // 테이블 업데이트 + tbody.innerHTML = tableRows.join(''); + + // 총계 업데이트 + if (tfoot) { + document.getElementById('totalManDays').textContent = grandTotalManDays.toFixed(2); + document.getElementById('totalLaborCost').textContent = `₩${grandTotalLaborCost.toLocaleString()}`; + tfoot.style.display = 'table-footer-group'; + } + + console.log('✅ 프로젝트별 분포 테이블 렌더링 완료'); + } + + /** + * 대체 테이블 렌더링 (작업자 데이터 기반) + */ + _renderFallbackTable(workerData, tbody, tfoot) { + if (!workerData || workerData.length === 0) { + tbody.innerHTML = ` + + + 해당 기간에 데이터가 없습니다 + + + `; + if (tfoot) tfoot.style.display = 'none'; + return; + } + + const manDayRate = 350000; + let totalManDays = 0; + let totalLaborCost = 0; + + const tableRows = workerData.map(worker => { + const hours = worker.totalHours || 0; + const manDays = Math.round((hours / 8) * 100) / 100; + const laborCost = manDays * manDayRate; + + totalManDays += manDays; + totalLaborCost += laborCost; + + return ` + + 작업자 기반 + ${worker.worker_name} + ${manDays} + - + ₩${laborCost.toLocaleString()} + + `; + }); + + tbody.innerHTML = tableRows.join(''); + + // 총계 업데이트 + if (tfoot) { + document.getElementById('totalManDays').textContent = totalManDays.toFixed(2); + document.getElementById('totalLaborCost').textContent = `₩${totalLaborCost.toLocaleString()}`; + tfoot.style.display = 'table-footer-group'; + } + } + + // ========== 오류 분석 테이블 ========== + + /** + * 오류 분석 테이블 렌더링 + * @param {Array} recentWorkData - 최근 작업 데이터 + */ + renderErrorAnalysisTable(recentWorkData) { + console.log('📊 오류 분석 테이블 렌더링 시작'); + console.log('📊 받은 데이터:', recentWorkData); + + const tableBody = document.getElementById('errorAnalysisTableBody'); + const tableFooter = document.getElementById('errorAnalysisTableFooter'); + + console.log('📊 DOM 요소 확인:', { tableBody, tableFooter }); + + // DOM 요소 존재 확인 + if (!tableBody) { + console.error('❌ errorAnalysisTableBody 요소를 찾을 수 없습니다'); + return; + } + + if (!recentWorkData || recentWorkData.length === 0) { + tableBody.innerHTML = ` + + + 해당 기간에 오류 데이터가 없습니다 + + + `; + if (tableFooter) { + tableFooter.style.display = 'none'; + } + return; + } + + // 작업 형태별 오류 데이터 집계 + const errorData = this.dataProcessor.aggregateErrorData(recentWorkData); + + let tableRows = []; + let grandTotalHours = 0; + let grandTotalRegularHours = 0; + let grandTotalErrorHours = 0; + + // 프로젝트별로 그룹화 + const projectGroups = new Map(); + errorData.forEach(workType => { + const projectKey = workType.isVacation ? 'vacation' : workType.project_id; + if (!projectGroups.has(projectKey)) { + projectGroups.set(projectKey, []); + } + projectGroups.get(projectKey).push(workType); + }); + + // 프로젝트별로 렌더링 + Array.from(projectGroups.entries()).forEach(([projectKey, workTypes]) => { + workTypes.forEach((workType, index) => { + grandTotalHours += workType.totalHours; + grandTotalRegularHours += workType.regularHours; + grandTotalErrorHours += workType.errorHours; + + const rowClass = workType.isVacation ? 'vacation-project' : 'project-group'; + const isFirstWorkType = index === 0; + const rowspan = workTypes.length; + + // 세부시간 구성 + let detailHours = []; + if (workType.regularHours > 0) { + detailHours.push(`정규: ${workType.regularHours}h`); + } + + // 오류 세부사항 추가 + workType.errorDetails.forEach(error => { + detailHours.push(`오류: ${error.type} ${error.hours}h`); + }); + + // 작업 타입 구성 (단순화) + let workTypeDisplay = ''; + if (workType.regularHours > 0) { + workTypeDisplay += ` +
+ 정규시간 +
+ `; + } + + workType.errorDetails.forEach(error => { + workTypeDisplay += ` +
+ 오류: ${error.type} +
+ `; + }); + + tableRows.push(` + + ${isFirstWorkType ? `${workType.isVacation ? '연차/휴무' : (workType.project_name || 'N/A')}` : ''} + ${workType.work_type_name} + ${workType.totalHours}h + + ${detailHours.join('
')} + + +
+ ${workTypeDisplay} +
+ + ${workType.errorRate}% + + `); + }); + }); + + if (tableRows.length === 0) { + tableBody.innerHTML = ` + + + 해당 기간에 작업 데이터가 없습니다 + + + `; + if (tableFooter) { + tableFooter.style.display = 'none'; + } + } else { + tableBody.innerHTML = tableRows.join(''); + + // 총계 업데이트 + const totalErrorRate = grandTotalHours > 0 ? ((grandTotalErrorHours / grandTotalHours) * 100).toFixed(1) : '0.0'; + + // 안전한 DOM 요소 접근 + const totalErrorHoursElement = document.getElementById('totalErrorHours'); + if (totalErrorHoursElement) { + totalErrorHoursElement.textContent = `${grandTotalHours}h`; + } + + if (tableFooter) { + const detailHoursCell = tableFooter.querySelector('.total-row td:nth-child(4)'); + const errorRateCell = tableFooter.querySelector('.total-row td:nth-child(6)'); + + if (detailHoursCell) { + detailHoursCell.innerHTML = ` + 정규: ${grandTotalRegularHours}h
오류: ${grandTotalErrorHours}h
+ `; + } + + if (errorRateCell) { + errorRateCell.innerHTML = `${totalErrorRate}%`; + } + + tableFooter.style.display = 'table-footer-group'; + } + } + + console.log('✅ 오류 분석 테이블 렌더링 완료'); + } + + // ========== 기간별 작업 현황 테이블 ========== + + /** + * 기간별 작업 현황 테이블 렌더링 + * @param {Array} projectData - 프로젝트 데이터 + * @param {Array} workerData - 작업자 데이터 + * @param {Array} recentWorkData - 최근 작업 데이터 + */ + renderWorkStatusTable(projectData, workerData, recentWorkData) { + console.log('📈 기간별 작업 현황 테이블 렌더링 시작'); + + const tableContainer = document.querySelector('#work-status-tab .table-container'); + if (!tableContainer) { + console.error('❌ 작업 현황 테이블 컨테이너를 찾을 수 없습니다'); + return; + } + + // 데이터가 없는 경우 처리 + if (!workerData || workerData.length === 0) { + tableContainer.innerHTML = ` +
+
📊
+
데이터가 없습니다
+
선택한 기간에 작업 데이터가 없습니다.
+
+ `; + return; + } + + // 작업자별 데이터 처리 + const workerStats = this._processWorkerStats(workerData, recentWorkData); + + let tableHTML = ` + + + + + + + + + + + + + + `; + + let totalHours = 0; + let totalManDays = 0; + + workerStats.forEach(worker => { + worker.projects.forEach((project, projectIndex) => { + project.workTypes.forEach((workType, workTypeIndex) => { + const isFirstProject = projectIndex === 0 && workTypeIndex === 0; + const workerRowspan = worker.totalRowspan; + + totalHours += workType.hours; + totalManDays += workType.manDays; + + tableHTML += ` + + ${isFirstProject ? ` + + ` : ''} + + + + ${isFirstProject ? ` + + + ` : ''} + + + `; + }); + }); + }); + + tableHTML += ` + + + + + + + + + +
작업자분류(프로젝트)작업내용투입시간작업공수작업일/일평균시간비고
${worker.name}${project.name}${workType.name}${workType.hours}h${worker.totalManDays.toFixed(1)}${worker.workDays}일 / ${worker.avgHours.toFixed(1)}h${workType.remarks}
총 공수${totalHours}h${totalManDays.toFixed(1)}
+ `; + + tableContainer.innerHTML = tableHTML; + console.log('✅ 기간별 작업 현황 테이블 렌더링 완료'); + } + + /** + * 작업자별 통계 처리 (내부 헬퍼) + */ + _processWorkerStats(workerData, recentWorkData) { + if (!workerData || workerData.length === 0) { + return []; + } + + return workerData.map(worker => { + // 해당 작업자의 작업 데이터 필터링 + const workerWork = recentWorkData ? + recentWorkData.filter(work => work.worker_id === worker.worker_id) : []; + + // 프로젝트별로 그룹화 + const projectMap = new Map(); + workerWork.forEach(work => { + const projectKey = work.project_id || 'unknown'; + if (!projectMap.has(projectKey)) { + projectMap.set(projectKey, { + name: work.project_name || `프로젝트 ${projectKey}`, + workTypes: new Map() + }); + } + + const project = projectMap.get(projectKey); + const workTypeKey = work.work_type_id || 'unknown'; + const workTypeName = work.work_type_name || `작업유형 ${workTypeKey}`; + + if (!project.workTypes.has(workTypeKey)) { + project.workTypes.set(workTypeKey, { + name: workTypeName, + hours: 0, + remarks: '정상' + }); + } + + const workType = project.workTypes.get(workTypeKey); + workType.hours += parseFloat(work.work_hours) || 0; + + // 오류가 있으면 비고 업데이트 + if (work.work_status === 'error' || work.error_type_id) { + workType.remarks = work.error_type_name || work.error_description || '오류'; + } + }); + + // 프로젝트 배열로 변환 + const projects = Array.from(projectMap.values()).map(project => ({ + ...project, + workTypes: Array.from(project.workTypes.values()).map(wt => ({ + ...wt, + manDays: Math.round((wt.hours / 8) * 10) / 10 + })) + })); + + // 전체 행 수 계산 + const totalRowspan = projects.reduce((sum, p) => sum + p.workTypes.length, 0); + + return { + name: worker.worker_name, + totalHours: worker.totalHours || 0, + totalManDays: (worker.totalHours || 0) / 8, + workDays: worker.workingDays || 0, + avgHours: worker.avgHours || 0, + projects, + totalRowspan: Math.max(totalRowspan, 1) + }; + }); + } +} + +// 전역 인스턴스 생성 +window.WorkAnalysisTableRenderer = new WorkAnalysisTableRenderer(); + +// Export는 브라우저 환경에서 제거됨 diff --git a/deploy/tkfb-package/web-ui/js/work-issue-report.js b/deploy/tkfb-package/web-ui/js/work-issue-report.js new file mode 100644 index 0000000..1cb49bc --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-issue-report.js @@ -0,0 +1,740 @@ +/** + * 문제 신고 등록 페이지 JavaScript + */ + +// API 설정 +const API_BASE = window.API_BASE_URL || 'http://localhost:20005/api'; + +// 상태 변수 +let selectedFactoryId = null; +let selectedWorkplaceId = null; +let selectedWorkplaceName = null; +let selectedType = null; // 'nonconformity' | 'safety' +let selectedCategoryId = null; +let selectedCategoryName = null; +let selectedItemId = null; +let selectedTbmSessionId = null; +let selectedVisitRequestId = null; +let photos = [null, null, null, null, null]; + +// 지도 관련 변수 +let canvas, ctx, canvasImage; +let mapRegions = []; +let todayWorkers = []; +let todayVisitors = []; + +// DOM 요소 +let factorySelect, issueMapCanvas; +let photoInput, currentPhotoIndex; + +// 초기화 +document.addEventListener('DOMContentLoaded', async () => { + factorySelect = document.getElementById('factorySelect'); + issueMapCanvas = document.getElementById('issueMapCanvas'); + photoInput = document.getElementById('photoInput'); + + canvas = issueMapCanvas; + ctx = canvas.getContext('2d'); + + // 이벤트 리스너 설정 + setupEventListeners(); + + // 공장 목록 로드 + await loadFactories(); +}); + +/** + * 이벤트 리스너 설정 + */ +function setupEventListeners() { + // 공장 선택 + factorySelect.addEventListener('change', onFactoryChange); + + // 지도 클릭 + canvas.addEventListener('click', onMapClick); + + // 기타 위치 토글 + document.getElementById('useCustomLocation').addEventListener('change', (e) => { + const customInput = document.getElementById('customLocationInput'); + customInput.classList.toggle('visible', e.target.checked); + + if (e.target.checked) { + // 지도 선택 초기화 + selectedWorkplaceId = null; + selectedWorkplaceName = null; + selectedTbmSessionId = null; + selectedVisitRequestId = null; + updateLocationInfo(); + } + }); + + // 유형 버튼 클릭 + document.querySelectorAll('.type-btn').forEach(btn => { + btn.addEventListener('click', () => onTypeSelect(btn.dataset.type)); + }); + + // 사진 슬롯 클릭 + document.querySelectorAll('.photo-slot').forEach(slot => { + slot.addEventListener('click', (e) => { + if (e.target.classList.contains('remove-btn')) return; + currentPhotoIndex = parseInt(slot.dataset.index); + photoInput.click(); + }); + }); + + // 사진 삭제 버튼 + document.querySelectorAll('.photo-slot .remove-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + e.stopPropagation(); + const slot = btn.closest('.photo-slot'); + const index = parseInt(slot.dataset.index); + removePhoto(index); + }); + }); + + // 사진 선택 + photoInput.addEventListener('change', onPhotoSelect); +} + +/** + * 공장 목록 로드 + */ +async function loadFactories() { + try { + const response = await fetch(`${API_BASE}/workplaces/categories/active/list`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) throw new Error('공장 목록 조회 실패'); + + const data = await response.json(); + if (data.success && data.data) { + data.data.forEach(factory => { + const option = document.createElement('option'); + option.value = factory.category_id; + option.textContent = factory.category_name; + factorySelect.appendChild(option); + }); + + // 첫 번째 공장 자동 선택 + if (data.data.length > 0) { + factorySelect.value = data.data[0].category_id; + onFactoryChange(); + } + } + } catch (error) { + console.error('공장 목록 로드 실패:', error); + } +} + +/** + * 공장 변경 시 + */ +async function onFactoryChange() { + selectedFactoryId = factorySelect.value; + if (!selectedFactoryId) return; + + // 위치 선택 초기화 + selectedWorkplaceId = null; + selectedWorkplaceName = null; + selectedTbmSessionId = null; + selectedVisitRequestId = null; + updateLocationInfo(); + + // 지도 데이터 로드 + await Promise.all([ + loadMapImage(), + loadMapRegions(), + loadTodayData() + ]); + + renderMap(); +} + +/** + * 배치도 이미지 로드 + */ +async function loadMapImage() { + try { + const response = await fetch(`${API_BASE}/workplaces/categories`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) return; + + const data = await response.json(); + if (data.success && data.data) { + const selectedCategory = data.data.find(c => c.category_id == selectedFactoryId); + if (selectedCategory && selectedCategory.layout_image) { + const baseUrl = (window.API_BASE_URL || 'http://localhost:20005').replace('/api', ''); + const fullImageUrl = selectedCategory.layout_image.startsWith('http') + ? selectedCategory.layout_image + : `${baseUrl}${selectedCategory.layout_image}`; + + canvasImage = new Image(); + canvasImage.onload = () => renderMap(); + canvasImage.src = fullImageUrl; + } + } + } catch (error) { + console.error('배치도 이미지 로드 실패:', error); + } +} + +/** + * 지도 영역 로드 + */ +async function loadMapRegions() { + try { + const response = await fetch(`${API_BASE}/workplaces/categories/${selectedFactoryId}/map-regions`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) return; + + const data = await response.json(); + if (data.success) { + mapRegions = data.data || []; + } + } catch (error) { + console.error('지도 영역 로드 실패:', error); + } +} + +/** + * 오늘 TBM/출입신청 데이터 로드 + */ +async function loadTodayData() { + const today = new Date().toISOString().split('T')[0]; + + try { + // TBM 세션 로드 + const tbmResponse = await fetch(`${API_BASE}/tbm/sessions/date/${today}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (tbmResponse.ok) { + const tbmData = await tbmResponse.json(); + todayWorkers = tbmData.data || []; + } + + // 출입 신청 로드 + const visitResponse = await fetch(`${API_BASE}/workplace-visits/requests`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (visitResponse.ok) { + const visitData = await visitResponse.json(); + todayVisitors = (visitData.data || []).filter(v => + v.visit_date === today && + (v.status === 'approved' || v.status === 'training_completed') + ); + } + } catch (error) { + console.error('오늘 데이터 로드 실패:', error); + } +} + +/** + * 지도 렌더링 + */ +function renderMap() { + if (!canvas || !ctx) return; + + // 캔버스 크기 설정 + const container = canvas.parentElement; + canvas.width = container.clientWidth; + canvas.height = 400; + + // 배경 그리기 + ctx.fillStyle = '#f3f4f6'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + + // 배치도 이미지 + if (canvasImage && canvasImage.complete) { + const scale = Math.min(canvas.width / canvasImage.width, canvas.height / canvasImage.height); + const x = (canvas.width - canvasImage.width * scale) / 2; + const y = (canvas.height - canvasImage.height * scale) / 2; + ctx.drawImage(canvasImage, x, y, canvasImage.width * scale, canvasImage.height * scale); + } + + // 작업장 영역 그리기 + mapRegions.forEach(region => { + const workers = todayWorkers.filter(w => w.workplace_id === region.workplace_id); + const visitors = todayVisitors.filter(v => v.workplace_id === region.workplace_id); + + const workerCount = workers.reduce((sum, w) => sum + (w.member_count || 0), 0); + const visitorCount = visitors.reduce((sum, v) => sum + (v.visitor_count || 0), 0); + + drawWorkplaceRegion(region, workerCount, visitorCount); + }); +} + +/** + * 작업장 영역 그리기 + */ +function drawWorkplaceRegion(region, workerCount, visitorCount) { + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + const width = x2 - x1; + const height = y2 - y1; + + // 선택된 작업장 하이라이트 + const isSelected = region.workplace_id === selectedWorkplaceId; + + // 색상 결정 + let fillColor, strokeColor; + if (isSelected) { + fillColor = 'rgba(34, 197, 94, 0.3)'; // 초록색 + strokeColor = 'rgb(34, 197, 94)'; + } else if (workerCount > 0 && visitorCount > 0) { + fillColor = 'rgba(34, 197, 94, 0.2)'; // 초록색 (작업+방문) + strokeColor = 'rgb(34, 197, 94)'; + } else if (workerCount > 0) { + fillColor = 'rgba(59, 130, 246, 0.2)'; // 파란색 (작업만) + strokeColor = 'rgb(59, 130, 246)'; + } else if (visitorCount > 0) { + fillColor = 'rgba(168, 85, 247, 0.2)'; // 보라색 (방문만) + strokeColor = 'rgb(168, 85, 247)'; + } else { + fillColor = 'rgba(156, 163, 175, 0.2)'; // 회색 (없음) + strokeColor = 'rgb(156, 163, 175)'; + } + + ctx.fillStyle = fillColor; + ctx.strokeStyle = strokeColor; + ctx.lineWidth = isSelected ? 3 : 2; + + ctx.beginPath(); + ctx.rect(x1, y1, width, height); + ctx.fill(); + ctx.stroke(); + + // 작업장명 표시 + const centerX = x1 + width / 2; + const centerY = y1 + height / 2; + + ctx.fillStyle = '#374151'; + ctx.font = '12px sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillText(region.workplace_name, centerX, centerY); + + // 인원수 표시 + const total = workerCount + visitorCount; + if (total > 0) { + ctx.fillStyle = strokeColor; + ctx.font = 'bold 14px sans-serif'; + ctx.fillText(`(${total}명)`, centerX, centerY + 16); + } +} + +/** + * 지도 클릭 처리 + */ +function onMapClick(e) { + const rect = canvas.getBoundingClientRect(); + const x = e.clientX - rect.left; + const y = e.clientY - rect.top; + + // 클릭된 영역 찾기 + for (const region of mapRegions) { + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + if (x >= x1 && x <= x2 && y >= y1 && y <= y2) { + selectWorkplace(region); + return; + } + } +} + +/** + * 작업장 선택 + */ +function selectWorkplace(region) { + // 기타 위치 체크박스 해제 + document.getElementById('useCustomLocation').checked = false; + document.getElementById('customLocationInput').classList.remove('visible'); + + selectedWorkplaceId = region.workplace_id; + selectedWorkplaceName = region.workplace_name; + + // 해당 작업장의 TBM/출입신청 확인 + const workers = todayWorkers.filter(w => w.workplace_id === region.workplace_id); + const visitors = todayVisitors.filter(v => v.workplace_id === region.workplace_id); + + if (workers.length > 0 || visitors.length > 0) { + // 작업 선택 모달 표시 + showWorkSelectionModal(workers, visitors); + } else { + selectedTbmSessionId = null; + selectedVisitRequestId = null; + } + + updateLocationInfo(); + renderMap(); + updateStepStatus(); +} + +/** + * 작업 선택 모달 표시 + */ +function showWorkSelectionModal(workers, visitors) { + const modal = document.getElementById('workSelectionModal'); + const optionsList = document.getElementById('workOptionsList'); + + optionsList.innerHTML = ''; + + // TBM 작업 옵션 + workers.forEach(w => { + const option = document.createElement('div'); + option.className = 'work-option'; + option.innerHTML = ` +
TBM: ${w.task_name || '작업'}
+
${w.project_name || ''} - ${w.member_count || 0}명
+ `; + option.onclick = () => { + selectedTbmSessionId = w.session_id; + selectedVisitRequestId = null; + closeWorkModal(); + updateLocationInfo(); + }; + optionsList.appendChild(option); + }); + + // 출입신청 옵션 + visitors.forEach(v => { + const option = document.createElement('div'); + option.className = 'work-option'; + option.innerHTML = ` +
출입: ${v.visitor_company}
+
${v.purpose_name || '방문'} - ${v.visitor_count || 0}명
+ `; + option.onclick = () => { + selectedVisitRequestId = v.request_id; + selectedTbmSessionId = null; + closeWorkModal(); + updateLocationInfo(); + }; + optionsList.appendChild(option); + }); + + modal.classList.add('visible'); +} + +/** + * 작업 선택 모달 닫기 + */ +function closeWorkModal() { + document.getElementById('workSelectionModal').classList.remove('visible'); +} + +/** + * 선택된 위치 정보 업데이트 + */ +function updateLocationInfo() { + const infoBox = document.getElementById('selectedLocationInfo'); + const customLocation = document.getElementById('customLocation').value; + const useCustom = document.getElementById('useCustomLocation').checked; + + if (useCustom && customLocation) { + infoBox.classList.remove('empty'); + infoBox.innerHTML = `선택된 위치: ${customLocation}`; + } else if (selectedWorkplaceName) { + infoBox.classList.remove('empty'); + let html = `선택된 위치: ${selectedWorkplaceName}`; + + if (selectedTbmSessionId) { + const worker = todayWorkers.find(w => w.session_id === selectedTbmSessionId); + if (worker) { + html += `
연결 작업: ${worker.task_name} (TBM)`; + } + } else if (selectedVisitRequestId) { + const visitor = todayVisitors.find(v => v.request_id === selectedVisitRequestId); + if (visitor) { + html += `
연결 작업: ${visitor.visitor_company} (출입)`; + } + } + + infoBox.innerHTML = html; + } else { + infoBox.classList.add('empty'); + infoBox.textContent = '지도에서 작업장을 클릭하여 위치를 선택하세요'; + } +} + +/** + * 유형 선택 + */ +function onTypeSelect(type) { + selectedType = type; + selectedCategoryId = null; + selectedCategoryName = null; + selectedItemId = null; + + // 버튼 상태 업데이트 + document.querySelectorAll('.type-btn').forEach(btn => { + btn.classList.toggle('selected', btn.dataset.type === type); + }); + + // 카테고리 로드 + loadCategories(type); + updateStepStatus(); +} + +/** + * 카테고리 로드 + */ +async function loadCategories(type) { + try { + const response = await fetch(`${API_BASE}/work-issues/categories/type/${type}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) throw new Error('카테고리 조회 실패'); + + const data = await response.json(); + if (data.success && data.data) { + renderCategories(data.data); + } + } catch (error) { + console.error('카테고리 로드 실패:', error); + } +} + +/** + * 카테고리 렌더링 + */ +function renderCategories(categories) { + const container = document.getElementById('categoryContainer'); + const grid = document.getElementById('categoryGrid'); + + grid.innerHTML = ''; + + categories.forEach(cat => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'category-btn'; + btn.textContent = cat.category_name; + btn.onclick = () => onCategorySelect(cat); + grid.appendChild(btn); + }); + + container.style.display = 'block'; +} + +/** + * 카테고리 선택 + */ +function onCategorySelect(category) { + selectedCategoryId = category.category_id; + selectedCategoryName = category.category_name; + selectedItemId = null; + + // 버튼 상태 업데이트 + document.querySelectorAll('.category-btn').forEach(btn => { + btn.classList.toggle('selected', btn.textContent === category.category_name); + }); + + // 항목 로드 + loadItems(category.category_id); + updateStepStatus(); +} + +/** + * 항목 로드 + */ +async function loadItems(categoryId) { + try { + const response = await fetch(`${API_BASE}/work-issues/items/category/${categoryId}`, { + headers: { 'Authorization': `Bearer ${localStorage.getItem('token')}` } + }); + + if (!response.ok) throw new Error('항목 조회 실패'); + + const data = await response.json(); + if (data.success && data.data) { + renderItems(data.data); + } + } catch (error) { + console.error('항목 로드 실패:', error); + } +} + +/** + * 항목 렌더링 + */ +function renderItems(items) { + const grid = document.getElementById('itemGrid'); + grid.innerHTML = ''; + + if (items.length === 0) { + grid.innerHTML = '

등록된 항목이 없습니다

'; + return; + } + + items.forEach(item => { + const btn = document.createElement('button'); + btn.type = 'button'; + btn.className = 'item-btn'; + btn.textContent = item.item_name; + btn.dataset.severity = item.severity; + btn.onclick = () => onItemSelect(item, btn); + grid.appendChild(btn); + }); +} + +/** + * 항목 선택 + */ +function onItemSelect(item, btn) { + // 단일 선택 (기존 선택 해제) + document.querySelectorAll('.item-btn').forEach(b => b.classList.remove('selected')); + btn.classList.add('selected'); + + selectedItemId = item.item_id; + updateStepStatus(); +} + +/** + * 사진 선택 + */ +function onPhotoSelect(e) { + const file = e.target.files[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = (event) => { + photos[currentPhotoIndex] = event.target.result; + updatePhotoSlot(currentPhotoIndex); + }; + reader.readAsDataURL(file); + + // 입력 초기화 + e.target.value = ''; +} + +/** + * 사진 슬롯 업데이트 + */ +function updatePhotoSlot(index) { + const slot = document.querySelector(`.photo-slot[data-index="${index}"]`); + + if (photos[index]) { + slot.classList.add('has-photo'); + let img = slot.querySelector('img'); + if (!img) { + img = document.createElement('img'); + slot.insertBefore(img, slot.firstChild); + } + img.src = photos[index]; + } else { + slot.classList.remove('has-photo'); + const img = slot.querySelector('img'); + if (img) img.remove(); + } +} + +/** + * 사진 삭제 + */ +function removePhoto(index) { + photos[index] = null; + updatePhotoSlot(index); +} + +/** + * 단계 상태 업데이트 + */ +function updateStepStatus() { + const steps = document.querySelectorAll('.step'); + const customLocation = document.getElementById('customLocation').value; + const useCustom = document.getElementById('useCustomLocation').checked; + + // Step 1: 위치 + const step1Complete = (useCustom && customLocation) || selectedWorkplaceId; + steps[0].classList.toggle('completed', step1Complete); + steps[1].classList.toggle('active', step1Complete); + + // Step 2: 유형 + const step2Complete = selectedType && selectedCategoryId; + steps[1].classList.toggle('completed', step2Complete); + steps[2].classList.toggle('active', step2Complete); + + // Step 3: 항목 + const step3Complete = selectedItemId; + steps[2].classList.toggle('completed', step3Complete); + steps[3].classList.toggle('active', step3Complete); + + // 제출 버튼 활성화 + const submitBtn = document.getElementById('submitBtn'); + const hasPhoto = photos.some(p => p !== null); + submitBtn.disabled = !(step1Complete && step2Complete && hasPhoto); +} + +/** + * 신고 제출 + */ +async function submitReport() { + const submitBtn = document.getElementById('submitBtn'); + submitBtn.disabled = true; + submitBtn.textContent = '제출 중...'; + + try { + const useCustom = document.getElementById('useCustomLocation').checked; + const customLocation = document.getElementById('customLocation').value; + const additionalDescription = document.getElementById('additionalDescription').value; + + const requestBody = { + factory_category_id: useCustom ? null : selectedFactoryId, + workplace_id: useCustom ? null : selectedWorkplaceId, + custom_location: useCustom ? customLocation : null, + tbm_session_id: selectedTbmSessionId, + visit_request_id: selectedVisitRequestId, + issue_category_id: selectedCategoryId, + issue_item_id: selectedItemId, + additional_description: additionalDescription || null, + photos: photos.filter(p => p !== null) + }; + + const response = await fetch(`${API_BASE}/work-issues`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': `Bearer ${localStorage.getItem('token')}` + }, + body: JSON.stringify(requestBody) + }); + + const data = await response.json(); + + if (data.success) { + alert('문제 신고가 등록되었습니다.'); + window.location.href = '/pages/safety/issue-list.html'; + } else { + throw new Error(data.error || '신고 등록 실패'); + } + } catch (error) { + console.error('신고 제출 실패:', error); + alert('신고 등록에 실패했습니다: ' + error.message); + } finally { + submitBtn.disabled = false; + submitBtn.textContent = '신고 제출'; + } +} + +// 기타 위치 입력 시 위치 정보 업데이트 +document.addEventListener('DOMContentLoaded', () => { + const customLocationInput = document.getElementById('customLocation'); + if (customLocationInput) { + customLocationInput.addEventListener('input', () => { + updateLocationInfo(); + updateStepStatus(); + }); + } +}); diff --git a/deploy/tkfb-package/web-ui/js/work-management.js b/deploy/tkfb-package/web-ui/js/work-management.js new file mode 100644 index 0000000..35e6bf9 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-management.js @@ -0,0 +1,230 @@ +// 작업 관리 페이지 JavaScript + +// 전역 변수 +let statsData = { + projects: 0, + workers: 0, + tasks: 0, + codeTypes: 0 +}; + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', function() { + console.log('🔧 작업 관리 페이지 초기화 시작'); + + initializePage(); + loadStatistics(); +}); + +// 페이지 초기화 +function initializePage() { + // 시간 업데이트 시작 + updateCurrentTime(); + setInterval(updateCurrentTime, 1000); + + // 사용자 정보 업데이트 + updateUserInfo(); + + // 프로필 메뉴 토글 + setupProfileMenu(); + + // 로그아웃 버튼 + setupLogoutButton(); +} + +// 현재 시간 업데이트 (시 분 초 형식으로 고정) +function updateCurrentTime() { + const now = new Date(); + const hours = String(now.getHours()).padStart(2, '0'); + const minutes = String(now.getMinutes()).padStart(2, '0'); + const seconds = String(now.getSeconds()).padStart(2, '0'); + const timeString = `${hours}시 ${minutes}분 ${seconds}초`; + + const timeElement = document.getElementById('timeValue'); + if (timeElement) { + timeElement.textContent = timeString; + } +} + +// navbar/sidebar는 app-init.js에서 공통 처리 +function updateUserInfo() { + // app-init.js가 navbar 사용자 정보를 처리 +} + +// 프로필 메뉴 설정 +function setupProfileMenu() { + const userProfile = document.getElementById('userProfile'); + const profileMenu = document.getElementById('profileMenu'); + + if (userProfile && profileMenu) { + userProfile.addEventListener('click', function(e) { + e.stopPropagation(); + const isVisible = profileMenu.style.display === 'block'; + profileMenu.style.display = isVisible ? 'none' : 'block'; + }); + + // 외부 클릭 시 메뉴 닫기 + document.addEventListener('click', function() { + profileMenu.style.display = 'none'; + }); + } +} + +// 로그아웃 버튼 설정 +function setupLogoutButton() { + const logoutBtn = document.getElementById('logoutBtn'); + if (logoutBtn) { + logoutBtn.addEventListener('click', function() { + if (confirm('로그아웃 하시겠습니까?')) { + localStorage.removeItem('token'); + localStorage.removeItem('user'); + localStorage.removeItem('userInfo'); + window.location.href = '/index.html'; + } + }); + } +} + +// 통계 데이터 로드 +async function loadStatistics() { + try { + console.log('📊 통계 데이터 로딩 시작'); + + // 프로젝트 수 조회 + try { + const projectsResponse = await apiCall('/projects', 'GET'); + if (projectsResponse && Array.isArray(projectsResponse)) { + statsData.projects = projectsResponse.length; + updateStatDisplay('projectCount', statsData.projects); + } + } catch (error) { + console.warn('프로젝트 통계 로드 실패:', error); + updateStatDisplay('projectCount', '오류'); + } + + // 작업자 수 조회 + try { + const workersResponse = await apiCall('/workers', 'GET'); + if (workersResponse && Array.isArray(workersResponse)) { + const activeWorkers = workersResponse.filter(w => w.status === 'active'); + statsData.workers = activeWorkers.length; + updateStatDisplay('workerCount', statsData.workers); + } + } catch (error) { + console.warn('작업자 통계 로드 실패:', error); + updateStatDisplay('workerCount', '오류'); + } + + // 작업 유형 수 조회 + try { + const tasksResponse = await apiCall('/tasks', 'GET'); + if (tasksResponse && Array.isArray(tasksResponse)) { + const activeTasks = tasksResponse.filter(t => t.is_active); + statsData.tasks = activeTasks.length; + updateStatDisplay('taskCount', statsData.tasks); + } + } catch (error) { + console.warn('작업 유형 통계 로드 실패:', error); + updateStatDisplay('taskCount', '오류'); + } + + // 코드 타입 수 조회 (임시로 고정값) + statsData.codeTypes = 3; // ISSUE_TYPE, ERROR_TYPE, WORK_STATUS + updateStatDisplay('codeTypeCount', statsData.codeTypes); + + console.log('✅ 통계 데이터 로딩 완료:', statsData); + + } catch (error) { + console.error('통계 데이터 로딩 오류:', error); + } +} + +// 통계 표시 업데이트 +function updateStatDisplay(elementId, value) { + const element = document.getElementById(elementId); + if (element) { + element.textContent = value; + + // 애니메이션 효과 + element.style.transform = 'scale(1.1)'; + setTimeout(() => { + element.style.transform = 'scale(1)'; + }, 200); + } +} + +// 최근 활동 관련 함수들 제거됨 + +// 페이지 네비게이션 +function navigateToPage(url) { + console.log(`🔗 페이지 이동: ${url}`); + + // 로딩 효과 + const card = event.currentTarget; + const originalContent = card.innerHTML; + + card.style.opacity = '0.7'; + card.style.pointerEvents = 'none'; + + // 잠시 후 페이지 이동 + setTimeout(() => { + window.location.href = url; + }, 300); +} + +// 토스트 메시지 표시 +function showToast(message, type = 'info') { + // 기존 토스트 제거 + const existingToast = document.querySelector('.toast'); + if (existingToast) { + existingToast.remove(); + } + + // 새 토스트 생성 + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + + // 스타일 적용 + Object.assign(toast.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '12px 24px', + borderRadius: '8px', + color: 'white', + fontWeight: '500', + zIndex: '1000', + transform: 'translateX(100%)', + transition: 'transform 0.3s ease' + }); + + // 타입별 배경색 + const colors = { + success: '#10b981', + error: '#ef4444', + warning: '#f59e0b', + info: '#3b82f6' + }; + toast.style.backgroundColor = colors[type] || colors.info; + + document.body.appendChild(toast); + + // 애니메이션 + setTimeout(() => { + toast.style.transform = 'translateX(0)'; + }, 100); + + // 자동 제거 + setTimeout(() => { + toast.style.transform = 'translateX(100%)'; + setTimeout(() => { + if (toast.parentNode) { + toast.remove(); + } + }, 300); + }, 3000); +} + +// 전역 함수로 노출 +window.navigateToPage = navigateToPage; diff --git a/deploy/tkfb-package/web-ui/js/work-report-api.js b/deploy/tkfb-package/web-ui/js/work-report-api.js new file mode 100644 index 0000000..4adc18d --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-report-api.js @@ -0,0 +1,51 @@ +// /js/work-report-api.js +import { apiGet, apiPost } from './api-helper.js'; + +/** + * 작업 보고서 작성을 위해 필요한 초기 데이터(작업자, 프로젝트, 태스크)를 가져옵니다. + * Promise.all을 사용하여 병렬로 API를 호출합니다. + * @returns {Promise<{workers: Array, projects: Array, tasks: Array}>} + */ +export async function getInitialData() { + try { + const [allWorkers, projects, tasks] = await Promise.all([ + apiGet('/workers'), + apiGet('/projects'), + apiGet('/tasks') + ]); + + // 활성화된 작업자만 필터링 + const workers = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + + // 데이터 형식 검증 + if (!Array.isArray(workers) || !Array.isArray(projects) || !Array.isArray(tasks)) { + throw new Error('서버에서 받은 데이터 형식이 올바르지 않습니다.'); + } + + // 작업자 목록은 ID 기준으로 정렬 + workers.sort((a, b) => a.worker_id - b.worker_id); + + return { workers, projects, tasks }; + } catch (error) { + console.error('초기 데이터 로딩 중 오류 발생:', error); + // 에러를 다시 던져서 호출한 쪽에서 처리할 수 있도록 함 + throw error; + } +} + +/** + * 작성된 작업 보고서 데이터를 서버에 전송합니다. + * @param {Array} reportData - 전송할 작업 보고서 데이터 배열 + * @returns {Promise} - 서버의 응답 결과 + */ +export async function createWorkReport(reportData) { + try { + const result = await apiPost('/workreports', reportData); + return result; + } catch (error) { + console.error('작업 보고서 생성 요청 실패:', error); + throw error; + } +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/work-report-create.js b/deploy/tkfb-package/web-ui/js/work-report-create.js new file mode 100644 index 0000000..d61ed79 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-report-create.js @@ -0,0 +1,79 @@ +// /js/work-report-create.js +import { renderCalendar } from './calendar.js'; +import { getInitialData, createWorkReport } from './work-report-api.js'; +import { initializeReportTable, getReportData } from './work-report-ui.js'; + +// 전역 상태 변수 +let selectedDate = ''; + +/** + * 날짜가 선택되었을 때 실행되는 콜백 함수. + * 초기 데이터를 로드하고 테이블을 렌더링합니다. + * @param {string} date - 선택된 날짜 (YYYY-MM-DD 형식) + */ +async function onDateSelect(date) { + selectedDate = date; + const tableBody = document.getElementById('reportBody'); + tableBody.innerHTML = '데이터를 불러오는 중...'; + + try { + const initialData = await getInitialData(); + initializeReportTable(initialData); + } catch (error) { + alert('데이터를 불러오는 데 실패했습니다: ' + error.message); + tableBody.innerHTML = '오류 발생! 데이터를 불러올 수 없습니다.'; + } +} + +/** + * '전체 등록' 버튼 클릭 시 실행되는 이벤트 핸들러. + * 폼 데이터를 서버에 전송합니다. + */ +async function handleSubmit() { + if (!selectedDate) { + alert('먼저 달력에서 날짜를 선택해주세요.'); + return; + } + + const reportData = getReportData(); + if (!reportData) { + // getReportData 내부에서 이미 alert으로 사용자에게 알림 + return; + } + + // 각 항목에 선택된 날짜 추가 + const payload = reportData.map(item => ({ ...item, date: selectedDate })); + + const submitBtn = document.getElementById('submitBtn'); + submitBtn.disabled = true; + submitBtn.textContent = '등록 중...'; + + try { + const result = await createWorkReport(payload); + if (result.success) { + alert('✅ 작업 보고서가 성공적으로 등록되었습니다!'); + // 성공 후 폼을 다시 로드하거나, 다른 페이지로 이동 등의 로직 추가 가능 + onDateSelect(selectedDate); // 현재 날짜의 폼을 다시 로드 + } else { + throw new Error(result.error || '알 수 없는 오류로 등록에 실패했습니다.'); + } + } catch (error) { + alert('❌ 등록 실패: ' + error.message); + } finally { + submitBtn.disabled = false; + submitBtn.textContent = '전체 등록'; + } +} + +/** + * 페이지 초기화 함수 + */ +function initializePage() { + renderCalendar('calendar', onDateSelect); + + const submitBtn = document.getElementById('submitBtn'); + submitBtn.addEventListener('click', handleSubmit); +} + +// DOM이 로드되면 페이지 초기화를 시작합니다. +document.addEventListener('DOMContentLoaded', initializePage); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/work-report-manage.js b/deploy/tkfb-package/web-ui/js/work-report-manage.js new file mode 100644 index 0000000..a628878 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-report-manage.js @@ -0,0 +1,213 @@ +import { renderCalendar } from '/js/calendar.js'; +import { API, getAuthHeaders, ensureAuthenticated } from '/js/api-config.js'; + +// 인증 확인 +ensureAuthenticated(); + +const calendarEl = document.getElementById('calendar'); +const reportBody = document.getElementById('reportBody'); +let selectedDate = ''; + +// 캘린더 렌더링 +renderCalendar('calendar', (dateStr) => { + selectedDate = dateStr; + loadReports(); +}); + +// 보고서 로딩 +async function loadReports() { + if (!selectedDate) return; + reportBody.innerHTML = '불러오는 중...'; + + try { + const [wRes, pRes, rRes] = await Promise.all([ + fetch(`${API}/workers`, { headers: getAuthHeaders() }), + fetch(`${API}/projects/active/list`, { headers: getAuthHeaders() }), + fetch(`${API}/workreports?start=${selectedDate}&end=${selectedDate}`, { headers: getAuthHeaders() }) + ]); + + if (![wRes, pRes, rRes].every(res => res.ok)) throw new Error('불러오기 실패'); + + const [allWorkers, projects, reports] = await Promise.all([ + wRes.json(), pRes.json(), rRes.json() + ]); + + // 활성화된 작업자만 필터링 + const workers = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + + // 배열 체크 + if (!Array.isArray(workers) || !Array.isArray(projects) || !Array.isArray(reports)) { + throw new Error('잘못된 데이터 형식'); + } + + if (!reports.length) { + reportBody.innerHTML = '등록된 보고서가 없습니다.'; + return; + } + + const nameMap = Object.fromEntries(workers.map(w => [w.worker_id, w.worker_name])); + const projMap = Object.fromEntries(projects.map(p => [p.project_id, p.project_name])); + // const taskMap = Object.fromEntries(tasks.map(t => [t.task_id, `${t.category}:${t.subcategory}`])); // tasks 테이블 삭제됨 + + reportBody.innerHTML = ''; + reports.forEach((r, i) => { + const tr = document.createElement('tr'); + tr.innerHTML = ` + ${i + 1} + ${nameMap[r.worker_id] || r.worker_id} + + + + + + + + + `; + + // 저장 버튼 + tr.querySelector('.save-btn').onclick = async () => { + // 입력값 검증 + const projectId = tr.querySelector('[data-id="project"]').value; + const taskId = tr.querySelector('[data-id="task"]').value; + const overtimeHours = tr.querySelector('[data-id="overtime"]').value; + + if (!projectId || !taskId) { + alert('❌ 프로젝트와 작업을 선택해주세요.'); + return; + } + + // 날짜 형식 처리 - MySQL DATE 형식으로 변환 + const formatDate = (dateStr) => { + if (!dateStr) return selectedDate; + + // 이미 YYYY-MM-DD 형식인지 확인 + if (/^\d{4}-\d{2}-\d{2}$/.test(dateStr)) { + return dateStr; + } + + // ISO 형식이나 다른 형식을 YYYY-MM-DD로 변환 + const date = new Date(dateStr); + if (isNaN(date.getTime())) { + return selectedDate; // 잘못된 날짜면 선택된 날짜 사용 + } + + return date.toISOString().split('T')[0]; // YYYY-MM-DD 형식으로 변환 + }; + + const payload = { + date: formatDate(r.date), // 날짜 형식 변환 + worker_id: r.worker_id, // 기존 작업자 ID 유지 + project_id: Number(projectId), + task_id: Number(taskId), + overtime_hours: overtimeHours ? Number(overtimeHours) : null, + work_details: tr.querySelector('[data-id="work_details"]').value, + memo: tr.querySelector('[data-id="memo"]').value.trim() || null + }; + + // 저장 버튼 상태 변경 (로딩 중) + const saveBtn = tr.querySelector('.save-btn'); + const originalText = saveBtn.textContent; + const originalColor = saveBtn.style.backgroundColor; + + saveBtn.textContent = '저장 중...'; + saveBtn.style.backgroundColor = '#ffc107'; + saveBtn.disabled = true; + + try { + const res = await fetch(`${API}/workreports/${r.id}`, { + method: 'PUT', + headers: { + ...getAuthHeaders(), + 'Content-Type': 'application/json' + }, + body: JSON.stringify(payload) + }); + + const result = await res.json(); + + if (res.ok && result.success) { + // 성공 상태 표시 + saveBtn.textContent = '✅ 완료'; + saveBtn.style.backgroundColor = '#28a745'; + saveBtn.style.color = 'white'; + + setTimeout(() => { + saveBtn.textContent = originalText; + saveBtn.style.backgroundColor = originalColor; + saveBtn.style.color = ''; + saveBtn.disabled = false; + }, 2000); + + // alert 대신 조용한 알림 + console.log('저장 완료:', result); + } else { + console.error('저장 실패:', result); + alert(`❌ 저장 실패: ${result.error || result.message || '알 수 없는 오류'}`); + + // 실패 시 버튼 복원 + saveBtn.textContent = originalText; + saveBtn.style.backgroundColor = originalColor; + saveBtn.disabled = false; + } + } catch (err) { + console.error('저장 요청 에러:', err); + alert('❌ 저장 요청 실패: ' + err.message); + + // 에러 시 버튼 복원 + saveBtn.textContent = originalText; + saveBtn.style.backgroundColor = originalColor; + saveBtn.disabled = false; + } + }; + + // 삭제 버튼 + tr.querySelector('.delete-btn').onclick = async () => { + if (!confirm('정말 삭제하시겠습니까?')) return; + + try { + const res = await fetch(`${API}/workreports/${r.id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + + if (res.ok) { + tr.remove(); + // 행 번호 다시 매기기 + updateRowNumbers(); + alert('✅ 삭제 완료'); + } else { + const result = await res.json(); + alert(`❌ 삭제 실패: ${result.error || result.message || '알 수 없는 오류'}`); + } + } catch (err) { + console.error('삭제 요청 에러:', err); + alert('❌ 삭제 요청 실패: ' + err.message); + } + }; + + reportBody.appendChild(tr); + }); + } catch (err) { + console.error('데이터 로딩 에러:', err); + reportBody.innerHTML = '❌ 불러오기 실패: ' + err.message + ''; + } +} + +// 행 번호 다시 매기기 +function updateRowNumbers() { + reportBody.querySelectorAll('tr').forEach((tr, i) => { + const firstTd = tr.querySelector('td:first-child'); + if (firstTd) firstTd.textContent = i + 1; + }); +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/work-report-review.js b/deploy/tkfb-package/web-ui/js/work-report-review.js new file mode 100644 index 0000000..7bd3ff4 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-report-review.js @@ -0,0 +1,1061 @@ +// js/work-report-review.js - 휴가 연동 완전판 +import { API, getAuthHeaders } from '/js/api-config.js'; + +class WorkReportReviewManager { + constructor() { + this.workers = []; + this.projects = []; + this.workTypes = []; + this.workStatusTypes = []; + this.errorTypes = []; + this.reports = []; + this.filteredReports = []; + this.attendanceData = []; // 휴가 정보 + this.reviewedReports = new Set(); // 검토완료된 보고서 ID + this.selectedReport = null; + this.init(); + } + + async init() { + try { + // 필수 DOM 요소 확인 + const requiredElements = ['reportsTableBody', 'editPanelContent', 'totalReports']; + const missingElements = requiredElements.filter(id => !document.getElementById(id)); + + if (missingElements.length > 0) { + console.error('필수 DOM 요소가 없습니다:', missingElements); + return; + } + + this.showLoading(true); + await this.loadData(); + this.setupEventListeners(); + this.setDefaultDates(); + await this.loadReports(); + this.showLoading(false); + } catch (error) { + this.showMessage('데이터 로드 중 오류가 발생했습니다.', 'error'); + console.error('초기화 오류:', error); + this.showLoading(false); + } + } + + async loadData() { + try { + // 기본 데이터 로딩 + const [workersRes, projectsRes, workTypesRes, workStatusRes, errorTypesRes] = await Promise.all([ + fetch(`${API}/workers`, { headers: getAuthHeaders() }), + fetch(`${API}/projects/active/list`, { headers: getAuthHeaders() }), + fetch(`${API}/daily-work-reports/work-types`, { headers: getAuthHeaders() }), + fetch(`${API}/daily-work-reports/work-status-types`, { headers: getAuthHeaders() }), + fetch(`${API}/daily-work-reports/error-types`, { headers: getAuthHeaders() }) + ]); + + if (!workersRes.ok || !projectsRes.ok) { + throw new Error(`API 응답 오류: Workers(${workersRes.status}), Projects(${projectsRes.status})`); + } + + const allWorkers = await workersRes.json(); + + // 활성화된 작업자만 필터링 + this.workers = allWorkers.filter(worker => { + return worker.status === 'active' || worker.is_active === 1 || worker.is_active === true; + }); + + this.projects = await projectsRes.json(); + + // 새로운 API들 로드 (실패해도 기본값 사용) + try { + this.workTypes = workTypesRes.ok ? await workTypesRes.json() : [ + {id: 1, name: 'Base'}, {id: 2, name: 'Vessel'}, {id: 3, name: 'Piping'} + ]; + this.workStatusTypes = workStatusRes.ok ? await workStatusRes.json() : [ + {id: 1, name: '정규'}, {id: 2, name: '에러'} + ]; + this.errorTypes = errorTypesRes.ok ? await errorTypesRes.json() : [ + {id: 1, name: '설계미스'}, {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, {id: 4, name: '작업 불량'} + ]; + } catch (error) { + console.log('⚠️ 일부 API 사용 불가, 기본값 사용'); + } + + // 휴가 정보 로드 + await this.loadAttendanceData(); + + this.populateFilters(); + console.log('기본 데이터 로드 완료'); + } catch (error) { + console.error('기본 데이터 로드 오류:', error); + throw error; + } + } + + async loadAttendanceData() { + try { + const startDate = document.getElementById('startDate').value; + const endDate = document.getElementById('endDate').value; + + if (!startDate || !endDate) return; + + // 휴가 정보 API 호출 (예상 엔드포인트) + const response = await fetch(`${API}/attendance?start_date=${startDate}&end_date=${endDate}`, { + headers: getAuthHeaders() + }); + + if (response.ok) { + this.attendanceData = await response.json(); + console.log('휴가 정보 로드 완료:', this.attendanceData.length); + } else if (response.status === 404) { + console.log('⚠️ 휴가 API 없음, 더미 데이터 생성'); + this.attendanceData = this.generateDummyAttendance(); + } else { + throw new Error(`휴가 정보 로드 실패: ${response.status}`); + } + } catch (error) { + console.log('⚠️ 휴가 정보 로드 오류, 더미 데이터 사용:', error.message); + this.attendanceData = this.generateDummyAttendance(); + } + } + + generateDummyAttendance() { + const startDate = document.getElementById('startDate').value; + const endDate = document.getElementById('endDate').value; + if (!startDate || !endDate) return []; + + const dummyAttendance = []; + const start = new Date(startDate); + const end = new Date(endDate); + + // 날짜별로 작업자들의 출근 상태 생성 + for (let d = new Date(start); d <= end; d.setDate(d.getDate() + 1)) { + const dateStr = d.toISOString().split('T')[0]; + + this.workers.forEach(worker => { + const rand = Math.random(); + let attendanceType = 'NORMAL'; // 기본값 + + // 5% 확률로 휴가 + if (rand < 0.05) { + const types = ['HALF_DAY', 'HALF_HALF_DAY', 'EARLY_LEAVE']; + attendanceType = types[Math.floor(Math.random() * types.length)]; + } + + dummyAttendance.push({ + id: `att_${worker.worker_id}_${dateStr}`, + worker_id: worker.worker_id, + worker_name: worker.worker_name, + date: dateStr, + attendance_type: attendanceType, + expected_hours: this.getExpectedHours(attendanceType) + }); + }); + } + + return dummyAttendance; + } + + getExpectedHours(attendanceType) { + switch (attendanceType) { + case 'HALF_DAY': return 4; // 반차 + case 'HALF_HALF_DAY': return 6; // 반반차 + case 'EARLY_LEAVE': return 2; // 조퇴 + case 'NORMAL': + default: return 8; // 일반근무 + } + } + + getAttendanceTypeName(attendanceType) { + switch (attendanceType) { + case 'HALF_DAY': return '반차'; + case 'HALF_HALF_DAY': return '반반차'; + case 'EARLY_LEAVE': return '조퇴'; + case 'NORMAL': + default: return '정상근무'; + } + } + + async loadReports() { + try { + const startDate = document.getElementById('startDate').value; + const endDate = document.getElementById('endDate').value; + const workerId = document.getElementById('workerFilter').value; + const projectId = document.getElementById('projectFilter').value; + + // 필수 조건 체크 + if (!startDate || !endDate) { + this.showMessage('시작 날짜와 종료 날짜는 필수입니다.', 'error'); + return; + } + + // 휴가 정보 먼저 로드 + await this.loadAttendanceData(); + + let url = `${API}/daily-work-reports/search?`; + const params = new URLSearchParams(); + + if (startDate) params.append('start_date', startDate); + if (endDate) params.append('end_date', endDate); + if (workerId) params.append('worker_id', workerId); + if (projectId) params.append('project_id', projectId); + + // 페이지네이션 (일단 많이 가져오기) + params.append('page', '1'); + params.append('limit', '1000'); + + url += params.toString(); + + const response = await fetch(url, { headers: getAuthHeaders() }); + + if (response.status === 404 || response.status === 500) { + // API가 아직 준비되지 않은 경우 더미 데이터 사용 + this.reports = this.generateDummyData(); + console.log('⚠️ API 응답 오류, 더미 데이터 사용:', response.status); + if (response.status === 404) { + this.showMessage('⚠️ 검토 API가 준비되지 않아 더미 데이터를 표시합니다.', 'warning'); + } else { + this.showMessage('⚠️ 서버 오류로 더미 데이터를 표시합니다.', 'warning'); + } + } else if (response.ok) { + const result = await response.json(); + this.reports = result.reports || []; + console.log('검색 결과:', result.summary); + } else { + throw new Error(`보고서 로드 실패: ${response.status}`); + } + + // 근무시간 검증 추가 + this.validateWorkHours(); + + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + + } catch (error) { + console.log('⚠️ 네트워크 오류로 더미 데이터 사용:', error.message); + // 더미 데이터로 대체 + this.reports = this.generateDummyData(); + this.validateWorkHours(); + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + // 사용자에게는 부드러운 메시지 표시 + this.showMessage('💡 데모 데이터로 화면을 구성했습니다.', 'info'); + } + } + + validateWorkHours() { + // 각 보고서에 대해 근무시간 검증 + this.reports.forEach(report => { + const attendance = this.attendanceData.find(att => + att.worker_id === report.worker_id && att.date === report.report_date + ); + + if (attendance) { + const expectedHours = attendance.expected_hours; + const actualHours = this.getWorkerDailyHours(report.worker_id, report.report_date); + + report.expected_hours = expectedHours; + report.actual_hours = actualHours; + report.attendance_type = attendance.attendance_type; + report.hours_status = this.getHoursStatus(actualHours, expectedHours); + report.is_reviewed = this.reviewedReports.has(`${report.worker_id}_${report.report_date}`); + } else { + // 휴가 정보가 없으면 기본 8시간으로 가정 + const actualHours = this.getWorkerDailyHours(report.worker_id, report.report_date); + report.expected_hours = 8; + report.actual_hours = actualHours; + report.attendance_type = 'NORMAL'; + report.hours_status = this.getHoursStatus(actualHours, 8); + report.is_reviewed = this.reviewedReports.has(`${report.worker_id}_${report.report_date}`); + } + }); + } + + getWorkerDailyHours(workerId, date) { + // 해당 작업자의 특정 날짜 총 작업시간 계산 + return this.reports + .filter(r => r.worker_id === workerId && r.report_date === date) + .reduce((sum, r) => sum + (r.work_hours || 0), 0); + } + + getHoursStatus(actualHours, expectedHours) { + const tolerance = 0.5; // 30분 허용 오차 + + if (Math.abs(actualHours - expectedHours) <= tolerance) { + return 'NORMAL'; // 정상 + } else if (actualHours < expectedHours) { + return 'UNDER'; // 부족 + } else { + return 'OVER'; // 초과 + } + } + + generateDummyData() { + const today = new Date(); + const dummyData = []; + + // 더미 데이터 생성 (최근 7일) + for (let i = 0; i < 7; i++) { + const date = new Date(today); + date.setDate(date.getDate() - i); + const dateStr = date.toISOString().split('T')[0]; + + this.workers.forEach(worker => { + // 80% 확률로 보고서 생성 + if (Math.random() > 0.2) { + const numEntries = Math.floor(Math.random() * 3) + 1; // 1-3개 작업 + + for (let j = 0; j < numEntries; j++) { + const workStatus = Math.random() > 0.9 ? 2 : 1; // 10% 확률로 에러 + const workHours = Math.random() > 0.95 ? + (Math.random() * 4 + 10) : // 5% 확률로 이상 시간 (10-14시간) + (Math.random() * 6 + 2); // 정상 시간 (2-8시간) + + dummyData.push({ + id: 1000000 + i * 100 + worker.worker_id * 10 + j, // 고유 정수 ID + report_date: dateStr, + worker_id: worker.worker_id, + worker_name: worker.worker_name, + project_id: this.projects[Math.floor(Math.random() * this.projects.length)]?.project_id || 1, + project_name: this.projects[Math.floor(Math.random() * this.projects.length)]?.project_name || 'Unknown', + work_type_id: Math.floor(Math.random() * 3) + 1, + work_type_name: this.workTypes[Math.floor(Math.random() * 3)]?.name || 'Base', + work_status_id: workStatus, + work_status_name: workStatus === 2 ? '에러' : '정규', + error_type_id: workStatus === 2 ? Math.floor(Math.random() * 4) + 1 : null, + error_type_name: workStatus === 2 ? this.errorTypes[Math.floor(Math.random() * 4)]?.name : null, + work_hours: Math.round(workHours * 2) / 2, // 0.5시간 단위 + created_at: `${dateStr}T${String(Math.floor(Math.random() * 24)).padStart(2, '0')}:${String(Math.floor(Math.random() * 60)).padStart(2, '0')}:00` + }); + } + } + }); + } + + return dummyData.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); + } + + populateFilters() { + // 작업자 필터 + const workerSelect = document.getElementById('workerFilter'); + if (workerSelect) { + workerSelect.innerHTML = ''; + this.workers.forEach(worker => { + workerSelect.innerHTML += ``; + }); + } + + // 프로젝트 필터 + const projectSelect = document.getElementById('projectFilter'); + if (projectSelect) { + projectSelect.innerHTML = ''; + this.projects.forEach(project => { + projectSelect.innerHTML += ``; + }); + } + } + + setDefaultDates() { + const today = new Date(); + const weekAgo = new Date(today); + weekAgo.setDate(weekAgo.getDate() - 7); + + const startDateInput = document.getElementById('startDate'); + const endDateInput = document.getElementById('endDate'); + + if (startDateInput) startDateInput.value = weekAgo.toISOString().split('T')[0]; + if (endDateInput) endDateInput.value = today.toISOString().split('T')[0]; + } + + updateDashboard() { + // 날짜별, 작업자별로 그룹화하여 계산 + const groupedReports = this.groupReportsByWorkerAndDate(); + const groups = Object.values(groupedReports); + + const total = groups.length; + const errors = groups.filter(group => group.some(r => r.work_status_id === 2)).length; + const warnings = groups.filter(group => { + const firstReport = group[0]; + return firstReport.hours_status === 'UNDER' || firstReport.hours_status === 'OVER'; + }).length; + const reviewed = groups.filter(group => group[0].is_reviewed).length; + + document.getElementById('totalReports').textContent = total; + document.getElementById('errorReports').textContent = errors; + document.getElementById('warningReports').textContent = warnings; + document.getElementById('missingReports').textContent = total - reviewed; // 미검토 건수 + } + + updateAlertsSection() { + const alertsList = document.getElementById('alertsList'); + if (!alertsList) return; + + const alerts = []; + const groupedReports = this.groupReportsByWorkerAndDate(); + + // 각 그룹별로 알림 체크 + Object.values(groupedReports).forEach(group => { + const firstReport = group[0]; + const hasError = group.some(r => r.work_status_id === 2); + const workerName = firstReport.worker_name; + const date = firstReport.report_date; + + // 에러 발생 건 + if (hasError) { + const errorReports = group.filter(r => r.work_status_id === 2); + alerts.push({ + type: 'error', + text: `${workerName} (${date}) - 에러 ${errorReports.length}건`, + time: this.formatDate(date), + priority: 1 + }); + } + + // 시간 불일치 + if (firstReport.hours_status === 'UNDER' || firstReport.hours_status === 'OVER') { + const statusText = firstReport.hours_status === 'UNDER' ? '부족' : '초과'; + alerts.push({ + type: 'warning', + text: `${workerName} (${date}) - 시간 ${statusText} (${firstReport.actual_hours}h/${firstReport.expected_hours}h)`, + time: this.formatDate(date), + priority: 2 + }); + } + + // 검토 대기 (정상이지만 아직 검토되지 않음) + if (!firstReport.is_reviewed && firstReport.hours_status === 'NORMAL' && !hasError) { + alerts.push({ + type: 'pending', + text: `${workerName} (${date}) - 검토 대기`, + time: this.formatDate(date), + priority: 3 + }); + } + }); + + // 우선순위별 정렬 + alerts.sort((a, b) => a.priority - b.priority); + + // 알림 표시 + if (alerts.length === 0) { + alertsList.innerHTML = ` +
+
+ ✅ 모든 항목이 정상이거나 검토 완료되었습니다 +
+
+ `; + } else { + alertsList.innerHTML = alerts.map(alert => ` +
+
+
+ ${this.getAlertTypeLabel(alert.type)} + ${alert.text} +
+
${alert.time}
+
+
+ `).join(''); + } + } + + getAlertTypeLabel(type) { + switch (type) { + case 'error': return '에러'; + case 'warning': return '주의'; + case 'pending': return '대기'; + case 'missing': return '미입력'; + default: return '알림'; + } + } + + updateTable() { + const tbody = document.getElementById('reportsTableBody'); + if (!tbody) return; + + if (this.filteredReports.length === 0) { + tbody.innerHTML = ` + + + 조회된 데이터가 없습니다 + + + `; + return; + } + + // 날짜별, 작업자별로 그룹화 + const groupedReports = this.groupReportsByWorkerAndDate(); + + tbody.innerHTML = Object.entries(groupedReports).map(([key, group]) => { + const [workerId, date] = key.split('_'); + const firstReport = group[0]; + const totalHours = group.reduce((sum, r) => sum + (r.work_hours || 0), 0); + const hasError = group.some(r => r.work_status_id === 2); + const rowClass = this.getGroupRowClass(firstReport, hasError); + + return ` + + ${this.formatDate(firstReport.report_date)} + ${firstReport.worker_name} + + + ${this.getAttendanceTypeName(firstReport.attendance_type)} + + + ${firstReport.expected_hours}h + ${totalHours}h + + + ${this.getHoursStatusName(firstReport.hours_status)} + + + ${group.map(r => r.project_name).join(', ')} + ${group.map(r => r.work_type_name).join(', ')} + + ${hasError ? '에러 포함' : '정상'} + + + ${firstReport.is_reviewed ? + '검토완료' : + '검토대기' + } + + + ${!firstReport.is_reviewed && firstReport.hours_status === 'NORMAL' && !hasError ? + `` : + '-' + } + + + `; + }).join(''); + } + + groupReportsByWorkerAndDate() { + const grouped = {}; + + this.filteredReports.forEach(report => { + const key = `${report.worker_id}_${report.report_date}`; + if (!grouped[key]) { + grouped[key] = []; + } + grouped[key].push(report); + }); + + return grouped; + } + + getGroupRowClass(report, hasError) { + if (report.is_reviewed) return 'row-reviewed'; + if (hasError || report.work_status_id === 2) return 'row-error'; + if (report.hours_status === 'UNDER' || report.hours_status === 'OVER') return 'row-warning'; + return 'row-normal'; + } + + getHoursStatusName(status) { + switch (status) { + case 'NORMAL': return '정상'; + case 'UNDER': return '부족'; + case 'OVER': return '초과'; + default: return '확인필요'; + } + } + + selectWorkerDate(workerId, date) { + // 해당 작업자의 특정 날짜 보고서들을 선택 + const reports = this.filteredReports.filter(r => + r.worker_id == workerId && r.report_date === date + ); + + if (reports.length > 0) { + this.selectedReport = reports[0]; // 첫 번째 보고서를 대표로 선택 + this.selectedReport.allReports = reports; // 전체 보고서 목록 추가 + this.updateEditPanel(); + + // 테이블에서 선택 표시 + document.querySelectorAll('.data-table tr.selected').forEach(tr => { + tr.classList.remove('selected'); + }); + + // 해당 행 선택 표시 + const rows = document.querySelectorAll('.data-table tr'); + rows.forEach(row => { + if (row.onclick && row.onclick.toString().includes(`'${workerId}', '${date}'`)) { + row.classList.add('selected'); + } + }); + } + } + + async markAsReviewed(workerId, date) { + try { + const key = `${workerId}_${date}`; + + // API 호출 (준비되면) + // const response = await fetch(`${API}/daily-work-reports/review`, { + // method: 'POST', + // headers: { ...getAuthHeaders(), 'Content-Type': 'application/json' }, + // body: JSON.stringify({ worker_id: workerId, report_date: date, reviewed: true }) + // }); + + // 현재는 로컬 상태만 업데이트 + this.reviewedReports.add(key); + + // 해당 보고서들의 검토 상태 업데이트 + this.reports.forEach(report => { + if (report.worker_id == workerId && report.report_date === date) { + report.is_reviewed = true; + } + }); + + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + + this.showMessage(`✅ ${this.getWorkerName(workerId)}의 ${date} 보고서가 검토완료 처리되었습니다.`, 'success'); + + } catch (error) { + this.showMessage('❌ 검토완료 처리 중 오류가 발생했습니다.', 'error'); + console.error('검토완료 오류:', error); + } + } + + getWorkerName(workerId) { + const worker = this.workers.find(w => w.worker_id == workerId); + return worker ? worker.worker_name : `작업자${workerId}`; + } + + updateEditPanel() { + const panelContent = document.getElementById('editPanelContent'); + if (!panelContent || !this.selectedReport) return; + + const report = this.selectedReport; + const allReports = report.allReports || [report]; + + panelContent.innerHTML = ` +
+

${report.worker_name} - ${this.formatDate(report.report_date)}

+
+
+ 출근형태:
+ + ${this.getAttendanceTypeName(report.attendance_type)} + +
+
+ 시간상태:
+ + ${this.getHoursStatusName(report.hours_status)} + +
+
기대시간: ${report.expected_hours}시간
+
실제시간: ${report.actual_hours}시간
+
+
+ +
+
작업 상세 (${allReports.length}건)
+ ${allReports.map((r, index) => ` +
+
+
프로젝트: ${r.project_name}
+
작업유형: ${r.work_type_name}
+
작업시간: ${r.work_hours}시간
+
상태: ${r.work_status_name}
+ ${r.error_type_name ? `
에러유형: ${r.error_type_name}
` : ''} +
+ +
+ `).join('')} +
+ +
+ ${!report.is_reviewed && report.hours_status === 'NORMAL' && !allReports.some(r => r.work_status_id === 2) ? + `` : '' + } + +
+ `; + } + + editSingleReport(reportId) { + // 개별 보고서 수정을 위해 기존 로직 사용 + this.selectedReport = this.filteredReports.find(r => r.id == reportId); + if (this.selectedReport) { + // 기존 수정 폼 표시 + this.showEditForm(); + } + } + + showEditForm() { + const panelContent = document.getElementById('editPanelContent'); + if (!panelContent || !this.selectedReport) return; + + const report = this.selectedReport; + + panelContent.innerHTML = ` +
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + + +
+ `; + + // 업무 상태 변경 시 에러 유형 표시/숨김 + const workStatusSelect = document.getElementById('editWorkStatus'); + const errorTypeGroup = document.getElementById('editErrorTypeGroup'); + + if (workStatusSelect && errorTypeGroup) { + workStatusSelect.addEventListener('change', (e) => { + if (e.target.value === '2') { + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + document.getElementById('editErrorType').value = ''; + } + }); + } + } + + async saveReport() { + if (!this.selectedReport) return; + + try { + this.showLoading(true); + + const formData = { + report_date: document.getElementById('editReportDate').value, + project_id: parseInt(document.getElementById('editProject').value), + work_type_id: parseInt(document.getElementById('editWorkType').value), + work_status_id: parseInt(document.getElementById('editWorkStatus').value), + error_type_id: document.getElementById('editErrorType').value ? + parseInt(document.getElementById('editErrorType').value) : null, + work_hours: parseFloat(document.getElementById('editWorkHours').value) + }; + + const response = await fetch(`${API}/daily-work-reports/${this.selectedReport.id}`, { + method: 'PUT', + headers: { + ...getAuthHeaders(), + 'Content-Type': 'application/json' + }, + body: JSON.stringify(formData) + }); + + if (response.status === 404 || response.status === 500) { + if (response.status === 404) { + this.showMessage('⚠️ 수정 API가 아직 준비되지 않았습니다.', 'warning'); + } else { + this.showMessage('⚠️ 서버 오류가 발생했습니다. 더미 데이터를 수정합니다.', 'warning'); + } + // 더미 데이터 업데이트 + this.updateDummyData(formData); + } else if (response.ok) { + this.showMessage('✅ 성공적으로 수정되었습니다.', 'success'); + await this.loadReports(); + } else { + const result = await response.json(); + throw new Error(result.error || '수정 중 오류가 발생했습니다.'); + } + + this.clearSelection(); + + } catch (error) { + this.showMessage(`❌ ${error.message}`, 'error'); + console.error('수정 오류:', error); + } finally { + this.showLoading(false); + } + } + + updateDummyData(formData) { + // 더미 데이터에서 수정 + const reportIndex = this.reports.findIndex(r => r.id === this.selectedReport.id); + if (reportIndex !== -1) { + this.reports[reportIndex] = { + ...this.reports[reportIndex], + ...formData, + project_name: this.projects.find(p => p.project_id === formData.project_id)?.project_name, + work_type_name: this.workTypes.find(wt => wt.id === formData.work_type_id)?.name, + work_status_name: this.workStatusTypes.find(ws => ws.id === formData.work_status_id)?.name, + error_type_name: formData.error_type_id ? + this.errorTypes.find(et => et.id === formData.error_type_id)?.name : null + }; + + // 시간 검증 다시 실행 + this.validateWorkHours(); + + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + } + } + + async deleteReport() { + if (!this.selectedReport) return; + + if (!confirm('정말로 이 보고서를 삭제하시겠습니까?')) return; + + try { + this.showLoading(true); + + const response = await fetch(`${API}/daily-work-reports/${this.selectedReport.id}`, { + method: 'DELETE', + headers: getAuthHeaders() + }); + + if (response.status === 404 || response.status === 500) { + if (response.status === 404) { + this.showMessage('⚠️ 삭제 API가 아직 준비되지 않았습니다.', 'warning'); + } else { + this.showMessage('⚠️ 서버 오류가 발생했습니다. 더미 데이터를 삭제합니다.', 'warning'); + } + // 더미 데이터에서 삭제 + this.reports = this.reports.filter(r => r.id !== this.selectedReport.id); + this.filteredReports = [...this.reports]; + this.updateDashboard(); + this.updateAlertsSection(); + this.updateTable(); + } else if (response.ok) { + this.showMessage('✅ 성공적으로 삭제되었습니다.', 'success'); + await this.loadReports(); + } else { + const result = await response.json(); + throw new Error(result.error || '삭제 중 오류가 발생했습니다.'); + } + + this.clearSelection(); + + } catch (error) { + this.showMessage(`❌ ${error.message}`, 'error'); + console.error('삭제 오류:', error); + } finally { + this.showLoading(false); + } + } + + clearSelection() { + this.selectedReport = null; + + // 테이블 선택 해제 + document.querySelectorAll('.data-table tr.selected').forEach(tr => { + tr.classList.remove('selected'); + }); + + // 패널 초기화 + const panelContent = document.getElementById('editPanelContent'); + if (panelContent) { + panelContent.innerHTML = ` +
+
📝
+
수정할 항목을 선택해주세요
+
+ `; + } + } + + setupEventListeners() { + // 필터 적용 버튼 + const applyFilterBtn = document.getElementById('applyFilter'); + if (applyFilterBtn) { + applyFilterBtn.addEventListener('click', () => { + this.loadReports(); + }); + } + + // 새로고침 버튼 + const refreshBtn = document.getElementById('refreshBtn'); + if (refreshBtn) { + refreshBtn.addEventListener('click', () => { + this.loadReports(); + }); + } + + // 내보내기 버튼 + const exportBtn = document.getElementById('exportBtn'); + if (exportBtn) { + exportBtn.addEventListener('click', () => { + this.exportData(); + }); + } + + // 엔터키로 필터 적용 + ['startDate', 'endDate', 'workerFilter', 'projectFilter'].forEach(id => { + const element = document.getElementById(id); + if (element) { + element.addEventListener('change', () => { + this.loadReports(); + }); + } + }); + } + + exportData() { + if (this.filteredReports.length === 0) { + this.showMessage('내보낼 데이터가 없습니다.', 'warning'); + return; + } + + // CSV 생성 + const headers = ['날짜', '작업자', '출근형태', '기대시간', '실제시간', '시간상태', '프로젝트', '작업유형', '상태', '검토상태']; + + // 그룹화된 데이터로 CSV 생성 + const groupedReports = this.groupReportsByWorkerAndDate(); + const csvContent = [ + headers.join(','), + ...Object.entries(groupedReports).map(([key, group]) => { + const firstReport = group[0]; + const totalHours = group.reduce((sum, r) => sum + (r.work_hours || 0), 0); + const hasError = group.some(r => r.work_status_id === 2); + + return [ + firstReport.report_date, + firstReport.worker_name, + this.getAttendanceTypeName(firstReport.attendance_type), + firstReport.expected_hours, + totalHours, + this.getHoursStatusName(firstReport.hours_status), + group.map(r => r.project_name).join('; '), + group.map(r => r.work_type_name).join('; '), + hasError ? '에러 포함' : '정상', + firstReport.is_reviewed ? '검토완료' : '검토대기' + ].join(','); + }) + ].join('\n'); + + // 파일 다운로드 + const blob = new Blob(['\uFEFF' + csvContent], { type: 'text/csv;charset=utf-8;' }); + const link = document.createElement('a'); + link.href = URL.createObjectURL(blob); + link.download = `작업보고서_검토_${new Date().toISOString().split('T')[0]}.csv`; + link.click(); + + this.showMessage('✅ 데이터가 내보내졌습니다.', 'success'); + } + + formatDate(dateStr) { + return new Date(dateStr).toLocaleDateString('ko-KR'); + } + + formatTime(dateTimeStr) { + return new Date(dateTimeStr).toLocaleString('ko-KR', { + month: 'short', + day: 'numeric', + hour: '2-digit', + minute: '2-digit' + }); + } + + showLoading(show) { + const overlay = document.getElementById('loadingOverlay'); + if (overlay) { + overlay.style.display = show ? 'flex' : 'none'; + } + } + + showMessage(message, type) { + const container = document.getElementById('message-container'); + if (container) { + container.innerHTML = `
${message}
`; + + if (type === 'success') { + setTimeout(() => { + container.innerHTML = ''; + }, 5000); + } + } + } +} + +// 전역 인스턴스 생성 +let workReportReview; + +// DOM 준비 후 초기화 +document.addEventListener('DOMContentLoaded', () => { + workReportReview = new WorkReportReviewManager(); + // 전역 접근을 위해 window에 할당 + window.workReportReview = workReportReview; +}); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/work-report-ui.js b/deploy/tkfb-package/web-ui/js/work-report-ui.js new file mode 100644 index 0000000..bdc6042 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-report-ui.js @@ -0,0 +1,141 @@ +// /js/work-report-ui.js + +const DEFAULT_PROJECT_ID = '13'; // 나중에는 API나 설정에서 받아오는 것이 좋음 +const DEFAULT_TASK_ID = '15'; + +/** + * 주어진 데이터를 바탕으로 + ${worker.worker_name} + + + + + + + + + + + + `; + + // 이벤트 리스너 설정 + const workTypeSelect = tr.querySelector('[name="work_type"]'); + const projectSelect = tr.querySelector('[name="project_id"]'); + const taskSelect = tr.querySelector('[name="task_id"]'); + + workTypeSelect.addEventListener('change', () => { + const isDisabled = ['연차', '휴무', '유급'].includes(workTypeSelect.value); + projectSelect.disabled = isDisabled; + taskSelect.disabled = isDisabled; + if (isDisabled) { + projectSelect.value = DEFAULT_PROJECT_ID; + taskSelect.value = DEFAULT_TASK_ID; + } + }); + + tr.querySelector('.remove-btn').addEventListener('click', () => { + tr.remove(); + updateRowNumbers(tr.parentElement); + }); + + return tr; +} + +/** + * 작업 보고서 테이블을 초기화하고 데이터를 채웁니다. + * @param {{workers: Array, projects: Array, tasks: Array}} initialData - 초기 데이터 + */ +export function initializeReportTable(initialData) { + const tableBody = document.getElementById('reportBody'); + if (!tableBody) return; + + tableBody.innerHTML = ''; // 기존 내용 초기화 + const { workers, projects, tasks } = initialData; + + if (!workers || workers.length === 0) { + tableBody.innerHTML = '등록할 작업자 정보가 없습니다.'; + return; + } + + workers.forEach((worker, index) => { + const row = createReportRow(worker, projects, tasks, index); + tableBody.appendChild(row); + }); +} + +/** + * 테이블에서 폼 데이터를 추출하여 배열로 반환합니다. + * @returns {Array|null} - 추출된 데이터 배열 또는 유효성 검사 실패 시 null + */ +export function getReportData() { + const tableBody = document.getElementById('reportBody'); + const rows = tableBody.querySelectorAll('tr'); + + if (rows.length === 0 || (rows.length === 1 && rows[0].cells.length < 2)) { + alert('등록할 내용이 없습니다.'); + return null; + } + + const reportData = []; + const workerIds = new Set(); + + for (const tr of rows) { + const workerId = tr.querySelector('[name="worker_id"]').value; + if (workerIds.has(workerId)) { + alert(`오류: 작업자 '${tr.cells[1].textContent.trim()}'가 중복 등록되었습니다.`); + return null; + } + workerIds.add(workerId); + + reportData.push({ + worker_id: workerId, + project_id: tr.querySelector('[name="project_id"]').value, + task_id: tr.querySelector('[name="task_id"]').value, + overtime_hours: tr.querySelector('[name="overtime"]').value || 0, + work_details: tr.querySelector('[name="work_type"]').value, + memo: tr.querySelector('[name="memo"]').value + }); + } + + return reportData; +} \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/work-review.js b/deploy/tkfb-package/web-ui/js/work-review.js new file mode 100644 index 0000000..22f1577 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/work-review.js @@ -0,0 +1,776 @@ +// work-review.js - 통합 API 설정 적용 버전 + +// ================================================================= +// 🌐 통합 API 설정 import +// ================================================================= +import { API, getAuthHeaders, apiCall } from '/js/api-config.js'; + +// 전역 변수 +let currentDate = new Date(); +let selectedDate = null; +let selectedDateData = null; +let basicData = { + workTypes: [], + workStatusTypes: [], + errorTypes: [], + projects: [] +}; + +// 현재 사용자 정보 가져오기 +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + return null; +} + +// 메시지 표시 +function showMessage(message, type = 'info') { + const container = document.getElementById('message-container'); + container.innerHTML = `
${message}
`; + + if (type !== 'loading') { + setTimeout(() => { + container.innerHTML = ''; + }, 5000); + } +} + +// 날짜 포맷팅 +function formatDate(date) { + const year = date.getFullYear(); + const month = String(date.getMonth() + 1).padStart(2, '0'); + const day = String(date.getDate()).padStart(2, '0'); + return `${year}-${month}-${day}`; +} + +// 월 표시 업데이트 +function updateMonthDisplay() { + const monthElement = document.getElementById('currentMonth'); + const year = currentDate.getFullYear(); + const month = currentDate.getMonth() + 1; + monthElement.textContent = `${year}년 ${month}월`; +} + +// 근무 유형 분류 +function classifyWorkType(totalHours) { + if (totalHours === 0) return { type: 'vacation', label: '휴무' }; + if (totalHours === 2) return { type: 'vacation', label: '조퇴' }; + if (totalHours === 4) return { type: 'vacation', label: '반차' }; + if (totalHours === 6) return { type: 'vacation', label: '반반차' }; + if (totalHours === 8) return { type: 'normal-work', label: '정시근무' }; + if (totalHours > 8) return { type: 'overtime', label: '잔업' }; + return { type: 'vacation', label: '기타' }; +} + +// 캘린더 렌더링 (데이터 로드 없이) +function renderCalendar() { + const calendar = document.getElementById('calendar'); + + // 기존 날짜 셀들 제거 (헤더는 유지) + const dayHeaders = calendar.querySelectorAll('.day-header'); + calendar.innerHTML = ''; + dayHeaders.forEach(header => calendar.appendChild(header)); + + const year = currentDate.getFullYear(); + const month = currentDate.getMonth(); + + // 해당 월의 첫째 날과 마지막 날 + const firstDay = new Date(year, month, 1); + const lastDay = new Date(year, month + 1, 0); + + // 첫째 주의 시작 (일요일부터 시작) + const startDate = new Date(firstDay); + startDate.setDate(startDate.getDate() - firstDay.getDay()); + + // 마지막 주의 끝 + const endDate = new Date(lastDay); + endDate.setDate(endDate.getDate() + (6 - lastDay.getDay())); + + // 오늘 날짜 + const today = new Date(); + const todayStr = formatDate(today); + + // 날짜 셀 생성 + let currentCalendarDate = new Date(startDate); + + while (currentCalendarDate <= endDate) { + const dateStr = formatDate(currentCalendarDate); + const isCurrentMonth = currentCalendarDate.getMonth() === month; + const isToday = dateStr === todayStr; + const isSelected = selectedDate === dateStr; + + const dayCell = document.createElement('div'); + dayCell.className = 'day-cell'; + + if (!isCurrentMonth) { + dayCell.classList.add('other-month'); + } + + if (isToday) { + dayCell.classList.add('today'); + } + + if (isSelected) { + dayCell.classList.add('selected'); + } + + // 날짜 번호 + const dayNumber = document.createElement('div'); + dayNumber.className = 'day-number'; + dayNumber.textContent = currentCalendarDate.getDate(); + dayCell.appendChild(dayNumber); + + // 클릭 이벤트 - 현재 월의 날짜만 클릭 가능 + if (isCurrentMonth) { + dayCell.style.cursor = 'pointer'; + dayCell.addEventListener('click', () => { + selectedDate = dateStr; + loadDayData(dateStr); + renderCalendar(); // 선택 상태 업데이트를 위해 재렌더링 + }); + } + + calendar.appendChild(dayCell); + currentCalendarDate.setDate(currentCalendarDate.getDate() + 1); + } +} + +// 특정 날짜 데이터 로드 (통합 API 사용) +async function loadDayData(dateStr) { + try { + showMessage(`${dateStr} 데이터를 불러오는 중... (통합 API)`, 'loading'); + + const data = await apiCall(`${API}/daily-work-reports?date=${dateStr}`); + const dataArray = Array.isArray(data) ? data : (data.data || []); + + // 데이터 처리 + processDayData(dateStr, dataArray); + renderDayInfo(); + + document.getElementById('message-container').innerHTML = ''; + + } catch (error) { + console.error('날짜 데이터 로드 실패:', error); + showMessage('데이터를 불러올 수 없습니다: ' + error.message, 'error'); + selectedDateData = null; + renderDayInfo(); + } +} + +// 일별 데이터 처리 +function processDayData(dateStr, works) { + const dayData = { + date: dateStr, + totalHours: 0, + workers: new Set(), + reviewed: Math.random() > 0.3, // 임시: 70% 확률로 검토 완료 + details: works + }; + + works.forEach(work => { + dayData.totalHours += parseFloat(work.work_hours || 0); + dayData.workers.add(work.worker_name || work.worker_id); + }); + + const workType = classifyWorkType(dayData.totalHours); + dayData.workType = workType.type; + dayData.workLabel = workType.label; + + selectedDateData = dayData; +} + +// 선택된 날짜 정보 렌더링 +function renderDayInfo() { + const dayInfoContainer = document.getElementById('day-info-container'); + + if (!selectedDate) { + dayInfoContainer.innerHTML = ` +
+

📅 날짜를 선택하세요

+

캘린더에서 날짜를 클릭하면 해당 날짜의 작업 정보를 확인할 수 있습니다.

+
+ `; + return; + } + + if (!selectedDateData) { + dayInfoContainer.innerHTML = ` +
+

📅 ${selectedDate}

+

해당 날짜에 등록된 작업이 없습니다.

+
+ `; + return; + } + + const data = selectedDateData; + + // 작업자별 상세 정보 생성 + const workerDetailsHtml = Array.from(data.workers).map(worker => { + const workerWorks = data.details.filter(w => (w.worker_name || w.worker_id) === worker); + const workerHours = workerWorks.reduce((sum, w) => sum + parseFloat(w.work_hours || 0), 0); + + const workerWorkItemsHtml = workerWorks.map(work => ` +
+
+ ${work.project_name || '프로젝트'} - ${work.work_hours}시간
+ 작업: ${work.work_type_name || '미지정'} | 상태: ${work.work_status_name || '미지정'} + ${work.error_type_name ? `
에러: ${work.error_type_name}` : ''} +
+
+ + +
+
+ `).join(''); + + return ` +
+
+ 👤 ${worker} - 총 ${workerHours}시간 + +
+
+ ${workerWorkItemsHtml} +
+
+ `; + }).join(''); + + dayInfoContainer.innerHTML = ` +
+
+

📅 ${selectedDate} 작업 정보

+
+ + +
+
+ +
+
+ 총 작업시간: + ${data.totalHours}시간 +
+
+ 근무 유형: + ${data.workLabel} +
+
+ 작업자 수: + ${data.workers.size}명 +
+
+ 검토 상태: + + ${data.reviewed ? '✅ 검토완료' : '⏳ 미검토'} + +
+
+ +
+

👥 작업자별 상세

+ ${workerDetailsHtml} +
+
+ `; +} + +// 검토 상태 토글 +function toggleReview() { + if (selectedDateData) { + selectedDateData.reviewed = !selectedDateData.reviewed; + renderDayInfo(); + + // TODO: 실제로는 여기서 API 호출해서 DB에 저장해야 함 + console.log(`검토 상태 변경: ${selectedDate} - ${selectedDateData.reviewed ? '검토완료' : '미검토'}`); + + showMessage(`검토 상태가 ${selectedDateData.reviewed ? '완료' : '미완료'}로 변경되었습니다.`, 'success'); + } +} + +// 현재 날짜 새로고침 +function refreshCurrentDay() { + if (selectedDate) { + loadDayData(selectedDate); + } +} + +// 🛠️ 작업 항목 수정 함수 (통합 API 사용) +async function editWorkItem(workId) { + try { + console.log('수정할 작업 ID:', workId); + + if (!selectedDateData) { + showMessage('작업 데이터를 찾을 수 없습니다.', 'error'); + return; + } + + const workData = selectedDateData.details.find(work => work.id == workId); + if (!workData) { + showMessage('수정할 작업 데이터를 찾을 수 없습니다.', 'error'); + return; + } + + // 기본 데이터가 없으면 로드 + if (basicData.workTypes.length === 0) { + showMessage('기본 데이터를 불러오는 중... (통합 API)', 'loading'); + await loadBasicData(); + } + + showEditModal(workData); + document.getElementById('message-container').innerHTML = ''; + + } catch (error) { + console.error('작업 정보 조회 오류:', error); + showMessage('작업 정보를 불러올 수 없습니다: ' + error.message, 'error'); + } +} + +// 🛠️ 수정 모달 표시 (개선된 버전) +function showEditModal(workData) { + const modalHtml = ` +
+
+
+

✏️ 작업 수정

+ +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+
+ `; + + document.body.insertAdjacentHTML('beforeend', modalHtml); + + // 업무 상태 변경 이벤트 + document.getElementById('editWorkStatus').addEventListener('change', (e) => { + const errorTypeGroup = document.getElementById('editErrorTypeGroup'); + if (e.target.value === '2') { + errorTypeGroup.style.display = 'block'; + } else { + errorTypeGroup.style.display = 'none'; + } + }); +} + +// 🛠️ 수정 모달 닫기 +function closeEditModal() { + const modal = document.getElementById('editModal'); + if (modal) { + modal.remove(); + } +} + +// 🛠️ 수정된 작업 저장 (통합 API 사용) +async function saveEditedWork(workId) { + try { + // 입력값 검증 + const projectId = document.getElementById('editProject').value; + const workTypeId = document.getElementById('editWorkType').value; + const workStatusId = document.getElementById('editWorkStatus').value; + const errorTypeId = document.getElementById('editErrorType').value; + const workHours = document.getElementById('editWorkHours').value; + + // 필수값 체크 + if (!projectId) { + showMessage('프로젝트를 선택해주세요.', 'error'); + document.getElementById('editProject').focus(); + return; + } + + if (!workTypeId) { + showMessage('작업 유형을 선택해주세요.', 'error'); + document.getElementById('editWorkType').focus(); + return; + } + + if (!workStatusId) { + showMessage('업무 상태를 선택해주세요.', 'error'); + document.getElementById('editWorkStatus').focus(); + return; + } + + if (!workHours || workHours <= 0) { + showMessage('작업 시간을 올바르게 입력해주세요.', 'error'); + document.getElementById('editWorkHours').focus(); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showMessage('에러 상태인 경우 에러 유형을 선택해주세요.', 'error'); + document.getElementById('editErrorType').focus(); + return; + } + + const updateData = { + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: errorTypeId ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours) + }; + + showMessage('작업을 수정하는 중... (통합 API)', 'loading'); + + // 저장 버튼 비활성화 + const saveBtn = document.querySelector('.btn-success'); + const originalText = saveBtn.textContent; + saveBtn.textContent = '저장 중...'; + saveBtn.disabled = true; + + const result = await apiCall(`${API}/daily-work-reports/my-entry/${workId}`, { + method: 'PUT', + body: JSON.stringify(updateData) + }); + + console.log('✅ 수정 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 수정되었습니다!', 'success'); + + closeEditModal(); + refreshCurrentDay(); // 현재 날짜 데이터 새로고침 + + } catch (error) { + console.error('❌ 수정 실패:', error); + showMessage('수정 중 오류가 발생했습니다: ' + error.message, 'error'); + + // 버튼 복원 + const saveBtn = document.querySelector('.btn-success'); + if (saveBtn) { + saveBtn.textContent = '💾 저장'; + saveBtn.disabled = false; + } + } +} + +// 🗑️ 작업 항목 삭제 (통합 API 사용) +async function deleteWorkItem(workId) { + // 확인 대화상자 + const confirmDelete = await showConfirmDialog( + '작업 삭제 확인', + '정말로 이 작업을 삭제하시겠습니까?', + '삭제된 작업은 복구할 수 없습니다.' + ); + + if (!confirmDelete) return; + + try { + console.log('삭제할 작업 ID:', workId); + + showMessage('작업을 삭제하는 중... (통합 API)', 'loading'); + + const result = await apiCall(`${API}/daily-work-reports/my-entry/${workId}`, { + method: 'DELETE' + }); + + console.log('✅ 삭제 성공 (통합 API):', result); + showMessage('✅ 작업이 성공적으로 삭제되었습니다!', 'success'); + + refreshCurrentDay(); // 현재 날짜 데이터 새로고침 + + } catch (error) { + console.error('❌ 삭제 실패:', error); + showMessage('삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 🗑️ 작업자의 모든 작업 삭제 (통합 API 사용) +async function deleteWorkerAllWorks(date, workerName) { + // 확인 대화상자 + const confirmDelete = await showConfirmDialog( + '전체 작업 삭제 확인', + `정말로 ${workerName}님의 ${date} 모든 작업을 삭제하시겠습니까?`, + '삭제된 작업들은 복구할 수 없습니다.' + ); + + if (!confirmDelete) return; + + try { + if (!selectedDateData) return; + + const workerWorks = selectedDateData.details.filter(w => (w.worker_name || w.worker_id) === workerName); + + if (workerWorks.length === 0) { + showMessage('삭제할 작업이 없습니다.', 'error'); + return; + } + + showMessage(`${workerName}님의 작업들을 삭제하는 중... (통합 API)`, 'loading'); + + // 순차적으로 삭제 (병렬 처리하면 서버 부하 발생 가능) + let successCount = 0; + let failCount = 0; + + for (const work of workerWorks) { + try { + await apiCall(`${API}/daily-work-reports/my-entry/${work.id}`, { + method: 'DELETE' + }); + successCount++; + } catch (error) { + console.error(`작업 ${work.id} 삭제 실패:`, error); + failCount++; + } + } + + if (failCount === 0) { + showMessage(`✅ ${workerName}님의 모든 작업(${successCount}개)이 삭제되었습니다!`, 'success'); + } else { + showMessage(`⚠️ ${successCount}개 삭제 완료, ${failCount}개 삭제 실패`, 'warning'); + } + + refreshCurrentDay(); // 현재 날짜 데이터 새로고침 + + } catch (error) { + console.error('❌ 전체 삭제 실패:', error); + showMessage('작업 삭제 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +// 확인 대화상자 표시 +function showConfirmDialog(title, message, warning) { + return new Promise((resolve) => { + const modalHtml = ` +
+
+
+

⚠️ ${title}

+
+
+

${message}

+

${warning}

+
+ +
+
+ `; + + document.body.insertAdjacentHTML('beforeend', modalHtml); + + // 전역 함수로 resolve 함수 노출 + window.resolveConfirm = (result) => { + const modal = document.getElementById('confirmModal'); + if (modal) modal.remove(); + delete window.resolveConfirm; + resolve(result); + }; + }); +} + +// 기본 데이터 로드 (통합 API 사용) +async function loadBasicData() { + try { + console.log('🔗 통합 API 설정을 사용한 기본 데이터 로딩...'); + + const promises = [ + // 활성 프로젝트 로드 + apiCall(`${API}/projects/active/list`) + .then(data => Array.isArray(data) ? data : (data.projects || [])) + .catch(() => []), + + // 작업 유형 로드 + apiCall(`${API}/daily-work-reports/work-types`) + .then(data => Array.isArray(data) ? data : [ + {id: 1, name: 'Base'}, + {id: 2, name: 'Vessel'}, + {id: 3, name: 'Piping'} + ]) + .catch(() => [ + {id: 1, name: 'Base'}, + {id: 2, name: 'Vessel'}, + {id: 3, name: 'Piping'} + ]), + + // 업무 상태 유형 로드 + apiCall(`${API}/daily-work-reports/work-status-types`) + .then(data => Array.isArray(data) ? data : [ + {id: 1, name: '정규'}, + {id: 2, name: '에러'} + ]) + .catch(() => [ + {id: 1, name: '정규'}, + {id: 2, name: '에러'} + ]), + + // 에러 유형 로드 + apiCall(`${API}/daily-work-reports/error-types`) + .then(data => Array.isArray(data) ? data : [ + {id: 1, name: '설계미스'}, + {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, + {id: 4, name: '작업 불량'} + ]) + .catch(() => [ + {id: 1, name: '설계미스'}, + {id: 2, name: '외주작업 불량'}, + {id: 3, name: '입고지연'}, + {id: 4, name: '작업 불량'} + ]) + ]; + + const [projects, workTypes, workStatusTypes, errorTypes] = await Promise.all(promises); + + basicData = { + projects, + workTypes, + workStatusTypes, + errorTypes + }; + + console.log('✅ 기본 데이터 로드 완료 (통합 API):', basicData); + } catch (error) { + console.error('기본 데이터 로드 실패:', error); + } +} + +// 이벤트 리스너 설정 +function setupEventListeners() { + document.getElementById('prevMonth').addEventListener('click', () => { + currentDate.setMonth(currentDate.getMonth() - 1); + updateMonthDisplay(); + selectedDate = null; + selectedDateData = null; + renderCalendar(); + renderDayInfo(); + }); + + document.getElementById('nextMonth').addEventListener('click', () => { + currentDate.setMonth(currentDate.getMonth() + 1); + updateMonthDisplay(); + selectedDate = null; + selectedDateData = null; + renderCalendar(); + renderDayInfo(); + }); + + // 오늘 날짜로 이동 버튼 추가 + document.getElementById('goToday')?.addEventListener('click', () => { + const today = new Date(); + currentDate = new Date(today); + updateMonthDisplay(); + renderCalendar(); + + // 오늘 날짜 자동 선택 + const todayStr = formatDate(today); + selectedDate = todayStr; + loadDayData(todayStr); + }); +} + +// 전역 함수로 노출 +window.toggleReview = toggleReview; +window.refreshCurrentDay = refreshCurrentDay; +window.editWorkItem = editWorkItem; +window.deleteWorkItem = deleteWorkItem; +window.deleteWorkerAllWorks = deleteWorkerAllWorks; +window.closeEditModal = closeEditModal; +window.saveEditedWork = saveEditedWork; + +// 초기화 +async function init() { + try { + const token = localStorage.getItem('token'); + if (!token || token === 'undefined') { + showMessage('로그인이 필요합니다.', 'error'); + setTimeout(() => { + window.location.href = '/'; + }, 2000); + return; + } + + updateMonthDisplay(); + setupEventListeners(); + renderCalendar(); + renderDayInfo(); + + // 기본 데이터 미리 로드 + await loadBasicData(); + + console.log('✅ 검토 페이지 초기화 완료 (통합 API 설정 적용)'); + + } catch (error) { + console.error('초기화 오류:', error); + showMessage('초기화 중 오류가 발생했습니다.', 'error'); + } +} + +// 페이지 로드 시 초기화 +document.addEventListener('DOMContentLoaded', init); \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/js/worker-individual-report.js b/deploy/tkfb-package/web-ui/js/worker-individual-report.js new file mode 100644 index 0000000..d40bd26 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/worker-individual-report.js @@ -0,0 +1,509 @@ +// worker-individual-report.js - 작업자별 개별 보고서 관리 + +// 전역 변수 +let currentWorkerId = null; +let currentWorkerName = ''; +let selectedDate = ''; +let currentUser = null; +let workTypes = []; +let workStatusTypes = []; +let errorTypes = []; +let projects = []; +let existingWork = []; + +// URL 파라미터에서 정보 추출 +function getUrlParams() { + const urlParams = new URLSearchParams(window.location.search); + return { + worker_id: urlParams.get('worker_id'), + worker_name: decodeURIComponent(urlParams.get('worker_name') || ''), + date: urlParams.get('date') || new Date().toISOString().split('T')[0] + }; +} + +// 현재 로그인한 사용자 정보 가져오기 +function getCurrentUser() { + try { + const token = localStorage.getItem('token'); + if (!token) return null; + + const payloadBase64 = token.split('.')[1]; + if (payloadBase64) { + const payload = JSON.parse(atob(payloadBase64)); + return payload; + } + } catch (error) { + console.log('토큰에서 사용자 정보 추출 실패:', error); + } + + try { + const userInfo = localStorage.getItem('user'); + if (userInfo) { + return JSON.parse(userInfo); + } + } catch (error) { + console.log('localStorage에서 사용자 정보 파싱 실패:', error); + } + return null; +} + +// 메시지 표시 함수 +function showMessage(msg, type = 'info') { + const container = document.getElementById('message-container'); + if (container) { + container.innerHTML = `
${msg}
`; + setTimeout(() => { + container.innerHTML = ''; + }, 5000); + } +} + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', async () => { + // API 함수가 로드될 때까지 기다림 + let retryCount = 0; + const maxRetries = 50; + + while (!window.apiCall && retryCount < maxRetries) { + await new Promise(resolve => setTimeout(resolve, 100)); + retryCount++; + } + + if (!window.apiCall) { + console.error('❌ API 함수를 로드할 수 없습니다.'); + showMessage('시스템을 초기화할 수 없습니다. 페이지를 새로고침해주세요.', 'error'); + return; + } + + try { + await initializePage(); + } catch (error) { + console.error('페이지 초기화 오류:', error); + showMessage('페이지를 불러오는 중 오류가 발생했습니다.', 'error'); + } +}); + +async function initializePage() { + console.log('🚀 개별 작업 보고서 페이지 초기화 시작'); + + // URL 파라미터 추출 + const params = getUrlParams(); + currentWorkerId = parseInt(params.worker_id); + currentWorkerName = params.worker_name; + selectedDate = params.date; + + // 사용자 정보 설정 + currentUser = getCurrentUser(); + + if (!currentWorkerId || !currentWorkerName) { + showMessage('잘못된 접근입니다. 작업자 정보가 없습니다.', 'error'); + setTimeout(() => { + window.history.back(); + }, 2000); + return; + } + + // 페이지 제목 설정 + updatePageHeader(); + + // 이벤트 리스너 설정 + setupEventListeners(); + + // 초기 데이터 로드 + await loadInitialData(); + + console.log('✅ 개별 작업 보고서 페이지 초기화 완료'); +} + +function updatePageHeader() { + document.getElementById('pageTitle').textContent = `👤 ${currentWorkerName} 작업 보고서`; + document.getElementById('pageSubtitle').textContent = `${selectedDate} 작업 내용을 관리합니다.`; + + // 작업자 정보 카드 업데이트 + document.getElementById('workerInitial').textContent = currentWorkerName.charAt(0); + document.getElementById('workerName').textContent = currentWorkerName; + document.getElementById('selectedDate').textContent = selectedDate; +} + +function setupEventListeners() { + // 새 작업 추가 버튼 + document.getElementById('addNewWorkBtn').addEventListener('click', showNewWorkForm); + document.getElementById('cancelNewWorkBtn').addEventListener('click', hideNewWorkForm); + document.getElementById('saveNewWorkBtn').addEventListener('click', saveNewWork); + + // 업무 상태 변경 시 에러 유형 섹션 토글 + document.getElementById('newWorkStatusSelect').addEventListener('change', toggleErrorTypeSection); + + // 빠른 시간 버튼 + document.querySelectorAll('.quick-time-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + document.getElementById('newWorkHours').value = e.target.dataset.hours; + }); + }); + + // 휴가 처리 버튼들 + document.querySelectorAll('.vacation-process-btn').forEach(btn => { + btn.addEventListener('click', (e) => { + const vacationType = e.target.dataset.type; + handleVacationProcess(vacationType); + }); + }); +} + +async function loadInitialData() { + try { + showMessage('데이터를 불러오는 중...', 'loading'); + + // 병렬로 데이터 로드 + await Promise.all([ + loadWorkerInfo(), + loadExistingWork(), + loadProjects(), + loadWorkTypes(), + loadWorkStatusTypes(), + loadErrorTypes() + ]); + + // UI 업데이트 + updateWorkerSummary(); + renderExistingWork(); + populateDropdowns(); + + showMessage('데이터 로드 완료', 'success'); + + } catch (error) { + console.error('초기 데이터 로드 실패:', error); + showMessage('데이터 로드 중 오류가 발생했습니다: ' + error.message, 'error'); + } +} + +async function loadWorkerInfo() { + try { + const response = await window.apiCall(`/workers/${currentWorkerId}`); + const worker = response.data || response; + document.getElementById('workerJob').textContent = worker.job_type || '작업자'; + } catch (error) { + console.error('작업자 정보 로드 오류:', error); + } +} + +async function loadExistingWork() { + try { + const response = await window.apiCall(`/daily-work-reports?date=${selectedDate}&worker_id=${currentWorkerId}`); + existingWork = Array.isArray(response) ? response : (response.data || []); + console.log(`✅ 기존 작업 ${existingWork.length}건 로드 완료`); + } catch (error) { + console.error('기존 작업 로드 오류:', error); + existingWork = []; + } +} + +async function loadProjects() { + try { + const response = await window.apiCall(`/projects/active/list`); + projects = Array.isArray(response) ? response : (response.data || []); + } catch (error) { + console.error('프로젝트 로드 오류:', error); + projects = []; + } +} + +async function loadWorkTypes() { + try { + const response = await window.apiCall(`/daily-work-reports/work-types`); + workTypes = Array.isArray(response) ? response : (response.data || []); + } catch (error) { + console.error('작업 유형 로드 오류:', error); + workTypes = []; + } +} + +async function loadWorkStatusTypes() { + try { + const response = await window.apiCall(`/daily-work-reports/work-status-types`); + workStatusTypes = Array.isArray(response) ? response : (response.data || []); + } catch (error) { + console.error('작업 상태 유형 로드 오류:', error); + workStatusTypes = []; + } +} + +async function loadErrorTypes() { + try { + const response = await window.apiCall(`/daily-work-reports/error-types`); + errorTypes = Array.isArray(response) ? response : (response.data || []); + } catch (error) { + console.error('에러 유형 로드 오류:', error); + errorTypes = []; + } +} + +function updateWorkerSummary() { + const totalHours = existingWork.reduce((sum, work) => sum + parseFloat(work.work_hours || 0), 0); + const workCount = existingWork.length; + + document.getElementById('totalHours').textContent = `${totalHours.toFixed(1)}h`; + document.getElementById('workCount').textContent = `${workCount}건`; + + // 12시간 초과 경고 + if (totalHours > 12) { + document.getElementById('totalHours').classList.add('warning'); + showMessage(`⚠️ 총 작업시간이 ${totalHours.toFixed(1)}시간으로 12시간을 초과했습니다.`, 'warning'); + } +} + +function renderExistingWork() { + const container = document.getElementById('existingWorkList'); + + if (existingWork.length === 0) { + container.innerHTML = ` +
+
📭
+

등록된 작업이 없습니다

+

${selectedDate}에 ${currentWorkerName}님의 작업이 등록되지 않았습니다.

+
+ `; + return; + } + + container.innerHTML = existingWork.map(work => ` +
+
+
+

${work.project_name || '미지정 프로젝트'}

+

${work.work_type_name || '미지정 작업'}

+
+
+ + ${work.work_status_name || '정상'} + + ${work.work_hours}h +
+
+ ${work.work_status_id === 2 && work.error_type_name ? ` +
+ 오류: + ${work.error_type_name} +
+ ` : ''} +
+ + +
+
+ `).join(''); +} + +function populateDropdowns() { + // 프로젝트 드롭다운 + const projectSelect = document.getElementById('newProjectSelect'); + projectSelect.innerHTML = ''; + projects.forEach(project => { + const option = document.createElement('option'); + option.value = project.project_id; + option.textContent = project.project_name; + projectSelect.appendChild(option); + }); + + // 작업 유형 드롭다운 + const workTypeSelect = document.getElementById('newWorkTypeSelect'); + workTypeSelect.innerHTML = ''; + workTypes.forEach(type => { + const option = document.createElement('option'); + option.value = type.id; + option.textContent = type.name; + workTypeSelect.appendChild(option); + }); + + // 작업 상태 드롭다운 + const workStatusSelect = document.getElementById('newWorkStatusSelect'); + workStatusSelect.innerHTML = ''; + workStatusTypes.forEach(status => { + const option = document.createElement('option'); + option.value = status.id; + option.textContent = status.name; + workStatusSelect.appendChild(option); + }); + + // 에러 유형 드롭다운 + const errorTypeSelect = document.getElementById('newErrorTypeSelect'); + errorTypeSelect.innerHTML = ''; + errorTypes.forEach(error => { + const option = document.createElement('option'); + option.value = error.id; + option.textContent = error.name; + errorTypeSelect.appendChild(option); + }); +} + +function showNewWorkForm() { + document.getElementById('newWorkSection').style.display = 'block'; + document.getElementById('addNewWorkBtn').style.display = 'none'; +} + +function hideNewWorkForm() { + document.getElementById('newWorkSection').style.display = 'none'; + document.getElementById('addNewWorkBtn').style.display = 'block'; + resetNewWorkForm(); +} + +function resetNewWorkForm() { + document.getElementById('newProjectSelect').value = ''; + document.getElementById('newWorkTypeSelect').value = ''; + document.getElementById('newWorkStatusSelect').value = ''; + document.getElementById('newErrorTypeSelect').value = ''; + document.getElementById('newWorkHours').value = '1.00'; + document.getElementById('newErrorTypeSection').classList.remove('visible'); +} + +function toggleErrorTypeSection() { + const workStatusSelect = document.getElementById('newWorkStatusSelect'); + const errorSection = document.getElementById('newErrorTypeSection'); + const errorTypeSelect = document.getElementById('newErrorTypeSelect'); + + if (workStatusSelect.value === '2') { // 에러 상태 + errorSection.classList.add('visible'); + errorTypeSelect.setAttribute('required', 'true'); + } else { + errorSection.classList.remove('visible'); + errorTypeSelect.removeAttribute('required'); + errorTypeSelect.value = ''; + } +} + +async function saveNewWork() { + try { + const projectId = document.getElementById('newProjectSelect').value; + const workTypeId = document.getElementById('newWorkTypeSelect').value; + const workStatusId = document.getElementById('newWorkStatusSelect').value; + const errorTypeId = document.getElementById('newErrorTypeSelect').value; + const workHours = document.getElementById('newWorkHours').value; + + // 유효성 검사 + if (!projectId || !workTypeId || !workStatusId || !workHours) { + showMessage('모든 필수 필드를 입력해주세요.', 'error'); + return; + } + + if (workStatusId === '2' && !errorTypeId) { + showMessage('에러 상태일 때는 에러 유형을 선택해야 합니다.', 'error'); + return; + } + + showMessage('작업을 저장하는 중...', 'loading'); + + const workData = { + report_date: selectedDate, + worker_id: currentWorkerId, + project_id: parseInt(projectId), + work_type_id: parseInt(workTypeId), + work_status_id: parseInt(workStatusId), + error_type_id: workStatusId === '2' ? parseInt(errorTypeId) : null, + work_hours: parseFloat(workHours), + created_by: currentUser?.user_id || 1 + }; + + const response = await window.apiCall(`/daily-work-reports`, 'POST', workData); + + showMessage('작업이 성공적으로 저장되었습니다.', 'success'); + + // 데이터 새로고침 + await loadExistingWork(); + updateWorkerSummary(); + renderExistingWork(); + hideNewWorkForm(); + + } catch (error) { + console.error('작업 저장 오류:', error); + showMessage(`작업 저장 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +async function editWork(workId) { + // TODO: 작업 수정 모달 또는 인라인 편집 구현 + console.log(`작업 ${workId} 수정`); + showMessage('작업 수정 기능은 곧 구현될 예정입니다.', 'info'); +} + +async function deleteWork(workId) { + if (!confirm('이 작업을 삭제하시겠습니까?')) { + return; + } + + try { + showMessage('작업을 삭제하는 중...', 'loading'); + + await window.apiCall(`/daily-work-reports/${workId}`, { + method: 'DELETE' + }); + + showMessage('작업이 성공적으로 삭제되었습니다.', 'success'); + + // 데이터 새로고침 + await loadExistingWork(); + updateWorkerSummary(); + renderExistingWork(); + + } catch (error) { + console.error('작업 삭제 오류:', error); + showMessage(`작업 삭제 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +async function handleVacationProcess(vacationType) { + const vacationNames = { + 'full': '연차', + 'half-half': '반반차', + 'half': '반차' + }; + + const vacationHours = { + 'full': 8, + 'half-half': 6, + 'half': 4 + }; + + if (!confirm(`${vacationNames[vacationType]} 처리하시겠습니까?\n(${vacationHours[vacationType]}시간으로 자동 입력됩니다)`)) { + return; + } + + try { + showMessage(`${vacationNames[vacationType]} 처리 중...`, 'loading'); + + // 휴가용 작업 보고서 생성 + const vacationWork = { + report_date: selectedDate, + worker_id: currentWorkerId, + project_id: 1, // 기본 프로젝트 (휴가용) + work_type_id: 999, // 휴가 전용 작업 유형 (DB에 추가 필요) + work_status_id: 1, // 정상 상태 + error_type_id: null, + work_hours: vacationHours[vacationType], + created_by: currentUser?.user_id || 1 + }; + + const response = await window.apiCall(`/daily-work-reports`, { + method: 'POST', + body: JSON.stringify(vacationWork) + }); + + showMessage(`${vacationNames[vacationType]} 처리가 완료되었습니다.`, 'success'); + + // 데이터 새로고침 + await loadExistingWork(); + updateWorkerSummary(); + renderExistingWork(); + + } catch (error) { + console.error('휴가 처리 오류:', error); + showMessage(`휴가 처리 중 오류가 발생했습니다: ${error.message}`, 'error'); + } +} + +// 전역 함수로 등록 +window.editWork = editWork; +window.deleteWork = deleteWork; diff --git a/deploy/tkfb-package/web-ui/js/worker-management.js b/deploy/tkfb-package/web-ui/js/worker-management.js new file mode 100644 index 0000000..8908fdb --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/worker-management.js @@ -0,0 +1,641 @@ +// 작업자 관리 페이지 JavaScript (부서 기반) + +// 전역 변수 +let departments = []; +let currentDepartmentId = null; +let allWorkers = []; +let filteredWorkers = []; +let currentEditingWorker = null; + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', async () => { + console.log('👥 작업자 관리 페이지 초기화 시작'); + await waitForApiConfig(); + await loadDepartments(); +}); + +// API 설정 로드 대기 +async function waitForApiConfig() { + let retryCount = 0; + while (!window.apiCall && retryCount < 50) { + await new Promise(resolve => setTimeout(resolve, 100)); + retryCount++; + } + if (!window.apiCall) { + console.error('API 설정 로드 실패'); + } +} + +// ============================================ +// 부서 관련 함수 +// ============================================ + +// 부서 목록 로드 +async function loadDepartments() { + try { + const response = await window.apiCall('/departments'); + const result = response; + + if (result && result.success) { + departments = result.data; + renderDepartmentList(); + updateParentDepartmentSelect(); + console.log('✅ 부서 목록 로드 완료:', departments.length + '개'); + } else if (Array.isArray(result)) { + departments = result; + renderDepartmentList(); + updateParentDepartmentSelect(); + } + } catch (error) { + console.error('부서 목록 로드 실패:', error); + showToast('부서 목록을 불러오는데 실패했습니다.', 'error'); + } +} + +// 부서 목록 렌더링 +function renderDepartmentList() { + const container = document.getElementById('departmentList'); + if (!container) return; + + if (departments.length === 0) { + container.innerHTML = ` +
+ 등록된 부서가 없습니다.
+ +
+ `; + return; + } + + container.innerHTML = departments.map(dept => { + const safeDeptId = parseInt(dept.department_id) || 0; + const safeDeptName = escapeHtml(dept.department_name || '-'); + const workerCount = parseInt(dept.worker_count) || 0; + return ` +
+
+ ${safeDeptName} + ${workerCount}명 +
+
+ + +
+
+ `; + }).join(''); +} + +// 부서 선택 +async function selectDepartment(departmentId) { + currentDepartmentId = departmentId; + renderDepartmentList(); + + const dept = departments.find(d => d.department_id === departmentId); + document.getElementById('workerListTitle').textContent = `${dept.department_name} 작업자`; + document.getElementById('addWorkerBtn').style.display = 'inline-flex'; + document.getElementById('workerToolbar').style.display = 'flex'; + + await loadWorkersByDepartment(departmentId); +} + +// 상위 부서 선택 옵션 업데이트 +function updateParentDepartmentSelect() { + const select = document.getElementById('parentDepartment'); + if (!select) return; + + const currentId = document.getElementById('departmentId')?.value; + + select.innerHTML = '' + + departments + .filter(d => d.department_id !== parseInt(currentId)) + .map(d => { + const safeDeptId = parseInt(d.department_id) || 0; + return ``; + }) + .join(''); +} + +// 부서 모달 열기 +function openDepartmentModal(departmentId = null) { + const modal = document.getElementById('departmentModal'); + const title = document.getElementById('departmentModalTitle'); + const form = document.getElementById('departmentForm'); + const deleteBtn = document.getElementById('deleteDeptBtn'); + + updateParentDepartmentSelect(); + + if (departmentId) { + const dept = departments.find(d => d.department_id === departmentId); + title.textContent = '부서 수정'; + deleteBtn.style.display = 'inline-flex'; + document.getElementById('departmentId').value = dept.department_id; + document.getElementById('departmentName').value = dept.department_name; + document.getElementById('parentDepartment').value = dept.parent_id || ''; + document.getElementById('departmentDescription').value = dept.description || ''; + document.getElementById('displayOrder').value = dept.display_order || 0; + document.getElementById('isActiveDept').checked = dept.is_active !== 0 && dept.is_active !== false; + } else { + title.textContent = '새 부서 등록'; + deleteBtn.style.display = 'none'; + form.reset(); + document.getElementById('departmentId').value = ''; + document.getElementById('isActiveDept').checked = true; + } + + modal.style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + setTimeout(() => { + document.getElementById('departmentName').focus(); + }, 100); +} + +// 부서 모달 닫기 +function closeDepartmentModal() { + const modal = document.getElementById('departmentModal'); + if (modal) { + modal.style.display = 'none'; + document.body.style.overflow = ''; + } +} + +// 부서 저장 +async function saveDepartment() { + const departmentId = document.getElementById('departmentId').value; + const data = { + department_name: document.getElementById('departmentName').value.trim(), + parent_id: document.getElementById('parentDepartment').value || null, + description: document.getElementById('departmentDescription').value.trim(), + display_order: parseInt(document.getElementById('displayOrder').value) || 0, + is_active: document.getElementById('isActiveDept').checked + }; + + if (!data.department_name) { + showToast('부서명은 필수 입력 항목입니다.', 'error'); + return; + } + + try { + const url = departmentId ? `/departments/${departmentId}` : '/departments'; + const method = departmentId ? 'PUT' : 'POST'; + + const response = await window.apiCall(url, method, data); + + if (response && response.success) { + showToast(response.message || '부서가 저장되었습니다.', 'success'); + closeDepartmentModal(); + await loadDepartments(); + } else { + throw new Error(response?.error || '저장 실패'); + } + } catch (error) { + console.error('부서 저장 실패:', error); + showToast('부서 저장에 실패했습니다.', 'error'); + } +} + +// 부서 수정 +function editDepartment(departmentId) { + openDepartmentModal(departmentId); +} + +// 부서 삭제 확인 +function confirmDeleteDepartment(departmentId) { + const dept = departments.find(d => d.department_id === departmentId); + if (!dept) return; + + const workerCount = dept.worker_count || 0; + let message = `"${dept.department_name}" 부서를 삭제하시겠습니까?`; + + if (workerCount > 0) { + message += `\n\n⚠️ 이 부서에는 ${workerCount}명의 작업자가 있습니다.\n삭제하면 작업자들의 부서 정보가 제거됩니다.`; + } + + if (confirm(message)) { + deleteDepartment(departmentId); + } +} + +// 부서 삭제 +async function deleteDepartment(departmentId = null) { + const id = departmentId || document.getElementById('departmentId').value; + if (!id) return; + + try { + const response = await window.apiCall(`/departments/${id}`, 'DELETE'); + + if (response && response.success) { + showToast('부서가 삭제되었습니다.', 'success'); + closeDepartmentModal(); + + if (currentDepartmentId === parseInt(id)) { + currentDepartmentId = null; + document.getElementById('workerListTitle').textContent = '부서를 선택하세요'; + document.getElementById('addWorkerBtn').style.display = 'none'; + document.getElementById('workerToolbar').style.display = 'none'; + document.getElementById('workerList').innerHTML = ` +
+

부서를 선택해주세요

+

왼쪽에서 부서를 선택하면 해당 부서의 작업자가 표시됩니다.

+
+ `; + } + + await loadDepartments(); + } else { + throw new Error(response?.error || '삭제 실패'); + } + } catch (error) { + console.error('부서 삭제 실패:', error); + showToast(error.message || '부서 삭제에 실패했습니다.', 'error'); + } +} + +// ============================================ +// 작업자 관련 함수 +// ============================================ + +// 부서별 작업자 로드 +async function loadWorkersByDepartment(departmentId) { + try { + const response = await window.apiCall(`/departments/${departmentId}/workers`); + + if (response && response.success) { + allWorkers = response.data; + filteredWorkers = [...allWorkers]; + renderWorkerList(); + console.log(`✅ ${departmentId} 부서 작업자 로드: ${allWorkers.length}명`); + } else if (Array.isArray(response)) { + allWorkers = response; + filteredWorkers = [...allWorkers]; + renderWorkerList(); + } + } catch (error) { + console.error('작업자 목록 로드 실패:', error); + showToast('작업자 목록을 불러오는데 실패했습니다.', 'error'); + } +} + +// 작업자 목록 렌더링 +function renderWorkerList() { + const container = document.getElementById('workerList'); + if (!container) return; + + if (filteredWorkers.length === 0) { + container.innerHTML = ` +
+

작업자가 없습니다

+

"+ 작업자 추가" 버튼을 눌러 작업자를 등록하세요.

+
+ `; + return; + } + + const tableHtml = ` + + + + + + + + + + + + + ${filteredWorkers.map(worker => { + const jobTypeMap = { + 'worker': '작업자', + 'leader': '그룹장', + 'admin': '관리자' + }; + const safeJobType = ['worker', 'leader', 'admin'].includes(worker.job_type) ? worker.job_type : ''; + const jobType = jobTypeMap[safeJobType] || escapeHtml(worker.job_type || '-'); + + const isInactive = worker.status === 'inactive'; + const isResigned = worker.employment_status === 'resigned'; + const hasAccount = worker.user_id !== null && worker.user_id !== undefined; + + let statusClass = 'active'; + let statusText = '현장직'; + if (isResigned) { + statusClass = 'resigned'; + statusText = '퇴사'; + } else if (isInactive) { + statusClass = 'inactive'; + statusText = '사무직'; + } + + const safeWorkerId = parseInt(worker.worker_id) || 0; + const safeWorkerName = escapeHtml(worker.worker_name || ''); + const firstChar = safeWorkerName ? safeWorkerName.charAt(0) : '?'; + + return ` + + + + + + + + + `; + }).join('')} + +
이름직책상태입사일계정관리
+
+
${firstChar}
+ ${safeWorkerName} +
+
${jobType}${statusText}${worker.join_date ? formatDate(worker.join_date) : '-'} + + +
+ + +
+
+ `; + + container.innerHTML = tableHtml; +} + +// 작업자 필터링 +function filterWorkers() { + const searchTerm = document.getElementById('workerSearch')?.value.toLowerCase().trim() || ''; + const statusValue = document.getElementById('statusFilter')?.value || ''; + + filteredWorkers = allWorkers.filter(worker => { + // 검색 필터 + const matchesSearch = !searchTerm || + worker.worker_name.toLowerCase().includes(searchTerm) || + (worker.job_type && worker.job_type.toLowerCase().includes(searchTerm)); + + // 상태 필터 + let matchesStatus = true; + if (statusValue === 'active') { + matchesStatus = worker.status !== 'inactive' && worker.employment_status !== 'resigned'; + } else if (statusValue === 'inactive') { + matchesStatus = worker.status === 'inactive'; + } else if (statusValue === 'resigned') { + matchesStatus = worker.employment_status === 'resigned'; + } + + return matchesSearch && matchesStatus; + }); + + renderWorkerList(); +} + +// 작업자 모달 열기 +function openWorkerModal(workerId = null) { + const modal = document.getElementById('workerModal'); + const title = document.getElementById('workerModalTitle'); + const deleteBtn = document.getElementById('deleteWorkerBtn'); + + if (!currentDepartmentId) { + showToast('먼저 부서를 선택해주세요.', 'error'); + return; + } + + if (workerId) { + const worker = allWorkers.find(w => w.worker_id === workerId); + if (!worker) { + showToast('작업자를 찾을 수 없습니다.', 'error'); + return; + } + + currentEditingWorker = worker; + title.textContent = '작업자 정보 수정'; + deleteBtn.style.display = 'inline-flex'; + + document.getElementById('workerId').value = worker.worker_id; + document.getElementById('workerName').value = worker.worker_name || ''; + document.getElementById('jobType').value = worker.job_type || 'worker'; + document.getElementById('joinDate').value = worker.join_date ? worker.join_date.split('T')[0] : ''; + document.getElementById('salary').value = worker.salary || ''; + document.getElementById('annualLeave').value = worker.annual_leave || 0; + document.getElementById('isActiveWorker').checked = worker.status !== 'inactive'; + document.getElementById('createAccount').checked = worker.user_id !== null && worker.user_id !== undefined; + document.getElementById('isResigned').checked = worker.employment_status === 'resigned'; + } else { + currentEditingWorker = null; + title.textContent = '새 작업자 등록'; + deleteBtn.style.display = 'none'; + + document.getElementById('workerForm').reset(); + document.getElementById('workerId').value = ''; + document.getElementById('isActiveWorker').checked = true; + document.getElementById('createAccount').checked = false; + document.getElementById('isResigned').checked = false; + } + + modal.style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + setTimeout(() => { + document.getElementById('workerName').focus(); + }, 100); +} + +// 작업자 모달 닫기 +function closeWorkerModal() { + const modal = document.getElementById('workerModal'); + if (modal) { + modal.style.display = 'none'; + document.body.style.overflow = ''; + currentEditingWorker = null; + } +} + +// 작업자 편집 +function editWorker(workerId) { + openWorkerModal(workerId); +} + +// 작업자 저장 +async function saveWorker() { + const workerId = document.getElementById('workerId').value; + + const workerData = { + worker_name: document.getElementById('workerName').value.trim(), + job_type: document.getElementById('jobType').value || 'worker', + join_date: document.getElementById('joinDate').value || null, + salary: document.getElementById('salary').value || null, + annual_leave: document.getElementById('annualLeave').value || 0, + status: document.getElementById('isActiveWorker').checked ? 'active' : 'inactive', + employment_status: document.getElementById('isResigned').checked ? 'resigned' : 'employed', + create_account: document.getElementById('createAccount').checked, + department_id: currentDepartmentId + }; + + if (!workerData.worker_name) { + showToast('작업자명은 필수 입력 항목입니다.', 'error'); + return; + } + + try { + let response; + + if (workerId) { + response = await window.apiCall(`/workers/${workerId}`, 'PUT', workerData); + } else { + response = await window.apiCall('/workers', 'POST', workerData); + } + + if (response && (response.success || response.data)) { + const action = workerId ? '수정' : '등록'; + showToast(`작업자가 성공적으로 ${action}되었습니다.`, 'success'); + + closeWorkerModal(); + await loadDepartments(); + await loadWorkersByDepartment(currentDepartmentId); + } else { + throw new Error(response?.message || '저장에 실패했습니다.'); + } + } catch (error) { + console.error('작업자 저장 오류:', error); + showToast(error.message || '작업자 저장 중 오류가 발생했습니다.', 'error'); + } +} + +// 작업자 삭제 확인 +function confirmDeleteWorker(workerId) { + const worker = allWorkers.find(w => w.worker_id === workerId); + if (!worker) { + showToast('작업자를 찾을 수 없습니다.', 'error'); + return; + } + + const confirmMessage = `"${worker.worker_name}" 작업자를 삭제하시겠습니까?\n\n⚠️ 관련된 모든 데이터(작업보고서, 이슈 등)가 함께 삭제됩니다.`; + + if (confirm(confirmMessage)) { + deleteWorkerById(workerId); + } +} + +// 작업자 삭제 (모달에서) +function deleteWorker() { + if (currentEditingWorker) { + confirmDeleteWorker(currentEditingWorker.worker_id); + } +} + +// 작업자 삭제 실행 +async function deleteWorkerById(workerId) { + try { + const response = await window.apiCall(`/workers/${workerId}`, 'DELETE'); + + if (response && (response.success || response.message)) { + showToast('작업자가 삭제되었습니다.', 'success'); + + closeWorkerModal(); + await loadDepartments(); + await loadWorkersByDepartment(currentDepartmentId); + } else { + throw new Error(response?.error || '삭제 실패'); + } + } catch (error) { + console.error('작업자 삭제 오류:', error); + showToast(error.message || '작업자 삭제에 실패했습니다.', 'error'); + } +} + +// ============================================ +// 유틸리티 함수 +// ============================================ + +// 날짜 포맷팅 +function formatDate(dateString) { + if (!dateString) return ''; + const date = new Date(dateString); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }); +} + +// 토스트 메시지 표시 +function showToast(message, type = 'info') { + const existingToast = document.querySelector('.toast'); + if (existingToast) { + existingToast.remove(); + } + + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + + Object.assign(toast.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '12px 24px', + borderRadius: '8px', + color: 'white', + fontWeight: '500', + zIndex: '10000', + transform: 'translateX(100%)', + transition: 'transform 0.3s ease' + }); + + const colors = { + success: '#10b981', + error: '#ef4444', + warning: '#f59e0b', + info: '#3b82f6' + }; + toast.style.backgroundColor = colors[type] || colors.info; + + document.body.appendChild(toast); + + setTimeout(() => { + toast.style.transform = 'translateX(0)'; + }, 100); + + setTimeout(() => { + toast.style.transform = 'translateX(100%)'; + setTimeout(() => { + if (toast.parentNode) { + toast.remove(); + } + }, 300); + }, 3000); +} + +// ============================================ +// 전역 함수 노출 +// ============================================ +window.openDepartmentModal = openDepartmentModal; +window.closeDepartmentModal = closeDepartmentModal; +window.saveDepartment = saveDepartment; +window.editDepartment = editDepartment; +window.deleteDepartment = deleteDepartment; +window.confirmDeleteDepartment = confirmDeleteDepartment; +window.selectDepartment = selectDepartment; + +window.openWorkerModal = openWorkerModal; +window.closeWorkerModal = closeWorkerModal; +window.saveWorker = saveWorker; +window.editWorker = editWorker; +window.deleteWorker = deleteWorker; +window.confirmDeleteWorker = confirmDeleteWorker; +window.filterWorkers = filterWorkers; diff --git a/deploy/tkfb-package/web-ui/js/workplace-layout-map.js b/deploy/tkfb-package/web-ui/js/workplace-layout-map.js new file mode 100644 index 0000000..35e0209 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/workplace-layout-map.js @@ -0,0 +1,494 @@ +// 작업장 레이아웃 지도 관리 + +// 전역 변수 +let layoutMapImage = null; +let mapRegions = []; +let canvas = null; +let ctx = null; +let isDrawing = false; +let startX = 0; +let startY = 0; +let currentRect = null; + +// ==================== 레이아웃 지도 모달 ==================== + +/** + * 레이아웃 지도 모달 열기 + */ +async function openLayoutMapModal() { + // window 객체에서 currentCategoryId 가져오기 + const currentCategoryId = window.currentCategoryId; + + if (!currentCategoryId) { + window.window.showToast('공장을 먼저 선택해주세요.', 'warning'); + return; + } + + const modal = document.getElementById('layoutMapModal'); + if (!modal) return; + + // 캔버스 초기화 + canvas = document.getElementById('regionCanvas'); + ctx = canvas.getContext('2d'); + + // 현재 카테고리의 레이아웃 이미지 및 영역 로드 + await loadLayoutMapData(); + + // 작업장 선택 옵션 업데이트 + updateWorkplaceSelect(); + + modal.style.display = 'flex'; + document.body.style.overflow = 'hidden'; +} + +/** + * 레이아웃 지도 모달 닫기 + */ +function closeLayoutMapModal() { + const modal = document.getElementById('layoutMapModal'); + if (modal) { + modal.style.display = 'none'; + document.body.style.overflow = ''; + } + + // 캔버스 이벤트 리스너 제거 + if (canvas) { + canvas.removeEventListener('mousedown', startDrawing); + canvas.removeEventListener('mousemove', draw); + canvas.removeEventListener('mouseup', stopDrawing); + } + + // 메인 페이지의 레이아웃 미리보기 업데이트 + const currentCategoryId = window.currentCategoryId; + const categories = window.categories; + + if (currentCategoryId && categories) { + const category = categories.find(c => c.category_id == currentCategoryId); + if (category && window.updateLayoutPreview) { + window.updateLayoutPreview(category); + } + } +} + +/** + * 레이아웃 지도 데이터 로드 + */ +async function loadLayoutMapData() { + try { + const currentCategoryId = window.currentCategoryId; + const categories = window.categories; + + // 현재 카테고리 정보 가져오기 + const category = categories.find(c => c.category_id == currentCategoryId); + if (!category) return; + + // 레이아웃 이미지 표시 + const currentImageDiv = document.getElementById('currentLayoutImage'); + if (category.layout_image) { + // 이미지 경로를 전체 URL로 변환 + const fullImageUrl = category.layout_image.startsWith('http') + ? category.layout_image + : `${window.API_BASE_URL || 'http://localhost:20005/api'}${category.layout_image}`.replace('/api/', '/'); + + currentImageDiv.innerHTML = ` + 현재 레이아웃 이미지 + `; + + // 캔버스에도 이미지 로드 + loadImageToCanvas(fullImageUrl); + } else { + currentImageDiv.innerHTML = '업로드된 이미지가 없습니다'; + } + + // 영역 데이터 로드 + const regionsResponse = await window.apiCall(`/workplaces/categories/${currentCategoryId}/map-regions`, 'GET'); + if (regionsResponse && regionsResponse.success) { + mapRegions = regionsResponse.data || []; + } else { + mapRegions = []; + } + + renderRegionList(); + } catch (error) { + console.error('레이아웃 지도 데이터 로딩 오류:', error); + window.window.showToast('레이아웃 지도 데이터를 불러오는데 실패했습니다.', 'error'); + } +} + +/** + * 이미지를 캔버스에 로드 + */ +function loadImageToCanvas(imagePath) { + const img = new Image(); + img.onload = function() { + // 캔버스 크기를 이미지 크기에 맞춤 (최대 800px) + const maxWidth = 800; + const scale = img.width > maxWidth ? maxWidth / img.width : 1; + + canvas.width = img.width * scale; + canvas.height = img.height * scale; + + // 이미지 그리기 + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + + layoutMapImage = img; + + // 기존 영역들 그리기 + drawExistingRegions(); + + // 캔버스 이벤트 리스너 등록 + setupCanvasEvents(); + }; + img.src = imagePath; +} + +/** + * 작업장 선택 옵션 업데이트 + */ +function updateWorkplaceSelect() { + const select = document.getElementById('regionWorkplaceSelect'); + if (!select) return; + + const currentCategoryId = window.currentCategoryId; + const workplaces = window.workplaces; + + // 현재 카테고리의 작업장만 필터링 + const categoryWorkplaces = workplaces.filter(w => w.category_id == currentCategoryId); + + let options = ''; + categoryWorkplaces.forEach(wp => { + // 이미 영역이 정의된 작업장은 표시 + const hasRegion = mapRegions.some(r => r.workplace_id === wp.workplace_id); + options += ``; + }); + + select.innerHTML = options; +} + +// ==================== 이미지 업로드 ==================== + +/** + * 이미지 미리보기 + */ +function previewLayoutImage(event) { + const file = event.target.files[0]; + if (!file) return; + + const reader = new FileReader(); + reader.onload = function(e) { + const currentImageDiv = document.getElementById('currentLayoutImage'); + currentImageDiv.innerHTML = ` + 미리보기 +

미리보기 (저장하려면 "이미지 업로드" 버튼을 클릭하세요)

+ `; + }; + reader.readAsDataURL(file); +} + +/** + * 레이아웃 이미지 업로드 + */ +async function uploadLayoutImage() { + const fileInput = document.getElementById('layoutImageFile'); + const file = fileInput.files[0]; + + if (!file) { + window.showToast('이미지 파일을 선택해주세요.', 'warning'); + return; + } + + const currentCategoryId = window.currentCategoryId; + + if (!currentCategoryId) { + window.showToast('공장을 먼저 선택해주세요.', 'error'); + return; + } + + try { + // FormData 생성 + const formData = new FormData(); + formData.append('image', file); + + // 업로드 요청 + const response = await fetch(`${window.API_BASE_URL || 'http://localhost:20005/api'}/workplaces/categories/${currentCategoryId}/layout-image`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token')}` + }, + body: formData + }); + + const result = await response.json(); + + if (result.success) { + window.showToast('이미지가 성공적으로 업로드되었습니다.', 'success'); + + // 이미지 경로를 전체 URL로 변환 + const fullImageUrl = `${window.API_BASE_URL || 'http://localhost:20005/api'}${result.data.image_path}`.replace('/api/', '/'); + + // 이미지를 캔버스에 로드 + loadImageToCanvas(fullImageUrl); + + // 현재 이미지 미리보기도 업데이트 + const currentImageDiv = document.getElementById('currentLayoutImage'); + if (currentImageDiv) { + currentImageDiv.innerHTML = ` + 현재 레이아웃 이미지 + `; + } + + // 카테고리 데이터 새로고침 (workplace-management.js의 loadCategories 함수 호출) + if (window.loadCategories) { + await window.loadCategories(); + + // 메인 페이지 미리보기도 업데이트 + const currentCategoryId = window.currentCategoryId; + const categories = window.categories; + if (currentCategoryId && categories && window.updateLayoutPreview) { + const category = categories.find(c => c.category_id == currentCategoryId); + if (category) { + window.updateLayoutPreview(category); + } + } + } + } else { + throw new Error(result.message || '업로드 실패'); + } + } catch (error) { + console.error('이미지 업로드 오류:', error); + window.showToast(error.message || '이미지 업로드 중 오류가 발생했습니다.', 'error'); + } +} + +// ==================== 영역 그리기 ==================== + +/** + * 캔버스 이벤트 설정 + */ +function setupCanvasEvents() { + canvas.addEventListener('mousedown', startDrawing); + canvas.addEventListener('mousemove', draw); + canvas.addEventListener('mouseup', stopDrawing); + canvas.addEventListener('mouseleave', stopDrawing); +} + +/** + * 그리기 시작 + */ +function startDrawing(e) { + const rect = canvas.getBoundingClientRect(); + startX = e.clientX - rect.left; + startY = e.clientY - rect.top; + isDrawing = true; +} + +/** + * 그리기 + */ +function draw(e) { + if (!isDrawing) return; + + const rect = canvas.getBoundingClientRect(); + const currentX = e.clientX - rect.left; + const currentY = e.clientY - rect.top; + + // 캔버스 다시 그리기 + ctx.clearRect(0, 0, canvas.width, canvas.height); + if (layoutMapImage) { + ctx.drawImage(layoutMapImage, 0, 0, canvas.width, canvas.height); + } + + // 기존 영역들 그리기 + drawExistingRegions(); + + // 현재 그리는 사각형 + const width = currentX - startX; + const height = currentY - startY; + + ctx.strokeStyle = '#3b82f6'; + ctx.lineWidth = 3; + ctx.strokeRect(startX, startY, width, height); + + ctx.fillStyle = 'rgba(59, 130, 246, 0.2)'; + ctx.fillRect(startX, startY, width, height); + + currentRect = { startX, startY, endX: currentX, endY: currentY }; +} + +/** + * 그리기 종료 + */ +function stopDrawing() { + isDrawing = false; +} + +/** + * 기존 영역들 그리기 + */ +function drawExistingRegions() { + mapRegions.forEach(region => { + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 2; + ctx.strokeRect(x1, y1, x2 - x1, y2 - y1); + + ctx.fillStyle = 'rgba(16, 185, 129, 0.15)'; + ctx.fillRect(x1, y1, x2 - x1, y2 - y1); + + // 작업장 이름 표시 + ctx.fillStyle = '#10b981'; + ctx.font = '14px sans-serif'; + ctx.fillText(region.workplace_name || '', x1 + 5, y1 + 20); + }); +} + +/** + * 현재 영역 지우기 + */ +function clearCurrentRegion() { + currentRect = null; + + // 캔버스 다시 그리기 + ctx.clearRect(0, 0, canvas.width, canvas.height); + if (layoutMapImage) { + ctx.drawImage(layoutMapImage, 0, 0, canvas.width, canvas.height); + } + drawExistingRegions(); +} + +/** + * 영역 저장 + */ +async function saveRegion() { + const workplaceId = document.getElementById('regionWorkplaceSelect').value; + + if (!workplaceId) { + window.showToast('작업장을 선택해주세요.', 'warning'); + return; + } + + if (!currentRect) { + window.showToast('영역을 그려주세요.', 'warning'); + return; + } + + const currentCategoryId = window.currentCategoryId; + + try { + // 비율로 변환 (0~100%) + const xStart = Math.min(currentRect.startX, currentRect.endX) / canvas.width * 100; + const yStart = Math.min(currentRect.startY, currentRect.endY) / canvas.height * 100; + const xEnd = Math.max(currentRect.startX, currentRect.endX) / canvas.width * 100; + const yEnd = Math.max(currentRect.startY, currentRect.endY) / canvas.height * 100; + + // 기존 영역이 있는지 확인 + const existingRegion = mapRegions.find(r => r.workplace_id == workplaceId); + + const regionData = { + workplace_id: parseInt(workplaceId), + category_id: parseInt(currentCategoryId), + x_start: xStart.toFixed(2), + y_start: yStart.toFixed(2), + x_end: xEnd.toFixed(2), + y_end: yEnd.toFixed(2), + shape: 'rect' + }; + + let response; + if (existingRegion) { + // 수정 + response = await window.apiCall(`/workplaces/map-regions/${existingRegion.region_id}`, 'PUT', regionData); + } else { + // 신규 등록 + response = await window.apiCall('/workplaces/map-regions', 'POST', regionData); + } + + if (response && response.success) { + window.showToast('영역이 성공적으로 저장되었습니다.', 'success'); + + // 데이터 새로고침 + await loadLayoutMapData(); + + // 현재 그림 초기화 + clearCurrentRegion(); + + // 작업장 선택 초기화 + document.getElementById('regionWorkplaceSelect').value = ''; + } else { + throw new Error(response?.message || '저장 실패'); + } + } catch (error) { + console.error('영역 저장 오류:', error); + window.showToast(error.message || '영역 저장 중 오류가 발생했습니다.', 'error'); + } +} + +/** + * 영역 목록 렌더링 + */ +function renderRegionList() { + const listDiv = document.getElementById('regionList'); + if (!listDiv) return; + + if (mapRegions.length === 0) { + listDiv.innerHTML = '

정의된 영역이 없습니다

'; + return; + } + + let listHtml = '
'; + + mapRegions.forEach(region => { + listHtml += ` +
+
+ ${region.workplace_name} + + (${region.x_start}%, ${region.y_start}%) ~ (${region.x_end}%, ${region.y_end}%) + +
+ +
+ `; + }); + + listHtml += '
'; + listDiv.innerHTML = listHtml; +} + +/** + * 영역 삭제 + */ +async function deleteRegion(regionId) { + if (!confirm('이 영역을 삭제하시겠습니까?')) { + return; + } + + try { + const response = await window.apiCall(`/workplaces/map-regions/${regionId}`, 'DELETE'); + + if (response && response.success) { + window.showToast('영역이 삭제되었습니다.', 'success'); + await loadLayoutMapData(); + } else { + throw new Error(response?.message || '삭제 실패'); + } + } catch (error) { + console.error('영역 삭제 오류:', error); + window.showToast(error.message || '영역 삭제 중 오류가 발생했습니다.', 'error'); + } +} + +// 전역 함수로 노출 +window.openLayoutMapModal = openLayoutMapModal; +window.closeLayoutMapModal = closeLayoutMapModal; +window.previewLayoutImage = previewLayoutImage; +window.uploadLayoutImage = uploadLayoutImage; +window.clearCurrentRegion = clearCurrentRegion; +window.saveRegion = saveRegion; +window.deleteRegion = deleteRegion; diff --git a/deploy/tkfb-package/web-ui/js/workplace-management.js b/deploy/tkfb-package/web-ui/js/workplace-management.js new file mode 100644 index 0000000..2fbcff4 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/workplace-management.js @@ -0,0 +1,2254 @@ +// 작업장 관리 페이지 JavaScript +// +// 참고: 이 파일은 점진적 마이그레이션 중입니다. +// 새로운 모듈 시스템: /js/workplace-management/ +// - state.js: 전역 상태 관리 +// - utils.js: 유틸리티 함수 +// - api.js: API 클라이언트 +// - index.js: 메인 컨트롤러 + +// 전역 변수 (모듈 시스템이 없을 때만 사용) +let categories = window.WorkplaceState?.categories || []; +let workplaces = window.WorkplaceState?.workplaces || []; +let currentCategoryId = window.WorkplaceState?.currentCategoryId || ''; +let currentEditingCategory = null; +let currentEditingWorkplace = null; + +// 페이지 초기화 (모듈 시스템이 없을 때만) +document.addEventListener('DOMContentLoaded', function() { + // 모듈 시스템이 이미 로드되어 있으면 초기화 건너뜀 + if (window.WorkplaceController) { + console.log('[workplace-management.js] 모듈 시스템 감지 - 기존 초기화 건너뜀'); + return; + } + + console.log('🏗️ 작업장 관리 페이지 초기화 시작 (레거시)'); + loadAllData(); +}); + +// 모든 데이터 로드 +async function loadAllData() { + // 모듈 시스템이 있으면 위임 + if (window.WorkplaceController) { + return window.WorkplaceController.loadAllData(); + } + + try { + await Promise.all([ + loadCategories(), + loadWorkplaces() + ]); + + renderCategoryTabs(); + renderWorkplaces(); + updateStatistics(); + } catch (error) { + console.error('데이터 로딩 오류:', error); + showToast('데이터를 불러오는데 실패했습니다.', 'error'); + } +} + +// ==================== 카테고리(공장) 관련 ==================== + +// 카테고리 목록 로드 +async function loadCategories() { + // 모듈 시스템이 있으면 위임 + if (window.WorkplaceAPI) { + const result = await window.WorkplaceAPI.loadCategories(); + categories = window.WorkplaceState?.categories || result; + return result; + } + + try { + const response = await window.apiCall('/workplaces/categories', 'GET'); + + let categoryData = []; + if (response && response.success && Array.isArray(response.data)) { + categoryData = response.data; + } else if (Array.isArray(response)) { + categoryData = response; + } + + categories = categoryData; + console.log(`✅ 카테고리 ${categories.length}개 로드 완료`); + } catch (error) { + console.error('카테고리 로딩 오류:', error); + categories = []; + } +} + +// 카테고리 탭 렌더링 +function renderCategoryTabs() { + const tabsContainer = document.getElementById('categoryTabs'); + if (!tabsContainer) return; + + // 전체 탭은 항상 표시 + let tabsHtml = ` + + `; + + // 각 카테고리 탭 추가 + categories.forEach(category => { + const count = workplaces.filter(w => w.category_id === category.category_id).length; + const isActive = currentCategoryId === category.category_id; + + tabsHtml += ` + + `; + }); + + tabsContainer.innerHTML = tabsHtml; +} + +// 카테고리 전환 +function switchCategory(categoryId) { + currentCategoryId = categoryId === '' ? '' : categoryId; + renderCategoryTabs(); + renderWorkplaces(); + + // 레이아웃 지도 섹션 표시/숨김 + const layoutMapSection = document.getElementById('layoutMapSection'); + const selectedCategoryName = document.getElementById('selectedCategoryName'); + + if (currentCategoryId && layoutMapSection) { + const category = categories.find(c => c.category_id == currentCategoryId); + if (category) { + layoutMapSection.style.display = 'block'; + if (selectedCategoryName) { + selectedCategoryName.textContent = category.category_name; + } + + // 레이아웃 미리보기 업데이트 + updateLayoutPreview(category); + } + } else if (layoutMapSection) { + layoutMapSection.style.display = 'none'; + } +} + +// 레이아웃 미리보기 업데이트 +async function updateLayoutPreview(category) { + const previewDiv = document.getElementById('layoutMapPreview'); + if (!previewDiv) return; + + if (category.layout_image) { + // 이미지 경로를 전체 URL로 변환 + const fullImageUrl = category.layout_image.startsWith('http') + ? category.layout_image + : `${window.API_BASE_URL || 'http://localhost:20005/api'}${category.layout_image}`.replace('/api/', '/'); + + // Canvas 컨테이너 생성 + previewDiv.innerHTML = ` +
+ +

+ 클릭하여 작업장 영역을 수정하려면 "지도 설정" 버튼을 누르세요 +

+
+ `; + + // 이미지와 영역 로드 + await loadImageWithRegions(fullImageUrl, category.category_id); + } else { + previewDiv.innerHTML = ` +
+ 🗺️ +

+ 이 공장의 레이아웃 이미지가 아직 등록되지 않았습니다 +

+

+ "지도 설정" 버튼을 눌러 레이아웃 이미지를 업로드하고 작업장 위치를 지정하세요 +

+
+ `; + } +} + +// 이미지와 영역을 캔버스에 로드 +async function loadImageWithRegions(imageUrl, categoryId) { + const canvas = document.getElementById('previewCanvas'); + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + const img = new Image(); + + img.onload = async function() { + // 최대 너비 설정 (반응형) + const maxWidth = 800; + const scale = img.width > maxWidth ? maxWidth / img.width : 1; + + canvas.width = img.width * scale; + canvas.height = img.height * scale; + + // 이미지 그리기 + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + + // 영역 데이터 로드 및 그리기 + try { + const response = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`, 'GET'); + + let regions = []; + if (response && response.success && Array.isArray(response.data)) { + regions = response.data; + } else if (Array.isArray(response)) { + regions = response; + } + + // 각 영역 그리기 + regions.forEach(region => { + // 퍼센트를 픽셀로 변환 + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + const width = x2 - x1; + const height = y2 - y1; + + // 영역 테두리 그리기 + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 2; + ctx.strokeRect(x1, y1, width, height); + + // 영역 배경 (반투명) + ctx.fillStyle = 'rgba(16, 185, 129, 0.15)'; + ctx.fillRect(x1, y1, width, height); + + // 작업장 이름 표시 + if (region.workplace_name) { + ctx.fillStyle = '#10b981'; + ctx.font = 'bold 14px sans-serif'; + + // 텍스트 배경 + const textMetrics = ctx.measureText(region.workplace_name); + const textPadding = 4; + ctx.fillStyle = 'rgba(255, 255, 255, 0.9)'; + ctx.fillRect(x1 + 5, y1 + 5, textMetrics.width + textPadding * 2, 20); + + // 텍스트 + ctx.fillStyle = '#10b981'; + ctx.fillText(region.workplace_name, x1 + 5 + textPadding, y1 + 20); + } + }); + + if (regions.length > 0) { + console.log(`✅ 레이아웃 미리보기에 ${regions.length}개 영역 표시 완료`); + } + } catch (error) { + console.error('영역 로드 오류:', error); + } + }; + + img.onerror = function() { + console.error('이미지 로드 실패:', imageUrl); + }; + + img.src = imageUrl; +} + +// 작업장 카드에 지도 썸네일 로드 +async function loadWorkplaceMapThumbnail(workplace) { + const thumbnailDiv = document.getElementById(`workplace-map-${workplace.workplace_id}`); + if (!thumbnailDiv) return; + + // 작업장 자체에 레이아웃 이미지가 있는 경우 + if (workplace.layout_image) { + const fullImageUrl = workplace.layout_image.startsWith('http') + ? workplace.layout_image + : `${window.API_BASE_URL || 'http://localhost:20005/api'}${workplace.layout_image}`.replace('/api/', '/'); + + // 설비 정보 로드 + let equipmentCount = 0; + try { + const eqResponse = await window.apiCall(`/equipments/workplace/${workplace.workplace_id}`, 'GET'); + if (eqResponse && eqResponse.success && Array.isArray(eqResponse.data)) { + equipmentCount = eqResponse.data.filter(eq => eq.map_x_percent != null).length; + } + } catch (e) { + console.debug('설비 정보 로드 실패'); + } + + const canvasId = `layout-canvas-${workplace.workplace_id}`; + thumbnailDiv.innerHTML = ` +
+
+ 📍 작업장 지도 + ${equipmentCount > 0 ? `설비 ${equipmentCount}개` : ''} +
+ +
클릭하여 지도 관리
+
+ `; + + // 캔버스에 이미지 및 설비 영역 그리기 + await loadWorkplaceCanvasWithEquipments(workplace.workplace_id, fullImageUrl, canvasId); + return; + } + + // 작업장에 이미지가 없으면 카테고리 지도의 영역 표시 + try { + // 해당 작업장의 지도 영역 정보 가져오기 + const response = await window.apiCall(`/workplaces/map-regions/workplace/${workplace.workplace_id}`, 'GET'); + + if (!response || (!response.success && !response.region_id)) { + // 영역이 정의되지 않은 경우 지도 업로드 안내 표시 + thumbnailDiv.innerHTML = ` +
+
🗺️
+
클릭하여 지도 설정
+
+ `; + return; + } + + const region = response.success ? response.data : response; + + // 영역 좌표 데이터가 없으면 종료 + if (!region || region.x_start === undefined || region.y_start === undefined || + region.x_end === undefined || region.y_end === undefined) { + return; + } + + // 카테고리 정보에서 레이아웃 이미지 가져오기 + const category = categories.find(c => c.category_id === workplace.category_id); + if (!category || !category.layout_image) return; + + const fullImageUrl = category.layout_image.startsWith('http') + ? category.layout_image + : `${window.API_BASE_URL || 'http://localhost:20005/api'}${category.layout_image}`.replace('/api/', '/'); + + // 캔버스 생성 + const canvasId = `thumbnail-canvas-${workplace.workplace_id}`; + thumbnailDiv.innerHTML = ` +
+
📍 공장 지도 내 위치
+ +
클릭하여 상세 지도 설정
+
+ `; + + // 이미지 로드 + const img = new Image(); + img.onload = function() { + const canvas = document.getElementById(canvasId); + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + + // 원본 이미지에서 영역 좌표 계산 (퍼센트를 픽셀로) + const x1 = (region.x_start / 100) * img.width; + const y1 = (region.y_start / 100) * img.height; + const x2 = (region.x_end / 100) * img.width; + const y2 = (region.y_end / 100) * img.height; + + const regionWidth = x2 - x1; + const regionHeight = y2 - y1; + + // 썸네일 크기 설정 (최대 너비 350px) + const maxThumbWidth = 350; + const scale = regionWidth > maxThumbWidth ? maxThumbWidth / regionWidth : 1; + + canvas.width = regionWidth * scale; + canvas.height = regionHeight * scale; + + // 영역만 잘라서 그리기 + ctx.drawImage( + img, + x1, y1, regionWidth, regionHeight, // 원본에서 잘라낼 영역 + 0, 0, canvas.width, canvas.height // 캔버스에 그릴 위치와 크기 + ); + + // 테두리 그리기 + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 3; + ctx.strokeRect(0, 0, canvas.width, canvas.height); + }; + + img.onerror = function() { + thumbnailDiv.innerHTML = ''; + }; + + img.src = fullImageUrl; + } catch (error) { + // 오류 시 조용히 처리 (지도가 없는 작업장도 많을 수 있으므로) + console.debug(`작업장 ${workplace.workplace_id}의 지도 영역 없음`); + } +} + +// 작업장 캔버스에 설비 영역 함께 그리기 +async function loadWorkplaceCanvasWithEquipments(workplaceId, imageUrl, canvasId) { + const img = new Image(); + img.onload = async function() { + const canvas = document.getElementById(canvasId); + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + + // 썸네일 크기 설정 (최대 너비 400px) + const maxThumbWidth = 400; + const scale = img.width > maxThumbWidth ? maxThumbWidth / img.width : 1; + + canvas.width = img.width * scale; + canvas.height = img.height * scale; + + // 이미지 그리기 + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + + // 설비 영역 로드 및 그리기 + try { + const response = await window.apiCall(`/equipments/workplace/${workplaceId}`, 'GET'); + let equipments = []; + if (response && response.success && Array.isArray(response.data)) { + equipments = response.data.filter(eq => eq.map_x_percent != null); + } + + // 설비 영역 그리기 + equipments.forEach(eq => { + const x = (parseFloat(eq.map_x_percent) / 100) * canvas.width; + const y = (parseFloat(eq.map_y_percent) / 100) * canvas.height; + const width = (parseFloat(eq.map_width_percent || 10) / 100) * canvas.width; + const height = (parseFloat(eq.map_height_percent || 10) / 100) * canvas.height; + + // 영역 배경 + ctx.fillStyle = 'rgba(16, 185, 129, 0.2)'; + ctx.fillRect(x, y, width, height); + + // 영역 테두리 + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 2; + ctx.strokeRect(x, y, width, height); + + // 설비 코드 표시 + if (eq.equipment_code) { + ctx.font = 'bold 10px sans-serif'; + const textMetrics = ctx.measureText(eq.equipment_code); + ctx.fillStyle = 'rgba(255, 255, 255, 0.9)'; + ctx.fillRect(x + 2, y + 2, textMetrics.width + 6, 14); + ctx.fillStyle = '#047857'; + ctx.fillText(eq.equipment_code, x + 5, y + 12); + } + }); + } catch (error) { + console.debug('설비 영역 로드 실패'); + } + }; + img.src = imageUrl; +} + +// 카테고리 모달 열기 +function openCategoryModal(categoryData = null) { + const modal = document.getElementById('categoryModal'); + const modalTitle = document.getElementById('categoryModalTitle'); + const deleteBtn = document.getElementById('deleteCategoryBtn'); + + if (!modal) return; + + currentEditingCategory = categoryData; + + if (categoryData) { + // 수정 모드 + modalTitle.textContent = '공장 수정'; + deleteBtn.style.display = 'inline-flex'; + + document.getElementById('categoryId').value = categoryData.category_id; + document.getElementById('categoryName').value = categoryData.category_name || ''; + document.getElementById('categoryDescription').value = categoryData.description || ''; + document.getElementById('categoryOrder').value = categoryData.display_order || 0; + } else { + // 신규 등록 모드 + modalTitle.textContent = '공장 추가'; + deleteBtn.style.display = 'none'; + + document.getElementById('categoryForm').reset(); + document.getElementById('categoryId').value = ''; + } + + modal.style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + setTimeout(() => { + document.getElementById('categoryName').focus(); + }, 100); +} + +// 카테고리 모달 닫기 +function closeCategoryModal() { + const modal = document.getElementById('categoryModal'); + if (modal) { + modal.style.display = 'none'; + document.body.style.overflow = ''; + currentEditingCategory = null; + } +} + +// 카테고리 저장 +async function saveCategory() { + try { + const categoryId = document.getElementById('categoryId').value; + + const categoryData = { + category_name: document.getElementById('categoryName').value.trim(), + description: document.getElementById('categoryDescription').value.trim() || null, + display_order: parseInt(document.getElementById('categoryOrder').value) || 0, + is_active: true + }; + + if (!categoryData.category_name) { + showToast('공장명은 필수 입력 항목입니다.', 'error'); + return; + } + + console.log('💾 저장할 카테고리 데이터:', categoryData); + + let response; + if (categoryId) { + // 수정 + response = await window.apiCall(`/workplaces/categories/${categoryId}`, 'PUT', categoryData); + } else { + // 신규 등록 + response = await window.apiCall('/workplaces/categories', 'POST', categoryData); + } + + if (response && (response.success || response.category_id)) { + const action = categoryId ? '수정' : '등록'; + showToast(`공장이 성공적으로 ${action}되었습니다.`, 'success'); + + closeCategoryModal(); + await loadAllData(); + } else { + throw new Error(response?.message || '저장에 실패했습니다.'); + } + } catch (error) { + console.error('카테고리 저장 오류:', error); + showToast(error.message || '카테고리 저장 중 오류가 발생했습니다.', 'error'); + } +} + +// 카테고리 삭제 +async function deleteCategory() { + if (!currentEditingCategory) return; + + if (!confirm(`"${currentEditingCategory.category_name}" 공장을 정말 삭제하시겠습니까?\n\n⚠️ 이 공장에 속한 모든 작업장의 공장 정보가 제거됩니다.`)) { + return; + } + + try { + const response = await window.apiCall(`/workplaces/categories/${currentEditingCategory.category_id}`, 'DELETE'); + + if (response && response.success) { + showToast('공장이 성공적으로 삭제되었습니다.', 'success'); + + closeCategoryModal(); + await loadAllData(); + } else { + throw new Error(response?.message || '삭제에 실패했습니다.'); + } + } catch (error) { + console.error('카테고리 삭제 오류:', error); + showToast(error.message || '카테고리 삭제 중 오류가 발생했습니다.', 'error'); + } +} + +// ==================== 작업장 관련 ==================== + +// 작업장 목록 로드 +async function loadWorkplaces() { + try { + const response = await window.apiCall('/workplaces', 'GET'); + + let workplaceData = []; + if (response && response.success && Array.isArray(response.data)) { + workplaceData = response.data; + } else if (Array.isArray(response)) { + workplaceData = response; + } + + workplaces = workplaceData; + console.log(`✅ 작업장 ${workplaces.length}개 로드 완료`); + } catch (error) { + console.error('작업장 로딩 오류:', error); + workplaces = []; + } +} + +// 작업장 렌더링 +function renderWorkplaces() { + const grid = document.getElementById('workplaceGrid'); + if (!grid) return; + + // 현재 카테고리별 필터링 + const filtered = currentCategoryId === '' + ? workplaces + : workplaces.filter(w => w.category_id == currentCategoryId); + + if (filtered.length === 0) { + grid.innerHTML = ` +
+
🏗️
+

등록된 작업장이 없습니다

+

"작업장 추가" 버튼을 눌러 작업장을 등록해보세요

+ +
+ `; + return; + } + + let gridHtml = ''; + + filtered.forEach(workplace => { + const categoryName = workplace.category_name || '미분류'; + const isActive = workplace.is_active === 1 || workplace.is_active === true; + + // 작업장 용도 아이콘 매핑 + const purposeIcons = { + '작업구역': '🔧', + '설비': '⚙️', + '휴게시설': '☕', + '회의실': '💼', + '창고': '📦', + '기타': '📍' + }; + const purposeIcon = workplace.workplace_purpose ? purposeIcons[workplace.workplace_purpose] || '📍' : '🏗️'; + + gridHtml += ` +
+
+
${purposeIcon}
+
+

${workplace.workplace_name}

+
+ ${workplace.category_id ? `🏭 ${categoryName}` : ''} + ${workplace.workplace_purpose ? `${workplace.workplace_purpose}` : ''} +
+
+
+ + + +
+
+ ${workplace.description ? `

${workplace.description}

` : ''} +
+
+ 등록: ${formatDate(workplace.created_at)} + ${workplace.updated_at !== workplace.created_at ? `수정: ${formatDate(workplace.updated_at)}` : ''} +
+
+ `; + }); + + grid.innerHTML = gridHtml; + + // 각 작업장의 지도 미리보기 로드 + filtered.forEach(workplace => { + if (workplace.category_id) { + loadWorkplaceMapThumbnail(workplace); + } + }); +} + +// 작업장 모달 열기 +function openWorkplaceModal(workplaceData = null) { + const modal = document.getElementById('workplaceModal'); + const modalTitle = document.getElementById('workplaceModalTitle'); + const deleteBtn = document.getElementById('deleteWorkplaceBtn'); + const categorySelect = document.getElementById('workplaceCategoryId'); + + if (!modal) return; + + currentEditingWorkplace = workplaceData; + + // 카테고리 선택 옵션 업데이트 + let categoryOptions = ''; + categories.forEach(cat => { + categoryOptions += ``; + }); + categorySelect.innerHTML = categoryOptions; + + if (workplaceData) { + // 수정 모드 + modalTitle.textContent = '작업장 수정'; + deleteBtn.style.display = 'inline-flex'; + + document.getElementById('workplaceId').value = workplaceData.workplace_id; + document.getElementById('workplaceCategoryId').value = workplaceData.category_id || ''; + document.getElementById('workplaceName').value = workplaceData.workplace_name || ''; + document.getElementById('workplacePurpose').value = workplaceData.workplace_purpose || ''; + document.getElementById('displayPriority').value = workplaceData.display_priority || 0; + document.getElementById('workplaceDescription').value = workplaceData.description || ''; + } else { + // 신규 등록 모드 + modalTitle.textContent = '작업장 추가'; + deleteBtn.style.display = 'none'; + + document.getElementById('workplaceForm').reset(); + document.getElementById('workplaceId').value = ''; + + // 현재 선택된 카테고리가 있으면 자동 선택 + if (currentCategoryId) { + document.getElementById('workplaceCategoryId').value = currentCategoryId; + } + } + + modal.style.display = 'flex'; + document.body.style.overflow = 'hidden'; + + setTimeout(() => { + document.getElementById('workplaceName').focus(); + }, 100); +} + +// 작업장 모달 닫기 +function closeWorkplaceModal() { + const modal = document.getElementById('workplaceModal'); + if (modal) { + modal.style.display = 'none'; + document.body.style.overflow = ''; + currentEditingWorkplace = null; + } +} + +// 작업장 편집 +function editWorkplace(workplaceId) { + const workplace = workplaces.find(w => w.workplace_id === workplaceId); + if (workplace) { + openWorkplaceModal(workplace); + } else { + showToast('작업장을 찾을 수 없습니다.', 'error'); + } +} + +// 작업장 저장 +async function saveWorkplace() { + try { + const workplaceId = document.getElementById('workplaceId').value; + + const workplaceData = { + category_id: document.getElementById('workplaceCategoryId').value || null, + workplace_name: document.getElementById('workplaceName').value.trim(), + workplace_purpose: document.getElementById('workplacePurpose').value || null, + display_priority: parseInt(document.getElementById('displayPriority').value) || 0, + description: document.getElementById('workplaceDescription').value.trim() || null, + is_active: true + }; + + if (!workplaceData.workplace_name) { + showToast('작업장명은 필수 입력 항목입니다.', 'error'); + return; + } + + console.log('💾 저장할 작업장 데이터:', workplaceData); + + let response; + if (workplaceId) { + // 수정 + response = await window.apiCall(`/workplaces/${workplaceId}`, 'PUT', workplaceData); + } else { + // 신규 등록 + response = await window.apiCall('/workplaces', 'POST', workplaceData); + } + + if (response && (response.success || response.workplace_id)) { + const action = workplaceId ? '수정' : '등록'; + showToast(`작업장이 성공적으로 ${action}되었습니다.`, 'success'); + + closeWorkplaceModal(); + await loadAllData(); + } else { + throw new Error(response?.message || '저장에 실패했습니다.'); + } + } catch (error) { + console.error('작업장 저장 오류:', error); + showToast(error.message || '작업장 저장 중 오류가 발생했습니다.', 'error'); + } +} + +// 작업장 삭제 확인 +function confirmDeleteWorkplace(workplaceId) { + const workplace = workplaces.find(w => w.workplace_id === workplaceId); + + if (!workplace) { + showToast('작업장을 찾을 수 없습니다.', 'error'); + return; + } + + if (confirm(`"${workplace.workplace_name}" 작업장을 정말 삭제하시겠습니까?\n\n⚠️ 삭제된 작업장은 복구할 수 없습니다.`)) { + deleteWorkplaceById(workplaceId); + } +} + +// 작업장 삭제 (수정 모드에서) +function deleteWorkplace() { + if (currentEditingWorkplace) { + confirmDeleteWorkplace(currentEditingWorkplace.workplace_id); + } +} + +// 작업장 삭제 실행 +async function deleteWorkplaceById(workplaceId) { + try { + const response = await window.apiCall(`/workplaces/${workplaceId}`, 'DELETE'); + + if (response && response.success) { + showToast('작업장이 성공적으로 삭제되었습니다.', 'success'); + + closeWorkplaceModal(); + await loadAllData(); + } else { + throw new Error(response?.message || '삭제에 실패했습니다.'); + } + } catch (error) { + console.error('작업장 삭제 오류:', error); + showToast(error.message || '작업장 삭제 중 오류가 발생했습니다.', 'error'); + } +} + +// ==================== 유틸리티 ==================== + +// 전체 새로고침 +async function refreshWorkplaces() { + const refreshBtn = document.querySelector('.btn-secondary'); + if (refreshBtn) { + const originalText = refreshBtn.innerHTML; + refreshBtn.innerHTML = '새로고침 중...'; + refreshBtn.disabled = true; + + await loadAllData(); + + refreshBtn.innerHTML = originalText; + refreshBtn.disabled = false; + } else { + await loadAllData(); + } + + showToast('데이터가 새로고침되었습니다.', 'success'); +} + +// 통계 업데이트 +async function updateStatistics() { + const total = workplaces.length; + const active = workplaces.filter(w => w.is_active === 1 || w.is_active === true).length; + const factoryTotal = categories.length; + + // 상단 통계 카드 업데이트 + const factoryCountEl = document.getElementById('factoryCount'); + const totalCountEl = document.getElementById('totalCount'); + const activeCountEl = document.getElementById('activeCount'); + const equipmentCountEl = document.getElementById('equipmentCount'); + + if (factoryCountEl) factoryCountEl.textContent = factoryTotal; + if (totalCountEl) totalCountEl.textContent = total; + if (activeCountEl) activeCountEl.textContent = active; + + // 설비 수 조회 및 업데이트 + if (equipmentCountEl) { + try { + const response = await window.apiCall('/equipments', 'GET'); + let equipmentCount = 0; + if (response && response.success && Array.isArray(response.data)) { + equipmentCount = response.data.length; + } else if (Array.isArray(response)) { + equipmentCount = response.length; + } + equipmentCountEl.textContent = equipmentCount; + } catch (e) { + equipmentCountEl.textContent = '-'; + } + } + + // 섹션 통계 업데이트 + const sectionTotalEl = document.getElementById('sectionTotalCount'); + const sectionActiveEl = document.getElementById('sectionActiveCount'); + + // 현재 필터링된 작업장 기준 + const filtered = currentCategoryId === '' + ? workplaces + : workplaces.filter(w => w.category_id == currentCategoryId); + const filteredActive = filtered.filter(w => w.is_active === 1 || w.is_active === true).length; + + if (sectionTotalEl) sectionTotalEl.textContent = filtered.length; + if (sectionActiveEl) sectionActiveEl.textContent = filteredActive; +} + +// 날짜 포맷팅 +function formatDate(dateString) { + if (!dateString) return ''; + + const date = new Date(dateString); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }); +} + +// 토스트 메시지 표시 +function showToast(message, type = 'info') { + // 기존 토스트 제거 + const existingToast = document.querySelector('.toast'); + if (existingToast) { + existingToast.remove(); + } + + // 새 토스트 생성 + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + + // 스타일 적용 + Object.assign(toast.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '12px 24px', + borderRadius: '8px', + color: 'white', + fontWeight: '500', + zIndex: '1000', + transform: 'translateX(100%)', + transition: 'transform 0.3s ease' + }); + + // 타입별 배경색 + const colors = { + success: '#10b981', + error: '#ef4444', + warning: '#f59e0b', + info: '#3b82f6' + }; + toast.style.backgroundColor = colors[type] || colors.info; + + document.body.appendChild(toast); + + // 애니메이션 + setTimeout(() => { + toast.style.transform = 'translateX(0)'; + }, 100); + + // 자동 제거 + setTimeout(() => { + toast.style.transform = 'translateX(100%)'; + setTimeout(() => { + if (toast.parentNode) { + toast.remove(); + } + }, 300); + }, 3000); +} + +// 전역 함수 및 변수로 노출 (다른 모듈에서 접근 가능하도록) +// 모듈 시스템이 이미 정의했으면 건너뜀 +if (!window.WorkplaceState) { + // getter/setter를 사용하여 항상 최신 값을 반환 + Object.defineProperty(window, 'categories', { + get: function() { + return categories; + } + }); + + Object.defineProperty(window, 'workplaces', { + get: function() { + return workplaces; + } + }); + + Object.defineProperty(window, 'currentCategoryId', { + get: function() { + return currentCategoryId; + }, + set: function(value) { + currentCategoryId = value; + } + }); +} + +// ==================== 작업장 지도 관리 ==================== + +// 작업장 지도 관련 전역 변수 +let workplaceCanvas = null; +let workplaceCtx = null; +let workplaceImage = null; +let workplaceIsDrawing = false; +let workplaceStartX = 0; +let workplaceStartY = 0; +let workplaceCurrentRect = null; +let workplaceEquipmentRegions = []; +let existingEquipments = []; // DB에서 로드한 기존 설비 목록 +let allEquipments = []; // 시스템 전체 설비 목록 (드롭다운 선택용) + +// 작업장 지도 모달 열기 +async function openWorkplaceMapModal(workplaceId) { + const workplace = workplaces.find(w => w.workplace_id === workplaceId); + if (!workplace) { + showToast('작업장 정보를 찾을 수 없습니다.', 'error'); + return; + } + + // 작업장 이름 설정 + const modalTitle = document.getElementById('workplaceMapModalTitle'); + if (modalTitle) { + modalTitle.textContent = `${workplace.workplace_name} - 지도 관리`; + } + + // 현재 작업장 ID 저장 + window.currentWorkplaceMapId = workplaceId; + + // 레이아웃 이미지 미리보기 영역 초기화 + const preview = document.getElementById('workplaceLayoutPreview'); + if (preview && workplace.layout_image) { + const fullImageUrl = workplace.layout_image.startsWith('http') + ? workplace.layout_image + : `${window.API_BASE_URL || 'http://localhost:20005/api'}${workplace.layout_image}`.replace('/api/', '/'); + preview.innerHTML = `작업장 레이아웃`; + + // 캔버스 초기화 + initWorkplaceCanvas(fullImageUrl); + } else if (preview) { + preview.innerHTML = '

레이아웃 이미지를 업로드해주세요

'; + } + + // 설비 영역 목록 로드 (API 연동) + await Promise.all([ + loadWorkplaceEquipments(workplaceId), + loadAllEquipments() + ]); + renderWorkplaceEquipmentList(); + + // 모달 표시 + const modal = document.getElementById('workplaceMapModal'); + if (modal) { + modal.style.display = 'flex'; + } +} + +// 작업장의 설비 목록 로드 +async function loadWorkplaceEquipments(workplaceId) { + try { + const response = await window.apiCall(`/equipments/workplace/${workplaceId}`, 'GET'); + + let equipments = []; + if (response && response.success && Array.isArray(response.data)) { + equipments = response.data; + } else if (Array.isArray(response)) { + equipments = response; + } + + // 지도 영역이 있는 설비만 workplaceEquipmentRegions에 추가 + workplaceEquipmentRegions = equipments + .filter(eq => eq.map_x_percent != null && eq.map_y_percent != null) + .map(eq => ({ + equipment_id: eq.equipment_id, + equipment_name: eq.equipment_name, + equipment_code: eq.equipment_code, + x_percent: parseFloat(eq.map_x_percent), + y_percent: parseFloat(eq.map_y_percent), + width_percent: parseFloat(eq.map_width_percent) || 10, + height_percent: parseFloat(eq.map_height_percent) || 10 + })); + + // 해당 작업장에 할당된 설비 목록 저장 + existingEquipments = equipments; + + console.log(`✅ 작업장 ${workplaceId}의 설비 ${equipments.length}개 로드 완료 (지도 영역: ${workplaceEquipmentRegions.length}개)`); + } catch (error) { + console.error('설비 로드 오류:', error); + workplaceEquipmentRegions = []; + existingEquipments = []; + } +} + +// 시스템 전체 설비 목록 로드 (드롭다운 선택용) +async function loadAllEquipments() { + try { + const response = await window.apiCall('/equipments', 'GET'); + + let equipments = []; + if (response && response.success && Array.isArray(response.data)) { + equipments = response.data; + } else if (Array.isArray(response)) { + equipments = response; + } + + allEquipments = equipments; + console.log(`✅ 전체 설비 ${allEquipments.length}개 로드 완료`); + } catch (error) { + console.error('전체 설비 로드 오류:', error); + allEquipments = []; + } +} + +// 작업장 지도 모달 닫기 +function closeWorkplaceMapModal() { + const modal = document.getElementById('workplaceMapModal'); + if (modal) { + modal.style.display = 'none'; + } + window.currentWorkplaceMapId = null; +} + +// 작업장 레이아웃 이미지 업로드 +async function uploadWorkplaceLayout() { + const fileInput = document.getElementById('workplaceLayoutFile'); + if (!fileInput || !fileInput.files || !fileInput.files[0]) { + showToast('파일을 선택해주세요.', 'warning'); + return; + } + + if (!window.currentWorkplaceMapId) { + showToast('작업장 정보를 찾을 수 없습니다.', 'error'); + return; + } + + const formData = new FormData(); + formData.append('image', fileInput.files[0]); + + try { + showToast('이미지 업로드 중...', 'info'); + + const response = await fetch(`${window.API_BASE_URL || 'http://localhost:20005/api'}/workplaces/${window.currentWorkplaceMapId}/layout-image`, { + method: 'POST', + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token')}` + }, + body: formData + }); + + const result = await response.json(); + + if (result.success) { + showToast('레이아웃 이미지가 업로드되었습니다.', 'success'); + + // 작업장 목록 새로고침 + await loadWorkplaces(); + renderWorkplaces(); + + // 미리보기 업데이트 및 캔버스 초기화 + const preview = document.getElementById('workplaceLayoutPreview'); + if (preview && result.data.image_path) { + const fullImageUrl = result.data.image_path.startsWith('http') + ? result.data.image_path + : `${window.API_BASE_URL || 'http://localhost:20005/api'}${result.data.image_path}`.replace('/api/', '/'); + preview.innerHTML = `작업장 레이아웃`; + + // 캔버스 초기화 (설비 영역 편집용) + initWorkplaceCanvas(fullImageUrl); + } + + // 파일 입력 초기화 + fileInput.value = ''; + } else { + showToast(result.message || '업로드 실패', 'error'); + } + } catch (error) { + console.error('레이아웃 이미지 업로드 오류:', error); + showToast('레이아웃 이미지 업로드 중 오류가 발생했습니다.', 'error'); + } +} + +// 작업장 캔버스 초기화 +function initWorkplaceCanvas(imageUrl) { + const img = new Image(); + img.onload = function() { + workplaceImage = img; + workplaceCanvas = document.getElementById('workplaceRegionCanvas'); + if (!workplaceCanvas) return; + + workplaceCtx = workplaceCanvas.getContext('2d'); + + // 캔버스 크기 설정 (최대 너비를 모달 크기에 맞게) + const container = document.getElementById('workplaceCanvasContainer'); + const maxWidth = container ? Math.min(container.clientWidth - 20, 900) : 800; + const scale = img.width > maxWidth ? maxWidth / img.width : 1; + + workplaceCanvas.width = img.width * scale; + workplaceCanvas.height = img.height * scale; + + // 이미지 그리기 + workplaceCtx.drawImage(img, 0, 0, workplaceCanvas.width, workplaceCanvas.height); + + // 기존 영역들 표시 + drawWorkplaceRegions(); + + // 이벤트 리스너 등록 (기존 리스너 제거 후 등록) + workplaceCanvas.onmousedown = startWorkplaceDraw; + workplaceCanvas.onmousemove = drawWorkplace; + workplaceCanvas.onmouseup = endWorkplaceDraw; + workplaceCanvas.onmouseleave = endWorkplaceDraw; + + // 터치 이벤트 지원 + workplaceCanvas.ontouchstart = handleWorkplaceTouchStart; + workplaceCanvas.ontouchmove = handleWorkplaceTouchMove; + workplaceCanvas.ontouchend = endWorkplaceDraw; + }; + img.onerror = function() { + console.error('작업장 이미지 로드 실패:', imageUrl); + }; + img.src = imageUrl; +} + +// 터치 이벤트 핸들러 +function handleWorkplaceTouchStart(e) { + e.preventDefault(); + const touch = e.touches[0]; + const rect = workplaceCanvas.getBoundingClientRect(); + workplaceIsDrawing = true; + workplaceStartX = touch.clientX - rect.left; + workplaceStartY = touch.clientY - rect.top; +} + +function handleWorkplaceTouchMove(e) { + e.preventDefault(); + if (!workplaceIsDrawing) return; + + const touch = e.touches[0]; + const rect = workplaceCanvas.getBoundingClientRect(); + const currentX = touch.clientX - rect.left; + const currentY = touch.clientY - rect.top; + + // 캔버스 초기화 및 이미지 다시 그리기 + workplaceCtx.drawImage(workplaceImage, 0, 0, workplaceCanvas.width, workplaceCanvas.height); + drawWorkplaceRegions(); + + // 현재 그리는 사각형 + workplaceCtx.strokeStyle = '#3b82f6'; + workplaceCtx.lineWidth = 3; + workplaceCtx.setLineDash([5, 5]); + workplaceCtx.strokeRect( + workplaceStartX, + workplaceStartY, + currentX - workplaceStartX, + currentY - workplaceStartY + ); + workplaceCtx.setLineDash([]); + + workplaceCurrentRect = { + x: workplaceStartX, + y: workplaceStartY, + width: currentX - workplaceStartX, + height: currentY - workplaceStartY + }; +} + +// 드래그 시작 +function startWorkplaceDraw(e) { + workplaceIsDrawing = true; + const rect = workplaceCanvas.getBoundingClientRect(); + workplaceStartX = e.clientX - rect.left; + workplaceStartY = e.clientY - rect.top; +} + +// 드래그 중 +function drawWorkplace(e) { + if (!workplaceIsDrawing) return; + + const rect = workplaceCanvas.getBoundingClientRect(); + const currentX = e.clientX - rect.left; + const currentY = e.clientY - rect.top; + + // 캔버스 초기화 및 이미지 다시 그리기 + workplaceCtx.drawImage(workplaceImage, 0, 0, workplaceCanvas.width, workplaceCanvas.height); + + // 기존 영역들 표시 + drawWorkplaceRegions(); + + // 현재 그리는 사각형 (점선으로) + workplaceCtx.strokeStyle = '#3b82f6'; + workplaceCtx.lineWidth = 3; + workplaceCtx.setLineDash([5, 5]); + workplaceCtx.strokeRect( + workplaceStartX, + workplaceStartY, + currentX - workplaceStartX, + currentY - workplaceStartY + ); + workplaceCtx.setLineDash([]); + + // 선택 영역 배경 (반투명) + workplaceCtx.fillStyle = 'rgba(59, 130, 246, 0.1)'; + workplaceCtx.fillRect( + workplaceStartX, + workplaceStartY, + currentX - workplaceStartX, + currentY - workplaceStartY + ); + + workplaceCurrentRect = { + x: workplaceStartX, + y: workplaceStartY, + width: currentX - workplaceStartX, + height: currentY - workplaceStartY + }; +} + +// 드래그 종료 +function endWorkplaceDraw(e) { + workplaceIsDrawing = false; +} + +// 기존 영역들 그리기 +function drawWorkplaceRegions() { + workplaceEquipmentRegions.forEach((region, index) => { + // 퍼센트를 픽셀로 변환 + const x = (region.x_percent / 100) * workplaceCanvas.width; + const y = (region.y_percent / 100) * workplaceCanvas.height; + const width = (region.width_percent / 100) * workplaceCanvas.width; + const height = (region.height_percent / 100) * workplaceCanvas.height; + + // 영역 배경 (반투명) + workplaceCtx.fillStyle = 'rgba(16, 185, 129, 0.15)'; + workplaceCtx.fillRect(x, y, width, height); + + // 영역 테두리 + workplaceCtx.strokeStyle = '#10b981'; + workplaceCtx.lineWidth = 2; + workplaceCtx.strokeRect(x, y, width, height); + + // 영역 이름 표시 (배경 포함) + const displayName = region.equipment_code ? `[${region.equipment_code}] ${region.equipment_name}` : region.equipment_name; + workplaceCtx.font = 'bold 12px sans-serif'; + const textMetrics = workplaceCtx.measureText(displayName); + const textPadding = 4; + + // 텍스트 배경 + workplaceCtx.fillStyle = 'rgba(255, 255, 255, 0.9)'; + workplaceCtx.fillRect(x + 3, y + 3, textMetrics.width + textPadding * 2, 18); + + // 텍스트 + workplaceCtx.fillStyle = '#047857'; + workplaceCtx.fillText(displayName, x + 3 + textPadding, y + 16); + }); +} + +// 현재 영역 지우기 +function clearWorkplaceCurrentRegion() { + workplaceCurrentRect = null; + if (workplaceCanvas && workplaceImage) { + workplaceCtx.drawImage(workplaceImage, 0, 0, workplaceCanvas.width, workplaceCanvas.height); + drawWorkplaceRegions(); + } +} + +// 설비 위치 저장 +async function saveWorkplaceEquipmentRegion() { + const equipmentSelect = document.getElementById('equipmentSelectInput'); + const equipmentNameInput = document.getElementById('equipmentNameInput'); + const equipmentCodeInput = document.getElementById('equipmentCodeInput'); + + const selectedEquipmentId = equipmentSelect?.value; + const newEquipmentName = equipmentNameInput?.value.trim(); + const newEquipmentCode = equipmentCodeInput?.value.trim(); + + // 기존 설비 선택 또는 새 설비 입력 확인 + if (!selectedEquipmentId && (!newEquipmentName || !newEquipmentCode)) { + showToast('기존 설비를 선택하거나 새 설비 코드와 이름을 입력해주세요.', 'warning'); + return; + } + + if (!workplaceCurrentRect) { + showToast('영역을 드래그하여 선택해주세요.', 'warning'); + return; + } + + // 퍼센트로 변환 (음수 영역 처리) + let xPercent = (Math.min(workplaceCurrentRect.x, workplaceCurrentRect.x + workplaceCurrentRect.width) / workplaceCanvas.width) * 100; + let yPercent = (Math.min(workplaceCurrentRect.y, workplaceCurrentRect.y + workplaceCurrentRect.height) / workplaceCanvas.height) * 100; + let widthPercent = (Math.abs(workplaceCurrentRect.width) / workplaceCanvas.width) * 100; + let heightPercent = (Math.abs(workplaceCurrentRect.height) / workplaceCanvas.height) * 100; + + try { + let equipmentId = selectedEquipmentId; + let equipmentName = ''; + + if (selectedEquipmentId) { + // 기존 설비 - 위치 및 작업장 업데이트 + const response = await window.apiCall(`/equipments/${selectedEquipmentId}/map-position`, 'PATCH', { + workplace_id: window.currentWorkplaceMapId, + map_x_percent: xPercent, + map_y_percent: yPercent, + map_width_percent: widthPercent, + map_height_percent: heightPercent + }); + + if (!response || !response.success) { + throw new Error(response?.message || '위치 저장 실패'); + } + + const eq = allEquipments.find(e => e.equipment_id == selectedEquipmentId); + equipmentName = eq?.equipment_name || '설비'; + } else { + // 새 설비 생성 + const response = await window.apiCall('/equipments', 'POST', { + equipment_code: newEquipmentCode, + equipment_name: newEquipmentName, + workplace_id: window.currentWorkplaceMapId, + map_x_percent: xPercent, + map_y_percent: yPercent, + map_width_percent: widthPercent, + map_height_percent: heightPercent, + status: 'active' + }); + + if (!response || !response.success) { + throw new Error(response?.message || '설비 생성 실패'); + } + + equipmentId = response.data.equipment_id; + equipmentName = newEquipmentName; + } + + // 로컬 배열 업데이트 + const newRegion = { + equipment_id: equipmentId, + equipment_name: equipmentName, + equipment_code: newEquipmentCode || existingEquipments.find(e => e.equipment_id == selectedEquipmentId)?.equipment_code, + x_percent: xPercent, + y_percent: yPercent, + width_percent: widthPercent, + height_percent: heightPercent + }; + + // 기존 영역이 있으면 교체, 없으면 추가 + const existingIndex = workplaceEquipmentRegions.findIndex(r => r.equipment_id == equipmentId); + if (existingIndex >= 0) { + workplaceEquipmentRegions[existingIndex] = newRegion; + } else { + workplaceEquipmentRegions.push(newRegion); + } + + // 설비 목록 새로고침 (현재 작업장 + 전체) + await Promise.all([ + loadWorkplaceEquipments(window.currentWorkplaceMapId), + loadAllEquipments() + ]); + + // UI 업데이트 + renderWorkplaceEquipmentList(); + clearWorkplaceCurrentRegion(); + if (equipmentNameInput) equipmentNameInput.value = ''; + if (equipmentCodeInput) equipmentCodeInput.value = ''; + if (equipmentSelect) equipmentSelect.value = ''; + + showToast(`설비 "${equipmentName}" 위치가 저장되었습니다.`, 'success'); + } catch (error) { + console.error('설비 위치 저장 오류:', error); + showToast(error.message || '설비 위치 저장 중 오류가 발생했습니다.', 'error'); + } +} + +// 설비 목록 렌더링 +function renderWorkplaceEquipmentList() { + const listDiv = document.getElementById('workplaceEquipmentList'); + + // 등록된 설비 목록 렌더링 + if (listDiv) { + if (workplaceEquipmentRegions.length === 0) { + listDiv.innerHTML = '

아직 정의된 설비가 없습니다

'; + } else { + let html = ''; + workplaceEquipmentRegions.forEach((region, index) => { + html += ` +
+
+ ${region.equipment_name} + [${region.equipment_code || '-'}] +
+ 위치: (${region.x_percent.toFixed(1)}%, ${region.y_percent.toFixed(1)}%) | 크기: ${region.width_percent.toFixed(1)}% × ${region.height_percent.toFixed(1)}% +
+
+ +
+ `; + }); + listDiv.innerHTML = html; + } + } + + // 설비 선택 드롭다운 업데이트 (항상 호출되어야 함!) + updateEquipmentSelectDropdown(); +} + +// 설비 선택 드롭다운 업데이트 +function updateEquipmentSelectDropdown() { + const selectEl = document.getElementById('equipmentSelectInput'); + if (!selectEl) { + console.warn('⚠️ equipmentSelectInput 요소를 찾을 수 없습니다'); + return; + } + + console.log(`📋 드롭다운 업데이트: 전체 설비 ${allEquipments.length}개`); + + // 전체 설비 중에서 아직 어떤 지도에도 배치되지 않은 설비만 표시 + // map_x_percent가 null이면 지도에 배치되지 않은 설비 + const availableEquipments = allEquipments.filter(eq => + eq.map_x_percent == null || eq.map_x_percent === '' + ); + + console.log(`📋 지도에 미배치된 설비: ${availableEquipments.length}개`); + + // 이 작업장에 이미 배치된 설비는 제외 (현재 작업장에서 방금 배치한 경우) + const registeredIds = workplaceEquipmentRegions.map(r => r.equipment_id); + const unregisteredEquipments = availableEquipments.filter(eq => !registeredIds.includes(eq.equipment_id)); + + console.log(`📋 선택 가능한 설비: ${unregisteredEquipments.length}개`); + + let options = ''; + + if (unregisteredEquipments.length === 0) { + options += ''; + } else { + unregisteredEquipments.forEach(eq => { + const workplaceInfo = eq.workplace_name ? ` (${eq.workplace_name})` : ' (미배정)'; + options += ``; + }); + } + + selectEl.innerHTML = options; + + // 배치 가능한 설비 수 표시 + const countEl = document.getElementById('availableEquipmentCount'); + if (countEl) { + countEl.textContent = `배치 가능: ${unregisteredEquipments.length}개`; + } +} + +// 설비 영역 삭제 (지도에서만 제거, 설비 자체는 유지) +async function removeWorkplaceEquipmentRegion(equipmentId) { + if (!confirm('이 설비의 지도 위치 정보를 삭제하시겠습니까?\n(설비 자체는 삭제되지 않습니다)')) { + return; + } + + try { + // API로 지도 위치 초기화 + const response = await window.apiCall(`/equipments/${equipmentId}/map-position`, 'PATCH', { + map_x_percent: null, + map_y_percent: null, + map_width_percent: null, + map_height_percent: null + }); + + if (!response || !response.success) { + throw new Error(response?.message || '위치 삭제 실패'); + } + + // 로컬 배열에서 제거 + workplaceEquipmentRegions = workplaceEquipmentRegions.filter(r => r.equipment_id != equipmentId); + + // 설비 목록 새로고침 (현재 작업장 + 전체) + await Promise.all([ + loadWorkplaceEquipments(window.currentWorkplaceMapId), + loadAllEquipments() + ]); + + renderWorkplaceEquipmentList(); + + // 캔버스 다시 그리기 + if (workplaceCanvas && workplaceImage) { + workplaceCtx.drawImage(workplaceImage, 0, 0, workplaceCanvas.width, workplaceCanvas.height); + drawWorkplaceRegions(); + } + + showToast('설비 위치가 삭제되었습니다.', 'success'); + } catch (error) { + console.error('설비 위치 삭제 오류:', error); + showToast(error.message || '설비 위치 삭제 중 오류가 발생했습니다.', 'error'); + } +} + +// 작업장 레이아웃 이미지 미리보기 +function previewWorkplaceLayoutImage(event) { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = function(e) { + const preview = document.getElementById('workplaceLayoutPreview'); + if (preview) { + preview.innerHTML = `미리보기`; + } + }; + reader.readAsDataURL(file); + } +} + +window.switchCategory = switchCategory; +window.openCategoryModal = openCategoryModal; +window.closeCategoryModal = closeCategoryModal; +window.saveCategory = saveCategory; +window.deleteCategory = deleteCategory; +window.openWorkplaceModal = openWorkplaceModal; +window.closeWorkplaceModal = closeWorkplaceModal; +window.editWorkplace = editWorkplace; +window.saveWorkplace = saveWorkplace; +window.deleteWorkplace = deleteWorkplace; +window.confirmDeleteWorkplace = confirmDeleteWorkplace; +window.refreshWorkplaces = refreshWorkplaces; +window.showToast = showToast; +window.loadCategories = loadCategories; +window.updateLayoutPreview = updateLayoutPreview; +window.openWorkplaceMapModal = openWorkplaceMapModal; +window.closeWorkplaceMapModal = closeWorkplaceMapModal; +window.uploadWorkplaceLayout = uploadWorkplaceLayout; +window.clearWorkplaceCurrentRegion = clearWorkplaceCurrentRegion; +window.saveWorkplaceEquipmentRegion = saveWorkplaceEquipmentRegion; +window.removeWorkplaceEquipmentRegion = removeWorkplaceEquipmentRegion; +window.previewWorkplaceLayoutImage = previewWorkplaceLayoutImage; +window.toggleNewEquipmentFields = toggleNewEquipmentFields; + +// 새 설비 필드 토글 (기존 설비 선택 시 숨김) +function toggleNewEquipmentFields() { + const selectEl = document.getElementById('equipmentSelectInput'); + const fieldsDiv = document.getElementById('newEquipmentFields'); + + if (selectEl && fieldsDiv) { + if (selectEl.value) { + fieldsDiv.style.display = 'none'; + } else { + fieldsDiv.style.display = 'block'; + } + } +} + +// ==================== 전체화면 설비 배치 편집기 ==================== + +// 전체화면 편집기 관련 전역 변수 +let fsCanvas = null; +let fsCtx = null; +let fsImage = null; +let fsIsDrawing = false; +let fsStartX = 0; +let fsStartY = 0; +let fsCurrentRect = null; +let fsSidebarVisible = true; + +// 전체화면 편집기 열기 +async function openFullscreenEquipmentEditor() { + const workplaceId = window.currentWorkplaceMapId; + if (!workplaceId) { + showToast('작업장을 먼저 선택해주세요.', 'warning'); + return; + } + + const workplace = workplaces.find(w => w.workplace_id === workplaceId); + if (!workplace) { + showToast('작업장 정보를 찾을 수 없습니다.', 'error'); + return; + } + + // 레이아웃 이미지 확인 + if (!workplace.layout_image) { + showToast('작업장 레이아웃 이미지를 먼저 업로드해주세요.', 'warning'); + return; + } + + // 전체화면 에디터 타이틀 설정 + const titleEl = document.getElementById('fullscreenEditorTitle'); + if (titleEl) { + titleEl.textContent = `${workplace.workplace_name} - 설비 위치 편집`; + } + + // 전체화면 에디터 표시 + const editor = document.getElementById('fullscreenEquipmentEditor'); + if (editor) { + editor.style.display = 'flex'; + document.body.style.overflow = 'hidden'; + } + + // 이미지 URL 생성 + const fullImageUrl = workplace.layout_image.startsWith('http') + ? workplace.layout_image + : `${window.API_BASE_URL || 'http://localhost:20005/api'}${workplace.layout_image}`.replace('/api/', '/'); + + // 캔버스 초기화 + initFullscreenCanvas(fullImageUrl); + + // 설비 목록 로드 및 드롭다운 업데이트 + await Promise.all([ + loadWorkplaceEquipments(workplaceId), + loadAllEquipments() + ]); + updateFsEquipmentUI(); +} + +// 전체화면 편집기 닫기 +function closeFullscreenEditor() { + const editor = document.getElementById('fullscreenEquipmentEditor'); + if (editor) { + editor.style.display = 'none'; + document.body.style.overflow = ''; + } + + // 전역 상태 초기화 + fsCanvas = null; + fsCtx = null; + fsImage = null; + fsIsDrawing = false; + fsCurrentRect = null; + + // 작업장 지도 모달의 설비 목록도 업데이트 + renderWorkplaceEquipmentList(); + + // 작업장 카드 목록 새로고침 (썸네일 업데이트) + renderWorkplaces(); +} + +// 사이드바 토글 +function toggleEditorSidebar() { + const sidebar = document.getElementById('fullscreenSidebar'); + const canvasArea = document.getElementById('fullscreenCanvasArea'); + const toggleIcon = document.getElementById('sidebarToggleIcon'); + + if (!sidebar || !canvasArea) return; + + fsSidebarVisible = !fsSidebarVisible; + + if (fsSidebarVisible) { + sidebar.style.display = 'flex'; + toggleIcon.textContent = '▶'; + } else { + sidebar.style.display = 'none'; + toggleIcon.textContent = '◀'; + } + + // 캔버스 크기 재조정 + if (fsImage) { + setTimeout(() => { + resizeFullscreenCanvas(); + }, 100); + } +} + +// 전체화면 캔버스 초기화 +function initFullscreenCanvas(imageUrl) { + const img = new Image(); + img.onload = function() { + fsImage = img; + fsCanvas = document.getElementById('fullscreenRegionCanvas'); + if (!fsCanvas) return; + + fsCtx = fsCanvas.getContext('2d'); + + // 캔버스 크기 조정 + resizeFullscreenCanvas(); + + // 이벤트 리스너 등록 + fsCanvas.onmousedown = startFsDraw; + fsCanvas.onmousemove = drawFsRegion; + fsCanvas.onmouseup = endFsDraw; + fsCanvas.onmouseleave = endFsDraw; + + // 터치 이벤트 지원 + fsCanvas.ontouchstart = handleFsTouchStart; + fsCanvas.ontouchmove = handleFsTouchMove; + fsCanvas.ontouchend = endFsDraw; + + console.log('✅ 전체화면 캔버스 초기화 완료'); + }; + + img.onerror = function() { + console.error('전체화면 이미지 로드 실패:', imageUrl); + showToast('이미지를 불러올 수 없습니다.', 'error'); + }; + + img.src = imageUrl; +} + +// 캔버스 크기 조정 (화면에 맞게) +function resizeFullscreenCanvas() { + if (!fsImage || !fsCanvas) return; + + const wrapper = document.getElementById('fullscreenCanvasWrapper'); + if (!wrapper) return; + + // 사용 가능한 영역 계산 + const maxWidth = wrapper.clientWidth - 40; + const maxHeight = wrapper.clientHeight - 40; + + // 이미지 비율 유지하면서 크기 조정 + const imgRatio = fsImage.width / fsImage.height; + const containerRatio = maxWidth / maxHeight; + + let scale; + if (imgRatio > containerRatio) { + // 이미지가 더 넓음 - 너비 기준 + scale = maxWidth / fsImage.width; + } else { + // 이미지가 더 높음 - 높이 기준 + scale = maxHeight / fsImage.height; + } + + // 최소/최대 스케일 제한 + scale = Math.min(Math.max(scale, 0.1), 2); + + fsCanvas.width = fsImage.width * scale; + fsCanvas.height = fsImage.height * scale; + + // 이미지 그리기 + fsCtx.drawImage(fsImage, 0, 0, fsCanvas.width, fsCanvas.height); + + // 기존 영역 그리기 + drawFsRegions(); + + // 줌 정보 업데이트 + const zoomInfo = document.getElementById('canvasZoomInfo'); + if (zoomInfo) { + zoomInfo.textContent = `${Math.round(scale * 100)}%`; + } +} + +// 드래그 시작 +function startFsDraw(e) { + fsIsDrawing = true; + const rect = fsCanvas.getBoundingClientRect(); + fsStartX = e.clientX - rect.left; + fsStartY = e.clientY - rect.top; +} + +// 드래그 중 +function drawFsRegion(e) { + if (!fsIsDrawing) return; + + const rect = fsCanvas.getBoundingClientRect(); + const currentX = e.clientX - rect.left; + const currentY = e.clientY - rect.top; + + // 캔버스 초기화 및 이미지 다시 그리기 + fsCtx.drawImage(fsImage, 0, 0, fsCanvas.width, fsCanvas.height); + + // 기존 영역들 표시 + drawFsRegions(); + + // 현재 그리는 사각형 (점선) + fsCtx.strokeStyle = '#3b82f6'; + fsCtx.lineWidth = 3; + fsCtx.setLineDash([8, 4]); + fsCtx.strokeRect( + fsStartX, + fsStartY, + currentX - fsStartX, + currentY - fsStartY + ); + fsCtx.setLineDash([]); + + // 선택 영역 배경 + fsCtx.fillStyle = 'rgba(59, 130, 246, 0.15)'; + fsCtx.fillRect( + fsStartX, + fsStartY, + currentX - fsStartX, + currentY - fsStartY + ); + + // 영역 정보 표시 + const width = Math.abs(currentX - fsStartX); + const height = Math.abs(currentY - fsStartY); + fsCtx.font = 'bold 12px sans-serif'; + fsCtx.fillStyle = '#3b82f6'; + fsCtx.fillText(`${Math.round(width)} × ${Math.round(height)}px`, Math.min(fsStartX, currentX) + 5, Math.min(fsStartY, currentY) - 5); + + fsCurrentRect = { + x: fsStartX, + y: fsStartY, + width: currentX - fsStartX, + height: currentY - fsStartY + }; +} + +// 드래그 종료 +function endFsDraw(e) { + fsIsDrawing = false; +} + +// 터치 이벤트 핸들러 +function handleFsTouchStart(e) { + e.preventDefault(); + const touch = e.touches[0]; + const rect = fsCanvas.getBoundingClientRect(); + fsIsDrawing = true; + fsStartX = touch.clientX - rect.left; + fsStartY = touch.clientY - rect.top; +} + +function handleFsTouchMove(e) { + e.preventDefault(); + if (!fsIsDrawing) return; + + const touch = e.touches[0]; + const rect = fsCanvas.getBoundingClientRect(); + const currentX = touch.clientX - rect.left; + const currentY = touch.clientY - rect.top; + + // 캔버스 초기화 및 이미지 다시 그리기 + fsCtx.drawImage(fsImage, 0, 0, fsCanvas.width, fsCanvas.height); + drawFsRegions(); + + // 현재 그리는 사각형 + fsCtx.strokeStyle = '#3b82f6'; + fsCtx.lineWidth = 3; + fsCtx.setLineDash([8, 4]); + fsCtx.strokeRect( + fsStartX, + fsStartY, + currentX - fsStartX, + currentY - fsStartY + ); + fsCtx.setLineDash([]); + + fsCtx.fillStyle = 'rgba(59, 130, 246, 0.15)'; + fsCtx.fillRect( + fsStartX, + fsStartY, + currentX - fsStartX, + currentY - fsStartY + ); + + fsCurrentRect = { + x: fsStartX, + y: fsStartY, + width: currentX - fsStartX, + height: currentY - fsStartY + }; +} + +// 기존 영역들 그리기 +function drawFsRegions() { + workplaceEquipmentRegions.forEach((region, index) => { + // 퍼센트를 픽셀로 변환 + const x = (region.x_percent / 100) * fsCanvas.width; + const y = (region.y_percent / 100) * fsCanvas.height; + const width = (region.width_percent / 100) * fsCanvas.width; + const height = (region.height_percent / 100) * fsCanvas.height; + + // 영역 배경 (반투명) + fsCtx.fillStyle = 'rgba(16, 185, 129, 0.2)'; + fsCtx.fillRect(x, y, width, height); + + // 영역 테두리 + fsCtx.strokeStyle = '#10b981'; + fsCtx.lineWidth = 2; + fsCtx.strokeRect(x, y, width, height); + + // 영역 이름 표시 + const displayName = region.equipment_code + ? `[${region.equipment_code}] ${region.equipment_name}` + : region.equipment_name; + fsCtx.font = 'bold 13px sans-serif'; + const textMetrics = fsCtx.measureText(displayName); + const textPadding = 6; + + // 텍스트 배경 + fsCtx.fillStyle = 'rgba(255, 255, 255, 0.95)'; + fsCtx.fillRect(x + 4, y + 4, textMetrics.width + textPadding * 2, 22); + + // 텍스트 + fsCtx.fillStyle = '#047857'; + fsCtx.fillText(displayName, x + 4 + textPadding, y + 19); + }); +} + +// 현재 영역 지우기 +function fsClearCurrentRegion() { + fsCurrentRect = null; + if (fsCanvas && fsImage) { + fsCtx.drawImage(fsImage, 0, 0, fsCanvas.width, fsCanvas.height); + drawFsRegions(); + } + showToast('영역이 초기화되었습니다.', 'info'); +} + +// 설비 영역 저장 (전체화면 편집기용) +async function fsSaveEquipmentRegion() { + const equipmentSelect = document.getElementById('fsEquipmentSelect'); + const equipmentNameInput = document.getElementById('fsEquipmentName'); + const equipmentCodeInput = document.getElementById('fsEquipmentCode'); + + const selectedEquipmentId = equipmentSelect?.value; + const newEquipmentName = equipmentNameInput?.value.trim(); + const newEquipmentCode = equipmentCodeInput?.value.trim(); + + // 기존 설비 선택 또는 새 설비 입력 확인 + if (!selectedEquipmentId && (!newEquipmentName || !newEquipmentCode)) { + showToast('기존 설비를 선택하거나 새 설비 코드와 이름을 입력해주세요.', 'warning'); + return; + } + + if (!fsCurrentRect) { + showToast('지도에서 영역을 드래그하여 선택해주세요.', 'warning'); + return; + } + + // 퍼센트로 변환 (음수 영역 처리) + let xPercent = (Math.min(fsCurrentRect.x, fsCurrentRect.x + fsCurrentRect.width) / fsCanvas.width) * 100; + let yPercent = (Math.min(fsCurrentRect.y, fsCurrentRect.y + fsCurrentRect.height) / fsCanvas.height) * 100; + let widthPercent = (Math.abs(fsCurrentRect.width) / fsCanvas.width) * 100; + let heightPercent = (Math.abs(fsCurrentRect.height) / fsCanvas.height) * 100; + + try { + let equipmentId = selectedEquipmentId; + let equipmentName = ''; + let equipmentCode = ''; + + if (selectedEquipmentId) { + // 기존 설비 - 위치 및 작업장 업데이트 + const response = await window.apiCall(`/equipments/${selectedEquipmentId}/map-position`, 'PATCH', { + workplace_id: window.currentWorkplaceMapId, + map_x_percent: xPercent, + map_y_percent: yPercent, + map_width_percent: widthPercent, + map_height_percent: heightPercent + }); + + if (!response || !response.success) { + throw new Error(response?.message || '위치 저장 실패'); + } + + const eq = allEquipments.find(e => e.equipment_id == selectedEquipmentId); + equipmentName = eq?.equipment_name || '설비'; + equipmentCode = eq?.equipment_code || ''; + } else { + // 새 설비 생성 + const response = await window.apiCall('/equipments', 'POST', { + equipment_code: newEquipmentCode, + equipment_name: newEquipmentName, + workplace_id: window.currentWorkplaceMapId, + map_x_percent: xPercent, + map_y_percent: yPercent, + map_width_percent: widthPercent, + map_height_percent: heightPercent, + status: 'active' + }); + + if (!response || !response.success) { + throw new Error(response?.message || '설비 생성 실패'); + } + + equipmentId = response.data.equipment_id; + equipmentName = newEquipmentName; + equipmentCode = newEquipmentCode; + } + + // 로컬 배열 업데이트 + const newRegion = { + equipment_id: equipmentId, + equipment_name: equipmentName, + equipment_code: equipmentCode, + x_percent: xPercent, + y_percent: yPercent, + width_percent: widthPercent, + height_percent: heightPercent + }; + + // 기존 영역이 있으면 교체, 없으면 추가 + const existingIndex = workplaceEquipmentRegions.findIndex(r => r.equipment_id == equipmentId); + if (existingIndex >= 0) { + workplaceEquipmentRegions[existingIndex] = newRegion; + } else { + workplaceEquipmentRegions.push(newRegion); + } + + // 설비 목록 새로고침 + await Promise.all([ + loadWorkplaceEquipments(window.currentWorkplaceMapId), + loadAllEquipments() + ]); + + // 입력 필드 초기화 (UI 업데이트 전에 먼저) + if (equipmentNameInput) equipmentNameInput.value = ''; + if (equipmentCodeInput) equipmentCodeInput.value = ''; // 비워야 다음 코드 자동 로드됨 + if (equipmentSelect) equipmentSelect.value = ''; + + // UI 업데이트 및 다음 관리번호 로드 + await updateFsEquipmentUI(); + fsClearCurrentRegion(); + + showToast(`설비 "${equipmentName}" 위치가 저장되었습니다.`, 'success'); + } catch (error) { + console.error('설비 위치 저장 오류:', error); + showToast(error.message || '설비 위치 저장 중 오류가 발생했습니다.', 'error'); + } +} + +// 새 설비 필드 토글 (전체화면 편집기용) +function fsToggleNewEquipmentFields() { + const selectEl = document.getElementById('fsEquipmentSelect'); + const fieldsDiv = document.getElementById('fsNewEquipmentFields'); + + if (selectEl && fieldsDiv) { + if (selectEl.value) { + fieldsDiv.style.opacity = '0.5'; + fieldsDiv.querySelector('input')?.setAttribute('disabled', 'true'); + document.getElementById('fsEquipmentCode')?.setAttribute('disabled', 'true'); + document.getElementById('fsEquipmentName')?.setAttribute('disabled', 'true'); + } else { + fieldsDiv.style.opacity = '1'; + document.getElementById('fsEquipmentCode')?.removeAttribute('disabled'); + document.getElementById('fsEquipmentName')?.removeAttribute('disabled'); + } + } +} + +// 다음 관리번호 로드 (전체화면 편집기용) +async function loadNextEquipmentCodeForFs() { + try { + const response = await window.apiCall('/equipments/next-code', 'GET'); + if (response && response.success) { + const codeInput = document.getElementById('fsEquipmentCode'); + if (codeInput && !codeInput.value) { + codeInput.value = response.data.next_code; + } + } + } catch (error) { + console.error('다음 관리번호 조회 실패:', error); + // 오류 시 무시 (사용자가 직접 입력) + } +} + +// 전체화면 편집기 UI 업데이트 +async function updateFsEquipmentUI() { + // 설비 선택 드롭다운 업데이트 + const selectEl = document.getElementById('fsEquipmentSelect'); + if (selectEl) { + // 지도에 미배치된 설비만 표시 + const availableEquipments = allEquipments.filter(eq => + eq.map_x_percent == null || eq.map_x_percent === '' + ); + + // 이미 이 작업장에 배치된 설비 제외 + const registeredIds = workplaceEquipmentRegions.map(r => r.equipment_id); + const unregisteredEquipments = availableEquipments.filter(eq => !registeredIds.includes(eq.equipment_id)); + + let options = ''; + + if (unregisteredEquipments.length === 0) { + options += ''; + } else { + unregisteredEquipments.forEach(eq => { + options += ``; + }); + } + + selectEl.innerHTML = options; + + // 배치 가능한 설비 수 표시 + const countEl = document.getElementById('fsAvailableEquipmentCount'); + if (countEl) { + countEl.textContent = `${unregisteredEquipments.length}개`; + } + } + + // 새 설비 코드 자동 생성 + await loadNextEquipmentCodeForFs(); + + // 등록된 설비 목록 업데이트 + const listEl = document.getElementById('fsEquipmentList'); + if (listEl) { + if (workplaceEquipmentRegions.length === 0) { + listEl.innerHTML = '

등록된 설비가 없습니다

'; + } else { + let html = ''; + workplaceEquipmentRegions.forEach((region) => { + html += ` +
+
+ ${region.equipment_name} + [${region.equipment_code || '-'}] +
+ 위치: (${region.x_percent.toFixed(1)}%, ${region.y_percent.toFixed(1)}%) +
+
+ +
+ `; + }); + listEl.innerHTML = html; + } + + // 등록된 설비 수 표시 + const registeredCountEl = document.getElementById('fsRegisteredCount'); + if (registeredCountEl) { + registeredCountEl.textContent = `${workplaceEquipmentRegions.length}개`; + } + } + + // 작업장 지도 모달의 설비 수도 업데이트 + const modalCountEl = document.getElementById('workplaceEquipmentCount'); + if (modalCountEl) { + modalCountEl.textContent = `${workplaceEquipmentRegions.length}개`; + } +} + +// 설비 영역 삭제 (전체화면 편집기용) +async function fsRemoveEquipmentRegion(equipmentId) { + if (!confirm('이 설비의 지도 위치를 삭제하시겠습니까?')) { + return; + } + + try { + // API로 지도 위치 초기화 + const response = await window.apiCall(`/equipments/${equipmentId}/map-position`, 'PATCH', { + map_x_percent: null, + map_y_percent: null, + map_width_percent: null, + map_height_percent: null + }); + + if (!response || !response.success) { + throw new Error(response?.message || '위치 삭제 실패'); + } + + // 로컬 배열에서 제거 + workplaceEquipmentRegions = workplaceEquipmentRegions.filter(r => r.equipment_id != equipmentId); + + // 설비 목록 새로고침 + await Promise.all([ + loadWorkplaceEquipments(window.currentWorkplaceMapId), + loadAllEquipments() + ]); + + // UI 업데이트 + updateFsEquipmentUI(); + + // 캔버스 다시 그리기 + if (fsCanvas && fsImage) { + fsCtx.drawImage(fsImage, 0, 0, fsCanvas.width, fsCanvas.height); + drawFsRegions(); + } + + showToast('설비 위치가 삭제되었습니다.', 'success'); + } catch (error) { + console.error('설비 위치 삭제 오류:', error); + showToast(error.message || '삭제 중 오류가 발생했습니다.', 'error'); + } +} + +// 전체화면 편집기 함수들 전역 노출 +window.openFullscreenEquipmentEditor = openFullscreenEquipmentEditor; +window.closeFullscreenEditor = closeFullscreenEditor; +window.toggleEditorSidebar = toggleEditorSidebar; +window.fsClearCurrentRegion = fsClearCurrentRegion; +window.fsSaveEquipmentRegion = fsSaveEquipmentRegion; +window.fsToggleNewEquipmentFields = fsToggleNewEquipmentFields; +window.fsRemoveEquipmentRegion = fsRemoveEquipmentRegion; diff --git a/deploy/tkfb-package/web-ui/js/workplace-management/api.js b/deploy/tkfb-package/web-ui/js/workplace-management/api.js new file mode 100644 index 0000000..d4880d6 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/workplace-management/api.js @@ -0,0 +1,329 @@ +/** + * Workplace Management - API Client + * 작업장 관리 관련 모든 API 호출을 관리 + */ + +class WorkplaceAPI { + constructor() { + this.state = window.WorkplaceState; + this.utils = window.WorkplaceUtils; + console.log('[WorkplaceAPI] 초기화 완료'); + } + + /** + * 모든 데이터 로드 + */ + async loadAllData() { + try { + await Promise.all([ + this.loadCategories(), + this.loadWorkplaces() + ]); + console.log('✅ 모든 데이터 로드 완료'); + } catch (error) { + console.error('데이터 로딩 오류:', error); + window.showToast?.('데이터를 불러오는데 실패했습니다.', 'error'); + } + } + + /** + * 카테고리 목록 로드 + */ + async loadCategories() { + try { + const response = await window.apiCall('/workplaces/categories', 'GET'); + + let categoryData = []; + if (response && response.success && Array.isArray(response.data)) { + categoryData = response.data; + } else if (Array.isArray(response)) { + categoryData = response; + } + + this.state.categories = categoryData; + console.log(`✅ 카테고리 ${this.state.categories.length}개 로드 완료`); + return categoryData; + } catch (error) { + console.error('카테고리 로딩 오류:', error); + this.state.categories = []; + return []; + } + } + + /** + * 카테고리 저장 (생성/수정) + */ + async saveCategory(categoryId, categoryData) { + try { + let response; + if (categoryId) { + response = await window.apiCall(`/workplaces/categories/${categoryId}`, 'PUT', categoryData); + } else { + response = await window.apiCall('/workplaces/categories', 'POST', categoryData); + } + + if (response && (response.success || response.category_id)) { + return response; + } + throw new Error(response?.message || '저장에 실패했습니다.'); + } catch (error) { + console.error('카테고리 저장 오류:', error); + throw error; + } + } + + /** + * 카테고리 삭제 + */ + async deleteCategory(categoryId) { + try { + const response = await window.apiCall(`/workplaces/categories/${categoryId}`, 'DELETE'); + if (response && response.success) { + return response; + } + throw new Error(response?.message || '삭제에 실패했습니다.'); + } catch (error) { + console.error('카테고리 삭제 오류:', error); + throw error; + } + } + + /** + * 작업장 목록 로드 + */ + async loadWorkplaces() { + try { + const response = await window.apiCall('/workplaces', 'GET'); + + let workplaceData = []; + if (response && response.success && Array.isArray(response.data)) { + workplaceData = response.data; + } else if (Array.isArray(response)) { + workplaceData = response; + } + + this.state.workplaces = workplaceData; + console.log(`✅ 작업장 ${this.state.workplaces.length}개 로드 완료`); + return workplaceData; + } catch (error) { + console.error('작업장 로딩 오류:', error); + this.state.workplaces = []; + return []; + } + } + + /** + * 작업장 저장 (생성/수정) + */ + async saveWorkplace(workplaceId, workplaceData) { + try { + let response; + if (workplaceId) { + response = await window.apiCall(`/workplaces/${workplaceId}`, 'PUT', workplaceData); + } else { + response = await window.apiCall('/workplaces', 'POST', workplaceData); + } + + if (response && (response.success || response.workplace_id)) { + return response; + } + throw new Error(response?.message || '저장에 실패했습니다.'); + } catch (error) { + console.error('작업장 저장 오류:', error); + throw error; + } + } + + /** + * 작업장 삭제 + */ + async deleteWorkplace(workplaceId) { + try { + const response = await window.apiCall(`/workplaces/${workplaceId}`, 'DELETE'); + if (response && response.success) { + return response; + } + throw new Error(response?.message || '삭제에 실패했습니다.'); + } catch (error) { + console.error('작업장 삭제 오류:', error); + throw error; + } + } + + /** + * 카테고리의 지도 영역 로드 + */ + async loadMapRegions(categoryId) { + try { + const response = await window.apiCall(`/workplaces/categories/${categoryId}/map-regions`, 'GET'); + + let regions = []; + if (response && response.success && Array.isArray(response.data)) { + regions = response.data; + } else if (Array.isArray(response)) { + regions = response; + } + return regions; + } catch (error) { + console.error('지도 영역 로드 오류:', error); + return []; + } + } + + /** + * 작업장의 지도 영역 로드 + */ + async loadWorkplaceMapRegion(workplaceId) { + try { + const response = await window.apiCall(`/workplaces/map-regions/workplace/${workplaceId}`, 'GET'); + return response; + } catch (error) { + console.error('작업장 지도 영역 로드 오류:', error); + return null; + } + } + + /** + * 작업장의 설비 목록 로드 + */ + async loadWorkplaceEquipments(workplaceId) { + try { + const response = await window.apiCall(`/equipments/workplace/${workplaceId}`, 'GET'); + + let equipments = []; + if (response && response.success && Array.isArray(response.data)) { + equipments = response.data; + } else if (Array.isArray(response)) { + equipments = response; + } + + // 지도 영역이 있는 설비만 workplaceEquipmentRegions에 추가 + this.state.workplaceEquipmentRegions = equipments + .filter(eq => eq.map_x_percent != null && eq.map_y_percent != null) + .map(eq => ({ + equipment_id: eq.equipment_id, + equipment_name: eq.equipment_name, + equipment_code: eq.equipment_code, + x_percent: parseFloat(eq.map_x_percent), + y_percent: parseFloat(eq.map_y_percent), + width_percent: parseFloat(eq.map_width_percent) || 10, + height_percent: parseFloat(eq.map_height_percent) || 10 + })); + + this.state.existingEquipments = equipments; + + console.log(`✅ 작업장 ${workplaceId}의 설비 ${equipments.length}개 로드 완료`); + return equipments; + } catch (error) { + console.error('설비 로드 오류:', error); + this.state.workplaceEquipmentRegions = []; + this.state.existingEquipments = []; + return []; + } + } + + /** + * 전체 설비 목록 로드 + */ + async loadAllEquipments() { + try { + const response = await window.apiCall('/equipments', 'GET'); + + let equipments = []; + if (response && response.success && Array.isArray(response.data)) { + equipments = response.data; + } else if (Array.isArray(response)) { + equipments = response; + } + + this.state.allEquipments = equipments; + console.log(`✅ 전체 설비 ${this.state.allEquipments.length}개 로드 완료`); + return equipments; + } catch (error) { + console.error('전체 설비 로드 오류:', error); + this.state.allEquipments = []; + return []; + } + } + + /** + * 설비 지도 위치 업데이트 + */ + async updateEquipmentMapPosition(equipmentId, positionData) { + try { + const response = await window.apiCall(`/equipments/${equipmentId}/map-position`, 'PATCH', positionData); + if (!response || !response.success) { + throw new Error(response?.message || '위치 저장 실패'); + } + return response; + } catch (error) { + console.error('설비 위치 업데이트 오류:', error); + throw error; + } + } + + /** + * 새 설비 생성 + */ + async createEquipment(equipmentData) { + try { + const response = await window.apiCall('/equipments', 'POST', equipmentData); + if (!response || !response.success) { + throw new Error(response?.message || '설비 생성 실패'); + } + return response; + } catch (error) { + console.error('설비 생성 오류:', error); + throw error; + } + } + + /** + * 다음 관리번호 조회 + */ + async getNextEquipmentCode() { + try { + const response = await window.apiCall('/equipments/next-code', 'GET'); + if (response && response.success) { + return response.data.next_code; + } + return null; + } catch (error) { + console.error('다음 관리번호 조회 실패:', error); + return null; + } + } + + /** + * 작업장 레이아웃 이미지 업로드 + */ + async uploadWorkplaceLayout(workplaceId, formData) { + try { + const response = await fetch( + `${this.utils.getApiBaseUrl()}/workplaces/${workplaceId}/layout-image`, + { + method: 'POST', + headers: { + 'Authorization': `Bearer ${localStorage.getItem('token')}` + }, + body: formData + } + ); + return await response.json(); + } catch (error) { + console.error('레이아웃 이미지 업로드 오류:', error); + throw error; + } + } +} + +// 전역 인스턴스 생성 +window.WorkplaceAPI = new WorkplaceAPI(); + +// 하위 호환성: 기존 함수들 +window.loadCategories = () => window.WorkplaceAPI.loadCategories(); +window.loadWorkplaces = () => window.WorkplaceAPI.loadWorkplaces(); +window.loadWorkplaceEquipments = (id) => window.WorkplaceAPI.loadWorkplaceEquipments(id); +window.loadAllEquipments = () => window.WorkplaceAPI.loadAllEquipments(); + +console.log('[Module] workplace-management/api.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/workplace-management/index.js b/deploy/tkfb-package/web-ui/js/workplace-management/index.js new file mode 100644 index 0000000..dde85da --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/workplace-management/index.js @@ -0,0 +1,553 @@ +/** + * Workplace Management - Module Loader + * 작업장 관리 모듈을 초기화하고 연결하는 메인 진입점 + * + * 로드 순서: + * 1. state.js - 전역 상태 관리 + * 2. utils.js - 유틸리티 함수 + * 3. api.js - API 클라이언트 + * 4. index.js - 이 파일 (메인 컨트롤러) + */ + +class WorkplaceController { + constructor() { + this.state = window.WorkplaceState; + this.api = window.WorkplaceAPI; + this.utils = window.WorkplaceUtils; + this.initialized = false; + + console.log('[WorkplaceController] 생성'); + } + + /** + * 초기화 + */ + async init() { + if (this.initialized) { + console.log('[WorkplaceController] 이미 초기화됨'); + return; + } + + console.log('🏗️ 작업장 관리 페이지 초기화 시작'); + + // API 함수가 로드될 때까지 대기 + let retryCount = 0; + while (!window.apiCall && retryCount < 50) { + await new Promise(resolve => setTimeout(resolve, 100)); + retryCount++; + } + + if (!window.apiCall) { + window.showToast?.('시스템을 초기화할 수 없습니다. 페이지를 새로고침해주세요.', 'error'); + return; + } + + // 모든 데이터 로드 + await this.loadAllData(); + + this.initialized = true; + console.log('[WorkplaceController] 초기화 완료'); + } + + /** + * 모든 데이터 로드 + */ + async loadAllData() { + try { + await this.api.loadAllData(); + this.renderCategoryTabs(); + this.renderWorkplaces(); + this.updateStatistics(); + } catch (error) { + console.error('데이터 로딩 오류:', error); + window.showToast?.('데이터를 불러오는데 실패했습니다.', 'error'); + } + } + + /** + * 카테고리 탭 렌더링 + */ + renderCategoryTabs() { + const tabsContainer = document.getElementById('categoryTabs'); + if (!tabsContainer) return; + + const categories = this.state.categories; + const workplaces = this.state.workplaces; + const currentCategoryId = this.state.currentCategoryId; + + let tabsHtml = ` + + `; + + categories.forEach(category => { + const count = workplaces.filter(w => w.category_id === category.category_id).length; + const isActive = currentCategoryId === category.category_id; + + tabsHtml += ` + + `; + }); + + tabsContainer.innerHTML = tabsHtml; + } + + /** + * 카테고리 전환 + */ + async switchCategory(categoryId) { + this.state.setCurrentCategory(categoryId); + this.renderCategoryTabs(); + this.renderWorkplaces(); + + const layoutMapSection = document.getElementById('layoutMapSection'); + const selectedCategoryName = document.getElementById('selectedCategoryName'); + + if (categoryId && layoutMapSection) { + const category = this.state.getCurrentCategory(); + if (category) { + layoutMapSection.style.display = 'block'; + if (selectedCategoryName) { + selectedCategoryName.textContent = category.category_name; + } + await this.updateLayoutPreview(category); + } + } else if (layoutMapSection) { + layoutMapSection.style.display = 'none'; + } + } + + /** + * 레이아웃 미리보기 업데이트 + */ + async updateLayoutPreview(category) { + const previewDiv = document.getElementById('layoutMapPreview'); + if (!previewDiv) return; + + if (category.layout_image) { + const fullImageUrl = this.utils.getFullImageUrl(category.layout_image); + + previewDiv.innerHTML = ` +
+ +

+ 클릭하여 작업장 영역을 수정하려면 "지도 설정" 버튼을 누르세요 +

+
+ `; + + await this.loadImageWithRegions(fullImageUrl, category.category_id); + } else { + previewDiv.innerHTML = ` +
+ 🗺️ +

+ 이 공장의 레이아웃 이미지가 아직 등록되지 않았습니다 +

+

+ "지도 설정" 버튼을 눌러 레이아웃 이미지를 업로드하고 작업장 위치를 지정하세요 +

+
+ `; + } + } + + /** + * 이미지와 영역을 캔버스에 로드 + */ + async loadImageWithRegions(imageUrl, categoryId) { + const canvas = document.getElementById('previewCanvas'); + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + const img = new Image(); + const self = this; + + img.onload = async function() { + const maxWidth = 800; + const scale = img.width > maxWidth ? maxWidth / img.width : 1; + + canvas.width = img.width * scale; + canvas.height = img.height * scale; + + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + + try { + const regions = await self.api.loadMapRegions(categoryId); + + regions.forEach(region => { + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + const width = x2 - x1; + const height = y2 - y1; + + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 2; + ctx.strokeRect(x1, y1, width, height); + + ctx.fillStyle = 'rgba(16, 185, 129, 0.15)'; + ctx.fillRect(x1, y1, width, height); + + if (region.workplace_name) { + ctx.font = 'bold 14px sans-serif'; + const textMetrics = ctx.measureText(region.workplace_name); + const textPadding = 4; + + ctx.fillStyle = 'rgba(255, 255, 255, 0.9)'; + ctx.fillRect(x1 + 5, y1 + 5, textMetrics.width + textPadding * 2, 20); + + ctx.fillStyle = '#10b981'; + ctx.fillText(region.workplace_name, x1 + 5 + textPadding, y1 + 20); + } + }); + + if (regions.length > 0) { + console.log(`✅ 레이아웃 미리보기에 ${regions.length}개 영역 표시 완료`); + } + } catch (error) { + console.error('영역 로드 오류:', error); + } + }; + + img.onerror = function() { + console.error('이미지 로드 실패:', imageUrl); + }; + + img.src = imageUrl; + } + + /** + * 작업장 렌더링 + */ + renderWorkplaces() { + const grid = document.getElementById('workplaceGrid'); + if (!grid) return; + + const filtered = this.state.getFilteredWorkplaces(); + + if (filtered.length === 0) { + grid.innerHTML = ` +
+
🏗️
+

등록된 작업장이 없습니다

+

"작업장 추가" 버튼을 눌러 작업장을 등록해보세요

+ +
+ `; + return; + } + + let gridHtml = ''; + + filtered.forEach(workplace => { + const categoryName = workplace.category_name || '미분류'; + const isActive = workplace.is_active === 1 || workplace.is_active === true; + const purposeIcon = this.utils.getPurposeIcon(workplace.workplace_purpose); + + gridHtml += ` +
+
+
${purposeIcon}
+
+

${workplace.workplace_name}

+
+ ${workplace.category_id ? `🏭 ${categoryName}` : ''} + ${workplace.workplace_purpose ? `${workplace.workplace_purpose}` : ''} +
+
+
+ + + +
+
+ ${workplace.description ? `

${workplace.description}

` : ''} +
+
+ 등록: ${this.utils.formatDate(workplace.created_at)} + ${workplace.updated_at !== workplace.created_at ? `수정: ${this.utils.formatDate(workplace.updated_at)}` : ''} +
+
+ `; + }); + + grid.innerHTML = gridHtml; + + filtered.forEach(workplace => { + if (workplace.category_id) { + this.loadWorkplaceMapThumbnail(workplace); + } + }); + } + + /** + * 작업장 카드에 지도 썸네일 로드 + */ + async loadWorkplaceMapThumbnail(workplace) { + const thumbnailDiv = document.getElementById(`workplace-map-${workplace.workplace_id}`); + if (!thumbnailDiv) return; + + if (workplace.layout_image) { + const fullImageUrl = this.utils.getFullImageUrl(workplace.layout_image); + + let equipmentCount = 0; + try { + const eqResponse = await window.apiCall(`/equipments/workplace/${workplace.workplace_id}`, 'GET'); + if (eqResponse && eqResponse.success && Array.isArray(eqResponse.data)) { + equipmentCount = eqResponse.data.filter(eq => eq.map_x_percent != null).length; + } + } catch (e) { + console.debug('설비 정보 로드 실패'); + } + + const canvasId = `layout-canvas-${workplace.workplace_id}`; + thumbnailDiv.innerHTML = ` +
+
+ 📍 작업장 지도 + ${equipmentCount > 0 ? `설비 ${equipmentCount}개` : ''} +
+ +
클릭하여 지도 관리
+
+ `; + + await this.loadWorkplaceCanvasWithEquipments(workplace.workplace_id, fullImageUrl, canvasId); + return; + } + + try { + const response = await this.api.loadWorkplaceMapRegion(workplace.workplace_id); + + if (!response || (!response.success && !response.region_id)) { + thumbnailDiv.innerHTML = ` +
+
🗺️
+
클릭하여 지도 설정
+
+ `; + return; + } + + const region = response.success ? response.data : response; + + if (!region || region.x_start === undefined || region.y_start === undefined || + region.x_end === undefined || region.y_end === undefined) { + return; + } + + const category = this.state.categories.find(c => c.category_id === workplace.category_id); + if (!category || !category.layout_image) return; + + const fullImageUrl = this.utils.getFullImageUrl(category.layout_image); + + const canvasId = `thumbnail-canvas-${workplace.workplace_id}`; + thumbnailDiv.innerHTML = ` +
+
📍 공장 지도 내 위치
+ +
클릭하여 상세 지도 설정
+
+ `; + + const img = new Image(); + img.onload = function() { + const canvas = document.getElementById(canvasId); + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + + const x1 = (region.x_start / 100) * img.width; + const y1 = (region.y_start / 100) * img.height; + const x2 = (region.x_end / 100) * img.width; + const y2 = (region.y_end / 100) * img.height; + + const regionWidth = x2 - x1; + const regionHeight = y2 - y1; + + const maxThumbWidth = 350; + const scale = regionWidth > maxThumbWidth ? maxThumbWidth / regionWidth : 1; + + canvas.width = regionWidth * scale; + canvas.height = regionHeight * scale; + + ctx.drawImage( + img, + x1, y1, regionWidth, regionHeight, + 0, 0, canvas.width, canvas.height + ); + + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 3; + ctx.strokeRect(0, 0, canvas.width, canvas.height); + }; + + img.onerror = function() { + thumbnailDiv.innerHTML = ''; + }; + + img.src = fullImageUrl; + } catch (error) { + console.debug(`작업장 ${workplace.workplace_id}의 지도 영역 없음`); + } + } + + /** + * 작업장 캔버스에 설비 영역 함께 그리기 + */ + async loadWorkplaceCanvasWithEquipments(workplaceId, imageUrl, canvasId) { + const img = new Image(); + img.onload = async function() { + const canvas = document.getElementById(canvasId); + if (!canvas) return; + + const ctx = canvas.getContext('2d'); + + const maxThumbWidth = 400; + const scale = img.width > maxThumbWidth ? maxThumbWidth / img.width : 1; + + canvas.width = img.width * scale; + canvas.height = img.height * scale; + + ctx.drawImage(img, 0, 0, canvas.width, canvas.height); + + try { + const response = await window.apiCall(`/equipments/workplace/${workplaceId}`, 'GET'); + let equipments = []; + if (response && response.success && Array.isArray(response.data)) { + equipments = response.data.filter(eq => eq.map_x_percent != null); + } + + equipments.forEach(eq => { + const x = (parseFloat(eq.map_x_percent) / 100) * canvas.width; + const y = (parseFloat(eq.map_y_percent) / 100) * canvas.height; + const width = (parseFloat(eq.map_width_percent || 10) / 100) * canvas.width; + const height = (parseFloat(eq.map_height_percent || 10) / 100) * canvas.height; + + ctx.fillStyle = 'rgba(16, 185, 129, 0.2)'; + ctx.fillRect(x, y, width, height); + + ctx.strokeStyle = '#10b981'; + ctx.lineWidth = 2; + ctx.strokeRect(x, y, width, height); + + if (eq.equipment_code) { + ctx.font = 'bold 10px sans-serif'; + const textMetrics = ctx.measureText(eq.equipment_code); + ctx.fillStyle = 'rgba(255, 255, 255, 0.9)'; + ctx.fillRect(x + 2, y + 2, textMetrics.width + 6, 14); + ctx.fillStyle = '#047857'; + ctx.fillText(eq.equipment_code, x + 5, y + 12); + } + }); + } catch (error) { + console.debug('설비 영역 로드 실패'); + } + }; + img.src = imageUrl; + } + + /** + * 통계 업데이트 + */ + async updateStatistics() { + const stats = this.state.getStatistics(); + + const factoryCountEl = document.getElementById('factoryCount'); + const totalCountEl = document.getElementById('totalCount'); + const activeCountEl = document.getElementById('activeCount'); + const equipmentCountEl = document.getElementById('equipmentCount'); + + if (factoryCountEl) factoryCountEl.textContent = stats.factoryTotal; + if (totalCountEl) totalCountEl.textContent = stats.total; + if (activeCountEl) activeCountEl.textContent = stats.active; + + if (equipmentCountEl) { + try { + const equipments = await this.api.loadAllEquipments(); + equipmentCountEl.textContent = equipments.length; + } catch (e) { + equipmentCountEl.textContent = '-'; + } + } + + const sectionTotalEl = document.getElementById('sectionTotalCount'); + const sectionActiveEl = document.getElementById('sectionActiveCount'); + + if (sectionTotalEl) sectionTotalEl.textContent = stats.filteredTotal; + if (sectionActiveEl) sectionActiveEl.textContent = stats.filteredActive; + } + + /** + * 전체 새로고침 + */ + async refreshWorkplaces() { + const refreshBtn = document.querySelector('.btn-secondary'); + if (refreshBtn) { + const originalText = refreshBtn.innerHTML; + refreshBtn.innerHTML = '새로고침 중...'; + refreshBtn.disabled = true; + + await this.loadAllData(); + + refreshBtn.innerHTML = originalText; + refreshBtn.disabled = false; + } else { + await this.loadAllData(); + } + + window.showToast?.('데이터가 새로고침되었습니다.', 'success'); + } + + /** + * 디버그 + */ + debug() { + console.log('[WorkplaceController] 상태 디버그:'); + this.state.debug(); + } +} + +// 전역 인스턴스 생성 +window.WorkplaceController = new WorkplaceController(); + +// 하위 호환성: 기존 전역 함수들 +window.switchCategory = (categoryId) => window.WorkplaceController.switchCategory(categoryId); +window.renderCategoryTabs = () => window.WorkplaceController.renderCategoryTabs(); +window.renderWorkplaces = () => window.WorkplaceController.renderWorkplaces(); +window.updateStatistics = () => window.WorkplaceController.updateStatistics(); +window.refreshWorkplaces = () => window.WorkplaceController.refreshWorkplaces(); +window.loadAllData = () => window.WorkplaceController.loadAllData(); +window.updateLayoutPreview = (category) => window.WorkplaceController.updateLayoutPreview(category); + +// DOMContentLoaded 이벤트에서 초기화 +document.addEventListener('DOMContentLoaded', () => { + setTimeout(() => { + window.WorkplaceController.init(); + }, 100); +}); + +console.log('[Module] workplace-management/index.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/workplace-management/state.js b/deploy/tkfb-package/web-ui/js/workplace-management/state.js new file mode 100644 index 0000000..80986d1 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/workplace-management/state.js @@ -0,0 +1,284 @@ +/** + * Workplace Management - State Manager + * 작업장 관리 페이지의 전역 상태 관리 + */ + +class WorkplaceState { + constructor() { + // 마스터 데이터 + this.categories = []; + this.workplaces = []; + this.allEquipments = []; + this.existingEquipments = []; + + // 현재 상태 + this.currentCategoryId = ''; + this.currentEditingCategory = null; + this.currentEditingWorkplace = null; + this.currentWorkplaceMapId = null; + + // 작업장 지도 관련 + this.workplaceCanvas = null; + this.workplaceCtx = null; + this.workplaceImage = null; + this.workplaceIsDrawing = false; + this.workplaceStartX = 0; + this.workplaceStartY = 0; + this.workplaceCurrentRect = null; + this.workplaceEquipmentRegions = []; + + // 전체화면 편집기 관련 + this.fsCanvas = null; + this.fsCtx = null; + this.fsImage = null; + this.fsIsDrawing = false; + this.fsStartX = 0; + this.fsStartY = 0; + this.fsCurrentRect = null; + this.fsSidebarVisible = true; + + // 리스너 + this.listeners = new Map(); + + console.log('[WorkplaceState] 초기화 완료'); + } + + /** + * 상태 업데이트 + */ + update(key, value) { + const prevValue = this[key]; + this[key] = value; + this.notifyListeners(key, value, prevValue); + } + + /** + * 리스너 등록 + */ + subscribe(key, callback) { + if (!this.listeners.has(key)) { + this.listeners.set(key, []); + } + this.listeners.get(key).push(callback); + } + + /** + * 리스너 알림 + */ + notifyListeners(key, newValue, prevValue) { + const keyListeners = this.listeners.get(key) || []; + keyListeners.forEach(callback => { + try { + callback(newValue, prevValue); + } catch (error) { + console.error(`[WorkplaceState] 리스너 오류 (${key}):`, error); + } + }); + } + + /** + * 현재 카테고리 변경 + */ + setCurrentCategory(categoryId) { + const prevId = this.currentCategoryId; + this.currentCategoryId = categoryId === '' ? '' : categoryId; + this.notifyListeners('currentCategoryId', this.currentCategoryId, prevId); + } + + /** + * 현재 카테고리 정보 가져오기 + */ + getCurrentCategory() { + if (!this.currentCategoryId) return null; + return this.categories.find(c => c.category_id == this.currentCategoryId); + } + + /** + * 현재 카테고리별 작업장 가져오기 + */ + getFilteredWorkplaces() { + if (this.currentCategoryId === '') { + return this.workplaces; + } + return this.workplaces.filter(w => w.category_id == this.currentCategoryId); + } + + /** + * 작업장 지도 상태 초기화 + */ + resetWorkplaceMapState() { + this.workplaceCanvas = null; + this.workplaceCtx = null; + this.workplaceImage = null; + this.workplaceIsDrawing = false; + this.workplaceCurrentRect = null; + } + + /** + * 전체화면 편집기 상태 초기화 + */ + resetFullscreenState() { + this.fsCanvas = null; + this.fsCtx = null; + this.fsImage = null; + this.fsIsDrawing = false; + this.fsCurrentRect = null; + } + + /** + * 통계 계산 + */ + getStatistics() { + const total = this.workplaces.length; + const active = this.workplaces.filter(w => + w.is_active === 1 || w.is_active === true + ).length; + const factoryTotal = this.categories.length; + + const filtered = this.getFilteredWorkplaces(); + const filteredActive = filtered.filter(w => + w.is_active === 1 || w.is_active === true + ).length; + + return { + total, + active, + factoryTotal, + filteredTotal: filtered.length, + filteredActive + }; + } + + /** + * 상태 초기화 + */ + reset() { + this.currentEditingCategory = null; + this.currentEditingWorkplace = null; + this.currentWorkplaceMapId = null; + this.resetWorkplaceMapState(); + this.resetFullscreenState(); + } + + /** + * 디버그 출력 + */ + debug() { + console.log('[WorkplaceState] 현재 상태:', { + categories: this.categories.length, + workplaces: this.workplaces.length, + currentCategoryId: this.currentCategoryId, + allEquipments: this.allEquipments.length, + workplaceEquipmentRegions: this.workplaceEquipmentRegions.length + }); + } +} + +// 전역 인스턴스 생성 +window.WorkplaceState = new WorkplaceState(); + +// 하위 호환성을 위한 전역 변수 프록시 +const wpStateProxy = window.WorkplaceState; + +Object.defineProperties(window, { + categories: { + get: () => wpStateProxy.categories, + set: (v) => { wpStateProxy.categories = v; } + }, + workplaces: { + get: () => wpStateProxy.workplaces, + set: (v) => { wpStateProxy.workplaces = v; } + }, + currentCategoryId: { + get: () => wpStateProxy.currentCategoryId, + set: (v) => { wpStateProxy.currentCategoryId = v; } + }, + currentEditingCategory: { + get: () => wpStateProxy.currentEditingCategory, + set: (v) => { wpStateProxy.currentEditingCategory = v; } + }, + currentEditingWorkplace: { + get: () => wpStateProxy.currentEditingWorkplace, + set: (v) => { wpStateProxy.currentEditingWorkplace = v; } + }, + workplaceCanvas: { + get: () => wpStateProxy.workplaceCanvas, + set: (v) => { wpStateProxy.workplaceCanvas = v; } + }, + workplaceCtx: { + get: () => wpStateProxy.workplaceCtx, + set: (v) => { wpStateProxy.workplaceCtx = v; } + }, + workplaceImage: { + get: () => wpStateProxy.workplaceImage, + set: (v) => { wpStateProxy.workplaceImage = v; } + }, + workplaceIsDrawing: { + get: () => wpStateProxy.workplaceIsDrawing, + set: (v) => { wpStateProxy.workplaceIsDrawing = v; } + }, + workplaceStartX: { + get: () => wpStateProxy.workplaceStartX, + set: (v) => { wpStateProxy.workplaceStartX = v; } + }, + workplaceStartY: { + get: () => wpStateProxy.workplaceStartY, + set: (v) => { wpStateProxy.workplaceStartY = v; } + }, + workplaceCurrentRect: { + get: () => wpStateProxy.workplaceCurrentRect, + set: (v) => { wpStateProxy.workplaceCurrentRect = v; } + }, + workplaceEquipmentRegions: { + get: () => wpStateProxy.workplaceEquipmentRegions, + set: (v) => { wpStateProxy.workplaceEquipmentRegions = v; } + }, + existingEquipments: { + get: () => wpStateProxy.existingEquipments, + set: (v) => { wpStateProxy.existingEquipments = v; } + }, + allEquipments: { + get: () => wpStateProxy.allEquipments, + set: (v) => { wpStateProxy.allEquipments = v; } + }, + fsCanvas: { + get: () => wpStateProxy.fsCanvas, + set: (v) => { wpStateProxy.fsCanvas = v; } + }, + fsCtx: { + get: () => wpStateProxy.fsCtx, + set: (v) => { wpStateProxy.fsCtx = v; } + }, + fsImage: { + get: () => wpStateProxy.fsImage, + set: (v) => { wpStateProxy.fsImage = v; } + }, + fsIsDrawing: { + get: () => wpStateProxy.fsIsDrawing, + set: (v) => { wpStateProxy.fsIsDrawing = v; } + }, + fsStartX: { + get: () => wpStateProxy.fsStartX, + set: (v) => { wpStateProxy.fsStartX = v; } + }, + fsStartY: { + get: () => wpStateProxy.fsStartY, + set: (v) => { wpStateProxy.fsStartY = v; } + }, + fsCurrentRect: { + get: () => wpStateProxy.fsCurrentRect, + set: (v) => { wpStateProxy.fsCurrentRect = v; } + }, + fsSidebarVisible: { + get: () => wpStateProxy.fsSidebarVisible, + set: (v) => { wpStateProxy.fsSidebarVisible = v; } + } +}); + +// currentWorkplaceMapId를 window에도 설정 +Object.defineProperty(window, 'currentWorkplaceMapId', { + get: () => wpStateProxy.currentWorkplaceMapId, + set: (v) => { wpStateProxy.currentWorkplaceMapId = v; } +}); + +console.log('[Module] workplace-management/state.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/workplace-management/utils.js b/deploy/tkfb-package/web-ui/js/workplace-management/utils.js new file mode 100644 index 0000000..04de92e --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/workplace-management/utils.js @@ -0,0 +1,154 @@ +/** + * Workplace Management - Utilities + * 작업장 관리 관련 유틸리티 함수들 + */ + +class WorkplaceUtils { + constructor() { + console.log('[WorkplaceUtils] 초기화 완료'); + } + + /** + * 날짜 포맷팅 + */ + formatDate(dateString) { + if (!dateString) return ''; + const date = new Date(dateString); + return date.toLocaleDateString('ko-KR', { + year: 'numeric', + month: '2-digit', + day: '2-digit' + }); + } + + /** + * API URL 생성 + */ + getApiBaseUrl() { + return window.API_BASE_URL || 'http://localhost:20005/api'; + } + + /** + * 이미지 URL 생성 + */ + getFullImageUrl(imagePath) { + if (!imagePath) return null; + if (imagePath.startsWith('http')) return imagePath; + return `${this.getApiBaseUrl()}${imagePath}`.replace('/api/', '/'); + } + + /** + * 작업장 용도 아이콘 반환 + */ + getPurposeIcon(purpose) { + const icons = { + '작업구역': '🔧', + '설비': '⚙️', + '휴게시설': '☕', + '회의실': '💼', + '창고': '📦', + '기타': '📍' + }; + return purpose ? (icons[purpose] || '📍') : '🏗️'; + } + + /** + * 퍼센트를 픽셀로 변환 + */ + percentToPixel(percent, canvasSize) { + return (percent / 100) * canvasSize; + } + + /** + * 픽셀을 퍼센트로 변환 + */ + pixelToPercent(pixel, canvasSize) { + return (pixel / canvasSize) * 100; + } + + /** + * 영역 좌표 정규화 (음수 처리) + */ + normalizeRect(rect, canvasWidth, canvasHeight) { + const xPercent = this.pixelToPercent( + Math.min(rect.x, rect.x + rect.width), + canvasWidth + ); + const yPercent = this.pixelToPercent( + Math.min(rect.y, rect.y + rect.height), + canvasHeight + ); + const widthPercent = this.pixelToPercent( + Math.abs(rect.width), + canvasWidth + ); + const heightPercent = this.pixelToPercent( + Math.abs(rect.height), + canvasHeight + ); + + return { xPercent, yPercent, widthPercent, heightPercent }; + } +} + +// 전역 인스턴스 생성 +window.WorkplaceUtils = new WorkplaceUtils(); + +// 하위 호환성: 기존 함수들 +window.formatDate = (dateString) => window.WorkplaceUtils.formatDate(dateString); + +// 토스트 메시지 표시 +window.showToast = function(message, type = 'info') { + // 기존 토스트 제거 + const existingToast = document.querySelector('.toast'); + if (existingToast) { + existingToast.remove(); + } + + // 새 토스트 생성 + const toast = document.createElement('div'); + toast.className = `toast toast-${type}`; + toast.textContent = message; + + // 스타일 적용 + Object.assign(toast.style, { + position: 'fixed', + top: '20px', + right: '20px', + padding: '12px 24px', + borderRadius: '8px', + color: 'white', + fontWeight: '500', + zIndex: '1000', + transform: 'translateX(100%)', + transition: 'transform 0.3s ease' + }); + + // 타입별 배경색 + const colors = { + success: '#10b981', + error: '#ef4444', + warning: '#f59e0b', + info: '#3b82f6' + }; + toast.style.backgroundColor = colors[type] || colors.info; + + document.body.appendChild(toast); + + // 애니메이션 + setTimeout(() => { + toast.style.transform = 'translateX(0)'; + }, 100); + + // 자동 제거 + setTimeout(() => { + toast.style.transform = 'translateX(100%)'; + setTimeout(() => { + if (toast.parentNode) { + toast.remove(); + } + }, 300); + }, 3000); +}; + +console.log('[Module] workplace-management/utils.js 로드 완료'); diff --git a/deploy/tkfb-package/web-ui/js/workplace-status.js b/deploy/tkfb-package/web-ui/js/workplace-status.js new file mode 100644 index 0000000..6e72dd7 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/workplace-status.js @@ -0,0 +1,1786 @@ +// 작업장 현황 JavaScript + +let selectedCategory = null; +let workplaceData = []; +let mapRegions = []; // 작업장 영역 데이터 +let canvas = null; +let ctx = null; +let canvasImage = null; + +// 금일 TBM 작업자 데이터 +let todayWorkers = []; + +// 금일 출입 신청 데이터 +let todayVisitors = []; + +// ==================== 초기화 ==================== + +document.addEventListener('DOMContentLoaded', async () => { + await loadCategories(); + + // 이벤트 리스너 + document.getElementById('categorySelect').addEventListener('change', onCategoryChange); + document.getElementById('refreshMapBtn').addEventListener('click', refreshMapData); + + // 기본값으로 제1공장 선택 + await selectFirstCategory(); + + // 임시 이동된 설비 로드 + await loadMovedEquipments(); +}); + +// ==================== 카테고리 (공장) 로드 ==================== + +async function loadCategories() { + try { + const response = await window.apiCall('/workplaces/categories', 'GET'); + + if (response && response.success) { + const categories = response.data || []; + const select = document.getElementById('categorySelect'); + + categories.forEach(cat => { + const option = document.createElement('option'); + option.value = cat.category_id; + option.textContent = cat.category_name; + option.dataset.layoutImage = cat.layout_image; + select.appendChild(option); + }); + } + } catch (error) { + console.error('카테고리 로드 오류:', error); + } +} + +/** + * 첫 번째 카테고리 자동 선택 + */ +async function selectFirstCategory() { + const select = document.getElementById('categorySelect'); + if (select.options.length > 1) { + // 첫 번째 옵션 선택 (인덱스 0은 "공장을 선택하세요") + select.selectedIndex = 1; + // 변경 이벤트 트리거 + await onCategoryChange({ target: select }); + } +} + +// ==================== 공장 선택 ==================== + +async function onCategoryChange(e) { + const categoryId = e.target.value; + + if (!categoryId) { + document.getElementById('workplaceMapContainer').style.display = 'none'; + document.getElementById('mapPlaceholder').style.display = 'flex'; + return; + } + + const selectedOption = e.target.options[e.target.selectedIndex]; + const layoutImage = selectedOption.dataset.layoutImage; + + selectedCategory = { + category_id: categoryId, + category_name: selectedOption.textContent, + layout_image: layoutImage + }; + + // 지도 로드 + await loadWorkplaceMap(); + + // 금일 작업 데이터 로드 + await loadTodayData(); + + // 지도 렌더링 + renderMap(); +} + +// ==================== 작업장 지도 로드 ==================== + +async function loadWorkplaceMap() { + try { + // 작업장 데이터 로드 + const response = await window.apiCall(`/workplaces?category_id=${selectedCategory.category_id}`, 'GET'); + + if (response && response.success) { + workplaceData = response.data || []; + } + + // 작업장 영역 데이터 로드 (map-regions API) + const regionsResponse = await window.apiCall(`/workplaces/categories/${selectedCategory.category_id}/map-regions`, 'GET'); + + if (regionsResponse && regionsResponse.success) { + mapRegions = regionsResponse.data || []; + console.log('[지도] 로드된 영역:', mapRegions); + } + + // 이미지 로드 + await loadMapImage(); + + // 지도 컨테이너 표시 + document.getElementById('mapPlaceholder').style.display = 'none'; + document.getElementById('workplaceMapContainer').style.display = 'block'; + } catch (error) { + console.error('작업장 데이터 로드 오류:', error); + } +} + +async function loadMapImage() { + return new Promise((resolve, reject) => { + const img = new Image(); + + const baseUrl = (window.API_BASE_URL || 'http://localhost:20005').replace('/api', ''); + const fullImageUrl = selectedCategory.layout_image.startsWith('http') + ? selectedCategory.layout_image + : `${baseUrl}${selectedCategory.layout_image}`; + + img.onload = () => { + canvasImage = img; + + // 캔버스 초기화 + canvas = document.getElementById('workplaceMapCanvas'); + canvas.width = img.width; + canvas.height = img.height; + ctx = canvas.getContext('2d'); + + // 클릭 이벤트 + canvas.addEventListener('click', onMapClick); + + resolve(); + }; + + img.onerror = () => { + console.error('이미지 로드 실패:', fullImageUrl); + reject(); + }; + + img.src = fullImageUrl; + }); +} + +// ==================== 금일 데이터 로드 ==================== + +async function loadTodayData() { + // 로컬 시간대 기준으로 오늘 날짜 구하기 (UTC가 아닌 한국 시간 기준) + const now = new Date(); + const year = now.getFullYear(); + const month = String(now.getMonth() + 1).padStart(2, '0'); + const day = String(now.getDate()).padStart(2, '0'); + const today = `${year}-${month}-${day}`; + + console.log('[대시보드] 조회 날짜 (로컬):', today); + + // TBM 작업자 데이터 로드 + await loadTodayWorkers(today); + + // 출입 신청 데이터 로드 + await loadTodayVisitors(today); +} + +async function loadTodayWorkers(date) { + try { + const response = await window.apiCall(`/tbm/sessions/date/${date}`, 'GET'); + + if (response && response.success) { + const sessions = response.data || []; + todayWorkers = []; + + // 각 세션의 작업 정보 추가 + sessions.forEach(session => { + if (session.workplace_id) { + const memberCount = session.team_member_count || 0; + const leaderCount = session.leader_id ? 1 : 0; + const totalCount = memberCount + leaderCount; + + todayWorkers.push({ + workplace_id: session.workplace_id, + task_name: session.task_name || '작업', + work_location: session.work_location || '', + member_count: totalCount, + project_name: session.project_name || '' + }); + + console.log(`[TBM] 작업 추가: ${session.work_location || session.workplace_id} - ${session.task_name} (${totalCount}명)`); + } + }); + + console.log('로드된 작업자:', todayWorkers); + } + } catch (error) { + console.error('TBM 작업자 데이터 로드 오류:', error); + } +} + +async function loadTodayVisitors(date) { + try { + // 날짜 형식 확인 (YYYY-MM-DD) + const formattedDate = date.split('T')[0]; + + const response = await window.apiCall(`/workplace-visits/requests`, 'GET'); + + if (response && response.success) { + const requests = response.data || []; + + // 금일 날짜와 승인된 요청 필터링 + todayVisitors = requests.filter(req => { + // UTC 변환 없이 로컬 날짜로 비교 + const visitDateObj = new Date(req.visit_date); + const visitYear = visitDateObj.getFullYear(); + const visitMonth = String(visitDateObj.getMonth() + 1).padStart(2, '0'); + const visitDay = String(visitDateObj.getDate()).padStart(2, '0'); + const visitDate = `${visitYear}-${visitMonth}-${visitDay}`; + + return visitDate === formattedDate && + (req.status === 'approved' || req.status === 'training_completed'); + }).map(req => ({ + workplace_id: req.workplace_id, + visitor_company: req.visitor_company, + visitor_count: req.visitor_count, + visit_time: req.visit_time, + purpose_name: req.purpose_name, + status: req.status + })); + + console.log('로드된 방문자:', todayVisitors); + } + } catch (error) { + console.error('출입 신청 데이터 로드 오류:', error); + } +} + +// ==================== 지도 렌더링 ==================== + +function renderMap() { + if (!canvas || !ctx || !canvasImage) return; + + // 이미지 그리기 + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.drawImage(canvasImage, 0, 0); + + // 모든 작업장 영역 표시 + mapRegions.forEach(region => { + // 해당 작업장의 작업자/방문자 인원 계산 + const workers = todayWorkers.filter(w => w.workplace_id === region.workplace_id); + const visitors = todayVisitors.filter(v => v.workplace_id === region.workplace_id); + + const totalWorkerCount = workers.reduce((sum, w) => sum + (w.member_count || 0), 0); + const totalVisitorCount = visitors.reduce((sum, v) => sum + (v.visitor_count || 0), 0); + + // 영역 그리기 + drawWorkplaceRegion(region, totalWorkerCount, totalVisitorCount); + }); +} + +function drawWorkplaceRegion(region, workerCount, visitorCount) { + // 사각형 좌표 변환 + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + const width = x2 - x1; + const height = y2 - y1; + const centerX = x1 + width / 2; + const centerY = y1 + height / 2; + + // 색상 결정 + let fillColor, strokeColor; + const hasActivity = workerCount > 0 || visitorCount > 0; + + if (workerCount > 0 && visitorCount > 0) { + // 둘 다 있음 - 초록색 + fillColor = 'rgba(34, 197, 94, 0.3)'; + strokeColor = 'rgb(34, 197, 94)'; + } else if (workerCount > 0) { + // 내부 작업자만 - 파란색 + fillColor = 'rgba(59, 130, 246, 0.3)'; + strokeColor = 'rgb(59, 130, 246)'; + } else if (visitorCount > 0) { + // 외부 방문자만 - 보라색 + fillColor = 'rgba(168, 85, 247, 0.3)'; + strokeColor = 'rgb(168, 85, 247)'; + } else { + // 인원 없음 - 회색 테두리만 + fillColor = 'rgba(0, 0, 0, 0)'; // 투명 + strokeColor = 'rgb(156, 163, 175)'; // 회색 + } + + // 사각형 그리기 + ctx.save(); + ctx.fillStyle = fillColor; + ctx.fillRect(x1, y1, width, height); + ctx.strokeStyle = strokeColor; + ctx.lineWidth = hasActivity ? 3 : 2; + ctx.strokeRect(x1, y1, width, height); + ctx.restore(); + + // 인원수 표시 (인원이 있을 때만) + if (hasActivity) { + ctx.save(); + ctx.font = 'bold 16px sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + + // 배경 원 + ctx.beginPath(); + ctx.arc(centerX, centerY, 20, 0, Math.PI * 2); + ctx.fillStyle = 'white'; + ctx.fill(); + ctx.strokeStyle = strokeColor; + ctx.lineWidth = 2; + ctx.stroke(); + + // 텍스트 + const totalCount = workerCount + visitorCount; + ctx.fillStyle = strokeColor; + ctx.fillText(totalCount.toString(), centerX, centerY); + ctx.restore(); + } else { + // 인원이 없을 때는 작업장 이름만 표시 + ctx.save(); + ctx.font = '12px sans-serif'; + ctx.textAlign = 'center'; + ctx.textBaseline = 'middle'; + ctx.fillStyle = 'rgb(107, 114, 128)'; + ctx.fillText(region.workplace_name, centerX, centerY); + ctx.restore(); + } +} + +// ==================== 지도 클릭 ==================== + +function onMapClick(e) { + const rect = canvas.getBoundingClientRect(); + const x = (e.clientX - rect.left) / rect.width * canvas.width; + const y = (e.clientY - rect.top) / rect.height * canvas.height; + + // 클릭한 위치의 작업장 영역 찾기 + for (const region of mapRegions) { + if (isPointInRegion(x, y, region)) { + // 작업장 정보를 찾아서 모달 표시 + const workplace = workplaceData.find(w => w.workplace_id === region.workplace_id); + if (workplace) { + showWorkplaceDetail({ ...workplace, ...region }); + } else { + // 작업장 정보가 없으면 region 데이터만 사용 + showWorkplaceDetail(region); + } + break; + } + } +} + +function isPointInRegion(x, y, region) { + // 사각형 영역 내부 체크 + const x1 = (region.x_start / 100) * canvas.width; + const y1 = (region.y_start / 100) * canvas.height; + const x2 = (region.x_end / 100) * canvas.width; + const y2 = (region.y_end / 100) * canvas.height; + + return x >= x1 && x <= x2 && y >= y1 && y <= y2; +} + +// ==================== 작업장 상세 정보 모달 ==================== + +// 현재 선택된 작업장 정보 (모달용) +let currentModalWorkplace = null; + +function showWorkplaceDetail(workplace) { + currentModalWorkplace = workplace; + const workers = todayWorkers.filter(w => w.workplace_id === workplace.workplace_id); + const visitors = todayVisitors.filter(v => v.workplace_id === workplace.workplace_id); + + // 모달 제목 + document.getElementById('modalWorkplaceName').textContent = workplace.workplace_name; + document.getElementById('modalWorkplaceDesc').textContent = `${selectedCategory.category_name} • ${workplace.description || ''}`; + + // 요약 카드 업데이트 + const totalWorkers = workers.reduce((sum, w) => sum + (w.member_count || 0), 0); + const totalVisitors = visitors.reduce((sum, v) => sum + (v.visitor_count || 0), 0); + + document.getElementById('summaryWorkerCount').textContent = totalWorkers; + document.getElementById('summaryVisitorCount').textContent = totalVisitors; + document.getElementById('summaryTaskCount').textContent = workers.length; + + // 배지 업데이트 + document.getElementById('workerCountBadge').textContent = totalWorkers; + document.getElementById('visitorCountBadge').textContent = totalVisitors; + + // 현황 개요 탭 - 현재 작업 목록 + renderCurrentTasks(workers); + + // 현황 개요 탭 - 설비 현황 + loadEquipmentStatus(workplace.workplace_id); + + // 작업자 탭 + renderWorkersTab(workers); + + // 방문자 탭 + renderVisitorsTab(visitors); + + // 상세 지도 초기화 + initDetailMap(workplace); + + // 첫 번째 탭 활성화 + switchWorkplaceTab('overview'); + + // 모달 표시 + document.getElementById('workplaceDetailModal').style.display = 'flex'; +} + +// 현재 작업 목록 렌더링 +function renderCurrentTasks(workers) { + const container = document.getElementById('currentTasksList'); + + if (workers.length === 0) { + container.innerHTML = '

현재 진행 중인 작업이 없습니다.

'; + return; + } + + let html = ''; + workers.forEach(worker => { + html += ` +
+
+

${escapeHtml(worker.task_name)}

+

+ ${worker.work_location ? `📍 ${escapeHtml(worker.work_location)}` : ''} + ${worker.project_name ? ` • 📁 ${escapeHtml(worker.project_name)}` : ''} +

+
+
+ 👷 + ${parseInt(worker.member_count) || 0}명 +
+
+ `; + }); + + container.innerHTML = html; +} + +// 설비 현황 로드 +async function loadEquipmentStatus(workplaceId) { + const container = document.getElementById('equipmentSummary'); + + try { + const response = await window.apiCall(`/equipments?workplace_id=${workplaceId}`, 'GET'); + + if (response && response.success && response.data && response.data.length > 0) { + const equipments = response.data; + let html = ''; + + // 최대 4개만 표시 + equipments.slice(0, 4).forEach(eq => { + const statusClass = eq.status === 'active' ? 'normal' : + eq.status === 'maintenance' ? 'warning' : 'error'; + const statusText = eq.status === 'active' ? '정상' : + eq.status === 'maintenance' ? '점검중' : '수리필요'; + + html += ` +
+ ⚙️ +
+

${escapeHtml(eq.equipment_name)}

+

${statusText}

+
+
+ `; + }); + + if (equipments.length > 4) { + html += `
+${equipments.length - 4}개 더...
`; + } + + container.innerHTML = html; + } else { + container.innerHTML = '

등록된 설비가 없습니다.

'; + } + } catch (error) { + console.error('설비 현황 로드 오류:', error); + container.innerHTML = '

설비 정보를 불러올 수 없습니다.

'; + } +} + +// 작업자 탭 렌더링 +function renderWorkersTab(workers) { + const container = document.getElementById('internalWorkersList'); + + if (workers.length === 0) { + container.innerHTML = '

금일 작업 예정 인원이 없습니다.

'; + return; + } + + let html = ''; + workers.forEach(worker => { + html += ` +
+
+

${escapeHtml(worker.task_name)}

+ ${parseInt(worker.member_count) || 0}명 +
+ ${worker.work_location ? `

📍 ${escapeHtml(worker.work_location)}

` : ''} + ${worker.project_name ? `

📁 ${escapeHtml(worker.project_name)}

` : ''} +
+ `; + }); + + container.innerHTML = html; +} + +// 방문자 탭 렌더링 +function renderVisitorsTab(visitors) { + const container = document.getElementById('externalVisitorsList'); + + if (visitors.length === 0) { + container.innerHTML = '

금일 방문 예정 인원이 없습니다.

'; + return; + } + + let html = ''; + visitors.forEach(visitor => { + const statusText = visitor.status === 'training_completed' ? '교육 완료' : '승인됨'; + + html += ` +
+
+

${escapeHtml(visitor.visitor_company)}

+ ${parseInt(visitor.visitor_count) || 0}명 • ${statusText} +
+

⏰ ${escapeHtml(visitor.visit_time)}

+

📋 ${escapeHtml(visitor.purpose_name)}

+
+ `; + }); + + container.innerHTML = html; +} + +// 상세 지도 초기화 +async function initDetailMap(workplace) { + const container = document.getElementById('detailMapContainer'); + const legendContainer = document.getElementById('detailMapLegend'); + + // 작업장에 레이아웃 이미지가 있는지 확인 + if (workplace.layout_image) { + const baseUrl = (window.API_BASE_URL || 'http://localhost:20005').replace('/api', ''); + const imageUrl = workplace.layout_image.startsWith('http') + ? workplace.layout_image + : `${baseUrl}${workplace.layout_image}`; + + // 이미지를 먼저 로드하여 비율 계산 + const img = new Image(); + img.onload = async () => { + // 이미지 래퍼를 생성하여 이미지와 마커가 같은 영역을 공유하도록 함 + container.innerHTML = ` +
+ ${workplace.workplace_name} 상세 지도 +
+
+ + `; + + // 설비 마커 로드 + await loadEquipmentMarkers(workplace.workplace_id); + }; + + img.onerror = () => { + container.innerHTML = ` +
+ 🗺️ +

지도 이미지를 불러올 수 없습니다.

+
+ `; + }; + + img.src = imageUrl; + + // 범례 표시 + legendContainer.innerHTML = ` +
+
+ 정상 가동 +
+
+
+ 점검 중 +
+
+
+ 수리 필요 +
+
+
+ 비활성 +
+ `; + } else { + container.innerHTML = ` +
+ 🗺️ +

상세 지도가 등록되지 않았습니다.

+

작업장 관리에서 레이아웃 이미지를 등록해주세요.

+
+ `; + legendContainer.innerHTML = ''; + } +} + +// 설비 마커 로드 및 표시 +async function loadEquipmentMarkers(workplaceId) { + const markersLayer = document.getElementById('equipmentMarkersLayer'); + if (!markersLayer) return; + + try { + const response = await window.apiCall(`/equipments?workplace_id=${workplaceId}`, 'GET'); + + if (response && response.success && response.data && response.data.length > 0) { + const equipments = response.data; + let markersHtml = ''; + + equipments.forEach(eq => { + // 위치 정보가 있는 설비만 마커 표시 + if (eq.map_x_percent != null && eq.map_y_percent != null) { + // 임시 이동된 설비는 별도 클래스 적용 + let statusClass = ''; + if (eq.is_temporarily_moved) { + statusClass = 'moved'; + } else { + statusClass = eq.status === 'active' ? 'active' : + eq.status === 'maintenance' ? 'maintenance' : + eq.status === 'repair_needed' ? 'repair' : 'inactive'; + } + + // 마커 크기 (기본값 또는 설정된 값) + const width = eq.map_width_percent || 8; + const height = eq.map_height_percent || 6; + + // 표시 이름: 설비 이름만 + const displayName = eq.equipment_name; + const movedBadge = eq.is_temporarily_moved ? ' 🚚' : ''; + + markersHtml += ` +
+ ${displayName}${movedBadge} +
+ `; + } + }); + + if (markersHtml) { + markersLayer.innerHTML = markersHtml; + } else { + markersLayer.innerHTML = '
위치가 등록된 설비가 없습니다.
'; + } + } else { + markersLayer.innerHTML = '
등록된 설비가 없습니다.
'; + } + } catch (error) { + console.error('설비 마커 로드 오류:', error); + markersLayer.innerHTML = '
설비 정보를 불러올 수 없습니다.
'; + } +} + +// 설비 툴팁 표시 +function showEquipmentTooltip(event, equipment) { + event.stopPropagation(); + + // 기존 툴팁 제거 + const existingTooltip = document.querySelector('.equipment-tooltip'); + if (existingTooltip) { + existingTooltip.remove(); + } + + const statusText = equipment.status === 'active' ? '정상 가동' : + equipment.status === 'maintenance' ? '점검 중' : + equipment.status === 'repair_needed' ? '수리 필요' : '비활성'; + + const statusClass = equipment.status === 'active' ? 'active' : + equipment.status === 'maintenance' ? 'maintenance' : + equipment.status === 'repair_needed' ? 'repair' : 'inactive'; + + const tooltip = document.createElement('div'); + tooltip.className = 'equipment-tooltip'; + tooltip.innerHTML = ` +
+ ${equipment.equipment_name} + ${statusText} +
+
+

코드: ${equipment.equipment_code}

+ ${equipment.equipment_type ? `

유형: ${equipment.equipment_type}

` : ''} + ${equipment.model_name ? `

모델: ${equipment.model_name}

` : ''} + ${equipment.manufacturer ? `

제조사: ${equipment.manufacturer}

` : ''} +
+
+ +
+ + `; + + // 툴팁 위치 설정 + const container = document.getElementById('detailMapContainer'); + const rect = container.getBoundingClientRect(); + tooltip.style.left = `${event.clientX - rect.left + 10}px`; + tooltip.style.top = `${event.clientY - rect.top + 10}px`; + + container.appendChild(tooltip); + + // 외부 클릭 시 툴팁 닫기 + setTimeout(() => { + document.addEventListener('click', function closeTooltip(e) { + if (!tooltip.contains(e.target)) { + tooltip.remove(); + document.removeEventListener('click', closeTooltip); + } + }); + }, 100); +} + +// 탭 전환 +function switchWorkplaceTab(tabName) { + // 모든 탭 비활성화 + document.querySelectorAll('.workplace-tab').forEach(tab => { + tab.classList.remove('active'); + }); + document.querySelectorAll('.workplace-tab-content').forEach(content => { + content.classList.remove('active'); + }); + + // 선택한 탭 활성화 + document.querySelector(`.workplace-tab[data-tab="${tabName}"]`).classList.add('active'); + document.getElementById(`tab-${tabName}`).classList.add('active'); + + // 이동 설비 탭 선택 시 데이터 로드 + if (tabName === 'moved-eq' && currentModalWorkplace) { + loadWorkplaceMovedEquipments(currentModalWorkplace.workplace_id); + } +} + +// 순회점검 페이지로 이동 +function openPatrolPage() { + closeWorkplaceModal(); + window.location.href = `/pages/inspection/daily-patrol.html?category=${selectedCategory.category_id}`; +} + +function closeWorkplaceModal() { + document.getElementById('workplaceDetailModal').style.display = 'none'; + currentModalWorkplace = null; +} + +// ==================== 새로고침 ==================== + +async function refreshMapData() { + if (!selectedCategory) return; + + await loadTodayData(); + renderMap(); +} + +// 전역 함수로 노출 +window.closeWorkplaceModal = closeWorkplaceModal; +window.switchWorkplaceTab = switchWorkplaceTab; +window.openPatrolPage = openPatrolPage; +window.showEquipmentTooltip = showEquipmentTooltip; + +// ========================================== +// 설비 상세 슬라이드 패널 +// ========================================== + +let currentPanelEquipment = null; +let panelFactories = []; +let panelWorkplaces = []; +let panelMovePosition = null; +let panelRepairCategories = []; +let panelRepairPhotoBases = []; + +const STATUS_LABELS = { + active: '정상 가동', + maintenance: '점검 중', + repair_needed: '수리 필요', + inactive: '비활성', + external: '외부 반출', + repair_external: '수리 외주' +}; + +// 패널 열기 +async function openEquipmentPanel(equipment) { + currentPanelEquipment = equipment; + + // 패널 헤더 설정 (설비 이름만) + document.getElementById('panelEquipmentTitle').textContent = equipment.equipment_name; + + const statusEl = document.getElementById('panelEquipmentStatus'); + statusEl.textContent = STATUS_LABELS[equipment.status] || equipment.status; + statusEl.className = `slide-panel-status ${equipment.status}`; + + // 기본 정보 렌더링 + renderPanelInfo(equipment); + + // 패널 열기 + document.getElementById('equipmentSlidePanel').classList.add('open'); + + // 데이터 로드 + await Promise.all([ + loadPanelPhotos(), + loadPanelRepairHistory(), + loadPanelExternalLogs(), + loadPanelFactories(), + loadPanelRepairCategories() + ]); +} + +// 패널 닫기 +function closeEquipmentPanel() { + document.getElementById('equipmentSlidePanel').classList.remove('open'); + currentPanelEquipment = null; +} + +// 기본 정보 렌더링 +function renderPanelInfo(eq) { + document.getElementById('panelEquipmentInfo').innerHTML = ` +
+ 모델명 + ${eq.model_name || '-'} +
+
+ 규격 + ${eq.specifications || '-'} +
+
+ 제조사 + ${eq.manufacturer || '-'} +
+
+ 구입처 + ${eq.supplier || '-'} +
+
+ 설비유형 + ${eq.equipment_type || '-'} +
+
+ 구입일 + ${eq.installation_date ? formatPanelDate(eq.installation_date) : '-'} +
+ `; +} + +// 사진 로드 +async function loadPanelPhotos() { + if (!currentPanelEquipment) return; + + try { + const response = await window.apiCall(`/equipments/${currentPanelEquipment.equipment_id}/photos`, 'GET'); + if (response && response.success) { + renderPanelPhotos(response.data); + } + } catch (error) { + console.error('사진 로드 실패:', error); + document.getElementById('panelPhotoGrid').innerHTML = + '
사진을 불러올 수 없습니다
'; + } +} + +function renderPanelPhotos(photos) { + const grid = document.getElementById('panelPhotoGrid'); + + if (!photos || photos.length === 0) { + grid.innerHTML = '
등록된 사진이 없습니다
'; + return; + } + + grid.innerHTML = photos.map(photo => ` +
+ + +
+ `).join(''); +} + +// 사진 확대 보기 +function viewPanelPhoto(url) { + // 간단한 이미지 뷰어 + const viewer = document.createElement('div'); + viewer.style.cssText = 'position:fixed;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.9);display:flex;align-items:center;justify-content:center;z-index:3000;cursor:pointer;'; + viewer.innerHTML = ``; + viewer.onclick = () => viewer.remove(); + document.body.appendChild(viewer); +} + +// 사진 업로드 모달 +function openPanelPhotoUpload() { + document.getElementById('panelPhotoInput').value = ''; + document.getElementById('panelPhotoDesc').value = ''; + document.getElementById('panelPhotoPreview').innerHTML = ''; + document.getElementById('panelPhotoModal').style.display = 'flex'; +} + +function closePanelPhotoModal() { + document.getElementById('panelPhotoModal').style.display = 'none'; +} + +function previewPanelPhoto(event) { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = e => { + document.getElementById('panelPhotoPreview').innerHTML = + ``; + }; + reader.readAsDataURL(file); + } +} + +async function uploadPanelPhoto() { + const fileInput = document.getElementById('panelPhotoInput'); + const description = document.getElementById('panelPhotoDesc').value; + + if (!fileInput.files[0]) { + alert('사진을 선택하세요.'); + return; + } + + const reader = new FileReader(); + reader.onload = async e => { + try { + const response = await window.apiCall(`/equipments/${currentPanelEquipment.equipment_id}/photos`, 'POST', { + photo_base64: e.target.result, + description: description + }); + + if (response && response.success) { + closePanelPhotoModal(); + loadPanelPhotos(); + } + } catch (error) { + console.error('업로드 실패:', error); + alert('사진 업로드에 실패했습니다.'); + } + }; + reader.readAsDataURL(fileInput.files[0]); +} + +async function deletePanelPhoto(photoId) { + if (!confirm('이 사진을 삭제하시겠습니까?')) return; + + try { + await window.apiCall(`/equipments/photos/${photoId}`, 'DELETE'); + loadPanelPhotos(); + } catch (error) { + console.error('삭제 실패:', error); + alert('삭제에 실패했습니다.'); + } +} + +// 수리 이력 로드 +async function loadPanelRepairHistory() { + if (!currentPanelEquipment) return; + + try { + const response = await window.apiCall(`/equipments/${currentPanelEquipment.equipment_id}/repair-history`, 'GET'); + if (response && response.success) { + renderPanelRepairHistory(response.data); + } + } catch (error) { + console.error('수리 이력 로드 실패:', error); + } +} + +function renderPanelRepairHistory(history) { + const container = document.getElementById('panelRepairHistory'); + + if (!history || history.length === 0) { + container.innerHTML = '
수리 이력이 없습니다
'; + return; + } + + container.innerHTML = history.slice(0, 5).map(h => { + const statusLabels = { + reported: '신고됨', received: '접수', in_progress: '처리중', completed: '완료', closed: '종료' + }; + const statusLabel = statusLabels[h.status] || h.status; + const statusClass = (h.status === 'completed' || h.status === 'closed') ? 'completed' : 'pending'; + + return ` +
+ ${formatPanelDate(h.created_at)} +
+
${h.item_name || '수리 요청'}
+
${truncateText(h.description, 30)}
+
+ ${statusLabel} +
+ `; + }).join(''); +} + +// 외부반출 이력 로드 +async function loadPanelExternalLogs() { + if (!currentPanelEquipment) return; + + try { + const response = await window.apiCall(`/equipments/${currentPanelEquipment.equipment_id}/external-logs`, 'GET'); + if (response && response.success) { + renderPanelExternalLogs(response.data); + } + } catch (error) { + console.error('외부반출 이력 로드 실패:', error); + } +} + +function renderPanelExternalLogs(logs) { + const container = document.getElementById('panelExternalHistory'); + + if (!logs || logs.length === 0) { + container.innerHTML = '
외부반출 이력이 없습니다
'; + return; + } + + container.innerHTML = logs.slice(0, 5).map(log => { + const isReturned = !!log.actual_return_date; + const statusClass = isReturned ? 'returned' : 'exported'; + const statusLabel = isReturned ? '반입완료' : '반출중'; + + return ` +
+ ${formatPanelDate(log.export_date)} +
+
${log.destination || '외부'}
+
${truncateText(log.reason, 30)}
+
+ ${!isReturned + ? `` + : `${statusLabel}` + } +
+ `; + }).join(''); +} + +// 공장/작업장 로드 (이동용) +async function loadPanelFactories() { + try { + const response = await window.apiCall('/workplaces/categories', 'GET'); + if (response && response.success) { + panelFactories = response.data; + } + } catch (error) { + console.error('공장 목록 로드 실패:', error); + } +} + +// 수리 카테고리 로드 +async function loadPanelRepairCategories() { + try { + const response = await window.apiCall('/equipments/repair-categories', 'GET'); + if (response && response.success) { + panelRepairCategories = response.data; + } + } catch (error) { + console.error('수리 항목 로드 실패:', error); + } +} + +// ==================== 임시이동 ==================== + +let selectedMoveFactory = null; +let selectedMoveWorkplace = null; + +function openPanelMoveModal() { + // 초기화 + selectedMoveFactory = null; + selectedMoveWorkplace = null; + panelMovePosition = null; + document.getElementById('panelMoveReason').value = ''; + document.getElementById('panelMoveConfirmBtn').disabled = true; + + // Step 1 표시 + document.getElementById('moveStep1').style.display = 'block'; + document.getElementById('moveStep2').style.display = 'none'; + document.getElementById('moveStep3').style.display = 'none'; + + // 공장 카드 렌더링 + renderMoveFactoryGrid(); + + document.getElementById('panelMoveModal').style.display = 'flex'; +} + +function closePanelMoveModal() { + document.getElementById('panelMoveModal').style.display = 'none'; +} + +function renderMoveFactoryGrid() { + const grid = document.getElementById('moveFactoryGrid'); + const icons = ['🏭', '🏢', '🏗️', '🏛️', '⚙️']; + + grid.innerHTML = panelFactories.map((f, i) => ` +
+
${icons[i % icons.length]}
+
${f.category_name}
+
+ `).join(''); + + // 이벤트 리스너 추가 + grid.querySelectorAll('.move-factory-card').forEach(card => { + card.onclick = () => { + const catId = card.dataset.categoryId; + const factory = panelFactories.find(f => f.category_id == catId); + if (factory) { + selectMoveFactory(factory); + } + }; + }); +} + +let panelMapRegions = []; // 이동 모달용 지도 영역 + +async function selectMoveFactory(factory) { + selectedMoveFactory = { + category_id: factory.category_id, + category_name: factory.category_name, + layout_image: factory.layout_image + }; + + // 작업장 목록 + 지도 영역 로드 + try { + const [wpResponse, regionsResponse] = await Promise.all([ + window.apiCall(`/workplaces?category_id=${factory.category_id}`, 'GET'), + window.apiCall(`/workplaces/categories/${factory.category_id}/map-regions`, 'GET') + ]); + + if (wpResponse && wpResponse.success) { + panelWorkplaces = wpResponse.data; + } + if (regionsResponse && regionsResponse.success) { + panelMapRegions = regionsResponse.data; + console.log('[이동모달] 로드된 영역:', panelMapRegions); + } else { + console.log('[이동모달] 영역 로드 실패:', regionsResponse); + } + } catch (error) { + console.error('작업장 로드 실패:', error); + return; + } + + // Step 2로 이동 + document.getElementById('moveStep1').style.display = 'none'; + document.getElementById('moveStep2').style.display = 'block'; + document.getElementById('moveStep2Title').textContent = `${factory.category_name} - 작업장 선택`; + + // 레이아웃 지도 렌더링 + renderMoveLayoutMap(factory.layout_image); +} + +function renderMoveLayoutMap(layoutImage) { + const container = document.getElementById('moveLayoutMapContainer'); + const baseUrl = (window.API_BASE_URL || '').replace('/api', ''); + + console.log('[이동모달] 렌더링 - layoutImage:', layoutImage); + console.log('[이동모달] 렌더링 - panelMapRegions:', panelMapRegions); + + if (!layoutImage) { + container.innerHTML = `
레이아웃 지도가 없습니다.
`; + return; + } + + // 지도 영역 데이터로 클릭 가능한 영역 생성 (x_start, y_start, x_end, y_end 사용) + let regionsHtml = panelMapRegions.map(region => { + const left = region.x_start; + const top = region.y_start; + const width = region.x_end - region.x_start; + const height = region.y_end - region.y_start; + return ` +
+ ${region.workplace_name} +
+ `; + }).join(''); + + container.innerHTML = ` + 공장 레이아웃 + ${regionsHtml} + `; + + // 영역 클릭 이벤트 + container.querySelectorAll('.move-wp-region').forEach(region => { + region.onclick = () => { + const wpId = parseInt(region.dataset.wpId); + const wp = panelWorkplaces.find(w => w.workplace_id === wpId); + if (wp) selectMoveWorkplace(wp); + }; + }); +} + +function selectMoveWorkplace(workplace) { + if (!workplace) return; + + console.log('[이동모달] 선택된 작업장:', workplace); + console.log('[이동모달] layout_image:', workplace.layout_image); + + selectedMoveWorkplace = workplace; + + // 상세 지도가 없으면 위치 없이 바로 확인 가능하게 + if (!workplace.layout_image) { + panelMovePosition = null; // 위치 좌표 없음 + document.getElementById('moveStep2').style.display = 'none'; + document.getElementById('moveStep3').style.display = 'block'; + document.getElementById('moveStep3Title').textContent = `${workplace.workplace_name}`; + document.getElementById('moveDetailMapContainer').innerHTML = ` +
+
📍
+
${workplace.workplace_name}
+
이 작업장에는 상세 지도가 없습니다.
+
위치 좌표 없이 작업장만 기록됩니다.
+
+ `; + document.getElementById('panelMoveConfirmBtn').disabled = false; + return; + } + + // Step 3으로 이동 + document.getElementById('moveStep2').style.display = 'none'; + document.getElementById('moveStep3').style.display = 'block'; + document.getElementById('moveStep3Title').textContent = `${workplace.workplace_name} - 위치 선택`; + + // 상세 지도 렌더링 + renderMoveDetailMap(); +} + +async function renderMoveDetailMap() { + const container = document.getElementById('moveDetailMapContainer'); + const baseUrl = (window.API_BASE_URL || '').replace('/api', ''); + const imageUrl = `${baseUrl}${selectedMoveWorkplace.layout_image}`; + + // 이동 대상 작업장의 기존 설비 로드 + let existingEquipments = []; + try { + const response = await window.apiCall(`/equipments?workplace_id=${selectedMoveWorkplace.workplace_id}`, 'GET'); + if (response && response.success) { + existingEquipments = response.data || []; + } + } catch (error) { + console.error('설비 로드 실패:', error); + } + + // 이미지 로드 후 마커 배치 + const img = new Image(); + img.onload = () => { + // 기존 설비 마커 HTML 생성 + const markersHtml = existingEquipments.map(eq => { + const isCurrentEquipment = eq.equipment_id === currentPanelEquipment.equipment_id; + const markerClass = isCurrentEquipment ? 'move-eq-marker current-moving' : 'move-eq-marker existing'; + const width = eq.map_width_percent || 6; + const height = eq.map_height_percent || 4; + return ` +
+ ${eq.equipment_name} +
+ `; + }).join(''); + + container.innerHTML = ` +
+ +
+ ${markersHtml} + +
+
+ `; + + // 지도 클릭 이벤트 + document.getElementById('moveMapWrapper').addEventListener('click', onMoveDetailMapClick); + }; + + img.onerror = () => { + container.innerHTML = `
지도를 불러올 수 없습니다.
`; + }; + + img.src = imageUrl; +} + +function onMoveDetailMapClick(event) { + const wrapper = document.getElementById('moveMapWrapper'); + const rect = wrapper.getBoundingClientRect(); + const x = ((event.clientX - rect.left) / rect.width) * 100; + const y = ((event.clientY - rect.top) / rect.height) * 100; + + // 현재 설비의 크기 사용 (없으면 기본값) + const width = currentPanelEquipment.map_width_percent || 6; + const height = currentPanelEquipment.map_height_percent || 4; + + panelMovePosition = { x, y, width, height }; + + // 타겟 마커 표시 + const targetMarker = document.getElementById('moveTargetMarker'); + targetMarker.style.left = x + '%'; + targetMarker.style.top = y + '%'; + targetMarker.style.width = width + '%'; + targetMarker.style.height = height + '%'; + targetMarker.style.display = 'flex'; + targetMarker.innerHTML = `${currentPanelEquipment.equipment_name}`; + + document.getElementById('panelMoveConfirmBtn').disabled = false; +} + +function moveBackToStep1() { + document.getElementById('moveStep2').style.display = 'none'; + document.getElementById('moveStep1').style.display = 'block'; + selectedMoveFactory = null; +} + +function moveBackToStep2() { + document.getElementById('moveStep3').style.display = 'none'; + document.getElementById('moveStep2').style.display = 'block'; + selectedMoveWorkplace = null; + panelMovePosition = null; + document.getElementById('panelMoveConfirmBtn').disabled = true; +} + +async function confirmPanelMove() { + if (!selectedMoveWorkplace) { + alert('작업장을 선택하세요.'); + return; + } + + // 상세 지도가 있는데 위치를 선택 안 한 경우 + if (selectedMoveWorkplace.layout_image && !panelMovePosition) { + alert('지도에서 위치를 클릭하세요.'); + return; + } + + const reason = document.getElementById('panelMoveReason').value; + + try { + const response = await window.apiCall(`/equipments/${currentPanelEquipment.equipment_id}/move`, 'POST', { + target_workplace_id: selectedMoveWorkplace.workplace_id, + target_x_percent: panelMovePosition ? panelMovePosition.x.toFixed(2) : null, + target_y_percent: panelMovePosition ? panelMovePosition.y.toFixed(2) : null, + from_workplace_id: currentPanelEquipment.workplace_id, + from_x_percent: currentPanelEquipment.map_x_percent, + from_y_percent: currentPanelEquipment.map_y_percent, + reason: reason + }); + + if (response && response.success) { + closePanelMoveModal(); + closeEquipmentPanel(); + alert('설비가 임시 이동되었습니다.'); + // 설비 마커 새로고침 + if (currentModalWorkplace && currentModalWorkplace.workplace_id) { + loadEquipmentMarkers(currentModalWorkplace.workplace_id); + } + } + } catch (error) { + console.error('이동 실패:', error); + alert('이동에 실패했습니다.'); + } +} + +// ==================== 수리신청 ==================== + +function openPanelRepairModal() { + const select = document.getElementById('panelRepairItem'); + select.innerHTML = ''; + panelRepairCategories.forEach(item => { + select.innerHTML += ``; + }); + // 새로 추가 옵션 + select.innerHTML += ''; + + document.getElementById('panelRepairDesc').value = ''; + document.getElementById('panelRepairPhotoInput').value = ''; + document.getElementById('newRepairTypeName').value = ''; + document.getElementById('newRepairTypeGroup').style.display = 'none'; + panelRepairPhotoBases = []; + + document.getElementById('panelRepairModal').style.display = 'flex'; +} + +function onRepairTypeChange() { + const select = document.getElementById('panelRepairItem'); + const newTypeGroup = document.getElementById('newRepairTypeGroup'); + + if (select.value === '__new__') { + newTypeGroup.style.display = 'block'; + document.getElementById('newRepairTypeName').focus(); + } else { + newTypeGroup.style.display = 'none'; + } +} + +function closePanelRepairModal() { + document.getElementById('panelRepairModal').style.display = 'none'; +} + +async function submitPanelRepair() { + const selectValue = document.getElementById('panelRepairItem').value; + const description = document.getElementById('panelRepairDesc').value; + const newTypeName = document.getElementById('newRepairTypeName').value.trim(); + + if (!description) { + alert('수리 내용을 입력하세요.'); + return; + } + + let itemId = selectValue; + + // 새 유형 추가하는 경우 + if (selectValue === '__new__') { + if (!newTypeName) { + alert('새 수리 유형 이름을 입력하세요.'); + return; + } + + try { + const addResponse = await window.apiCall('/equipments/repair-categories', 'POST', { + item_name: newTypeName + }); + + if (addResponse && addResponse.success) { + itemId = addResponse.data.item_id; + // 목록에 추가 + panelRepairCategories.push({ item_id: itemId, item_name: newTypeName }); + } else { + alert('새 유형 추가에 실패했습니다.'); + return; + } + } catch (error) { + console.error('새 유형 추가 실패:', error); + alert('새 유형 추가에 실패했습니다.'); + return; + } + } + + // 사진 처리 + const fileInput = document.getElementById('panelRepairPhotoInput'); + const photos = []; + + if (fileInput.files.length > 0) { + for (const file of fileInput.files) { + const base64 = await readFileAsBase64(file); + photos.push(base64); + } + } + + try { + const response = await window.apiCall(`/equipments/${currentPanelEquipment.equipment_id}/repair-request`, 'POST', { + item_id: itemId || null, + description: description, + photo_base64_list: photos, + workplace_id: currentPanelEquipment.workplace_id + }); + + if (response && response.success) { + closePanelRepairModal(); + loadPanelRepairHistory(); + alert('수리 신청이 접수되었습니다.'); + } + } catch (error) { + console.error('수리 신청 실패:', error); + alert('수리 신청에 실패했습니다.'); + } +} + +function readFileAsBase64(file) { + return new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = () => resolve(reader.result); + reader.onerror = reject; + reader.readAsDataURL(file); + }); +} + +// ==================== 외부반출 ==================== + +function openPanelExportModal() { + document.getElementById('panelIsRepairExport').checked = false; + document.getElementById('panelExportDate').value = new Date().toISOString().slice(0, 10); + document.getElementById('panelExpectedReturn').value = ''; + document.getElementById('panelExportDest').value = ''; + document.getElementById('panelExportReason').value = ''; + + document.getElementById('panelExportModal').style.display = 'flex'; +} + +function closePanelExportModal() { + document.getElementById('panelExportModal').style.display = 'none'; +} + +async function submitPanelExport() { + const exportDate = document.getElementById('panelExportDate').value; + + if (!exportDate) { + alert('반출일을 입력하세요.'); + return; + } + + try { + const response = await window.apiCall(`/equipments/${currentPanelEquipment.equipment_id}/export`, 'POST', { + export_date: exportDate, + expected_return_date: document.getElementById('panelExpectedReturn').value || null, + destination: document.getElementById('panelExportDest').value, + reason: document.getElementById('panelExportReason').value, + is_repair: document.getElementById('panelIsRepairExport').checked + }); + + if (response && response.success) { + closePanelExportModal(); + loadPanelExternalLogs(); + alert('외부 반출이 등록되었습니다.'); + } + } catch (error) { + console.error('반출 실패:', error); + alert('반출 등록에 실패했습니다.'); + } +} + +// ==================== 반입 ==================== + +function openPanelReturnModal(logId) { + document.getElementById('panelReturnLogId').value = logId; + document.getElementById('panelReturnDate').value = new Date().toISOString().slice(0, 10); + document.getElementById('panelReturnStatus').value = 'active'; + + document.getElementById('panelReturnModal').style.display = 'flex'; +} + +function closePanelReturnModal() { + document.getElementById('panelReturnModal').style.display = 'none'; +} + +async function submitPanelReturn() { + const logId = document.getElementById('panelReturnLogId').value; + const returnDate = document.getElementById('panelReturnDate').value; + + if (!returnDate) { + alert('반입일을 입력하세요.'); + return; + } + + try { + const response = await window.apiCall(`/equipments/external-logs/${logId}/return`, 'POST', { + return_date: returnDate, + new_status: document.getElementById('panelReturnStatus').value + }); + + if (response && response.success) { + closePanelReturnModal(); + loadPanelExternalLogs(); + alert('반입 처리가 완료되었습니다.'); + } + } catch (error) { + console.error('반입 실패:', error); + alert('반입 처리에 실패했습니다.'); + } +} + +// ==================== 임시 이동 설비 목록 ==================== + +async function loadMovedEquipments() { + const listEl = document.getElementById('movedEquipmentList'); + const emptyEl = document.getElementById('noMovedEquipment'); + + if (!listEl) return; + + try { + const response = await window.apiCall('/equipments/moved/list', 'GET'); + + if (response && response.success && response.data && response.data.length > 0) { + const equipments = response.data; + emptyEl.style.display = 'none'; + listEl.style.display = 'grid'; + + listEl.innerHTML = equipments.map(eq => ` +
+
+ ${eq.equipment_code} + 임시이동 +
+
${eq.equipment_name}
+
+
+ 원래 위치 + ${eq.original_workplace_name || '-'} +
+
+
+ 현재 위치 + ${eq.current_workplace_name || '-'} +
+
+
+ 이동일: ${formatPanelDate(eq.moved_at)} +
+ +
+ `).join(''); + } else { + listEl.style.display = 'none'; + emptyEl.style.display = 'block'; + } + } catch (error) { + console.error('임시 이동 설비 로드 실패:', error); + listEl.innerHTML = '
로드 실패
'; + } +} + +// 작업장별 이동 설비 로드 +async function loadWorkplaceMovedEquipments(workplaceId) { + const movedInList = document.getElementById('movedInEquipmentList'); + const movedOutList = document.getElementById('movedOutEquipmentList'); + const badge = document.getElementById('movedEqCountBadge'); + + try { + const response = await window.apiCall('/equipments/moved/list', 'GET'); + + if (response && response.success && response.data) { + const allMoved = response.data; + + // 이 작업장으로 이동해 온 설비 (current_workplace_id = workplaceId) + const movedIn = allMoved.filter(eq => eq.current_workplace_id === workplaceId); + + // 이 작업장에서 다른 곳으로 이동한 설비 (workplace_id = workplaceId) + const movedOut = allMoved.filter(eq => eq.workplace_id === workplaceId); + + // 배지 업데이트 + const totalCount = movedIn.length + movedOut.length; + if (totalCount > 0) { + badge.textContent = totalCount; + badge.style.display = 'inline-flex'; + } else { + badge.style.display = 'none'; + } + + // 이동해 온 설비 렌더링 + if (movedIn.length > 0) { + movedInList.innerHTML = movedIn.map(eq => ` +
+
+ ${eq.equipment_code} + ${eq.equipment_name} +
+
+ 📤 ${eq.original_workplace_name || '알 수 없음'} + + 📥 여기 +
+
이동일: ${formatPanelDate(eq.moved_at)}
+
+ `).join(''); + } else { + movedInList.innerHTML = '

없음

'; + } + + // 이동해 간 설비 렌더링 + if (movedOut.length > 0) { + movedOutList.innerHTML = movedOut.map(eq => ` +
+
+ ${eq.equipment_code} + ${eq.equipment_name} +
+
+ 📤 여기 + + 📥 ${eq.current_workplace_name || '알 수 없음'} +
+
이동일: ${formatPanelDate(eq.moved_at)}
+
+ `).join(''); + } else { + movedOutList.innerHTML = '

없음

'; + } + } + } catch (error) { + console.error('작업장 이동 설비 로드 실패:', error); + movedInList.innerHTML = '

로드 실패

'; + movedOutList.innerHTML = '

로드 실패

'; + } +} + +// 원위치 복귀 +async function returnEquipmentToOriginal(equipmentId) { + if (!confirm('이 설비를 원래 위치로 복귀시키겠습니까?')) return; + + try { + const response = await window.apiCall(`/equipments/${equipmentId}/return`, 'POST'); + + if (response && response.success) { + alert('설비가 원래 위치로 복귀되었습니다.'); + loadMovedEquipments(); + // 지도 새로고침 + if (selectedCategory) { + renderMap(); + } + } + } catch (error) { + console.error('복귀 실패:', error); + alert('복귀에 실패했습니다.'); + } +} + +// 이동된 설비 상세 보기 +function showMovedEquipmentDetail(equipmentId) { + // TODO: 설비 상세 패널 열기 + console.log('설비 상세:', equipmentId); +} + +// ==================== 유틸리티 ==================== + +function formatPanelDate(dateStr) { + if (!dateStr) return '-'; + const date = new Date(dateStr); + return `${date.getMonth() + 1}/${date.getDate()}`; +} + +function truncateText(text, maxLen) { + if (!text) return '-'; + return text.length > maxLen ? text.slice(0, maxLen) + '...' : text; +} + +// 전역 함수 노출 +window.openEquipmentPanel = openEquipmentPanel; +window.closeEquipmentPanel = closeEquipmentPanel; +window.openPanelPhotoUpload = openPanelPhotoUpload; +window.closePanelPhotoModal = closePanelPhotoModal; +window.previewPanelPhoto = previewPanelPhoto; +window.uploadPanelPhoto = uploadPanelPhoto; +window.deletePanelPhoto = deletePanelPhoto; +window.viewPanelPhoto = viewPanelPhoto; +window.openPanelMoveModal = openPanelMoveModal; +window.closePanelMoveModal = closePanelMoveModal; +window.selectMoveFactory = selectMoveFactory; +window.selectMoveWorkplace = selectMoveWorkplace; +window.onMoveDetailMapClick = onMoveDetailMapClick; +window.moveBackToStep1 = moveBackToStep1; +window.moveBackToStep2 = moveBackToStep2; +window.confirmPanelMove = confirmPanelMove; +window.openPanelRepairModal = openPanelRepairModal; +window.closePanelRepairModal = closePanelRepairModal; +window.submitPanelRepair = submitPanelRepair; +window.onRepairTypeChange = onRepairTypeChange; +window.openPanelExportModal = openPanelExportModal; +window.closePanelExportModal = closePanelExportModal; +window.submitPanelExport = submitPanelExport; +window.openPanelReturnModal = openPanelReturnModal; +window.closePanelReturnModal = closePanelReturnModal; +window.submitPanelReturn = submitPanelReturn; +window.loadMovedEquipments = loadMovedEquipments; +window.returnEquipmentToOriginal = returnEquipmentToOriginal; +window.showMovedEquipmentDetail = showMovedEquipmentDetail; +window.loadWorkplaceMovedEquipments = loadWorkplaceMovedEquipments; diff --git a/deploy/tkfb-package/web-ui/js/zone-detail.js b/deploy/tkfb-package/web-ui/js/zone-detail.js new file mode 100644 index 0000000..86b5393 --- /dev/null +++ b/deploy/tkfb-package/web-ui/js/zone-detail.js @@ -0,0 +1,1423 @@ +// zone-detail.js - 구역 상세 페이지 JavaScript + +// 전역 상태 +let workplaceId = null; +let workplaceData = null; +let zoneItems = []; +let selectedZoneItem = null; +let isAddingItem = false; +let selectionStart = null; +let selectionBox = null; + +// XSS 방지를 위한 HTML 이스케이프 함수 +function escapeHtml(str) { + if (str === null || str === undefined) return ''; + return String(str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +} + +// axios 설정 대기 +function waitForAxiosConfig() { + return new Promise((resolve) => { + const check = setInterval(() => { + if (axios.defaults.baseURL) { + clearInterval(check); + resolve(); + } + }, 50); + setTimeout(() => { + clearInterval(check); + resolve(); + }, 5000); + }); +} + +// 페이지 초기화 +document.addEventListener('DOMContentLoaded', async () => { + await waitForAxiosConfig(); + + // URL에서 workplace_id 파라미터 가져오기 + const urlParams = new URLSearchParams(window.location.search); + workplaceId = urlParams.get('id'); + + if (!workplaceId) { + alert('잘못된 접근입니다.'); + goBack(); + return; + } + + // 현재 날짜 표시 + const now = new Date(); + document.getElementById('currentDate').textContent = now.toLocaleDateString('ko-KR', { + year: 'numeric', + month: 'long', + day: 'numeric', + weekday: 'short' + }); + + // 데이터 로드 + await loadWorkplaceDetail(); +}); + +// 작업장 상세 정보 로드 +async function loadWorkplaceDetail() { + try { + const today = new Date().toISOString().slice(0, 10); + const response = await axios.get(`/patrol/workplaces/${workplaceId}/detail?date=${today}`); + + if (response.data.success) { + workplaceData = response.data.data; + renderPage(); + } else { + throw new Error(response.data.message || '데이터 로드 실패'); + } + } catch (error) { + console.error('작업장 상세 정보 로드 실패:', error); + alert('데이터를 불러오는데 실패했습니다.'); + } +} + +// 페이지 렌더링 +function renderPage() { + if (!workplaceData) return; + + const { workplace, summary } = workplaceData; + + // 헤더 정보 + document.getElementById('zoneName').textContent = workplace.workplace_name; + document.getElementById('zoneCategory').textContent = workplace.category_name || ''; + + // 요약 카드 + renderSummaryCards(summary); + + // 각 탭 콘텐츠 렌더링 + renderMapTab(); + renderIssuesTab(); + renderEquipmentTab(); + renderVisitsTab(); + renderTbmTab(); + renderPatrolTab(); + + // 구역 현황 로드 + loadZoneItems(); +} + +// ==================== 구역 지도 탭 ==================== + +// 지도 탭 렌더링 +function renderMapTab() { + const container = document.getElementById('zoneMapContainer'); + const { workplace } = workplaceData; + + // 작업장 자체의 지도 이미지 사용 + const mapImage = workplace.layout_image; + if (mapImage) { + // 이미지 URL 생성 (API base URL에서 /api 제거) + const staticUrl = window.API_BASE_URL ? window.API_BASE_URL.replace(/\/api$/, '') : ''; + const imageUrl = mapImage.startsWith('http') ? mapImage : staticUrl + mapImage; + + container.innerHTML = ` + ${escapeHtml(workplace.workplace_name)} 지도 + `; + } else { + container.innerHTML = ` +
+
🗺️
+

작업장 지도 이미지가 등록되지 않았습니다.

+

지도 없이도 현황을 등록할 수 있습니다.

+
+ `; + // 지도가 없어도 설비 목록은 표시 + renderEquipmentList(); + } + + // 마우스 이벤트 핸들러 설정 + setupMapEventHandlers(container); +} + +// 설비 목록 렌더링 (지도가 없을 때 텍스트로 표시) +function renderEquipmentList() { + if (!workplaceData || !workplaceData.equipments || workplaceData.equipments.length === 0) return; + + const container = document.getElementById('zoneMapContainer'); + const { equipments } = workplaceData; + + const listHtml = ` +
+

등록된 설비 (${equipments.length}개)

+
+ ${equipments.map(eq => { + let statusIcon = '⚙️'; + let statusText = '정상'; + let statusColor = '#22c55e'; + if (eq.status === 'repair_needed' || eq.status === 'repair_external') { + statusIcon = '🔧'; + statusText = eq.status === 'repair_external' ? '외부수리' : '수리필요'; + statusColor = '#ef4444'; + } else if (eq.status === 'maintenance') { + statusIcon = '⚠️'; + statusText = '점검중'; + statusColor = '#f59e0b'; + } else if (eq.is_temporarily_moved) { + statusIcon = '📤'; + statusText = '이동됨'; + statusColor = '#9ca3af'; + } + return ` +
+ ${statusIcon} + ${escapeHtml(eq.equipment_name)} + ${statusText} +
+ `; + }).join('')} +
+
+ `; + + container.insertAdjacentHTML('beforeend', listHtml); +} + +// 지도 이미지 로드 완료 +function onMapImageLoaded() { + renderEquipmentsOnMap(); + renderZoneItemsOnMap(); +} + +// 지도 이미지 로드 실패 +function onMapImageError() { + const container = document.getElementById('zoneMapContainer'); + container.innerHTML = ` +
+
⚠️
+

지도 이미지를 불러올 수 없습니다.

+

지도 없이도 현황을 등록할 수 있습니다.

+
+ `; + setupMapEventHandlers(container); +} + +// 지도 이벤트 핸들러 설정 +function setupMapEventHandlers(container) { + container.addEventListener('mousedown', onMapMouseDown); + container.addEventListener('mousemove', onMapMouseMove); + container.addEventListener('mouseup', onMapMouseUp); + container.addEventListener('mouseleave', onMapMouseLeave); + + // 터치 이벤트 (모바일) + container.addEventListener('touchstart', onMapTouchStart, { passive: false }); + container.addEventListener('touchmove', onMapTouchMove, { passive: false }); + container.addEventListener('touchend', onMapTouchEnd); +} + +// 설비를 지도에 렌더링 +function renderEquipmentsOnMap() { + const container = document.getElementById('zoneMapContainer'); + if (!workplaceData || !workplaceData.equipments) return; + + const { equipments } = workplaceData; + const currentWorkplaceId = parseInt(workplaceId); + + // 기존 설비 마커 제거 + container.querySelectorAll('.equipment-map-marker').forEach(el => el.remove()); + + equipments.forEach(eq => { + // 이 작업장에 표시할 좌표 결정 + let x, y, width, height; + let isHere = true; // 이 작업장에 현재 있는지 + let isVisitor = false; // 다른 곳에서 임시로 온 설비인지 + + // 원래 이 작업장 설비인 경우 + if (eq.workplace_id === currentWorkplaceId) { + if (eq.is_temporarily_moved && eq.current_workplace_id !== currentWorkplaceId) { + // 다른 곳으로 이동함 - 원래 위치에 "이동됨" 표시 + x = eq.map_x_percent; + y = eq.map_y_percent; + width = eq.map_width_percent || 5; + height = eq.map_height_percent || 5; + isHere = false; + } else { + // 현재 여기 있음 + x = eq.current_map_x_percent || eq.map_x_percent; + y = eq.current_map_y_percent || eq.map_y_percent; + width = eq.current_map_width_percent || eq.map_width_percent || 5; + height = eq.current_map_height_percent || eq.map_height_percent || 5; + } + } else if (eq.current_workplace_id === currentWorkplaceId) { + // 다른 곳에서 임시로 온 설비 + x = eq.current_map_x_percent; + y = eq.current_map_y_percent; + width = eq.current_map_width_percent || 5; + height = eq.current_map_height_percent || 5; + isVisitor = true; + } else { + return; // 이 작업장과 관계없는 설비 + } + + // 좌표가 없으면 건너뜀 + if (x === null || x === undefined || y === null || y === undefined) return; + + // 상태에 따른 색상과 아이콘 + let bgColor, borderColor, icon, statusText; + if (!isHere) { + // 다른 곳으로 이동됨 + bgColor = 'rgba(156, 163, 175, 0.3)'; + borderColor = '#9ca3af'; + icon = '📤'; + statusText = `→ ${eq.current_workplace_name || '외부'}`; + } else if (eq.status === 'repair_needed' || eq.status === 'repair_external') { + // 수리 필요/요청 + bgColor = 'rgba(239, 68, 68, 0.4)'; + borderColor = '#ef4444'; + icon = '🔧'; + statusText = eq.status === 'repair_external' ? '외부수리중' : '수리필요'; + } else if (eq.status === 'maintenance') { + // 점검중 + bgColor = 'rgba(245, 158, 11, 0.4)'; + borderColor = '#f59e0b'; + icon = '⚠️'; + statusText = '점검중'; + } else if (isVisitor) { + // 다른 곳에서 온 임시 설비 + bgColor = 'rgba(139, 92, 246, 0.4)'; + borderColor = '#8b5cf6'; + icon = '📥'; + statusText = '임시배치'; + } else { + // 정상 + bgColor = 'rgba(34, 197, 94, 0.4)'; + borderColor = '#22c55e'; + icon = '⚙️'; + statusText = '정상'; + } + + // 상태별 마커 클래스 결정 + let markerClass = 'equipment-marker'; + if (!isHere) { + markerClass += ' inactive'; + } else if (eq.status === 'repair_needed' || eq.status === 'repair_external') { + markerClass += ' repair'; + } else if (eq.status === 'maintenance') { + markerClass += ' maintenance'; + } else if (isVisitor) { + markerClass += ' moved'; + } else { + markerClass += ' active'; + } + + const marker = document.createElement('div'); + marker.className = markerClass; + marker.style.cssText = ` + left: ${x}%; + top: ${y}%; + width: ${width}%; + height: ${height}%; + `; + + // 이동/임시배치 표시 이모지 + const badge = !isHere ? ' 📤' : isVisitor ? ' 🚚' : ''; + + // 마커 라벨 (설비 이름만 표시) + marker.innerHTML = `${escapeHtml(eq.equipment_name)}${badge}`; + marker.title = `${eq.equipment_name}\n상태: ${statusText}`; + + // 호버 시 정보 표시 + marker.addEventListener('mouseenter', () => { + marker.style.transform = 'scale(1.1)'; + marker.style.zIndex = '50'; + }); + marker.addEventListener('mouseleave', () => { + marker.style.transform = 'scale(1)'; + marker.style.zIndex = '5'; + }); + + // 클릭 시 상세 정보 표시 + marker.addEventListener('click', (e) => { + e.stopPropagation(); + showEquipmentInfo(eq, isHere, isVisitor); + }); + + container.appendChild(marker); + }); +} + +// 설비 정보 표시 +function showEquipmentInfo(eq, isHere, isVisitor) { + let statusText = '정상'; + if (!isHere) { + statusText = `다른 작업장으로 이동됨 (${eq.current_workplace_name || '외부'})`; + } else if (eq.status === 'repair_needed') { + statusText = '수리 필요'; + } else if (eq.status === 'repair_external') { + statusText = '외부 수리중'; + } else if (eq.status === 'maintenance') { + statusText = '점검중'; + } else if (isVisitor) { + statusText = '임시 배치 (원래 위치 아님)'; + } + + alert(`📌 ${eq.equipment_name}\n\n` + + `유형: ${eq.equipment_type || '-'}\n` + + `관리번호: ${eq.equipment_code || '-'}\n` + + `상태: ${statusText}\n` + + (eq.notes ? `비고: ${eq.notes}` : '')); +} + +// 구역 현황 목록 로드 +async function loadZoneItems() { + try { + const response = await axios.get(`/patrol/workplaces/${workplaceId}/zone-items`); + if (response.data.success) { + zoneItems = response.data.data || []; + renderZoneItemsList(); + renderZoneItemsOnMap(); + } + } catch (error) { + console.error('구역 현황 로드 실패:', error); + zoneItems = []; + renderZoneItemsList(); + } +} + +// 현황 목록 렌더링 +function renderZoneItemsList() { + const container = document.getElementById('zoneItemsList'); + const typeLabels = { + 'working': '작업중', + 'temp_storage': '임시적치', + 'moved_equipment': '이동설비', + 'unreported': '미신고품', + 'general': '일반', + 'other': '기타' + }; + const warningLabels = { + 'good': '양호', + 'caution': '주의', + 'needs_management': '관리필요' + }; + const projectTypeLabels = { + 'project': '프로젝트', + 'non_project': '비프로젝트', + 'unknown': '미확인' + }; + + if (!zoneItems.length) { + container.innerHTML = ` +
+

등록된 현황

+ 0개 +
+
+ 등록된 현황이 없습니다.
+ 위 [현황 등록] 버튼을 눌러 지도에서 범위를 선택하세요. +
+ `; + return; + } + + container.innerHTML = ` +
+

등록된 현황

+ ${zoneItems.length}개 +
+ ${zoneItems.map(item => ` +
+
+
+
+ ${escapeHtml(item.item_name)} + ${item.photos && item.photos.length > 0 ? `📷${item.photos.length}` : ''} +
+
+ ${typeLabels[item.item_type] || item.item_type} + ${item.project_type === 'project' && item.project_name ? `• ${escapeHtml(item.project_name)}` : ''} + ${item.project_type === 'unknown' ? `• 미확인` : ''} +
+
+ ${warningLabels[item.warning_level] || '양호'} +
+ `).join('')} + `; +} + +// 지도 위에 현황 마커 렌더링 +function renderZoneItemsOnMap() { + const container = document.getElementById('zoneMapContainer'); + + // 기존 마커 제거 + container.querySelectorAll('.zone-item-marker').forEach(el => el.remove()); + + // 유형 라벨 + const typeLabels = { + 'working': '작업중', + 'temp_storage': '임시적치', + 'moved_equipment': '이동설비', + 'unreported': '미신고품' + }; + + // 마커 추가 + zoneItems.forEach(item => { + const marker = document.createElement('div'); + const isSelected = selectedZoneItem === item.item_id; + const warningClass = item.warning_level === 'needs_management' ? 'warning-high' : + item.warning_level === 'caution' ? 'warning-mid' : ''; + + marker.className = `zone-item-marker ${isSelected ? 'selected' : ''} ${warningClass}`; + marker.style.cssText = ` + left: ${item.x_percent}%; + top: ${item.y_percent}%; + width: ${item.width_percent || 5}%; + height: ${item.height_percent || 5}%; + --marker-color: ${item.color || '#3b82f6'}; + `; + marker.dataset.itemId = item.item_id; + + // 클릭 시 바로 수정 모달 열기 + marker.onclick = (e) => { + e.stopPropagation(); + editZoneItem(item.item_id); + }; + + // 주의 수준 아이콘 + const warningIcon = item.warning_level === 'needs_management' ? '⚠️ ' : + item.warning_level === 'caution' ? '⚡ ' : ''; + + // 라벨 (이름 + 유형) + const typeName = typeLabels[item.item_type] || item.item_type; + marker.innerHTML = ` + ${warningIcon}${escapeHtml(item.item_name)} + ${typeName} + `; + + marker.title = `${item.item_name}\n유형: ${typeName}\n클릭하여 수정`; + + container.appendChild(marker); + }); +} + +// 현황 선택 +function selectZoneItem(itemId) { + selectedZoneItem = selectedZoneItem === itemId ? null : itemId; + renderZoneItemsList(); + renderZoneItemsOnMap(); +} + +// 현황 등록 시작/토글 +function startAddItem() { + const container = document.getElementById('zoneMapContainer'); + const btn = document.getElementById('addItemBtn'); + + if (isAddingItem) { + // 이미 등록 모드면 취소 + cancelAddItem(); + return; + } + + isAddingItem = true; + selectedZoneItem = null; + container.classList.add('adding-item'); + + // 버튼 텍스트 변경 + btn.innerHTML = '❌ 취소'; + btn.classList.add('btn-danger'); + btn.classList.remove('btn-primary'); + + // 하단 안내 바 (오버레이 대신) + let guideBar = document.getElementById('addItemGuideBar'); + if (!guideBar) { + guideBar = document.createElement('div'); + guideBar.id = 'addItemGuideBar'; + guideBar.className = 'add-item-guide-bar'; + container.appendChild(guideBar); + } + guideBar.innerHTML = ` + 👆 + 클릭: 위치 지정 | 드래그: 영역 선택 + `; + guideBar.style.display = 'flex'; +} + +// 현황 등록 취소 +function cancelAddItem() { + isAddingItem = false; + const container = document.getElementById('zoneMapContainer'); + container.classList.remove('adding-item'); + + // 안내 바 숨기기 + const guideBar = document.getElementById('addItemGuideBar'); + if (guideBar) guideBar.style.display = 'none'; + + // 선택 박스 정리 + if (selectionBox) { + selectionBox.remove(); + selectionBox = null; + } + selectionStart = null; + + // 버튼 원복 + const btn = document.getElementById('addItemBtn'); + btn.innerHTML = '➕ 현황 등록'; + btn.classList.remove('btn-danger'); + btn.classList.add('btn-primary'); +} + +// 마우스 이벤트 핸들러 +function onMapMouseDown(e) { + if (!isAddingItem) return; + if (e.target.closest('.zone-item-marker, .equipment-marker')) return; // 기존 마커 클릭 무시 + + e.preventDefault(); + const container = document.getElementById('zoneMapContainer'); + const rect = container.getBoundingClientRect(); + + selectionStart = { + x: e.clientX - rect.left, + y: e.clientY - rect.top, + xPercent: ((e.clientX - rect.left) / rect.width) * 100, + yPercent: ((e.clientY - rect.top) / rect.height) * 100, + time: Date.now() + }; + + // 선택 박스 생성 + selectionBox = document.createElement('div'); + selectionBox.className = 'selection-box'; + selectionBox.style.left = selectionStart.x + 'px'; + selectionBox.style.top = selectionStart.y + 'px'; + selectionBox.style.width = '0px'; + selectionBox.style.height = '0px'; + container.appendChild(selectionBox); + + // 크기 표시 라벨 + const sizeLabel = document.createElement('div'); + sizeLabel.className = 'selection-size-label'; + sizeLabel.id = 'selectionSizeLabel'; + selectionBox.appendChild(sizeLabel); +} + +function onMapMouseMove(e) { + if (!isAddingItem || !selectionStart || !selectionBox) return; + + const container = document.getElementById('zoneMapContainer'); + const rect = container.getBoundingClientRect(); + + const currentX = Math.max(0, Math.min(e.clientX - rect.left, rect.width)); + const currentY = Math.max(0, Math.min(e.clientY - rect.top, rect.height)); + + const left = Math.min(selectionStart.x, currentX); + const top = Math.min(selectionStart.y, currentY); + const width = Math.abs(currentX - selectionStart.x); + const height = Math.abs(currentY - selectionStart.y); + + selectionBox.style.left = left + 'px'; + selectionBox.style.top = top + 'px'; + selectionBox.style.width = width + 'px'; + selectionBox.style.height = height + 'px'; + + // 크기 표시 업데이트 + const widthPercent = ((width / rect.width) * 100).toFixed(1); + const heightPercent = ((height / rect.height) * 100).toFixed(1); + const sizeLabel = document.getElementById('selectionSizeLabel'); + if (sizeLabel && width > 30) { + sizeLabel.textContent = `${widthPercent}% × ${heightPercent}%`; + sizeLabel.style.display = 'block'; + } +} + +function onMapMouseUp(e) { + if (!isAddingItem || !selectionStart) return; + + const container = document.getElementById('zoneMapContainer'); + const rect = container.getBoundingClientRect(); + + const endX = Math.max(0, Math.min(e.clientX - rect.left, rect.width)); + const endY = Math.max(0, Math.min(e.clientY - rect.top, rect.height)); + + const width = Math.abs(endX - selectionStart.x); + const height = Math.abs(endY - selectionStart.y); + const elapsed = Date.now() - selectionStart.time; + + // 선택 박스 제거 + if (selectionBox) { + selectionBox.remove(); + selectionBox = null; + } + + // 빠른 클릭 (200ms 이하) 또는 작은 영역 (15px 이하) → 고정 크기 마커 + if (elapsed < 200 || (width < 15 && height < 15)) { + const xPercent = Math.max(0, selectionStart.xPercent - 2.5); // 중앙 정렬 + const yPercent = Math.max(0, selectionStart.yPercent - 2.5); + openZoneItemModal(xPercent, yPercent, 5, 5); + } else { + // 드래그로 선택한 영역 + const xPercent = Math.min(selectionStart.xPercent, (endX / rect.width) * 100); + const yPercent = Math.min(selectionStart.yPercent, (endY / rect.height) * 100); + const widthPercent = (width / rect.width) * 100; + const heightPercent = (height / rect.height) * 100; + openZoneItemModal(xPercent, yPercent, widthPercent, heightPercent); + } + + selectionStart = null; + // 등록 모드 유지 (연속 등록 가능) +} + +function onMapMouseLeave() { + // 지도 영역 벗어나면 현재 선택만 취소 (모드는 유지) + if (selectionBox && selectionStart) { + selectionBox.remove(); + selectionBox = null; + selectionStart = null; + } +} + +// 터치 이벤트 (모바일) +function onMapTouchStart(e) { + if (!isAddingItem) return; + if (e.target.closest('.zone-item-marker, .equipment-marker')) return; + e.preventDefault(); + const touch = e.touches[0]; + onMapMouseDown({ clientX: touch.clientX, clientY: touch.clientY, target: e.target }); +} + +function onMapTouchMove(e) { + if (!isAddingItem || !selectionStart) return; + e.preventDefault(); + const touch = e.touches[0]; + onMapMouseMove({ clientX: touch.clientX, clientY: touch.clientY }); +} + +function onMapTouchEnd(e) { + if (!isAddingItem || !selectionStart) return; + const touch = e.changedTouches[0]; + onMapMouseUp({ clientX: touch.clientX, clientY: touch.clientY }); +} + +// 프로젝트 목록 캐시 +let projectsCache = null; +let selectedPhotos = []; + +// 프로젝트 목록 로드 +async function loadProjects() { + if (projectsCache) return projectsCache; + try { + const response = await axios.get('/projects?status=in_progress&limit=100'); + if (response.data.success) { + projectsCache = response.data.data || []; + return projectsCache; + } + } catch (err) { + console.error('프로젝트 로드 실패:', err); + } + return []; +} + +// 프로젝트 타입 변경 +function onProjectTypeChange(value) { + const projectGroup = document.getElementById('projectSelectGroup'); + if (value === 'project') { + projectGroup.style.display = 'block'; + populateProjectSelect(); + } else { + projectGroup.style.display = 'none'; + } +} + +// 프로젝트 셀렉트 채우기 +async function populateProjectSelect() { + const select = document.getElementById('zoneItemProject'); + const projects = await loadProjects(); + + select.innerHTML = ''; + projects.forEach(p => { + select.innerHTML += ``; + }); +} + +// 커스텀 유형 추가 +function addCustomType() { + const customType = prompt('새로운 상태/유형을 입력하세요:'); + if (!customType || !customType.trim()) return; + + const select = document.getElementById('zoneItemType'); + const value = customType.trim().toLowerCase().replace(/\s+/g, '_'); + + // 중복 체크 + if (Array.from(select.options).some(opt => opt.value === value)) { + alert('이미 존재하는 유형입니다.'); + return; + } + + const option = document.createElement('option'); + option.value = value; + option.textContent = customType.trim(); + select.appendChild(option); + select.value = value; +} + +// 사진 선택 +function onPhotoSelected(event) { + const files = Array.from(event.target.files); + files.forEach(file => { + if (!file.type.startsWith('image/')) return; + if (selectedPhotos.length >= 5) { + alert('사진은 최대 5장까지 등록할 수 있습니다.'); + return; + } + + const reader = new FileReader(); + reader.onload = (e) => { + selectedPhotos.push({ + file: file, + dataUrl: e.target.result + }); + renderPhotoPreview(); + }; + reader.readAsDataURL(file); + }); + event.target.value = ''; // 리셋 +} + +// 사진 미리보기 렌더링 +function renderPhotoPreview() { + const container = document.getElementById('photoPreviewList'); + container.innerHTML = selectedPhotos.map((photo, idx) => ` +
+ 사진 ${idx + 1} + +
+ `).join(''); +} + +// 사진 제거 +function removePhoto(index) { + selectedPhotos.splice(index, 1); + renderPhotoPreview(); +} + +// 현황 모달 열기 +function openZoneItemModal(x, y, width, height, item = null) { + const modal = document.getElementById('zoneItemModal'); + const title = document.getElementById('zoneItemModalTitle'); + const deleteBtn = document.getElementById('deleteZoneItemBtn'); + + // 사진 초기화 + selectedPhotos = []; + renderPhotoPreview(); + + if (item) { + // 수정 모드 + title.textContent = '현황 수정'; + deleteBtn.style.display = 'inline-block'; + + document.getElementById('zoneItemId').value = item.item_id; + document.getElementById('zoneItemX').value = item.x_percent; + document.getElementById('zoneItemY').value = item.y_percent; + document.getElementById('zoneItemWidth').value = item.width_percent || 5; + document.getElementById('zoneItemHeight').value = item.height_percent || 5; + document.getElementById('zoneItemName').value = item.item_name || ''; + document.getElementById('zoneItemType').value = item.item_type || 'working'; + document.getElementById('zoneItemWarning').value = item.warning_level || 'good'; + document.getElementById('zoneItemDesc').value = item.description || ''; + document.getElementById('zoneItemColor').value = item.color || '#3b82f6'; + + // 프로젝트 타입 + const projectType = item.project_type || 'non_project'; + document.querySelector(`input[name="zoneItemProjectType"][value="${projectType}"]`).checked = true; + onProjectTypeChange(projectType); + if (projectType === 'project' && item.project_id) { + setTimeout(() => { + document.getElementById('zoneItemProject').value = item.project_id; + }, 100); + } + + // 기존 사진 로드 (있으면) + if (item.photos && item.photos.length > 0) { + item.photos.forEach(photo => { + selectedPhotos.push({ + existing: true, + photo_id: photo.photo_id, + dataUrl: photo.photo_url + }); + }); + renderPhotoPreview(); + } + } else { + // 등록 모드 + title.textContent = '현황 등록'; + deleteBtn.style.display = 'none'; + + document.getElementById('zoneItemId').value = ''; + document.getElementById('zoneItemX').value = x; + document.getElementById('zoneItemY').value = y; + document.getElementById('zoneItemWidth').value = width; + document.getElementById('zoneItemHeight').value = height; + document.getElementById('zoneItemForm').reset(); + document.getElementById('zoneItemColor').value = '#3b82f6'; + + // 기본값 설정 + document.querySelector('input[name="zoneItemProjectType"][value="non_project"]').checked = true; + onProjectTypeChange('non_project'); + } + + modal.style.display = 'flex'; +} + +// 현황 수정 모달 열기 +function editZoneItem(itemId) { + const item = zoneItems.find(i => i.item_id === itemId); + if (!item) return; + openZoneItemModal(item.x_percent, item.y_percent, item.width_percent, item.height_percent, item); +} + +// 모달 닫기 +function closeZoneItemModal() { + document.getElementById('zoneItemModal').style.display = 'none'; +} + +// 색상 프리셋 선택 +function setItemColor(color) { + document.getElementById('zoneItemColor').value = color; +} + +// 현황 저장 +async function saveZoneItem() { + const itemId = document.getElementById('zoneItemId').value; + const projectType = document.querySelector('input[name="zoneItemProjectType"]:checked')?.value || 'non_project'; + const projectId = projectType === 'project' ? document.getElementById('zoneItemProject').value : null; + + const itemData = { + item_name: document.getElementById('zoneItemName').value.trim(), + item_type: document.getElementById('zoneItemType').value, + warning_level: document.getElementById('zoneItemWarning').value, + project_type: projectType, + project_id: projectId || null, + description: document.getElementById('zoneItemDesc').value.trim(), + color: document.getElementById('zoneItemColor').value, + x_percent: parseFloat(document.getElementById('zoneItemX').value), + y_percent: parseFloat(document.getElementById('zoneItemY').value), + width_percent: parseFloat(document.getElementById('zoneItemWidth').value), + height_percent: parseFloat(document.getElementById('zoneItemHeight').value) + }; + + if (!itemData.item_name) { + alert('명칭을 입력해주세요.'); + return; + } + + if (projectType === 'project' && !projectId) { + alert('프로젝트를 선택해주세요.'); + return; + } + + try { + let response; + if (itemId) { + // 수정 + response = await axios.put(`/patrol/zone-items/${itemId}`, itemData); + } else { + // 등록 + response = await axios.post(`/patrol/workplaces/${workplaceId}/zone-items`, itemData); + } + + if (response.data.success) { + const savedItemId = itemId || response.data.data?.item_id; + + // 사진 업로드 (새로 추가된 사진만) + const newPhotos = selectedPhotos.filter(p => !p.existing && p.file); + if (newPhotos.length > 0 && savedItemId) { + await uploadZoneItemPhotos(savedItemId, newPhotos); + } + + closeZoneItemModal(); + await loadZoneItems(); + alert(itemId ? '현황이 수정되었습니다.' : '현황이 등록되었습니다.'); + } else { + throw new Error(response.data.message || '저장 실패'); + } + } catch (error) { + console.error('현황 저장 실패:', error); + alert('저장에 실패했습니다: ' + (error.response?.data?.message || error.message)); + } +} + +// 사진 업로드 +async function uploadZoneItemPhotos(itemId, photos) { + for (const photo of photos) { + try { + const formData = new FormData(); + formData.append('photo', photo.file); + formData.append('item_id', itemId); + + await axios.post('/patrol/zone-items/photos', formData, { + headers: { 'Content-Type': 'multipart/form-data' } + }); + } catch (err) { + console.error('사진 업로드 실패:', err); + } + } +} + +// 현황 삭제 +async function deleteZoneItem() { + const itemId = document.getElementById('zoneItemId').value; + if (!itemId) return; + + if (!confirm('이 현황을 삭제하시겠습니까?')) return; + + try { + const response = await axios.delete(`/patrol/zone-items/${itemId}`); + if (response.data.success) { + closeZoneItemModal(); + selectedZoneItem = null; + await loadZoneItems(); + alert('현황이 삭제되었습니다.'); + } else { + throw new Error(response.data.message || '삭제 실패'); + } + } catch (error) { + console.error('현황 삭제 실패:', error); + alert('삭제에 실패했습니다: ' + (error.response?.data?.message || error.message)); + } +} + +// 요약 카드 렌더링 +function renderSummaryCards(summary) { + const container = document.getElementById('summaryCards'); + + container.innerHTML = ` +
+
⚙️
+
+
${summary.equipmentCount}
+
등록 설비
+
+
+
+
🔧
+
+
${summary.pendingRepairs}
+
수리 요청
+
+
+
+
🚨
+
+
${summary.openIssues}
+
미해결 신고
+
+
+
+
🚶
+
+
${summary.todayVisitors}
+
금일 방문자
+
+
+
+
📋
+
+
${summary.todayTbmSessions}
+
금일 TBM
+
+
+ `; +} + +// 안전신고/부적합 탭 렌더링 +function renderIssuesTab() { + const container = document.getElementById('issuesContent'); + const { workIssues } = workplaceData; + + if (!workIssues.all.length) { + container.innerHTML = ` +
+
+
최근 30일간 신고 내역이 없습니다.
+
+ `; + return; + } + + let html = ''; + + // 안전 신고 + if (workIssues.safety.length > 0) { + html += ` +
+

+ 🛡️ 안전 신고 + ${workIssues.safety.length} +

+
+ ${workIssues.safety.map(issue => renderIssueCard(issue, 'safety')).join('')} +
+
+ `; + } + + // 부적합 사항 + if (workIssues.nonconformity.length > 0) { + html += ` +
+

+ ⚠️ 부적합 사항 + ${workIssues.nonconformity.length} +

+
+ ${workIssues.nonconformity.map(issue => renderIssueCard(issue, 'nonconformity')).join('')} +
+
+ `; + } + + container.innerHTML = html; +} + +// 신고 카드 렌더링 +function renderIssueCard(issue, type) { + const statusLabels = { + 'pending': '대기', + 'received': '접수', + 'in_progress': '처리중', + 'completed': '완료', + 'closed': '종료' + }; + const severityLabels = { + 'low': '경미', + 'medium': '보통', + 'high': '중요', + 'critical': '긴급' + }; + + return ` +
+
+ ${escapeHtml(issue.title)} + ${statusLabels[issue.status] || issue.status} +
+
+ 📁 ${escapeHtml(issue.category_name || '미분류')} + ${issue.severity ? `${severityLabels[issue.severity]}` : ''} + 📅 ${formatDateTime(issue.created_at)} + 👤 ${escapeHtml(issue.reporter_name || '익명')} +
+ ${issue.description ? `
${escapeHtml(issue.description)}
` : ''} +
+ `; +} + +// 설비/수리 탭 렌더링 +function renderEquipmentTab() { + const container = document.getElementById('equipmentContent'); + const { equipments, repairRequests } = workplaceData; + + let html = ''; + + // 수리 요청 + if (repairRequests.length > 0) { + html += ` +
+

+ 🔧 수리 요청 + ${repairRequests.length} +

+
+ ${repairRequests.map(req => renderRepairCard(req)).join('')} +
+
+ `; + } + + // 설비 현황 + if (equipments.length > 0) { + html += ` +
+

+ ⚙️ 설비 현황 + ${equipments.length} +

+
+ ${equipments.map(eq => renderEquipmentCard(eq)).join('')} +
+
+ `; + } + + if (!html) { + html = ` +
+
⚙️
+
등록된 설비가 없습니다.
+
+ `; + } + + container.innerHTML = html; +} + +// 수리 요청 카드 렌더링 +function renderRepairCard(req) { + const priorityLabels = { + 'emergency': '긴급', + 'high': '높음', + 'normal': '보통', + 'low': '낮음' + }; + + return ` +
+
+ ${escapeHtml(req.equipment_name)} + ${priorityLabels[req.priority] || req.priority} +
+
📋 ${escapeHtml(req.repair_category)}
+ ${req.description ? `
${escapeHtml(req.description)}
` : ''} +
📅 ${formatDate(req.request_date)}
+
+ `; +} + +// 설비 카드 렌더링 +function renderEquipmentCard(eq) { + const statusLabels = { + 'active': '정상', + 'inactive': '비활성', + 'repair_needed': '수리필요', + 'under_repair': '수리중', + 'disposed': '폐기' + }; + + return ` +
+
⚙️
+
+
${escapeHtml(eq.equipment_name)}
+
${escapeHtml(eq.equipment_type || '-')}
+
+ ${statusLabels[eq.status] || eq.status} +
+ `; +} + +// 출입현황 탭 렌더링 +function renderVisitsTab() { + const container = document.getElementById('visitsContent'); + const { visitRecords } = workplaceData; + + if (!visitRecords.length) { + container.innerHTML = ` +
+
🚶
+
금일 승인된 방문자가 없습니다.
+
+ `; + return; + } + + container.innerHTML = ` +
+

+ 🚶 금일 방문자 + ${visitRecords.length} +

+
+ ${visitRecords.map(visit => renderVisitCard(visit)).join('')} +
+
+ `; +} + +// 방문자 카드 렌더링 +function renderVisitCard(visit) { + return ` +
+
+
+ ${escapeHtml(visit.visitor_name)} + ${visit.visitor_company ? `(${escapeHtml(visit.visitor_company)})` : ''} +
+
+
${escapeHtml(visit.purpose_name || visit.visit_purpose || '')}
+
+ 🕐 ${escapeHtml(visit.visit_time_from || '')} ~ ${escapeHtml(visit.visit_time_to || '')} + ${visit.companion_count > 0 ? `👥 동행 ${visit.companion_count}명` : ''} + ${visit.vehicle_number ? `🚗 ${escapeHtml(visit.vehicle_number)}` : ''} +
+
+ `; +} + +// TBM 탭 렌더링 +function renderTbmTab() { + const container = document.getElementById('tbmContent'); + const { tbmSessions } = workplaceData; + + if (!tbmSessions.length) { + container.innerHTML = ` +
+
📋
+
금일 TBM 세션이 없습니다.
+
+ `; + return; + } + + container.innerHTML = ` +
+

+ 📋 금일 TBM + ${tbmSessions.length} +

+
+ ${tbmSessions.map(tbm => renderTbmCard(tbm)).join('')} +
+
+ `; +} + +// TBM 카드 렌더링 +function renderTbmCard(tbm) { + const statusLabels = { + 'draft': '작성중', + 'in_progress': '진행중', + 'completed': '완료' + }; + + return ` +
+
+ ${escapeHtml(tbm.task_name || tbm.work_type_name || '작업')} + ${statusLabels[tbm.status] || tbm.status} +
+
+ 📍 ${escapeHtml(tbm.work_location || '-')} + 👷 ${escapeHtml(tbm.leader_name || tbm.leader_worker_name || '-')} + 👥 ${tbm.team_size || (tbm.team ? tbm.team.length : 0)}명 +
+ ${tbm.work_content ? ` +
+
작업내용
+
${escapeHtml(tbm.work_content)}
+
+ ` : ''} + ${tbm.safety_measures ? ` +
+
안전조치
+
${escapeHtml(tbm.safety_measures)}
+
+ ` : ''} + ${tbm.team && tbm.team.length > 0 ? ` +
+
참석자 (${tbm.team.length}명)
+
+ ${tbm.team.map(m => ` + ${escapeHtml(m.worker_name)} + `).join('')} +
+
+ ` : ''} +
+ `; +} + +// 순회점검 탭 렌더링 +function renderPatrolTab() { + const container = document.getElementById('patrolContent'); + const { recentPatrol } = workplaceData; + + if (!recentPatrol || !recentPatrol.length) { + container.innerHTML = ` +
+
🔍
+
최근 7일간 순회점검 기록이 없습니다.
+
+ `; + return; + } + + container.innerHTML = ` +
+

+ 🔍 최근 순회점검 + ${recentPatrol.length} +

+
+ ${recentPatrol.map(patrol => renderPatrolCard(patrol)).join('')} +
+
+ `; +} + +// 순회점검 카드 렌더링 +function renderPatrolCard(patrol) { + const timeLabels = { 'morning': '오전', 'afternoon': '오후' }; + + return ` +
+
+ ${formatDate(patrol.patrol_date)} + ${timeLabels[patrol.patrol_time] || patrol.patrol_time} +
+
+ 👤 ${escapeHtml(patrol.inspector_name || '-')} + 📊 ${patrol.status === 'completed' ? '완료' : '진행중'} +
+
+
+
${patrol.checked_count || 0}
+
점검 항목
+
+
+
${patrol.issue_count || 0}
+
주의/불량
+
+
+ ${patrol.notes ? `
📝 ${escapeHtml(patrol.notes)}
` : ''} +
+ `; +} + +// 탭 전환 +function switchTab(tabName) { + // 탭 버튼 활성화 + document.querySelectorAll('.tab-btn').forEach(btn => { + btn.classList.toggle('active', btn.dataset.tab === tabName); + }); + + // 탭 콘텐츠 표시 + document.querySelectorAll('.tab-content').forEach(content => { + content.classList.toggle('active', content.id === `tab-${tabName}`); + }); +} + +// 뒤로 가기 +function goBack() { + // 이전 페이지로 이동, 없으면 일일순회점검 페이지로 + if (document.referrer && document.referrer.includes(window.location.host)) { + window.history.back(); + } else { + window.location.href = '/pages/inspection/daily-patrol.html'; + } +} + +// 유틸리티 함수 +function formatDate(dateStr) { + if (!dateStr) return ''; + const date = new Date(dateStr); + return date.toLocaleDateString('ko-KR', { month: 'long', day: 'numeric', weekday: 'short' }); +} + +function formatDateTime(dateStr) { + if (!dateStr) return ''; + const date = new Date(dateStr); + return date.toLocaleString('ko-KR', { month: 'numeric', day: 'numeric', hour: '2-digit', minute: '2-digit' }); +} diff --git a/deploy/tkfb-package/web-ui/logo 2.png b/deploy/tkfb-package/web-ui/logo 2.png new file mode 100644 index 0000000..5bbd962 Binary files /dev/null and b/deploy/tkfb-package/web-ui/logo 2.png differ diff --git a/deploy/tkfb-package/web-ui/logo.png b/deploy/tkfb-package/web-ui/logo.png new file mode 100644 index 0000000..5bbd962 Binary files /dev/null and b/deploy/tkfb-package/web-ui/logo.png differ diff --git a/deploy/tkfb-package/web-ui/pages/admin/.gitkeep b/deploy/tkfb-package/web-ui/pages/admin/.gitkeep new file mode 100644 index 0000000..cb80f3f --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/.gitkeep @@ -0,0 +1 @@ +# Placeholder file to create admin directory diff --git a/deploy/tkfb-package/web-ui/pages/admin/accounts.html b/deploy/tkfb-package/web-ui/pages/admin/accounts.html new file mode 100644 index 0000000..622b723 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/accounts.html @@ -0,0 +1,286 @@ + + + + + + 관리자 설정 | (주)테크니컬코리아 + + + + + + +
+ + + + +
+
+ + + +
+
+

사용자 계정 관리

+ +
+ +
+
+ +
+ + + + +
+
+ +
+ + + + + + + + + + + + + + +
사용자명아이디역할상태최종 로그인관리
+
+ + +
+
+ + +
+
+

알림 수신자 설정

+

알림 유형별 수신자를 지정합니다. 지정된 사용자에게만 알림이 전송됩니다.

+
+ +
+
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/attendance-report.html b/deploy/tkfb-package/web-ui/pages/admin/attendance-report.html new file mode 100644 index 0000000..76f474c --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/attendance-report.html @@ -0,0 +1,486 @@ + + + + + + 출퇴근-작업보고서 대조 | (주)테크니컬코리아 + + + + + + + + + + + + + +
+
+ + + +
+
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+
+
+
+
+ + +
+
+ +
+
+ + +
+
+
+

대조 결과

+

출퇴근 기록과 작업보고서의 시간을 비교합니다

+
+
+
+ +
+
+
+
+
+
+ + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/departments.html b/deploy/tkfb-package/web-ui/pages/admin/departments.html new file mode 100644 index 0000000..5f09881 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/departments.html @@ -0,0 +1,316 @@ + + + + + + 부서 관리 | (주)테크니컬코리아 + + + + + + + + + + + +
+
+
+ + +
+ +
+

부서 목록

+
+ +
+
+ + +
+
+ 부서를 선택하세요 + +
+ + +
+ 0명 선택됨 + + +
+ +
+
+ 왼쪽에서 부서를 선택하면 해당 부서의 작업자가 표시됩니다. +
+
+
+
+
+
+
+ + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/equipment-detail.html b/deploy/tkfb-package/web-ui/pages/admin/equipment-detail.html new file mode 100644 index 0000000..fbacf63 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/equipment-detail.html @@ -0,0 +1,344 @@ + + + + + + 설비 상세 | (주)테크니컬코리아 + + + + + + + + + + + + +
+ +
+
+ + + + +
+ +
+ + +
+
+

설비 사진

+ +
+
+
등록된 사진이 없습니다
+
+
+ + +
+
+

위치 정보

+
+
+
+
+ 원래 위치: + - +
+ +
+
+ +
+
+
+ + +
+ + + +
+ + +
+
+

수리 이력

+
+
+
수리 이력이 없습니다
+
+
+ + +
+
+

외부반출 이력

+
+
+
외부반출 이력이 없습니다
+
+
+ + +
+
+

이동 이력

+
+
+
이동 이력이 없습니다
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/equipments.html b/deploy/tkfb-package/web-ui/pages/admin/equipments.html new file mode 100644 index 0000000..d7c67f4 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/equipments.html @@ -0,0 +1,220 @@ + + + + + + 설비 관리 | (주)테크니컬코리아 + + + + + + + + + + + + +
+ +
+
+ + + +
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/issue-categories.html b/deploy/tkfb-package/web-ui/pages/admin/issue-categories.html new file mode 100644 index 0000000..a4c8e41 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/issue-categories.html @@ -0,0 +1,321 @@ + + + + + + 신고 카테고리 관리 | (주)테크니컬코리아 + + + + + + + + + + + +
+
+
+ + + +
+ + +
+ + +
+
카테고리를 불러오는 중...
+
+
+
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/notifications.html b/deploy/tkfb-package/web-ui/pages/admin/notifications.html new file mode 100644 index 0000000..42b3833 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/notifications.html @@ -0,0 +1,554 @@ + + + + + + 알림 관리 | (주)테크니컬코리아 + + + + + + + + + + + + +
+
+
+

알림 관리

+
+ +
+
+ +
+
+
0
+
읽지 않은 알림
+
+
+
0
+
전체 알림
+
+
+ +
+
+

알림 목록

+
+ + + +
+
+ +
+
+
🔔
+

알림이 없습니다.

+
+
+ + +
+
+
+ + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/projects.html b/deploy/tkfb-package/web-ui/pages/admin/projects.html new file mode 100644 index 0000000..26433af --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/projects.html @@ -0,0 +1,687 @@ + + + + + + 프로젝트 관리 | (주)테크니컬코리아 + + + + + + + + + +
+
+ + +
+ 전체 0 + 활성 0 + 비활성 0 +
+ +
+ + + + + + + + + + + + + + + + + +
#Job No.프로젝트명상태계약일납기일PM현장활성관리
+
+
+
+ + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/repair-management.html b/deploy/tkfb-package/web-ui/pages/admin/repair-management.html new file mode 100644 index 0000000..89cd9be --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/repair-management.html @@ -0,0 +1,852 @@ + + + + + + 시설설비 관리 | (주)테크니컬코리아 + + + + + + + + + + + +
+
+ + +
+
+
0
+
신청
+
+
+
0
+
접수
+
+
+
0
+
처리중
+
+
+
0
+
완료
+
+
+ +
+ + + + + + + + + + + + + + + + + +
신청일작업장유형설명담당자상태처리
로딩중...
+
+
+
+ + + + + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/tasks.html b/deploy/tkfb-package/web-ui/pages/admin/tasks.html new file mode 100644 index 0000000..27248c4 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/tasks.html @@ -0,0 +1,596 @@ + + + + + + 작업 관리 | (주)테크니컬코리아 + + + + + + + + + + + +
+
+ + +
+ +
+
+ 공정 목록 + 0 +
+
    +
+
+ + +
+
+ 전체 작업 +
+ 활성 0 + 비활성 0 +
+
+
+ + + + + + + + + + + + +
#작업명소속 공정설명상태관리
+
+
+
+
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/workers.html b/deploy/tkfb-package/web-ui/pages/admin/workers.html new file mode 100644 index 0000000..7536732 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/workers.html @@ -0,0 +1,495 @@ + + + + + + 작업자 관리 | (주)테크니컬코리아 + + + + + + + + + + + + + + + +
+
+
+ + + +
+ +
+
+

부서 목록

+ +
+
+ +
+
+ + +
+
+

부서를 선택하세요

+ +
+ +
+
+

부서를 선택해주세요

+

왼쪽에서 부서를 선택하면 해당 부서의 작업자가 표시됩니다.

+
+
+
+
+
+
+
+ + + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/admin/workplaces.html b/deploy/tkfb-package/web-ui/pages/admin/workplaces.html new file mode 100644 index 0000000..48b8a81 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/admin/workplaces.html @@ -0,0 +1,429 @@ + + + + + + 작업장 관리 | (주)테크니컬코리아 + + + + + + + + + + + + + +
+
+
+ +
+
+

+ 🏭 + 작업장 관리 +

+

공장 및 작업장을 등록하고 설비 위치를 지도에서 관리합니다

+
+
+ + + +
+
+ + +
+
+
🏢
+
+

0

+

공장

+
+
+
+
📍
+
+

0

+

전체 작업장

+
+
+
+
+
+

0

+

활성 작업장

+
+
+
+
⚙️
+
+

0

+

등록된 설비

+
+
+
+ + +
+ + +
+ + + + + +
+
+

+ 📋 + 작업장 목록 +

+
+ 전체 0 + 활성 0 +
+
+
+
+ +
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/annual-overview.html b/deploy/tkfb-package/web-ui/pages/attendance/annual-overview.html new file mode 100644 index 0000000..86bffe9 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/annual-overview.html @@ -0,0 +1,762 @@ + + + + + + 연간 연차 현황 | 테크니컬코리아 + + + + + + + + + + + +
+
+ + + +
+ 차감 우선순위: +
1. 이월
+
2. 정기연차
+
3. 장기근속
+
4. 경조사
+
+ + +
+
+ + + + + + + + + + + + + + + + + +
No이름이월정기연차장기근속경조사총 발생총 사용잔여
로딩 중...
+
+
+ + +
+ 변경사항이 있으면 저장 버튼을 눌러주세요 + +
+
+
+ + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/checkin.html b/deploy/tkfb-package/web-ui/pages/attendance/checkin.html new file mode 100644 index 0000000..701cb43 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/checkin.html @@ -0,0 +1,398 @@ + + + + + + 출근 체크 | (주)테크니컬코리아 + + + + + + + + + + + + +
+
+

출근 체크

+

클릭하여 출근/결근 상태를 변경하세요

+ +
+ + + + +
+ +
+
+ + 0 + 출근 +
+
+ + 0 + 결근 +
+
+ + 0 + 연차 +
+
+ +
+ +
+ +
+
+ +
+
+
+ + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/daily.html b/deploy/tkfb-package/web-ui/pages/attendance/daily.html new file mode 100644 index 0000000..7ae1a55 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/daily.html @@ -0,0 +1,392 @@ + + + + + + 일일 출퇴근 입력 | (주)테크니컬코리아 + + + + + + + + + + + + +
+
+ + + +
+
+
+

작업자 출퇴근 기록

+

근태 구분을 선택하면 근무시간이 자동 입력됩니다. 연장근로는 별도로 입력 가능합니다. (조퇴: 2시간, 반반차: 6시간, 반차: 4시간, 정시: 8시간, 주말근무: 0시간)

+
+
+
+ +
+ +
+ +
+
+
+
+
+
+ + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/monthly.html b/deploy/tkfb-package/web-ui/pages/attendance/monthly.html new file mode 100644 index 0000000..3938c29 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/monthly.html @@ -0,0 +1,1161 @@ + + + + + + 월별 출근부 | (주)테크니컬코리아 + + + + + + + + + + + + + +
+
+ + + +
+
+ +
+
+ + +
+
+
+

2026년 2월 출근부

+
+
+
+
+
+
+
+
+
+
+ + +
+
+
+
+ 휴무 (주말/공휴일) +
+
+
+ 정시근무 (8h) +
+
+
+ 연차/반차/반반차/조퇴 +
+
+
+ 연장근무 (초과시간 표시) +
+
+
+ 미입력 +
+
+
+ 미입사 +
+
+
+
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/my-vacation-info.html b/deploy/tkfb-package/web-ui/pages/attendance/my-vacation-info.html new file mode 100644 index 0000000..c206860 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/my-vacation-info.html @@ -0,0 +1,554 @@ + + + + + + 내 연차 정보 | 테크니컬코리아 + + + + + + + + + + + +
+
+ + + +
+ + +
+ + + + + + +
+
+ + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/vacation-allocation.html b/deploy/tkfb-package/web-ui/pages/attendance/vacation-allocation.html new file mode 100644 index 0000000..e0aab09 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/vacation-allocation.html @@ -0,0 +1,354 @@ + + + + + + + 휴가 발생 입력 | 테크니컬코리아 + + + + + + + + + + + + + + + +
+ + + + + +
+
+ + + + + +
+ + + +
+ + +
+
+
+

개별 작업자 휴가 입력

+
+
+ + +
+
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+
+

자동 계산 (연차만 해당)

+ +
+ +
+ + +
+
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ + +
+
+ + +
+

기존 입력 내역

+
+ + + + + + + + + + + + + + + + + + +
작업자연도휴가 유형총 일수사용 일수잔여 일수비고작업
+

작업자를 선택하세요

+
+
+
+ +
+
+
+ + +
+
+
+

근속년수별 연차 일괄 생성

+
+
+ +
+ 주의: 이 기능은 연차(ANNUAL) 휴가 유형만 생성합니다. 각 작업자의 입사일을 기준으로 근속년수를 계산하여 자동으로 연차를 부여합니다. +
+ +
+
+
+ + +
+ +
+ + +
+
+ +
+ + +
+
+ + + + +
+
+
+ + +
+
+
+

특별 휴가 유형 관리

+ +
+
+ +
+ + + + + + + + + + + + + + + + + +
유형명코드우선순위특별 휴가시스템 유형설명작업
+
+

데이터를 불러오는 중...

+
+
+ +
+
+
+ +
+
+ +
+ + +
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/vacation-approval.html b/deploy/tkfb-package/web-ui/pages/attendance/vacation-approval.html new file mode 100644 index 0000000..8affa36 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/vacation-approval.html @@ -0,0 +1,264 @@ + + + + + + 휴가 승인 관리 | (주)테크니컬코리아 + + + + + + + + + + + + + +
+
+ + + +
+ + +
+ + +
+
+
+
+

승인 대기 목록

+

대기 중인 휴가 신청을 승인하거나 거부할 수 있습니다

+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+

전체 신청 내역

+
+ + ~ + + + +
+
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/vacation-input.html b/deploy/tkfb-package/web-ui/pages/attendance/vacation-input.html new file mode 100644 index 0000000..630924b --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/vacation-input.html @@ -0,0 +1,291 @@ + + + + + + 휴가 직접 입력 | (주)테크니컬코리아 + + + + + + + + + + + + +
+
+ + + +
+
+
+

휴가 정보 입력

+

승인 절차 없이 휴가 정보를 직접 입력합니다. 입력 즉시 승인 상태로 저장됩니다.

+
+
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ 작업자를 선택하세요 +
+
+ +
+ + +
+
+ +
+ +
+
+
+
+
+ + +
+
+
+

최근 입력 내역

+
+ +
+
+
+
+ +
+
+
+
+
+
+ + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/vacation-management.html b/deploy/tkfb-package/web-ui/pages/attendance/vacation-management.html new file mode 100644 index 0000000..85c0283 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/vacation-management.html @@ -0,0 +1,458 @@ + + + + + + 휴가 관리 | (주)테크니컬코리아 + + + + + + + + + + + + + +
+
+ + + +
+ + + +
+ + +
+
+
+
+

승인 대기 목록

+

대기 중인 휴가 신청을 승인하거나 거부할 수 있습니다

+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+

휴가 정보 직접 입력

+

승인 절차 없이 휴가 정보를 직접 입력합니다. 입력 즉시 승인 상태로 저장됩니다.

+
+
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ +
+ 작업자를 선택하세요 +
+
+ +
+ + +
+
+ +
+ +
+
+
+
+ + +
+
+

최근 입력 내역

+
+ +
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+

전체 신청 내역

+
+ + ~ + + + +
+
+
+
+ +
+
+
+
+
+
+
+ + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/vacation-request.html b/deploy/tkfb-package/web-ui/pages/attendance/vacation-request.html new file mode 100644 index 0000000..e72defd --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/vacation-request.html @@ -0,0 +1,269 @@ + + + + + + 휴가 신청 | (주)테크니컬코리아 + + + + + + + + + + + + +
+
+ + + +
+
+
+

휴가 잔여 현황

+
+
+
+ +
+
+
+
+ + +
+
+
+

휴가 신청

+
+
+
+
+
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+ +
+ + +
+
+ +
+ +
+
+
+
+
+ + +
+
+
+

내 신청 내역

+
+
+
+ +
+
+
+
+
+
+ + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/attendance/work-status.html b/deploy/tkfb-package/web-ui/pages/attendance/work-status.html new file mode 100644 index 0000000..fbb2a59 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/attendance/work-status.html @@ -0,0 +1,700 @@ + + + + + + 근무 현황 | (주)테크니컬코리아 + + + + + + + + + + + +
+
+ + + + +
+ 정시 0 + 연차 0 + 반차 0 + 반반차 0 + 조퇴 0 + 연장 0 + 결근 0 +
+ + + + + + + + + + + + + + + +
#이름출근근태구분기본연장합계
+ +
+ + +
+
+
+ + + + + diff --git a/deploy/tkfb-package/web-ui/pages/dashboard.html b/deploy/tkfb-package/web-ui/pages/dashboard.html new file mode 100644 index 0000000..b8c9693 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/dashboard.html @@ -0,0 +1,514 @@ + + + + + + + 작업 현황판 | 테크니컬코리아 + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+
+
+
+

작업장 현황

+
+ + +
+
+
+
+ + + + +
+
🏭
+

공장을 선택하세요

+

위에서 공장을 선택하면 작업장 현황을 확인할 수 있습니다.

+
+
+
+
+ + +
+
+
+
+

🚚 임시 이동된 설비

+ +
+
+
+
+ +
+ +
+
+
+ +
+ + + + +
+ + +
+ + +
+
+ +
+
+

+

+
+ +
+ + +
+ +
+ + + + + +
+ + +
+ +
+ +
+
+
👷
+
+ 0 + 작업자 +
+
+
+
🚪
+
+ 0 + 방문자 +
+
+
+
📋
+
+ 0 + 작업 수 +
+
+
+ + +
+

+ 🔧 + 진행 중인 작업 +

+
+

진행 중인 작업이 없습니다.

+
+
+ + +
+

+ ⚙️ + 설비 현황 +

+
+

설비 정보를 불러오는 중...

+
+
+
+ + +
+
+
+ + +
+
+
+ + +
+
+
+ 🗺️ +

상세 지도를 불러오는 중...

+
+
+
+
+ + +
+
+ +
+

+ 📥 + 이 작업장으로 이동해 온 설비 +

+
+

없음

+
+
+ + +
+

+ 📤 + 다른 곳으로 이동한 설비 +

+
+

없음

+
+
+
+
+
+
+ + + + + +
+
+ +
+

+ +
+
+ +
+ +
+
+
+ + +
+
+

설비 사진

+ +
+
+
등록된 사진이 없습니다
+
+
+ + +
+ + + +
+ + +
+

수리 이력

+
+
수리 이력이 없습니다
+
+
+ + +
+

외부반출 이력

+
+
외부반출 이력이 없습니다
+
+
+
+
+
+
+ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/pages/inspection/daily-patrol.html b/deploy/tkfb-package/web-ui/pages/inspection/daily-patrol.html new file mode 100644 index 0000000..a55c2a0 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/inspection/daily-patrol.html @@ -0,0 +1,202 @@ + + + + + + 일일순회점검 | (주)테크니컬코리아 + + + + + + + + + + + + +
+
+
+ + + + +
+ +
+ +
+ +
+ + + + + + +
+
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/inspection/zone-detail.html b/deploy/tkfb-package/web-ui/pages/inspection/zone-detail.html new file mode 100644 index 0000000..7b08cd9 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/inspection/zone-detail.html @@ -0,0 +1,297 @@ + + + + + + 구역 상세 | (주)테크니컬코리아 + + + + + + + + + + + + +
+
+
+ +
+
+ +
+
+

작업장

+

공장

+
+
+ +
+
+ + +
+ +
+ + +
+ + + + + + +
+ + +
+ +
+
+
+

구역 현황

+
+ +
+
+
+
+
지도를 로딩 중...
+
+
+
주의 수준
+
+
양호
+
주의
+
관리필요
+
+
설비 상태
+
+
⚙️ 정상 가동
+
🔧 수리 필요
+
⚠️ 점검중
+
📤 타 작업장 이동
+
📥 임시 배치
+
+
+
+
+ +
+
+
+ + +
+
+
+

로딩 중...

+
+
+ + +
+
+
+

로딩 중...

+
+
+ + +
+
+
+

로딩 중...

+
+
+ + +
+
+
+

로딩 중...

+
+
+ + +
+
+
+

로딩 중...

+
+
+
+
+
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/profile/info.html b/deploy/tkfb-package/web-ui/pages/profile/info.html new file mode 100644 index 0000000..52759b2 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/profile/info.html @@ -0,0 +1,303 @@ + + + + + + 내 프로필 | (주)테크니컬코리아 + + + + + +
+ + +
+
+
+

사용자

+

역할

+
+ +
+ +
+

기본 정보

+
+
+ 사용자 ID + - +
+
+ 사용자명 + - +
+
+ 이름 + - +
+
+ 권한 레벨 + - +
+
+ 작업자 ID + - +
+
+ 가입일 + - +
+
+
+ + +
+

활동 정보

+
+
+ 마지막 로그인 + - +
+
+ 이메일 + - +
+
+ + +
+
+ - + 작업 보고서 +
+
+ - + 이번 달 활동 +
+
+ - + 팀 기여도 +
+
+
+ + +
+

빠른 작업

+
+ + 비밀번호 변경 + + + + + + 돌아가기 + +
+
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/pages/profile/password.html b/deploy/tkfb-package/web-ui/pages/profile/password.html new file mode 100644 index 0000000..5fb0d9e --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/profile/password.html @@ -0,0 +1,373 @@ + + + + + + 비밀번호 변경 | (주)테크니컬코리아 + + + + + +
+ + +
+
+

비밀번호 변경

+

계정 보안을 위해 정기적으로 비밀번호를 변경해주세요

+
+ +
+
+

새 비밀번호 설정

+
+ +
+ +
+ + +
+

비밀번호 요구사항

+
    +
  • 최소 6자 이상 입력해주세요
  • +
  • 영문 대/소문자, 숫자, 특수문자를 조합하면 더 안전합니다
  • +
  • 개인정보나 쉬운 단어는 피해주세요
  • +
  • 이전 비밀번호와 다르게 설정해주세요
  • +
+
+ + +
+
+ +
+ + +
+
+ +
+ +
+ + +
+
+
+ +
+ +
+ + +
+
+ +
+ + +
+
+ + +
+
+
+
+ + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/pages/safety/checklist-manage.html b/deploy/tkfb-package/web-ui/pages/safety/checklist-manage.html new file mode 100644 index 0000000..986ef1d --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/safety/checklist-manage.html @@ -0,0 +1,596 @@ + + + + + + 안전 체크리스트 관리 - TK-FB + + + + + + + +
+ + + +
+ + + +
+ + +
+
+ +
+
+ + +
+
+ +
+
+ +
+
+ + +
+
+ + +
+
+ +
+
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/safety/issue-detail.html b/deploy/tkfb-package/web-ui/pages/safety/issue-detail.html new file mode 100644 index 0000000..53c375d --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/safety/issue-detail.html @@ -0,0 +1,453 @@ + + + + + + 신고 상세 | (주)테크니컬코리아 + + + + + + + + + + +
+ + +
+
+ + ← 목록으로 + + +
+
+
+

로딩 중...

+
+ +
+ + +
+

신고 정보

+
+
+ + +
+

신고 내용

+
+
+ + + + + + + + +
+

상태 변경 이력

+
+
+ + +
+
+
+ + + + + + + + +
+ × + +
+
+ + + + diff --git a/deploy/tkfb-package/web-ui/pages/safety/issue-report.html b/deploy/tkfb-package/web-ui/pages/safety/issue-report.html new file mode 100644 index 0000000..ebe4725 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/safety/issue-report.html @@ -0,0 +1,618 @@ + + + + + + 문제 신고 | (주)테크니컬코리아 + + + + + + + + + + + + +
+ + +
+ +
+
+ 1 + 위치 선택 +
+
+ 2 + 유형 선택 +
+
+ 3 + 항목 선택 +
+
+ 4 + 사진/설명 +
+
+ + +
+

1. 발생 위치 선택

+ +
+ + +
+ +
+ +
+ +
+ 지도에서 작업장을 클릭하여 위치를 선택하세요 +
+ +
+ + +
+ +
+ +
+
+ + +
+

2. 문제 유형 선택

+ +
+
+
부적합 사항
+
자재, 설계, 검사 관련 문제
+
+
+
안전 관련
+
보호구, 위험구역, 안전수칙 관련
+
+
+ + +
+ + +
+

3. 신고 항목 선택

+

해당하는 항목을 선택하세요. 여러 개 선택 가능합니다.

+ +
+

먼저 카테고리를 선택하세요

+
+
+ + +
+

4. 사진 및 추가 설명

+ +
+ +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+ +
+ + +
+
+ + +
+ + +
+
+
+ + +
+
+

작업 선택

+

이 위치에 등록된 작업이 있습니다. 연결할 작업을 선택하세요.

+
+ +
+
+ + + + diff --git a/deploy/tkfb-package/web-ui/pages/safety/management.html b/deploy/tkfb-package/web-ui/pages/safety/management.html new file mode 100644 index 0000000..1edb958 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/safety/management.html @@ -0,0 +1,291 @@ + + + + + + 안전관리 | (주)테크니컬코리아 + + + + + + + + + + +
+ + + + +
+
+ + + +
+
+
승인 대기
+
0
+
+
+
승인 완료
+
0
+
+
+
교육 완료
+
0
+
+
+
반려
+
0
+
+
+ + +
+
+ + + + + +
+ + +
+ +
+
+
+
+
+ + + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/pages/safety/report-status.html b/deploy/tkfb-package/web-ui/pages/safety/report-status.html new file mode 100644 index 0000000..4c37ff9 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/safety/report-status.html @@ -0,0 +1,306 @@ + + + + + + 안전신고 현황 | (주)테크니컬코리아 + + + + + + + + + + +
+ + +
+
+ + + +
+
+
-
+
신고
+
+
+
-
+
접수
+
+
+
-
+
처리중
+
+
+
-
+
완료
+
+
+ + +
+ + + + + + + + 안전 신고 + +
+ + +
+
+
로딩 중...
+
+
+
+
+
+ + + + diff --git a/deploy/tkfb-package/web-ui/pages/safety/report.html b/deploy/tkfb-package/web-ui/pages/safety/report.html new file mode 100644 index 0000000..88a286f --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/safety/report.html @@ -0,0 +1,778 @@ + + + + + + 신고 | (주)테크니컬코리아 + + + + + + + + + + +
+ + +
+
+ + + +
+
+ 1 + 위치 선택 +
+
+
+ 2 + 유형 선택 +
+
+
+ 3 + 항목 선택 +
+
+
+ 4 + 사진/설명 +
+
+ + +
+

+ 1 + 발생 위치 선택 +

+ +
+ + +
+ +
+ +
+ +
+ 지도에서 작업장을 클릭하여 위치를 선택하세요 +
+ +
+ + +
+ +
+ +
+
+ + +
+

+ 2 + 문제 유형 선택 +

+ +
+
+
📋
+
부적합 사항
+
자재, 설계, 검사 관련 문제
+
+
+
+
안전 문제
+
보호구, 위험구역, 안전수칙 관련
+
+
+ + +
+ + +
+

+ 3 + 신고 항목 선택 +

+

해당하는 항목을 선택하거나 직접 입력하세요.

+ +
+

먼저 카테고리를 선택하세요

+
+ + + +
+ + +
+

+ 4 + 사진 및 추가 설명 +

+ +
+ +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+ +
+ + +
+
+ + +
+ + +
+
+
+ + +
+
+

작업 선택

+

이 위치에 등록된 작업이 있습니다. 연결할 작업을 선택하세요.

+
+ +
+
+
+ + + + diff --git a/deploy/tkfb-package/web-ui/pages/safety/training-conduct.html b/deploy/tkfb-package/web-ui/pages/safety/training-conduct.html new file mode 100644 index 0000000..06379ad --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/safety/training-conduct.html @@ -0,0 +1,327 @@ + + + + + + 안전교육 진행 | (주)테크니컬코리아 + + + + + + + + + + +
+ + + + +
+
+ + +
+ +
+

출입 신청 정보

+
+ +
+
+ + +
+

안전교육 체크리스트

+

+ 방문자에게 다음 안전 사항을 교육하고 체크해주세요. +

+ +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+
+ + +
+
+
+ 중요: 모든 체크리스트 항목을 완료하고 방문자의 서명을 받은 후 교육 완료 처리를 해주세요. + 교육 완료 후에는 수정할 수 없습니다. +
+
+ + +
+

방문자 서명 (0명)

+

+ 각 방문자가 왼쪽에 이름을 쓰고 오른쪽에 서명한 후 "저장" 버튼을 눌러주세요. +

+ +
+ +
+ 이름 + + 서명 +
+ +
+
왼쪽에 이름을 쓰고, 오른쪽에 서명해주세요
+
(마우스, 터치, 또는 Apple Pencil 사용)
+
+
+ +
+ + +
+ +
+ 서명 날짜: +
+ + +
+ +
+
+ + +
+ + +
+
+
+
+
+ + + + + diff --git a/deploy/tkfb-package/web-ui/pages/safety/visit-request.html b/deploy/tkfb-package/web-ui/pages/safety/visit-request.html new file mode 100644 index 0000000..1fca46d --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/safety/visit-request.html @@ -0,0 +1,371 @@ + + + + + + 출입 신청 | (주)테크니컬코리아 + + + + + + + + + + +
+ + + + +
+
+ + + +
+
+

출입 정보 입력

+ +
+ +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
지도에서 작업장을 선택하세요
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+ + +
+ + +
+ + +
+ + +
+ + +
+
+
+ + +
+
+

내 출입 신청 현황

+
+ +
+
+
+
+
+
+
+ + +
+
+
+

작업장 선택

+ +
+ + +
+ + +
+ + + +
+
+ + + + + diff --git a/deploy/tkfb-package/web-ui/pages/work/.gitkeep b/deploy/tkfb-package/web-ui/pages/work/.gitkeep new file mode 100644 index 0000000..7765d68 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/work/.gitkeep @@ -0,0 +1 @@ +# Placeholder file to create work directory diff --git a/deploy/tkfb-package/web-ui/pages/work/analysis.html b/deploy/tkfb-package/web-ui/pages/work/analysis.html new file mode 100644 index 0000000..cc7551c --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/work/analysis.html @@ -0,0 +1,2859 @@ + + + + + + 작업 분석 | (주)테크니컬코리아 + + + + + + + + + + + + + + + +
+ + + ← 뒤로가기 + + + + + + + + + +
+
+ +
+ + +
+ +
+ + +
+ + +
+ +
+ + + +
+
+ + +
+ + + + + + + + + + + + + + +
+
+ + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/pages/work/nonconformity.html b/deploy/tkfb-package/web-ui/pages/work/nonconformity.html new file mode 100644 index 0000000..93a69be --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/work/nonconformity.html @@ -0,0 +1,306 @@ + + + + + + 부적합 현황 | (주)테크니컬코리아 + + + + + + + + + + +
+ + +
+
+ + + +
+
+
-
+
신고
+
+
+
-
+
접수
+
+
+
-
+
처리중
+
+
+
-
+
완료
+
+
+ + +
+ + + + + + + + 부적합 신고 + +
+ + +
+
+
로딩 중...
+
+
+
+
+
+ + + + diff --git a/deploy/tkfb-package/web-ui/pages/work/report-create.html b/deploy/tkfb-package/web-ui/pages/work/report-create.html new file mode 100644 index 0000000..f9606fa --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/work/report-create.html @@ -0,0 +1,182 @@ + + + + + + 일일 작업보고서 작성 | (주)테크니컬코리아 + + + + + + + + + +
+ + + + +
+ +
+ + +
+ + +
+ + +
+ +
+ +
+
+ + + +
+
+ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/deploy/tkfb-package/web-ui/pages/work/tbm.html b/deploy/tkfb-package/web-ui/pages/work/tbm.html new file mode 100644 index 0000000..5a1adc7 --- /dev/null +++ b/deploy/tkfb-package/web-ui/pages/work/tbm.html @@ -0,0 +1,672 @@ + + + + + + TBM 관리 | (주)테크니컬코리아 + + + + + + + + + + + +
+ + + + +
+
+ +
+
+

+ 🛠 + TBM (Tool Box Meeting) +

+

아침 안전 회의 및 팀 구성 관리

+
+
+ + +
+ + +
+ + +
+
+
+

+ 📅 + 오늘의 TBM +

+
+ +
+
+ +
+ + 오늘 등록 + 0 + + + + 완료 + 0 + + + + 진행중 + 0 + + +
+ +
+ +
+ + + +
+
+ + +
+
+
+

+ 📚 + TBM 기록 +

+
+ +
+
+ +
+ + + 0 + + + + 완료 + 0 + + + +
+ + +
+ +
+ + + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/templates/README.md b/deploy/tkfb-package/web-ui/templates/README.md new file mode 100644 index 0000000..2c004a5 --- /dev/null +++ b/deploy/tkfb-package/web-ui/templates/README.md @@ -0,0 +1,207 @@ +# 페이지 레이아웃 템플릿 가이드 + +이 디렉토리에는 프로젝트의 표준 페이지 레이아웃 템플릿이 포함되어 있습니다. + +## 📋 사용 가능한 템플릿 + +### 1. `dashboard-layout.html` +**용도**: 메인 대시보드 페이지 +**특징**: +- 빠른 작업 섹션 포함 +- 여러 콘텐츠 섹션 지원 +- 푸터 포함 +- 토스트 알림 지원 + +**적합한 페이지**: +- `dashboard.html` (메인 대시보드) +- 통계/분석 대시보드 + +--- + +### 2. `work-layout.html` +**용도**: 작업 관련 페이지 +**특징**: +- 페이지 제목 및 설명 섹션 +- 검색/필터 영역 +- 작업 콘텐츠 카드 +- 로딩 스피너 +- 모달 지원 + +**적합한 페이지**: +- `work/report-create.html` (작업 보고서 작성) +- `work/report-view.html` (작업 현황 확인) +- `work/analysis.html` (작업 분석) + +--- + +### 3. `admin-layout.html` +**용도**: 관리자 기능 페이지 +**특징**: +- 뒤로가기 버튼이 있는 헤더 +- 탭 네비게이션 지원 +- 데이터 테이블 레이아웃 +- 페이지네이션 +- 일괄 선택 기능 +- 확인 모달 + +**적합한 페이지**: +- `admin/projects.html` (프로젝트 관리) +- `admin/workers.html` (작업자 관리) +- `admin/codes.html` (코드 관리) +- `admin/accounts.html` (계정 관리) + +--- + +### 4. `simple-layout.html` +**용도**: 단순한 폼/프로필 페이지 +**특징**: +- 좁은 중앙 컨테이너 (최대 800px) +- 폼 요소 스타일링 +- 뒤로가기 버튼 +- 정보 표시 리스트 +- 반응형 폼 레이아웃 + +**적합한 페이지**: +- `profile/info.html` (내 프로필) +- `profile/password.html` (비밀번호 변경) +- 설정 페이지 + +--- + +## 🎨 공통 요소 + +모든 템플릿에는 다음이 포함됩니다: + +### CSS +```html + +``` +- 색상, 타이포그래피, 간격 등 CSS 변수 +- 공통 컴포넌트 스타일 (버튼, 카드, 배지 등) + +### 상단 네비게이션 (Navbar) +```html + + +``` +- 자동으로 로드되는 표준 네비게이션 헤더 +- 사용자 프로필 메뉴, 로그아웃 기능 포함 +- 현재 시각 표시 + +### 사이드바 네비게이션 (Sidebar) +```html + + +``` +- 카테고리별 접이식 메뉴 (작업관리, 안전관리, 근태관리, 시스템관리) +- 사용자 권한에 따른 메뉴 자동 필터링 +- 접기/펼치기 상태 자동 저장 (localStorage) +- 현재 페이지 자동 하이라이트 + +### 인증 +```html + +``` +- 페이지 접근 시 자동 로그인 확인 +- 미인증 시 로그인 페이지로 리다이렉트 + +--- + +## 🚀 템플릿 사용 방법 + +### 1단계: 템플릿 복사 +```bash +cp web-ui/templates/work-layout.html web-ui/pages/work/new-page.html +``` + +### 2단계: 메타데이터 수정 +```html +새 페이지 | 테크니컬코리아 +``` + +### 3단계: CSS/JS 추가 +```html + + + + + +``` + +### 4단계: 콘텐츠 작성 +템플릿의 주석 처리된 예시 코드를 참고하여 실제 콘텐츠로 교체합니다. + +--- + +## 📐 CSS 변수 활용 + +모든 템플릿은 `design-system.css`의 CSS 변수를 사용합니다: + +### 색상 +```css +var(--primary-500) /* 하늘색 (기본) */ +var(--success-500) /* 성공 (녹색) */ +var(--error-500) /* 오류 (빨간색) */ +var(--text-primary) /* 주요 텍스트 */ +``` + +### 간격 +```css +var(--space-2) /* 8px */ +var(--space-4) /* 16px */ +var(--space-6) /* 24px */ +``` + +### 타이포그래피 +```css +var(--text-sm) /* 14px */ +var(--text-base) /* 16px */ +var(--font-medium) /* 500 */ +var(--font-bold) /* 700 */ +``` + +### 기타 +```css +var(--radius-md) /* 8px 둥근 모서리 */ +var(--shadow-md) /* 중간 그림자 */ +var(--transition-fast) /* 150ms 전환 */ +``` + +--- + +## ✅ 모범 사례 + +### DO ✅ +- 템플릿을 복사하여 시작 +- CSS 변수 사용 +- 의미있는 클래스명 사용 +- 주석으로 섹션 구분 +- 반응형 디자인 고려 + +### DON'T ❌ +- 하드코딩된 색상 사용 (`#0ea5e9` 대신 `var(--primary-500)`) +- 인라인 스타일 남발 +- 중복 코드 작성 +- 템플릿 구조 크게 변경 + +--- + +## 🔄 템플릿 업데이트 + +템플릿이 업데이트되면: +1. 기존 페이지를 즉시 수정할 필요는 없음 +2. 새 기능이 필요한 페이지만 선택적으로 적용 +3. 주요 변경사항은 `개발 log/` 디렉토리에 문서화 + +--- + +## 📞 문의 + +템플릿 사용에 대한 질문이나 개선 제안이 있으면: +- `CODING_GUIDE.md` 참조 +- 개발팀에 문의 + +--- + +**마지막 업데이트**: 2026-01-20 +**버전**: 1.0.0 diff --git a/deploy/tkfb-package/web-ui/templates/admin-layout.html b/deploy/tkfb-package/web-ui/templates/admin-layout.html new file mode 100644 index 0000000..c9ee676 --- /dev/null +++ b/deploy/tkfb-package/web-ui/templates/admin-layout.html @@ -0,0 +1,157 @@ + + + + + + + 관리자 | 테크니컬코리아 + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + + + + +
+ +
+ + + +
+ + +
+
+ + +
+
+ + +
+ +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ + ID이름상태등록일작업
1샘플 데이터활성2025-01-20 + + +
+
+ + + +
+ +
+
+ + + + + + + + + + diff --git a/deploy/tkfb-package/web-ui/templates/dashboard-layout.html b/deploy/tkfb-package/web-ui/templates/dashboard-layout.html new file mode 100644 index 0000000..fa06825 --- /dev/null +++ b/deploy/tkfb-package/web-ui/templates/dashboard-layout.html @@ -0,0 +1,104 @@ + + + + + + + 대시보드 | 테크니컬코리아 + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ + +
+
+
+

⚡ 빠른 작업

+
+ +
+
+ + +
+
+
+
+

📊 콘텐츠 제목

+ +
+ +
+
+
+
+ +

여기에 페이지 콘텐츠를 추가하세요.

+
+
+
+ +
+ + + + +
+ + +
+ + + + diff --git a/deploy/tkfb-package/web-ui/templates/simple-layout.html b/deploy/tkfb-package/web-ui/templates/simple-layout.html new file mode 100644 index 0000000..d2b4d2f --- /dev/null +++ b/deploy/tkfb-package/web-ui/templates/simple-layout.html @@ -0,0 +1,299 @@ + + + + + + + 페이지 제목 | 테크니컬코리아 + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+ +

페이지 제목

+
+ + +
+
+

섹션 제목

+
+
+ + +
+ + +
+ + + 도움말 텍스트 +
+ + +
+ + +
+ + +
+ + +
+ + +
+ +
+ + +
+ +
+ + +
+
+ + +
+ + +
+ +
+ +
+
+ + +
+
+

추가 정보

+
+
+
+
+ 항목 1: + 값 1 +
+
+ 항목 2: + 값 2 +
+
+ 항목 3: + 값 3 +
+
+
+
+ +
+
+ + + + + +
+ + + + + + diff --git a/deploy/tkfb-package/web-ui/templates/work-layout.html b/deploy/tkfb-package/web-ui/templates/work-layout.html new file mode 100644 index 0000000..44ca82d --- /dev/null +++ b/deploy/tkfb-package/web-ui/templates/work-layout.html @@ -0,0 +1,131 @@ + + + + + + + 작업 관리 | 테크니컬코리아 + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ + +
+

📋 페이지 제목

+

페이지 설명을 여기에 작성하세요

+
+ + +
+ +
+
+ + +
+
+ + +
+ +
+ + +
+

여기에 작업 관련 콘텐츠를 추가하세요.

+ + + +
+ + +
+ + +
+
+ +
+
+ + + + + + + + + + diff --git a/deploy/web-ui-config.js b/deploy/web-ui-config.js new file mode 100644 index 0000000..9fc26a9 --- /dev/null +++ b/deploy/web-ui-config.js @@ -0,0 +1,33 @@ +// /js/config.js - Synology NAS 배포용 +// 이 파일을 web-ui/js/config.js로 복사하세요 + +export const config = { + // API 관련 설정 + api: { + // Synology NAS Docker 환경에서 사용하는 API 서버 포트 + port: 3005, + // API의 기본 경로 + path: '/api', + }, + + // 페이지 경로 설정 + paths: { + loginPage: '/index.html', + dashboard: '/pages/dashboard.html', + defaultDashboard: '/pages/dashboard.html', + systemDashboard: '/pages/dashboard.html', + groupLeaderDashboard: '/pages/dashboard.html', + }, + + // 공용 컴포넌트 경로 설정 + components: { + sidebar: '/components/sidebar.html', + 'sidebar-nav': '/components/sidebar-nav.html', + navbar: '/components/navbar.html', + }, + + // 애플리케이션 관련 기타 설정 + app: { + tokenRefreshInterval: 5 * 60 * 1000, + } +}; diff --git a/docs/vacation-data-flow-guide.md b/docs/vacation-data-flow-guide.md new file mode 100644 index 0000000..c43915f --- /dev/null +++ b/docs/vacation-data-flow-guide.md @@ -0,0 +1,271 @@ +# 휴가 데이터 흐름 가이드 + +> 작성일: 2026-02-05 +> 목적: 휴가 관련 데이터 저장 구조 및 연동 방식 문서화 + +--- + +## 1. 테이블 구조 + +### 1.1 vacation_balance_details (연간 휴가 잔액) +**목적**: 작업자별 연간 휴가 발생/사용 일수 관리 + +| 컬럼 | 설명 | 예시 | +|------|------|------| +| `worker_id` | 작업자 ID | 1 | +| `vacation_type_id` | 휴가 **유형** ID (vacation_types 참조) | 1 (이월), 2 (정기연차) | +| `year` | 연도 | 2026 | +| `total_days` | 발생 일수 | 15 | +| `used_days` | 사용 일수 (자동 연동) | 3 | +| `remaining_days` | 잔여 일수 (자동 계산 컬럼) | 12 | + +### 1.2 daily_attendance_records (일별 근태 기록) +**목적**: 일별 출근/휴가/근무시간 기록 + +| 컬럼 | 설명 | 예시 | +|------|------|------| +| `worker_id` | 작업자 ID | 1 | +| `record_date` | 기록 날짜 | 2026-02-05 | +| `attendance_type_id` | 근태 유형 (1=정상, 2=지각, 3=조퇴, 4=결근, 5=휴가) | 5 | +| `vacation_type_id` | 휴가 **사용** 유형 (1=연차, 2=반차, 3=반반차) | 1 | +| `total_work_hours` | 총 근무시간 | 8.0 | + +### 1.3 vacation_types (휴가 유형 마스터) +**목적**: 휴가 유형 정의 및 차감 우선순위 + +| type_code | type_name | priority | 용도 | +|-----------|-----------|----------|------| +| CARRYOVER | 이월 | 1 | 작년 이월 연차 | +| ANNUAL | 정기연차 | 2 | 올해 발생 연차 | +| LONG_SERVICE | 장기근속 | 3 | 장기근속 보상 | +| WEDDING | 결혼 | 4 | 경조사 | +| SPOUSE_BIRTH | 배우자 출산 | 4 | 경조사 | +| ... | ... | 4 | 기타 경조사 | + +--- + +## 2. 데이터 흐름 + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ 휴가 데이터 흐름도 │ +└─────────────────────────────────────────────────────────────────┘ + +[annual-overview.html] [work-status.html] +연간 연차 현황 페이지 근무 현황 페이지 + │ │ + │ 발생 일수 입력 │ 휴가 사용 기록 + │ (이월, 정기연차, 장기근속, 경조사) │ (연차/반차/반반차) + ▼ ▼ +┌──────────────────┐ ┌──────────────────┐ +│ vacation_balance │◀───── 연동 ───────│ daily_attendance │ +│ _details │ │ _records │ +│ │ │ │ +│ total_days: 15 │ used_days │ vacation_type_id │ +│ used_days: 3 ◀──┼──── 자동 업데이트 ──┼── 1 (연차) │ +│ remaining: 12 │ │ │ +└──────────────────┘ └──────────────────┘ +``` + +--- + +## 3. 연동 로직 + +### 3.1 휴가 사용 시 (work-status.html에서 저장) + +**파일**: `api.hyungi.net/services/attendanceService.js` + +```javascript +// upsertAttendanceRecordService 함수 내부 + +// 1. 기존 기록 조회 +const existingRecord = await AttendanceModel.getDailyAttendanceRecords(record_date, worker_id); + +// 2. 휴가 사용 유형 → 차감 일수 변환 +// vacation_type_id: 1=연차(1일), 2=반차(0.5일), 3=반반차(0.25일) +const daysMap = { 1: 1, 2: 0.5, 3: 0.25 }; +const newDays = daysMap[vacation_type_id] || 0; + +// 3. 이전 휴가가 있었으면 복구 (변경된 경우) +if (previousDays > 0) { + await vacationBalanceModel.restoreByPriority(worker_id, year, previousDays); +} + +// 4. 새 휴가 차감 (우선순위: 이월 → 정기연차 → 장기근속 → 경조사) +if (newDays > 0) { + await vacationBalanceModel.deductByPriority(worker_id, year, newDays); +} +``` + +### 3.2 차감 우선순위 로직 + +**파일**: `api.hyungi.net/models/vacationBalanceModel.js` + +```javascript +// deductByPriority 함수 + +// 1. 우선순위순으로 잔여 일수가 있는 잔액 조회 +SELECT * FROM vacation_balance_details vbd +INNER JOIN vacation_types vt ON vbd.vacation_type_id = vt.id +WHERE vbd.worker_id = ? AND vbd.year = ? + AND (vbd.total_days - vbd.used_days) > 0 +ORDER BY vt.priority ASC -- 이월(1) → 정기연차(2) → 장기근속(3) → 경조사(4) + +// 2. 순서대로 차감 +for (const balance of balances) { + const available = balance.remaining_days; + const toDeduct = Math.min(remaining, available); + + UPDATE vacation_balance_details + SET used_days = used_days + ? + WHERE id = ? +} +``` + +--- + +## 4. 주요 파일 위치 + +``` +api.hyungi.net/ +├── models/ +│ ├── vacationBalanceModel.js # 휴가 잔액 DB 쿼리 +│ │ ├── deductByPriority() # 우선순위 차감 ★ +│ │ └── restoreByPriority() # 우선순위 복구 ★ +│ └── attendanceModel.js # 근태 기록 DB 쿼리 +│ +├── services/ +│ └── attendanceService.js # 근태 저장 비즈니스 로직 +│ └── upsertAttendanceRecordService() # 연동 로직 포함 ★ +│ +├── controllers/ +│ ├── vacationBalanceController.js # 휴가 잔액 API +│ └── attendanceController.js # 근태 API +│ +└── routes/ + ├── vacationBalanceRoutes.js + └── attendanceRoutes.js + +web-ui/pages/attendance/ +├── annual-overview.html # 연간 연차 현황 (발생 일수 입력) - 관리자 전용 +├── my-vacation-info.html # 내 연차 정보 (잔여 확인 + 연장근로) - 전체 사용자 ★ +├── work-status.html # 근무 현황 (휴가 사용 기록) +└── monthly.html # 월별 출근부 (조회 전용) +``` + +--- + +## 5. API 엔드포인트 + +### 5.1 휴가 잔액 관련 + +| Method | Endpoint | 설명 | +|--------|----------|------| +| GET | `/vacation-balances/year/:year` | 연도별 전체 잔액 조회 | +| GET | `/vacation-balances/worker/:workerId/year/:year` | 작업자별 잔액 조회 | +| POST | `/vacation-balances/bulk-upsert` | 일괄 저장 (연간 연차 현황) | + +### 5.2 근태 기록 관련 + +| Method | Endpoint | 설명 | +|--------|----------|------| +| POST | `/attendance/records` | 근태 기록 저장 (휴가 연동 포함) | +| GET | `/attendance/records?date=&worker_id=` | 근태 기록 조회 | + +--- + +## 6. 차감 일수 매핑 + +### 6.1 휴가 사용 유형 (daily_attendance_records.vacation_type_id) + +| ID | 유형 | 차감 일수 | +|----|------|----------| +| 1 | 연차 (ANNUAL_FULL) | 1일 | +| 2 | 반차 (ANNUAL_HALF) | 0.5일 | +| 3 | 반반차 (ANNUAL_QUARTER) | 0.25일 | + +### 6.2 근태 유형 (daily_attendance_records.attendance_type_id) + +| ID | 유형 | 설명 | +|----|------|------| +| 1 | NORMAL | 정상 출근 | +| 2 | LATE | 지각 | +| 3 | EARLY_LEAVE | 조퇴 | +| 4 | ABSENT | 결근 | +| 5 | VACATION | 휴가 | + +--- + +## 7. 주의사항 + +### 7.1 휴가 잔액이 없는 경우 +- 잔액이 없어도 근태 기록은 저장됨 +- 콘솔에 경고 로그 출력 +- 관리자가 연간 연차 현황에서 발생 일수를 먼저 입력해야 함 + +### 7.2 휴가 수정 시 +- 기존 휴가 → 복구 (restoreByPriority) +- 새 휴가 → 차감 (deductByPriority) +- 연차 → 반차 변경 시: 1일 복구 → 0.5일 차감 + +### 7.3 복구 우선순위 +- 차감 우선순위의 역순으로 복구 +- 마지막에 차감된 유형부터 먼저 복구 +- 예: 경조사(4) → 장기근속(3) → 정기연차(2) → 이월(1) + +--- + +## 8. 테스트 시나리오 + +### 8.1 기본 플로우 +1. [연간 연차 현황] 김철수에게 정기연차 15일 입력 → 저장 +2. [근무 현황] 2026-02-05에 김철수 연차 선택 → 저장 +3. [연간 연차 현황] 새로고침 → 총 사용: 1일, 잔여: 14일 확인 + +### 8.2 수정 플로우 +1. [근무 현황] 기존 연차(1일) → 반차(0.5일)로 변경 → 저장 +2. [연간 연차 현황] 새로고침 → 총 사용: 0.5일, 잔여: 14.5일 확인 + +### 8.3 우선순위 테스트 +1. [연간 연차 현황] 이월 2일, 정기연차 15일 입력 +2. [근무 현황] 연차 3회 사용 (3일) +3. [연간 연차 현황] 확인: + - 이월: 2일 발생, 2일 사용, 0일 잔여 + - 정기연차: 15일 발생, 1일 사용, 14일 잔여 + +--- + +## 9. 내 연차 정보 페이지 (my-vacation-info.html) + +### 9.1 기능 +- **연차 잔여 현황**: 유형별(이월, 정기연차, 장기근속, 경조사) 잔여 일수 표시 +- **월간 연장근로**: 선택한 월의 연장근로 시간 및 일별 상세 + +### 9.2 접근 권한 +| 사용자 유형 | 기능 | +|------------|------| +| 일반 사용자 | 본인 정보만 조회 (user.worker_id 기준) | +| 관리자 | 작업자 선택하여 조회 가능 | + +### 9.3 연장근로 계산 로직 +```javascript +// daily_attendance_records에서 8시간 초과분 합산 +records.forEach(r => { + const hours = parseFloat(r.total_work_hours) || 0; + if (hours > 8) { + totalOvertimeHours += (hours - 8); + } +}); +``` + +### 9.4 메뉴 위치 +- 근태 관리 > 내 연차 정보 (최상단) + +--- + +## 10. 향후 개선 사항 + +- [ ] 휴가 신청/승인 시스템 연동 (vacation_requests 테이블) +- [ ] 연차 촉진제 알림 기능 +- [ ] 휴가 사용 내역 상세 조회 기능 +- [ ] 부서별 휴가 현황 대시보드 diff --git a/docs/zone-data-guide.md b/docs/zone-data-guide.md new file mode 100644 index 0000000..8617cad --- /dev/null +++ b/docs/zone-data-guide.md @@ -0,0 +1,224 @@ +# 구역 관련 데이터 구조 가이드 + +## 개요 + +작업장(구역) 관련 데이터는 여러 테이블에 분산 저장됩니다. 이 문서는 각 테이블의 역할과 관계를 정리합니다. + +--- + +## 테이블 구조 + +### 1. 설비 정보 (`equipments`) + +**용도**: 회사 소유 설비/장비의 마스터 데이터 + +**등록 경로**: 설비 관리 페이지 (`/pages/equipment/`) + +| 주요 컬럼 | 설명 | +|-----------|------| +| `equipment_id` | PK | +| `equipment_code` | 관리번호 (예: TKP-001) | +| `equipment_name` | 설비명 | +| `equipment_type` | 유형 (용접기, 턴테이블 등) | +| `workplace_id` | 원래 배치된 작업장 | +| `status` | 상태 (active, repair_needed, maintenance 등) | +| `map_x_percent`, `map_y_percent` | 지도상 위치 (%) | +| `is_temporarily_moved` | 임시 이동 여부 | +| `current_workplace_id` | 현재 위치 (이동 시) | + +**특징**: +- 영구적인 자산 관리 목적 +- 설비 관리 페이지에서 CRUD +- 구역 상세 페이지에서는 **조회만** 가능 + +--- + +### 2. 구역 현황 (`workplace_zone_items`) + +**용도**: 작업장 내 일시적/상시적 현황 기록 (적치물, 작업중 물품, 미신고품 등) + +**등록 경로**: 구역 상세 페이지 (`/pages/inspection/zone-detail.html`) + +| 주요 컬럼 | 설명 | +|-----------|------| +| `item_id` | PK | +| `workplace_id` | 작업장 ID | +| `item_name` | 명칭 | +| `item_type` | 상태/유형 (working, temp_storage, moved_equipment, unreported) | +| `warning_level` | 주의 수준 (good, caution, needs_management) | +| `project_type` | 프로젝트 여부 (project, non_project, unknown) | +| `project_id` | 연결된 프로젝트 ID | +| `x_percent`, `y_percent` | 지도상 위치 (%) | +| `width_percent`, `height_percent` | 영역 크기 (%) | +| `color` | 표시 색상 | +| `description` | 상세 설명 | +| `created_by` | 등록자 | + +**특징**: +- 순회점검 중 또는 수시로 등록 +- 사진 첨부 가능 (`zone_item_photos` 테이블) +- 해소되면 삭제 또는 비활성화 + +--- + +### 3. 구역 현황 사진 (`zone_item_photos`) + +**용도**: 구역 현황에 첨부된 사진 + +| 주요 컬럼 | 설명 | +|-----------|------| +| `photo_id` | PK | +| `item_id` | 연결된 현황 ID (FK → workplace_zone_items) | +| `photo_url` | 사진 경로 | +| `created_at` | 업로드 시간 | + +--- + +### 4. 구역 현황 이력 (`zone_item_history`) + +**용도**: 구역 현황의 등록/수정/삭제 이력 추적 + +| 주요 컬럼 | 설명 | +|-----------|------| +| `history_id` | PK | +| `item_id` | 현황 ID (FK → workplace_zone_items) | +| `action_type` | 행위 (created, updated, deleted) | +| `changed_fields` | 변경된 필드명 (JSON) | +| `old_values` | 이전 값 (JSON) | +| `new_values` | 새 값 (JSON) | +| `changed_by` | 변경자 ID | +| `changed_at` | 변경 시간 | + +**특징**: +- 모든 변경사항 자동 기록 +- 누가, 언제, 무엇을 변경했는지 추적 가능 +- 삭제된 항목의 마지막 상태도 보존 + +--- + +### 5. 순회점검 세션 (`patrol_sessions`) + +**용도**: 일일순회점검 수행 기록 + +**등록 경로**: 일일순회점검 페이지 (`/pages/inspection/daily-patrol.html`) + +| 주요 컬럼 | 설명 | +|-----------|------| +| `session_id` | PK | +| `patrol_date` | 점검 날짜 | +| `patrol_time` | 시간대 (morning, afternoon) | +| `category_id` | 점검 공장 | +| `inspector_id` | 점검자 | +| `status` | 상태 (in_progress, completed) | +| `notes` | 특이사항 | + +--- + +### 6. 순회점검 체크기록 (`patrol_check_records`) + +**용도**: 각 작업장별 체크리스트 점검 결과 + +| 주요 컬럼 | 설명 | +|-----------|------| +| `record_id` | PK | +| `session_id` | 세션 ID (FK → patrol_sessions) | +| `workplace_id` | 작업장 ID | +| `checklist_item_id` | 체크항목 ID | +| `is_checked` | 점검 완료 여부 | +| `check_result` | 결과 (pass, fail, na) | +| `notes` | 비고 | + +**특징**: +- 점검 세션 완료 시 일괄 저장 +- 일시적인 점검 기록 (매일 새로 생성) + +--- + +## 데이터 흐름도 + +``` +┌─────────────────────────────────────────────────────────────┐ +│ 구역 상세 페이지 │ +│ (zone-detail.html) │ +└─────────────────────────────────────────────────────────────┘ + │ + ┌───────────────┼───────────────┐ + ▼ ▼ ▼ + ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ + │ equipments │ │ workplace_ │ │ patrol_ │ + │ (설비) │ │ zone_items │ │ sessions │ + │ │ │ (현황) │ │ (점검) │ + └──────────────┘ └──────────────┘ └──────────────┘ + │ │ │ + │ ▼ ▼ + │ ┌──────────────┐ ┌──────────────┐ + │ │ zone_item_ │ │ patrol_check │ + │ │ photos │ │ _records │ + │ │ (사진) │ │ (체크기록) │ + │ └──────────────┘ └──────────────┘ + │ + ▼ + ┌──────────────┐ + │ repair_ │ + │ requests │ + │ (수리요청) │ + └──────────────┘ +``` + +--- + +## 사용 시나리오 + +### 시나리오 1: 순회점검 중 미신고품 발견 + +1. 일일순회점검 진행 (`patrol_sessions` 생성) +2. 체크리스트 점검 (`patrol_check_records` 저장) +3. 미신고품 발견 → 구역 현황 등록 (`workplace_zone_items`) +4. 사진 촬영 → 첨부 (`zone_item_photos`) + +### 시나리오 2: 설비 상태 확인 + +1. 구역 상세 페이지 접근 +2. 지도에 설비 표시 (`equipments` 조회) +3. 수리 필요 설비 확인 → 수리 요청 (`repair_requests`) + +### 시나리오 3: 임시 적치물 관리 + +1. 작업 중 자재 임시 적치 +2. 구역 현황 등록 (item_type: temp_storage) +3. 작업 완료 후 → 현황 삭제 + +--- + +## API 엔드포인트 + +| 기능 | Method | Endpoint | +|------|--------|----------| +| 설비 목록 | GET | `/api/equipments` | +| 구역 현황 목록 | GET | `/api/patrol/workplaces/:id/zone-items` | +| 구역 현황 등록 | POST | `/api/patrol/workplaces/:id/zone-items` | +| 구역 현황 수정 | PUT | `/api/patrol/zone-items/:itemId` | +| 구역 현황 삭제 | DELETE | `/api/patrol/zone-items/:itemId` | +| 현황 사진 업로드 | POST | `/api/patrol/zone-items/photos` | +| 순회점검 세션 | POST | `/api/patrol/sessions` | +| 체크기록 저장 | POST | `/api/patrol/sessions/:id/records` | + +--- + +## 주의사항 + +1. **설비 vs 구역 현황** + - 설비: 회사 자산 (영구 관리) + - 구역 현황: 일시적 상황 기록 (수시 변경) + +2. **순회점검 체크기록 vs 구역 현황** + - 체크기록: 당일 점검 결과 (일회성) + - 구역 현황: 해소될 때까지 유지 (지속성) + +3. **프로젝트 연결** + - 구역 현황만 프로젝트 연결 가능 + - 설비는 작업장에만 연결 + +--- + +*최종 수정: 2026-02-05* diff --git a/web-ui/components/mobile-nav.html b/web-ui/components/mobile-nav.html new file mode 100644 index 0000000..edd2765 --- /dev/null +++ b/web-ui/components/mobile-nav.html @@ -0,0 +1,135 @@ + + + + + + + diff --git a/web-ui/components/navbar.html b/web-ui/components/navbar.html index 4875afd..53922b4 100644 --- a/web-ui/components/navbar.html +++ b/web-ui/components/navbar.html @@ -3,6 +3,10 @@
+ +
@@ -16,7 +20,7 @@
--월 --일 (--) - --:--:-- + --시 --분 --초
🌤️ @@ -598,18 +602,61 @@ body { font-size: var(--text-sm); } +/* 모바일 메뉴 버튼 */ +.mobile-menu-btn { + display: none; + align-items: center; + justify-content: center; + width: 44px; + height: 44px; + background: rgba(255, 255, 255, 0.15); + border: 1px solid rgba(255, 255, 255, 0.25); + border-radius: 10px; + cursor: pointer; + color: white; + font-size: 1.5rem; + transition: all 0.2s; + margin-right: var(--space-3); + flex-shrink: 0; +} + +.mobile-menu-btn:hover, +.mobile-menu-btn:active { + background: rgba(255, 255, 255, 0.25); +} + /* 반응형 디자인 */ +@media (max-width: 1024px) { + .mobile-menu-btn { + display: flex; + } +} + @media (max-width: 768px) { .dashboard-header { - padding: var(--space-3) var(--space-4); + padding: var(--space-2) var(--space-3); + height: 64px; + } + + body { + padding-top: 64px; + } + + .header-content { + padding: 0 var(--space-2); + } + + .brand-logo { + width: 36px; + height: 36px; } .brand-title { - font-size: var(--text-lg); + font-size: var(--text-base); } .brand-subtitle { - font-size: var(--text-xs); + display: none; } .header-center { @@ -620,6 +667,11 @@ body { display: none; } + .user-avatar { + width: 36px; + height: 36px; + } + .dashboard-btn .btn-text, .report-btn .btn-text { display: none; @@ -627,12 +679,55 @@ body { .dashboard-btn, .report-btn { - padding: var(--space-2) var(--space-3); + padding: var(--space-2); + width: 40px; + height: 40px; + justify-content: center; + } + + .dashboard-btn .btn-icon, + .report-btn .btn-icon { + margin: 0; + } + + .notification-btn { + width: 40px; + height: 40px; } .notification-dropdown { - width: 280px; - right: -50px; + position: fixed; + top: 64px; + left: var(--space-3); + right: var(--space-3); + width: auto; + } + + .header-right { + gap: var(--space-2); + } + + .mobile-menu-btn { + width: 40px; + height: 40px; + margin-right: var(--space-2); + } + + .user-profile { + padding: var(--space-1) var(--space-2); + } + + .profile-menu { + position: fixed; + top: 64px; + right: var(--space-3); + left: auto; + width: 200px; } } + +/* 모바일 사이드바 열릴 때 바디 스크롤 방지 */ +body.sidebar-mobile-open { + overflow: hidden; +} \ No newline at end of file diff --git a/web-ui/components/sidebar-nav.html b/web-ui/components/sidebar-nav.html index ae3e634..2bd3234 100644 --- a/web-ui/components/sidebar-nav.html +++ b/web-ui/components/sidebar-nav.html @@ -89,6 +89,9 @@