feat: 구매/안전 시스템 전면 개편 — tkpurchase 개편 + tksafety 신규 + 권한 보강

Phase 1: tkuser 협력업체 CRUD 이관 (읽기전용 → 전체 CRUD)
Phase 2: tkpurchase 개편 — 일용공 신청/확정, 작업일정, 업무현황, 계정관리, 협력업체 포털
Phase 3: tksafety 신규 시스템 — 방문관리 + 안전교육 신고
Phase 4: SSO 인증 보강 (partner_company_id JWT, 만료일 체크), 권한 테이블 기반 접근 제어

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Hyungi Ahn
2026-03-12 17:42:59 +09:00
parent a195dd1d50
commit b800792152
63 changed files with 5548 additions and 262 deletions

View File

@@ -0,0 +1,146 @@
-- migration-purchase-safety.sql
-- 협력업체/일용직 관리 및 안전교육 테이블 마이그레이션
-- MariaDB용, 재실행 안전 (IF NOT EXISTS / ADD COLUMN IF NOT EXISTS)
-- 생성일: 2026-03-12
-- ============================================================
-- 1. sso_users 테이블에 협력업체 관련 컬럼 추가
-- ============================================================
ALTER TABLE sso_users
ADD COLUMN IF NOT EXISTS partner_company_id INT DEFAULT NULL
COMMENT '협력업체 소속 시 partner_companies.id, 내부직원은 NULL';
ALTER TABLE sso_users
ADD COLUMN IF NOT EXISTS account_expires_at DATETIME DEFAULT NULL
COMMENT '협력업체 계정 만료일, 내부직원은 NULL';
-- 외래키는 IF NOT EXISTS 구문이 없으므로 프로시저로 안전하게 추가
DELIMITER //
DROP PROCEDURE IF EXISTS __add_fk_sso_users_partner_company//
CREATE PROCEDURE __add_fk_sso_users_partner_company()
BEGIN
IF NOT EXISTS (
SELECT 1 FROM information_schema.TABLE_CONSTRAINTS
WHERE CONSTRAINT_SCHEMA = DATABASE()
AND TABLE_NAME = 'sso_users'
AND CONSTRAINT_NAME = 'fk_sso_users_partner_company'
) THEN
ALTER TABLE sso_users
ADD CONSTRAINT fk_sso_users_partner_company
FOREIGN KEY (partner_company_id) REFERENCES partner_companies(id)
ON DELETE SET NULL;
END IF;
END//
DELIMITER ;
CALL __add_fk_sso_users_partner_company();
DROP PROCEDURE IF EXISTS __add_fk_sso_users_partner_company;
-- ============================================================
-- 2. day_labor_requests (일용직 작업 요청)
-- ============================================================
CREATE TABLE IF NOT EXISTS day_labor_requests (
id INT AUTO_INCREMENT PRIMARY KEY,
requester_id INT NOT NULL COMMENT 'sso_users.user_id',
department_id INT,
work_date DATE NOT NULL,
worker_count INT NOT NULL DEFAULT 1,
work_description TEXT,
workplace_name VARCHAR(100),
status ENUM('pending','approved','rejected','completed') DEFAULT 'pending',
approved_by INT,
approved_at DATETIME,
safety_reported BOOLEAN DEFAULT FALSE,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_day_labor_work_date (work_date),
INDEX idx_day_labor_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================
-- 3. partner_schedules (협력업체 작업 일정)
-- ============================================================
CREATE TABLE IF NOT EXISTS partner_schedules (
id INT AUTO_INCREMENT PRIMARY KEY,
company_id INT NOT NULL,
work_date DATE NOT NULL,
work_description TEXT,
workplace_name VARCHAR(100),
expected_workers INT DEFAULT 1,
registered_by INT NOT NULL,
status ENUM('scheduled','in_progress','completed','cancelled') DEFAULT 'scheduled',
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_partner_sched_work_date (work_date),
INDEX idx_partner_sched_company_date (company_id, work_date),
CONSTRAINT fk_partner_schedules_company
FOREIGN KEY (company_id) REFERENCES partner_companies(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================
-- 4. partner_work_checkins (협력업체 출퇴근 체크)
-- ============================================================
CREATE TABLE IF NOT EXISTS partner_work_checkins (
id INT AUTO_INCREMENT PRIMARY KEY,
schedule_id INT NOT NULL,
company_id INT NOT NULL,
checked_by INT NOT NULL,
check_in_time DATETIME,
check_out_time DATETIME,
worker_names TEXT,
actual_worker_count INT,
notes TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_checkin_schedule_time (schedule_id, check_in_time),
CONSTRAINT fk_checkins_schedule
FOREIGN KEY (schedule_id) REFERENCES partner_schedules(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================
-- 5. daily_work_reports (일일 작업 보고)
-- ============================================================
CREATE TABLE IF NOT EXISTS daily_work_reports (
id INT AUTO_INCREMENT PRIMARY KEY,
schedule_id INT NOT NULL,
checkin_id INT NOT NULL,
company_id INT NOT NULL,
report_date DATE NOT NULL,
reporter_id INT NOT NULL,
actual_workers INT,
work_content TEXT,
progress_rate TINYINT CHECK (progress_rate BETWEEN 0 AND 100),
issues TEXT,
next_plan TEXT,
confirmed_by INT,
confirmed_at DATETIME,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_daily_report_date (report_date),
INDEX idx_daily_report_schedule (schedule_id),
CONSTRAINT fk_daily_reports_schedule
FOREIGN KEY (schedule_id) REFERENCES partner_schedules(id),
CONSTRAINT fk_daily_reports_checkin
FOREIGN KEY (checkin_id) REFERENCES partner_work_checkins(id),
CONSTRAINT fk_daily_reports_company
FOREIGN KEY (company_id) REFERENCES partner_companies(id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ============================================================
-- 6. safety_education_reports (안전교육 보고)
-- ============================================================
CREATE TABLE IF NOT EXISTS safety_education_reports (
id INT AUTO_INCREMENT PRIMARY KEY,
target_type ENUM('day_labor','partner_schedule','manual') NOT NULL,
target_id INT,
education_date DATE NOT NULL,
educator VARCHAR(50),
attendees JSON,
status ENUM('planned','completed','cancelled') DEFAULT 'planned',
notes TEXT,
registered_by INT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_safety_edu_date (education_date),
INDEX idx_safety_edu_target (target_type, target_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;