Files
TK-FB-Project/docs/database/CURRENT_SCHEMA.md
Hyungi Ahn 05843da1c4 refactor(db,frontend): Improve queries and modularize frontend
- Replaced SELECT* queries in 8 models with explicit columns.
- Began modularizing work-report-calendar.js by creating CalendarAPI.js, CalendarState.js, and CalendarView.js.
- Refactored manage-project.js to use global API helpers.
- Fixed API container crash by adding missing volume mounts to docker-compose.yml.
- Added new migration for missing columns in the projects table.
- Documented current DB schema and deployment notes.
2025-12-19 12:42:24 +09:00

11 KiB

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

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.

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

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

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

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

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

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

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

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

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

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

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

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

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.

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;