TK-FB(공장관리+신고)와 M-Project(부적합관리)를 3개 독립 시스템으로 분리하기 위한 전체 코드 구조 작성. - SSO 인증 서비스 (bcrypt + pbkdf2 이중 해시 지원) - System 1: 공장관리 (TK-FB 기반, 신고 코드 제거) - System 2: 신고 (TK-FB에서 workIssue 코드 추출) - System 3: 부적합관리 (M-Project 기반) - Gateway 포털 (path-based 라우팅) - 통합 docker-compose.yml 및 배포 스크립트 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
224 lines
11 KiB
PL/PgSQL
224 lines
11 KiB
PL/PgSQL
-- 016_add_management_fields.sql
|
||
-- 관리함에서 사용할 추가 필드들과 완료 사진 업로드 기능 추가
|
||
|
||
BEGIN;
|
||
|
||
DO $$
|
||
DECLARE
|
||
migration_name VARCHAR(255) := '016_add_management_fields.sql';
|
||
migration_notes TEXT := '관리함 필드 추가: 원인/해결방안, 담당부서/담당자, 조치예상일, 완료확인일, 원인부서, 의견, 완료사진, 프로젝트별 No 등';
|
||
current_status VARCHAR(50);
|
||
BEGIN
|
||
-- migration_log 테이블이 없으면 생성 (멱등성)
|
||
CREATE TABLE IF NOT EXISTS migration_log (
|
||
id SERIAL PRIMARY KEY,
|
||
migration_file VARCHAR(255) NOT NULL UNIQUE,
|
||
executed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(),
|
||
status VARCHAR(50),
|
||
notes TEXT,
|
||
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
|
||
);
|
||
|
||
SELECT status INTO current_status FROM migration_log WHERE migration_file = migration_name;
|
||
|
||
IF current_status IS NULL THEN
|
||
RAISE NOTICE '--- 마이그레이션 % 시작 ---', migration_name;
|
||
|
||
-- issues 테이블에 관리함 관련 컬럼들 추가
|
||
|
||
-- 완료 사진 경로
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'completion_photo_path') THEN
|
||
ALTER TABLE issues ADD COLUMN completion_photo_path VARCHAR(255);
|
||
RAISE NOTICE '✅ issues.completion_photo_path 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.completion_photo_path 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 해결방안 (관리함에서 입력)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'solution') THEN
|
||
ALTER TABLE issues ADD COLUMN solution TEXT;
|
||
RAISE NOTICE '✅ issues.solution 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.solution 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 담당부서 (관리함에서 선택)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'responsible_department') THEN
|
||
ALTER TABLE issues ADD COLUMN responsible_department department_type;
|
||
RAISE NOTICE '✅ issues.responsible_department 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.responsible_department 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 담당자 (관리함에서 입력)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'responsible_person') THEN
|
||
ALTER TABLE issues ADD COLUMN responsible_person VARCHAR(100);
|
||
RAISE NOTICE '✅ issues.responsible_person 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.responsible_person 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 조치 예상일 (관리함에서 입력)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'expected_completion_date') THEN
|
||
ALTER TABLE issues ADD COLUMN expected_completion_date DATE;
|
||
RAISE NOTICE '✅ issues.expected_completion_date 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.expected_completion_date 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 완료 확인일 (완료 상태로 변경 시 자동 입력)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'actual_completion_date') THEN
|
||
ALTER TABLE issues ADD COLUMN actual_completion_date DATE;
|
||
RAISE NOTICE '✅ issues.actual_completion_date 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.actual_completion_date 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 원인부서 (관리함에서 입력)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'cause_department') THEN
|
||
ALTER TABLE issues ADD COLUMN cause_department department_type;
|
||
RAISE NOTICE '✅ issues.cause_department 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.cause_department 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- ISSUE에 대한 의견 (관리함에서 입력)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'management_comment') THEN
|
||
ALTER TABLE issues ADD COLUMN management_comment TEXT;
|
||
RAISE NOTICE '✅ issues.management_comment 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.management_comment 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 프로젝트별 순번 (No) - 프로젝트 내에서 1, 2, 3... 순으로 증가
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'project_sequence_no') THEN
|
||
ALTER TABLE issues ADD COLUMN project_sequence_no INTEGER;
|
||
RAISE NOTICE '✅ issues.project_sequence_no 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.project_sequence_no 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 최종 내용 (수정된 내용이 있으면 수정본, 없으면 원본)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'final_description') THEN
|
||
ALTER TABLE issues ADD COLUMN final_description TEXT;
|
||
RAISE NOTICE '✅ issues.final_description 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.final_description 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 최종 카테고리 (수정된 카테고리가 있으면 수정본, 없으면 원본)
|
||
IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name = 'issues' AND column_name = 'final_category') THEN
|
||
ALTER TABLE issues ADD COLUMN final_category issuecategory;
|
||
RAISE NOTICE '✅ issues.final_category 컬럼이 추가되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ issues.final_category 컬럼이 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 인덱스 추가
|
||
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'issues' AND indexname = 'idx_issues_project_sequence') THEN
|
||
CREATE INDEX idx_issues_project_sequence ON issues (project_id, project_sequence_no);
|
||
RAISE NOTICE '✅ idx_issues_project_sequence 인덱스가 생성되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ idx_issues_project_sequence 인덱스가 이미 존재합니다.';
|
||
END IF;
|
||
|
||
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'issues' AND indexname = 'idx_issues_responsible_department') THEN
|
||
CREATE INDEX idx_issues_responsible_department ON issues (responsible_department) WHERE responsible_department IS NOT NULL;
|
||
RAISE NOTICE '✅ idx_issues_responsible_department 인덱스가 생성되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ idx_issues_responsible_department 인덱스가 이미 존재합니다.';
|
||
END IF;
|
||
|
||
IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE tablename = 'issues' AND indexname = 'idx_issues_expected_completion') THEN
|
||
CREATE INDEX idx_issues_expected_completion ON issues (expected_completion_date) WHERE expected_completion_date IS NOT NULL;
|
||
RAISE NOTICE '✅ idx_issues_expected_completion 인덱스가 생성되었습니다.';
|
||
ELSE
|
||
RAISE NOTICE 'ℹ️ idx_issues_expected_completion 인덱스가 이미 존재합니다.';
|
||
END IF;
|
||
|
||
-- 프로젝트별 순번 자동 생성 함수
|
||
CREATE OR REPLACE FUNCTION generate_project_sequence_no(p_project_id BIGINT) RETURNS INTEGER AS $func$
|
||
DECLARE
|
||
next_no INTEGER;
|
||
BEGIN
|
||
-- 해당 프로젝트의 최대 순번 + 1
|
||
SELECT COALESCE(MAX(project_sequence_no), 0) + 1
|
||
INTO next_no
|
||
FROM issues
|
||
WHERE project_id = p_project_id;
|
||
|
||
RETURN next_no;
|
||
END;
|
||
$func$ LANGUAGE plpgsql;
|
||
RAISE NOTICE '✅ generate_project_sequence_no 함수가 생성되었습니다.';
|
||
|
||
-- 기존 이슈들에 대해 프로젝트별 순번 설정
|
||
DO $update_sequence$
|
||
DECLARE
|
||
issue_record RECORD;
|
||
seq_no INTEGER;
|
||
BEGIN
|
||
FOR issue_record IN
|
||
SELECT id, project_id
|
||
FROM issues
|
||
WHERE project_sequence_no IS NULL
|
||
ORDER BY project_id, report_date
|
||
LOOP
|
||
SELECT generate_project_sequence_no(issue_record.project_id) INTO seq_no;
|
||
UPDATE issues
|
||
SET project_sequence_no = seq_no
|
||
WHERE id = issue_record.id;
|
||
END LOOP;
|
||
END $update_sequence$;
|
||
RAISE NOTICE '✅ 기존 이슈들의 프로젝트별 순번이 설정되었습니다.';
|
||
|
||
-- 기존 이슈들의 final_description과 final_category 초기화
|
||
UPDATE issues
|
||
SET
|
||
final_description = description,
|
||
final_category = category
|
||
WHERE final_description IS NULL OR final_category IS NULL;
|
||
RAISE NOTICE '✅ 기존 이슈들의 final_description과 final_category가 초기화되었습니다.';
|
||
|
||
-- 마이그레이션 검증
|
||
DECLARE
|
||
col_count INTEGER;
|
||
idx_count INTEGER;
|
||
func_count INTEGER;
|
||
BEGIN
|
||
SELECT COUNT(*) INTO col_count FROM information_schema.columns
|
||
WHERE table_name = 'issues' AND column_name IN (
|
||
'completion_photo_path', 'solution', 'responsible_department', 'responsible_person',
|
||
'expected_completion_date', 'actual_completion_date', 'cause_department',
|
||
'management_comment', 'project_sequence_no', 'final_description', 'final_category'
|
||
);
|
||
|
||
SELECT COUNT(*) INTO idx_count FROM pg_indexes
|
||
WHERE tablename = 'issues' AND indexname IN (
|
||
'idx_issues_project_sequence', 'idx_issues_responsible_department', 'idx_issues_expected_completion'
|
||
);
|
||
|
||
SELECT COUNT(*) INTO func_count FROM pg_proc WHERE proname = 'generate_project_sequence_no';
|
||
|
||
RAISE NOTICE '=== 마이그레이션 검증 결과 ===';
|
||
RAISE NOTICE '추가된 컬럼: %/11개', col_count;
|
||
RAISE NOTICE '생성된 인덱스: %/3개', idx_count;
|
||
RAISE NOTICE '생성된 함수: %/1개', func_count;
|
||
|
||
IF col_count = 11 AND idx_count = 3 AND func_count = 1 THEN
|
||
RAISE NOTICE '✅ 마이그레이션이 성공적으로 완료되었습니다!';
|
||
INSERT INTO migration_log (migration_file, status, notes) VALUES (migration_name, 'SUCCESS', migration_notes);
|
||
ELSE
|
||
RAISE EXCEPTION '❌ 마이그레이션 검증 실패!';
|
||
END IF;
|
||
END;
|
||
|
||
ELSIF current_status = 'SUCCESS' THEN
|
||
RAISE NOTICE 'ℹ️ 마이그레이션 %는 이미 성공적으로 실행되었습니다. 스킵합니다.', migration_name;
|
||
ELSE
|
||
RAISE NOTICE '⚠️ 마이그레이션 %는 이전에 실패했습니다. 수동 확인이 필요합니다.', migration_name;
|
||
END IF;
|
||
END $$;
|
||
|
||
COMMIT;
|