convert to gitea

This commit is contained in:
2025-09-15 13:33:34 +09:00
commit 95882ac072
277 changed files with 46023 additions and 0 deletions

View File

@ -0,0 +1,59 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_add_category`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_category_name VARCHAR(40),
OUT p_new_category_id TINYINT UNSIGNED,
OUT p_result_message VARCHAR(255)
)
COMMENT '카테고리 추가 및 로그 기록 (ID 자동 할당)'
BEGIN
DECLARE v_existing_cat_id TINYINT UNSIGNED DEFAULT NULL;
DECLARE v_next_id TINYINT UNSIGNED;
DECLARE v_max_id TINYINT UNSIGNED;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK; SET p_new_category_id = NULL; SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_new_category_id = NULL; SET p_result_message = '작업 주체 정보는 필수입니다.';
ELSEIF p_category_name IS NULL OR p_category_name = '' THEN
SET p_new_category_id = NULL; SET p_result_message = '카테고리 이름은 필수입니다.';
ELSE
-- 카테고리 이름 중복 검사
SELECT category_id INTO v_existing_cat_id FROM resource_category WHERE LOWER(category_name) = LOWER(p_category_name) LIMIT 1;
IF v_existing_cat_id IS NOT NULL THEN
SET p_new_category_id = NULL; SET p_result_message = CONCAT('이미 사용 중인 카테고리 이름입니다: ', p_category_name);
ELSE
-- 다음 ID 할당
SELECT IFNULL(MAX(category_id), 0) INTO v_max_id FROM resource_category;
SET v_next_id = v_max_id + 1;
IF v_next_id > 255 THEN
SET p_new_category_id = NULL; SET p_result_message = '더 이상 카테고리 ID를 할당할 수 없습니다 (최대 255).';
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
INSERT INTO resource_category (category_id, category_name) VALUES (v_next_id, p_category_name);
SET p_new_category_id = v_next_id;
INSERT INTO log_add_category (log_date, admin_user_id, actor_description, category_id, category_name)
VALUES (v_now, p_admin_user_id, p_actor_description, p_new_category_id, p_category_name);
COMMIT;
SET p_result_message = CONCAT('카테고리 "', p_category_name, '" (ID: ', p_new_category_id, ') 추가 완료.');
END IF; -- ID 범위 IF 종료
END IF; -- 이름 중복 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,53 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_add_group`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_group_name VARCHAR(100),
IN p_manager_user_id BIGINT, -- 파라미터명 변경됨
OUT p_new_group_id BIGINT,
OUT p_result_message VARCHAR(255)
)
COMMENT '그룹(부서) 추가 및 로그 기록'
BEGIN
DECLARE v_existing_group_id BIGINT DEFAULT NULL;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK; SET p_new_group_id = NULL; SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_new_group_id = NULL; SET p_result_message = '작업 주체 정보는 필수입니다.';
ELSEIF p_group_name IS NULL OR p_group_name = '' THEN
SET p_new_group_id = NULL; SET p_result_message = '그룹(부서) 이름은 필수입니다.';
ELSE
-- 그룹 이름 중복 검사
SELECT group_id INTO v_existing_group_id FROM group_info WHERE LOWER(group_name) = LOWER(p_group_name) LIMIT 1;
IF v_existing_group_id IS NOT NULL THEN
SET p_new_group_id = NULL; SET p_result_message = CONCAT('이미 사용 중인 그룹(부서) 이름입니다: ', p_group_name);
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
INSERT INTO group_info (group_name, manager_user_id) -- 컬럼명 변경됨
VALUES (p_group_name, p_manager_user_id); -- 파라미터명 변경됨
SET p_new_group_id = LAST_INSERT_ID();
INSERT INTO log_add_group (log_date, admin_user_id, actor_description, group_id, group_name, manager_user_id) -- 컬럼명 변경됨
VALUES (v_now, p_admin_user_id, p_actor_description, p_new_group_id, p_group_name, p_manager_user_id); -- 파라미터명 변경됨
COMMIT;
SET p_result_message = CONCAT('그룹(부서) "', p_group_name, '" (ID: ', p_new_group_id, ') 추가 완료.');
END IF; -- 그룹 이름 중복 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,60 @@
DELIMITER $$
CREATE PROCEDURE `sp_add_resource`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_category_id TINYINT UNSIGNED,
IN p_resource_code VARCHAR(100),
IN p_manufacturer VARCHAR(100),
IN p_resource_name VARCHAR(100),
IN p_serial_num VARCHAR(200),
IN p_spec_value DECIMAL(10, 2),
IN p_spec_unit TINYINT UNSIGNED,
IN p_user_id BIGINT,
IN p_comments VARCHAR(200),
IN p_purchase_date DATE, -- 파라미터명 및 타입 변경
IN p_is_locked BOOLEAN,
OUT p_new_resource_id BIGINT
)
COMMENT '자산 추가 및 로그 기록'
BEGIN
DECLARE v_now DATETIME DEFAULT NOW(); -- register_date 용
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '작업 주체 정보(관리자 ID 또는 프로세스 설명)는 필수입니다.';
END IF;
IF p_resource_name IS NULL OR p_resource_name = '' THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '제품명은 필수입니다.';
END IF;
IF p_serial_num IS NOT NULL AND p_serial_num != '' AND EXISTS (SELECT 1 FROM resource_info WHERE serial_num = p_serial_num) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '이미 등록된 시리얼 번호입니다.';
END IF;
-- 트랜잭션 시작
START TRANSACTION;
INSERT INTO resource_info (
category_id, resource_code, manufacturer, resource_name, serial_num,
spec_value, spec_unit, user_id, comments, purchase_date, register_date, is_locked
-- update_date는 ON UPDATE CURRENT_TIMESTAMP 로 자동 관리됨
) VALUES (
p_category_id, p_resource_code, p_manufacturer, p_resource_name, p_serial_num,
p_spec_value, p_spec_unit, p_user_id, p_comments, p_purchase_date, v_now, p_is_locked
);
SET p_new_resource_id = LAST_INSERT_ID();
INSERT INTO log_add_resource (
log_date, admin_user_id, actor_description, resource_id, category_id, resource_code,
manufacturer, resource_name, serial_num, spec_value, spec_unit, user_id, comments,
purchase_date, register_date -- 컬럼명 변경 반영
) VALUES (
v_now, p_admin_user_id, p_actor_description, p_new_resource_id, p_category_id, p_resource_code,
p_manufacturer, p_resource_name, p_serial_num, p_spec_value, p_spec_unit, p_user_id, p_comments,
p_purchase_date, v_now -- 컬럼명 변경 반영
);
COMMIT;
END
$$
DELIMITER ;

View File

@ -0,0 +1,62 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_add_user`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_display_name VARCHAR(100), -- 파라미터명 변경
IN p_account_name VARCHAR(255), -- 파라미터명 변경
IN p_group_id BIGINT,
OUT p_new_user_id BIGINT,
OUT p_result_message VARCHAR(255)
)
COMMENT '사용자 추가 및 로그 기록'
BEGIN
DECLARE v_existing_user_id BIGINT DEFAULT NULL;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK;
SET p_new_user_id = NULL;
SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_new_user_id = NULL;
SET p_result_message = '작업 주체 정보는 필수입니다.';
-- RETURN; -- ★ 제거
ELSEIF p_account_name IS NULL OR p_account_name = '' THEN
SET p_new_user_id = NULL;
SET p_result_message = '계정 이름은 필수입니다.';
-- RETURN; -- ★ 제거
ELSE
-- 계정 이름 중복 검사
SELECT user_id INTO v_existing_user_id FROM user_info WHERE LOWER(account_name) = LOWER(p_account_name) LIMIT 1;
IF v_existing_user_id IS NOT NULL THEN
SET p_new_user_id = NULL;
SET p_result_message = CONCAT('이미 사용 중인 계정 이름입니다: ', p_account_name);
-- RETURN; -- ★ 제거
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
INSERT INTO user_info (display_name, account_name, group_id)
VALUES (p_display_name, p_account_name, p_group_id);
SET p_new_user_id = LAST_INSERT_ID();
INSERT INTO log_add_user (log_date, admin_user_id, actor_description, user_id, display_name, account_name, group_id)
VALUES (v_now, p_admin_user_id, p_actor_description, p_new_user_id, p_display_name, p_account_name, p_group_id);
COMMIT;
SET p_result_message = CONCAT('사용자 "', IFNULL(p_display_name, p_account_name), '" (ID: ', p_new_user_id, ') 추가 완료.');
END IF; -- 계정 중복 검사 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,53 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_delete_category`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_category_id TINYINT UNSIGNED,
OUT p_result_message VARCHAR(255)
)
COMMENT '카테고리 삭제 및 로그 기록 (사용 자산 확인 포함)'
BEGIN
DECLARE v_category_name VARCHAR(40);
DECLARE v_asset_count INT DEFAULT 0;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK; SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_result_message = '작업 주체 정보는 필수입니다.';
ELSE
-- 삭제 대상 정보 조회
SELECT category_name INTO v_category_name FROM resource_category WHERE category_id = p_category_id;
IF v_category_name IS NULL THEN
SET p_result_message = CONCAT('삭제할 카테고리를 찾을 수 없습니다 (ID: ', p_category_id, ')');
ELSE
-- 사용 중인 자산 확인
SELECT COUNT(*) INTO v_asset_count FROM resource_info WHERE category_id = p_category_id;
IF v_asset_count > 0 THEN
SET p_result_message = CONCAT('카테고리 "', v_category_name, '"를 사용하는 자산 ', v_asset_count, '개가 있어 삭제할 수 없습니다. 자산 카테고리를 먼저 변경하세요.');
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
INSERT INTO log_delete_category (log_date, admin_user_id, actor_description, category_id, category_name)
VALUES (v_now, p_admin_user_id, p_actor_description, p_category_id, v_category_name);
DELETE FROM resource_category WHERE category_id = p_category_id;
COMMIT;
SET p_result_message = CONCAT('카테고리 "', v_category_name, '" (ID: ', p_category_id, ') 삭제 완료.');
END IF; -- 자산 확인 IF 종료
END IF; -- 카테고리 존재 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,55 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_delete_group`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_group_id BIGINT,
OUT p_result_message VARCHAR(255)
)
COMMENT '그룹(부서) 삭제 및 로그 기록 (멤버 확인 포함)'
BEGIN
DECLARE v_group_name VARCHAR(100);
DECLARE v_manager_user_id BIGINT; -- 변수명 변경
DECLARE v_member_count INT DEFAULT 0;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK; SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_result_message = '작업 주체 정보는 필수입니다.';
ELSE
-- 삭제 대상 정보 조회
SELECT group_name, manager_user_id INTO v_group_name, v_manager_user_id -- 컬럼명/변수명 변경
FROM group_info WHERE group_id = p_group_id;
IF v_group_name IS NULL THEN
SET p_result_message = CONCAT('삭제할 그룹(부서)을 찾을 수 없습니다 (ID: ', p_group_id, ')');
ELSE
-- 소속된 사용자 확인
SELECT COUNT(*) INTO v_member_count FROM user_info WHERE group_id = p_group_id;
IF v_member_count > 0 THEN
SET p_result_message = CONCAT('그룹(부서) "', v_group_name, '"에 속한 사용자 ', v_member_count, '명이 있어 삭제할 수 없습니다. 사용자 소속을 먼저 변경하세요.');
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
INSERT INTO log_delete_group (log_date, admin_user_id, actor_description, group_id, group_name, manager_user_id) -- 컬럼명 변경
VALUES (v_now, p_admin_user_id, p_actor_description, p_group_id, v_group_name, v_manager_user_id); -- 변수명 변경
DELETE FROM group_info WHERE group_id = p_group_id;
COMMIT;
SET p_result_message = CONCAT('그룹(부서) "', v_group_name, '" (ID: ', p_group_id, ') 삭제 완료.');
END IF; -- 멤버 확인 IF 종료
END IF; -- 그룹 존재 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,44 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_delete_resource`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_resource_id BIGINT
)
COMMENT '자산 삭제 및 로그 기록'
BEGIN
DECLARE v_now DATETIME DEFAULT NOW();
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '작업 주체 정보(관리자 ID 또는 프로세스 설명)는 필수입니다.';
END IF;
IF NOT EXISTS (SELECT 1 FROM resource_info WHERE resource_id = p_resource_id) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '삭제할 자산을 찾을 수 없습니다.';
END IF;
-- 트랜잭션 시작
START TRANSACTION;
-- 로그 기록 (삭제 전에!)
INSERT INTO log_delete_resource (
log_date, admin_user_id, actor_description, resource_id, category_id, resource_code,
manufacturer, resource_name, serial_num, spec_value, spec_unit, user_id, comments,
purchase_date, register_date -- 컬럼명 변경 반영
)
SELECT
v_now, p_admin_user_id, p_actor_description, resource_id, category_id, resource_code,
manufacturer, resource_name, serial_num, spec_value, spec_unit, user_id, comments,
purchase_date, register_date -- 컬럼명 변경 반영
FROM resource_info WHERE resource_id = p_resource_id;
-- 자산 삭제
DELETE FROM resource_info WHERE resource_id = p_resource_id;
COMMIT;
END
$$
DELIMITER ;

View File

