SET NAMES utf8mb4; USE baiyue_firstleg; /* * 船期日历的事实契约。 * * 这些表不修改入库单或海运订舱聚合:入库单仍是履约主数据,订舱仍是 * RELEASED/DRAFT 聚合。船期日历只消费这里的稳定事实和审计版本。 */ CREATE TABLE fl_sailing_receipt_batch_fact ( id BIGINT UNSIGNED NOT NULL COMMENT '稳定收货批次事实ID(receiptBatchId)', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户隔离键,继承入库事实', receipt_batch_key VARCHAR(64) NOT NULL COMMENT '同一物理收货批次的不可变业务键', fact_version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '同一批次复测/冲正版本', inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', measurement_id BIGINT UNSIGNED NULL COMMENT '最终审核测量批次ID', receiving_warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '实际收货仓ID', channel_code VARCHAR(64) NULL COMMENT '收货渠道编码快照', channel_name VARCHAR(128) NULL COMMENT '收货渠道名称快照', departure_port_code VARCHAR(32) NULL COMMENT '起运港编码快照', destination_port_code VARCHAR(32) NULL COMMENT '目的港编码快照', received_at DATETIME(3) NOT NULL COMMENT '实际收货完成时间,不使用入库单inbounded_at替代', actual_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '最终审核实测体积m3', fact_status VARCHAR(24) NOT NULL DEFAULT 'APPROVED' COMMENT '事实状态:APPROVED/REVERSED/VOIDED/SUPERSEDED', reversal_of_fact_id BIGINT UNSIGNED NULL COMMENT '冲正所替代的事实ID', source_type VARCHAR(32) NOT NULL DEFAULT 'FIRSTLEG_RECEIPT' COMMENT '事实来源', created_by BIGINT UNSIGNED NULL COMMENT '写入人或系统主体', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (id), UNIQUE KEY uk_sailing_receipt_batch_version (tenant_id, receipt_batch_key, fact_version), KEY idx_sailing_receipt_batch_current (tenant_id, receipt_batch_key, fact_status, fact_version), KEY idx_sailing_receipt_match (tenant_id, receiving_warehouse_id, channel_code, received_at, id), KEY idx_sailing_receipt_inbound (tenant_id, inbound_id, received_at, id), CONSTRAINT chk_sailing_receipt_volume CHECK (actual_volume_cbm > 0), CONSTRAINT chk_sailing_receipt_status CHECK (fact_status IN ('APPROVED','REVERSED','VOIDED','SUPERSEDED')) ) ENGINE=InnoDB COMMENT='船期日历稳定收货批次实测事实及版本历史'; CREATE TABLE fl_sailing_inbound_volume_forecast ( id BIGINT UNSIGNED NOT NULL COMMENT '货量预报事实ID(forecastId)', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户隔离键,继承入库事实', forecast_key VARCHAR(64) NOT NULL COMMENT '同一未收货对象的不可变业务键', fact_version INT UNSIGNED NOT NULL DEFAULT 1 COMMENT '预报修订版本', inbound_id BIGINT UNSIGNED NOT NULL COMMENT '入库单ID', receiving_warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '预计收货仓ID', channel_code VARCHAR(64) NULL COMMENT '预计渠道编码快照', channel_name VARCHAR(128) NULL COMMENT '预计渠道名称快照', departure_port_code VARCHAR(32) NULL COMMENT '预计起运港编码快照', destination_port_code VARCHAR(32) NULL COMMENT '预计目的港编码快照', expected_arrival_at DATETIME(3) NOT NULL COMMENT '预计到仓时间', forecast_volume_cbm DECIMAL(18,4) NOT NULL COMMENT '未收货预计体积m3,不得使用申报体积代替', source_type VARCHAR(32) NOT NULL COMMENT '预报来源,例如OPERATIONS/UPSTREAM_MEASUREMENT;不得使用客户申报体积冒充预报', fact_status VARCHAR(24) NOT NULL DEFAULT 'VALID' COMMENT '事实状态:VALID/SUPERSEDED/VOIDED/CONSUMED', effective_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '本版本生效时间', created_by BIGINT UNSIGNED NULL COMMENT '写入人或系统主体', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3), PRIMARY KEY (id), UNIQUE KEY uk_sailing_forecast_version (tenant_id, forecast_key, fact_version), KEY idx_sailing_forecast_current (tenant_id, forecast_key, fact_status, fact_version), KEY idx_sailing_forecast_match (tenant_id, receiving_warehouse_id, channel_code, expected_arrival_at, id), KEY idx_sailing_forecast_inbound (tenant_id, inbound_id, expected_arrival_at, id), CONSTRAINT chk_sailing_forecast_volume CHECK (forecast_volume_cbm > 0), CONSTRAINT chk_sailing_forecast_status CHECK (fact_status IN ('VALID','SUPERSEDED','VOIDED','CONSUMED')) ) ENGINE=InnoDB COMMENT='船期日历未收货量预报事实及版本历史'; CREATE TABLE fl_sailing_assignment ( id BIGINT UNSIGNED NOT NULL COMMENT '归班事实ID', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '客户隔离键', sailing_id BIGINT UNSIGNED NULL COMMENT '船期实例ID,UNMATCHED为空', origin_sailing_id BIGINT UNSIGNED NULL COMMENT '异常重排/取消前的原船期实例ID', inbound_id BIGINT UNSIGNED NULL COMMENT '归班对象入库单ID', inbound_code VARCHAR(64) NULL COMMENT '入仓码快照,仅用于展示', receipt_batch_id BIGINT UNSIGNED NULL COMMENT '收货批次事实ID', forecast_id BIGINT UNSIGNED NULL COMMENT '货量预报事实ID', assignment_source VARCHAR(24) NOT NULL DEFAULT 'AUTO' COMMENT '归班来源:AUTO/MANUAL/ROLLOVER', assignment_version INT UNSIGNED NOT NULL COMMENT '同一对象的归班版本', match_status VARCHAR(24) NOT NULL COMMENT 'FORECAST_MATCHED/RECEIVED/LATE/UNMATCHED/SUPERSEDED', volume_cbm DECIMAL(18,4) NULL COMMENT '已收实测体积', forecast_volume_cbm DECIMAL(18,4) NULL COMMENT '未收有效预计体积', route_source VARCHAR(32) NULL COMMENT '航线来源:INBOUND_FACT/FORECAST_FACT/CHANNEL_DEFAULT', volume_source VARCHAR(32) NULL COMMENT 'MEASURED_ACTUAL或预报来源', rule_version VARCHAR(64) NOT NULL COMMENT '自动归班规则版本', matched_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), superseded_at DATETIME(3) NULL, locked_at DATETIME(3) NULL COMMENT '截止/订舱/关闭后冻结时间', lock_reason VARCHAR(32) NULL COMMENT 'CUTOFF/BOOKING_CONFIRMED/CLOSED', operator_id BIGINT UNSIGNED NULL, reason VARCHAR(500) NULL, created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), PRIMARY KEY (id), KEY idx_sailing_assignment_current (tenant_id, sailing_id, match_status, matched_at, id), KEY idx_sailing_assignment_origin (tenant_id, origin_sailing_id, match_status, id), KEY idx_sailing_assignment_receipt (tenant_id, receipt_batch_id, assignment_version, id), KEY idx_sailing_assignment_forecast (tenant_id, forecast_id, assignment_version, id), KEY idx_sailing_assignment_inbound (tenant_id, inbound_id, match_status, id), CONSTRAINT chk_sailing_assignment_status CHECK (match_status IN ('FORECAST_MATCHED','RECEIVED','LATE','UNMATCHED','SUPERSEDED')), CONSTRAINT chk_sailing_assignment_source CHECK (assignment_source IN ('AUTO','MANUAL','ROLLOVER')) ) ENGINE=InnoDB COMMENT='船期日历自动归班事实及不可变版本历史'; CREATE TABLE fl_sailing_booking_link ( id BIGINT UNSIGNED NOT NULL COMMENT '船期-订舱关联ID', tenant_id BIGINT UNSIGNED NOT NULL COMMENT '平台关联隔离键', sailing_id BIGINT UNSIGNED NOT NULL COMMENT '计划船期实例ID', ocean_booking_id BIGINT UNSIGNED NOT NULL COMMENT '海运订舱ID', link_status VARCHAR(24) NOT NULL DEFAULT 'ACTIVE' COMMENT '关联状态:ACTIVE/REVOKED', active_booking_guard TINYINT NULL COMMENT 'ACTIVE为1,REVOKED为空,用于唯一约束', booking_status_snapshot VARCHAR(24) NOT NULL COMMENT '关联时订舱状态快照;只有RELEASED可建立', warehouse_id BIGINT UNSIGNED NULL COMMENT '关联仓库快照', channel_code VARCHAR(64) NULL COMMENT '关联渠道快照', departure_port_code VARCHAR(32) NULL COMMENT '关联起运港快照', destination_port_code VARCHAR(32) NULL COMMENT '关联目的港快照', linked_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), revoked_at DATETIME(3) NULL, operator_id BIGINT UNSIGNED NULL, operator_name VARCHAR(64) NULL, reason VARCHAR(500) NULL, PRIMARY KEY (id), UNIQUE KEY uk_sailing_booking_active (ocean_booking_id, active_booking_guard), KEY idx_sailing_booking_link (sailing_id, link_status, ocean_booking_id), KEY idx_sailing_booking_booking (ocean_booking_id, link_status, id), CONSTRAINT chk_sailing_booking_link_status CHECK (link_status IN ('ACTIVE','REVOKED')), CONSTRAINT chk_sailing_booking_link_guard CHECK ((link_status='ACTIVE' AND active_booking_guard=1) OR (link_status='REVOKED' AND active_booking_guard IS NULL)), CONSTRAINT chk_sailing_booking_released CHECK (booking_status_snapshot='RELEASED') ) ENGINE=InnoDB COMMENT='船期计划与已放舱订舱的最小关联及历史';