init: SR System — Helpdesk & ITAM Portal

This commit is contained in:
pray4skylark
2026-06-02 13:50:39 +09:00
commit 832c9f096f
262 changed files with 30470 additions and 0 deletions
@@ -0,0 +1,51 @@
server:
port: 8080
spring:
datasource:
url: jdbc:postgresql://localhost:5432/sr_system
username: sr_admin
password: ${DB_PASSWORD:'!Tp@rtner$'}
driver-class-name: org.postgresql.Driver
jpa:
hibernate:
ddl-auto: validate
show-sql: false
properties:
hibernate:
dialect: org.hibernate.dialect.PostgreSQLDialect
format_sql: true
jackson:
serialization:
fail-on-empty-beans: false
flyway:
enabled: true
locations: classpath:db/migration
baseline-on-migrate: true
validate-on-migrate: false
batch:
jdbc:
initialize-schema: always
job:
enabled: false
jwt:
secret: ${JWT_SECRET:sr-system-jwt-secret-key-change-in-production-at-least-256-bits-long}
access-token-expiration: 3600000
refresh-token-expiration: 604800000
parking:
enabled: false
schedule:
weekday-start: "20:00"
weekday-end: "08:00"
weekends: true
file:
upload-dir: ./uploads
notification:
slack:
webhook-url: ${SLACK_WEBHOOK_URL:}
email:
enabled: false
@@ -0,0 +1,443 @@
-- ============================================================
-- SR System (HQ Helpdesk) - Initial Schema
-- PostgreSQL 15
-- ============================================================
-- ============================================================
-- SEQUENCES (INCREMENT BY 50 for JPA allocationSize)
-- ============================================================
CREATE SEQUENCE sq_employees START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_projects START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_dispatch_histories START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_tickets START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_ticket_comments START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_equipment START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_equipment_assignments START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_equipment_maintenance START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_reports START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_training_progress START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_notifications START WITH 1 INCREMENT BY 50;
CREATE SEQUENCE sq_common_codes START WITH 1 INCREMENT BY 50;
-- ============================================================
-- TB_EMPLOYEE
-- ============================================================
CREATE TABLE tb_employee (
id BIGINT NOT NULL PRIMARY KEY,
login_id VARCHAR(50) NOT NULL UNIQUE,
password VARCHAR(255) NOT NULL,
name VARCHAR(100) NOT NULL,
email VARCHAR(255),
phone VARCHAR(20),
role_code VARCHAR(20) NOT NULL CHECK (role_code IN ('ADMIN', 'MANAGER', 'EMPLOYEE')),
emp_status VARCHAR(20) NOT NULL CHECK (emp_status IN ('ACTIVE', 'ON_LEAVE', 'RESIGNED')),
dispatch_status VARCHAR(20) NOT NULL CHECK (dispatch_status IN ('WAITING', 'DISPATCHED')),
joined_date DATE,
left_date DATE,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N'
);
CREATE INDEX idx_employee_login_id ON tb_employee(login_id);
CREATE INDEX idx_employee_role_code ON tb_employee(role_code);
CREATE INDEX idx_employee_emp_status ON tb_employee(emp_status);
CREATE INDEX idx_employee_dispatch_status ON tb_employee(dispatch_status);
-- ============================================================
-- TB_PROJECT
-- ============================================================
CREATE TABLE tb_project (
id BIGINT NOT NULL PRIMARY KEY,
project_type VARCHAR(20) NOT NULL CHECK (project_type IN ('SI', 'SM', 'MIGRATION')),
project_name VARCHAR(255) NOT NULL,
contract_company VARCHAR(255) NOT NULL,
end_user_company VARCHAR(255),
contract_type VARCHAR(20) NOT NULL CHECK (contract_type IN ('TURN_KEY', 'MM')),
status VARCHAR(20) NOT NULL CHECK (status IN ('PREPARING', 'ONGOING', 'COMPLETED', 'HOLD')),
start_date DATE NOT NULL,
end_date DATE,
work_location_type VARCHAR(20) NOT NULL CHECK (work_location_type IN ('ON_SITE', 'REMOTE', 'HYBRID')),
work_address VARCHAR(500),
tech_environment TEXT,
main_task_desc TEXT,
internal_manager_id BIGINT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_project_internal_manager
FOREIGN KEY (internal_manager_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_project_project_type ON tb_project(project_type);
CREATE INDEX idx_project_status ON tb_project(status);
CREATE INDEX idx_project_contract_company ON tb_project(contract_company);
CREATE INDEX idx_project_internal_manager_id ON tb_project(internal_manager_id);
-- ============================================================
-- TB_DISPATCH_HISTORY
-- ============================================================
CREATE TABLE tb_dispatch_history (
id BIGINT NOT NULL PRIMARY KEY,
employee_id BIGINT NOT NULL,
project_id BIGINT NOT NULL,
start_date DATE NOT NULL,
end_date DATE,
role_title VARCHAR(255) NOT NULL,
contribution_rate INTEGER NOT NULL CHECK (contribution_rate BETWEEN 0 AND 100),
individual_tech TEXT NOT NULL,
performed_tasks TEXT NOT NULL,
achievements TEXT,
client_feedback TEXT,
internal_rating INTEGER CHECK (internal_rating BETWEEN 0 AND 100),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_dispatch_employee
FOREIGN KEY (employee_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT,
CONSTRAINT fk_dispatch_project
FOREIGN KEY (project_id)
REFERENCES tb_project(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_dispatch_employee_id ON tb_dispatch_history(employee_id);
CREATE INDEX idx_dispatch_project_id ON tb_dispatch_history(project_id);
CREATE INDEX idx_dispatch_start_date ON tb_dispatch_history(start_date);
-- ============================================================
-- TB_TICKET
-- ============================================================
CREATE TABLE tb_ticket (
id BIGINT NOT NULL PRIMARY KEY,
project_id BIGINT NOT NULL,
requester_id BIGINT NOT NULL,
assignee_id BIGINT,
category VARCHAR(20) NOT NULL CHECK (category IN ('BUG', 'FEATURE', 'SUPPORT', 'QA')),
priority VARCHAR(20) NOT NULL CHECK (priority IN ('LOW', 'NORMAL', 'HIGH', 'CRITICAL')),
title VARCHAR(500) NOT NULL,
description TEXT NOT NULL,
status VARCHAR(20) NOT NULL CHECK (status IN ('OPEN', 'ASSIGNED', 'IN_PROGRESS', 'RESOLVED', 'CLOSED')),
due_date TIMESTAMP,
resolved_at TIMESTAMP,
resolution_note TEXT,
sla_warn_flag CHAR(1) NOT NULL DEFAULT 'N',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_ticket_project
FOREIGN KEY (project_id)
REFERENCES tb_project(id)
ON DELETE RESTRICT,
CONSTRAINT fk_ticket_requester
FOREIGN KEY (requester_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT,
CONSTRAINT fk_ticket_assignee
FOREIGN KEY (assignee_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_ticket_project_id ON tb_ticket(project_id);
CREATE INDEX idx_ticket_requester_id ON tb_ticket(requester_id);
CREATE INDEX idx_ticket_assignee_id ON tb_ticket(assignee_id);
CREATE INDEX idx_ticket_status ON tb_ticket(status);
CREATE INDEX idx_ticket_priority ON tb_ticket(priority);
CREATE INDEX idx_ticket_category ON tb_ticket(category);
CREATE INDEX idx_ticket_due_date ON tb_ticket(due_date);
-- ============================================================
-- TB_TICKET_COMMENT
-- ============================================================
CREATE TABLE tb_ticket_comment (
id BIGINT NOT NULL PRIMARY KEY,
ticket_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
comment_text TEXT NOT NULL,
attached_file_url VARCHAR(1000),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_comment_ticket
FOREIGN KEY (ticket_id)
REFERENCES tb_ticket(id)
ON DELETE RESTRICT,
CONSTRAINT fk_comment_user
FOREIGN KEY (user_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_comment_ticket_id ON tb_ticket_comment(ticket_id);
CREATE INDEX idx_comment_user_id ON tb_ticket_comment(user_id);
-- ============================================================
-- TB_EQUIPMENT
-- ============================================================
CREATE TABLE tb_equipment (
id BIGINT NOT NULL PRIMARY KEY,
equipment_type VARCHAR(20) NOT NULL CHECK (equipment_type IN ('LAPTOP', 'MONITOR', 'TEST_DEVICE', 'ACCESSORY')),
manufacturer VARCHAR(255) NOT NULL,
model_name VARCHAR(255) NOT NULL,
serial_number VARCHAR(100) NOT NULL UNIQUE,
asset_code VARCHAR(100) NOT NULL UNIQUE,
specifications JSONB,
status VARCHAR(20) NOT NULL CHECK (status IN ('AVAILABLE', 'IN_USE', 'REPAIRING', 'RETIRED', 'LOST')),
purchase_date DATE NOT NULL,
warranty_exp_date DATE,
version BIGINT NOT NULL DEFAULT 0,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N'
);
CREATE INDEX idx_equipment_equipment_type ON tb_equipment(equipment_type);
CREATE INDEX idx_equipment_status ON tb_equipment(status);
CREATE INDEX idx_equipment_asset_code ON tb_equipment(asset_code);
CREATE INDEX idx_equipment_serial_number ON tb_equipment(serial_number);
-- ============================================================
-- TB_EQUIPMENT_ASSIGNMENT
-- ============================================================
CREATE TABLE tb_equipment_assignment (
id BIGINT NOT NULL PRIMARY KEY,
equipment_id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
assigned_date TIMESTAMP NOT NULL DEFAULT NOW(),
returned_date TIMESTAMP,
cond_on_assign TEXT NOT NULL,
cond_on_return TEXT,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_assignment_equipment
FOREIGN KEY (equipment_id)
REFERENCES tb_equipment(id)
ON DELETE RESTRICT,
CONSTRAINT fk_assignment_user
FOREIGN KEY (user_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_assignment_equipment_id ON tb_equipment_assignment(equipment_id);
CREATE INDEX idx_assignment_user_id ON tb_equipment_assignment(user_id);
CREATE INDEX idx_assignment_assigned_date ON tb_equipment_assignment(assigned_date);
-- ============================================================
-- TB_EQUIPMENT_MAINTENANCE
-- ============================================================
CREATE TABLE tb_equipment_maintenance (
id BIGINT NOT NULL PRIMARY KEY,
equipment_id BIGINT NOT NULL,
reported_by BIGINT NOT NULL,
maintenance_type VARCHAR(20) NOT NULL CHECK (maintenance_type IN ('REPAIR', 'UPGRADE', 'INSPECTION', 'DISPOSAL')),
issue_description TEXT NOT NULL,
action_taken TEXT,
cost NUMERIC(12, 2) NOT NULL DEFAULT 0,
reported_date TIMESTAMP NOT NULL DEFAULT NOW(),
resolved_date TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_maintenance_equipment
FOREIGN KEY (equipment_id)
REFERENCES tb_equipment(id)
ON DELETE RESTRICT,
CONSTRAINT fk_maintenance_reported_by
FOREIGN KEY (reported_by)
REFERENCES tb_employee(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_maintenance_equipment_id ON tb_equipment_maintenance(equipment_id);
CREATE INDEX idx_maintenance_reported_by ON tb_equipment_maintenance(reported_by);
CREATE INDEX idx_maintenance_type ON tb_equipment_maintenance(maintenance_type);
-- ============================================================
-- TB_REPORT
-- ============================================================
CREATE TABLE tb_report (
id BIGINT NOT NULL PRIMARY KEY,
dispatch_id BIGINT,
user_id BIGINT NOT NULL,
report_type VARCHAR(20) NOT NULL CHECK (report_type IN ('DAILY', 'WEEKLY', 'MONTHLY', 'RETURN')),
target_date DATE NOT NULL,
completed_tasks TEXT NOT NULL,
planned_tasks TEXT NOT NULL,
issues_and_risks TEXT,
support_requested TEXT,
status VARCHAR(20) NOT NULL CHECK (status IN ('DRAFT', 'SUBMITTED', 'APPROVED', 'REJECTED')),
reviewer_id BIGINT,
review_comment TEXT,
reviewed_at TIMESTAMP,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_report_dispatch
FOREIGN KEY (dispatch_id)
REFERENCES tb_dispatch_history(id)
ON DELETE RESTRICT,
CONSTRAINT fk_report_user
FOREIGN KEY (user_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT,
CONSTRAINT fk_report_reviewer
FOREIGN KEY (reviewer_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_report_user_id ON tb_report(user_id);
CREATE INDEX idx_report_dispatch_id ON tb_report(dispatch_id);
CREATE INDEX idx_report_report_type ON tb_report(report_type);
CREATE INDEX idx_report_status ON tb_report(status);
CREATE INDEX idx_report_target_date ON tb_report(target_date);
CREATE INDEX idx_report_reviewer_id ON tb_report(reviewer_id);
-- ============================================================
-- TB_TRAINING_PROGRESS
-- ============================================================
CREATE TABLE tb_training_progress (
id BIGINT NOT NULL PRIMARY KEY,
user_id BIGINT NOT NULL,
course_name VARCHAR(255) NOT NULL,
progress_rate INTEGER NOT NULL CHECK (progress_rate BETWEEN 0 AND 100),
status VARCHAR(20) NOT NULL CHECK (status IN ('NOT_STARTED', 'ONGOING', 'COMPLETED')),
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_training_user
FOREIGN KEY (user_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_training_user_id ON tb_training_progress(user_id);
CREATE INDEX idx_training_status ON tb_training_progress(status);
CREATE INDEX idx_training_course_name ON tb_training_progress(course_name);
-- ============================================================
-- TB_NOTIFICATION
-- ============================================================
CREATE TABLE tb_notification (
id BIGINT NOT NULL PRIMARY KEY,
user_id BIGINT NOT NULL,
type VARCHAR(50) NOT NULL,
title VARCHAR(255) NOT NULL,
message TEXT NOT NULL,
is_read CHAR(1) NOT NULL DEFAULT 'N',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N',
CONSTRAINT fk_notification_user
FOREIGN KEY (user_id)
REFERENCES tb_employee(id)
ON DELETE RESTRICT
);
CREATE INDEX idx_notification_user_id ON tb_notification(user_id);
CREATE INDEX idx_notification_type ON tb_notification(type);
CREATE INDEX idx_notification_is_read ON tb_notification(is_read);
-- ============================================================
-- TB_COMMON_CODE
-- ============================================================
CREATE TABLE tb_common_code (
id BIGINT NOT NULL PRIMARY KEY,
group_code VARCHAR(50) NOT NULL,
code_value VARCHAR(100) NOT NULL,
code_name VARCHAR(255) NOT NULL,
option_val1 VARCHAR(255),
option_val2 VARCHAR(255),
sort_order INTEGER NOT NULL DEFAULT 0,
is_active CHAR(1) NOT NULL DEFAULT 'Y',
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) NOT NULL DEFAULT 'N'
);
CREATE INDEX idx_common_code_group_code ON tb_common_code(group_code);
CREATE INDEX idx_common_code_is_active ON tb_common_code(is_active);
CREATE UNIQUE INDEX idx_common_code_group_value ON tb_common_code(group_code, code_value);
-- ============================================================
-- INITIAL DATA - COMMON CODES
-- ============================================================
INSERT INTO tb_common_code (id, group_code, code_value, code_name, sort_order, is_active) VALUES
(nextval('sq_common_codes'), 'EMP_ROLE', 'ADMIN', '최고 관리자', 1, 'Y'),
(nextval('sq_common_codes'), 'EMP_ROLE', 'MANAGER', '본사 관리자', 2, 'Y'),
(nextval('sq_common_codes'), 'EMP_ROLE', 'EMPLOYEE', '일반 사용자', 3, 'Y'),
(nextval('sq_common_codes'), 'EMP_STATUS', 'ACTIVE', '재직', 1, 'Y'),
(nextval('sq_common_codes'), 'EMP_STATUS', 'ON_LEAVE', '휴직', 2, 'Y'),
(nextval('sq_common_codes'), 'EMP_STATUS', 'RESIGNED', '퇴사', 3, 'Y'),
(nextval('sq_common_codes'), 'DISPATCH_STATUS', 'WAITING', '대기', 1, 'Y'),
(nextval('sq_common_codes'), 'DISPATCH_STATUS', 'DISPATCHED', '파견중', 2, 'Y'),
(nextval('sq_common_codes'), 'PROJECT_TYPE', 'SI', '시스템 통합', 1, 'Y'),
(nextval('sq_common_codes'), 'PROJECT_TYPE', 'SM', '시스템 유지보수', 2, 'Y'),
(nextval('sq_common_codes'), 'PROJECT_TYPE', 'MIGRATION', '마이그레이션', 3, 'Y'),
(nextval('sq_common_codes'), 'CONTRACT_TYPE', 'TURN_KEY', '턴키', 1, 'Y'),
(nextval('sq_common_codes'), 'CONTRACT_TYPE', 'MM', '인월계약', 2, 'Y'),
(nextval('sq_common_codes'), 'PROJECT_STATUS', 'PREPARING', '준비중', 1, 'Y'),
(nextval('sq_common_codes'), 'PROJECT_STATUS', 'ONGOING', '진행중', 2, 'Y'),
(nextval('sq_common_codes'), 'PROJECT_STATUS', 'COMPLETED', '완료', 3, 'Y'),
(nextval('sq_common_codes'), 'PROJECT_STATUS', 'HOLD', '보류', 4, 'Y'),
(nextval('sq_common_codes'), 'WORK_LOCATION', 'ON_SITE', '현상근무', 1, 'Y'),
(nextval('sq_common_codes'), 'WORK_LOCATION', 'REMOTE', '재택', 2, 'Y'),
(nextval('sq_common_codes'), 'WORK_LOCATION', 'HYBRID', '하이브리드', 3, 'Y'),
(nextval('sq_common_codes'), 'TICKET_CATEGORY', 'BUG', '버그', 1, 'Y'),
(nextval('sq_common_codes'), 'TICKET_CATEGORY', 'FEATURE', '기능요청', 2, 'Y'),
(nextval('sq_common_codes'), 'TICKET_CATEGORY', 'SUPPORT', '기술지원', 3, 'Y'),
(nextval('sq_common_codes'), 'TICKET_CATEGORY', 'QA', '품질문의', 4, 'Y'),
(nextval('sq_common_codes'), 'TICKET_PRIORITY', 'LOW', '낮음', 1, 'Y'),
(nextval('sq_common_codes'), 'TICKET_PRIORITY', 'NORMAL', '보통', 2, 'Y'),
(nextval('sq_common_codes'), 'TICKET_PRIORITY', 'HIGH', '높음', 3, 'Y'),
(nextval('sq_common_codes'), 'TICKET_PRIORITY', 'CRITICAL', '긴급', 4, 'Y'),
(nextval('sq_common_codes'), 'TICKET_STATUS', 'OPEN', '접수', 1, 'Y'),
(nextval('sq_common_codes'), 'TICKET_STATUS', 'ASSIGNED', '배정', 2, 'Y'),
(nextval('sq_common_codes'), 'TICKET_STATUS', 'IN_PROGRESS', '처리중', 3, 'Y'),
(nextval('sq_common_codes'), 'TICKET_STATUS', 'RESOLVED', '해결', 4, 'Y'),
(nextval('sq_common_codes'), 'TICKET_STATUS', 'CLOSED', '종료', 5, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_TYPE', 'LAPTOP', '노트북', 1, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_TYPE', 'MONITOR', '모니터', 2, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_TYPE', 'TEST_DEVICE', '테스트장비', 3, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_TYPE', 'ACCESSORY', '액세서리', 4, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_STATUS', 'AVAILABLE', '사용가능', 1, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_STATUS', 'IN_USE', '사용중', 2, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_STATUS', 'REPAIRING', '수리중', 3, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_STATUS', 'RETIRED', '폐기', 4, 'Y'),
(nextval('sq_common_codes'), 'EQUIPMENT_STATUS', 'LOST', '분실', 5, 'Y'),
(nextval('sq_common_codes'), 'MAINTENANCE_TYPE', 'REPAIR', '수리', 1, 'Y'),
(nextval('sq_common_codes'), 'MAINTENANCE_TYPE', 'UPGRADE', '업그레이드', 2, 'Y'),
(nextval('sq_common_codes'), 'MAINTENANCE_TYPE', 'INSPECTION', '점검', 3, 'Y'),
(nextval('sq_common_codes'), 'MAINTENANCE_TYPE', 'DISPOSAL', '폐기', 4, 'Y'),
(nextval('sq_common_codes'), 'REPORT_TYPE', 'DAILY', '일일보고', 1, 'Y'),
(nextval('sq_common_codes'), 'REPORT_TYPE', 'WEEKLY', '주간보고', 2, 'Y'),
(nextval('sq_common_codes'), 'REPORT_TYPE', 'MONTHLY', '월간보고', 3, 'Y'),
(nextval('sq_common_codes'), 'REPORT_TYPE', 'RETURN', '복귀보고', 4, 'Y'),
(nextval('sq_common_codes'), 'REPORT_STATUS', 'DRAFT', '임시저장', 1, 'Y'),
(nextval('sq_common_codes'), 'REPORT_STATUS', 'SUBMITTED', '제출', 2, 'Y'),
(nextval('sq_common_codes'), 'REPORT_STATUS', 'APPROVED', '승인', 3, 'Y'),
(nextval('sq_common_codes'), 'REPORT_STATUS', 'REJECTED', '반려', 4, 'Y'),
(nextval('sq_common_codes'), 'TRAINING_STATUS', 'NOT_STARTED', '수강전', 1, 'Y'),
(nextval('sq_common_codes'), 'TRAINING_STATUS', 'ONGOING', '수강중', 2, 'Y'),
(nextval('sq_common_codes'), 'TRAINING_STATUS', 'COMPLETED', '완료', 3, 'Y');
@@ -0,0 +1,11 @@
INSERT INTO tb_employee (id, login_id, password, name, email, role_code, emp_status, dispatch_status, joined_date)
SELECT nextval('sq_employees'), 'admin', '$2a$10$esMvhqy5..BznXdoGHNGiej3zIx8UV9x2x5NM6rJayIChMFV0sV76', 'Admin', 'admin@sr-system.com', 'ADMIN', 'ACTIVE', 'WAITING', CURRENT_DATE
WHERE NOT EXISTS (SELECT 1 FROM tb_employee WHERE login_id = 'admin');
INSERT INTO tb_employee (id, login_id, password, name, email, role_code, emp_status, dispatch_status, joined_date)
SELECT nextval('sq_employees'), 'manager', '$2a$10$yLm4w9OMemIrhMtPuNL5seoxWDZJ5R38yNB2yTOaQ0BhoLOgZehfm', 'Manager Kim', 'manager@sr-system.com', 'MANAGER', 'ACTIVE', 'WAITING', CURRENT_DATE
WHERE NOT EXISTS (SELECT 1 FROM tb_employee WHERE login_id = 'manager');
INSERT INTO tb_employee (id, login_id, password, name, email, role_code, emp_status, dispatch_status, joined_date)
SELECT nextval('sq_employees'), 'employee', '$2a$10$FNveJr.DdyTjtRl0eOYVfOvEEmAWSrip3tUdeo2PMsNznlLxmcCly', 'Employee Lee', 'employee@sr-system.com', 'EMPLOYEE', 'ACTIVE', 'WAITING', CURRENT_DATE
WHERE NOT EXISTS (SELECT 1 FROM tb_employee WHERE login_id = 'employee');
@@ -0,0 +1,160 @@
-- ============================================================
-- SR System - Complete Seed Data (clean insert)
-- V5 — self-contained, no BEGIN/COMMIT (Flyway handles TX)
-- ============================================================
-- Remove previous seed data (FK-safe order)
DELETE FROM tb_notification;
DELETE FROM tb_training_progress;
DELETE FROM tb_report;
DELETE FROM tb_equipment_maintenance;
DELETE FROM tb_equipment_assignment;
DELETE FROM tb_equipment;
DELETE FROM tb_ticket_comment;
DELETE FROM tb_ticket;
DELETE FROM tb_dispatch_history;
DELETE FROM tb_project;
DELETE FROM tb_employee WHERE login_id IN ('parkdispatch', 'kimdev', 'leespecialist', 'choiexpert');
-- Reset sequences (not sq_employees — V2 keeps IDs 1/51/101)
ALTER SEQUENCE sq_projects RESTART WITH 1;
ALTER SEQUENCE sq_dispatch_histories RESTART WITH 1;
ALTER SEQUENCE sq_tickets RESTART WITH 1;
ALTER SEQUENCE sq_ticket_comments RESTART WITH 1;
ALTER SEQUENCE sq_equipment RESTART WITH 1;
ALTER SEQUENCE sq_equipment_assignments RESTART WITH 1;
ALTER SEQUENCE sq_equipment_maintenance RESTART WITH 1;
ALTER SEQUENCE sq_reports RESTART WITH 1;
ALTER SEQUENCE sq_training_progress RESTART WITH 1;
ALTER SEQUENCE sq_notifications RESTART WITH 1;
-- Update employee(101) → DISPATCHED
UPDATE tb_employee SET dispatch_status = 'DISPATCHED', updated_at = NOW() WHERE login_id = 'employee' AND dispatch_status = 'WAITING';
-- ============================================================
-- 1. EMPLOYEES (4명, explicit IDs)
-- ============================================================
INSERT INTO tb_employee (id, login_id, password, name, email, role_code, emp_status, dispatch_status, joined_date) VALUES
(151, 'parkdispatch', '$2a$10$FNveJr.DdyTjtRl0eOYVfOvEEmAWSrip3tUdeo2PMsNznlLxmcCly', '박파견', 'park@dispatch.com', 'EMPLOYEE', 'ACTIVE', 'DISPATCHED', '2024-03-01'),
(201, 'kimdev', '$2a$10$FNveJr.DdyTjtRl0eOYVfOvEEmAWSrip3tUdeo2PMsNznlLxmcCly', '김개발', 'kim@dispatch.com', 'EMPLOYEE', 'ACTIVE', 'DISPATCHED', '2024-06-01'),
(251, 'leespecialist','$2a$10$FNveJr.DdyTjtRl0eOYVfOvEEmAWSrip3tUdeo2PMsNznlLxmcCly', '이전문', 'lee@sr-system.com', 'MANAGER', 'ACTIVE', 'WAITING', '2023-01-01'),
(301, 'choiexpert', '$2a$10$FNveJr.DdyTjtRl0eOYVfOvEEmAWSrip3tUdeo2PMsNznlLxmcCly', '최전문', 'choi@sr-system.com', 'MANAGER', 'ACTIVE', 'WAITING', '2022-07-01');
-- ============================================================
-- 2. PROJECTS (4개, nextval → 1, 51, 101, 151)
-- ============================================================
INSERT INTO tb_project (id, project_type, project_name, contract_company, end_user_company, contract_type, status, start_date, end_date, work_location_type, work_address, tech_environment, main_task_desc, internal_manager_id) VALUES
(nextval('sq_projects'), 'SI', '삼성페이 고도화 (SI)', '삼성전자', '삼성전자', 'TURN_KEY', 'ONGOING', '2025-01-01', '2026-12-31', 'ON_SITE', '서울시 서초구', 'Java 17, Spring Boot 3.x, Oracle 19c, Kubernetes', '삼성페이 차세대 시스템 구축', 1),
(nextval('sq_projects'), 'SM', 'LG CNS SM 운영', 'LG CNS', 'LG CNS', 'MM', 'ONGOING', '2024-01-01', '2026-06-30', 'HYBRID', '서울시 강남구', 'Java 11, Spring Framework, Oracle 11g, Jenkins', 'LG CNS 시스템 유지보수', 51),
(nextval('sq_projects'), 'SM', '카카오 서비스 운영', '카카오', '카카오', 'MM', 'ONGOING', '2024-06-01', '2025-12-31', 'REMOTE', '경기도 판교', 'Kotlin, Spring Cloud, MySQL, Kafka', '카카오 서비스 운영', 51),
(nextval('sq_projects'), 'SI', 'SK하이닉스 차세대', 'SK하이닉스','SK하이닉스','TURN_KEY','PREPARING', '2026-07-01', '2027-12-31', 'ON_SITE', '충청북도 청주시','Java 17, Spring Boot 3.x, PostgreSQL, React', 'SK하이닉스 MES 시스템 구축', 1);
-- ============================================================
-- 3. DISPATCH HISTORIES (3건, nextval → 1, 51, 101)
-- ============================================================
INSERT INTO tb_dispatch_history (id, employee_id, project_id, start_date, role_title, contribution_rate, individual_tech, performed_tasks, achievements, client_feedback, internal_rating) VALUES
(nextval('sq_dispatch_histories'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), (SELECT id FROM tb_project WHERE project_name LIKE '삼성페이%'), '2025-01-01', '프론트엔드 개발자', 80, 'React, TypeScript, Next.js, Tailwind CSS', '프론트엔드 아키텍처 설계 및 공통 컴포넌트 개발, 성능 최적화', '프론트엔드 로딩 속도 40% 개선, 공통 UI 라이브러리 구축', '협업 능력이 뛰어나고 기술적으로 신뢰할 수 있음', 85),
(nextval('sq_dispatch_histories'), (SELECT id FROM tb_employee WHERE login_id='kimdev'), (SELECT id FROM tb_project WHERE project_name LIKE '카카오%'), '2024-06-01', '백엔드 엔지니어', 60, 'Java, Kotlin, Spring Cloud, MySQL, Kafka', 'MSA 기반 백엔드 개발 및 배포, Kafka 이벤트 처리', '메시지 처리량 2배 향상, 장애 대응 시간 50% 단축', '적극적인 문제 해결 능력 보유', 78),
(nextval('sq_dispatch_histories'), (SELECT id FROM tb_employee WHERE login_id='employee'), (SELECT id FROM tb_project WHERE project_name LIKE 'LG CNS%'), '2024-01-01', '유지보수 엔지니어', 70, 'Java 11, Spring Framework, Oracle 11g, Jenkins', '장애 대응, 정기 패치, 성능 모니터링, 배치 자동화', '월간 장애 건수 30% 감소, 배포 자동화 구축', '꼼꼼하고 안정적인 운영 능력', 82);
-- ============================================================
-- 4. TICKETS (8건, nextval → 1, 51, 101, 151, 201, 251, 301, 351)
-- ============================================================
INSERT INTO tb_ticket (id, project_id, requester_id, assignee_id, category, priority, title, description, status, due_date) VALUES
(nextval('sq_tickets'), (SELECT id FROM tb_project WHERE project_name LIKE '삼성페이%'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), NULL, 'BUG', 'CRITICAL', 'JVM 메모리 릭 및 Heap Dump 분석 요청', 'Prod JVM 메모리 사용량 지속 증가, Full GC 빈도 높음', 'OPEN', '2026-05-25 18:00:00'),
(nextval('sq_tickets'), (SELECT id FROM tb_project WHERE project_name LIKE 'LG CNS%'), (SELECT id FROM tb_employee WHERE login_id='employee'), NULL, 'SUPPORT', 'HIGH', '사내망 방화벽 정책 가이드 필요', '파견지 사내망 연동 방화벽 정책 가이드 요청', 'OPEN', '2026-05-28 18:00:00');
INSERT INTO tb_ticket (id, project_id, requester_id, assignee_id, category, priority, title, description, status, due_date, sla_warn_flag)
VALUES (nextval('sq_tickets'), (SELECT id FROM tb_project WHERE project_name LIKE '삼성페이%'), (SELECT id FROM tb_employee WHERE login_id='kimdev'), (SELECT id FROM tb_employee WHERE login_id='leespecialist'), 'BUG', 'CRITICAL', 'CI/CD 파이프라인 staging 배포 실패', 'Staging 배포 시 Docker build 실패, 의존성 문제', 'ASSIGNED', '2026-05-24 18:00:00', 'Y');
INSERT INTO tb_ticket (id, project_id, requester_id, assignee_id, category, priority, title, description, status, due_date) VALUES
(nextval('sq_tickets'), (SELECT id FROM tb_project WHERE project_name LIKE '카카오%'), (SELECT id FROM tb_employee WHERE login_id='kimdev'), (SELECT id FROM tb_employee WHERE login_id='choiexpert'), 'SUPPORT', 'NORMAL', 'MacBook Pro 배터리 교체 요청', 'MacBook Pro 14 M1 배터리 성능 78%, 교체 주기 도래', 'IN_PROGRESS', '2026-06-05 18:00:00'),
(nextval('sq_tickets'), (SELECT id FROM tb_project WHERE project_name LIKE 'LG CNS%'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), (SELECT id FROM tb_employee WHERE login_id='leespecialist'), 'SUPPORT', 'HIGH', 'VPN 접속 연장 요청', '원격 접속 VPN 인증서 만료 예정', 'RESOLVED', '2026-05-20 18:00:00'),
(nextval('sq_tickets'), (SELECT id FROM tb_project WHERE project_name LIKE '삼성페이%'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), (SELECT id FROM tb_employee WHERE login_id='leespecialist'), 'BUG', 'HIGH', 'DB 커넥션 풀 고갈 문제 분석', '오전 10-12시 DB 커넥션 풀 고갈 현상', 'CLOSED', '2026-05-18 18:00:00'),
(nextval('sq_tickets'), (SELECT id FROM tb_project WHERE project_name LIKE '삼성페이%'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), NULL, 'QA', 'HIGH', '오라클 쿼리 튜닝 필요 (Full Scan)', '실행 계획 Full Scan 발생, 5000만건 테이블 인덱스 튜닝 필요', 'OPEN', '2026-06-01 18:00:00'),
(nextval('sq_tickets'), (SELECT id FROM tb_project WHERE project_name LIKE '카카오%'), (SELECT id FROM tb_employee WHERE login_id='kimdev'), NULL, 'FEATURE', 'NORMAL', 'API 응답 캐싱 도입 제안', '반복 API 응답 속도 개선을 위한 Redis 캐싱 도입', 'OPEN', '2026-06-10 18:00:00');
-- Add resolved/closed timestamps
UPDATE tb_ticket SET resolved_at = '2026-05-19 17:00:00', resolution_note = 'VPN 인증서 재발급 완료' WHERE id = (SELECT id FROM tb_ticket WHERE title LIKE 'VPN 접속%');
UPDATE tb_ticket SET resolved_at = '2026-05-17 12:00:00', resolution_note = 'Connection leak 수정 완료' WHERE id = (SELECT id FROM tb_ticket WHERE title LIKE 'DB 커넥션 풀%');
-- ============================================================
-- 5. TICKET COMMENTS (6건, nextval → 1, 51, 101, 151, 201, 251)
-- ============================================================
INSERT INTO tb_ticket_comment (id, ticket_id, user_id, comment_text, attached_file_url)
VALUES (nextval('sq_ticket_comments'), (SELECT id FROM tb_ticket WHERE title LIKE 'JVM 메모리 릭%'), (SELECT id FROM tb_employee WHERE login_id='leespecialist'), 'Heap Dump 분석 결과: G1OldGen 누수 패턴 확인됨', '/uploads/heap-dump-analysis-20260520.pdf');
INSERT INTO tb_ticket_comment (id, ticket_id, user_id, comment_text)
VALUES (nextval('sq_ticket_comments'), (SELECT id FROM tb_ticket WHERE title LIKE 'JVM 메모리 릭%'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), 'Reference Chain 추적 중, 곧 수정안 올리겠습니다.');
INSERT INTO tb_ticket_comment (id, ticket_id, user_id, comment_text)
VALUES (nextval('sq_ticket_comments'), (SELECT id FROM tb_ticket WHERE title LIKE 'CI/CD%'), (SELECT id FROM tb_employee WHERE login_id='leespecialist'), 'Dockerfile base image 태그가 latest로 지정됨. 특정 버전으로 고정 필요.');
INSERT INTO tb_ticket_comment (id, ticket_id, user_id, comment_text)
VALUES (nextval('sq_ticket_comments'), (SELECT id FROM tb_ticket WHERE title LIKE 'CI/CD%'), (SELECT id FROM tb_employee WHERE login_id='kimdev'), '17-jdk-slim으로 변경 후 재빌드하겠습니다.');
INSERT INTO tb_ticket_comment (id, ticket_id, user_id, comment_text)
VALUES (nextval('sq_ticket_comments'), (SELECT id FROM tb_ticket WHERE title LIKE 'MacBook Pro 배터리%'), (SELECT id FROM tb_employee WHERE login_id='choiexpert'), '배터리 재고 확인 후 회신드리겠습니다.');
INSERT INTO tb_ticket_comment (id, ticket_id, user_id, comment_text, attached_file_url)
VALUES (nextval('sq_ticket_comments'), (SELECT id FROM tb_ticket WHERE title LIKE '오라클 쿼리 튜닝%'), (SELECT id FROM tb_employee WHERE login_id='leespecialist'), '결합 인덱스 생성으로 튜닝 가능. 스크립트 첨부.', '/uploads/tuning_script_20260521.sql');
-- ============================================================
-- 6. EQUIPMENT (8건, nextval → 1, 51, 101, 151, 201, 251, 301, 351)
-- ============================================================
INSERT INTO tb_equipment (id, equipment_type, manufacturer, model_name, serial_number, asset_code, specifications, status, purchase_date, warranty_exp_date, version) VALUES
(nextval('sq_equipment'), 'LAPTOP', 'Apple', 'MacBook Pro 16 M3', 'F2G8H3J9K1', 'HQ-LP-2026-0001', '{"cpu":"M3 Pro","ram":"36GB","ssd":"512GB"}', 'IN_USE', '2026-01-15', '2028-01-15', 0),
(nextval('sq_equipment'), 'LAPTOP', 'Apple', 'MacBook Pro 14 M3', 'A1B2C3D4E5', 'HQ-LP-2026-0002', '{"cpu":"M3","ram":"18GB","ssd":"512GB"}', 'AVAILABLE', '2026-02-01', '2028-02-01', 0),
(nextval('sq_equipment'), 'MONITOR', 'LG', '27UN880 Ergo', 'LG-27U-001', 'HQ-MO-2026-0001', '{"size":"27\"","resolution":"4K UHD","panel":"IPS"}', 'IN_USE', '2026-01-20', '2028-01-20', 0),
(nextval('sq_equipment'), 'LAPTOP', 'Samsung', 'Galaxy Book4 Pro', 'SAMSUNG-001', 'HQ-LP-2026-0003', '{"cpu":"Ultra 7","ram":"16GB","ssd":"256GB"}', 'REPAIRING', '2026-03-01', '2028-03-01', 0),
(nextval('sq_equipment'), 'MONITOR', 'Dell', 'U2723QE', 'DELL-U27-002', 'HQ-MO-2026-0002', '{"size":"27\"","resolution":"4K","panel":"IPS Black"}', 'AVAILABLE', '2026-04-01', '2028-04-01', 0),
(nextval('sq_equipment'), 'ACCESSORY', 'Logitech', 'MX Master 3S', 'LOG-MX-001', 'HQ-AC-2026-0001', '{"type":"Mouse","connection":"Bluetooth"}', 'IN_USE', '2026-01-10', '2027-01-10', 0),
(nextval('sq_equipment'), 'TEST_DEVICE', 'Samsung', 'Galaxy S24 Ultra', 'SAMSUNG-PH-001','HQ-TD-2026-0001', '{"storage":"512GB","color":"Titanium Gray"}', 'AVAILABLE', '2026-02-15', '2027-02-15', 0),
(nextval('sq_equipment'), 'ACCESSORY', 'Apple', 'Magic Keyboard (Kor)', 'APPLE-KB-001', 'HQ-AC-2026-0002', '{"type":"Keyboard","layout":"Korean","connection":"Bluetooth"}','IN_USE', '2026-01-10', '2028-01-10', 0);
-- ============================================================
-- 7. EQUIPMENT ASSIGNMENTS (3건, nextval → 1, 51, 101)
-- ============================================================
INSERT INTO tb_equipment_assignment (id, equipment_id, user_id, assigned_date, cond_on_assign) VALUES
(nextval('sq_equipment_assignments'), (SELECT id FROM tb_equipment WHERE asset_code='HQ-LP-2026-0001'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), '2026-01-20 09:00:00', '초기 지급: 케이스/충전기 포함, 외관 이상 없음'),
(nextval('sq_equipment_assignments'), (SELECT id FROM tb_equipment WHERE asset_code='HQ-MO-2026-0001'), (SELECT id FROM tb_employee WHERE login_id='employee'), '2026-02-01 10:00:00', '모니터 암 포함, 불량 화소 없음'),
(nextval('sq_equipment_assignments'), (SELECT id FROM tb_equipment WHERE asset_code='HQ-AC-2026-0001'), (SELECT id FROM tb_employee WHERE login_id='kimdev'), '2026-01-15 14:00:00', '수신기 포함');
-- ============================================================
-- 8. EQUIPMENT MAINTENANCE (2건, nextval → 1, 51)
-- ============================================================
INSERT INTO tb_equipment_maintenance (id, equipment_id, reported_by, maintenance_type, issue_description, action_taken, cost, reported_date, resolved_date) VALUES
(nextval('sq_equipment_maintenance'), (SELECT id FROM tb_equipment WHERE asset_code='HQ-LP-2026-0003'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), 'REPAIR', '액정 파손, 터치패널 일부 미작동', '액정 교체 및 전체 기능 테스트 완료', 450000.00, '2026-04-10 09:00:00', '2026-04-15 18:00:00'),
(nextval('sq_equipment_maintenance'), (SELECT id FROM tb_equipment WHERE asset_code='HQ-LP-2026-0001'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), 'UPGRADE', 'SSD 512GB→1TB 업그레이드 요청', 'Samsung 990 Pro 1TB 교체, 데이터 마이그레이션 완료', 180000.00, '2026-03-20 10:00:00', '2026-03-21 16:00:00');
-- ============================================================
-- 9. REPORTS (5건, nextval → 1, 51, 101, 151, 201)
-- ============================================================
INSERT INTO tb_report (id, dispatch_id, user_id, report_type, target_date, completed_tasks, planned_tasks, issues_and_risks, support_requested, status) VALUES
(nextval('sq_reports'), (SELECT id FROM tb_dispatch_history WHERE employee_id=(SELECT id FROM tb_employee WHERE login_id='employee') LIMIT 1), (SELECT id FROM tb_employee WHERE login_id='employee'), 'WEEKLY', '2026-05-11', '정기 패치 적용 완료\n배치 오류 수정 3건\n보안 취약점 점검', 'DB 정기 점검\n월간 리포팅\n매뉴얼 업데이트', 'DB 디스크 사용률 85%, 증설 검토', '디스크 증설 요청', 'DRAFT'),
(nextval('sq_reports'), (SELECT id FROM tb_dispatch_history WHERE employee_id=(SELECT id FROM tb_employee WHERE login_id='employee') LIMIT 1), (SELECT id FROM tb_employee WHERE login_id='employee'), 'WEEKLY', '2026-05-18', 'DB 정기 점검 완료\n보안 패치 CVE-2026-1234 적용\n장애 대응 매뉴얼 v2.1', '성능 테스트 준비\n배치 자동화 고도화\n문서 정리', '없음', '없음', 'SUBMITTED'),
(nextval('sq_reports'), (SELECT id FROM tb_dispatch_history WHERE employee_id=(SELECT id FROM tb_employee WHERE login_id='employee') LIMIT 1), (SELECT id FROM tb_employee WHERE login_id='employee'), 'WEEKLY', '2026-05-04', '긴급 패치 2건\n모니터링 대시보드 고도화\n배치 자동화 테스트', '배치 자동화 본배포\n정기 보고서', '긴급 패치로 일정 지연', '없음', 'APPROVED'),
(nextval('sq_reports'), (SELECT id FROM tb_dispatch_history WHERE employee_id=(SELECT id FROM tb_employee WHERE login_id='parkdispatch') LIMIT 1), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), 'WEEKLY', '2026-05-18', '공통 컴포넌트 리팩토링\nLCP 2.5s→1.2s 최적화\nStorybook 문서화', '신규 페이지 5건\nE2E 테스트\n코드 리뷰', '디자인팀 일정 조율', '없음', 'SUBMITTED'),
(nextval('sq_reports'), (SELECT id FROM tb_dispatch_history WHERE employee_id=(SELECT id FROM tb_employee WHERE login_id='kimdev') LIMIT 1), (SELECT id FROM tb_employee WHERE login_id='kimdev'), 'WEEKLY', '2026-05-18', 'Kafka Lag 모니터링 개선\nAPI Gateway 인증 업데이트\nCI/CD 파이프라인 개선', '부하 테스트\nKafka 업그레이드 준비', 'Kafka 3.5→3.7 호환성', '업그레이드 가이드 요청', 'SUBMITTED');
-- ============================================================
-- 10. TRAINING PROGRESS (6건, nextval → 1, 51, 101, 151, 201, 251)
-- ============================================================
INSERT INTO tb_training_progress (id, user_id, course_name, progress_rate, status) VALUES
(nextval('sq_training_progress'), (SELECT id FROM tb_employee WHERE login_id='employee'), 'Spring Boot 심화', 100, 'COMPLETED'),
(nextval('sq_training_progress'), (SELECT id FROM tb_employee WHERE login_id='employee'), 'Kubernetes 실무', 65, 'ONGOING'),
(nextval('sq_training_progress'), (SELECT id FROM tb_employee WHERE login_id='employee'), 'Docker & 컨테이너', 100, 'COMPLETED'),
(nextval('sq_training_progress'), (SELECT id FROM tb_employee WHERE login_id='employee'), 'DevOps 파이프라인', 0, 'NOT_STARTED'),
(nextval('sq_training_progress'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), 'Spring Boot 심화', 45, 'ONGOING'),
(nextval('sq_training_progress'), (SELECT id FROM tb_employee WHERE login_id='kimdev'), 'Apache Kafka 심화', 80, 'ONGOING');
-- ============================================================
-- 11. NOTIFICATIONS (6건, nextval → 1, 51, 101, 151, 201, 251)
-- ============================================================
INSERT INTO tb_notification (id, user_id, type, title, message, is_read) VALUES
(nextval('sq_notifications'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), 'TICKET_ASSIGNED', 'SR 티켓 배정', 'CI/CD 배포 실패 건이 이전문 님께 배정됨', 'N'),
(nextval('sq_notifications'), (SELECT id FROM tb_employee WHERE login_id='leespecialist'), 'TICKET_ASSIGNED', 'SR 티켓 배정', 'CI/CD 배포 실패 건 담당자 지정됨', 'Y'),
(nextval('sq_notifications'), 51, 'REPORT_SUBMITTED', '보고서 제출', 'Employee Lee 님 주간 보고서 제출', 'N'),
(nextval('sq_notifications'), (SELECT id FROM tb_employee WHERE login_id='employee'), 'REPORT_APPROVED', '보고서 승인', '5/4 주간 보고서 승인됨', 'Y'),
(nextval('sq_notifications'), (SELECT id FROM tb_employee WHERE login_id='parkdispatch'), 'EQUIPMENT_MAINTENANCE','장비 수리 완료', 'Galaxy Book4 Pro 액정 수리 완료', 'N'),
(nextval('sq_notifications'), 1, 'SLA_WARNING', 'SLA 임박', 'CI/CD 배포 실패 건 처리 기한 24시간 이내', 'N');
@@ -0,0 +1,5 @@
-- ============================================================
-- V6: Add multi-image support to equipment (JSONB array)
-- ============================================================
ALTER TABLE tb_equipment ADD COLUMN IF NOT EXISTS images JSONB DEFAULT '[]'::jsonb;
@@ -0,0 +1,29 @@
-- V7__add_report_enhancements.sql
-- 업무 보고 고도화: 근무 시간, blocker 플래그, 산출물, 주간 계획 연동
ALTER TABLE tb_report
ADD COLUMN IF NOT EXISTS work_hours NUMERIC(5,2),
ADD COLUMN IF NOT EXISTS blocker_flag CHAR(1) DEFAULT 'N' NOT NULL,
ADD COLUMN IF NOT EXISTS artifacts JSONB,
ADD COLUMN IF NOT EXISTS weekly_plan_id BIGINT;
-- 주간 계획 테이블
CREATE TABLE IF NOT EXISTS tb_weekly_plan (
id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
week_start DATE NOT NULL,
status VARCHAR(20) NOT NULL,
tasks JSONB,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) DEFAULT 'N' NOT NULL,
CONSTRAINT pk_weekly_plan PRIMARY KEY (id),
CONSTRAINT fk_weekly_plan_user FOREIGN KEY (user_id) REFERENCES tb_employee (id)
);
CREATE SEQUENCE IF NOT EXISTS sq_weekly_plans START WITH 1 INCREMENT BY 50;
-- 인덱스 추가
CREATE INDEX IF NOT EXISTS idx_weekly_plan_user ON tb_weekly_plan (user_id);
CREATE INDEX IF NOT EXISTS idx_weekly_plan_week_start ON tb_weekly_plan (week_start);
CREATE INDEX IF NOT EXISTS idx_report_weekly_plan ON tb_report (weekly_plan_id);
@@ -0,0 +1,23 @@
-- V8__add_daily_task_progress.sql
-- 일일 태스크 진도 관리 테이블
CREATE TABLE IF NOT EXISTS tb_daily_task_progress (
id BIGINT NOT NULL,
report_id BIGINT NOT NULL,
weekly_plan_id BIGINT NOT NULL,
task_name VARCHAR(500) NOT NULL,
progress_rate INTEGER NOT NULL,
work_hours NUMERIC(5,2) NOT NULL,
created_at TIMESTAMP NOT NULL DEFAULT NOW(),
updated_at TIMESTAMP NOT NULL DEFAULT NOW(),
is_deleted CHAR(1) DEFAULT 'N' NOT NULL,
CONSTRAINT pk_daily_task_progress PRIMARY KEY (id),
CONSTRAINT fk_daily_task_progress_report FOREIGN KEY (report_id) REFERENCES tb_report (id),
CONSTRAINT fk_daily_task_progress_weekly_plan FOREIGN KEY (weekly_plan_id) REFERENCES tb_weekly_plan (id)
);
CREATE SEQUENCE IF NOT EXISTS sq_daily_task_progress START WITH 1 INCREMENT BY 50;
-- 인덱스 추가
CREATE INDEX IF NOT EXISTS idx_daily_task_progress_report ON tb_daily_task_progress (report_id);
CREATE INDEX IF NOT EXISTS idx_daily_task_progress_weekly_plan ON tb_daily_task_progress (weekly_plan_id);
@@ -0,0 +1 @@
ALTER TABLE tb_notification ADD COLUMN link_url VARCHAR(500);