# Current Database Schema > **Last Updated**: 2025-12-19 > **Source**: Synthesized from `hyungi_schema_v2.sql`, migration files, setup scripts, and model definitions. This document represents the most up-to-date understanding of the database schema, reflecting all migrations and code-inferred structures. --- ## Main Tables ### `users` *Source: `hyungi_schema_v2.sql`* ```sql 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; ``` ### `projects` *Source: `hyungi_schema_v2.sql` + `20251219010000_add_columns_to_projects.js` migration.* ```sql 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, `is_active` tinyint(1) DEFAULT 1, `project_status` varchar(255) DEFAULT 'active', `completed_date` date 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; ``` ### `workers` *Source: `hyungi_schema_v2.sql`* ```sql 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; ``` ### `daily_work_reports` *Source: `hyungi.sql`* ```sql 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`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ``` --- ## Attendance Management Tables *Source: `create-attendance-tables.js`* ### `work_attendance_types` ```sql 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='근로 유형 관리 테이블'; ``` ### `vacation_types` ```sql 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='휴가 유형 관리 테이블'; ``` ### `daily_attendance_records` ```sql 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`) ) COMMENT='일일 근태 기록 테이블'; ``` ### `worker_vacation_balance` ```sql 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`) ) COMMENT='작업자별 휴가 잔여 관리 테이블'; ``` --- ## Legacy & Misc Tables ### `Tools` *Source: Inferred from `models/toolsModel.js`* ```sql CREATE TABLE `Tools` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(255) DEFAULT NULL, `location` varchar(255) DEFAULT NULL, `stock` int(11) DEFAULT NULL, `status` varchar(255) DEFAULT NULL, `factory_id` int(11) DEFAULT NULL, `map_x` decimal(10, 6) DEFAULT NULL, `map_y` decimal(10, 6) DEFAULT NULL, `map_zone` varchar(255) DEFAULT NULL, `map_note` text, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; ``` ### `DailyIssueReports` *Source: `hyungi.sql`* ```sql 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`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; ``` ### `IssueTypes` *Source: `hyungi.sql`* ```sql 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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; ``` ### `work_types` *Source: `hyungi.sql`* ```sql 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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ``` ### `work_status_types` *Source: `hyungi.sql`* ```sql 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 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ``` ### `error_types` *Source: `hyungi.sql`* ```sql CREATE TABLE `error_types` ( `id` int(11) NOT NULL AUTO_INCREMENT, `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(), PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ``` ### `WorkReports` (Legacy) *Source: `hyungi.sql`* *Note: This appears to be a legacy version of `daily_work_reports`.* ```sql 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`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; ```