-- Phase-one first-leg order fields. Safe to run repeatedly on MySQL 8. USE baiyue_order; SET NAMES utf8mb4; DROP PROCEDURE IF EXISTS phase1_add_column; DELIMITER $$ CREATE PROCEDURE phase1_add_column( IN p_table_name VARCHAR(64), IN p_column_name VARCHAR(64), IN p_definition VARCHAR(1000) ) BEGIN IF NOT EXISTS ( SELECT 1 FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = p_table_name AND COLUMN_NAME = p_column_name ) THEN SET @phase1_sql = CONCAT('ALTER TABLE `', p_table_name, '` ADD COLUMN `', p_column_name, '` ', p_definition); PREPARE phase1_stmt FROM @phase1_sql; EXECUTE phase1_stmt; DEALLOCATE PREPARE phase1_stmt; END IF; END$$ DELIMITER ; CALL phase1_add_column('ord_order', 'pickup_method', "VARCHAR(24) NULL COMMENT '取货方式'"); CALL phase1_add_column('ord_order', 'receiving_warehouse_id', "BIGINT UNSIGNED NULL COMMENT '国内收货仓逻辑ID'"); CALL phase1_add_column('ord_order', 'receiving_warehouse_name', "VARCHAR(128) NULL COMMENT '下单时国内收货仓名称快照;主数据变化不回写'"); CALL phase1_add_column('ord_order', 'receiving_warehouse_address', "VARCHAR(512) NULL COMMENT '国内收货仓完整地址快照'"); CALL phase1_add_column('ord_order', 'receiving_time', "VARCHAR(128) NULL COMMENT '国内收货仓收货时间快照'"); CALL phase1_add_column('ord_order', 'channel_code', "VARCHAR(64) NULL COMMENT '运输渠道编码'"); CALL phase1_add_column('ord_order', 'channel_name', "VARCHAR(128) NULL COMMENT '下单时运输渠道名称快照;渠道主数据变化不回写'"); CALL phase1_add_column('ord_order', 'tax_mode', "VARCHAR(24) NULL COMMENT '报关税务方式:BUY_DECLARATION买单、TAX_REFUND退税'"); CALL phase1_add_column('ord_order', 'container_mode', "VARCHAR(24) NULL COMMENT '装运方式:FULL_CONTAINER整柜、LCL散货拼箱'"); CALL phase1_add_column('ord_order', 'customs_inspection', "TINYINT(1) NULL COMMENT '是否需要商检:0否、1是'"); CALL phase1_add_column('ord_order', 'destination_type', "VARCHAR(24) NULL COMMENT '目的仓类型:FBA亚马逊仓、OVERSEAS海外仓、PRIVATE私人地址'"); CALL phase1_add_column('ord_order', 'amazon_warehouse_code', "VARCHAR(32) NULL COMMENT 'Amazon目的仓编码'"); CALL phase1_add_column('ord_order', 'shipment_id', "VARCHAR(64) NULL COMMENT '订单级Amazon Shipment ID'"); CALL phase1_add_column('ord_order', 'reference_id', "VARCHAR(64) NULL COMMENT '订单级Amazon Reference ID'"); CALL phase1_add_column('ord_order', 'express_company', "VARCHAR(64) NULL COMMENT '履约快递公司名称快照'"); CALL phase1_add_column('ord_order', 'express_tracking_no', "VARCHAR(128) NULL COMMENT '履约快递单号'"); CALL phase1_add_column('ord_order_cargo', 'sku_no', "VARCHAR(64) NULL COMMENT '货物SKU编码'"); CALL phase1_add_column('ord_order_cargo', 'upc_no', "VARCHAR(64) NULL COMMENT '货物UPC条码'"); CALL phase1_add_column('ord_order_cargo', 'cargo_name_en', "VARCHAR(128) NULL COMMENT '货物英文品名'"); CALL phase1_add_column('ord_order_cargo', 'customs_hs_code', "VARCHAR(20) NULL COMMENT '目的国清关HS编码'"); CALL phase1_add_column('ord_order_cargo', 'units_per_package', "INT UNSIGNED NULL COMMENT '每箱产品数量'"); CALL phase1_add_column('ord_order_cargo', 'total_quantity', "INT UNSIGNED NULL COMMENT '产品总数量'"); CALL phase1_add_column('ord_order_cargo', 'net_weight_kg', "DECIMAL(18,3) NULL COMMENT '货物净重,单位千克'"); CALL phase1_add_column('ord_order_cargo', 'unit_declared_value', "DECIMAL(18,2) NULL COMMENT '单件申报价值;币种取订单申报币种'"); CALL phase1_add_column('ord_order_cargo', 'material', "VARCHAR(128) NULL COMMENT '产品材质'"); CALL phase1_add_column('ord_order_cargo', 'product_usage', "VARCHAR(128) NULL COMMENT '产品用途'"); CALL phase1_add_column('ord_order_cargo', 'model', "VARCHAR(64) NULL COMMENT '产品型号'"); CALL phase1_add_column('ord_order_cargo', 'brand', "VARCHAR(64) NULL COMMENT '产品品牌'"); CALL phase1_add_column('ord_order_cargo', 'product_length_cm', "DECIMAL(12,2) NULL COMMENT '单件产品长度,单位厘米'"); CALL phase1_add_column('ord_order_cargo', 'product_width_cm', "DECIMAL(12,2) NULL COMMENT '单件产品宽度,单位厘米'"); CALL phase1_add_column('ord_order_cargo', 'product_height_cm', "DECIMAL(12,2) NULL COMMENT '单件产品高度,单位厘米'"); CALL phase1_add_column('ord_order_cargo', 'shipment_id', "VARCHAR(64) NULL COMMENT '本货物明细对应的Amazon Shipment ID'"); CALL phase1_add_column('ord_order_cargo', 'reference_id', "VARCHAR(64) NULL COMMENT '本货物明细对应的Amazon Reference ID'"); CALL phase1_add_column('ord_order_cargo', 'product_image_file_id', "BIGINT UNSIGNED NULL COMMENT 'File服务中的产品图片逻辑文件ID'"); -- 货物级字段上线前,FBA 编号只保存在主单;回填后提交校验可统一按每条货物执行。 UPDATE ord_order_cargo cargo JOIN ord_order orders ON orders.id = cargo.order_id AND orders.tenant_id = cargo.tenant_id SET cargo.shipment_id = COALESCE(NULLIF(cargo.shipment_id, ''), orders.shipment_id), cargo.reference_id = COALESCE(NULLIF(cargo.reference_id, ''), orders.reference_id) WHERE orders.destination_type = 'FBA' AND ((cargo.shipment_id IS NULL OR cargo.shipment_id = '') OR (cargo.reference_id IS NULL OR cargo.reference_id = '')); DROP PROCEDURE phase1_add_column; -- 已有订单库的幂等记录迁移,和订单写入处于同一个本地事务。 CREATE TABLE IF NOT EXISTS ord_idempotency_record ( id BIGINT UNSIGNED NOT NULL COMMENT '幂等记录 ID', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户ID和数据隔离键', operator_id BIGINT UNSIGNED NOT NULL COMMENT '发起写操作的用户ID', operation VARCHAR(32) NOT NULL COMMENT '幂等操作类型', resource_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '操作目标资源ID;创建前未知时为0', idempotency_key VARCHAR(128) NOT NULL COMMENT '客户端幂等键', request_hash CHAR(64) NOT NULL COMMENT '规范化请求内容SHA-256摘要,用于识别同键不同请求', status VARCHAR(16) NOT NULL COMMENT '处理状态:PROCESSING处理中、COMPLETED已完成', result_order_id BIGINT UNSIGNED NULL COMMENT '成功操作生成或更新的订单ID,用于幂等重放', completed_at DATETIME(3) NULL COMMENT '处理完成时间', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间', updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '更新时间', PRIMARY KEY (id), UNIQUE KEY uk_order_idempotency_scope (tenant_id, operator_id, operation, idempotency_key), KEY idx_order_idempotency_created (created_at) ) ENGINE=InnoDB COMMENT='订单写接口持久化幂等记录';