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 ;