@ -0,0 +1,62 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_delete_user`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_user_id BIGINT,
OUT p_result_message VARCHAR(255)
)
COMMENT '사용자 삭제 및 로그 기록 (할당 자산 확인 포함)'
BEGIN
DECLARE v_display_name VARCHAR(100);
DECLARE v_account_name VARCHAR(255);
DECLARE v_group_id BIGINT;
DECLARE v_assigned_assets_count INT DEFAULT 0;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK; SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_result_message = '작업 주체 정보는 필수입니다.';
-- RETURN; -- ★ 제거
ELSE
-- 삭제 대상 정보 조회 및 존재 확인
SELECT display_name, account_name, group_id INTO v_display_name, v_account_name, v_group_id
FROM user_info WHERE user_id = p_user_id;
IF v_account_name IS NULL THEN
SET p_result_message = CONCAT('삭제할 사용자를 찾을 수 없습니다 (ID: ', p_user_id, ')');
-- RETURN; -- ★ 제거
ELSE
-- 할당된 자산 확인
SELECT COUNT(*) INTO v_assigned_assets_count FROM resource_info WHERE user_id = p_user_id;
IF v_assigned_assets_count > 0 THEN
SET p_result_message = CONCAT('사용자 "', IFNULL(v_display_name, v_account_name), '"에게 할당된 자산 ', v_assigned_assets_count, '개가 있어 삭제할 수 없습니다. 자산 할당을 먼저 해제하세요.');
-- RETURN; -- ★ 제거
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
INSERT INTO log_delete_user (log_date, admin_user_id, actor_description, user_id,
display_name, account_name, group_id)
VALUES (v_now, p_admin_user_id, p_actor_description, p_user_id,
v_display_name, v_account_name, v_group_id);
DELETE FROM user_info WHERE user_id = p_user_id;
COMMIT;
SET p_result_message = CONCAT('사용자 "', IFNULL(v_display_name, v_account_name), '" (ID: ', p_user_id, ') 삭제 완료.');
END IF; -- 자산 확인 IF 종료
END IF; -- 사용자 존재 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,16 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_all_categories`()
COMMENT '모든 자산 카테고리 목록 조회 (이름순)'
BEGIN
SELECT category_id, category_name
FROM resource_category
ORDER BY category_id;
END
$$
DELIMITER ;

View File

@ -0,0 +1,23 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_all_groups`()
COMMENT '모든 그룹(부서) 목록 조회 (관리자 이름 포함, 이름순)'
BEGIN
SELECT
g.group_id,
g.group_name,
g.manager_user_id,
-- 관리자 표시 이름 생성 (user_list 프로시저와 유사하게)
CASE
WHEN m.user_id IS NOT NULL AND m.display_name IS NOT NULL AND m.display_name != '' AND m.account_name IS NOT NULL THEN CONCAT(m.display_name, ' [', m.account_name, ']')
WHEN m.display_name IS NOT NULL AND m.display_name != '' THEN m.display_name
WHEN m.account_name IS NOT NULL THEN m.account_name
ELSE NULL -- 매니저 없는 경우
END AS manager_display_name
FROM group_info g
LEFT JOIN user_info m ON g.manager_user_id = m.user_id -- user_info 와 조인
ORDER BY g.group_id;
END
$$
DELIMITER ;

View File

@ -0,0 +1,67 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_all_resources`(
IN p_page_num INT,
IN p_page_size INT,
IN p_sort_column VARCHAR(50),
IN p_sort_direction VARCHAR(4),
IN p_category_id TINYINT UNSIGNED,
IN p_group_id BIGINT,
IN p_user_id BIGINT
)
COMMENT '전체 자산 목록 조회 (페이징, 정렬, 필터링)'
BEGIN
DECLARE v_offset INT;
DECLARE v_order_by_clause VARCHAR(255);
DECLARE v_sql TEXT;
-- 입력값 기본 처리
IF UPPER(p_sort_direction) != 'ASC' THEN SET p_sort_direction = 'DESC'; END IF;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 20; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
-- 정렬 기준 설정
SET v_order_by_clause = CASE p_sort_column
WHEN 'id' THEN CONCAT('ORDER BY r.resource_id ', p_sort_direction)
WHEN 'name' THEN CONCAT('ORDER BY r.resource_name ', p_sort_direction)
WHEN 'category' THEN CONCAT('ORDER BY rc.category_name ', p_sort_direction)
WHEN 'code' THEN CONCAT('ORDER BY r.resource_code ', p_sort_direction)
WHEN 'user' THEN CONCAT('ORDER BY user_display_name ', p_sort_direction)
WHEN 'group' THEN CONCAT('ORDER BY g.group_name ', p_sort_direction)
WHEN 'serial' THEN CONCAT('ORDER BY r.serial_num ', p_sort_direction)
WHEN 'purchased' THEN CONCAT('ORDER BY r.purchase_date ', p_sort_direction) -- 정렬 기준 변경: created -> purchased
WHEN 'registered' THEN CONCAT('ORDER BY r.register_date ', p_sort_direction) -- 정렬 기준 추가: registered
WHEN 'updated' THEN CONCAT('ORDER BY r.update_date ', p_sort_direction)
WHEN 'is_locked' THEN CONCAT('ORDER BY r.is_locked ', p_sort_direction)
ELSE 'ORDER BY r.resource_id DESC'
END;
IF p_sort_column != 'id' THEN SET v_order_by_clause = CONCAT(v_order_by_clause, ', r.resource_id DESC'); END IF;
-- 동적 SQL 생성
SET v_sql = CONCAT(
'SELECT SQL_CALC_FOUND_ROWS ',
' r.resource_id, r.category_id, rc.category_name, r.resource_code, r.manufacturer, ',
' r.resource_name, r.serial_num, r.spec_value, r.spec_unit, r.user_id, ',
' CASE WHEN u.user_id IS NOT NULL AND u.display_name IS NOT NULL AND u.display_name != \'\' AND u.account_name IS NOT NULL THEN CONCAT(u.display_name, \' [\', u.account_name, \']\') WHEN u.display_name IS NOT NULL AND u.display_name != \'\' THEN u.display_name ELSE u.account_name END AS user_display_name, ', -- 사용자 표시 이름 로직 변경
' g.group_name, r.comments, r.purchase_date, r.register_date, r.update_date, r.is_locked ', -- 컬럼명 변경 반영
'FROM resource_info r ',
' LEFT JOIN resource_category rc ON r.category_id = rc.category_id ',
' LEFT JOIN user_info u ON r.user_id = u.user_id ',
' LEFT JOIN group_info g ON u.group_id = g.group_id ',
'WHERE (? IS NULL OR r.category_id = ?) ',
' AND (? IS NULL OR g.group_id = ?) ',
' AND (? IS NULL OR r.user_id = ?) ',
v_order_by_clause,
' LIMIT ? OFFSET ?'
);
-- SQL 실행
PREPARE stmt FROM v_sql;
EXECUTE stmt USING p_category_id, p_category_id, p_group_id, p_group_id, p_user_id, p_user_id, p_page_size, v_offset;
SELECT FOUND_ROWS() AS total_count;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,71 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_all_resources_export`(
-- 페이징 파라미터 제거
IN p_sort_column VARCHAR(50),
IN p_sort_direction VARCHAR(4),
IN p_category_id TINYINT UNSIGNED,
IN p_group_id BIGINT,
IN p_user_id BIGINT
)
COMMENT '전체 자산 목록 조회 (내보내기용 - 페이징 없음, 잠금 상태 포함)'
BEGIN
DECLARE v_order_by_clause VARCHAR(255);
DECLARE v_sql TEXT;
IF UPPER(p_sort_direction) NOT IN ('ASC', 'DESC') THEN SET p_sort_direction = 'DESC'; END IF;
-- 정렬 기준 설정 (기존과 동일, is_locked 포함)
SET v_order_by_clause = CASE p_sort_column
WHEN 'id' THEN CONCAT('ORDER BY r.resource_id ', p_sort_direction)
WHEN 'name' THEN CONCAT('ORDER BY r.resource_name ', p_sort_direction)
WHEN 'category' THEN CONCAT('ORDER BY rc.category_name ', p_sort_direction)
WHEN 'code' THEN CONCAT('ORDER BY r.resource_code ', p_sort_direction)
WHEN 'user' THEN CONCAT('ORDER BY user_display_name ', p_sort_direction)
WHEN 'group' THEN CONCAT('ORDER BY g.group_name ', p_sort_direction)
WHEN 'serial' THEN CONCAT('ORDER BY r.serial_num ', p_sort_direction)
WHEN 'purchased' THEN CONCAT('ORDER BY r.purchase_date ', p_sort_direction)
WHEN 'registered' THEN CONCAT('ORDER BY r.register_date ', p_sort_direction)
WHEN 'updated' THEN CONCAT('ORDER BY r.update_date ', p_sort_direction)
WHEN 'is_locked' THEN CONCAT('ORDER BY r.is_locked ', p_sort_direction)
ELSE CONCAT('ORDER BY r.resource_id ', p_sort_direction)
END;
IF p_sort_column != 'id' THEN
SET v_order_by_clause = CONCAT(v_order_by_clause, ', r.resource_id DESC');
END IF;
SET v_sql = CONCAT(
'SELECT ', -- SQL_CALC_FOUND_ROWS 제거 (총 개수 필요 없음)
' r.resource_id, r.category_id, rc.category_name, r.resource_code, r.manufacturer, ',
' r.resource_name, r.serial_num, r.spec_value, r.spec_unit, r.user_id, ',
' CASE ',
' WHEN u.user_id IS NOT NULL AND u.display_name IS NOT NULL AND u.display_name != \'\' AND u.account_name IS NOT NULL THEN CONCAT(u.display_name, \' [\', u.account_name, \']\') ',
' WHEN u.display_name IS NOT NULL AND u.display_name != \'\' THEN u.display_name ',
' ELSE u.account_name ',
' END AS user_display_name, ',
' g.group_name, r.comments, r.purchase_date, r.register_date, r.update_date, r.is_locked ',
'FROM resource_info r ',
' LEFT JOIN resource_category rc ON r.category_id = rc.category_id ',
' LEFT JOIN user_info u ON r.user_id = u.user_id ',
' LEFT JOIN group_info g ON u.group_id = g.group_id ',
'WHERE (CAST(? AS SIGNED) IS NULL OR r.category_id = ?) ',
' AND (CAST(? AS SIGNED) IS NULL OR g.group_id = ?) ',
' AND (CAST(? AS SIGNED) IS NULL OR r.user_id = ?) ',
v_order_by_clause
-- LIMIT ... OFFSET ... 제거
);
SET @p_category_id_filter = p_category_id;
SET @p_group_id_filter = p_group_id;
SET @p_user_id_filter = p_user_id;
PREPARE stmt FROM v_sql;
EXECUTE stmt USING
@p_category_id_filter, @p_category_id_filter,
@p_group_id_filter, @p_group_id_filter,
@p_user_id_filter, @p_user_id_filter;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,23 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_all_users`()
COMMENT '모든 사용자 목록 간략 조회 (폼 선택용)'
BEGIN
SELECT
user_id,
-- 표시 이름 형식: "표시이름 [계정명]" 또는 "표시이름" 또는 "계정명"
CASE
WHEN display_name IS NOT NULL AND display_name != '' AND account_name IS NOT NULL THEN CONCAT(display_name, ' [', account_name, ']')
WHEN display_name IS NOT NULL AND display_name != '' THEN display_name
ELSE account_name
END AS user_display_name
FROM user_info
ORDER BY user_display_name;
END
$$
DELIMITER ;

View File

