Files
zyt/server/sql/1.9.20260721/luoyang_pharmacy_erp.sql
T
2026-07-22 14:50:34 +08:00

385 lines
16 KiB
SQL

-- zyt projection and integration state for the Luoyang pharmacy ERP.
-- Existing-order DDL is guarded because this migration may be resumed after a partial deployment.
SET @schema_name := DATABASE();
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND COLUMN_NAME = 'ej_pharmacy_order_no'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD COLUMN `ej_pharmacy_order_no` varchar(40) NULL DEFAULT NULL COMMENT ''Remote ej ERP order number'' AFTER `ship_mode`'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND COLUMN_NAME = 'ej_pharmacy_submit_time'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD COLUMN `ej_pharmacy_submit_time` int unsigned NOT NULL DEFAULT 0 AFTER `ej_pharmacy_order_no`'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND COLUMN_NAME = 'ej_pharmacy_status'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD COLUMN `ej_pharmacy_status` varchar(32) NOT NULL DEFAULT '''' AFTER `ej_pharmacy_submit_time`'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND COLUMN_NAME = 'ej_pharmacy_review_status'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD COLUMN `ej_pharmacy_review_status` varchar(24) NOT NULL DEFAULT '''' AFTER `ej_pharmacy_status`'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND COLUMN_NAME = 'ej_pharmacy_status_version'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD COLUMN `ej_pharmacy_status_version` bigint unsigned NOT NULL DEFAULT 0 AFTER `ej_pharmacy_review_status`'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND COLUMN_NAME = 'ej_pharmacy_current_step'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD COLUMN `ej_pharmacy_current_step` varchar(100) NOT NULL DEFAULT '''' AFTER `ej_pharmacy_status_version`'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND COLUMN_NAME = 'ej_pharmacy_remark'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD COLUMN `ej_pharmacy_remark` varchar(500) NOT NULL DEFAULT '''' AFTER `ej_pharmacy_current_step`'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- Repair a partial deployment that created the order number as NOT NULL DEFAULT ''.
ALTER TABLE `zyt_tcm_prescription_order`
MODIFY COLUMN `ej_pharmacy_order_no` varchar(40) NULL DEFAULT NULL COMMENT 'Remote ej ERP order number';
UPDATE `zyt_tcm_prescription_order` SET `ej_pharmacy_order_no` = NULL
WHERE `ej_pharmacy_order_no` = '';
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND INDEX_NAME = 'uk_ej_pharmacy_order_no'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD UNIQUE KEY `uk_ej_pharmacy_order_no` (`ej_pharmacy_order_no`)'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_tcm_prescription_order'
AND INDEX_NAME = 'idx_ej_pharmacy_status'
),
'SELECT 1',
'ALTER TABLE `zyt_tcm_prescription_order` ADD KEY `idx_ej_pharmacy_status` (`ej_pharmacy_status`,`ej_pharmacy_status_version`)'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
-- EJ callbacks may carry longer Unicode carrier codes and tracking numbers than the legacy order projection.
ALTER TABLE `zyt_tcm_prescription_order`
MODIFY COLUMN `express_company` varchar(32) NOT NULL DEFAULT '' COMMENT 'Carrier code',
MODIFY COLUMN `tracking_number` varchar(100) NOT NULL DEFAULT '' COMMENT 'Tracking number';
ALTER TABLE `zyt_express_tracking`
MODIFY COLUMN `tracking_number` varchar(100) NOT NULL DEFAULT '' COMMENT 'Tracking number';
ALTER TABLE `zyt_express_trace`
MODIFY COLUMN `tracking_number` varchar(100) NOT NULL DEFAULT '' COMMENT 'Tracking number';
CREATE TABLE IF NOT EXISTS `zyt_ej_medicine_catalog` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`medicine_code` varchar(32) NOT NULL,
`name` varchar(120) NOT NULL,
`brand` varchar(120) NOT NULL DEFAULT '',
`unit` varchar(24) NOT NULL,
`settlement_price` decimal(12,4) NOT NULL DEFAULT 0.0000,
`retail_price` decimal(12,4) NOT NULL DEFAULT 0.0000,
`status` tinyint unsigned NOT NULL DEFAULT 1,
`catalog_version` bigint unsigned NOT NULL DEFAULT 0,
`remote_deleted` tinyint unsigned NOT NULL DEFAULT 0,
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_medicine_code` (`medicine_code`),
KEY `idx_catalog_version` (`catalog_version`),
KEY `idx_name_status` (`name`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `zyt_ej_medicine_mapping` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`local_medicine_id` bigint unsigned NOT NULL,
`medicine_code` varchar(32) NOT NULL,
`status` tinyint unsigned NOT NULL DEFAULT 1,
`operator_id` bigint unsigned NOT NULL DEFAULT 0,
`operator_name` varchar(80) NOT NULL DEFAULT '',
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
`delete_time` int unsigned DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_local_medicine` (`local_medicine_id`),
UNIQUE KEY `uk_medicine_code` (`medicine_code`),
KEY `idx_medicine_status` (`medicine_code`,`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_ej_medicine_mapping'
AND INDEX_NAME = 'uk_medicine_code'
),
'SELECT 1',
'ALTER TABLE `zyt_ej_medicine_mapping` ADD UNIQUE KEY `uk_medicine_code` (`medicine_code`)'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
CREATE TABLE IF NOT EXISTS `zyt_ej_pharmacy_submission` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`prescription_order_id` bigint unsigned NOT NULL,
`source_revision` int unsigned NOT NULL DEFAULT 1,
`request_hash` char(64) NOT NULL,
`request_id` varchar(64) NOT NULL DEFAULT '',
`remote_order_no` varchar(40) NOT NULL DEFAULT '',
`status` varchar(24) NOT NULL DEFAULT 'PENDING',
`http_status` int unsigned NOT NULL DEFAULT 0,
`response_summary` json DEFAULT NULL,
`error_message` varchar(1000) NOT NULL DEFAULT '',
`operator_id` bigint unsigned NOT NULL DEFAULT 0,
`operator_name` varchar(80) NOT NULL DEFAULT '',
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_revision` (`prescription_order_id`,`source_revision`),
KEY `idx_status_time` (`status`,`update_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `zyt_pharmacy_submission_claim` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`prescription_order_id` bigint unsigned NOT NULL,
`source_revision` int unsigned NOT NULL DEFAULT 1,
`target` varchar(16) NOT NULL,
`status` varchar(24) NOT NULL DEFAULT 'PENDING',
`claim_token` char(32) NOT NULL,
`idempotency_key` char(64) NOT NULL,
`remote_order_no` varchar(64) NOT NULL DEFAULT '',
`request_id` varchar(64) NOT NULL DEFAULT '',
`error_message` varchar(1000) NOT NULL DEFAULT '',
`operator_id` bigint unsigned NOT NULL DEFAULT 0,
`operator_name` varchar(80) NOT NULL DEFAULT '',
`claimed_at` int unsigned NOT NULL DEFAULT 0,
`lease_expires_at` int unsigned NOT NULL DEFAULT 0,
`completed_at` int unsigned NOT NULL DEFAULT 0,
`failed_at` int unsigned NOT NULL DEFAULT 0,
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_revision` (`prescription_order_id`,`source_revision`),
UNIQUE KEY `uk_claim_token` (`claim_token`),
KEY `idx_status_time` (`status`,`update_time`),
KEY `idx_target_remote` (`target`,`remote_order_no`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `zyt_pharmacy_submission_claim`
MODIFY COLUMN `status` varchar(24) NOT NULL DEFAULT 'PENDING';
SET @ddl := IF(
EXISTS (
SELECT 1 FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = @schema_name AND TABLE_NAME = 'zyt_pharmacy_submission_claim'
AND COLUMN_NAME = 'lease_expires_at'
),
'SELECT 1',
'ALTER TABLE `zyt_pharmacy_submission_claim` ADD COLUMN `lease_expires_at` int unsigned NOT NULL DEFAULT 0 AFTER `claimed_at`'
);
PREPARE stmt FROM @ddl; EXECUTE stmt; DEALLOCATE PREPARE stmt;
UPDATE `zyt_pharmacy_submission_claim`
SET `lease_expires_at` = `claimed_at` + 300
WHERE `status` = 'PENDING' AND `lease_expires_at` = 0 AND `claimed_at` > 0;
CREATE TABLE IF NOT EXISTS `zyt_pharmacy_submission_claim_audit` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`claim_id` bigint unsigned NOT NULL,
`prescription_order_id` bigint unsigned NOT NULL,
`source_revision` int unsigned NOT NULL DEFAULT 1,
`target` varchar(16) NOT NULL,
`action` varchar(32) NOT NULL,
`from_status` varchar(24) NOT NULL,
`to_status` varchar(24) NOT NULL,
`remote_order_no` varchar(64) NOT NULL DEFAULT '',
`note` varchar(1000) NOT NULL DEFAULT '',
`operator_id` bigint unsigned NOT NULL DEFAULT 0,
`operator_name` varchar(80) NOT NULL DEFAULT '',
`create_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
KEY `idx_claim_time` (`claim_id`,`create_time`),
KEY `idx_order_time` (`prescription_order_id`,`create_time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `zyt_ej_pharmacy_callback_inbox` (
`id` bigint unsigned NOT NULL AUTO_INCREMENT,
`event_id` char(36) NOT NULL,
`pharmacy_order_no` varchar(40) NOT NULL,
`source_order_no` varchar(64) NOT NULL,
`event_type` varchar(48) NOT NULL,
`status_version` bigint unsigned NOT NULL DEFAULT 0,
`payload` json NOT NULL,
`process_status` varchar(24) NOT NULL DEFAULT 'PENDING',
`processed_time` int unsigned NOT NULL DEFAULT 0,
`error_message` varchar(1000) NOT NULL DEFAULT '',
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`),
UNIQUE KEY `uk_event_id` (`event_id`),
KEY `idx_process_status` (`process_status`,`id`),
KEY `idx_order_version` (`pharmacy_order_no`,`status_version`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE IF NOT EXISTS `zyt_ej_pharmacy_sync_state` (
`id` tinyint unsigned NOT NULL,
`cursor` bigint unsigned NOT NULL DEFAULT 0,
`last_success_time` int unsigned NOT NULL DEFAULT 0,
`last_failure_time` int unsigned NOT NULL DEFAULT 0,
`last_error_summary` varchar(500) NOT NULL DEFAULT '',
`lock_token` char(32) NOT NULL DEFAULT '',
`lock_expires_at` int unsigned NOT NULL DEFAULT 0,
`create_time` int unsigned NOT NULL DEFAULT 0,
`update_time` int unsigned NOT NULL DEFAULT 0,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO `zyt_ej_pharmacy_sync_state` (`id`, `cursor`, `create_time`, `update_time`)
VALUES (1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP())
ON DUPLICATE KEY UPDATE `id` = VALUES(`id`);
-- Page sits beside the existing doctor medicine library; API nodes make every endpoint visible to AuthMiddleware.
SET @doctor_medicine_menu_id := (
SELECT `id`
FROM `zyt_system_menu`
WHERE `perms` = 'doctor.medicine/lists'
OR (`component` = 'doctor/medicine' AND `type` = 'C')
ORDER BY (`perms` = 'doctor.medicine/lists') DESC, `id` ASC
LIMIT 1
);
SET @doctor_medicine_parent_id := (
SELECT `pid` FROM `zyt_system_menu` WHERE `id` = @doctor_medicine_menu_id LIMIT 1
);
INSERT INTO `zyt_system_menu` (
`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`,
`selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`
)
SELECT
@doctor_medicine_parent_id, 'C', '洛阳药房药材映射', '', 0,
'pharmacy.medicineMapping/lists', 'pharmacy/medicine-mapping', 'pharmacy/medicine_mapping/index',
'', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
FROM DUAL
WHERE @doctor_medicine_parent_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM `zyt_system_menu` WHERE `perms` = 'pharmacy.medicineMapping/lists'
);
SET @medicine_mapping_menu_id := (
SELECT `id` FROM `zyt_system_menu` WHERE `perms` = 'pharmacy.medicineMapping/lists' LIMIT 1
);
INSERT INTO `zyt_system_menu` (
`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`,
`selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`
)
SELECT
@medicine_mapping_menu_id, 'A', `permission_node`.`name`, '', `permission_node`.`sort`,
`permission_node`.`perms`, '', '', '', '', 0, 1, 0, UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
FROM (
SELECT '查看同步状态' AS `name`, 10 AS `sort`, 'pharmacy.medicineMapping/status' AS `perms`
UNION ALL SELECT '检索远端药材', 20, 'pharmacy.medicineMapping/catalogOptions'
UNION ALL SELECT '同步远端目录', 30, 'pharmacy.medicineMapping/sync'
UNION ALL SELECT '保存药材映射', 40, 'pharmacy.medicineMapping/save'
UNION ALL SELECT '解除药材映射', 50, 'pharmacy.medicineMapping/unlink'
) AS `permission_node`
WHERE @medicine_mapping_menu_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM `zyt_system_menu` AS `existing_menu`
WHERE `existing_menu`.`perms` = `permission_node`.`perms`
);
-- New clients use this explicit unified-upload permission. The historical
-- submitGancaoRecipel node remains valid and its controller still routes by ship_mode.
SET @prescription_order_menu_id := (
SELECT `id` FROM `zyt_system_menu` WHERE `perms` = 'tcm.prescriptionOrder/lists' LIMIT 1
);
INSERT INTO `zyt_system_menu` (
`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`,
`selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`
)
SELECT
@prescription_order_menu_id, 'A', '上传药房', '', 10,
'tcm.prescriptionOrder/uploadToPharmacy', '', '', '', '', 0, 1, 0,
UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
FROM DUAL
WHERE @prescription_order_menu_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM `zyt_system_menu` WHERE `perms` = 'tcm.prescriptionOrder/uploadToPharmacy'
);
-- Historical route retained as a controlled compatibility alias for the same pharmacy-upload capability.
INSERT INTO `zyt_system_menu` (
`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`,
`selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`
)
SELECT
@prescription_order_menu_id, 'A', '上传药房(兼容入口)', '', 11,
'tcm.prescriptionOrder/submitGancaoRecipel', '', '', '', '', 0, 1, 0,
UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
FROM DUAL
WHERE @prescription_order_menu_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM `zyt_system_menu` WHERE `perms` = 'tcm.prescriptionOrder/submitGancaoRecipel'
);
-- Manual reconciliation can finalize an uncertain remote result or release it for retry,
-- so it requires a separate high-risk permission from ordinary pharmacy upload.
INSERT INTO `zyt_system_menu` (
`pid`, `type`, `name`, `icon`, `sort`, `perms`, `paths`, `component`,
`selected`, `params`, `is_cache`, `is_show`, `is_disable`, `create_time`, `update_time`
)
SELECT
@prescription_order_menu_id, 'A', '人工核对甘草提交', '', 12,
'tcm.prescriptionOrder/confirmGancaoSubmission', '', '', '', '', 0, 1, 0,
UNIX_TIMESTAMP(), UNIX_TIMESTAMP()
FROM DUAL
WHERE @prescription_order_menu_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM `zyt_system_menu` WHERE `perms` = 'tcm.prescriptionOrder/confirmGancaoSubmission'
);