DELIMITER // CREATE OR REPLACE PROCEDURE orm_exec_insert_v2( IN p_tablename VARCHAR(200), -- tablename IN p_pk VARCHAR(100), -- primary key(for update delete) IN p_action VARCHAR(20), -- CRUDP IN p_uuid VARCHAR(100), IN p_userid VARCHAR(100) ) /* Function : orm_api_v2 [新增]的核心程式, 智慧的組出相應的 sql Description: 關於 Master-Detail 的補充說明 Build Date : 2023/12/16 Modified for MariaDB */ BEGIN DECLARE v_maxcount INT; DECLARE v_currid INT; DECLARE v_is_md SMALLINT; DECLARE v_is_excel SMALLINT; DECLARE v_maxid INT; DECLARE v_excel_id INT; DECLARE v_cnt INT; DECLARE v_cn_field VARCHAR(100); DECLARE v_cd_field VARCHAR(100); DECLARE v_billno VARCHAR(20); DECLARE v_sub_table VARCHAR(100); DECLARE v_sql TEXT; DECLARE v_max_no VARCHAR(20); DECLARE v_maxcnt INT; -- step 1: 判斷狀態: 是否 master-detail 多筆資料? SELECT MAX(parent_id) INTO v_maxcount FROM orm_json_tmp WHERE uuid = p_uuid; -- @is_md 是使用 input-table template 用的判斷 SELECT COUNT(*), IFNULL(MAX(parent_id), 0) INTO v_is_md, v_maxid FROM orm_json_tmp WHERE uuid = p_uuid AND json_key = 'details' AND valuetype = 'array'; SELECT COUNT(*), IFNULL(MAX(parent_id), 0) INTO v_is_excel, v_excel_id FROM orm_json_tmp WHERE uuid = p_uuid AND json_key = 'excel' AND valuetype = 'array'; -- step 2: update/insert create_user (僅允許一次一筆資料) SET v_cn_field = 'create_user'; SET v_cd_field = 'create_date'; -- Check if create_user column exists SELECT COUNT(*) INTO v_cnt FROM information_schema.columns WHERE table_name = p_tablename AND column_name = v_cn_field; IF v_cnt > 0 THEN SELECT COUNT(*) INTO v_cnt FROM orm_json_tmp WHERE uuid = p_uuid AND json_key = v_cn_field; IF v_cnt = 0 THEN INSERT INTO orm_json_tmp (uuid, parent_id, json_key, json_value, ValueType) VALUES (p_uuid, v_maxcount, v_cn_field, p_userid, 'string'); ELSE UPDATE orm_json_tmp SET json_value = p_userid WHERE uuid = p_uuid AND json_key = v_cn_field; END IF; END IF; -- Check if create_date column exists SELECT COUNT(*) INTO v_cnt FROM information_schema.columns WHERE table_name = p_tablename AND column_name = v_cd_field; IF v_cnt > 0 THEN SELECT COUNT(*) INTO v_cnt FROM orm_json_tmp WHERE uuid = p_uuid AND json_key = v_cd_field; IF v_cnt = 0 THEN INSERT INTO orm_json_tmp (uuid, parent_id, json_key, json_value, ValueType) VALUES (p_uuid, v_maxcount, v_cd_field, DATE_FORMAT(NOW(), '%Y-%m-%d'), 'string'); ELSE UPDATE orm_json_tmp SET json_value = DATE_FORMAT(NOW(), '%Y-%m-%d') WHERE uuid = p_uuid AND json_key = v_cd_field; END IF; END IF; -- step 3: 針對 m-d 的單號前置處理(針對 billno=自動編碼, 給定新的單號) SELECT COUNT(*) INTO v_cnt FROM orm_json_tmp WHERE uuid = p_uuid AND json_key = 'billno' AND (json_value LIKE '%自動%' OR json_value LIKE '%Auto%'); IF v_cnt > 0 THEN -- hard-code IF p_pk = '' OR p_tablename LIKE '%_d%' THEN -- master-detail 的 detail insert SET v_max_no = CONCAT(SUBSTRING(p_tablename, 4, 6), SUBSTRING(p_userid, 1, 6)); ELSE -- 先取得今天最大號 SET @sql = CONCAT('SELECT MAX(billno) INTO @max_billno FROM ', p_tablename, ' WHERE DATE(billdate) = CURDATE()'); PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; -- 計算新單號 (需要實現 sys_next_no 函數) SET v_max_no = sys_next_no(@max_billno); -- 紀錄新增單號 DELETE FROM sys_new_billno WHERE create_time < DATE_SUB(NOW(), INTERVAL 3 DAY); -- 防錯 SELECT COUNT(*) INTO v_maxcnt FROM sys_new_billno WHERE tablename = p_tablename AND login_user = p_userid; IF v_maxcnt > 0 THEN UPDATE sys_new_billno SET billno = v_max_no WHERE tablename = p_tablename AND login_user = p_userid; ELSE INSERT INTO sys_new_billno VALUES (p_tablename, p_userid, v_max_no, NOW()); END IF; END IF; UPDATE orm_json_tmp SET json_value = v_max_no WHERE uuid = p_uuid AND json_key = 'billno' AND (json_value LIKE '%自動%' OR json_value LIKE '%Auto%'); END IF; -- master-detail IF v_is_md > 0 THEN -- 寫入 master 一筆 CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, v_maxcount); -- 取得表頭的單號 SELECT billno INTO v_billno FROM sys_new_billno WHERE tablename = p_tablename AND login_user = p_userid; -- 寫入 details 多筆 SELECT detail_table INTO v_sub_table FROM zen_function WHERE maintable = p_tablename LIMIT 1; IF IFNULL(v_sub_table, '') = '' THEN SET v_sub_table = CONCAT(SUBSTRING(p_tablename, 1, LENGTH(p_tablename)-1), 'd'); END IF; -- 多筆 detail 資料寫入 SET v_currid = 1; WHILE v_currid < v_maxid DO -- 執行核心程式 CALL orm_api_kernel_v2(v_sub_table, p_pk, p_action, p_uuid, v_currid); -- 取得下一筆資料 SET v_currid = v_currid + 1; END WHILE; ELSEIF v_is_excel > 0 THEN -- excel 多筆資料匯入 SET v_currid = 1; WHILE v_currid < v_excel_id-1 DO -- 執行核心程式 CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, v_currid); -- 取得下一筆資料 SET v_currid = v_currid + 1; END WHILE; ELSEIF v_maxcount > 1 THEN -- 多筆資料寫入 SET v_currid = 1; WHILE v_currid <= v_maxcount DO -- 執行核心程式 CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, v_currid); -- 取得下一筆資料 SET v_currid = v_currid + 1; END WHILE; ELSE CALL orm_api_kernel_v2(p_tablename, p_pk, p_action, p_uuid, 1); END IF; END // DELIMITER ;