@ -0,0 +1,21 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_assets_count_by_category`()
COMMENT '카테고리별 자산 수 조회 (대시보드용)'
BEGIN
SELECT
rc.category_id,
rc.category_name,
COUNT(r.resource_id) AS asset_count
FROM resource_category rc
LEFT JOIN resource_info r ON rc.category_id = r.category_id
GROUP BY rc.category_id, rc.category_name
ORDER BY rc.category_name;
END
$$
DELIMITER ;

View File

@ -0,0 +1,100 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_category_audit_logs`(
IN p_search_term VARCHAR(100), -- 검색어 (NULL 가능)
IN p_start_date DATE, -- 시작일 (NULL 가능)
IN p_end_date DATE, -- 종료일 (NULL 가능)
IN p_page_num INT, -- 페이지 번호 (기본값 1)
IN p_page_size INT -- 페이지 크기 (기본값 20)
)
COMMENT '카테고리 관련 감사 로그 통합 조회 (검색, 기간, 페이징)'
BEGIN
DECLARE v_offset INT;
SET @v_search_like = NULL;
-- 입력값 기본 처리
IF p_search_term IS NOT NULL AND p_search_term != '' THEN
SET @v_search_like = CONCAT('%', p_search_term, '%');
END IF;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 20; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
-- 날짜 범위 조건 문자열 동적 생성
SET @v_date_condition = '';
IF p_start_date IS NOT NULL THEN
SET @v_date_condition = CONCAT('AND l.log_date >= DATE(''', p_start_date, ''') ');
END IF;
IF p_end_date IS NOT NULL THEN
SET @v_date_condition = CONCAT(@v_date_condition, 'AND l.log_date < DATE_ADD(DATE(''', p_end_date, '''), INTERVAL 1 DAY) ');
END IF;
-- 검색 조건 문자열 동적 생성 (통합 결과셋 대상)
SET @v_search_condition = '';
IF @v_search_like IS NOT NULL THEN
SET @v_search_condition = CONCAT(
'WHERE (',
' actor_info LIKE @v_search_like ', -- 작업자 정보
' OR CAST(target_id AS CHAR) LIKE @v_search_like ', -- 대상 카테고리 ID
' OR target_info_at_log LIKE @v_search_like ', -- 대상 카테고리 정보 (이름)
' OR details LIKE @v_search_like', -- 상세 내용
') '
);
ELSE
SET @v_search_condition = 'WHERE 1=1 ';
END IF;
-- 최종 동적 SQL 구성
SET @v_sql = CONCAT('
SELECT SQL_CALC_FOUND_ROWS * FROM (
-- 카테고리 추가 로그
SELECT
\'ADD\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.category_id AS target_id,
l.category_name AS target_info_at_log, -- 추가 시점 카테고리 이름
CONCAT(\' : \', l.category_name, \' (ID: \', l.category_id, \')\') AS details
FROM log_add_category l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
UNION ALL
-- 카테고리 수정 로그
SELECT
\'UPDATE\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.category_id AS target_id,
l.new_category_name AS target_info_at_log, -- 수정 후 카테고리 이름
CONCAT(\' : \', COALESCE(l.old_category_name, \'\'), \'->\', l.new_category_name, \' (ID: \', l.category_id, \')\') AS details
FROM log_update_category l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
UNION ALL
-- 카테고리 삭제 로그
SELECT
\'DELETE\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.category_id AS target_id,
l.category_name AS target_info_at_log, -- 삭제 시점 카테고리 이름
CONCAT(\' : \', l.category_name, \' (ID: \', l.category_id, \')\') AS details
FROM log_delete_category l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
) AS combined_logs
', @v_search_condition, '
ORDER BY log_date DESC
LIMIT ? OFFSET ?
');
-- SQL 문 실행
PREPARE stmt FROM @v_sql;
EXECUTE stmt USING p_page_size, v_offset;
-- 전체 결과 수 계산 값 반환
SELECT FOUND_ROWS() AS total_count;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,18 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_category_by_id`(
IN p_category_id TINYINT UNSIGNED
)
COMMENT '카테고리 ID로 정보 조회'
BEGIN
SELECT category_id, category_name
FROM resource_category
WHERE category_id = p_category_id;
END
$$
DELIMITER ;

View File

@ -0,0 +1,18 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_dashboard_summary`()
COMMENT '대시보드 요약 정보 조회 (총 자산, 사용자, 그룹, 미할당 자산 수)'
BEGIN
SELECT
(SELECT COUNT(*) FROM resource_info) AS total_assets,
(SELECT COUNT(*) FROM user_info) AS total_users,
(SELECT COUNT(*) FROM group_info) AS total_groups,
(SELECT COUNT(*) FROM resource_info WHERE user_id IS NULL) AS unassigned_assets;
END
$$
DELIMITER ;

View File

@ -0,0 +1,103 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_group_audit_logs`(
IN p_search_term VARCHAR(100), -- 검색어 (NULL 가능)
IN p_start_date DATE, -- 시작일 (NULL 가능)
IN p_end_date DATE, -- 종료일 (NULL 가능)
IN p_page_num INT, -- 페이지 번호 (기본값 1)
IN p_page_size INT -- 페이지 크기 (기본값 20)
)
COMMENT '그룹(부서) 관련 감사 로그 통합 조회 (검색, 기간, 페이징)'
BEGIN
DECLARE v_offset INT;
SET @v_search_like = NULL;
-- 입력값 기본 처리
IF p_search_term IS NOT NULL AND p_search_term != '' THEN
SET @v_search_like = CONCAT('%', p_search_term, '%');
END IF;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 20; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
-- 날짜 범위 조건 문자열 동적 생성
SET @v_date_condition = '';
IF p_start_date IS NOT NULL THEN
SET @v_date_condition = CONCAT('AND l.log_date >= DATE(''', p_start_date, ''') ');
END IF;
IF p_end_date IS NOT NULL THEN
SET @v_date_condition = CONCAT(@v_date_condition, 'AND l.log_date < DATE_ADD(DATE(''', p_end_date, '''), INTERVAL 1 DAY) ');
END IF;
-- 검색 조건 문자열 동적 생성 (통합 결과셋 대상)
SET @v_search_condition = '';
IF @v_search_like IS NOT NULL THEN
SET @v_search_condition = CONCAT(
'WHERE (',
' actor_info LIKE @v_search_like ', -- 작업자 정보
' OR CAST(target_id AS CHAR) LIKE @v_search_like ', -- 대상 그룹 ID
' OR target_info_at_log LIKE @v_search_like ', -- 대상 그룹 정보 (이름)
' OR details LIKE @v_search_like', -- 상세 내용
') '
);
ELSE
SET @v_search_condition = 'WHERE 1=1 ';
END IF;
-- 최종 동적 SQL 구성
SET @v_sql = CONCAT('
SELECT SQL_CALC_FOUND_ROWS * FROM (
-- 그룹 추가 로그
SELECT
\'ADD\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.group_id AS target_id,
l.group_name AS target_info_at_log, -- 추가 시점 그룹 이름
CONCAT(\' : \', l.group_name, IF(l.manager_user_id IS NULL, \'\', CONCAT(\' ( ID: \', l.manager_user_id, \')\'))) AS details
FROM log_add_group l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
UNION ALL
-- 그룹 수정 로그
SELECT
\'UPDATE\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.group_id AS target_id,
l.new_group_name AS target_info_at_log, -- 수정 후 그룹 이름
CONCAT(\' : \', l.new_group_name, \'. \',
IF(l.old_group_name <=> l.new_group_name, \'\', CONCAT(\' : \', COALESCE(l.old_group_name, \'\'), \'->\', l.new_group_name, \'. \')),
IF(l.old_manager_user_id <=> l.new_manager_user_id, \'\', CONCAT(\' : \', COALESCE(l.old_manager_user_id, \'\'), \'->\', COALESCE(l.new_manager_user_id, \'\'), \'. \'))
) AS details
FROM log_update_group l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
UNION ALL
-- 그룹 삭제 로그
SELECT
\'DELETE\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.group_id AS target_id,
l.group_name AS target_info_at_log, -- 삭제 시점 그룹 이름
CONCAT(\' : \', l.group_name) AS details
FROM log_delete_group l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
) AS combined_logs
', @v_search_condition, '
ORDER BY log_date DESC
LIMIT ? OFFSET ?
');
-- SQL 문 실행
PREPARE stmt FROM @v_sql;
EXECUTE stmt USING p_page_size, v_offset;
-- 전체 결과 수 계산 값 반환
SELECT FOUND_ROWS() AS total_count;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,24 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_group_by_id`(
IN p_group_id BIGINT
)
COMMENT '그룹(부서) ID로 상세 정보 조회 (관리자 정보 포함)'
BEGIN
SELECT
g.group_id,
g.group_name,
g.manager_user_id, -- 컬럼명 변경됨
u.display_name AS manager_display_name, -- 관리자 표시 이름
u.account_name AS manager_account_name -- 관리자 계정 이름
FROM group_info g
LEFT JOIN user_info u ON g.manager_user_id = u.user_id -- 조인 컬럼 변경됨
WHERE g.group_id = p_group_id;
END
$$
DELIMITER ;

View File

@ -0,0 +1,114 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_resource_audit_logs`(
IN p_search_term VARCHAR(100), -- 검색어 (NULL 가능)
IN p_start_date DATE, -- 시작일 (NULL 가능)
IN p_end_date DATE, -- 종료일 (NULL 가능)
IN p_page_num INT, -- 페이지 번호 (기본값 1)
IN p_page_size INT -- 페이지 크기 (기본값 20)
)
COMMENT '자산 관련 감사 로그 통합 조회 (검색, 기간, 페이징)'
BEGIN
DECLARE v_offset INT;
SET @v_search_like = NULL; -- 검색어용 세션 변수
-- 입력값 기본 처리
IF p_search_term IS NOT NULL AND p_search_term != '' THEN
SET @v_search_like = CONCAT('%', p_search_term, '%');
END IF;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 20; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
-- 날짜 범위 조건 문자열 동적 생성
SET @v_date_condition = '';
IF p_start_date IS NOT NULL THEN
SET @v_date_condition = CONCAT('AND l.log_date >= DATE(''', p_start_date, ''') '); -- DATE() 사용하여 시간 무시
END IF;
IF p_end_date IS NOT NULL THEN
-- 종료일 다음 날 0시 미만으로 포함
SET @v_date_condition = CONCAT(@v_date_condition, 'AND l.log_date < DATE_ADD(DATE(''', p_end_date, '''), INTERVAL 1 DAY) ');
END IF;
-- 검색 조건 문자열 동적 생성 (통합 결과셋 대상)
SET @v_search_condition = '';
IF @v_search_like IS NOT NULL THEN
SET @v_search_condition = CONCAT(
'WHERE (',
' actor_info LIKE @v_search_like ', -- 작업자 정보
' OR CAST(target_id AS CHAR) LIKE @v_search_like ', -- 대상 ID (문자열로 변환하여 검색)
' OR target_info_at_log LIKE @v_search_like ', -- 대상 정보 (이름 등)
' OR serial_num LIKE @v_search_like ', -- 시리얼 번호
' OR details LIKE @v_search_like', -- 상세 내용
') '
);
ELSE
SET @v_search_condition = 'WHERE 1=1 '; -- 검색어 없으면 모든 결과
END IF;
-- 최종 동적 SQL 구성
-- 1. 각 로그 테이블에서 기간 필터링 적용하여 UNION ALL
-- 2. UNION ALL 결과셋에 대해 검색어 필터링 적용
-- 3. 정렬, 페이징 적용
SET @v_sql = CONCAT('
SELECT SQL_CALC_FOUND_ROWS * FROM (
-- 자산 추가 로그
SELECT
\'ADD\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.resource_id AS target_id,
l.resource_name AS target_info_at_log,
l.serial_num,
CONCAT(\' : \', l.resource_name, \' (SN:\', IFNULL(l.serial_num, \'-\'), \')\') AS details
FROM log_add_resource l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
UNION ALL
-- 자산 수정 로그
SELECT
\'UPDATE\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.resource_id AS target_id,
l.resource_name AS target_info_at_log, -- 변경 후 이름
l.serial_num AS serial_num, -- 변경 후 시리얼
-- 상세 내용 생성 (예시: 변경된 필드 표시 - 필요시 복잡하게 구현 가능)
CONCAT(
\' : \', IFNULL(l.resource_name, \'( )\'),
\' (ID:\', l.resource_id, \')\'
-- 여기에 변경된 필드 정보 추가 가능 (예: IF(old_value!=new_value, ...))
) AS details
FROM log_update_resource l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
UNION ALL
-- 자산 삭제 로그
SELECT
\'DELETE\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.resource_id AS target_id,
l.resource_name AS target_info_at_log, -- 삭제 시점 이름
l.serial_num AS serial_num, -- 삭제 시점 시리얼
CONCAT(\' : \', l.resource_name, \' (SN:\', IFNULL(l.serial_num, \'-\'), \')\') AS details
FROM log_delete_resource l LEFT JOIN auth_user au ON l.admin_user_id = au.id
WHERE 1=1 ', @v_date_condition, '
) AS combined_logs
', @v_search_condition, ' -- 최종 검색 조건 적용
ORDER BY log_date DESC
LIMIT ? OFFSET ? -- 페이징 적용
');
-- SQL 문 실행
PREPARE stmt FROM @v_sql;
-- LIMIT 절에 파라미터 바인딩
EXECUTE stmt USING p_page_size, v_offset;
-- 전체 결과 수 계산 값 반환 (두 번째 결과셋)
SELECT FOUND_ROWS() AS total_count;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,21 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_resource_by_id`(
IN p_resource_id BIGINT
)
COMMENT '자산 ID로 상세 정보 조회'
BEGIN
SELECT
r.resource_id, r.category_id, rc.category_name, r.resource_code, r.manufacturer,
r.resource_name, r.serial_num, r.spec_value, r.spec_unit, r.user_id,
CASE WHEN u.user_id IS NOT NULL AND u.display_name IS NOT NULL AND u.display_name != '' AND u.account_name IS NOT NULL THEN CONCAT(u.display_name, ' [', u.account_name, ']') WHEN u.display_name IS NOT NULL AND u.display_name != '' THEN u.display_name ELSE u.account_name END AS user_display_name, -- 사용자 표시 이름 로직 변경
g.group_name, r.comments, r.purchase_date, r.register_date, r.update_date, r.is_locked -- 컬럼명 변경 반영
FROM resource_info r
LEFT JOIN resource_category rc ON r.category_id = rc.category_id
LEFT JOIN user_info u ON r.user_id = u.user_id
LEFT JOIN group_info g ON u.group_id = g.group_id
WHERE r.resource_id = p_resource_id;
END
$$
DELIMITER ;

View File

@ -0,0 +1,31 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_resources_by_account`( -- 이름 변경
IN p_account_name VARCHAR(255) -- 파라미터명 변경
)
COMMENT '사용자 계정명으로 할당된 자원 목록 조회 (간단 버전)'
BEGIN
DECLARE v_user_id BIGINT DEFAULT NULL;
-- 계정 이름으로 사용자 ID 찾기
SELECT user_id INTO v_user_id
FROM user_info WHERE LOWER(account_name) = LOWER(p_account_name) LIMIT 1; -- 컬럼명 변경
-- 사용자가 존재하면 해당 사용자의 자산 목록 반환
IF v_user_id IS NOT NULL THEN
SELECT r.resource_id, r.resource_name, r.serial_num
FROM resource_info r
WHERE r.user_id = v_user_id
ORDER BY r.register_date; -- 정렬 기준 변경: create_date -> register_date
ELSE
-- 사용자가 없으면 빈 결과 반환
SELECT NULL AS resource_id, NULL AS resource_name, NULL AS serial_num WHERE FALSE;
END IF;
END
$$
DELIMITER ;

View File

@ -0,0 +1,71 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_resources_by_search`(
IN p_search_term VARCHAR(100),
IN p_page_num INT,
IN p_page_size INT,
IN p_sort_column VARCHAR(50),
IN p_sort_direction VARCHAR(4),
IN p_category_id TINYINT UNSIGNED,
IN p_group_id BIGINT,
IN p_user_id BIGINT
)
COMMENT '자산 검색 결과 조회 (페이징, 정렬, 필터링)'
BEGIN
DECLARE v_offset INT;
DECLARE v_order_by_clause VARCHAR(255);
DECLARE v_sql TEXT;
SET @p_search_like = NULL; -- 세션 변수 사용
-- 입력값 기본 처리
IF p_search_term IS NOT NULL AND p_search_term != '' THEN SET @p_search_like = CONCAT('%', p_search_term, '%'); END IF;
IF UPPER(p_sort_direction) != 'ASC' THEN SET p_sort_direction = 'DESC'; END IF;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 20; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
-- 정렬 기준 설정
SET v_order_by_clause = CASE p_sort_column
WHEN 'id' THEN CONCAT('ORDER BY r.resource_id ', p_sort_direction)
WHEN 'name' THEN CONCAT('ORDER BY r.resource_name ', p_sort_direction)
WHEN 'category' THEN CONCAT('ORDER BY rc.category_name ', p_sort_direction)
WHEN 'code' THEN CONCAT('ORDER BY r.resource_code ', p_sort_direction)
WHEN 'user' THEN CONCAT('ORDER BY user_display_name ', p_sort_direction)
WHEN 'group' THEN CONCAT('ORDER BY g.group_name ', p_sort_direction)
WHEN 'serial' THEN CONCAT('ORDER BY r.serial_num ', p_sort_direction)
WHEN 'purchased' THEN CONCAT('ORDER BY r.purchase_date ', p_sort_direction) -- 정렬 기준 변경
WHEN 'registered' THEN CONCAT('ORDER BY r.register_date ', p_sort_direction) -- 정렬 기준 추가
WHEN 'updated' THEN CONCAT('ORDER BY r.update_date ', p_sort_direction)
WHEN 'is_locked' THEN CONCAT('ORDER BY r.is_locked ', p_sort_direction)
ELSE 'ORDER BY r.resource_id DESC'
END;
IF p_sort_column != 'id' THEN SET v_order_by_clause = CONCAT(v_order_by_clause, ', r.resource_id DESC'); END IF;
-- 동적 SQL 생성
SET v_sql = CONCAT(
'SELECT SQL_CALC_FOUND_ROWS ',
' r.resource_id, r.category_id, rc.category_name, r.resource_code, r.manufacturer, ',
' r.resource_name, r.serial_num, r.spec_value, r.spec_unit, r.user_id, ',
' CASE WHEN u.user_id IS NOT NULL AND u.display_name IS NOT NULL AND u.display_name != \'\' AND u.account_name IS NOT NULL THEN CONCAT(u.display_name, \' [\', u.account_name, \']\') WHEN u.display_name IS NOT NULL AND u.display_name != \'\' THEN u.display_name ELSE u.account_name END AS user_display_name, ', -- 사용자 표시 이름 로직 변경
' g.group_name, r.comments, r.purchase_date, r.register_date, r.update_date, r.is_locked ', -- 컬럼명 변경 반영
'FROM resource_info r ',
' LEFT JOIN resource_category rc ON r.category_id = rc.category_id ',
' LEFT JOIN user_info u ON r.user_id = u.user_id ',
' LEFT JOIN group_info g ON u.group_id = g.group_id ',
'WHERE ((@p_search_like IS NULL) OR (r.resource_name LIKE @p_search_like OR r.serial_num LIKE @p_search_like OR r.resource_code LIKE @p_search_like OR u.display_name LIKE @p_search_like OR u.account_name LIKE @p_search_like OR r.manufacturer LIKE @p_search_like OR r.comments LIKE @p_search_like)) ', -- 검색 컬럼 변경
' AND (? IS NULL OR r.category_id = ?) ',
' AND (? IS NULL OR g.group_id = ?) ',
' AND (? IS NULL OR r.user_id = ?) ',
v_order_by_clause,
' LIMIT ? OFFSET ?'
);
-- SQL 실행
PREPARE stmt FROM v_sql;
EXECUTE stmt USING p_category_id, p_category_id, p_group_id, p_group_id, p_user_id, p_user_id, p_page_size, v_offset;
SELECT FOUND_ROWS() AS total_count;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,89 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_resources_by_search_export`(
IN p_search_term VARCHAR(100), -- ★★★ 검색어 입력 파라미터 ★★★
IN p_sort_column VARCHAR(50),
IN p_sort_direction VARCHAR(4),
IN p_category_id TINYINT UNSIGNED,
IN p_group_id BIGINT,
IN p_user_id BIGINT
)
COMMENT '검색된 전체 자산 목록 조회 (내보내기용 - 페이징 없음, 잠금 상태 포함)'
BEGIN
DECLARE v_order_by_clause VARCHAR(255);
DECLARE v_sql TEXT;
DECLARE v_search_like_term VARCHAR(105); -- 검색어 앞뒤에 % 추가
IF UPPER(p_sort_direction) NOT IN ('ASC', 'DESC') THEN SET p_sort_direction = 'DESC'; END IF;
-- 정렬 기준 설정 (is_locked 포함)
SET v_order_by_clause = CASE p_sort_column
WHEN 'id' THEN CONCAT('ORDER BY r.resource_id ', p_sort_direction)
WHEN 'name' THEN CONCAT('ORDER BY r.resource_name ', p_sort_direction)
WHEN 'category' THEN CONCAT('ORDER BY rc.category_name ', p_sort_direction)
WHEN 'code' THEN CONCAT('ORDER BY r.resource_code ', p_sort_direction)
WHEN 'user' THEN CONCAT('ORDER BY user_display_name ', p_sort_direction)
WHEN 'group' THEN CONCAT('ORDER BY g.group_name ', p_sort_direction)
WHEN 'serial' THEN CONCAT('ORDER BY r.serial_num ', p_sort_direction)
WHEN 'purchased' THEN CONCAT('ORDER BY r.purchase_date ', p_sort_direction)
WHEN 'registered' THEN CONCAT('ORDER BY r.register_date ', p_sort_direction)
WHEN 'updated' THEN CONCAT('ORDER BY r.update_date ', p_sort_direction)
WHEN 'is_locked' THEN CONCAT('ORDER BY r.is_locked ', p_sort_direction)
ELSE CONCAT('ORDER BY r.resource_id ', p_sort_direction)
END;
IF p_sort_column != 'id' THEN
SET v_order_by_clause = CONCAT(v_order_by_clause, ', r.resource_id DESC');
END IF;
-- 검색어 LIKE 조건용 문자열 생성
SET v_search_like_term = IF(p_search_term IS NOT NULL AND p_search_term != '', CONCAT('%', p_search_term, '%'), NULL);
SET v_sql = CONCAT(
'SELECT ',
' r.resource_id, r.category_id, rc.category_name, r.resource_code, r.manufacturer, ',
' r.resource_name, r.serial_num, r.spec_value, r.spec_unit, r.user_id, ',
' CASE ',
' WHEN u.user_id IS NOT NULL AND u.display_name IS NOT NULL AND u.display_name != \'\' AND u.account_name IS NOT NULL THEN CONCAT(u.display_name, \' [\', u.account_name, \']\') ',
' WHEN u.display_name IS NOT NULL AND u.display_name != \'\' THEN u.display_name ',
' ELSE u.account_name ',
' END AS user_display_name, ',
' g.group_name, r.comments, r.purchase_date, r.register_date, r.update_date, r.is_locked ',
'FROM resource_info r ',
' LEFT JOIN resource_category rc ON r.category_id = rc.category_id ',
' LEFT JOIN user_info u ON r.user_id = u.user_id ',
' LEFT JOIN group_info g ON u.group_id = g.group_id ',
'WHERE (CAST(? AS SIGNED) IS NULL OR r.category_id = ?) ', -- category_id 필터
' AND (CAST(? AS SIGNED) IS NULL OR g.group_id = ?) ', -- group_id 필터
' AND (CAST(? AS SIGNED) IS NULL OR r.user_id = ?) ', -- user_id 필터
' AND (? IS NULL OR ( ', -- ★★★ 검색어 조건 시작 (v_search_like_term 이 NULL이면 이 AND 조건 전체가 참이 됨) ★★★
' LOWER(r.resource_name) LIKE LOWER(?) OR ',
' LOWER(r.serial_num) LIKE LOWER(?) OR ',
' LOWER(r.resource_code) LIKE LOWER(?) OR ',
' (u.user_id IS NOT NULL AND LOWER(u.display_name) LIKE LOWER(?)) OR ', -- u.display_name 이 NULL 이 아닐 때만 검색
' (u.user_id IS NOT NULL AND LOWER(u.account_name) LIKE LOWER(?)) OR ', -- u.account_name 이 NULL 이 아닐 때만 검색
' LOWER(r.manufacturer) LIKE LOWER(?) OR ',
' LOWER(r.comments) LIKE LOWER(?) ',
' )) ', -- ★★★ 검색어 조건 끝 ★★★
v_order_by_clause
);
-- Prepared Statement 에 사용할 변수 설정
SET @p_category_id_param = p_category_id;
SET @p_group_id_param = p_group_id;
SET @p_user_id_param = p_user_id;
SET @p_search_term_param = v_search_like_term; -- %가 포함된 검색어 또는 NULL
PREPARE stmt FROM v_sql;
EXECUTE stmt USING
@p_category_id_param, @p_category_id_param,
@p_group_id_param, @p_group_id_param,
@p_user_id_param, @p_user_id_param,
@p_search_term_param, -- 검색어 NULL 체크용
@p_search_term_param, @p_search_term_param, @p_search_term_param, -- resource 관련 필드 검색
@p_search_term_param, @p_search_term_param, -- user 관련 필드 검색
@p_search_term_param, @p_search_term_param; -- manufacturer, comments 검색
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,115 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_user_audit_logs`(
IN p_search_term VARCHAR(100), -- 검색어 (NULL 가능)
IN p_start_date DATE, -- 시작일 (NULL 가능)
IN p_end_date DATE, -- 종료일 (NULL 가능)
IN p_page_num INT, -- 페이지 번호 (기본값 1)
IN p_page_size INT -- 페이지 크기 (기본값 20)
)
COMMENT '사용자 관련 감사 로그 통합 조회 (검색, 기간, 페이징)'
BEGIN
DECLARE v_offset INT;
SET @v_search_like = NULL; -- 검색어용 세션 변수
-- 입력값 기본 처리
IF p_search_term IS NOT NULL AND p_search_term != '' THEN
SET @v_search_like = CONCAT('%', p_search_term, '%');
END IF;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 20; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
-- 날짜 범위 조건 문자열 동적 생성
SET @v_date_condition = '';
IF p_start_date IS NOT NULL THEN
SET @v_date_condition = CONCAT('AND l.log_date >= DATE(''', p_start_date, ''') ');
END IF;
IF p_end_date IS NOT NULL THEN
SET @v_date_condition = CONCAT(@v_date_condition, 'AND l.log_date < DATE_ADD(DATE(''', p_end_date, '''), INTERVAL 1 DAY) ');
END IF;
-- 검색 조건 문자열 동적 생성 (통합 결과셋 대상)
SET @v_search_condition = '';
IF @v_search_like IS NOT NULL THEN
SET @v_search_condition = CONCAT(
'WHERE (',
' actor_info LIKE @v_search_like ', -- 작업자 정보
' OR CAST(target_id AS CHAR) LIKE @v_search_like ', -- 대상 사용자 ID
' OR target_info_at_log LIKE @v_search_like ', -- 대상 사용자 정보 (이름, 계정)
' OR group_name_at_log LIKE @v_search_like ', -- 대상 부서 이름
' OR details LIKE @v_search_like', -- 상세 내용
') '
);
ELSE
SET @v_search_condition = 'WHERE 1=1 '; -- 검색어 없으면 모든 결과
END IF;
-- 최종 동적 SQL 구성
SET @v_sql = CONCAT('
SELECT SQL_CALC_FOUND_ROWS * FROM (
-- 사용자 추가 로그
SELECT
\'ADD\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.user_id AS target_id,
COALESCE(l.display_name, l.account_name) AS target_info_at_log, -- 추가 시점 정보
g.group_name AS group_name_at_log, -- 추가 시점 그룹 이름
CONCAT(\' : \', COALESCE(l.display_name, \'\'), \' (\', l.account_name, \')\') AS details
FROM log_add_user l
LEFT JOIN auth_user au ON l.admin_user_id = au.id
LEFT JOIN group_info g ON l.group_id = g.group_id
WHERE 1=1 ', @v_date_condition, '
UNION ALL
-- 사용자 수정 로그
SELECT
\'UPDATE\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.user_id AS target_id,
COALESCE(l.new_display_name, l.new_account_name) AS target_info_at_log, -- 수정 후 정보
g_new.group_name AS group_name_at_log, -- 수정 후 그룹 이름
CONCAT(\' : \', COALESCE(l.new_display_name, \'\'), \' (\', l.new_account_name, \'). \',
IF(l.old_display_name <=> l.new_display_name, \'\', CONCAT(\' : \', COALESCE(l.old_display_name, \'\'), \'->\', COALESCE(l.new_display_name, \'\'), \'. \')),
IF(l.old_account_name <=> l.new_account_name, \'\', CONCAT(\' : \', l.old_account_name, \'->\', l.new_account_name, \'. \')),
IF(l.old_group_id <=> l.new_group_id, \'\', CONCAT(\' : \', COALESCE(g_old.group_name, \'\'), \'->\', COALESCE(g_new.group_name, \'\'), \'. \'))
) AS details
FROM log_update_user l
LEFT JOIN auth_user au ON l.admin_user_id = au.id
LEFT JOIN group_info g_old ON l.old_group_id = g_old.group_id -- 변경 전 그룹 조인
LEFT JOIN group_info g_new ON l.new_group_id = g_new.group_id -- 변경 후 그룹 조인
WHERE 1=1 ', @v_date_condition, '
UNION ALL
-- 사용자 삭제 로그
SELECT
\'DELETE\' AS log_type, l.log_id, l.log_date,
COALESCE(au.username, l.actor_description, \'System/Unknown\') AS actor_info,
l.user_id AS target_id,
COALESCE(l.display_name, l.account_name) AS target_info_at_log, -- 삭제 시점 정보
g.group_name AS group_name_at_log, -- 삭제 시점 그룹 이름
CONCAT(\' : \', COALESCE(l.display_name, \'\'), \' (\', l.account_name, \')\') AS details
FROM log_delete_user l
LEFT JOIN auth_user au ON l.admin_user_id = au.id
LEFT JOIN group_info g ON l.group_id = g.group_id
WHERE 1=1 ', @v_date_condition, '
) AS combined_logs
', @v_search_condition, ' -- 최종 검색 조건 적용
ORDER BY log_date DESC
LIMIT ? OFFSET ? -- 페이징 적용
');
-- SQL 문 실행
PREPARE stmt FROM @v_sql;
EXECUTE stmt USING p_page_size, v_offset;
-- 전체 결과 수 계산 값 반환
SELECT FOUND_ROWS() AS total_count;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,24 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_user_by_id`(
IN p_user_id BIGINT
)
COMMENT '사용자 ID로 상세 정보 조회'
BEGIN
SELECT
u.user_id,
u.display_name, -- 컬럼명 변경
u.account_name, -- 컬럼명 변경
u.group_id,
g.group_name
FROM user_info u
LEFT JOIN group_info g ON u.group_id = g.group_id
WHERE u.user_id = p_user_id;
END
$$
DELIMITER ;

View File

@ -0,0 +1,80 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_get_user_list`(
IN p_search_term VARCHAR(100),
IN p_page_num INT,
IN p_page_size INT,
IN p_sort_column VARCHAR(50),
IN p_sort_direction VARCHAR(4),
IN p_group_id BIGINT
)
COMMENT '사용자 목록 조회 (검색, 페이징, 정렬, 필터링, 자산 수 포함)'
BEGIN
DECLARE v_offset INT;
DECLARE v_order_by_clause VARCHAR(255);
DECLARE v_where_clause TEXT;
DECLARE v_sql TEXT;
SET @p_search_like = NULL; -- 세션 변수 사용 유지 (Prepared Statement 제약)
-- 입력값 기본 처리
IF p_search_term IS NOT NULL AND p_search_term != '' THEN SET @p_search_like = CONCAT('%', p_search_term, '%'); END IF;
IF UPPER(p_sort_direction) NOT IN ('ASC', 'DESC') THEN SET p_sort_direction = 'ASC'; END IF;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 20; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
-- 정렬 기준 설정
SET v_order_by_clause = CASE p_sort_column
WHEN 'name' THEN CONCAT('ORDER BY user_display_name ', p_sort_direction)
WHEN 'account' THEN CONCAT('ORDER BY u.account_name ', p_sort_direction) -- 정렬 기준 변경: email -> account
WHEN 'group' THEN CONCAT('ORDER BY g.group_name ', p_sort_direction)
WHEN 'assets' THEN CONCAT('ORDER BY assigned_asset_count ', p_sort_direction)
ELSE 'ORDER BY user_display_name ASC'
END;
IF p_sort_column != 'name' THEN SET v_order_by_clause = CONCAT(v_order_by_clause, ', u.user_id ASC'); END IF;
-- 검색 조건 설정
SET v_where_clause = 'WHERE 1=1 ';
IF @p_search_like IS NOT NULL THEN
SET v_where_clause = CONCAT(v_where_clause, 'AND (u.display_name LIKE @p_search_like OR u.account_name LIKE @p_search_like OR g.group_name LIKE @p_search_like) '); -- 검색 컬럼 변경
END IF;
IF p_group_id IS NOT NULL THEN
SET v_where_clause = CONCAT(v_where_clause, 'AND u.group_id = ? ');
END IF;
-- 동적 SQL 생성
SET v_sql = CONCAT(
'SELECT SQL_CALC_FOUND_ROWS ',
' u.user_id, ',
' CASE WHEN u.display_name IS NOT NULL AND u.display_name != \'\' AND u.account_name IS NOT NULL THEN CONCAT(u.display_name, \' [\', u.account_name, \']\') WHEN u.display_name IS NOT NULL AND u.display_name != \'\' THEN u.display_name ELSE u.account_name END AS user_display_name, ', -- 표시 이름 로직 변경
' u.account_name, ', -- 컬럼명 변경
' g.group_name, ',
' COUNT(r.resource_id) AS assigned_asset_count ',
'FROM user_info u ',
' LEFT JOIN group_info g ON u.group_id = g.group_id ',
' LEFT JOIN resource_info r ON u.user_id = r.user_id ',
v_where_clause,
'GROUP BY u.user_id, u.display_name, u.account_name, g.group_name ', -- GROUP BY 컬럼 변경
v_order_by_clause,
' LIMIT ? OFFSET ?'
);
-- SQL 실행
PREPARE stmt FROM v_sql;
IF p_group_id IS NOT NULL THEN
EXECUTE stmt USING p_group_id, p_page_size, v_offset;
ELSE
EXECUTE stmt USING p_page_size, v_offset;
END IF;
-- 전체 개수 반환
SELECT FOUND_ROWS() AS total_count;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,74 @@
DELIMITER $$
CREATE PROCEDURE `sp_get_user_status_list`(
IN p_search_term VARCHAR(100),
IN p_page_num INT,
IN p_page_size INT,
IN p_sort_column VARCHAR(50),
IN p_sort_direction VARCHAR(4),
IN p_group_id BIGINT
)
BEGIN
DECLARE v_offset INT;
DECLARE v_order_by_clause VARCHAR(255);
DECLARE v_where_clause TEXT;
DECLARE v_sql TEXT;
SET @p_search_like = NULL;
IF p_search_term IS NOT NULL AND p_search_term != '' THEN
SET @p_search_like = CONCAT('%', p_search_term, '%');
END IF;
IF UPPER(p_sort_direction) NOT IN ('ASC', 'DESC') THEN SET p_sort_direction = 'ASC'; END IF;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 20; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
SET v_order_by_clause = CASE p_sort_column
WHEN 'name' THEN CONCAT('ORDER BY user_display_name ', p_sort_direction)
WHEN 'email' THEN CONCAT('ORDER BY u.email_address ', p_sort_direction)
WHEN 'group' THEN CONCAT('ORDER BY g.group_name ', p_sort_direction)
WHEN 'assets' THEN CONCAT('ORDER BY assigned_asset_count ', p_sort_direction)
ELSE 'ORDER BY user_display_name ASC'
END;
IF p_sort_column != 'name' THEN
SET v_order_by_clause = CONCAT(v_order_by_clause, ', u.user_id ASC');
END IF;
SET v_where_clause = 'WHERE 1=1 ';
IF @p_search_like IS NOT NULL THEN
SET v_where_clause = CONCAT(v_where_clause, 'AND (u.user_name LIKE @p_search_like OR u.email_address LIKE @p_search_like OR g.group_name LIKE @p_search_like) ');
END IF;
IF p_group_id IS NOT NULL THEN
SET v_where_clause = CONCAT(v_where_clause, 'AND u.group_id = ? ');
END IF;
SET v_sql = CONCAT(
'SELECT SQL_CALC_FOUND_ROWS ',
' u.user_id, ',
' CASE WHEN u.user_name IS NOT NULL AND u.email_address IS NOT NULL THEN CONCAT(u.user_name, \' [\', LOWER(SUBSTRING_INDEX(u.email_address, \'@\', 1)), \']\') WHEN u.user_name IS NOT NULL THEN u.user_name ELSE u.email_address END AS user_display_name, ',
' u.email_address, ',
' g.group_name, ',
' COUNT(r.resource_id) AS assigned_asset_count ',
'FROM user_info u ',
' LEFT JOIN group_info g ON u.group_id = g.group_id ',
' LEFT JOIN resource_info r ON u.user_id = r.user_id ',
v_where_clause,
'GROUP BY u.user_id, u.user_name, u.email_address, g.group_name ',
v_order_by_clause,
' LIMIT ? OFFSET ?'
);
PREPARE stmt FROM v_sql;
IF p_group_id IS NOT NULL THEN
EXECUTE stmt USING p_group_id, p_page_size, v_offset;
ELSE
EXECUTE stmt USING p_page_size, v_offset;
END IF;
SELECT FOUND_ROWS() AS total_count;
DEALLOCATE PREPARE stmt;
END
$$
DELIMITER ;

View File

@ -0,0 +1,43 @@
DELIMITER $$
CREATE PROCEDURE `sp_search_users_for_autocomplete_paged`(
IN p_search_term VARCHAR(255),
IN p_page_num INT,
IN p_page_size INT,
IN p_total_count_limit INT -- FOUND_ROWS() 계산 시 과도한 스캔 방지용 (선택적)
)
BEGIN
DECLARE v_offset INT;
IF p_page_num IS NULL OR p_page_num < 1 THEN SET p_page_num = 1; END IF;
IF p_page_size IS NULL OR p_page_size < 1 THEN SET p_page_size = 10; END IF;
SET v_offset = (p_page_num - 1) * p_page_size;
-- 실제 데이터 조회 (페이지네이션 적용)
SELECT SQL_CALC_FOUND_ROWS DISTINCT -- DISTINCT 유지, SQL_CALC_FOUND_ROWS 추가
user_id,
CASE
WHEN display_name IS NOT NULL AND display_name != '' AND account_name IS NOT NULL THEN CONCAT(display_name, ' [', account_name, ']')
WHEN display_name IS NOT NULL AND display_name != '' THEN display_name
ELSE account_name
END AS user_display_name
FROM user_info
WHERE
(p_search_term IS NULL OR p_search_term = '' OR
LOWER(display_name) LIKE CONCAT('%', LOWER(p_search_term), '%') OR
LOWER(account_name) LIKE CONCAT('%', LOWER(p_search_term), '%'))
ORDER BY user_display_name
LIMIT v_offset, p_page_size; -- OFFSET, LIMIT 순서 주의
-- 전체 결과 수 조회 (LIMIT 절에 의해 영향받지 않음)
-- p_total_count_limit 값은 이 SELECT 문의 LIMIT 과는 별개로,
-- FOUND_ROWS()가 너무 큰 테이블 전체를 스캔하는 것을 방지하기 위한 최적화 기법으로 사용될 수 있으나,
-- MySQL/MariaDB 에서 FOUND_ROWS()는 이전 SELECT 문의 LIMIT을 무시하고 실제 필터링된 전체 행 수를 계산합니다.
-- 따라서 p_total_count_limit 파라미터는 여기서는 직접적인 용도가 없을 수 있습니다.
-- 만약 필요하다면, 별도의 COUNT(*) 쿼리를 조건부로 실행하는 등의 로직을 추가할 수 있습니다.
SELECT FOUND_ROWS() AS total_count;
END
$$
DELIMITER ;

View File

@ -0,0 +1,131 @@
DELIMITER $$
CREATE PROCEDURE `sp_sync_resource_info_from_scan`( -- 새 이름으로 생성
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_user_account_name VARCHAR(255), -- 사용자 계정명
IN p_category VARCHAR(100), -- 스캔된 카테고리명
IN p_manufacturer VARCHAR(100), -- 스캔된 제조사
IN p_resource_name VARCHAR(100), -- 스캔된 제품명
IN p_serial_num VARCHAR(200), -- 스캔된 시리얼 번호
IN p_spec_value VARCHAR(255), -- 스캔된 사양 값 (문자열)
IN p_spec_unit VARCHAR(10), -- 스캔된 사양 단위 (문자열)
IN p_detected_by VARCHAR(50), -- 스캔 도구 정보 등 (현재 로직 미사용)
IN p_change_type TINYINT, -- 1: ADD(추가/할당), 2: DELETE(할당 해제)
OUT p_result_message VARCHAR(255)
)
COMMENT '스캔 정보 기반 자산 정보 동기화(추가/할당/해제) 및 로그 (Rust 연동용)'
BEGIN
DECLARE v_user_id BIGINT DEFAULT NULL;
DECLARE v_category_id TINYINT UNSIGNED;
DECLARE v_spec_unit_id TINYINT UNSIGNED DEFAULT NULL;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE v_existing_resource_id BIGINT;
DECLARE v_common_log VARCHAR(255);
DECLARE v_new_spec_value DECIMAL(10, 2) DEFAULT NULL;
DECLARE v_comments_to_set VARCHAR(200) DEFAULT NULL;
DECLARE v_existing_user_id BIGINT; -- 기존 자산의 할당 사용자 ID
DECLARE v_is_locked BOOLEAN DEFAULT FALSE;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @errno = MYSQL_ERRNO, @sqlstate = RETURNED_SQLSTATE, @text = MESSAGE_TEXT;
ROLLBACK; SET p_result_message = CONCAT('처리 중 오류 발생 (', @errno, '/', @sqlstate, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_result_message = '작업 주체 정보(관리자 ID 또는 프로세스 설명)는 필수입니다.';
ELSE
-- 트랜잭션 시작
START TRANSACTION;
SET p_result_message = NULL;
-- 카테고리/단위 ID 매핑
IF p_category = 'VGA' THEN
SET p_category = 'GPU';
END IF;
SELECT category_id INTO v_category_id FROM resource_category WHERE category_name = p_category LIMIT 1;
IF v_category_id IS NULL THEN
SET v_category_id = 0; -- 기본값 0 또는 다른 처리
SET p_result_message = CONCAT('주의: 알 수 없는 카테고리(', p_category, ')가 ID 0으로 처리됨. ');
END IF;
SET v_spec_unit_id = CASE LOWER(TRIM(p_spec_unit)) WHEN 'mhz' THEN 1 WHEN 'mb' THEN 2 WHEN 'gb' THEN 3 WHEN 'tb' THEN 4 WHEN 'pb' THEN 5 WHEN 'inch' THEN 6 ELSE NULL END;
-- 사용자 ID 조회
SELECT user_id INTO v_user_id FROM user_info WHERE LOWER(account_name) = LOWER(p_user_account_name) LIMIT 1;
SET v_common_log = CONCAT(p_user_account_name, ' - ', p_category, ' (SN:', IFNULL(p_serial_num, 'N/A'), ')');
-- 스펙 값 처리
IF p_change_type = 1 AND p_spec_value IS NOT NULL AND p_spec_value != 'N/A' THEN
IF p_spec_value REGEXP '^[0-9]+([.][0-9]+)?$' THEN SET v_new_spec_value = CAST(p_spec_value AS DECIMAL(10, 2));
ELSE SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '주의: Spec 값 "', p_spec_value, '"는 유효 숫자가 아님. '); END IF;
END IF;
-- === 변경 타입 분기 ===
IF p_change_type = 1 THEN -- ADD (자산 추가 또는 사용자 할당)
IF p_serial_num IS NULL OR p_serial_num = '' THEN
ROLLBACK; SET p_result_message = CONCAT(IFNULL(p_result_message,''), '추가/할당 실패: 시리얼 번호는 필수입니다. ', v_common_log);
ELSE
-- 시리얼 번호로 기존 자산 조회
SELECT resource_id, user_id INTO v_existing_resource_id, v_existing_user_id FROM resource_info WHERE serial_num = p_serial_num LIMIT 1;
IF v_existing_resource_id IS NOT NULL THEN -- 자산 존재
IF v_is_locked = TRUE THEN -- ★★★ 자산이 잠겨있는 경우 ★★★
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '자산이 잠겨있어 스캔 정보로 업데이트하지 않음: ', v_common_log);
ELSE
IF v_existing_user_id IS NULL AND v_user_id IS NOT NULL THEN -- 미할당 자산 -> 사용자 할당
UPDATE resource_info SET user_id = v_user_id, update_date = v_now WHERE resource_id = v_existing_resource_id;
INSERT INTO log_update_resource (log_date, admin_user_id, actor_description, resource_id, user_id) VALUES (v_now, p_admin_user_id, p_actor_description, v_existing_resource_id, v_user_id);
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '기존 미할당 자산에 사용자 할당 완료: ', v_common_log);
COMMIT;
ELSEIF v_existing_user_id = v_user_id THEN -- 이미 해당 사용자에게 할당됨
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '이미 사용자에게 할당된 동일 자산: ', v_common_log); COMMIT;
ELSE -- 다른 사용자 할당 or 중복 추가 시도
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '이미 등록된 시리얼 번호 (다른 사용자 또는 중복): ', v_common_log); COMMIT;
END IF;
END IF;
ELSE -- 자산 미존재 (신규 추가)
IF v_category_id = 0 THEN -- 유효하지 않은 카테고리 (선택적)
ROLLBACK; SET p_result_message = CONCAT(IFNULL(p_result_message,''), '추가 실패: 유효한 카테고리 정보가 필요합니다.');
ELSE
IF v_user_id IS NULL THEN SET v_comments_to_set = CONCAT('Detected from Host: ', p_user_account_name); END IF;
INSERT INTO resource_info (category_id, manufacturer, resource_name, serial_num, spec_value, spec_unit, user_id, comments, register_date, is_locked) VALUES (v_category_id, p_manufacturer, p_resource_name, p_serial_num, v_new_spec_value, v_spec_unit_id, v_user_id, v_comments_to_set, v_now, FALSE);
SET v_existing_resource_id = LAST_INSERT_ID();
INSERT INTO log_add_resource (log_date, admin_user_id, actor_description, resource_id, category_id, resource_code, manufacturer, resource_name, serial_num, spec_value, spec_unit, user_id, comments, purchase_date, register_date) SELECT v_now, p_admin_user_id, p_actor_description, r.resource_id, r.category_id, r.resource_code, r.manufacturer, r.resource_name, r.serial_num, r.spec_value, r.spec_unit, r.user_id, r.comments, r.purchase_date, r.register_date FROM resource_info r WHERE r.resource_id = v_existing_resource_id;
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '신규 등록 완료: ', v_common_log);
COMMIT;
END IF; -- 카테고리 유효성 IF 종료
END IF; -- 자산 존재 IF 종료
END IF; -- 시리얼 번호 유효성 IF 종료
ELSEIF p_change_type = 2 THEN -- DELETE (사용자 할당 해제)
IF v_user_id IS NULL THEN
ROLLBACK; SET p_result_message = CONCAT(IFNULL(p_result_message,''), '할당 해제 실패: 기준 사용자 ID를 찾을 수 없습니다. (', p_user_account_name, ')');
ELSEIF p_serial_num IS NULL OR p_serial_num = '' THEN
ROLLBACK; SET p_result_message = CONCAT(IFNULL(p_result_message,''), '할당 해제 실패: 기준 시리얼 번호가 없습니다. ', v_common_log);
ELSE
SELECT resource_id, is_locked INTO v_existing_resource_id, v_is_locked FROM resource_info WHERE user_id = v_user_id AND serial_num = p_serial_num LIMIT 1;
IF v_existing_resource_id IS NULL THEN
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '할당 해제 대상 없음 (사용자 + 시리얼 기준). ', v_common_log); COMMIT;
ELSEIF v_is_locked = TRUE THEN
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '자산이 잠겨있어 자동 할당 해제하지 않음: ', v_common_log); COMMIT;
ELSE
UPDATE resource_info SET user_id = NULL, update_date = v_now WHERE resource_id = v_existing_resource_id;
INSERT INTO log_update_resource (log_date, admin_user_id, actor_description, resource_id, user_id) VALUES (v_now, p_admin_user_id, p_actor_description, v_existing_resource_id, NULL);
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '사용자 할당 해제 완료: ', v_common_log);
COMMIT;
END IF; -- 할당 해제 대상 존재 IF 종료
END IF; -- 파라미터 유효성 IF 종료
ELSE -- 알 수 없는 타입
SET p_result_message = CONCAT(IFNULL(p_result_message, ''), '알 수 없는 작업 타입: ', p_change_type); COMMIT;
END IF; -- 변경 타입 IF 종료
END IF; -- 작업 주체 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,56 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_update_category_name`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_category_id TINYINT UNSIGNED,
IN p_new_category_name VARCHAR(40),
OUT p_result_message VARCHAR(255)
)
COMMENT '카테고리 이름 수정 및 로그 기록'
BEGIN
DECLARE v_old_category_name VARCHAR(40);
DECLARE v_existing_cat_id TINYINT UNSIGNED DEFAULT NULL;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK; SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_result_message = '작업 주체 정보는 필수입니다.';
ELSEIF p_new_category_name IS NULL OR p_new_category_name = '' THEN
SET p_result_message = '카테고리 이름은 필수입니다.';
ELSE
-- 기존 정보 조회 및 존재 확인
SELECT category_name INTO v_old_category_name FROM resource_category WHERE category_id = p_category_id;
IF v_old_category_name IS NULL THEN
SET p_result_message = CONCAT('수정할 카테고리를 찾을 수 없습니다 (ID: ', p_category_id, ')');
ELSE
-- 카테고리 이름 중복 검사 (자기 자신 제외)
SELECT category_id INTO v_existing_cat_id FROM resource_category WHERE LOWER(category_name) = LOWER(p_new_category_name) AND category_id != p_category_id LIMIT 1;
IF v_existing_cat_id IS NOT NULL THEN
SET p_result_message = CONCAT('이미 사용 중인 카테고리 이름입니다: ', p_new_category_name);
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
UPDATE resource_category SET category_name = p_new_category_name WHERE category_id = p_category_id;
INSERT INTO log_update_category (log_date, admin_user_id, actor_description, category_id, old_category_name, new_category_name)
VALUES (v_now, p_admin_user_id, p_actor_description, p_category_id, v_old_category_name, p_new_category_name);
COMMIT;
SET p_result_message = CONCAT('카테고리 (ID: ', p_category_id, ') 이름 수정 완료.');
END IF; -- 이름 중복 IF 종료
END IF; -- 카테고리 존재 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,68 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_update_group`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_group_id BIGINT,
IN p_group_name VARCHAR(100),
IN p_manager_user_id BIGINT, -- 파라미터명 변경됨
OUT p_result_message VARCHAR(255)
)
COMMENT '그룹(부서) 정보 수정 및 로그 기록'
BEGIN
DECLARE v_old_group_name VARCHAR(100);
DECLARE v_old_manager_user_id BIGINT; -- 변수명 변경됨
DECLARE v_existing_group_id BIGINT DEFAULT NULL;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK; SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_result_message = '작업 주체 정보는 필수입니다.';
ELSEIF p_group_name IS NULL OR p_group_name = '' THEN
SET p_result_message = '그룹(부서) 이름은 필수입니다.';
ELSE
-- 기존 정보 조회 및 존재 확인
SELECT group_name, manager_user_id INTO v_old_group_name, v_old_manager_user_id -- 컬럼명/변수명 변경
FROM group_info WHERE group_id = p_group_id;
IF v_old_group_name IS NULL THEN
SET p_result_message = CONCAT('수정할 그룹(부서)을 찾을 수 없습니다 (ID: ', p_group_id, ')');
ELSE
-- 그룹 이름 중복 검사 (자기 자신 제외)
SELECT group_id INTO v_existing_group_id
FROM group_info WHERE LOWER(group_name) = LOWER(p_group_name) AND group_id != p_group_id LIMIT 1;
IF v_existing_group_id IS NOT NULL THEN
SET p_result_message = CONCAT('이미 다른 그룹(부서)에서 사용 중인 이름입니다: ', p_group_name);
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
UPDATE group_info SET
group_name = p_group_name,
manager_user_id = p_manager_user_id -- 컬럼명/파라미터명 변경
WHERE group_id = p_group_id;
INSERT INTO log_update_group (log_date, admin_user_id, actor_description, group_id,
old_group_name, old_manager_user_id, -- 컬럼명 변경
new_group_name, new_manager_user_id) -- 컬럼명 변경
VALUES (v_now, p_admin_user_id, p_actor_description, p_group_id,
v_old_group_name, v_old_manager_user_id, -- 변수명 변경
p_group_name, p_manager_user_id); -- 파라미터명 변경
COMMIT;
SET p_result_message = CONCAT('그룹(부서) (ID: ', p_group_id, ') 정보 수정 완료.');
END IF; -- 그룹 이름 중복 IF 종료
END IF; -- 그룹 존재 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

View File

@ -0,0 +1,67 @@
DELIMITER $$
CREATE PROCEDURE `sp_update_resource`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_resource_id BIGINT,
IN p_category_id TINYINT UNSIGNED,
IN p_resource_code VARCHAR(100),
IN p_manufacturer VARCHAR(100),
IN p_resource_name VARCHAR(100),
IN p_serial_num VARCHAR(200),
IN p_spec_value DECIMAL(10, 2),
IN p_spec_unit TINYINT UNSIGNED,
IN p_user_id BIGINT,
IN p_comments VARCHAR(200),
IN p_purchase_date DATE,
IN p_is_locked BOOLEAN
)
COMMENT '자산 정보 수정 및 로그 기록'
BEGIN
-- DECLARE v_original_create_date DATETIME; -- register_date로 대체
DECLARE v_now DATETIME DEFAULT NOW();
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '작업 주체 정보(관리자 ID 또는 프로세스 설명)는 필수입니다.';
END IF;
IF p_resource_name IS NULL OR p_resource_name = '' THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '제품명은 필수입니다.';
END IF;
IF p_serial_num IS NOT NULL AND p_serial_num != '' AND EXISTS (SELECT 1 FROM resource_info WHERE serial_num = p_serial_num AND resource_id != p_resource_id) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '이미 다른 자산에서 사용 중인 시리얼 번호입니다.';
END IF;
-- 트랜잭션 시작
START TRANSACTION;
-- 자산 정보 업데이트 (update_date는 자동 업데이트)
UPDATE resource_info SET
category_id = p_category_id,
resource_code = p_resource_code,
manufacturer = p_manufacturer,
resource_name = p_resource_name,
serial_num = p_serial_num,
spec_value = p_spec_value,
spec_unit = p_spec_unit,
user_id = p_user_id,
comments = p_comments,
purchase_date = p_purchase_date,
is_locked = p_is_locked
-- register_date는 수정하지 않음
WHERE resource_id = p_resource_id;
-- 로그 기록 (변경 후 정보만 기록)
INSERT INTO log_update_resource (
log_date, admin_user_id, actor_description, resource_id, category_id, resource_code,
manufacturer, resource_name, serial_num, spec_value, spec_unit, user_id, comments,
purchase_date -- 컬럼명 변경 반영
) VALUES (
v_now, p_admin_user_id, p_actor_description, p_resource_id, p_category_id, p_resource_code,
p_manufacturer, p_resource_name, p_serial_num, p_spec_value, p_spec_unit, p_user_id, p_comments,
p_purchase_date -- 컬럼명 변경 반영
);
COMMIT;
END
$$
DELIMITER ;

View File

@ -0,0 +1,75 @@
DELIMITER $$
SET @saved_sql_mode = @@sql_mode
$$
SET @@sql_mode = 'NO_AUTO_VALUE_ON_ZERO'
$$
CREATE PROCEDURE `sp_update_user`(
IN p_admin_user_id INT,
IN p_actor_description VARCHAR(100),
IN p_user_id BIGINT,
IN p_display_name VARCHAR(100), -- 파라미터명 변경
IN p_account_name VARCHAR(255), -- 파라미터명 변경
IN p_group_id BIGINT,
OUT p_result_message VARCHAR(255)
)
COMMENT '사용자 정보 수정 및 로그 기록'
BEGIN
DECLARE v_old_display_name VARCHAR(100);
DECLARE v_old_account_name VARCHAR(255);
DECLARE v_old_group_id BIGINT;
DECLARE v_existing_user_id BIGINT DEFAULT NULL;
DECLARE v_now DATETIME DEFAULT NOW();
DECLARE EXIT HANDLER FOR SQLEXCEPTION
BEGIN
GET DIAGNOSTICS CONDITION 1 @sqlstate = RETURNED_SQLSTATE, @errno = MYSQL_ERRNO, @text = MESSAGE_TEXT;
ROLLBACK; SET p_result_message = CONCAT('DB 오류 (', @errno, '): ', @text);
END;
-- 입력값 검증
IF p_admin_user_id IS NULL AND p_actor_description IS NULL THEN
SET p_result_message = '작업 주체 정보는 필수입니다.';
-- RETURN; -- ★ 제거
ELSEIF p_account_name IS NULL OR p_account_name = '' THEN
SET p_result_message = '계정 이름은 필수입니다.';
-- RETURN; -- ★ 제거
ELSE
-- 기존 정보 조회 및 존재 확인
SELECT display_name, account_name, group_id INTO v_old_display_name, v_old_account_name, v_old_group_id
FROM user_info WHERE user_id = p_user_id;
IF v_old_account_name IS NULL THEN
SET p_result_message = CONCAT('수정할 사용자를 찾을 수 없습니다 (ID: ', p_user_id, ')');
-- RETURN; -- ★ 제거
ELSE
-- 계정 이름 중복 검사 (자기 자신 제외)
SELECT user_id INTO v_existing_user_id
FROM user_info WHERE LOWER(account_name) = LOWER(p_account_name) AND user_id != p_user_id LIMIT 1;
IF v_existing_user_id IS NOT NULL THEN
SET p_result_message = CONCAT('이미 다른 사용자가 사용 중인 계정 이름입니다: ', p_account_name);
-- RETURN; -- ★ 제거
ELSE
-- 모든 검증 통과, 트랜잭션 시작
START TRANSACTION;
UPDATE user_info SET
display_name = p_display_name,
account_name = p_account_name,
group_id = p_group_id
WHERE user_id = p_user_id;
INSERT INTO log_update_user (log_date, admin_user_id, actor_description, user_id,
old_display_name, old_account_name, old_group_id,
new_display_name, new_account_name, new_group_id)
VALUES (v_now, p_admin_user_id, p_actor_description, p_user_id,
v_old_display_name, v_old_account_name, v_old_group_id,
p_display_name, p_account_name, p_group_id);
COMMIT;
SET p_result_message = CONCAT('사용자 (ID: ', p_user_id, ') 정보 수정 완료.');
END IF; -- 계정 중복 IF 종료
END IF; -- 사용자 존재 IF 종료
END IF; -- 입력값 검증 IF 종료
END
$$
DELIMITER ;

14
db/schema/auth_group.sql Normal file
View File

@ -0,0 +1,14 @@
CREATE TABLE `auth_group` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(150) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 4,
AVG_ROW_LENGTH = 8192,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `auth_group`
ADD UNIQUE INDEX name(name);

View File

@ -0,0 +1,21 @@
CREATE TABLE `auth_group_permissions` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`group_id` INT(11) NOT NULL,
`permission_id` INT(11) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `auth_group_permissions`
ADD UNIQUE INDEX auth_group_permissions_group_id_permission_id_0cd325b0_uniq(group_id, permission_id);
ALTER TABLE `auth_group_permissions`
ADD CONSTRAINT `auth_group_permissio_permission_id_84c5c92e_fk_auth_perm` FOREIGN KEY (permission_id)
REFERENCES auth_permission(id);
ALTER TABLE `auth_group_permissions`
ADD CONSTRAINT `auth_group_permissions_group_id_b120cbf9_fk_auth_group_id` FOREIGN KEY (group_id)
REFERENCES auth_group(id);

View File

@ -0,0 +1,20 @@
CREATE TABLE `auth_permission` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NOT NULL,
`content_type_id` INT(11) NOT NULL,
`codename` VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 41,
AVG_ROW_LENGTH = 409,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `auth_permission`
ADD UNIQUE INDEX auth_permission_content_type_id_codename_01ab375a_uniq(content_type_id, codename);
ALTER TABLE `auth_permission`
ADD CONSTRAINT `auth_permission_content_type_id_2f476e4b_fk_django_co` FOREIGN KEY (content_type_id)
REFERENCES django_content_type(id);

23
db/schema/auth_user.sql Normal file
View File

@ -0,0 +1,23 @@
CREATE TABLE `auth_user` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`password` VARCHAR(128) NOT NULL,
`last_login` DATETIME(6) DEFAULT NULL,
`is_superuser` TINYINT(1) NOT NULL,
`username` VARCHAR(150) NOT NULL,
`first_name` VARCHAR(150) NOT NULL,
`last_name` VARCHAR(150) NOT NULL,
`email` VARCHAR(254) NOT NULL,
`is_staff` TINYINT(1) NOT NULL,
`is_active` TINYINT(1) NOT NULL,
`date_joined` DATETIME(6) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 20,
AVG_ROW_LENGTH = 4096,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `auth_user`
ADD UNIQUE INDEX username(username);

View File

@ -0,0 +1,21 @@
CREATE TABLE `auth_user_groups` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`user_id` INT(11) NOT NULL,
`group_id` INT(11) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `auth_user_groups`
ADD UNIQUE INDEX auth_user_groups_user_id_group_id_94350c0c_uniq(user_id, group_id);
ALTER TABLE `auth_user_groups`
ADD CONSTRAINT `auth_user_groups_group_id_97559544_fk_auth_group_id` FOREIGN KEY (group_id)
REFERENCES auth_group(id);
ALTER TABLE `auth_user_groups`
ADD CONSTRAINT `auth_user_groups_user_id_6a12ed8b_fk_auth_user_id` FOREIGN KEY (user_id)
REFERENCES auth_user(id);

View File

@ -0,0 +1,21 @@
CREATE TABLE `auth_user_user_permissions` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`user_id` INT(11) NOT NULL,
`permission_id` INT(11) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `auth_user_user_permissions`
ADD UNIQUE INDEX auth_user_user_permissions_user_id_permission_id_14a6b632_uniq(user_id, permission_id);
ALTER TABLE `auth_user_user_permissions`
ADD CONSTRAINT `auth_user_user_permi_permission_id_1fbb5f2c_fk_auth_perm` FOREIGN KEY (permission_id)
REFERENCES auth_permission(id);
ALTER TABLE `auth_user_user_permissions`
ADD CONSTRAINT `auth_user_user_permissions_user_id_a95ead1b_fk_auth_user_id` FOREIGN KEY (user_id)
REFERENCES auth_user(id);

View File

@ -0,0 +1,25 @@
CREATE TABLE `django_admin_log` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`action_time` DATETIME(6) NOT NULL,
`object_id` LONGTEXT DEFAULT NULL,
`object_repr` VARCHAR(200) NOT NULL,
`action_flag` SMALLINT(5) UNSIGNED NOT NULL CHECK (`action_flag` >= 0),
`change_message` LONGTEXT NOT NULL,
`content_type_id` INT(11) DEFAULT NULL,
`user_id` INT(11) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 22,
AVG_ROW_LENGTH = 819,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `django_admin_log`
ADD CONSTRAINT `django_admin_log_content_type_id_c4bce8eb_fk_django_co` FOREIGN KEY (content_type_id)
REFERENCES django_content_type(id);
ALTER TABLE `django_admin_log`
ADD CONSTRAINT `django_admin_log_user_id_c564eba6_fk_auth_user_id` FOREIGN KEY (user_id)
REFERENCES auth_user(id);

View File

@ -0,0 +1,15 @@
CREATE TABLE `django_content_type` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`app_label` VARCHAR(100) NOT NULL,
`model` VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 12,
AVG_ROW_LENGTH = 2978,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `django_content_type`
ADD UNIQUE INDEX django_content_type_app_label_model_76bd3d3b_uniq(app_label, model);

View File

@ -0,0 +1,13 @@
CREATE TABLE `django_migrations` (
`id` BIGINT(20) NOT NULL AUTO_INCREMENT,
`app` VARCHAR(255) NOT NULL,
`name` VARCHAR(255) NOT NULL,
`applied` DATETIME(6) NOT NULL,
PRIMARY KEY (id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 20,
AVG_ROW_LENGTH = 862,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;

View File

@ -0,0 +1,14 @@
CREATE TABLE `django_session` (
`session_key` VARCHAR(40) NOT NULL,
`session_data` LONGTEXT NOT NULL,
`expire_date` DATETIME(6) NOT NULL,
PRIMARY KEY (session_key)
)
ENGINE = INNODB,
AVG_ROW_LENGTH = 390,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
ROW_FORMAT = DYNAMIC;
ALTER TABLE `django_session`
ADD INDEX django_session_expire_date_a5c62663(expire_date);

20
db/schema/group_info.sql Normal file
View File

@ -0,0 +1,20 @@
CREATE TABLE `group_info` (
`group_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '그룹 고유 ID (PK)',
`group_name` VARCHAR(100) NOT NULL COMMENT '그룹(부서) 이름 (UNIQUE)',
`manager_user_id` BIGINT(20) DEFAULT NULL COMMENT '그룹 관리자 사용자 ID (FK, user_info.user_id)',
PRIMARY KEY (group_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 8,
AVG_ROW_LENGTH = 2730,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '그룹(부서) 정보',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `group_info`
ADD UNIQUE INDEX uix_group_name(group_name) COMMENT '그룹 이름은 고유해야 함';
ALTER TABLE `group_info`
ADD CONSTRAINT `fk_group_manager` FOREIGN KEY (manager_user_id)
REFERENCES user_info(user_id) ON DELETE SET NULL ON UPDATE CASCADE;

View File

@ -0,0 +1,19 @@
CREATE TABLE `log_add_category` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`category_id` TINYINT(3) UNSIGNED NOT NULL COMMENT '추가된 카테고리 ID',
`category_name` VARCHAR(40) NOT NULL COMMENT '추가된 카테고리 이름',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 5,
AVG_ROW_LENGTH = 4096,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '자산 카테고리 추가 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_add_category`
ADD CONSTRAINT `chk_log_add_cat_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,19 @@
CREATE TABLE `log_add_group` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`group_id` BIGINT(20) NOT NULL COMMENT '추가된 그룹 ID',
`group_name` VARCHAR(100) NOT NULL COMMENT '추가된 그룹 이름',
`manager_user_id` BIGINT(20) DEFAULT NULL COMMENT '추가된 그룹 관리자 ID',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 2,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '그룹(부서) 추가 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_add_group`
ADD CONSTRAINT `chk_log_add_group_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,29 @@
CREATE TABLE `log_add_resource` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`resource_id` BIGINT(20) NOT NULL COMMENT '추가된 자산 ID',
`category_id` TINYINT(3) UNSIGNED NOT NULL COMMENT '카테고리 ID',
`resource_code` VARCHAR(100) DEFAULT NULL COMMENT '관리 코드',
`manufacturer` VARCHAR(100) DEFAULT NULL COMMENT '제조사',
`resource_name` VARCHAR(100) NOT NULL COMMENT '제품명',
`serial_num` VARCHAR(200) DEFAULT NULL COMMENT '시리얼 번호',
`spec_value` DECIMAL(10, 2) DEFAULT NULL COMMENT '사양 값',
`spec_unit` TINYINT(3) UNSIGNED DEFAULT NULL COMMENT '사양 단위 ID',
`user_id` BIGINT(20) DEFAULT NULL COMMENT '할당 사용자 ID',
`comments` VARCHAR(200) DEFAULT NULL COMMENT '비고',
`purchase_date` DATE DEFAULT NULL COMMENT '구매 일자',
`register_date` DATETIME NOT NULL COMMENT '시스템 등록 일시',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 503,
AVG_ROW_LENGTH = 228,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '자산 추가 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_add_resource`
ADD CONSTRAINT `chk_log_add_resource_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,19 @@
CREATE TABLE `log_add_user` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`user_id` BIGINT(20) NOT NULL COMMENT '추가된 사용자 ID',
`display_name` VARCHAR(100) DEFAULT NULL COMMENT '추가된 표시 이름',
`account_name` VARCHAR(255) NOT NULL COMMENT '추가된 계정 이름',
`group_id` BIGINT(20) DEFAULT NULL COMMENT '추가된 그룹 ID',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '사용자 추가 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_add_user`
ADD CONSTRAINT `chk_log_add_user_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,19 @@
CREATE TABLE `log_delete_category` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`category_id` TINYINT(3) UNSIGNED NOT NULL COMMENT '삭제된 카테고리 ID',
`category_name` VARCHAR(40) NOT NULL COMMENT '삭제 시점 카테고리 이름',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 4,
AVG_ROW_LENGTH = 8192,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '자산 카테고리 삭제 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_delete_category`
ADD CONSTRAINT `chk_log_delete_cat_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,19 @@
CREATE TABLE `log_delete_group` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`group_id` BIGINT(20) NOT NULL COMMENT '삭제된 그룹 ID',
`group_name` VARCHAR(100) NOT NULL COMMENT '삭제 시점 그룹 이름',
`manager_user_id` BIGINT(20) DEFAULT NULL COMMENT '삭제 시점 관리자 ID',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 2,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '그룹(부서) 삭제 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_delete_group`
ADD CONSTRAINT `chk_log_delete_group_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,29 @@
CREATE TABLE `log_delete_resource` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`resource_id` BIGINT(20) NOT NULL COMMENT '삭제된 자산 ID',
`category_id` TINYINT(3) UNSIGNED NOT NULL COMMENT '삭제 시점 카테고리 ID',
`resource_code` VARCHAR(100) DEFAULT NULL COMMENT '삭제 시점 관리 코드',
`manufacturer` VARCHAR(100) DEFAULT NULL COMMENT '삭제 시점 제조사',
`resource_name` VARCHAR(100) NOT NULL COMMENT '삭제 시점 제품명',
`serial_num` VARCHAR(200) DEFAULT NULL COMMENT '삭제 시점 시리얼 번호',
`spec_value` DECIMAL(10, 2) DEFAULT NULL COMMENT '삭제 시점 사양 값',
`spec_unit` TINYINT(3) UNSIGNED DEFAULT NULL COMMENT '삭제 시점 사양 단위 ID',
`user_id` BIGINT(20) DEFAULT NULL COMMENT '삭제 시점 사용자 ID',
`comments` VARCHAR(200) DEFAULT NULL COMMENT '삭제 시점 비고',
`purchase_date` DATE DEFAULT NULL COMMENT '삭제 시점 구매 일자',
`register_date` DATETIME NOT NULL COMMENT '삭제 시점 시스템 등록 일시',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 5,
AVG_ROW_LENGTH = 4096,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '자산 삭제 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_delete_resource`
ADD CONSTRAINT `chk_log_delete_resource_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,19 @@
CREATE TABLE `log_delete_user` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`user_id` BIGINT(20) NOT NULL COMMENT '삭제된 사용자 ID',
`display_name` VARCHAR(100) DEFAULT NULL COMMENT '삭제 시점 표시 이름',
`account_name` VARCHAR(255) NOT NULL COMMENT '삭제 시점 계정 이름',
`group_id` BIGINT(20) DEFAULT NULL COMMENT '삭제 시점 그룹 ID',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '사용자 삭제 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_delete_user`
ADD CONSTRAINT `chk_log_delete_user_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,20 @@
CREATE TABLE `log_update_category` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`category_id` TINYINT(3) UNSIGNED NOT NULL COMMENT '수정된 카테고리 ID',
`old_category_name` VARCHAR(40) DEFAULT NULL COMMENT '변경 전 카테고리 이름',
`new_category_name` VARCHAR(40) NOT NULL COMMENT '변경 후 카테고리 이름',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 2,
AVG_ROW_LENGTH = 16384,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '자산 카테고리 수정 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_update_category`
ADD CONSTRAINT `chk_log_update_cat_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,20 @@
CREATE TABLE `log_update_group` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`group_id` BIGINT(20) NOT NULL COMMENT '수정된 그룹 ID',
`old_group_name` VARCHAR(100) DEFAULT NULL COMMENT '변경 전 그룹 이름',
`old_manager_user_id` BIGINT(20) DEFAULT NULL COMMENT '변경 전 관리자 ID',
`new_group_name` VARCHAR(100) NOT NULL COMMENT '변경 후 그룹 이름',
`new_manager_user_id` BIGINT(20) DEFAULT NULL COMMENT '변경 후 관리자 ID',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '그룹(부서) 정보 수정 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_update_group`
ADD CONSTRAINT `chk_log_update_group_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,28 @@
CREATE TABLE `log_update_resource` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`resource_id` BIGINT(20) NOT NULL COMMENT '수정된 자산 ID',
`category_id` TINYINT(3) UNSIGNED DEFAULT NULL COMMENT '변경 후 카테고리 ID',
`resource_code` VARCHAR(100) DEFAULT NULL COMMENT '변경 후 관리 코드',
`manufacturer` VARCHAR(100) DEFAULT NULL COMMENT '변경 후 제조사',
`resource_name` VARCHAR(100) DEFAULT NULL COMMENT '변경 후 제품명',
`serial_num` VARCHAR(200) DEFAULT NULL COMMENT '변경 후 시리얼 번호',
`spec_value` DECIMAL(10, 2) DEFAULT NULL COMMENT '변경 후 사양 값',
`spec_unit` TINYINT(3) UNSIGNED DEFAULT NULL COMMENT '변경 후 사양 단위 ID',
`user_id` BIGINT(20) DEFAULT NULL COMMENT '변경 후 사용자 ID',
`comments` VARCHAR(200) DEFAULT NULL COMMENT '변경 후 비고',
`purchase_date` DATE DEFAULT NULL COMMENT '변경 후 구매 일자',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 7,
AVG_ROW_LENGTH = 2730,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '자산 정보 수정 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_update_resource`
ADD CONSTRAINT `chk_log_update_resource_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,22 @@
CREATE TABLE `log_update_user` (
`log_id` BIGINT(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '로그 ID (PK)',
`log_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '로그 기록 시각',
`admin_user_id` INT(11) DEFAULT NULL COMMENT '작업 관리자 ID (FK, auth_user.id)',
`actor_description` VARCHAR(100) DEFAULT NULL COMMENT '작업 주체 설명 (자동화 등)',
`user_id` BIGINT(20) NOT NULL COMMENT '수정된 사용자 ID',
`old_display_name` VARCHAR(100) DEFAULT NULL COMMENT '변경 전 표시 이름',
`old_account_name` VARCHAR(255) DEFAULT NULL COMMENT '변경 전 계정 이름',
`old_group_id` BIGINT(20) DEFAULT NULL COMMENT '변경 전 그룹 ID',
`new_display_name` VARCHAR(100) DEFAULT NULL COMMENT '변경 후 표시 이름',
`new_account_name` VARCHAR(255) NOT NULL COMMENT '변경 후 계정 이름',
`new_group_id` BIGINT(20) DEFAULT NULL COMMENT '변경 후 그룹 ID',
PRIMARY KEY (log_id)
)
ENGINE = INNODB,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '사용자 정보 수정 활동 로그',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `log_update_user`
ADD CONSTRAINT `chk_log_update_user_actor` CHECK (`admin_user_id` is not null or `actor_description` is not null);

View File

@ -0,0 +1,14 @@
CREATE TABLE `resource_category` (
`category_id` TINYINT(3) UNSIGNED NOT NULL COMMENT '카테고리 ID (PK, 0-255)',
`category_name` VARCHAR(40) NOT NULL COMMENT '카테고리 이름 (UNIQUE)',
PRIMARY KEY (category_id)
)
ENGINE = INNODB,
AVG_ROW_LENGTH = 2048,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '자산 카테고리',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `resource_category`
ADD UNIQUE INDEX uix_category_name(category_name) COMMENT '카테고리 이름은 고유해야 함';

View File

@ -0,0 +1,35 @@
CREATE TABLE `resource_info` (
`resource_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '자산 고유 ID (PK)',
`category_id` TINYINT(3) UNSIGNED NOT NULL COMMENT '자산 카테고리 ID (FK)',
`resource_code` VARCHAR(100) DEFAULT NULL COMMENT '관리 코드 (자산 번호 등)',
`manufacturer` VARCHAR(100) DEFAULT NULL COMMENT '제조사',
`resource_name` VARCHAR(100) NOT NULL COMMENT '제품명 또는 모델명',
`serial_num` VARCHAR(200) DEFAULT NULL COMMENT '시리얼 번호 (UNIQUE)',
`spec_value` DECIMAL(10, 2) DEFAULT NULL COMMENT '주요 사양 값 (숫자)',
`spec_unit` TINYINT(3) UNSIGNED DEFAULT NULL COMMENT '사양 단위 ID',
`user_id` BIGINT(20) DEFAULT NULL COMMENT '현재 할당된 사용자 ID (FK, user_info.user_id)',
`comments` VARCHAR(200) DEFAULT NULL COMMENT '비고 또는 추가 설명',
`purchase_date` DATE DEFAULT NULL COMMENT '구매 일자',
`is_locked` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '동기화 대상 제외용 잠금(0:해제, 1:잠금)',
`register_date` DATETIME NOT NULL DEFAULT current_timestamp() COMMENT '시스템 최초 등록 일시',
`update_date` DATETIME DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP COMMENT '최종 정보 수정 일시',
PRIMARY KEY (resource_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 503,
AVG_ROW_LENGTH = 164,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '개별 자산 정보',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `resource_info`
ADD UNIQUE INDEX uix_serial_num(serial_num) COMMENT '시리얼 번호는 고유해야 함 (NULL 제외)';
ALTER TABLE `resource_info`
ADD CONSTRAINT `fk_resource_category` FOREIGN KEY (category_id)
REFERENCES resource_category(category_id) ON DELETE NO ACTION ON UPDATE CASCADE;
ALTER TABLE `resource_info`
ADD CONSTRAINT `fk_resource_user` FOREIGN KEY (user_id)
REFERENCES user_info(user_id) ON DELETE SET NULL ON UPDATE CASCADE;

21
db/schema/user_info.sql Normal file
View File

@ -0,0 +1,21 @@
CREATE TABLE `user_info` (
`user_id` BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '사용자 고유 ID (PK)',
`display_name` VARCHAR(100) DEFAULT NULL COMMENT '표시 이름 (AD의 displayName)',
`account_name` VARCHAR(255) NOT NULL COMMENT '계정 이름 (AD의 sAMAccountName 또는 userPrincipalName 앞부분, UNIQUE)',
`group_id` BIGINT(20) DEFAULT NULL COMMENT '소속 그룹 ID (FK, group_info.group_id)',
PRIMARY KEY (user_id)
)
ENGINE = INNODB,
AUTO_INCREMENT = 87,
AVG_ROW_LENGTH = 682,
CHARACTER SET utf8mb4,
COLLATE utf8mb4_general_ci,
COMMENT = '사용자 기본 정보',
ROW_FORMAT = DYNAMIC;
ALTER TABLE `user_info`
ADD UNIQUE INDEX uix_account_name(account_name) COMMENT '계정 이름은 고유해야 함';
ALTER TABLE `user_info`
ADD CONSTRAINT `fk_user_group` FOREIGN KEY (group_id)
REFERENCES group_info(group_id) ON DELETE SET NULL ON UPDATE CASCADE;

16
db/seeds/group_info.sql Normal file
View File

@ -0,0 +1,16 @@
--
-- Script was generated by Devart dbForge Studio for MySQL, Version 10.1.165.0
-- Product home page: https://www.devart.com/dbforge/mysql/studio
-- Script date 2025-04-22 오후 6:41:32
-- Server version: 11.1.1
--
SET NAMES 'utf8';
INSERT INTO gyber.group_info(group_id, group_name, user_id) VALUES
(1, 'A실', NULL),
(2, 'B본부', NULL),
(3, 'OneImmers', NULL),
(4, 'StudioHG', NULL),
(5, '영상&연출팀', NULL),
(6, '테크코어실', NULL);

View File

@ -0,0 +1,16 @@
--
-- Script was generated by Devart dbForge Studio for MySQL, Version 10.1.165.0
-- Product home page: https://www.devart.com/dbforge/mysql/studio
-- Script date 2025-04-22 오후 6:41:33
-- Server version: 11.1.1
--
SET NAMES 'utf8';
INSERT INTO gyber.resource_category(category_id, category_name) VALUES
(0, 'Etc'),
(1, 'CPU'),
(2, 'MainBoard'),
(3, 'GPU'),
(4, 'Memory'),
(5, 'Storage');

96
db/seeds/user_info.sql Normal file
View File

@ -0,0 +1,96 @@
--
-- Script was generated by Devart dbForge Studio for MySQL, Version 10.1.165.0
-- Product home page: https://www.devart.com/dbforge/mysql/studio
-- Script date 2025-04-22 오후 6:41:33
-- Server version: 11.1.1
--
SET NAMES 'utf8';
INSERT INTO gyber.user_info(user_id, user_name, email_address, group_id) VALUES
(1, '백두산', 'mountain', NULL),
(2, '고세준', 'sjgo', NULL),
(3, '김진일', 'jinilkim', 4),
(4, '손향미', 'hyangmi', 2),
(5, '정윤호', 'unows', 2),
(6, '박상호', 'getling', 2),
(7, '이진훈', 'granadaone', 2),
(8, '홍래진', 'rehjinh', 6),
(9, '이민권', 'mklee', 4),
(10, '고진호', 'gohjinho', 2),
(11, '강희준', 'naddo1714', 2),
(12, '신용철', 'everwait', 2),
(13, '고철우', 'cwkoh', 4),
(14, '조영란', 'youngran', 5),
(15, '김준일', 'dewdewdew', 4),
(16, '이승혁', 'afelbaum', 2),
(17, '정운덕', 'aomgaomgaomg', 2),
(18, '양범진', 'tigerjin', 6),
(19, '김준호', 'juno4481', 2),
(20, '박주상', 'jusang', 4),
(21, '조우현', 'kenneth', 2),
(22, '박동현', 'rylynn6318', 2),
(23, '임태현', 'langley', 6),
(24, '이소현', 'shyi', 2),
(25, '김채영', 'chaechae', 5),
(26, '우석균', 'sgwoo1127', 2),
(27, '오승석', 'l2vator', 6),
(28, '문왕민', 'moonwm', 2),
(29, '정영준', 'nullcahn', 2),
(30, '정현성', 'gringreem', 2),
(31, '배재근', 'jack', 6),
(32, '이시온', 'leesion', 2),
(33, '김교성', 'kimks', 2),
(34, '김미애', 'kimlove', 2),
(35, '김혜승', 'holing', 4),
(36, '박민기', 'waffle', 2),
(37, '최범휘', 'bum4496', 2),
(38, '차수연', 'bibi333', 2),
(39, '김성호', 'destroyart1009', 2),
(40, '이동근', 'incl', 4),
(41, '김서후', 'sh1116', 4),
(42, '홍석훈', 'ken10', 2),
(43, '지동석', 'jidong', 4),
(44, '정의로', 'justiceway', 2),
(45, '김묘진', 'lihda61', 4),
(46, '이범규', 'beomguy1', 4),
(47, '이정환', 'shrimp81', 4),
(48, '강동수', 'honeybear', 4),
(49, '황은아', 'eunah', 5),
(50, '최정익', 'simaenaga9093', 4),
(51, '박하림', 'rim86', 4),
(52, '김상우', 'depicts', 4),
(53, '김규민', 'doogk3', 4),
(54, '조혜진', 'nice160', 4),
(55, '최월환', 'show0720', 4),
(56, '양승희', 'Van', 4),
(57, '허민형', 'heo_323', 5),
(58, '이진영', 'thiscamp45', 4),
(59, '김균호', 'khkim', 4),
(60, '이준수', 'cumplir', 4),
(61, '이동만', 'dmlee', 4),
(62, '이선후', 'shmongsil126', 4),
(63, '이진우', 'jinu2', 4),
(64, '양정우', 'didwjddn6333', 4),
(65, '정명진', 'noah', 2),
(66, '신수진', 'shara', 2),
(67, '김도영', 'dykim', 2),
(68, '이태우', 'twlee528', 4),
(69, '임선혁', 'shlim', 4),
(70, '김예진', 'dlclrh10', 4),
(71, '송윤기', 'yksong', 2),
(72, '홍승민', 'smhong', 4),
(73, '김채윤', 'gili', 4),
(74, '이지은', 'jieunl', 5),
(75, '김명석', 'kimms0808', 4),
(76, '스테파노', 'stefano', 4),
(77, '황성환', 'kingmaru', 2),
(78, '이지현', 'jihyunlee103', 4),
(79, '김준식', 'junsikk', 4),
(80, '김민정', 'min3867', 4),
(81, '조보경', 'dinoegg2', 4),
(82, '강빈', 'rkdqlsxp', 2),
(83, '이광희', 'ovan', 2),
(84, '홍정우', 'wjddntmakdlf', 2),
(85, '전성빈', 'junsb0603', 4),
(86, '김태풍', 'typoon', 6);