-- 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 ;