This commit is contained in:
2026-10-20 11:33:20 +08:00
parent 16ac817524
commit 6fa5d281ec
61 changed files with 31358 additions and 8 deletions
@@ -0,0 +1,224 @@
{
"baiyue_lastleg": {
"createdTables": [
"event_delivery_retry_audit",
"ll_appointment_cargo_verification",
"ll_appointment_followup",
"ll_appointment_impact",
"ll_appointment_impact_history",
"ll_delivery_facts_changed",
"ll_dispatch_command",
"ll_dispatch_delivery_arrangement",
"ll_dispatch_draft_command",
"ll_dispatch_history",
"ll_fba_appointment_command",
"ll_fba_receiving_agreement",
"ll_fba_receiving_change",
"ll_fba_receiving_member",
"ll_fba_receiving_plan",
"ll_fba_receiving_revision",
"ll_procurement_budget_authorization",
"ll_procurement_carton",
"ll_procurement_carton_source",
"ll_procurement_closure",
"ll_procurement_closure_item",
"ll_procurement_command",
"ll_procurement_control_note",
"ll_procurement_disposition",
"ll_procurement_estimate_review",
"ll_procurement_fee_correction",
"ll_procurement_fee_correction_item",
"ll_procurement_flow",
"ll_procurement_label_item",
"ll_procurement_label_set",
"ll_procurement_manifest",
"ll_procurement_receipt",
"ll_procurement_repack",
"ll_procurement_shipment",
"ll_procurement_shipment_item",
"ll_procurement_wallet_attempt",
"ll_return_carton_stock_receipt",
"ll_selfop_inventory_daily",
"ll_selfop_inventory_day_version",
"ll_selfop_inventory_flow",
"ll_selfop_inventory_snapshot",
"ll_selfop_outbound_discovery_scope",
"ll_selfop_outbound_item",
"ll_selfop_outbound_order",
"ll_selfop_owner",
"ll_selfop_product",
"ll_selfop_sku_daily_sales",
"ll_selfop_sku_profile",
"ll_selfop_sync_run",
"ll_selfop_sync_scope",
"ll_selfop_sync_stage",
"ll_selfop_sync_task",
"ll_selfop_warehouse_daily_sales"
],
"addedColumns": [
"ll_cargo_discard_carton.source_type",
"ll_dispatch_draft.warehouse_id",
"ll_dispatch_draft.record_version",
"ll_dispatch_draft.sources_json",
"ll_dispatch_draft_container.source_keys_json",
"ll_dispatch_item.customer_name",
"ll_dispatch_item.source_key",
"ll_dispatch_item.source_version",
"ll_dispatch_item.source_snapshot_json",
"ll_dispatch_order.trip_id",
"ll_dispatch_order.overseas_warehouse_code",
"ll_dispatch_order.stage",
"ll_dispatch_order.record_version",
"ll_dispatch_order.cargo_revision",
"ll_dispatch_order.cargo_hash",
"ll_dispatch_order.review_state",
"ll_dispatch_order.review_round",
"ll_dispatch_order.review_basis_hash",
"ll_dispatch_order.dispatch_review_json",
"ll_dispatch_order.loading_review_json",
"ll_dispatch_order.resources_json",
"ll_dispatch_order.planned_departure_at",
"ll_dispatch_order.loading_completed_at",
"ll_dispatch_order.loading_completion_hash",
"ll_dispatch_order.loading_confirmation_json",
"ll_dispatch_order.arrangement_key",
"ll_dispatch_order.arrangement_business_hash",
"ll_dispatch_order.departed_at",
"ll_dispatch_order.delivery_completed_at",
"ll_dispatch_order.remark",
"ll_dispatch_pallet_lock.active_warehouse_pallet_id",
"ll_dropship_carton.product_quantity",
"ll_dropship_order_profile.manifest_version",
"ll_dropship_order_profile.manifest_package_count",
"ll_dropship_order_profile.manifest_fragment_count",
"ll_dropship_order_profile.manifest_hash",
"ll_exception_order.return_context_json",
"ll_exception_return_item.return_carton_id",
"ll_exception_return_item.return_carton_mark",
"ll_exception_return_item.received_packages",
"ll_inbound_fba_appointment.confirmation_no",
"ll_inbound_fba_appointment.planned_date",
"ll_inbound_fba_appointment.planned_at",
"ll_inbound_fba_appointment.planned_end_at",
"ll_inbound_fba_appointment.appointment_start_utc",
"ll_inbound_fba_appointment.appointment_end_utc",
"ll_inbound_fba_appointment.timezone",
"ll_inbound_fba_appointment.origin_warehouse_id",
"ll_inbound_fba_appointment.replacement_keys_json",
"ll_inbound_fba_appointment.repartition_reason",
"ll_inbound_fba_appointment_item.cargo_verification_version",
"ll_inbound_fba_appointment_item.shipment_references_json",
"ll_local_looseboard_order.product_name",
"ll_local_looseboard_order.estimated_pallet_count",
"ll_local_looseboard_order.origin_contact_name",
"ll_local_looseboard_order.origin_contact_phone",
"ll_local_looseboard_order.destination_contact_name",
"ll_local_looseboard_order.destination_contact_phone",
"ll_local_looseboard_order.pickup_at",
"ll_local_looseboard_order.delivery_at",
"ll_outbound_pallet_item.dispatch_item_id",
"ll_outbound_pallet_item.source_attribution_id",
"ll_outbound_pallet_item.source_order_id",
"ll_outbound_pallet_item.source_inventory_position_id",
"ll_outbound_pallet_item.source_return_receipt_id",
"ll_outbound_pallet_item.source_return_carton_id",
"ll_overseas_procurement_fee.purpose",
"ll_overseas_procurement_fee.confirmation_origin",
"ll_overseas_procurement_fee.fee_version",
"ll_overseas_procurement_fee.active",
"ll_overseas_procurement_fee.determination",
"ll_overseas_procurement_fee.original_currency",
"ll_overseas_procurement_fee.original_amount",
"ll_overseas_procurement_fee.exchange_rate",
"ll_overseas_procurement_fee.exchange_rate_month",
"ll_overseas_procurement_fee.business_date",
"ll_overseas_procurement_fee.wallet_business_id",
"ll_overseas_procurement_fee.wallet_business_no",
"ll_overseas_procurement_fee.wallet_hold_id",
"ll_overseas_procurement_fee.wallet_ledger_id",
"ll_overseas_procurement_fee.settled_command_event_id",
"ll_overseas_procurement_fee.source_fee_id",
"ll_overseas_procurement_fee.parent_fee_id",
"ll_overseas_procurement_fee.request_hash",
"ll_overseas_procurement_status_history.operation_type",
"ll_overseas_procurement_status_history.change_detail",
"ll_receiving_container_session.source_container_booking_id",
"ll_receiving_container_session.container_fact_hash",
"ll_receiving_container_session.overseas_warehouse_code",
"ll_return_inventory_outbound_movement.return_sku_quantity",
"ll_us_truck_order.vehicle_type",
"ll_us_truck_order.origin_contact_name",
"ll_us_truck_order.origin_contact_phone",
"ll_us_truck_order.destination_contact_name",
"ll_us_truck_order.destination_contact_phone",
"ll_us_truck_order.pickup_at",
"ll_us_truck_order.delivery_at"
],
"addedIndexes": [
"ll_cargo_discard_item.uk_ll_discard_position_sku",
"ll_dispatch_draft_container.uk_ll_dispatch_draft_container_sequence",
"ll_dispatch_order.uk_dispatch_trip",
"ll_dispatch_pallet_lock.uk_ll_dispatch_active_warehouse_pallet",
"ll_dispatch_pda_pick_order.idx_dispatch_pick_return_receipt",
"ll_dropship_order_profile.idx_ll_dropship_profile_manifest",
"ll_dropship_sku_inventory.uk_ll_dropship_sku_inventory",
"ll_exception_order.idx_ll_exception_delivery_return",
"ll_exception_return_item.uk_ll_exception_return_carton",
"ll_fleet_trip_dispatch.uk_fleet_trip_dispatch_trip",
"ll_inbound_fba_appointment.idx_ll_fba_appointment_planned",
"ll_inbound_fba_appointment_item.idx_ll_fba_active_source",
"ll_inbound_fba_appointment_item.idx_ll_fba_active_order",
"ll_inbound_plan_pallet.idx_ll_inbound_pallet_no",
"ll_outbound_pallet_item.uk_outbound_source_attribution",
"ll_overseas_procurement_fee.uk_ll_procurement_fee_version",
"ll_return_packing_plan.idx_ll_return_packing_plan_warehouse",
"ll_warehouse_transfer_inventory_allocation.idx_ll_wh_transfer_allocation_position"
]
},
"baiyue_firstleg": {
"createdTables": [
"event_delivery_retry_audit",
"fl_chargeable_weight_confirmation",
"fl_customs_broker_submission",
"fl_customs_clearance_result",
"fl_customs_completion_action_history",
"fl_customs_declaration_batch",
"fl_sailing",
"fl_sailing_assignment",
"fl_sailing_booking_link",
"fl_sailing_channel",
"fl_sailing_history",
"fl_sailing_inbound_volume_forecast",
"fl_sailing_receipt_batch_fact",
"fl_sailing_template"
],
"addedColumns": [
"fl_customs_completion_document.customer_confirm_status",
"fl_customs_completion_document.customer_confirmed_by",
"fl_customs_completion_document.customer_confirmed_by_name",
"fl_customs_completion_document.customer_confirmed_at",
"fl_customs_completion_document.customer_reject_reason",
"fl_fee_item.default_price"
],
"addedIndexes": [
"fl_carrier_schedule_node_fact.idx_container_shipping_node_timeline",
"fl_container_booking.uk_container_booking_ocean_container",
"fl_container_booking.idx_container_booking_container_no",
"fl_container_booking.idx_container_booking_merge",
"fl_container_booking.idx_container_booking_transit_summary",
"fl_container_fee_detail.idx_container_fee_review",
"fl_container_transport_history.uk_container_transport_history_operation",
"fl_customer_charge_rule.idx_charge_rule_initialization",
"fl_inbound_measurement.idx_measure_inbound_status_id",
"fl_inbound_measurement_item.idx_measure_item_candidate",
"fl_inbound_order.idx_inbound_smart_loading",
"fl_inbound_split_item.idx_inbound_split_candidate",
"fl_loading_plan_item.uk_loading_item_plan_assignment",
"fl_loading_plan_item.idx_loading_item_candidate",
"fl_loading_plan_item.idx_loading_item_pallet",
"fl_ocean_booking.uk_ocean_booking_bill_of_lading",
"fl_truck_appointment.uk_truck_active_ocean_booking",
"fl_truck_appointment.idx_truck_appointment_ocean"
]
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,116 @@
[
{
"status": "PENDING_REVIEW",
"count": 127,
"total": 127,
"passed": true
},
{
"status": "WAIT_MEASURE",
"count": 195,
"total": 195,
"passed": true
},
{
"status": "WAIT_WEIGHT_CONFIRM",
"count": 125,
"total": 125,
"passed": true
},
{
"status": "WEIGHT_CONFIRMED",
"count": 1,
"total": 1,
"passed": true
},
{
"status": "WAIT_CUSTOMS_DOCS",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "WAIT_PALLETIZE",
"count": 6,
"total": 6,
"passed": true
},
{
"status": "WAIT_SPLIT",
"count": 126,
"total": 126,
"passed": true
},
{
"status": "LOADING",
"count": 9,
"total": 9,
"passed": true
},
{
"status": "LOADED",
"count": 73,
"total": 73,
"passed": true
},
{
"status": "EXPORT_CUSTOMS",
"count": 12,
"total": 12,
"passed": true
},
{
"status": "SAILING_CLEARANCE",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "WAIT_UNLOAD",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "WAIT_DISPATCH",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "OUTBOUND_DOCUMENT",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "DELIVERING",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "SIGNED",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "DELIVERED",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "COMPLETED",
"count": 2,
"total": 2,
"passed": true
},
{
"status": "MEASUREMENT_REVIEW",
"count": 120,
"total": 120,
"passed": true
}
]
@@ -0,0 +1,523 @@
[
{
"path": "/api/auth/login",
"http": 200,
"code": "200",
"requestId": "d8386ec4-397e-479f-a02f-ed5248d2d772, 3b6b0258-8944-403d-8290-b2a3f6393bd4",
"passed": true
},
{
"path": "/api/platform/v1/orders/status-counts",
"http": 200,
"code": "200",
"requestId": "36a52333-5a14-4eea-a5ed-bd3f5b77bd95, 83a342cc-b86b-44ce-a70b-5cd38d043caa",
"passed": true,
"counts": {
"PENDING_REVIEW": 127,
"WAIT_MEASURE": 195,
"WAIT_PALLETIZE": 6,
"WAIT_SPLIT": 126,
"LOADING": 9,
"LOADED": 73,
"DELIVERED": 0,
"COMPLETED": 2,
"WAIT_WEIGHT_CONFIRM": 125,
"WEIGHT_CONFIRMED": 1,
"WAIT_CUSTOMS_DOCS": 0,
"EXPORT_CUSTOMS": 12,
"SAILING_CLEARANCE": 0,
"WAIT_UNLOAD": 0,
"WAIT_DISPATCH": 0,
"OUTBOUND_DOCUMENT": 0,
"DELIVERING": 0,
"SIGNED": 0,
"MEASUREMENT_REVIEW": 120
}
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=PENDING_REVIEW",
"http": 200,
"code": "200",
"requestId": "cec5abdd-3d32-4ec4-9646-ee82ae4bbb53, 2ceadbc6-b8b5-4966-bb5f-14785549e57e",
"passed": true,
"total": "127",
"records": [
{
"orderId": "2112105953787518978",
"tenantId": "2112105501490544641",
"inboundId": "2112105957231161346",
"mainStatus": "PENDING_REVIEW"
},
{
"orderId": "2112105886309556225",
"tenantId": "2112105195373461506",
"inboundId": "2112105890017439745",
"mainStatus": "PENDING_REVIEW"
},
{
"orderId": "2112105822484832258",
"tenantId": "2112105195373461506",
"inboundId": "2112105825983000577",
"mainStatus": "PENDING_REVIEW"
},
{
"orderId": "2112105768302813186",
"tenantId": "2112105195373461506",
"inboundId": "2112105772081999873",
"mainStatus": "PENDING_REVIEW"
},
{
"orderId": "2112105682319581185",
"tenantId": "2112105501490544641",
"inboundId": "2112105687122178049",
"mainStatus": "PENDING_REVIEW"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_MEASURE",
"http": 200,
"code": "200",
"requestId": "970d462f-c6c0-4be5-a625-f56bcd015380, 97d186ed-00e7-4d2c-84c3-e4cf8bd264b8",
"passed": true,
"total": "195",
"records": [
{
"orderId": "2112102981498183681",
"tenantId": "2112102958765047809",
"inboundId": "2112103003577118721",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2098325342631428097",
"tenantId": "2098324852501774338",
"inboundId": "2098325343935848449",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2098325190034259969",
"tenantId": "2098324852501774338",
"inboundId": "2098325191338680322",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2098325037621641217",
"tenantId": "2098324852501774338",
"inboundId": "2098325038921867265",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2098324887905959938",
"tenantId": "2098324852501774338",
"inboundId": "2098324891550801921",
"mainStatus": "WAIT_MEASURE"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_WEIGHT_CONFIRM",
"http": 200,
"code": "200",
"requestId": "3df59adf-731b-4388-bf88-4439adf9fa90, d2d74f05-5875-4b2f-93ff-e161dbe4186e",
"passed": true,
"total": "125",
"records": [
{
"orderId": "2085355345216114689",
"tenantId": "2085308606829346818",
"inboundId": "2085355347941904385",
"mainStatus": null
},
{
"orderId": "2085355345975283713",
"tenantId": "2085308606829346818",
"inboundId": "2085355347992236034",
"mainStatus": null
},
{
"orderId": "2085355346734452738",
"tenantId": "2085308606829346818",
"inboundId": "2085355360826806273",
"mainStatus": null
},
{
"orderId": "2085355347493621762",
"tenantId": "2085308606829346818",
"inboundId": "2085355360881332226",
"mainStatus": null
},
{
"orderId": "2085355348282150913",
"tenantId": "2085308606829346818",
"inboundId": "2085355360931663873",
"mainStatus": null
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WEIGHT_CONFIRMED",
"http": 200,
"code": "200",
"requestId": "089af451-73c8-461d-9e7f-d39305be69e7, dc1098ac-4bc2-4538-852a-4e592363658b",
"passed": true,
"total": "1",
"records": [
{
"orderId": "2085341741574098946",
"tenantId": "2085308606829346818",
"inboundId": "2085341749429522434",
"mainStatus": null
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_CUSTOMS_DOCS",
"http": 200,
"code": "200",
"requestId": "789f82d6-5b7e-4f28-b542-12c4537f695c, 94e8eb5d-c0d9-4f0c-854d-2df1458c81be",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_PALLETIZE",
"http": 200,
"code": "200",
"requestId": "9fca92f3-47d2-4a5b-9360-73ba15570f8b, d66b74f3-a292-418f-91d3-5b364e5d1141",
"passed": true,
"total": "6",
"records": [
{
"orderId": "2112105882580819970",
"tenantId": "2112105195373461506",
"inboundId": "2112105899853082626",
"mainStatus": "WAIT_PALLETIZE"
},
{
"orderId": "2112105818881925122",
"tenantId": "2112105195373461506",
"inboundId": "2112105836158382082",
"mainStatus": "WAIT_PALLETIZE"
},
{
"orderId": "2112105764741849089",
"tenantId": "2112105195373461506",
"inboundId": "2112105781263331330",
"mainStatus": "WAIT_PALLETIZE"
},
{
"orderId": "2112104925457424385",
"tenantId": "2112104631512203266",
"inboundId": "2112104942167650305",
"mainStatus": "WAIT_PALLETIZE"
},
{
"orderId": "2112104871636115457",
"tenantId": "2112104551203864578",
"inboundId": "2112104887486509058",
"mainStatus": "WAIT_PALLETIZE"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_SPLIT",
"http": 200,
"code": "200",
"requestId": "c051f77b-bf8b-40f7-ae48-b0199c425a2c, 379ba9b5-caa8-4ba6-b7bc-ae5e9a1b7096",
"passed": true,
"total": "126",
"records": [
{
"orderId": "2112105949454802945",
"tenantId": "2112105501490544641",
"inboundId": "2112105974222286850",
"mainStatus": "WAIT_SPLIT"
},
{
"orderId": "2112105677974282242",
"tenantId": "2112105501490544641",
"inboundId": "2112105696567750658",
"mainStatus": "WAIT_SPLIT"
},
{
"orderId": "2112105550538743809",
"tenantId": "2112105501490544641",
"inboundId": "2112105615210835970",
"mainStatus": "WAIT_SPLIT"
},
{
"orderId": "2112105269298077697",
"tenantId": "2112105195373461506",
"inboundId": "2112105371026845697",
"mainStatus": "WAIT_SPLIT"
},
{
"orderId": "2112104769605476353",
"tenantId": "2112104551203864578",
"inboundId": "2112104783950114818",
"mainStatus": "WAIT_SPLIT"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=LOADING",
"http": 200,
"code": "200",
"requestId": "f1731715-f948-457e-9e66-95bcae492242, d1559d04-db13-41e0-85fa-b0776f32c224",
"passed": true,
"total": "9",
"records": [
{
"orderId": "2092816910277038081",
"tenantId": "2092816814294667266",
"inboundId": "2092816913754202115",
"mainStatus": "LOADING"
},
{
"orderId": "2092816871253233665",
"tenantId": "2092816814294667266",
"inboundId": "2092816875699281923",
"mainStatus": "LOADING"
},
{
"orderId": "2092816836365012994",
"tenantId": "2092816814294667266",
"inboundId": "2092816850256633858",
"mainStatus": "LOADING"
},
{
"orderId": "2092814878690398210",
"tenantId": "2092814835845664769",
"inboundId": "2092814880129130499",
"mainStatus": "LOADING"
},
{
"orderId": "2091000814000001101",
"tenantId": "10001",
"inboundId": "2091000814000001301",
"mainStatus": "LOADING"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=LOADED",
"http": 200,
"code": "200",
"requestId": "8adb0c88-721d-49e5-ae76-400c43aebf81, 4b3c1edd-8a2e-40c4-82ac-36ac366afe8c",
"passed": true,
"total": "73",
"records": [
{
"orderId": "2093269574496440322",
"tenantId": "2093269089353961474",
"inboundId": "2093269587792433154",
"mainStatus": "LOADED"
},
{
"orderId": "2093269527184691202",
"tenantId": "2093269089353961474",
"inboundId": "2093269537020383234",
"mainStatus": "LOADED"
},
{
"orderId": "2093269460814024706",
"tenantId": "2093269089353961474",
"inboundId": "2093269473657032707",
"mainStatus": "LOADED"
},
{
"orderId": "2093269413967843329",
"tenantId": "2093269089353961474",
"inboundId": "2093269422700433411",
"mainStatus": "LOADED"
},
{
"orderId": "2093269346426966017",
"tenantId": "2093269089353961474",
"inboundId": "2093269359261585410",
"mainStatus": "LOADED"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=EXPORT_CUSTOMS",
"http": 200,
"code": "200",
"requestId": "ef20726d-cda3-4f23-b1aa-b05efe574617, 9e8b9d3d-bd7b-43b4-bd3e-f7488276292a",
"passed": true,
"total": "12",
"records": [
{
"orderId": "2086081433932726274",
"tenantId": "10001",
"inboundId": "2086081437650956290",
"mainStatus": null
},
{
"orderId": "2086085225151528961",
"tenantId": "10001",
"inboundId": "2086085239259049985",
"mainStatus": null
},
{
"orderId": "2086085487601713154",
"tenantId": "10001",
"inboundId": "2086085491298971650",
"mainStatus": null
},
{
"orderId": "2086086464165707778",
"tenantId": "10001",
"inboundId": "2086086473193926658",
"mainStatus": null
},
{
"orderId": "2086088193535967234",
"tenantId": "10001",
"inboundId": "2086088197887537154",
"mainStatus": null
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=SAILING_CLEARANCE",
"http": 200,
"code": "200",
"requestId": "152a2d06-7280-40ca-b2b4-e431e38aad09, 038f2149-53ea-4d8d-80c2-f179a964be24",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_UNLOAD",
"http": 200,
"code": "200",
"requestId": "39d0e8cf-3864-4353-a368-e1d534d80b31, 7a5cd168-cb61-4459-b20a-f2f2313941e0",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_DISPATCH",
"http": 200,
"code": "200",
"requestId": "f2b1a845-bed6-4816-8b8f-eafd958ec354, 33d70b80-347e-42c8-a9f7-2850abc390e3",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=OUTBOUND_DOCUMENT",
"http": 200,
"code": "200",
"requestId": "507b600b-e51a-4dfd-a1b4-4e521a8a5b43, 8d82c176-67f8-4f2d-a67e-cb1f07cb8bb9",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=DELIVERING",
"http": 200,
"code": "200",
"requestId": "a4ce3c7c-093c-46ef-86f4-562713de83fa, 7800d83e-902c-4596-8a2c-9ac5622999e1",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=SIGNED",
"http": 200,
"code": "200",
"requestId": "1d9273c0-16b9-46a7-8d91-de893b3fda4e, 8e2e2611-b64a-4875-975b-3f70247d2ba8",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=DELIVERED",
"http": 200,
"code": "200",
"requestId": "15254699-ce87-40d2-ab92-524be410a608, 03296c5a-921c-474b-bc94-b163d9bbeca9",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=COMPLETED",
"http": 200,
"code": "200",
"requestId": "e0ba9860-9602-40e7-9480-a8f270ab2ada, aaf30bb1-06be-454a-8f94-051961520d6b",
"passed": true,
"total": "2",
"records": [
{
"orderId": "2084515377635758081",
"tenantId": "2084513933705150465",
"inboundId": "2085623586303365121",
"mainStatus": "COMPLETED"
},
{
"orderId": "2084210113483173890",
"tenantId": "10001",
"inboundId": "2085623585678413826",
"mainStatus": "COMPLETED"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=MEASUREMENT_REVIEW",
"http": 200,
"code": "200",
"requestId": "c19b7ce9-6fd0-4d0b-a21a-7c89ba39b244, 756e5250-341e-4b41-998d-419a68fc9102",
"passed": true,
"total": "120",
"records": [
{
"orderId": "2085355293542289410",
"tenantId": "2085308606829346818",
"inboundId": "2085355307198435329",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2085355294326624258",
"tenantId": "2085308606829346818",
"inboundId": "2085355307252961281",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2085355295115153410",
"tenantId": "2085308606829346818",
"inboundId": "2085355307303292930",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2085355295895293953",
"tenantId": "2085308606829346818",
"inboundId": "2085355307357818882",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2085355296650268673",
"tenantId": "2085308606829346818",
"inboundId": "2085355307408150530",
"mainStatus": "WAIT_MEASURE"
}
]
},
{
"path": "9202/actuator/health",
"http": 200,
"body": {
"status": "UP"
},
"passed": true
},
{
"path": "9303/actuator/health",
"http": 200,
"body": {
"status": "UP"
},
"passed": true
}
]
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,357 @@
-- 本地服务结构补齐;仅创建缺失表、添加缺失字段,不删除现有数据。
SET NAMES utf8mb4;
CREATE TABLE fl_customs_broker_submission (
id bigint unsigned NOT NULL COMMENT '首次发送报关行批次ID',
customs_container_id bigint unsigned NOT NULL COMMENT '所属整柜报关聚合ID',
loading_plan_id bigint unsigned NOT NULL COMMENT '装柜计划ID快照',
batch_no varchar(64) NOT NULL COMMENT '首次发送报关行批次号',
status varchar(16) NOT NULL COMMENT '发送状态:SENT已发送',
source_version int unsigned NOT NULL COMMENT '发送时整柜报关聚合版本',
source_snapshot_json json NOT NULL COMMENT '发送时冻结资料版本与覆盖范围快照',
sent_by bigint unsigned NOT NULL COMMENT '首次发送操作人ID',
sent_by_name varchar(64) DEFAULT NULL COMMENT '首次发送操作人名称快照',
sent_at datetime(3) NOT NULL COMMENT '首次发送时间',
version int unsigned NOT NULL DEFAULT '1' 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_customs_broker_submission_container (customs_container_id),
UNIQUE KEY uk_customs_broker_submission_batch (batch_no),
KEY idx_customs_broker_submission_plan (loading_plan_id,sent_at),
CONSTRAINT fk_customs_broker_submission_container FOREIGN KEY (customs_container_id) REFERENCES fl_customs_container (id),
CONSTRAINT chk_customs_broker_submission_status CHECK ((status in (_utf8mb4'SENT')))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='冻结退税报关资料首次发送报关行批次事实';
ALTER TABLE `fl_customs_completion_document` ADD COLUMN customer_confirm_status varchar(20) NOT NULL DEFAULT 'PENDING' COMMENT '客户回执确认状态:PENDING/CONFIRMED/REJECTED';
ALTER TABLE `fl_customs_completion_document` ADD COLUMN customer_confirmed_by bigint unsigned DEFAULT NULL COMMENT '客户确认人ID';
ALTER TABLE `fl_customs_completion_document` ADD COLUMN customer_confirmed_by_name varchar(64) DEFAULT NULL COMMENT '客户确认人名称快照';
ALTER TABLE `fl_customs_completion_document` ADD COLUMN customer_confirmed_at datetime(3) DEFAULT NULL COMMENT '客户确认时间';
ALTER TABLE `fl_customs_completion_document` ADD COLUMN customer_reject_reason varchar(500) DEFAULT NULL COMMENT '客户打回原因';
CREATE TABLE fl_customs_completion_action_history (
id bigint unsigned NOT NULL COMMENT '客户回执动作历史ID',
completion_document_id bigint unsigned NOT NULL COMMENT '报关行回执当前版本逻辑根ID',
receipt_version int unsigned NOT NULL COMMENT '动作对应的回执文件版本',
action varchar(16) NOT NULL COMMENT '客户动作:CONFIRM确认、REJECT打回',
reason varchar(500) DEFAULT NULL COMMENT '客户打回原因;确认动作为空',
operator_id bigint unsigned NOT NULL COMMENT '客户操作人ID',
operator_name varchar(64) DEFAULT NULL COMMENT '客户操作人名称快照',
created_at datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '客户动作时间',
PRIMARY KEY (id),
KEY idx_customs_completion_action_history (completion_document_id,receipt_version,created_at,id),
CONSTRAINT fk_customs_completion_action_history_document FOREIGN KEY (completion_document_id) REFERENCES fl_customs_completion_document (id),
CONSTRAINT chk_customs_completion_action_history_action CHECK ((action in (_utf8mb4'CONFIRM',_utf8mb4'REJECT')))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='客户报关行回执确认与打回不可变历史';
CREATE TABLE fl_customs_declaration_batch (
id BIGINT UNSIGNED NOT NULL COMMENT '正式申报批次ID',
customs_container_id BIGINT UNSIGNED NOT NULL COMMENT '所属整柜报关聚合ID',
loading_plan_id BIGINT UNSIGNED NOT NULL COMMENT '装柜计划ID快照',
batch_no VARCHAR(64) NULL COMMENT '平台正式申报批次号',
status VARCHAR(32) NOT NULL COMMENT '批次状态:READY/SUBMITTED/ACKNOWLEDGED/RESULT_PENDING/CLOSED/CANCELLED',
source_version INT UNSIGNED NOT NULL COMMENT '创建时整柜报关聚合版本',
source_snapshot_json JSON NOT NULL COMMENT '提交时资料、回执和确认版本快照',
customs_entry_no VARCHAR(64) NULL COMMENT '报关单号',
submitted_by BIGINT UNSIGNED NULL COMMENT '正式申报提交人',
submitted_by_name VARCHAR(64) NULL COMMENT '正式申报提交人名称快照',
submitted_at DATETIME(3) NULL COMMENT '正式申报提交时间',
acknowledged_by BIGINT UNSIGNED NULL COMMENT '报关行确认受理人',
acknowledged_by_name VARCHAR(64) NULL COMMENT '报关行确认受理人名称快照',
acknowledged_at DATETIME(3) NULL COMMENT '报关行确认受理时间',
remark VARCHAR(500) NULL COMMENT '批次说明',
version INT UNSIGNED NOT NULL DEFAULT 0 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_customs_declaration_batch_container(customs_container_id, id),
KEY idx_customs_declaration_batch_plan(loading_plan_id,status,created_at),
CONSTRAINT fk_customs_declaration_batch_container FOREIGN KEY(customs_container_id) REFERENCES fl_customs_container(id),
CONSTRAINT chk_customs_declaration_batch_status CHECK(status IN ('READY','SUBMITTED','ACKNOWLEDGED','RESULT_PENDING','CLOSED','CANCELLED'))
) ENGINE=InnoDB COMMENT='整柜正式申报批次事实';
CREATE TABLE fl_customs_clearance_result (
id BIGINT UNSIGNED NOT NULL COMMENT '海关结果事实ID',
declaration_batch_id BIGINT UNSIGNED NOT NULL COMMENT '所属正式申报批次ID',
customs_container_id BIGINT UNSIGNED NOT NULL COMMENT '所属整柜报关聚合ID',
result_type VARCHAR(32) NOT NULL COMMENT '结果类型:INSPECTION/SUPPLEMENT_REQUIRED/RELEASED/DETAINED/OTHER',
result_status VARCHAR(16) NOT NULL DEFAULT 'OPEN' COMMENT '结果状态:OPEN/RESOLVED/CANCELLED',
customs_entry_no VARCHAR(64) NULL COMMENT '报关单号快照',
occurred_at DATETIME(3) NOT NULL COMMENT '海关事实发生时间',
resolution VARCHAR(1000) NULL COMMENT '处理结果或异常说明',
evidence_file_id BIGINT UNSIGNED NULL COMMENT '结果凭证File文件ID',
recorded_by BIGINT UNSIGNED NOT NULL COMMENT '平台录入人',
recorded_by_name VARCHAR(64) NULL COMMENT '平台录入人名称快照',
recorded_at DATETIME(3) NOT NULL COMMENT '平台录入时间',
previous_result_id BIGINT UNSIGNED NULL COMMENT '前序结果事实ID',
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),
KEY idx_customs_clearance_result_batch(declaration_batch_id,occurred_at,id),
KEY idx_customs_clearance_result_container(customs_container_id, result_type, result_status),
CONSTRAINT fk_customs_clearance_result_batch FOREIGN KEY(declaration_batch_id) REFERENCES fl_customs_declaration_batch(id),
CONSTRAINT chk_customs_clearance_result_type CHECK(result_type IN ('INSPECTION','SUPPLEMENT_REQUIRED','RELEASED','DETAINED','OTHER')),
CONSTRAINT chk_customs_clearance_result_status CHECK(result_status IN ('OPEN','RESOLVED','CANCELLED'))
) ENGINE=InnoDB COMMENT='正式申报后的海关结果不可变事实';
ALTER TABLE `fl_fee_item` ADD COLUMN default_price decimal(12,2) DEFAULT NULL COMMENT '默认价格CNY;仅选费带入,实际费用可修改';
CREATE TABLE fl_chargeable_weight_confirmation (
id BIGINT NOT NULL COMMENT '确认记录ID',
tenant_id BIGINT NOT NULL COMMENT '客户隔离ID',
inbound_id BIGINT NOT NULL COMMENT '独立来源入仓单ID',
operator_id BIGINT NOT NULL COMMENT '确认客户成员ID',
command_key VARCHAR(128) NOT NULL COMMENT '成员确认幂等键',
fingerprint CHAR(64) NOT NULL COMMENT '计费重及测量轮次摘要',
chargeable_weight_kg DECIMAL(18,4) NOT NULL COMMENT '客户确认计费重千克',
confirmed_at DATETIME(3) NOT NULL COMMENT '客户确认时间',
PRIMARY KEY(id), UNIQUE KEY uk_weight_confirmation_command(tenant_id,operator_id,command_key),
KEY idx_weight_confirmation_inbound(tenant_id,inbound_id,id)
) ENGINE=InnoDB COMMENT='客户计费重独立确认历史';
CREATE TABLE fl_sailing_channel (
id BIGINT NOT NULL,
channel_code VARCHAR(64) NOT NULL,
channel_name VARCHAR(128) NOT NULL,
source_type VARCHAR(24) NOT NULL,
mapped_channel_code VARCHAR(64) NULL,
default_departure_port_code VARCHAR(32) NULL,
default_destination_port_code VARCHAR(32) NULL,
default_cutoff_days TINYINT NOT NULL DEFAULT 3,
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
remark VARCHAR(1000) NULL,
created_by BIGINT NOT NULL,
created_by_name VARCHAR(128) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_by BIGINT NOT NULL,
updated_by_name VARCHAR(128) NULL,
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
version INT NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY uk_fl_sailing_channel_code (channel_code),
KEY idx_fl_sailing_channel_status (status)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE fl_sailing_template (
id BIGINT NOT NULL,
template_no VARCHAR(64) NOT NULL,
template_name VARCHAR(128) NOT NULL,
channel_id BIGINT NOT NULL,
channel_code_snapshot VARCHAR(64) NOT NULL,
channel_name_snapshot VARCHAR(128) NOT NULL,
warehouse_id BIGINT NOT NULL,
warehouse_name_snapshot VARCHAR(128) NULL,
departure_port_code VARCHAR(32) NOT NULL,
destination_port_code VARCHAR(32) NOT NULL,
weekday TINYINT NOT NULL,
weekday_mask TINYINT NOT NULL DEFAULT 1,
etd_local_time TIME NOT NULL,
cutoff_days TINYINT NOT NULL DEFAULT 3,
cutoff_local_time TIME NOT NULL DEFAULT '18:00:00',
valid_from DATE NOT NULL,
valid_to DATE NULL,
voyage_rule VARCHAR(64) NULL,
vessel_name VARCHAR(128) NULL,
status VARCHAR(16) NOT NULL DEFAULT 'ACTIVE',
remark VARCHAR(1000) NULL,
created_by BIGINT NOT NULL,
created_by_name VARCHAR(128) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_by BIGINT NOT NULL,
updated_by_name VARCHAR(128) NULL,
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
version INT NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY uk_fl_sailing_template_no (template_no),
KEY idx_fl_sailing_template_filter (warehouse_id,channel_id,status,weekday),
CONSTRAINT ck_fl_sailing_template_weekday CHECK (weekday BETWEEN 1 AND 7),
CONSTRAINT ck_fl_sailing_template_cutoff_days CHECK (cutoff_days BETWEEN 0 AND 30)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE fl_sailing (
id BIGINT NOT NULL,
sailing_no VARCHAR(64) NOT NULL,
template_id BIGINT NULL,
channel_id BIGINT NOT NULL,
channel_code_snapshot VARCHAR(64) NOT NULL,
channel_name_snapshot VARCHAR(128) NOT NULL,
warehouse_id BIGINT NOT NULL,
warehouse_name_snapshot VARCHAR(128) NULL,
departure_port_code VARCHAR(32) NOT NULL,
destination_port_code VARCHAR(32) NOT NULL,
vessel_name VARCHAR(128) NULL,
voyage_no VARCHAR(64) NULL,
etd_at DATETIME(3) NOT NULL,
warehouse_cutoff_at DATETIME(3) NOT NULL,
eta_at DATETIME(3) NULL,
status VARCHAR(16) NOT NULL DEFAULT 'OPEN',
source_type VARCHAR(24) NOT NULL DEFAULT 'MANUAL',
generated_key VARCHAR(192) NULL,
planned_capacity_cbm DECIMAL(14,3) NULL,
remark VARCHAR(1000) NULL,
created_by BIGINT NOT NULL,
created_by_name VARCHAR(128) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
updated_by BIGINT NOT NULL,
updated_by_name VARCHAR(128) NULL,
updated_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3),
version INT NOT NULL DEFAULT 0,
PRIMARY KEY (id),
UNIQUE KEY uk_fl_sailing_no (sailing_no),
UNIQUE KEY uk_fl_sailing_generated_key (generated_key),
UNIQUE KEY uk_fl_sailing_business (warehouse_id,channel_code_snapshot,departure_port_code,destination_port_code,etd_at,voyage_no),
KEY idx_fl_sailing_calendar (etd_at,warehouse_id,channel_id,status),
KEY idx_fl_sailing_route (departure_port_code,destination_port_code),
CONSTRAINT ck_fl_sailing_status CHECK (status IN ('DRAFT','OPEN','CLOSED','DEPARTED','CANCELLED','COMPLETED'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE fl_sailing_history (
id BIGINT NOT NULL,
sailing_id BIGINT NOT NULL,
action VARCHAR(32) NOT NULL,
from_status VARCHAR(16) NULL,
to_status VARCHAR(16) NULL,
reason VARCHAR(1000) NULL,
operator_id BIGINT NULL,
operator_name VARCHAR(128) NULL,
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
PRIMARY KEY (id),
KEY idx_fl_sailing_history_sailing (sailing_id,created_at,id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
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='船期计划与已放舱订舱的最小关联及历史';
CREATE TABLE event_delivery_retry_audit (
request_id VARCHAR(36) NOT NULL COMMENT '人工重试请求UUID和幂等键',
producer_table VARCHAR(64) NOT NULL COMMENT '本服务发件箱表名',
entry_id VARCHAR(64) NOT NULL COMMENT '发件箱记录主键',
event_id VARCHAR(128) NOT NULL COMMENT '原事件全局标识',
event_type VARCHAR(64) NOT NULL COMMENT '原事件类型',
payload_hash VARCHAR(71) NOT NULL COMMENT '原事件不可变负载摘要',
operator_name VARCHAR(128) NOT NULL COMMENT '持有运维凭据的操作人标识',
reason VARCHAR(500) NOT NULL COMMENT '人工重试原因',
previous_failures INT NOT NULL COMMENT '重试前累计失败次数',
previous_error VARCHAR(1000) NULL COMMENT '重试前最后一次脱敏错误',
requested_at DATETIME(3) NOT NULL COMMENT '重试申请提交时间',
PRIMARY KEY (request_id),
KEY idx_event_retry_entry (producer_table,entry_id,requested_at),
KEY idx_event_retry_event (event_id,requested_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='业务事件人工重试审计,与恢复待发送状态同事务提交';
@@ -0,0 +1,29 @@
{
"baselineTables": 131,
"actualTables": 128,
"addedTables": [
"fl_customs_broker_submission",
"fl_customs_completion_action_history",
"fl_customs_declaration_batch",
"fl_customs_clearance_result",
"fl_chargeable_weight_confirmation",
"fl_sailing_channel",
"fl_sailing_template",
"fl_sailing",
"fl_sailing_history",
"fl_sailing_receipt_batch_fact",
"fl_sailing_inbound_volume_forecast",
"fl_sailing_assignment",
"fl_sailing_booking_link",
"event_delivery_retry_audit"
],
"addedColumns": [
"fl_customs_completion_document.customer_confirm_status",
"fl_customs_completion_document.customer_confirmed_by",
"fl_customs_completion_document.customer_confirmed_by_name",
"fl_customs_completion_document.customer_confirmed_at",
"fl_customs_completion_document.customer_reject_reason",
"fl_fee_item.default_price"
],
"unsafe": []
}
@@ -0,0 +1,84 @@
[
{
"path": "/api/auth/login",
"http": 200,
"code": "200",
"requestId": "83e3631c-8cda-4729-80c4-106a1a6275d6, b8d91668-aad6-4513-bc55-9e1e8e2312c1",
"passed": true
},
{
"path": "/api/platform/v1/last-leg/orders?page=1&size=5",
"http": 200,
"code": "200",
"requestId": "3ececcb5-f6d3-452d-b675-83a1422132ab, 3494117d-b608-442c-86d3-930723d31c72",
"passed": true
},
{
"path": "/api/platform/v1/last-leg/dispatches?page=1&size=5",
"http": 200,
"code": "200",
"requestId": "9f1a9717-a0b7-4400-ae51-5e95695bdbb3, 2867b52e-a75c-4375-97fc-3b785414944e",
"passed": true
},
{
"path": "/api/platform/v1/last-leg/dispatches/drafts?page=1&size=5",
"http": 200,
"code": "200",
"requestId": "b7e68664-fa9f-4e57-93f5-560ca5c7afe7, 81e0d34d-c37e-4160-84d6-1d77d25b7549",
"passed": true
},
{
"path": "/api/platform/v1/last-leg/appointment-work/summary",
"http": 200,
"code": "A0403",
"message": "Access denied",
"requestId": "43f418ef-f7d3-4fad-a506-1ff1e909404d, e45bdbc3-25a0-42c3-8ba0-67d3dda55408",
"passed": false
},
{
"path": "/api/platform/inbounds?page=1&size=5",
"http": 200,
"code": "200",
"requestId": "c2db90b4-0132-4ebb-bf01-65bbdd4e8f72, af8884fb-8002-4d59-a3c0-89310f36e614",
"passed": true
},
{
"path": "/api/platform/v1/first-leg/tasks?tenantId=10001&page=1&size=5",
"http": 200,
"code": "200",
"requestId": "b9ce00ca-d62c-41dc-a752-7f83d8f72786, 264cbdd1-f6a5-4317-95b2-280f09772e41",
"passed": true
},
{
"path": "/api/platform/v1/sailing-channels",
"http": 200,
"code": "A0403",
"message": "Access denied",
"requestId": "b9d52e7d-b9e4-434b-9daf-74a492cb4176, bb9b768f-c314-4d6e-a45d-6b99c697fe07",
"passed": false
},
{
"path": "/api/platform/v1/sailing-templates?page=1&size=5",
"http": 200,
"code": "A0403",
"message": "Access denied",
"requestId": "d88b13dc-af9d-43b7-ad44-cd7ec30e4fb0, 4fdc6213-1b44-48ae-bfcf-22ee6917a8d3",
"passed": false
},
{
"path": "9202/actuator/health",
"http": 200,
"body": {
"status": "UP"
},
"passed": true
},
{
"path": "9303/actuator/health",
"http": 200,
"body": {
"status": "UP"
},
"passed": true
}
]
+25
View File
@@ -0,0 +1,25 @@
import fs from 'node:fs';
const base=process.env.ADMIN_TEST_GATEWAY;
if(!base||!['127.0.0.1','localhost'].includes(new URL(base).hostname))throw new Error('仅允许本机');
let token='';const checks=[];
async function call(path,body) {
const r=await fetch(base+path,{method:body?'POST':'GET',headers:{...(token?{Authorization:'Bearer '+token}:{}),...(body?{'Content-Type':'application/json'}:{})},body:body?JSON.stringify(body):undefined,signal:AbortSignal.timeout(45000)});
const value=await r.json().catch(()=>null);
checks.push({path,http:r.status,code:value?.code,message:String(value?.code)==='200'?undefined:value?.message,requestId:r.headers.get('x-request-id'),passed:r.status===200&&String(value?.code)==='200'});
fs.writeFileSync(new URL('http-smoke.json',import.meta.url),JSON.stringify(checks,null,2));
return value;
}
const login=await call('/api/auth/login',{loginId:process.env.ADMIN_TEST_USERNAME,password:process.env.ADMIN_TEST_PASSWORD});
if(!login?.data?.accessToken)throw new Error('本地登录失败');token=login.data.accessToken;
for(const path of [
'/api/platform/v1/last-leg/orders?page=1&size=5',
'/api/platform/v1/last-leg/dispatches?page=1&size=5',
'/api/platform/v1/last-leg/dispatches/drafts?page=1&size=5',
'/api/platform/v1/last-leg/appointment-work/summary',
'/api/platform/inbounds?page=1&size=5',
'/api/platform/v1/first-leg/tasks?tenantId=10001&page=1&size=5',
'/api/platform/v1/sailing-channels',
'/api/platform/v1/sailing-templates?page=1&size=5'
])await call(path);
for(const port of [9202,9303]){const r=await fetch(`http://127.0.0.1:${port}/actuator/health`);checks.push({path:`${port}/actuator/health`,http:r.status,body:await r.json(),passed:r.ok});}
fs.writeFileSync(new URL('http-smoke.json',import.meta.url),JSON.stringify(checks,null,2));console.log(JSON.stringify(checks,null,2));
+895
View File
@@ -0,0 +1,895 @@
-- 本地服务结构补齐;仅创建缺失表、添加缺失字段,不删除现有数据。
SET NAMES utf8mb4;
ALTER TABLE `ll_local_looseboard_order` ADD COLUMN product_name VARCHAR(255) NULL COMMENT '商品名称';
ALTER TABLE `ll_local_looseboard_order` ADD COLUMN estimated_pallet_count INT NULL COMMENT '客户申报预计托数,不代表实际收货';
ALTER TABLE `ll_local_looseboard_order` ADD COLUMN origin_contact_name VARCHAR(128) NULL COMMENT '起运地联系人';
ALTER TABLE `ll_local_looseboard_order` ADD COLUMN origin_contact_phone VARCHAR(128) NULL COMMENT '起运地联系电话';
ALTER TABLE `ll_local_looseboard_order` ADD COLUMN destination_contact_name VARCHAR(128) NULL COMMENT '目的地联系人';
ALTER TABLE `ll_local_looseboard_order` ADD COLUMN destination_contact_phone VARCHAR(128) NULL COMMENT '目的地联系电话';
ALTER TABLE `ll_local_looseboard_order` ADD COLUMN pickup_at DATETIME(3) NULL COMMENT '取货时间(当地时间,不转换时区)';
ALTER TABLE `ll_local_looseboard_order` ADD COLUMN delivery_at DATETIME(3) NULL COMMENT '送货时间(当地时间,不转换时区)';
CREATE TABLE ll_appointment_followup (
id BIGINT NOT NULL COMMENT '预约筹划跟进记录ID',
source_key VARCHAR(160) NOT NULL COMMENT '稳定ORDER、BOOKING或CONTAINER及接仓点来源键',
customer_id VARCHAR(128) NOT NULL COMMENT '货源客户;整柜共享记录由服务端固定为平台作用域0',
source_order_id BIGINT NULL COMMENT '已形成的真实尾程货源ID,尚未生成时为空',
stage VARCHAR(32) NOT NULL COMMENT '跟进对象:DRAYAGE_CONTACT/TERMINAL_APPOINTMENT/WAREHOUSE_RECEIVING/FBA_RECEIVING',
version INT NOT NULL COMMENT '同一货源及跟进对象的记录版本',
contacted_party VARCHAR(200) NULL COMMENT '本次联系对象,不替代承运主档',
result VARCHAR(1000) NOT NULL COMMENT '本次反馈事实,不自动确认预约或推进实物作业',
next_action VARCHAR(500) NULL COMMENT '下一步安排',
followup_date DATE NULL COMMENT '按业务地点当地日期记录的下次跟进日',
operator_id VARCHAR(128) NOT NULL COMMENT '登录平台操作者ID',
operator_name VARCHAR(200) NULL COMMENT '操作人姓名快照',
command_key VARCHAR(64) NOT NULL COMMENT '持久幂等键',
request_hash CHAR(64) NOT NULL COMMENT '含操作者身份的请求SHA256摘要',
created_at DATETIME(3) NOT NULL COMMENT 'UTC记录时间',
PRIMARY KEY (id),
UNIQUE KEY uk_appointment_followup_version (source_key,stage,version),
UNIQUE KEY uk_appointment_followup_command (source_key,stage,command_key),
KEY idx_appointment_followup_date (followup_date,source_order_id),
CONSTRAINT fk_appointment_followup_order FOREIGN KEY (source_order_id) REFERENCES ll_order(id),
CONSTRAINT chk_appointment_followup_stage CHECK (stage IN ('DRAYAGE_CONTACT','TERMINAL_APPOINTMENT','WAREHOUSE_RECEIVING','FBA_RECEIVING'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='真实在途货源的预约筹划联系记录,追加留痕';
CREATE TABLE ll_dispatch_command (
id BIGINT NOT NULL COMMENT '持久命令内部主键',
dispatch_id BIGINT NOT NULL COMMENT '命令所属整车排车主单ID',
dispatch_no VARCHAR(64) NOT NULL COMMENT '命令所属真实排车业务号',
action VARCHAR(40) NOT NULL COMMENT '本次整车作业动作',
operator_id VARCHAR(128) NOT NULL COMMENT '原始可信操作主体ID',
idempotency_key VARCHAR(255) NOT NULL COMMENT '跨操作主体全局唯一的原始请求键',
record_version BIGINT NOT NULL COMMENT '原请求明确提交的排车版本,零为合法首版',
command_hash CHAR(64) NOT NULL COMMENT '绑定原主体动作业务号版本和完整载荷的严格摘要',
result_json LONGTEXT NOT NULL COMMENT '按动作类型恢复的不可变成功结果JSON',
created_at DATETIME(3) NOT NULL COMMENT '成功命令记录时间,使用UTC',
PRIMARY KEY (id),
UNIQUE KEY uk_dispatch_command_key (idempotency_key),
KEY idx_dispatch_command_history (dispatch_id,created_at,id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='整车排车公共持久命令账本';
CREATE TABLE ll_dispatch_delivery_arrangement (
id BIGINT NOT NULL COMMENT '安排事实内部主键',
dispatch_order_id BIGINT NOT NULL COMMENT '唯一整车排车主单ID',
dispatch_no VARCHAR(128) NOT NULL COMMENT '真实排车业务号',
arrangement_key VARCHAR(128) NOT NULL COMMENT '本次唯一安排业务事实标识',
business_hash CHAR(64) NOT NULL COMMENT '排除操作者及纯并发版本的安排业务摘要',
cargo_hash CHAR(64) NOT NULL COMMENT '本车实际拣货来源摘要',
loading_completion_hash CHAR(64) NOT NULL COMMENT '装车完成事实摘要',
original_command_key VARCHAR(255) NOT NULL COMMENT '首次安排的全局请求键',
original_operator_id VARCHAR(128) NOT NULL COMMENT '首次安排操作主体',
result_json JSON NOT NULL COMMENT '全部客户出库及客户目的地派送不可变结果',
cargo_json JSON NOT NULL COMMENT '逐客户逐拣货归属的不可变真实来源',
created_at DATETIME(3) NOT NULL COMMENT '本次安排实际创建时间',
PRIMARY KEY (id),
UNIQUE KEY uk_dispatch_arrangement_dispatch (dispatch_order_id),
UNIQUE KEY uk_dispatch_arrangement_key (arrangement_key),
UNIQUE KEY uk_dispatch_arrangement_command (original_command_key)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='整车排车唯一派送安排事实';
CREATE TABLE ll_delivery_facts_changed (
id BIGINT NOT NULL COMMENT '持久信号内部主键',
customer_id VARCHAR(128) NOT NULL COMMENT '真实签收货物客户ID',
dispatch_id BIGINT NOT NULL COMMENT '整车排车主单ID',
dispatch_no VARCHAR(128) NOT NULL COMMENT '真实排车业务号',
delivery_id BIGINT NOT NULL COMMENT '本客户派送单ID',
delivery_no VARCHAR(128) NOT NULL COMMENT '真实派送业务号',
delivery_version BIGINT NOT NULL COMMENT '触发信号的真实派送版本',
facts_hash CHAR(64) NOT NULL COMMENT '该版本真实签收事实摘要',
occurred_at DATETIME(3) NOT NULL COMMENT '签收事实实际发生时间',
state VARCHAR(16) NOT NULL DEFAULT 'PENDING' COMMENT '待核对PENDING或已核对PROCESSED',
attempt_count INT NOT NULL DEFAULT 0 COMMENT '已记录的汇总失败次数',
next_attempt_at DATETIME(3) NOT NULL COMMENT '下次可重试时间',
last_error_code VARCHAR(64) NULL COMMENT '最近失败诊断码不保存敏感异常正文',
processed_at DATETIME(3) NULL COMMENT '与主阶段汇总同事务确认时间',
PRIMARY KEY (id),
UNIQUE KEY uk_delivery_fact_version (customer_id,delivery_id,delivery_version),
KEY idx_delivery_fact_due (state,next_attempt_at,id),
KEY idx_delivery_fact_dispatch (dispatch_id,state,id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='正常签收事实变化的本地持久待汇总信号';
ALTER TABLE `ll_outbound_pallet_item` ADD COLUMN dispatch_item_id BIGINT NULL COMMENT '本次整车排车作业明细ID';
ALTER TABLE `ll_outbound_pallet_item` ADD COLUMN source_attribution_id BIGINT NULL COMMENT '不可变PDA真实拣货归属ID';
ALTER TABLE `ll_outbound_pallet_item` ADD COLUMN source_order_id BIGINT NULL COMMENT '本行真实来源尾程订单ID';
ALTER TABLE `ll_outbound_pallet_item` ADD COLUMN source_inventory_position_id BIGINT NULL COMMENT '本行实际拣货库存仓位ID';
ALTER TABLE `ll_outbound_pallet_item` ADD COLUMN source_return_receipt_id BIGINT NULL COMMENT '本行实际退回再派实收记录ID';
ALTER TABLE `ll_outbound_pallet_item` ADD COLUMN source_return_carton_id BIGINT NULL COMMENT '本行实际退货换标来源箱ID';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN purpose VARCHAR(32) NULL COMMENT '费用业务用途;由履约节点确定';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN confirmation_origin VARCHAR(16) NOT NULL DEFAULT 'BUSINESS' COMMENT '核定入口:BUSINESS业务节点、FINANCIAL财务操作';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN fee_version INT NULL COMMENT '同用途费用确认版本';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN active TINYINT(1) NOT NULL DEFAULT 1 COMMENT '是否当前有效版本';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN determination VARCHAR(24) NULL COMMENT 'POSITIVE正额、ZERO零元、NOT_APPLICABLE不适用';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN original_currency CHAR(3) NULL COMMENT '核定原币CNY或USD';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN original_amount DECIMAL(20,2) NULL COMMENT '核定原币金额';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN exchange_rate DECIMAL(20,6) NULL COMMENT '已确认汇率快照';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN exchange_rate_month CHAR(7) NULL COMMENT '已确认汇率所属月份';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN business_date DATE NULL COMMENT '实际费用业务日期';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN wallet_business_id BIGINT NULL COMMENT '资金冻结对应采购费用记录';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN wallet_business_no VARCHAR(128) NULL COMMENT '资金冻结业务号;实际国际运费引用原预估';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN wallet_hold_id VARCHAR(64) NULL COMMENT 'Finance冻结引用';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN wallet_ledger_id VARCHAR(64) NULL COMMENT 'Finance实际处理流水引用';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN settled_command_event_id VARCHAR(64) NULL COMMENT '成功实扣或退款的资金命令事件';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN source_fee_id BIGINT NULL COMMENT '已实扣费用来源ID';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN parent_fee_id BIGINT NULL COMMENT '原费用或预估引用';
ALTER TABLE `ll_overseas_procurement_fee` ADD COLUMN request_hash CHAR(64) NULL COMMENT '确认请求摘要';
ALTER TABLE `ll_overseas_procurement_status_history` ADD COLUMN operation_type varchar(32) COLLATE utf8mb4_unicode_ci NULL COMMENT '操作类型:CREATE、REVIEW或UPDATE';
ALTER TABLE `ll_overseas_procurement_status_history` ADD COLUMN change_detail json DEFAULT NULL COMMENT '字段变更前后值JSON';
ALTER TABLE `ll_receiving_container_session` ADD COLUMN source_container_booking_id varchar(128) COLLATE utf8mb4_unicode_ci NULL COMMENT '稳定来源柜预订ID';
ALTER TABLE `ll_receiving_container_session` ADD COLUMN container_fact_hash varchar(64) COLLATE utf8mb4_unicode_ci NULL COMMENT '领取时整柜订单与计划事实摘要';
ALTER TABLE `ll_receiving_container_session` ADD COLUMN overseas_warehouse_code varchar(128) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '海外接柜仓业务编码快照';
ALTER TABLE `ll_return_inventory_outbound_movement` ADD COLUMN return_sku_quantity BIGINT NULL COMMENT '退货单SKU本来源计划出库件数快照,NULL为历史整箱出库';
ALTER TABLE `ll_us_truck_order` ADD COLUMN vehicle_type VARCHAR(32) NULL COMMENT '车辆类型:PALLET_15为15拖,PALLET_30为30拖;拼车未提供时为空';
ALTER TABLE `ll_us_truck_order` ADD COLUMN origin_contact_name VARCHAR(128) NULL COMMENT '起运地联系人';
ALTER TABLE `ll_us_truck_order` ADD COLUMN origin_contact_phone VARCHAR(128) NULL COMMENT '起运地联系电话';
ALTER TABLE `ll_us_truck_order` ADD COLUMN destination_contact_name VARCHAR(128) NULL COMMENT '目的地联系人';
ALTER TABLE `ll_us_truck_order` ADD COLUMN destination_contact_phone VARCHAR(128) NULL COMMENT '目的地联系电话';
ALTER TABLE `ll_us_truck_order` ADD COLUMN pickup_at DATETIME NULL COMMENT '取货时间,按填写的日期时分保存,不转换时区';
ALTER TABLE `ll_us_truck_order` ADD COLUMN delivery_at DATETIME NULL COMMENT '送货时间,按填写的日期时分保存;拼车来源未提供时为空';
CREATE TABLE event_delivery_retry_audit (
request_id VARCHAR(36) NOT NULL COMMENT '人工重试请求UUID和幂等键',
producer_table VARCHAR(64) NOT NULL COMMENT '本服务发件箱表名',
entry_id VARCHAR(64) NOT NULL COMMENT '发件箱记录主键',
event_id VARCHAR(128) NOT NULL COMMENT '原事件全局标识',
event_type VARCHAR(64) NOT NULL COMMENT '原事件类型',
payload_hash VARCHAR(71) NOT NULL COMMENT '原事件不可变负载摘要',
operator_name VARCHAR(128) NOT NULL COMMENT '持有运维凭据的操作人标识',
reason VARCHAR(500) NOT NULL COMMENT '人工重试原因',
previous_failures INT NOT NULL COMMENT '重试前累计失败次数',
previous_error VARCHAR(1000) NULL COMMENT '重试前最后一次脱敏错误',
requested_at DATETIME(3) NOT NULL COMMENT '重试申请提交时间',
PRIMARY KEY (request_id),
KEY idx_event_retry_entry (producer_table,entry_id,requested_at),
KEY idx_event_retry_event (event_id,requested_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='业务事件人工重试审计,与恢复待发送状态同事务提交';
CREATE TABLE ll_procurement_wallet_attempt (
id BIGINT NOT NULL COMMENT '请求尝试ID',
order_id BIGINT NOT NULL COMMENT '采购订单ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
fee_id BIGINT NOT NULL COMMENT '不可变费用版本ID',
attempt_no BIGINT NOT NULL COMMENT '费用版本内请求序号',
operation VARCHAR(32) NOT NULL COMMENT '资金操作:FREEZE冻结、SETTLE结算、SETTLE_ACTUAL实际结算、RELEASE释放、REFUND退款',
business_no VARCHAR(128) NOT NULL COMMENT 'Finance资金业务号',
amount DECIMAL(20,2) NULL COMMENT '请求金额;全额结算或释放可空',
command_event_id VARCHAR(64) NOT NULL COMMENT '资金指令事件唯一引用',
status VARCHAR(16) NOT NULL COMMENT '资金请求结果:PENDING未决、SUCCEEDED成功、FAILED明确失败',
result_hash CHAR(64) NULL COMMENT '原业务回执摘要',
wallet_hold_id VARCHAR(64) NULL COMMENT 'Finance冻结引用',
wallet_ledger_id VARCHAR(64) NULL COMMENT 'Finance处理流水引用',
error_code VARCHAR(64) NULL COMMENT '业务失败码',
error_message VARCHAR(500) NULL COMMENT '内部失败诊断,不直接对客展示',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '请求时间',
completed_at DATETIME(3) NULL COMMENT '最终结果时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_attempt_event(command_event_id),
UNIQUE KEY uk_procurement_attempt_number(fee_id,attempt_no),
KEY idx_procurement_attempt_order(customer_id,order_id,status),
CONSTRAINT chk_procurement_attempt_status CHECK(status IN('PENDING','SUCCEEDED','FAILED'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购费用资金命令尝试与不可变结果';
CREATE TABLE ll_procurement_flow (
order_id BIGINT NOT NULL COMMENT '采购订单ID,一单一个履约批次',
customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
purchased_at DATETIME(3) NULL COMMENT '真实购买时间',
purchased_product_name VARCHAR(255) NULL COMMENT '实际购买商品',
purchased_specification VARCHAR(500) NULL COMMENT '实际购买规格',
purchased_quantity BIGINT NULL COMMENT '实际购买件数',
purchase_amount DECIMAL(20,2) NULL COMMENT '供应商实付原币金额',
purchase_currency CHAR(3) NULL COMMENT '供应商实付原币CNY或USD',
purchase_voucher_id BIGINT NULL COMMENT '购买凭证引用',
purchase_issue VARCHAR(500) NULL COMMENT '购买未核定或异常说明',
purchase_confirmed_at DATETIME(3) NULL COMMENT '货款核定时间,不代表扣费成功',
actual_warehouse_id BIGINT NULL COMMENT '首次实际收货冻结的仓库ID',
actual_warehouse_code VARCHAR(128) NULL COMMENT '实际收货仓编码快照',
actual_warehouse_name VARCHAR(255) NULL COMMENT '实际收货仓名称快照',
overseas_received_at DATETIME(3) NULL COMMENT '海外整批收货完成时间',
packing_version INT NULL COMMENT '当前确认装箱清单版本',
overseas_shipped_at DATETIME(3) NULL COMMENT '国际段整批实际交寄时间',
domestic_received_at DATETIME(3) NULL COMMENT '国内整批收货完成时间',
charges_confirmed_at DATETIME(3) NULL COMMENT '国内整单费用核定时间',
customer_shipped_at DATETIME(3) NULL COMMENT '国内寄客户实际交寄时间',
domestic_receiver_name VARCHAR(128) NULL COMMENT '国际段国内收件人',
domestic_receiver_phone VARCHAR(64) NULL COMMENT '国际段国内收件电话',
domestic_receiver_address VARCHAR(1000) NULL COMMENT '国际段国内接收地址',
cancelled_at DATETIME(3) NULL COMMENT '购买前取消时间',
closed_at DATETIME(3) NULL COMMENT '异常关闭时间',
control_reason VARCHAR(1000) 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(order_id), KEY idx_procurement_flow_customer(customer_id,order_id),
CONSTRAINT chk_procurement_purchase_quantity CHECK(purchased_quantity IS NULL OR purchased_quantity>0),
CONSTRAINT chk_procurement_purchase_amount CHECK(purchase_amount IS NULL OR purchase_amount>=0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购单一批次履约事实';
CREATE TABLE ll_procurement_command (
id BIGINT NOT NULL COMMENT '操作记录ID', order_id BIGINT NOT NULL COMMENT '采购订单ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键', action VARCHAR(48) NOT NULL COMMENT '采购节点动作',
idempotency_key VARCHAR(128) NOT NULL COMMENT '操作幂等键', request_hash CHAR(64) NOT NULL COMMENT '请求摘要',
operator_id VARCHAR(128) NOT NULL COMMENT '执行人', reason VARCHAR(1000) NOT NULL COMMENT '操作依据',
detail_json JSON NOT NULL COMMENT '内部操作及更正依据快照,不直接对客展示',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '执行时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_command(order_id,action,idempotency_key),
KEY idx_procurement_command_customer(customer_id,order_id,created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购节点幂等与不可变审计';
CREATE TABLE ll_procurement_budget_authorization (
id BIGINT NOT NULL COMMENT '预算授权ID', order_id BIGINT NOT NULL COMMENT '采购订单ID',
customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
previous_amount DECIMAL(20,2) NULL COMMENT '原货款预算总上限;未授权保持空', previous_currency CHAR(3) NOT NULL COMMENT '原预算币种',
authorized_amount DECIMAL(20,2) NOT NULL COMMENT '客户授权的新货款总上限', currency CHAR(3) NOT NULL COMMENT '客户授权币种',
voucher_file_id BIGINT NOT NULL COMMENT '客户确认书面或聊天凭证', reason VARCHAR(1000) NOT NULL COMMENT '授权依据',
reviewed_by VARCHAR(128) NOT NULL COMMENT '核验人员', reviewed_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '核验时间',
PRIMARY KEY(id), KEY idx_procurement_budget_order(customer_id,order_id,id),
CONSTRAINT chk_procurement_budget_amount CHECK(authorized_amount>=0 AND previous_amount>=0),
CONSTRAINT chk_procurement_budget_currency CHECK(currency IN('CNY','USD') AND previous_currency IN('CNY','USD'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购货款预算授权核验历史';
CREATE TABLE ll_procurement_receipt (
id BIGINT NOT NULL COMMENT '实收明细ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
receipt_no VARCHAR(64) NOT NULL COMMENT '采购收货业务编号', leg VARCHAR(16) NOT NULL COMMENT 'OVERSEAS海外或DOMESTIC国内',
source_carton_id BIGINT NULL COMMENT '国内实收关联原国际交寄箱,海外为空', warehouse_id BIGINT NULL COMMENT '海外实际收货仓',
good_quantity BIGINT NOT NULL COMMENT '可发合格件数', damaged_quantity BIGINT NOT NULL COMMENT '破损待处置件数', extra_quantity BIGINT NOT NULL COMMENT '多到件数,不增加可发数量',
received_at DATETIME(3) NOT NULL COMMENT '实际收货时间', active TINYINT(1) NOT NULL DEFAULT 1 COMMENT '当前有效实收事实',
supersedes_id BIGINT NULL COMMENT '受控更正所替代的原实收记录', created_by VARCHAR(128) NOT NULL COMMENT '登记人员',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '登记时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_receipt_no(receipt_no), KEY idx_procurement_receipt_source(order_id,leg,source_carton_id,active),
CONSTRAINT chk_procurement_receipt_quantity CHECK(good_quantity>=0 AND damaged_quantity>=0 AND extra_quantity>=0 AND good_quantity+damaged_quantity+extra_quantity>0),
CONSTRAINT chk_procurement_receipt_leg CHECK((leg='OVERSEAS' AND source_carton_id IS NULL) OR (leg='DOMESTIC' AND source_carton_id IS NOT NULL))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购分次实收与受控更正事实';
CREATE TABLE ll_procurement_disposition (
id BIGINT NOT NULL COMMENT '差异处理ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
leg VARCHAR(16) NOT NULL COMMENT 'OVERSEAS海外或DOMESTIC国内', source_carton_id BIGINT NULL COMMENT '国内原交寄箱来源',
receipt_id BIGINT NULL COMMENT '破损或多货对应实收记录,短少为空', kind VARCHAR(24) NOT NULL COMMENT 'SHORTAGE短少、DAMAGED破损、EXTRA多货',
quantity BIGINT NOT NULL COMMENT '已批准处置件数', decision VARCHAR(32) NOT NULL COMMENT 'ACCEPT_SHORTAGE确认短少、DISPOSE_DAMAGED拒收或处置、RETURN_EXTRA退回多货',
active TINYINT(1) NOT NULL DEFAULT 1 COMMENT '当前有效处置;撤销只改变有效性并保留原事实',
voucher_file_id BIGINT NOT NULL COMMENT '本单客户确认或实际处置凭证', reason VARCHAR(1000) NOT NULL COMMENT '处置依据',
created_by VARCHAR(128) NOT NULL COMMENT '采购管理人员', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '确认时间',
PRIMARY KEY(id), KEY idx_procurement_disposition_source(order_id,leg,source_carton_id,receipt_id,kind),
CONSTRAINT chk_procurement_disposition_quantity CHECK(quantity>0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购单内差异处置,不自动退款';
CREATE TABLE ll_procurement_manifest (
id BIGINT NOT NULL COMMENT '装箱清单ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
version INT NOT NULL COMMENT '订单内装箱版本', status VARCHAR(16) NOT NULL COMMENT 'DRAFT草稿、CONFIRMED已确认、SUPERSEDED已替代',
confirmed_at DATETIME(3) NULL COMMENT '确认时间', created_by VARCHAR(128) NOT NULL COMMENT '制单人',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '版本保存时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_manifest_version(order_id,version),
CONSTRAINT chk_procurement_manifest_status CHECK(status IN('DRAFT','CONFIRMED','SUPERSEDED'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购装箱清单不可变版本';
CREATE TABLE ll_procurement_carton (
id BIGINT NOT NULL COMMENT '版本内箱记录ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', manifest_id BIGINT NOT NULL COMMENT '装箱清单版本',
carton_no VARCHAR(64) NOT NULL COMMENT '采购订单内业务箱号', length_cm DECIMAL(12,2) NOT NULL COMMENT '外箱长厘米',
width_cm DECIMAL(12,2) NOT NULL COMMENT '外箱宽厘米', height_cm DECIMAL(12,2) NOT NULL COMMENT '外箱高厘米',
gross_weight_kg DECIMAL(12,3) NOT NULL COMMENT '封箱毛重千克', quantity BIGINT NOT NULL COMMENT '本箱合格商品总件数',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_carton_version(manifest_id,carton_no), KEY idx_procurement_carton_order(order_id,manifest_id),
CONSTRAINT chk_procurement_carton_measurement CHECK(length_cm>0 AND width_cm>0 AND height_cm>0 AND gross_weight_kg>0 AND quantity>0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购版本化逐箱实测与件数';
CREATE TABLE ll_procurement_carton_source (
carton_id BIGINT NOT NULL COMMENT '版本内箱ID', receipt_id BIGINT NOT NULL COMMENT '海外实收明细来源', quantity BIGINT NOT NULL COMMENT '从该实收装入本箱的件数',
PRIMARY KEY(carton_id,receipt_id), KEY idx_procurement_carton_receipt(receipt_id), CONSTRAINT chk_procurement_carton_source_quantity CHECK(quantity>0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购箱内货物的实收来源与数量';
CREATE TABLE ll_procurement_shipment (
id BIGINT NOT NULL COMMENT '采购交寄ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
shipment_no VARCHAR(64) NOT NULL COMMENT '交寄业务编号', leg VARCHAR(16) NOT NULL COMMENT 'OVERSEAS国际交寄或DOMESTIC寄客户',
manifest_id BIGINT NOT NULL COMMENT '原海外装箱清单版本', shipped_at DATETIME(3) NOT NULL COMMENT '整批真实交承运方时间',
address_snapshot JSON NOT NULL COMMENT '本段交寄时的收寄姓名电话地址快照', created_by VARCHAR(128) NOT NULL COMMENT '交寄确认人',
created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '确认时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_shipment_leg(order_id,leg), UNIQUE KEY uk_procurement_shipment_no(shipment_no),
CONSTRAINT chk_procurement_shipment_leg CHECK(leg IN('OVERSEAS','DOMESTIC'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购两段各一次整批真实交寄';
CREATE TABLE ll_procurement_shipment_item (
shipment_id BIGINT NOT NULL COMMENT '采购交寄ID', carton_id BIGINT NOT NULL COMMENT '原海外装箱版本内箱ID', quantity BIGINT NOT NULL COMMENT '本次实际交寄件数',
carrier VARCHAR(128) NOT NULL COMMENT '承运商快照', tracking_no VARCHAR(128) NOT NULL COMMENT '运单号快照',
label_snapshot JSON NOT NULL COMMENT '当次箱规、面单及货物来源快照',
PRIMARY KEY(shipment_id,carton_id), CONSTRAINT chk_procurement_shipment_item_quantity CHECK(quantity>0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购整批交寄逐箱事实';
CREATE TABLE ll_procurement_label_set (
id BIGINT NOT NULL COMMENT '面单批版本ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
leg VARCHAR(16) NOT NULL COMMENT 'OVERSEAS国际段或DOMESTIC寄客户段', version INT NOT NULL COMMENT '订单段内面单版本',
manifest_id BIGINT NOT NULL COMMENT '原海外确认装箱版本', cargo_hash CHAR(64) NOT NULL COMMENT '箱规及有效货物来源摘要',
sender_snapshot JSON NOT NULL COMMENT '寄件人姓名电话地址快照', receiver_snapshot JSON NOT NULL COMMENT '收件人姓名电话地址快照',
created_by VARCHAR(128) NOT NULL COMMENT '制单操作人', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '上传确认时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_label_version(order_id,leg,version),
CONSTRAINT chk_procurement_label_leg CHECK(leg IN('OVERSEAS','DOMESTIC'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购两段面单不可变版本和地址快照';
CREATE TABLE ll_procurement_label_item (
label_set_id BIGINT NOT NULL COMMENT '面单批版本ID', carton_id BIGINT NOT NULL COMMENT '原海外清单箱ID',
file_id BIGINT NOT NULL COMMENT '本采购订单面单文件', page_no INT NOT NULL COMMENT '该箱对应文件页码,从1开始',
carrier VARCHAR(128) NOT NULL COMMENT '承运商', tracking_no VARCHAR(128) NOT NULL COMMENT '箱主或子运单号',
applied_at DATETIME(3) NULL COMMENT '真实贴单时间', applied_by VARCHAR(128) NULL COMMENT '贴单确认人',
PRIMARY KEY(label_set_id,carton_id), CONSTRAINT chk_procurement_label_page CHECK(page_no>0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购逐箱文件页关联及贴单事实';
CREATE TABLE ll_procurement_estimate_review (
id BIGINT NOT NULL COMMENT '预估核对ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', label_set_id BIGINT NOT NULL COMMENT '已核对国际面单版本',
fee_id BIGINT NOT NULL COMMENT '唯一有效预估费用版本', reviewed_by VARCHAR(128) NOT NULL COMMENT '核价人员',
reviewed_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '核对时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_estimate_review(label_set_id,fee_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='面单清单与预估冻结的显式核对关联';
CREATE TABLE ll_procurement_repack (
id BIGINT NOT NULL COMMENT '换包装版本ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', carton_id BIGINT NOT NULL COMMENT '原国际交寄箱ID,保持一对一来源',
length_cm DECIMAL(12,2) NOT NULL COMMENT '新外箱长厘米', width_cm DECIMAL(12,2) NOT NULL COMMENT '新外箱宽厘米',
height_cm DECIMAL(12,2) NOT NULL COMMENT '新外箱高厘米', gross_weight_kg DECIMAL(12,3) NOT NULL COMMENT '新封箱毛重千克',
voucher_file_id BIGINT NOT NULL COMMENT '本单换包装证据', reason VARCHAR(1000) NOT NULL COMMENT '换包装依据',
created_by VARCHAR(128) NOT NULL COMMENT '国内作业人员', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '登记时间',
PRIMARY KEY(id), KEY idx_procurement_repack_carton(order_id,carton_id,id),
CONSTRAINT chk_procurement_repack_measurement CHECK(length_cm>0 AND width_cm>0 AND height_cm>0 AND gross_weight_kg>0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购国内原箱一对一换包装不可变历史';
CREATE TABLE ll_procurement_fee_correction (
id BIGINT NOT NULL COMMENT '费用链更正ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
correction_no VARCHAR(64) NOT NULL COMMENT '财务更正业务号', root_fee_id BIGINT NOT NULL COMMENT '原实际费用链根',
idempotency_key VARCHAR(128) NOT NULL COMMENT '本单更正请求幂等键', request_hash CHAR(64) NOT NULL COMMENT '更正目标及凭证请求摘要',
target_original_amount DECIMAL(20,2) NOT NULL COMMENT '本次正确原币总额', original_currency CHAR(3) NOT NULL COMMENT '沿用原费用币种',
exchange_rate DECIMAL(20,6) NOT NULL COMMENT '沿用原费用汇率快照', exchange_rate_month CHAR(7) NOT NULL COMMENT '原汇率月份,不取本次操作月份',
target_amount DECIMAL(20,2) NOT NULL COMMENT '正确总额折算CNY', previous_net_amount DECIMAL(20,2) NOT NULL COMMENT '确认前整链净实扣CNY',
difference_amount DECIMAL(20,2) NOT NULL COMMENT 'CNY正差额追加、负差额退款、零差额仅留核对记录',
voucher_file_id BIGINT NOT NULL COMMENT '本订单财务更正凭证', reason VARCHAR(500) NOT NULL COMMENT '更正依据',
created_by VARCHAR(128) NOT NULL COMMENT '授权财务操作人', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '确认时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_correction_no(correction_no), UNIQUE KEY uk_procurement_correction_request(order_id,idempotency_key),
KEY idx_procurement_correction_root(order_id,root_fee_id,id),
CONSTRAINT chk_procurement_correction_amount CHECK(target_original_amount>=0 AND target_amount>=0 AND previous_net_amount>=0 AND exchange_rate>0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购费用链更正目标与原汇率快照';
CREATE TABLE ll_procurement_fee_correction_item (
correction_id BIGINT NOT NULL COMMENT '本次费用链更正ID', fee_id BIGINT NOT NULL COMMENT '本次产生的独立正差额或退款费用ID',
PRIMARY KEY(correction_id,fee_id), UNIQUE KEY uk_procurement_correction_fee(fee_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购费用目标更正与逐笔资金事实关联';
CREATE TABLE ll_procurement_control_note (
id BIGINT NOT NULL COMMENT '采购更正说明ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
note_no VARCHAR(64) NOT NULL COMMENT '更正说明业务号', target_type VARCHAR(24) NOT NULL COMMENT '购买、仓库、实收或交寄事实类型',
target_id BIGINT NULL COMMENT '本单事实对象引用,购买为空', blocking TINYINT(1) NOT NULL COMMENT '是否阻断后续计划履约',
voucher_file_id BIGINT NOT NULL COMMENT '本单内部事实更正凭证', reason VARCHAR(1000) NOT NULL COMMENT '内部更正说明',
client_summary VARCHAR(500) NULL COMMENT '人工确认的对客摘要,不复制内部原始内容',
original_value_json JSON NULL COMMENT '服务端记录的原事实快照', corrected_value_json JSON NULL COMMENT '服务端记录的更正事实快照',
created_by VARCHAR(128) NOT NULL COMMENT '采购管理操作人', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '登记时间',
resolved_by VARCHAR(128) NULL COMMENT '处理确认人', resolved_at DATETIME(3) NULL COMMENT '阻断解除时间',
resolution_reason VARCHAR(1000) NULL COMMENT '内部处理结果', resolution_voucher_id BIGINT NULL COMMENT '本单处理凭证',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_note_no(note_no), KEY idx_procurement_note_block(order_id,blocking,resolved_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购不可覆盖事实的更正说明及阻断异常';
CREATE TABLE ll_procurement_closure (
id BIGINT NOT NULL COMMENT '采购异常关闭ID', order_id BIGINT NOT NULL COMMENT '采购订单ID', customer_id VARCHAR(128) NOT NULL COMMENT '客户隔离键',
closure_no VARCHAR(64) NOT NULL COMMENT '异常关闭业务号', customer_voucher_file_id BIGINT NOT NULL COMMENT '客户同意停止履约凭证',
financial_conclusion VARCHAR(1000) NOT NULL COMMENT '已知费用及后续无需收费的处理结论,不改变资金事实',
reason VARCHAR(1000) NOT NULL COMMENT '内部关闭原因', client_summary VARCHAR(500) NOT NULL COMMENT '人工确认的对客关闭摘要',
created_by VARCHAR(128) NOT NULL COMMENT '采购管理确认人', created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '关闭确认时间',
PRIMARY KEY(id), UNIQUE KEY uk_procurement_closure_order(order_id), UNIQUE KEY uk_procurement_closure_no(closure_no)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='采购实物资金收口后的异常关闭事实';
CREATE TABLE ll_procurement_closure_item (
id BIGINT NOT NULL COMMENT '关闭货物处置ID', closure_id BIGINT NOT NULL COMMENT '采购关闭ID',
source_kind VARCHAR(32) NOT NULL COMMENT '购买未达、在途未达、合格、破损或多货来源', source_id BIGINT NULL COMMENT '原实收或国际交寄箱,购买未达为空',
quantity BIGINT NOT NULL COMMENT '本来源最终明确去向件数', decision VARCHAR(40) NOT NULL COMMENT '供应商保管、退还、报失、客户授权保管或处置',
destination VARCHAR(500) NOT NULL COMMENT '实际去向及接收方说明', voucher_file_id BIGINT NOT NULL COMMENT '本单实物处置证明',
PRIMARY KEY(id), KEY idx_procurement_closure_source(closure_id,source_kind,source_id),
CONSTRAINT chk_procurement_closure_quantity CHECK(quantity>0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='异常关闭逐来源剩余货物最终去向,不产生新发运';
CREATE TABLE ll_selfop_outbound_discovery_scope (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
catalog_from_utc DATETIME(3) NULL COMMENT '账号完整目录连续覆盖UTC下界,不等同销量覆盖',
catalog_until_utc DATETIME(3) NULL COMMENT '账号完整目录连续覆盖UTC上界,不等同销量覆盖',
next_sequence BIGINT NOT NULL DEFAULT 1 COMMENT '新发现任务的单调调度序号;重试沿用,只安排任务,不判断对象内容的新旧',
next_observation_sequence BIGINT NOT NULL DEFAULT 1 COMMENT '每次实际出库详情请求前分配的单调采集代次;与 task 调度序号独立,重试请求也分配新代次',
active_task_id BIGINT NULL COMMENT '当前共享发现/详情补齐任务',
lease_owner VARCHAR(128) NULL COMMENT '账号发现执行者',
lease_until_utc DATETIME(3) NULL COMMENT '账号发现租约到期时刻',
fence_token BIGINT NOT NULL DEFAULT 0 COMMENT '防止过期发现进程继续写共享暂存或派发任务',
request_budget INT NOT NULL COMMENT '一次调度允许的目录、详情请求总预算,必须为正',
time_budget_seconds INT NOT NULL COMMENT '一次调度允许占用的执行时长,必须为正',
min_request_interval_ms INT NOT NULL COMMENT '同账号请求最小间隔,按已核准配额配置',
api_budget_json JSON NULL COMMENT '账号所有采集族共用的预算、统计日、保守预留及确认消耗、尝试许可和独占交接依据',
api_cooldown_until_utc DATETIME(3) NULL COMMENT '账号全部真实请求共用冷却UTC截止,重启与跨日不清除',
api_pause_reason VARCHAR(64) NULL COMMENT '账号停止或等待的固定原因码,不保存供应商原始错误或凭据',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_discovery_account (source_account),
CONSTRAINT chk_selfop_outbound_discovery_scope CHECK (request_budget > 0 AND time_budget_seconds > 0 AND min_request_interval_ms > 0 AND fence_token >= 0 AND next_sequence > 0 AND next_observation_sequence > 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='账号共享出库目录与详情发现协调作用域';
CREATE TABLE ll_selfop_sync_scope (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
data_family VARCHAR(16) NOT NULL COMMENT 'OUTBOUND 或 INVENTORY;按账号+仓库+任务族互斥',
scope_json JSON NOT NULL COMMENT '本仓范围规则,customerMode=ALL_AUTHORIZED,库存为全部品质;当前账号全部授权货主均自营,不将当天出现的货主列表当白名单',
scope_hash CHAR(64) NOT NULL COMMENT '仓库、货主范围规则、品质、时区及单位口径的规范化摘要;不包含当天观测到的客户/SKU 集合',
business_timezone VARCHAR(64) NOT NULL COMMENT '本仓报表及调度时区,初始建议值为 Asia/Shanghai,各仓独立核准',
source_timezone VARCHAR(64) NULL COMMENT '本仓已核准的出库源时间时区',
schedule_cron VARCHAR(128) NOT NULL COMMENT '本仓、本任务族的调度表达式,按 business_timezone 执行',
stale_after_seconds INT NOT NULL COMMENT '本仓、本任务族数据过期阈值,必须为正;库存初始可采用 26 小时,后续按仓调整',
warehouse_policy_ref VARCHAR(128) NULL COMMENT '未来按仓告警/补货策略的稳定引用;一期为空,不建告警规则表',
initial_from_utc DATETIME(3) NULL COMMENT '首采固定UTC下界,按本仓业务时区减一个月',
initial_until_utc DATETIME(3) NULL COMMENT '首采固定UTC截止,重试不重新取当前时间',
discovery_from_utc DATETIME(3) NULL COMMENT '本仓已发布的连续销量覆盖UTC下界',
discovery_until_utc DATETIME(3) NULL COMMENT '本仓已发布的连续销量覆盖UTC上界,不含端点',
fact_revision BIGINT NOT NULL DEFAULT 0 COMMENT '出库事实归并修订号;内容实际变化才增加',
published_fact_revision BIGINT NOT NULL DEFAULT 0 COMMENT '本仓最后已发布销量版所使用的事实修订号',
rebuild_required TINYINT NOT NULL DEFAULT 0 COMMENT '事实变化待重建标记;跨仓修订同时置旧、新仓为 1',
invalidated_at_utc DATETIME(3) NULL COMMENT '最近一次因事实修订使当前版待重建的时刻',
published_run_id BIGINT NULL COMMENT '唯一对外可见版本,指向本任务族已发布执行批次',
lease_owner VARCHAR(128) NULL COMMENT '当前执行者令牌,不使用仅进程内锁',
lease_until_utc DATETIME(3) NULL COMMENT '租约到期时刻',
fence_token BIGINT NOT NULL DEFAULT 0 COMMENT '每次取得租约递增,事实提交和发布均校验',
known_order_cursor_id BIGINT NULL COMMENT '本仓已可靠处理的稳定订单内部标识游标',
known_order_round_max_id BIGINT NULL COMMENT '本轮已知单复查固定最大内部标识',
known_order_round_started_at_utc DATETIME(3) NULL COMMENT '本仓已知单复查轮次开始UTC时间',
known_order_round_finished_at_utc DATETIME(3) NULL COMMENT '本仓已知单完整轮转完成UTC时间',
history_round_from_utc DATETIME(3) NULL COMMENT '本仓历史核对固定UTC下界',
history_round_until_utc DATETIME(3) NULL COMMENT '本仓历史核对固定UTC上界',
history_slice_cursor_utc DATETIME(3) NULL COMMENT '本仓下一待核对历史切片UTC位置',
history_round_finished_at_utc DATETIME(3) NULL COMMENT '上一轮历史时间片全部完成时刻',
review_request_budget INT NOT NULL COMMENT '本仓单次复查最大请求数,必须为正',
review_time_budget_seconds INT NOT NULL COMMENT '本仓单次复查最大执行秒数,必须为正',
review_target_days INT NOT NULL DEFAULT 7 COMMENT '建议每 7 天轮转一遍,属于待配额验证的目标,不保证首次大量详情在单次调度内完成',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_scope (source_account,warehouse_code,data_family),
KEY idx_selfop_scope_lease (lease_until_utc),
CONSTRAINT chk_selfop_sync_scope CHECK (data_family IN ('OUTBOUND','INVENTORY') AND stale_after_seconds > 0 AND review_request_budget > 0 AND review_time_budget_seconds > 0 AND review_target_days > 0 AND fact_revision >= 0 AND published_fact_revision >= 0 AND fence_token >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='分仓任务族租约及发布指针';
CREATE TABLE ll_selfop_sync_task (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
task_no VARCHAR(64) NOT NULL COMMENT '稳定采集业务任务号,重试沿用,不展示内部数据库标识',
execution_purpose VARCHAR(16) NOT NULL COMMENT 'BUSINESS或VALIDATION;由服务端冻结用途,子任务继承',
validation_root_task_id BIGINT NULL COMMENT '验证会话唯一预算根任务,根引用自身,正式任务为空',
validation_budget_json JSON NULL COMMENT '验证根冻结硬预算、累计消耗、库存分仓页数、截止时刻及停止原因',
business_root_task_id BIGINT NULL COMMENT '测试人工正式采集共享预算根任务;生产任务为空',
business_budget_json JSON NULL COMMENT '仅测试正式采集根保存冻结请求上限、截止时间、消耗及停止原因',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
task_role VARCHAR(24) NOT NULL COMMENT 'ACCOUNT_DISCOVERY 或 WAREHOUSE_SYNC',
scope_id BIGINT NULL COMMENT '分仓任务必须引用分仓作用域;仅账号共享发现为空',
warehouse_code VARCHAR(64) NULL COMMENT '来源仓库原始编码,按仓独立统计',
discovery_scope_id BIGINT NULL COMMENT '共享发现必填,引用账号发现协调器',
upstream_task_id BIGINT NULL COMMENT '出库分仓任务引用已持久化目录的共享发现切片;库存无此上游',
discovery_sequence BIGINT NULL COMMENT '共享任务及分仓子任务继承的调度顺序;重试保持不变,不用于事实覆盖判定',
observation_baseline BIGINT NULL COMMENT '共享任务建立时已分配的最大详情采集代次,分仓子任务继承;用于识别旧任务恢复期间出现的其他任务新观测',
request_key VARCHAR(128) NOT NULL COMMENT '共享发现包含切片/计划槽位;分仓任务包含仓库、任务族及切片或计划槽位;人工附请求幂等键',
request_hash CHAR(64) NOT NULL COMMENT '请求类型、查询范围、范围摘要的指纹;同键不同请求拒绝',
task_type VARCHAR(24) NOT NULL COMMENT '计划、补采、复核、重建与验证;INVENTORY_FLOW_HISTORY为流水片,INVENTORY_HISTORY_BUILD为本地历史还原',
planned_at_utc DATETIME(3) NULL COMMENT '计划时点;人工请求可空',
query_from_utc DATETIME(3) NULL COMMENT '出库查询区间UTC下界,库存不填',
query_until_utc DATETIME(3) NULL COMMENT '出库查询区间UTC上界,不含端点,库存不填',
query_scope_json JSON NOT NULL COMMENT '不变的账号、货主、仓库、品质和查询条件快照;按单补查在此记录单号',
routing_manifest_json JSON NULL COMMENT '共享切片目录完整标记、每仓对象键集合/数量和详情就绪状态;各对象记录 effectiveStageId,需新代次复查时记录 refreshTaskId,完成后指向新有效暂存;不改写旧载荷',
scope_hash CHAR(64) NOT NULL COMMENT '建任务时的业务范围摘要',
status VARCHAR(20) NOT NULL COMMENT 'WAITING_SOURCE、READY、RUNNING、RETRY_WAIT、SUCCEEDED、DEAD、SAMPLE_DONE;样本结束不等于正式成功',
apply_state VARCHAR(20) NOT NULL COMMENT '正式出库归并NOT_STARTED、APPLYING、BLOCKED、APPLIED;共享发现、库存、重建及验证为NOT_APPLICABLE',
affected_warehouse_codes_json JSON NULL COMMENT '本次归并可能改变的仓集合,包含原仓与新仓;首段事实写入前登记,扩大集合须先取得新增仓租约并锁 scope,不能写完再补',
apply_started_at_utc DATETIME(3) NULL COMMENT '首段事实提交UTC时间',
apply_completed_at_utc DATETIME(3) NULL COMMENT '全部必需事实归并完成UTC时间,失败不填',
attempt_count INT NOT NULL DEFAULT 0 COMMENT '已创建的执行尝试数',
next_retry_at_utc DATETIME(3) NULL COMMENT '有限退避后下一次可执行时刻',
requested_by VARCHAR(128) NULL COMMENT '人工请求的平台操作人,仅内部审计',
result_published_run_id BIGINT NULL COMMENT '正式成功任务实际发布或复用的版本;验证和共享发现为空',
progress_json JSON NULL COMMENT '与可靠检查点一起提交的有界阶段、单位、尝试和质量进度,不保存单据集合',
progress_updated_at_utc DATETIME(3) NULL COMMENT '最后可靠业务检查点UTC时间,与执行心跳分开',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_task_no (task_no),
UNIQUE KEY uk_selfop_task_request (source_account,request_key),
KEY idx_selfop_task_poll (status,next_retry_at_utc,id),
KEY idx_selfop_task_upstream (upstream_task_id,warehouse_code),
KEY idx_selfop_task_apply (apply_state,id),
KEY idx_selfop_task_scope_list (scope_id,created_at,id),
KEY idx_selfop_task_account_list (source_account,task_role,created_at,id),
KEY idx_selfop_task_business_root (business_root_task_id,status,id),
CONSTRAINT chk_selfop_business_budget CHECK ((business_root_task_id IS NULL AND business_budget_json IS NULL) OR (execution_purpose='BUSINESS' AND business_root_task_id IS NOT NULL AND ((business_root_task_id=id AND business_budget_json IS NOT NULL) OR (business_root_task_id<>id AND business_budget_json IS NULL)))),
CONSTRAINT chk_selfop_sync_task CHECK (attempt_count >= 0 AND execution_purpose IN ('BUSINESS','VALIDATION') AND ((execution_purpose = 'BUSINESS' AND validation_root_task_id IS NULL AND validation_budget_json IS NULL) OR (execution_purpose = 'VALIDATION' AND validation_root_task_id IS NOT NULL AND apply_state = 'NOT_APPLICABLE' AND result_published_run_id IS NULL AND status <> 'SUCCEEDED')) AND ((task_role = 'ACCOUNT_DISCOVERY' AND scope_id IS NULL AND warehouse_code IS NULL AND discovery_scope_id IS NOT NULL) OR (task_role = 'WAREHOUSE_SYNC' AND scope_id IS NOT NULL AND warehouse_code IS NOT NULL)))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='一次计划或人工请求';
CREATE TABLE ll_selfop_sync_run (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
task_id BIGINT NOT NULL COMMENT '本次执行请求',
execution_purpose VARCHAR(16) NOT NULL COMMENT '从逻辑任务冻结继承,验证尝试不能作为正式统计版本',
scope_id BIGINT NULL COMMENT '仅账号共享发现为空;分仓执行必须有作用域',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
warehouse_code VARCHAR(64) NULL COMMENT '来源仓库原始编码,按仓独立统计',
run_role VARCHAR(24) NOT NULL COMMENT 'ACCOUNT_DISCOVERY 或 WAREHOUSE_SYNC',
upstream_task_id BIGINT NULL COMMENT '分仓出库计算引用的共享切片及其稳定暂存集合',
attempt_no INT NOT NULL COMMENT '同一请求从 1 起递增',
scope_hash CHAR(64) NOT NULL COMMENT '本版本的业务范围摘要',
scope_snapshot_json JSON NOT NULL COMMENT '分仓版只含本仓货主/品质、固定首采 [B,E0)、时区、调度与过期阈值;账号发现保存待路由仓集合,不冒充业务版',
observed_dimensions_json JSON NULL COMMENT '本次实际出现的仓库/货主集合及数量摘要,仅作采集证据;例如已观测 70 货主不等于固定授权范围',
fence_token BIGINT NOT NULL COMMENT '本尝试持有的栅栏版本',
base_published_run_id BIGINT NULL COMMENT '执行开始时的上一可见版本',
reference_sales_run_id BIGINT NULL COMMENT '库存构建开始时固定的本仓已发布销量版,用其不可变 SKU 维度生成出库已知商品占位;没有已发布销量版时为空,不读取半归并订单事实',
inventory_daily_sample_date DATE NULL COMMENT '北京时间当日首个合格计划库存发布代表日期,非代表为空',
inventory_sample_rule_version VARCHAR(32) NULL COMMENT '日库存代表选择规则 DAILY_SCHEDULED_FIRST_V1,与日标记原子保存',
status VARCHAR(24) NOT NULL COMMENT 'FETCHING、VALIDATED、ROUTED、FACTS_APPLIED、BUILDING、READY、PUBLISHED、REUSED、YIELDED、FAILED、ABORTED、SAMPLE_DONE;复用和验证不是版本头',
last_phase VARCHAR(24) NOT NULL COMMENT '失败/中止前所在阶段,支持判断是否已经归并事实',
fetch_started_at_utc DATETIME(3) NULL COMMENT '实际采集开始UTC时间',
fetch_finished_at_utc DATETIME(3) NULL COMMENT '实际采集完成UTC时间,未完成为空',
build_started_at_utc DATETIME(3) NULL COMMENT '实际开始有界候选构建UTC时间,用于构建耗时及首采合并间隔',
warehouse_daily_ready TINYINT NOT NULL DEFAULT 0 COMMENT '仓库日汇总已完整构建并校验,含完整空版本',
finished_at_utc DATETIME(3) NULL COMMENT '本次尝试终止UTC时间',
published_at_utc DATETIME(3) NULL COMMENT '实际原子切换发布指针UTC时间',
superseded_at_utc DATETIME(3) NULL COMMENT '被新发布版替代的首次UTC时间,同事务填写且重试不重置',
page_count INT NOT NULL DEFAULT 0 COMMENT '已完整获取页数',
source_total_count BIGINT NULL COMMENT '上游可靠返回的总数;未返回则为空',
unique_object_count BIGINT NOT NULL DEFAULT 0 COMMENT '规范化去重后对象数',
progress_snapshot_json JSON NULL COMMENT '尝试终止时冻结的有界可靠进度摘要,历史尝试不随逻辑任务改写',
heartbeat_at_utc DATETIME(3) NULL COMMENT '有效执行者最新UTC心跳,不代表业务检查点推进',
coverage_status VARCHAR(16) NOT NULL COMMENT 'UNKNOWN、PARTIAL、COMPLETE;分页完整与数值有效性分别判断',
covered_from_utc DATETIME(3) NULL COMMENT '本仓销量版本实际连续覆盖UTC下界',
covered_until_utc DATETIME(3) NULL COMMENT '本仓销量版本实际连续覆盖UTC上界,不含端点',
complete_day_from DATE NULL COMMENT '本仓完整自然日区间首日,包含',
complete_day_until DATE NULL COMMENT '本仓完整自然日区间末日,不含',
applied_fact_revision BIGINT NULL COMMENT '本次尝试归并后的事实修订号,库存为空',
calculated_fact_revision BIGINT NULL COMMENT '候选销量版本计算所依据的固定事实修订号',
error_code VARCHAR(64) NULL COMMENT '内部可诊断错误分类,不保存认证信息',
error_message VARCHAR(500) NULL COMMENT '脱敏后的固定错误摘要',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_run_attempt (task_id,attempt_no),
UNIQUE KEY uk_selfop_inventory_daily (source_account,warehouse_code,inventory_daily_sample_date),
KEY idx_selfop_run_scope (scope_id,id),
KEY idx_selfop_run_status (status,updated_at),
CONSTRAINT chk_selfop_inventory_daily CHECK ((inventory_daily_sample_date IS NULL AND inventory_sample_rule_version IS NULL) OR (inventory_daily_sample_date IS NOT NULL AND inventory_sample_rule_version IS NOT NULL AND inventory_sample_rule_version = 'DAILY_SCHEDULED_FIRST_V1' AND execution_purpose = 'BUSINESS' AND run_role = 'WAREHOUSE_SYNC' AND status = 'PUBLISHED' AND coverage_status = 'COMPLETE')),
CONSTRAINT chk_selfop_sync_run CHECK (attempt_no > 0 AND page_count >= 0 AND unique_object_count >= 0 AND execution_purpose IN ('BUSINESS','VALIDATION') AND (execution_purpose <> 'VALIDATION' OR status NOT IN ('PUBLISHED','REUSED')) AND (source_total_count IS NULL OR source_total_count >= 0) AND ((run_role = 'ACCOUNT_DISCOVERY' AND scope_id IS NULL AND warehouse_code IS NULL) OR (run_role = 'WAREHOUSE_SYNC' AND scope_id IS NOT NULL AND warehouse_code IS NOT NULL)))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='执行尝试、覆盖证明和版本头';
CREATE TABLE ll_selfop_sync_stage (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
run_id BIGINT NOT NULL COMMENT '首次写入该暂存对象的执行尝试',
stage_batch_id BIGINT NOT NULL COMMENT '出库取共享发现 task.id,便于断点续取;库存取本次 run.id,严禁跨尝试混页',
last_fetch_run_id BIGINT NOT NULL COMMENT '最后一次补齐该对象的执行尝试,保留重试来源',
observation_sequence BIGINT NULL COMMENT '该完整出库详情实际请求的采集代次;有效出库对象必填,目录待补对象和库存为空;不能填 task 调度序号',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
previous_warehouse_code VARCHAR(64) NULL COMMENT '路由时从已有单据识别的原仓库;归并前再校验,跨仓时通知两仓',
object_type VARCHAR(16) NOT NULL COMMENT 'OUTBOUND_ORDER 或 PRODUCT_STOCK',
object_key_hash CHAR(64) NOT NULL COMMENT '规范化业务键摘要;原业务键保留在载荷中并核对',
first_page_no INT NOT NULL COMMENT '首次发现页码',
observed_at_utc DATETIME(3) NOT NULL COMMENT '实际接收该对象的时刻',
content_hash CHAR(64) NOT NULL COMMENT '完整规范化对象摘要',
payload_json JSON NOT NULL COMMENT '目录阶段可先存订单头,详情齐后补完整 SKU;VALID 后不再修改;库存保存产品库存字段',
before_payload_json JSON NULL COMMENT '订单归并事务内记录归并前的完整规范化事实;新增单为空',
validation_status VARCHAR(16) NOT NULL COMMENT '暂存校验状态:PENDING待核验、VALID有效、INVALID异常',
validation_code VARCHAR(64) NULL COMMENT '字段缺失、冲突、未知时区等原因',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_stage_object (stage_batch_id,object_type,object_key_hash),
KEY idx_selfop_stage_history (object_type,object_key_hash,stage_batch_id),
KEY idx_selfop_stage_observation (object_type,object_key_hash,validation_status,observation_sequence),
KEY idx_selfop_stage_fact_observation (observation_sequence,warehouse_code,object_type,validation_status,run_id,observed_at_utc),
KEY idx_selfop_stage_route (stage_batch_id,warehouse_code,validation_status),
CONSTRAINT chk_selfop_sync_stage CHECK (first_page_no > 0 AND (object_type <> 'OUTBOUND_ORDER' OR validation_status <> 'VALID' OR observation_sequence IS NOT NULL))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='待验证事实与修订证据';
CREATE TABLE ll_selfop_outbound_order (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
customer_code VARCHAR(64) NOT NULL COMMENT '领星货主原始编码,不等同平台客户标识',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
delivery_no VARCHAR(128) NOT NULL COMMENT 'OMP 发货单号,采用列表及详情同一身份',
source_no VARCHAR(128) NULL COMMENT 'WMS 来源出库单号,缺失不以内部 ID 回退展示',
source_status INT NOT NULL COMMENT '原始状态,100 已出库、99 已取消;不改造成内部状态码',
source_created_time VARCHAR(64) NULL COMMENT '来源创建时间原始字符串,不使用采集时间替代',
source_outbound_time VARCHAR(64) NULL COMMENT '来源实际出库时间原始字符串,不使用采集时间替代',
source_timezone VARCHAR(64) NULL COMMENT '解析采用的源时区',
outbound_at_utc DATETIME(3) NULL COMMENT '已核准的实际出库时间点;非出库状态可空',
business_date DATE NULL COMMENT '已核准业务时区下的出库日',
business_timezone VARCHAR(64) NOT NULL COMMENT '该事实当前归属仓所用业务时区,迁仓后重新确定业务日',
sales_eligible TINYINT NOT NULL DEFAULT 0 COMMENT '仅已出库、时间与全部数量有效时为 1',
revision_no BIGINT NOT NULL DEFAULT 1 COMMENT '该单内容变更次数,不等于拉取次数',
content_hash CHAR(64) NOT NULL COMMENT '订单头及完整 SKU 明细规范化摘要',
last_run_id BIGINT NOT NULL COMMENT '最后一次确认或修订的执行尝试',
last_observation_sequence BIGINT NOT NULL COMMENT '最后接受的完整详情采集代次;仅防旧观测重放,不按 task 调度序号拒绝较晚实际读取的事实,不冒充领星源版本号',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_order (source_account,customer_code,delivery_no),
KEY idx_selfop_order_daily (source_account,warehouse_code,sales_eligible,business_date,id),
KEY idx_selfop_order_run (last_run_id),
CONSTRAINT chk_selfop_outbound_order CHECK (revision_no > 0 AND last_observation_sequence > 0 AND sales_eligible IN (0,1) AND (sales_eligible = 0 OR (source_status = 100 AND source_timezone IS NOT NULL AND outbound_at_utc IS NOT NULL AND business_date IS NOT NULL)))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='最后确认的单据事实';
CREATE TABLE ll_selfop_outbound_item (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
order_id BIGINT NOT NULL COMMENT '对应外部出库事实',
sku_code VARCHAR(128) NOT NULL COMMENT '原始 productSku',
product_name VARCHAR(255) NULL COMMENT '来源商品名称,仅作展示',
actual_quantity DECIMAL(20,6) NOT NULL COMMENT '详情 actualDeliveryQty,必须为非负有效数值',
quantity_unit VARCHAR(32) NOT NULL COMMENT '已核准业务单位;未确认单位不发布正式数量统计',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_order_sku (order_id,sku_code),
KEY idx_selfop_item_sku (sku_code,order_id),
CONSTRAINT chk_selfop_outbound_item CHECK (actual_quantity >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='整单替换的实际出库明细';
CREATE TABLE ll_selfop_inventory_snapshot (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
snapshot_run_id BIGINT NOT NULL COMMENT 'INVENTORY 执行尝试;发布后该批明细不可修改',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
customer_code VARCHAR(64) NOT NULL COMMENT '领星货主原始编码,不等同平台客户标识',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
sku_code VARCHAR(128) NOT NULL COMMENT '原始产品 SKU',
product_quality SMALLINT NOT NULL COMMENT '来源品质,当前 0 正品、1 次品;全量均保存,不套用整箱库存',
product_name VARCHAR(255) NULL COMMENT '来源名称',
physical_quantity DECIMAL(20,6) NULL COMMENT '来源stkQty实物库存,未知为空',
available_quantity DECIMAL(20,6) NULL COMMENT '来源useStkQty可用库存,未知为空,不再次扣冻结',
frozen_quantity DECIMAL(20,6) NULL COMMENT '来源freezeQty冻结库存,未知为空',
transit_quantity DECIMAL(20,6) NULL COMMENT '来源transitQty在途数量,未知为空,不计可售库存',
source_unique_key VARCHAR(512) NULL COMMENT '原 uniqueKey4tenant,只作来源证据',
observed_at_utc DATETIME(3) NOT NULL COMMENT '所在页实际采集时间;缺行占位取本批采集完成时间',
quality_status VARCHAR(16) NOT NULL COMMENT 'VALID、UNKNOWN、INVALID;STALE 按批次年龄实时派生',
quality_reason VARCHAR(64) NULL COMMENT 'SOURCE_ROW_MISSING、FIELD_MISSING、NEGATIVE_QUANTITY 等',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_stock_snapshot (snapshot_run_id,source_account,customer_code,warehouse_code,sku_code,product_quality),
KEY idx_selfop_stock_lookup (source_account,customer_code,warehouse_code,sku_code,product_quality,snapshot_run_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='产品库存全量批次明细';
CREATE TABLE ll_selfop_sku_daily_sales (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
sales_run_id BIGINT NOT NULL COMMENT 'OUTBOUND 执行尝试,同时是计算版本',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
customer_code VARCHAR(64) NOT NULL COMMENT '领星货主原始编码,不等同平台客户标识',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
sku_code VARCHAR(128) NOT NULL COMMENT '原始产品 SKU',
business_date DATE NOT NULL COMMENT '已核准业务日',
outbound_quantity DECIMAL(20,6) NOT NULL COMMENT '有效出库实际件数之和,非负',
outbound_order_count BIGINT NOT NULL COMMENT '该维度去重发货单数,非负',
quantity_unit VARCHAR(32) NOT NULL COMMENT '同一统计维度内一致的业务单位',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_daily_version (sales_run_id,source_account,customer_code,warehouse_code,sku_code,business_date),
KEY idx_selfop_daily_window_cover (sales_run_id,source_account,warehouse_code,business_date,customer_code,sku_code,outbound_quantity,outbound_order_count,quantity_unit),
KEY idx_selfop_daily_sku_cover (sales_run_id,source_account,warehouse_code,customer_code,sku_code,business_date,outbound_quantity,outbound_order_count,quantity_unit),
CONSTRAINT chk_selfop_sku_daily_sales CHECK (outbound_quantity >= 0 AND outbound_order_count >= 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='完整销量版本的稀疏日事实';
CREATE TABLE ll_selfop_warehouse_daily_sales (
sales_run_id BIGINT NOT NULL COMMENT '完整销量计算版本标识',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码',
business_date DATE NOT NULL COMMENT '已核准业务日',
observed_quantity DECIMAL(38,6) NULL COMMENT '该日PCS非负有效出库量之和,无有效行时为空',
invalid_row_count BIGINT NOT NULL COMMENT '该日数量为空或负数或单位非PCS的日事实行数',
source_row_count BIGINT NOT NULL COMMENT '该日参与仓库汇总的SKU日事实总行数',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
PRIMARY KEY (sales_run_id,source_account,warehouse_code,business_date),
CONSTRAINT chk_selfop_warehouse_daily_sales CHECK (source_row_count > 0 AND invalid_row_count >= 0 AND invalid_row_count <= source_row_count AND (observed_quantity IS NULL OR observed_quantity >= 0))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='完整销量版本按仓按日汇总,随SKU日事实批次原子构建';
CREATE TABLE ll_selfop_sku_profile (
id BIGINT NOT NULL COMMENT '应用生成的记录标识',
created_at DATETIME(3) NOT NULL COMMENT 'UTC创建时间',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
profile_run_id BIGINT NOT NULL COMMENT '本仓销量或库存候选版本;与对应 daily/snapshot 使用同一 run,发布后该版本全部维度行不可修改',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号别名,不保存密钥',
customer_code VARCHAR(64) NOT NULL COMMENT '领星货主原始编码,不等同平台客户标识',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库原始编码,按仓独立统计',
sku_code VARCHAR(128) NOT NULL COMMENT '原始产品 SKU',
product_name VARCHAR(255) NULL COMMENT '本版本确认的名称,不实时连接其他版本名称',
quantity_unit VARCHAR(32) NULL COMMENT '本版本已核准单位;未知或两版本单位冲突时不计算混合指标',
first_seen_at_utc DATETIME(3) NULL COMMENT '本证据族真实观测到本仓商品的最早接收时刻;缺行占位不能生成观察证据',
earliest_evidence_at_utc DATETIME(3) NULL COMMENT '库存版取真实库存首次观察时刻;销量版从该版有效事实重新求最早已核准出库时间,可随改期、取消或迁仓撤回/后移',
evidence_type VARCHAR(24) NOT NULL COMMENT 'INVENTORY_OBSERVATION、VALID_OUTBOUND、NONE;不得将销量证据复制成库存真实观察证据',
evidence_run_id BIGINT NULL COMMENT '本证据族真实依据的采集批次,无证据占位为空',
last_seen_run_id BIGINT NULL COMMENT '本证据族最近真实观测批次,无证据占位为空',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_profile_version (profile_run_id,source_account,customer_code,warehouse_code,sku_code),
KEY idx_selfop_profile_evidence (profile_run_id,earliest_evidence_at_utc,customer_code,sku_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='随发布版本固定的 SKU 维度与观察依据';
CREATE TABLE ll_appointment_impact (
container_booking_id VARCHAR(64) NOT NULL COMMENT '稳定柜次关联键,不作业务编号展示',
impact_no VARCHAR(40) NOT NULL COMMENT '船期核对事项业务号',
baseline_json LONGTEXT NOT NULL COMMENT '已核对基准或首次变化前观察,原来源时间口径',
latest_json LONGTEXT NOT NULL COMMENT '最新已读取观察,未知可为JSON null',
forecast_token CHAR(64) NOT NULL COMMENT '最新观察摘要,处理时防止旧预测结案',
status VARCHAR(20) NOT NULL COMMENT '事项状态:MONITORING监测/OPEN待处理/RESOLVED已完成',
reason VARCHAR(64) NULL COMMENT '预测变化或资料待核实原因',
owner_id VARCHAR(128) NULL COMMENT '认领平台人员ID',
owner_name VARCHAR(200) NULL COMMENT '负责人姓名快照',
version INT NOT NULL COMMENT '观察及人工处理共同版本',
updated_at DATETIME(3) NOT NULL COMMENT 'UTC更新时间',
PRIMARY KEY (container_booking_id),
UNIQUE KEY uk_appointment_impact_no (impact_no),
KEY idx_appointment_impact_work (status,updated_at),
CONSTRAINT chk_appointment_impact_status CHECK (status IN ('MONITORING','OPEN','RESOLVED'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='一柜一个稳定船期变化核对事项,不改写预约或运输';
CREATE TABLE ll_appointment_impact_history (
id BIGINT NOT NULL COMMENT '历史记录标识',
container_booking_id VARCHAR(64) NOT NULL COMMENT '关联柜次标识',
version INT NOT NULL COMMENT '记录版本',
action VARCHAR(20) NOT NULL COMMENT '操作类型:OBSERVED观察/CLAIM认领/RECORD记录/RESOLVE完成',
operator_id VARCHAR(128) NOT NULL COMMENT '操作人标识',
operator_name VARCHAR(200) NULL COMMENT '操作人姓名',
result VARCHAR(1000) NULL COMMENT '人工处理结果;观察记录为空',
next_action VARCHAR(500) NULL COMMENT '下一步处理事项',
followup_date DATE NULL COMMENT '业务跟进日期',
command_key VARCHAR(64) NULL COMMENT '人工命令幂等键;观察记录为空',
request_hash CHAR(64) NULL COMMENT '请求内容摘要',
response_json LONGTEXT NOT NULL COMMENT '该版本完整响应快照,支持精确重放',
created_at DATETIME(3) NOT NULL COMMENT 'UTC记录时间',
PRIMARY KEY (id),
UNIQUE KEY uk_appointment_impact_version (container_booking_id,version),
UNIQUE KEY uk_appointment_impact_command (container_booking_id,operator_id,command_key),
CONSTRAINT fk_appointment_impact_history FOREIGN KEY (container_booking_id) REFERENCES ll_appointment_impact(container_booking_id),
CONSTRAINT chk_appointment_impact_action CHECK (action IN ('OBSERVED','CLAIM','RECORD','RESOLVE'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='船期观察及人工处理追加历史';
CREATE TABLE ll_selfop_owner (
id BIGINT NOT NULL COMMENT '主键',
run_id BIGINT NOT NULL COMMENT '完整资料采集版本',
source_account VARCHAR(64) COLLATE utf8mb4_bin NOT NULL COMMENT '来源账号',
customer_code VARCHAR(64) COLLATE utf8mb4_bin NOT NULL COMMENT '领星货主编码',
customer_name VARCHAR(255) NULL COMMENT '领星货主名称',
source_status VARCHAR(32) NULL COMMENT '来源启停状态',
observed_at_utc DATETIME(6) NOT NULL COMMENT '资料观测时间',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_owner_version (run_id,source_account,customer_code),
KEY idx_selfop_owner_lookup (source_account,customer_code,run_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自营领星货主资料版本';
CREATE TABLE ll_selfop_product (
id BIGINT NOT NULL COMMENT '主键',
run_id BIGINT NOT NULL COMMENT '完整资料采集版本',
source_account VARCHAR(64) COLLATE utf8mb4_bin NOT NULL COMMENT '来源账号',
customer_code VARCHAR(64) COLLATE utf8mb4_bin NOT NULL COMMENT '领星货主编码',
sku_code VARCHAR(128) COLLATE utf8mb4_bin NOT NULL COMMENT '货主商品编码',
product_name VARCHAR(255) NULL COMMENT '商品名称',
declared_length DECIMAL(24,6) NULL COMMENT '商品资料长度',
declared_width DECIMAL(24,6) NULL COMMENT '商品资料宽度',
declared_height DECIMAL(24,6) NULL COMMENT '商品资料高度',
declared_size_unit VARCHAR(32) NULL COMMENT '商品资料尺寸单位',
measured_length DECIMAL(24,6) NULL COMMENT '仓库实测长度',
measured_width DECIMAL(24,6) NULL COMMENT '仓库实测宽度',
measured_height DECIMAL(24,6) NULL COMMENT '仓库实测高度',
measured_size_unit VARCHAR(32) NULL COMMENT '仓库实测尺寸单位',
observed_at_utc DATETIME(6) NOT NULL COMMENT '资料观测时间',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_product_version (run_id,source_account,customer_code,sku_code),
KEY idx_selfop_product_lookup (source_account,customer_code,sku_code,run_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='自营领星商品资料版本';
CREATE TABLE ll_selfop_inventory_flow (
id BIGINT NOT NULL COMMENT '应用生成的流水记录标识',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库编码',
customer_code VARCHAR(64) NOT NULL COMMENT '来源货主编码',
sku_code VARCHAR(128) NOT NULL COMMENT '来源商品编码',
source_flow_id VARCHAR(64) NOT NULL COMMENT '来源流水字符串标识',
product_quality INT NOT NULL COMMENT '来源品质,零正品一次品,其他未知',
cell_no VARCHAR(128) NULL COMMENT '来源库位编码',
inner_batch_no VARCHAR(128) NULL COMMENT '来源内部批次号',
bill_no VARCHAR(128) NULL COMMENT '来源业务单号',
source_no VARCHAR(128) NULL COMMENT '来源关联单号',
bill_type VARCHAR(32) NULL COMMENT '来源业务类型,未验证类型不得参与正式还原',
book_qty DECIMAL(20,6) NULL COMMENT '来源记账增减量,未知为空',
book_change_qty_raw VARCHAR(64) NULL COMMENT '来源带符号变动量原文',
delta_quantity DECIMAL(20,6) NULL COMMENT '解析后的有符号实物变动量',
close_quantity DECIMAL(20,6) NULL COMMENT '对应库位批次品质链的结存',
source_create_time VARCHAR(64) NULL COMMENT '来源北京时间原文',
event_at_utc DATETIME(3) NULL COMMENT '流水发生UTC时刻,无法解析时为空',
business_date DATE NULL COMMENT '北京时间业务日期',
quantity_unit VARCHAR(16) NULL COMMENT '已确认数量单位,未知为空',
content_hash CHAR(64) NOT NULL COMMENT '当前事实内容摘要',
revision_no BIGINT NOT NULL COMMENT '同来源流水单调增加的修订号',
stage_id BIGINT NOT NULL COMMENT '当前事实对应不可变暂存证据',
first_run_id BIGINT NOT NULL COMMENT '首次观察执行尝试',
last_run_id BIGINT NOT NULL COMMENT '最近确认执行尝试',
last_observed_at DATETIME(3) NOT NULL COMMENT '最近观察UTC时刻',
validation_status VARCHAR(16) NOT NULL COMMENT '字段资格,有效或未知',
validation_reason VARCHAR(64) NULL COMMENT '数量或身份待核验原因',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_flow_source (source_account,warehouse_code,source_flow_id),
KEY idx_selfop_flow_sku (source_account,warehouse_code,customer_code,sku_code,event_at_utc),
KEY idx_selfop_flow_day (source_account,warehouse_code,business_date),
CONSTRAINT chk_selfop_flow_revision CHECK (revision_no > 0)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='自营历史库存流水最新事实,旧版本保留于暂存证据';
CREATE TABLE ll_selfop_inventory_day_version (
id BIGINT NOT NULL COMMENT '不可变历史日版本标识',
source_account VARCHAR(64) NOT NULL COMMENT '受控来源账号',
warehouse_code VARCHAR(64) NOT NULL COMMENT '来源仓库编码',
business_date DATE NOT NULL COMMENT '北京时间日末所属日期',
scope_hash CHAR(64) NOT NULL COMMENT '业务范围摘要',
rule_version VARCHAR(32) NOT NULL COMMENT '日末库存还原规则版本',
build_run_id BIGINT NOT NULL COMMENT '历史重建执行尝试',
publication_group_id BIGINT NOT NULL COMMENT '必须一起切换的发布组标识',
sales_run_id BIGINT NULL COMMENT '构建时固定的销量证据版本',
anchor_run_id BIGINT NOT NULL COMMENT '固定的独立库存锚点版本',
input_hash CHAR(64) NOT NULL COMMENT '冻结流水修订与覆盖及锚点输入摘要',
evidence_json JSON NOT NULL COMMENT '固定输入清单及不可变证据引用',
status VARCHAR(16) NOT NULL COMMENT '构建中、就绪、已发布、已替代或失败',
head_slot TINYINT NULL COMMENT '当前日头为一,非当前版本为空',
valid_sku_count BIGINT NOT NULL DEFAULT 0 COMMENT '合格商品数',
unknown_sku_count BIGINT NOT NULL DEFAULT 0 COMMENT '待核验商品数',
created_at DATETIME(3) NOT NULL COMMENT '版本创建UTC时刻',
published_at DATETIME(3) NULL COMMENT '发布组提交UTC时刻',
superseded_at DATETIME(3) NULL COMMENT '被新组替代的UTC时刻',
invalidated_at DATETIME(3) NULL COMMENT '已确认输入失效的UTC时刻',
invalidation_reason VARCHAR(64) NULL COMMENT '旧版本失效原因',
rebuild_run_id BIGINT NULL COMMENT '处理失效版本的重建尝试',
PRIMARY KEY (id),
UNIQUE KEY uk_selfop_history_head (source_account,warehouse_code,business_date,head_slot),
UNIQUE KEY uk_selfop_history_build_day (build_run_id,business_date),
KEY idx_selfop_history_group (publication_group_id,status),
CONSTRAINT chk_selfop_history_head CHECK (head_slot IS NULL OR (head_slot=1 AND status='PUBLISHED'))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='历史日库存不可变版本及原子发布日头';
CREATE TABLE ll_selfop_inventory_daily (
day_version_id BIGINT NOT NULL COMMENT '所属历史日版本',
customer_code VARCHAR(64) NOT NULL COMMENT '来源货主编码',
sku_code VARCHAR(128) NOT NULL COMMENT '来源商品编码',
product_quality INT NOT NULL COMMENT '来源库存品质',
physical_quantity DECIMAL(20,6) NULL COMMENT '日末实物库存,未知为空,已确认零为零',
quality_status VARCHAR(16) NOT NULL COMMENT '日末资格,有效或未知',
quality_reason VARCHAR(64) NULL COMMENT '缺覆盖或锚点等未知原因',
anchor_reference BIGINT NULL COMMENT '独立库存锚点版本',
evidence_hash CHAR(64) NOT NULL COMMENT '该日计算证据摘要',
source VARCHAR(32) NOT NULL COMMENT '库存来源标记,流水还原',
PRIMARY KEY (day_version_id,customer_code,sku_code,product_quality),
KEY idx_selfop_daily_identity (customer_code,sku_code,day_version_id),
CONSTRAINT chk_selfop_daily_quantity CHECK ((quality_status='VALID' AND physical_quantity IS NOT NULL AND physical_quantity>=0) OR (quality_status='UNKNOWN' AND physical_quantity IS NULL))
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin COMMENT='历史日末分货主商品品质实物库存';
@@ -0,0 +1,100 @@
[
{
"db": "baiyue_firstleg",
"baselineTables": 131,
"missingColumns": [],
"missingIndexes": [
"fl_container_booking.uk_container_booking_ocean_container",
"fl_container_booking.idx_container_booking_container_no",
"fl_container_booking.idx_container_booking_merge",
"fl_container_booking.idx_container_booking_transit_summary",
"fl_container_fee_detail.idx_container_fee_review",
"fl_container_transport_history.uk_container_transport_history_operation",
"fl_customer_charge_rule.idx_charge_rule_initialization",
"fl_inbound_order.idx_inbound_smart_loading",
"fl_inbound_measurement.idx_measure_inbound_status_id",
"fl_loading_plan_item.uk_loading_item_plan_assignment",
"fl_loading_plan_item.idx_loading_item_candidate",
"fl_loading_plan_item.idx_loading_item_pallet",
"fl_ocean_booking.uk_ocean_booking_bill_of_lading",
"fl_carrier_schedule_node_fact.idx_container_shipping_node_timeline",
"fl_truck_appointment.uk_truck_active_ocean_booking",
"fl_truck_appointment.idx_truck_appointment_ocean",
"fl_inbound_measurement_item.idx_measure_item_candidate",
"fl_inbound_split_item.idx_inbound_split_candidate"
],
"appliedIndexes": [
"fl_container_booking.uk_container_booking_ocean_container",
"fl_container_booking.idx_container_booking_container_no",
"fl_container_booking.idx_container_booking_merge",
"fl_container_booking.idx_container_booking_transit_summary",
"fl_container_fee_detail.idx_container_fee_review",
"fl_container_transport_history.uk_container_transport_history_operation",
"fl_customer_charge_rule.idx_charge_rule_initialization",
"fl_inbound_order.idx_inbound_smart_loading",
"fl_inbound_measurement.idx_measure_inbound_status_id",
"fl_loading_plan_item.uk_loading_item_plan_assignment",
"fl_loading_plan_item.idx_loading_item_candidate",
"fl_loading_plan_item.idx_loading_item_pallet",
"fl_ocean_booking.uk_ocean_booking_bill_of_lading",
"fl_carrier_schedule_node_fact.idx_container_shipping_node_timeline",
"fl_truck_appointment.uk_truck_active_ocean_booking",
"fl_truck_appointment.idx_truck_appointment_ocean",
"fl_inbound_measurement_item.idx_measure_item_candidate",
"fl_inbound_split_item.idx_inbound_split_candidate"
],
"blockedIndexes": []
},
{
"db": "baiyue_lastleg",
"baselineTables": 218,
"missingColumns": [],
"missingIndexes": [
"ll_cargo_discard_item.uk_ll_discard_position_sku",
"ll_dispatch_draft_container.uk_ll_dispatch_draft_container_sequence",
"ll_dispatch_order.uk_dispatch_trip",
"ll_dispatch_pallet_lock.uk_ll_dispatch_active_warehouse_pallet",
"ll_dispatch_pda_pick_order.idx_dispatch_pick_return_receipt",
"ll_dropship_order_profile.idx_ll_dropship_profile_manifest",
"ll_dropship_sku_inventory.uk_ll_dropship_sku_inventory",
"ll_exception_order.idx_ll_exception_delivery_return",
"ll_exception_return_item.uk_ll_exception_return_carton",
"ll_inbound_fba_appointment.idx_ll_fba_appointment_planned",
"ll_inbound_fba_appointment_item.idx_ll_fba_active_source",
"ll_inbound_fba_appointment_item.idx_ll_fba_active_order",
"ll_inbound_plan.uk_ll_inbound_plan_source_order",
"ll_inbound_plan_pallet.idx_ll_inbound_pallet_no",
"ll_outbound_pallet_item.uk_outbound_source_attribution",
"ll_overseas_procurement_fee.uk_ll_procurement_fee_version",
"ll_fleet_trip_dispatch.uk_fleet_trip_dispatch_trip",
"ll_warehouse_transfer_inventory_allocation.idx_ll_wh_transfer_allocation_position",
"ll_return_packing_plan.idx_ll_return_packing_plan_warehouse"
],
"appliedIndexes": [
"ll_cargo_discard_item.uk_ll_discard_position_sku",
"ll_dispatch_draft_container.uk_ll_dispatch_draft_container_sequence",
"ll_dispatch_order.uk_dispatch_trip",
"ll_dispatch_pallet_lock.uk_ll_dispatch_active_warehouse_pallet",
"ll_dispatch_pda_pick_order.idx_dispatch_pick_return_receipt",
"ll_dropship_order_profile.idx_ll_dropship_profile_manifest",
"ll_dropship_sku_inventory.uk_ll_dropship_sku_inventory",
"ll_exception_order.idx_ll_exception_delivery_return",
"ll_exception_return_item.uk_ll_exception_return_carton",
"ll_inbound_fba_appointment.idx_ll_fba_appointment_planned",
"ll_inbound_fba_appointment_item.idx_ll_fba_active_source",
"ll_inbound_fba_appointment_item.idx_ll_fba_active_order",
"ll_inbound_plan_pallet.idx_ll_inbound_pallet_no",
"ll_outbound_pallet_item.uk_outbound_source_attribution",
"ll_overseas_procurement_fee.uk_ll_procurement_fee_version",
"ll_fleet_trip_dispatch.uk_fleet_trip_dispatch_trip",
"ll_warehouse_transfer_inventory_allocation.idx_ll_wh_transfer_allocation_position",
"ll_return_packing_plan.idx_ll_return_packing_plan_warehouse"
],
"blockedIndexes": [
{
"index": "ll_inbound_plan.uk_ll_inbound_plan_source_order",
"reason": "ERROR 1062 (23000) at line 1: Duplicate entry '10001-0' for key 'll_inbound_plan.uk_ll_inbound_plan_source_order'\r\n"
}
]
}
]
@@ -0,0 +1,267 @@
{
"baselineTables": 218,
"actualTables": 170,
"addedTables": [
"ll_dispatch_draft_command",
"ll_dispatch_history",
"ll_return_carton_stock_receipt",
"ll_fba_receiving_agreement",
"ll_fba_receiving_member",
"ll_fba_receiving_change",
"ll_fba_receiving_revision",
"ll_fba_receiving_plan",
"ll_appointment_cargo_verification",
"ll_fba_appointment_command",
"ll_appointment_followup",
"ll_dispatch_command",
"ll_dispatch_delivery_arrangement",
"ll_delivery_facts_changed",
"event_delivery_retry_audit",
"ll_procurement_wallet_attempt",
"ll_procurement_flow",
"ll_procurement_command",
"ll_procurement_budget_authorization",
"ll_procurement_receipt",
"ll_procurement_disposition",
"ll_procurement_manifest",
"ll_procurement_carton",
"ll_procurement_carton_source",
"ll_procurement_shipment",
"ll_procurement_shipment_item",
"ll_procurement_label_set",
"ll_procurement_label_item",
"ll_procurement_estimate_review",
"ll_procurement_repack",
"ll_procurement_fee_correction",
"ll_procurement_fee_correction_item",
"ll_procurement_control_note",
"ll_procurement_closure",
"ll_procurement_closure_item",
"ll_selfop_outbound_discovery_scope",
"ll_selfop_sync_scope",
"ll_selfop_sync_task",
"ll_selfop_sync_run",
"ll_selfop_sync_stage",
"ll_selfop_outbound_order",
"ll_selfop_outbound_item",
"ll_selfop_inventory_snapshot",
"ll_selfop_sku_daily_sales",
"ll_selfop_warehouse_daily_sales",
"ll_selfop_sku_profile",
"ll_appointment_impact",
"ll_appointment_impact_history",
"ll_selfop_owner",
"ll_selfop_product",
"ll_selfop_inventory_flow",
"ll_selfop_inventory_day_version",
"ll_selfop_inventory_daily"
],
"addedColumns": [
"ll_cargo_discard_carton.source_type",
"ll_dispatch_draft.warehouse_id",
"ll_dispatch_draft.record_version",
"ll_dispatch_draft.sources_json",
"ll_dispatch_draft_container.source_keys_json",
"ll_dispatch_item.customer_name",
"ll_dispatch_item.source_key",
"ll_dispatch_item.source_version",
"ll_dispatch_item.source_snapshot_json",
"ll_dispatch_order.trip_id",
"ll_dispatch_order.overseas_warehouse_code",
"ll_dispatch_order.stage",
"ll_dispatch_order.record_version",
"ll_dispatch_order.cargo_revision",
"ll_dispatch_order.cargo_hash",
"ll_dispatch_order.review_state",
"ll_dispatch_order.review_round",
"ll_dispatch_order.review_basis_hash",
"ll_dispatch_order.dispatch_review_json",
"ll_dispatch_order.loading_review_json",
"ll_dispatch_order.resources_json",
"ll_dispatch_order.planned_departure_at",
"ll_dispatch_order.loading_completed_at",
"ll_dispatch_order.loading_completion_hash",
"ll_dispatch_order.loading_confirmation_json",
"ll_dispatch_order.arrangement_key",
"ll_dispatch_order.arrangement_business_hash",
"ll_dispatch_order.departed_at",
"ll_dispatch_order.delivery_completed_at",
"ll_dispatch_order.remark",
"ll_dispatch_pallet_lock.active_warehouse_pallet_id",
"ll_dropship_carton.product_quantity",
"ll_dropship_order_profile.manifest_version",
"ll_dropship_order_profile.manifest_package_count",
"ll_dropship_order_profile.manifest_fragment_count",
"ll_dropship_order_profile.manifest_hash",
"ll_exception_order.return_context_json",
"ll_exception_return_item.return_carton_id",
"ll_exception_return_item.return_carton_mark",
"ll_exception_return_item.received_packages",
"ll_inbound_fba_appointment.confirmation_no",
"ll_inbound_fba_appointment.planned_date",
"ll_inbound_fba_appointment.planned_at",
"ll_inbound_fba_appointment.planned_end_at",
"ll_inbound_fba_appointment.appointment_start_utc",
"ll_inbound_fba_appointment.appointment_end_utc",
"ll_inbound_fba_appointment.timezone",
"ll_inbound_fba_appointment.origin_warehouse_id",
"ll_inbound_fba_appointment.replacement_keys_json",
"ll_inbound_fba_appointment.repartition_reason",
"ll_inbound_fba_appointment_item.cargo_verification_version",
"ll_inbound_fba_appointment_item.shipment_references_json",
"ll_local_looseboard_order.product_name",
"ll_local_looseboard_order.origin_contact_name",
"ll_local_looseboard_order.destination_contact_name",
"ll_local_looseboard_order.pickup_at",
"ll_outbound_pallet_item.dispatch_item_id",
"ll_outbound_pallet_item.source_attribution_id",
"ll_outbound_pallet_item.source_order_id",
"ll_outbound_pallet_item.source_inventory_position_id",
"ll_outbound_pallet_item.source_return_receipt_id",
"ll_outbound_pallet_item.source_return_carton_id",
"ll_overseas_procurement_fee.purpose",
"ll_overseas_procurement_fee.confirmation_origin",
"ll_overseas_procurement_fee.fee_version",
"ll_overseas_procurement_fee.active",
"ll_overseas_procurement_fee.determination",
"ll_overseas_procurement_fee.original_currency",
"ll_overseas_procurement_fee.original_amount",
"ll_overseas_procurement_fee.exchange_rate",
"ll_overseas_procurement_fee.exchange_rate_month",
"ll_overseas_procurement_fee.business_date",
"ll_overseas_procurement_fee.wallet_business_id",
"ll_overseas_procurement_fee.wallet_business_no",
"ll_overseas_procurement_fee.wallet_hold_id",
"ll_overseas_procurement_fee.wallet_ledger_id",
"ll_overseas_procurement_fee.settled_command_event_id",
"ll_overseas_procurement_fee.source_fee_id",
"ll_overseas_procurement_fee.parent_fee_id",
"ll_overseas_procurement_fee.request_hash",
"ll_overseas_procurement_status_history.operation_type",
"ll_overseas_procurement_status_history.change_detail",
"ll_receiving_container_session.source_container_booking_id",
"ll_receiving_container_session.container_fact_hash",
"ll_receiving_container_session.overseas_warehouse_code",
"ll_us_truck_order.vehicle_type",
"ll_us_truck_order.origin_contact_name",
"ll_us_truck_order.origin_contact_phone",
"ll_us_truck_order.destination_contact_name",
"ll_us_truck_order.destination_contact_phone",
"ll_us_truck_order.pickup_at",
"ll_us_truck_order.delivery_at"
],
"unsafe": [
{
"table": "ll_dispatch_draft",
"column": "warehouse_id",
"count": 11,
"definition": "warehouse_id BIGINT NOT NULL COMMENT '本草稿唯一起运公共仓库引用'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dispatch_draft",
"column": "sources_json",
"count": 11,
"definition": "sources_json LONGTEXT NOT NULL COMMENT '服务端核验的真实来源及客户版本快照数组'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dispatch_draft_container",
"column": "source_keys_json",
"count": 7,
"definition": "source_keys_json LONGTEXT NOT NULL COMMENT '本装车容器已取得本草稿占用的来源键数组'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dispatch_item",
"column": "source_key",
"count": 60,
"definition": "source_key VARCHAR(255) NOT NULL COMMENT '本条货物稳定权威来源键'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dispatch_item",
"column": "source_version",
"count": 60,
"definition": "source_version CHAR(64) NOT NULL COMMENT '选货时核对的真实来源版本摘要'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dispatch_item",
"column": "source_snapshot_json",
"count": 60,
"definition": "source_snapshot_json JSON NOT NULL COMMENT '本条货物不可变来源及关联事实快照'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dispatch_order",
"column": "trip_id",
"count": 48,
"definition": "trip_id BIGINT NOT NULL COMMENT '本趟唯一车辆资源记录ID'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dispatch_order",
"column": "cargo_hash",
"count": 48,
"definition": "cargo_hash CHAR(64) NOT NULL COMMENT '当前整车真实货物及来源摘要'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dropship_carton",
"column": "product_quantity",
"count": 83,
"definition": "product_quantity bigint NOT NULL COMMENT '该箱实收商品件数'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dropship_order_profile",
"column": "manifest_version",
"count": 17,
"definition": "manifest_version int NOT NULL COMMENT '整托清单版本'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dropship_order_profile",
"column": "manifest_package_count",
"count": 17,
"definition": "manifest_package_count int NOT NULL COMMENT '整托总箱数'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dropship_order_profile",
"column": "manifest_fragment_count",
"count": 17,
"definition": "manifest_fragment_count int NOT NULL COMMENT '整托客户分片总数'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_dropship_order_profile",
"column": "manifest_hash",
"count": 17,
"definition": "manifest_hash char(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '整托完整清单摘要'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_overseas_procurement_status_history",
"column": "operation_type",
"count": 9,
"definition": "operation_type varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '操作类型:CREATE、REVIEW或UPDATE'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_receiving_container_session",
"column": "source_container_booking_id",
"count": 1,
"definition": "source_container_booking_id varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '稳定来源柜预订ID'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_receiving_container_session",
"column": "container_fact_hash",
"count": 1,
"definition": "container_fact_hash varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '领取时整柜订单与计划事实摘要'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
}
]
}
@@ -0,0 +1,2 @@
Table Create Table
fl_carrier_schedule_node_fact CREATE TABLE `fl_carrier_schedule_node_fact` (\n `id` bigint unsigned NOT NULL COMMENT '标准船节点事实ID',\n `query_id` bigint unsigned NOT NULL COMMENT '所属查询任务ID',\n `event_key` varchar(192) NOT NULL COMMENT '供应商编码与供应商事件ID组成的幂等键',\n `provider_code` varchar(32) NOT NULL COMMENT '轨迹供应商编码',\n `provider_event_id` varchar(128) NOT NULL COMMENT '供应商稳定事件ID',\n `provider_node_code` varchar(64) NOT NULL COMMENT '供应商原始节点编码',\n `standard_node` varchar(32) NOT NULL COMMENT '标准船节点',\n `node_sequence` int unsigned NOT NULL COMMENT '标准节点单调序号',\n `observed_at` datetime(3) NOT NULL COMMENT '供应商观测时间',\n `estimated_at` datetime(3) DEFAULT NULL COMMENT '供应商预计发生时间',\n `actual_at` datetime(3) DEFAULT NULL COMMENT '供应商确认实际发生时间',\n `location_code` varchar(32) DEFAULT NULL COMMENT '节点地点编码',\n `location_name` varchar(128) DEFAULT NULL COMMENT '节点地点名称',\n `source_reference` varchar(500) DEFAULT NULL COMMENT '可审计来源引用',\n `raw_payload_hash` char(64) NOT NULL COMMENT '原始响应SHA-256;不保存敏感原文',\n `created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '事实入库时间',\n `container_booking_id` bigint unsigned NOT NULL COMMENT '所属真实货柜ID',\n PRIMARY KEY (`id`),\n UNIQUE KEY `uk_carrier_schedule_node_event` (`query_id`,`event_key`),\n KEY `idx_carrier_schedule_node_timeline` (`query_id`,`node_sequence`,`observed_at`,`id`),\n KEY `idx_container_shipping_node_timeline` (`container_booking_id`,`observed_at`,`id`),\n CONSTRAINT `fk_carrier_schedule_node_query` FOREIGN KEY (`query_id`) REFERENCES `fl_carrier_schedule_query` (`id`),\n CONSTRAINT `chk_carrier_schedule_node_sequence` CHECK ((`node_sequence` in (10,20,30,40,50,60,70,80,90,100))),\n CONSTRAINT `chk_carrier_schedule_node_standard` CHECK ((`standard_node` in (_utf8mb4'DEPARTED_WAREHOUSE',_utf8mb4'AT_ORIGIN_PORT',_utf8mb4'LOADED_ON_VESSEL',_utf8mb4'DEPARTED_ORIGIN_PORT',_utf8mb4'IN_TRANSIT',_utf8mb4'ARRIVED_DESTINATION_PORT',_utf8mb4'DISCHARGED_FROM_VESSEL',_utf8mb4'PICKUP_READY',_utf8mb4'PICKED_UP',_utf8mb4'EMPTY_RETURNED')))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='供应商标准船节点不可变事实'
1 Table Create Table
2 fl_carrier_schedule_node_fact CREATE TABLE `fl_carrier_schedule_node_fact` (\n `id` bigint unsigned NOT NULL COMMENT '标准船节点事实ID',\n `query_id` bigint unsigned NOT NULL COMMENT '所属查询任务ID',\n `event_key` varchar(192) NOT NULL COMMENT '供应商编码与供应商事件ID组成的幂等键',\n `provider_code` varchar(32) NOT NULL COMMENT '轨迹供应商编码',\n `provider_event_id` varchar(128) NOT NULL COMMENT '供应商稳定事件ID',\n `provider_node_code` varchar(64) NOT NULL COMMENT '供应商原始节点编码',\n `standard_node` varchar(32) NOT NULL COMMENT '标准船节点',\n `node_sequence` int unsigned NOT NULL COMMENT '标准节点单调序号',\n `observed_at` datetime(3) NOT NULL COMMENT '供应商观测时间',\n `estimated_at` datetime(3) DEFAULT NULL COMMENT '供应商预计发生时间',\n `actual_at` datetime(3) DEFAULT NULL COMMENT '供应商确认实际发生时间',\n `location_code` varchar(32) DEFAULT NULL COMMENT '节点地点编码',\n `location_name` varchar(128) DEFAULT NULL COMMENT '节点地点名称',\n `source_reference` varchar(500) DEFAULT NULL COMMENT '可审计来源引用',\n `raw_payload_hash` char(64) NOT NULL COMMENT '原始响应SHA-256;不保存敏感原文',\n `created_at` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '事实入库时间',\n `container_booking_id` bigint unsigned NOT NULL COMMENT '所属真实货柜ID',\n PRIMARY KEY (`id`),\n UNIQUE KEY `uk_carrier_schedule_node_event` (`query_id`,`event_key`),\n KEY `idx_carrier_schedule_node_timeline` (`query_id`,`node_sequence`,`observed_at`,`id`),\n KEY `idx_container_shipping_node_timeline` (`container_booking_id`,`observed_at`,`id`),\n CONSTRAINT `fk_carrier_schedule_node_query` FOREIGN KEY (`query_id`) REFERENCES `fl_carrier_schedule_query` (`id`),\n CONSTRAINT `chk_carrier_schedule_node_sequence` CHECK ((`node_sequence` in (10,20,30,40,50,60,70,80,90,100))),\n CONSTRAINT `chk_carrier_schedule_node_standard` CHECK ((`standard_node` in (_utf8mb4'DEPARTED_WAREHOUSE',_utf8mb4'AT_ORIGIN_PORT',_utf8mb4'LOADED_ON_VESSEL',_utf8mb4'DEPARTED_ORIGIN_PORT',_utf8mb4'IN_TRANSIT',_utf8mb4'ARRIVED_DESTINATION_PORT',_utf8mb4'DISCHARGED_FROM_VESSEL',_utf8mb4'PICKUP_READY',_utf8mb4'PICKED_UP',_utf8mb4'EMPTY_RETURNED')))\n) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='供应商标准船节点不可变事实'
@@ -0,0 +1,2 @@
CONSTRAINT_NAME CHECK_CLAUSE
chk_loading_pick_task_status (`task_status` in (_utf8mb4\\'LOADING\\',_utf8mb4\\'COMPLETED\\'))
1 CONSTRAINT_NAME CHECK_CLAUSE
2 chk_loading_pick_task_status (`task_status` in (_utf8mb4\\'LOADING\\',_utf8mb4\\'COMPLETED\\'))
@@ -0,0 +1,2 @@
Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation Created
trg_loading_pick_task_before_update ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` TRIGGER `trg_loading_pick_task_before_update` BEFORE UPDATE ON `fl_loading_pick_task` FOR EACH ROW BEGIN IF OLD.task_status = 'COMPLETED' THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '已完成PDA拣货任务不可修改'; END IF; IF NEW.loading_plan_id <> OLD.loading_plan_id OR NOT (NEW.container_booking_id <=> OLD.container_booking_id) OR NOT (NEW.cabinet_no <=> OLD.cabinet_no) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA拣货任务稳定归属不可修改'; END IF; IF NOT (OLD.task_status = 'LOADING' AND NEW.task_status IN ('LOADING', 'COMPLETED')) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA拣货任务状态只允许完成'; END IF; END utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci 2026-08-27 14:02:32.25
1 Trigger sql_mode SQL Original Statement character_set_client collation_connection Database Collation Created
2 trg_loading_pick_task_before_update ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION CREATE DEFINER=`root`@`localhost` TRIGGER `trg_loading_pick_task_before_update` BEFORE UPDATE ON `fl_loading_pick_task` FOR EACH ROW BEGIN IF OLD.task_status = 'COMPLETED' THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '已完成PDA拣货任务不可修改'; END IF; IF NEW.loading_plan_id <> OLD.loading_plan_id OR NOT (NEW.container_booking_id <=> OLD.container_booking_id) OR NOT (NEW.cabinet_no <=> OLD.cabinet_no) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA拣货任务稳定归属不可修改'; END IF; IF NOT (OLD.task_status = 'LOADING' AND NEW.task_status IN ('LOADING', 'COMPLETED')) THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA拣货任务状态只允许完成'; END IF; END utf8mb4 utf8mb4_0900_ai_ci utf8mb4_0900_ai_ci 2026-08-27 14:02:32.25
@@ -0,0 +1,22 @@
DROP TRIGGER IF EXISTS trg_loading_pick_task_before_update;
DELIMITER $$
CREATE TRIGGER trg_loading_pick_task_before_update
BEFORE UPDATE ON fl_loading_pick_task
FOR EACH ROW
BEGIN
IF OLD.task_status = 'COMPLETED' THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = '已完成PDA拣货任务不可修改';
END IF;
IF NEW.loading_plan_id <> OLD.loading_plan_id
OR NOT (NEW.container_booking_id <=> OLD.container_booking_id)
OR NOT (NEW.cabinet_no <=> OLD.cabinet_no) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA拣货任务稳定归属不可修改';
END IF;
IF NOT ((OLD.task_status = 'LOADING' AND NEW.task_status IN ('LOADING','COMPLETING'))
OR (OLD.task_status = 'COMPLETING' AND NEW.task_status IN ('COMPLETING','COMPLETION_FAILED','COMPLETED'))
OR (OLD.task_status = 'COMPLETION_FAILED' AND NEW.task_status = 'COMPLETING')) THEN
SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = 'PDA拣货任务状态流转非法';
END IF;
END$$
DELIMITER ;
+119
View File
@@ -0,0 +1,119 @@
{
"baselineTables": 218,
"actualTables": 180,
"addedTables": [
"ll_appointment_followup",
"ll_dispatch_command",
"ll_dispatch_delivery_arrangement",
"ll_delivery_facts_changed",
"event_delivery_retry_audit",
"ll_procurement_wallet_attempt",
"ll_procurement_flow",
"ll_procurement_command",
"ll_procurement_budget_authorization",
"ll_procurement_receipt",
"ll_procurement_disposition",
"ll_procurement_manifest",
"ll_procurement_carton",
"ll_procurement_carton_source",
"ll_procurement_shipment",
"ll_procurement_shipment_item",
"ll_procurement_label_set",
"ll_procurement_label_item",
"ll_procurement_estimate_review",
"ll_procurement_repack",
"ll_procurement_fee_correction",
"ll_procurement_fee_correction_item",
"ll_procurement_control_note",
"ll_procurement_closure",
"ll_procurement_closure_item",
"ll_selfop_outbound_discovery_scope",
"ll_selfop_sync_scope",
"ll_selfop_sync_task",
"ll_selfop_sync_run",
"ll_selfop_sync_stage",
"ll_selfop_outbound_order",
"ll_selfop_outbound_item",
"ll_selfop_inventory_snapshot",
"ll_selfop_sku_daily_sales",
"ll_selfop_warehouse_daily_sales",
"ll_selfop_sku_profile",
"ll_appointment_impact",
"ll_appointment_impact_history",
"ll_selfop_owner",
"ll_selfop_product",
"ll_selfop_inventory_flow",
"ll_selfop_inventory_day_version",
"ll_selfop_inventory_daily"
],
"addedColumns": [
"ll_local_looseboard_order.product_name",
"ll_local_looseboard_order.estimated_pallet_count",
"ll_local_looseboard_order.origin_contact_name",
"ll_local_looseboard_order.origin_contact_phone",
"ll_local_looseboard_order.destination_contact_name",
"ll_local_looseboard_order.destination_contact_phone",
"ll_local_looseboard_order.pickup_at",
"ll_local_looseboard_order.delivery_at",
"ll_outbound_pallet_item.dispatch_item_id",
"ll_outbound_pallet_item.source_attribution_id",
"ll_outbound_pallet_item.source_order_id",
"ll_outbound_pallet_item.source_inventory_position_id",
"ll_outbound_pallet_item.source_return_receipt_id",
"ll_outbound_pallet_item.source_return_carton_id",
"ll_overseas_procurement_fee.purpose",
"ll_overseas_procurement_fee.confirmation_origin",
"ll_overseas_procurement_fee.fee_version",
"ll_overseas_procurement_fee.active",
"ll_overseas_procurement_fee.determination",
"ll_overseas_procurement_fee.original_currency",
"ll_overseas_procurement_fee.original_amount",
"ll_overseas_procurement_fee.exchange_rate",
"ll_overseas_procurement_fee.exchange_rate_month",
"ll_overseas_procurement_fee.business_date",
"ll_overseas_procurement_fee.wallet_business_id",
"ll_overseas_procurement_fee.wallet_business_no",
"ll_overseas_procurement_fee.wallet_hold_id",
"ll_overseas_procurement_fee.wallet_ledger_id",
"ll_overseas_procurement_fee.settled_command_event_id",
"ll_overseas_procurement_fee.source_fee_id",
"ll_overseas_procurement_fee.parent_fee_id",
"ll_overseas_procurement_fee.request_hash",
"ll_overseas_procurement_status_history.operation_type",
"ll_overseas_procurement_status_history.change_detail",
"ll_receiving_container_session.source_container_booking_id",
"ll_receiving_container_session.container_fact_hash",
"ll_receiving_container_session.overseas_warehouse_code",
"ll_return_inventory_outbound_movement.return_sku_quantity",
"ll_us_truck_order.vehicle_type",
"ll_us_truck_order.origin_contact_name",
"ll_us_truck_order.origin_contact_phone",
"ll_us_truck_order.destination_contact_name",
"ll_us_truck_order.destination_contact_phone",
"ll_us_truck_order.pickup_at",
"ll_us_truck_order.delivery_at"
],
"unsafe": [
{
"table": "ll_overseas_procurement_status_history",
"column": "operation_type",
"count": 9,
"definition": "operation_type varchar(32) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '操作类型:CREATE、REVIEW或UPDATE'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_receiving_container_session",
"column": "source_container_booking_id",
"count": 1,
"definition": "source_container_booking_id varchar(128) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '稳定来源柜预订ID'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
},
{
"table": "ll_receiving_container_session",
"column": "container_fact_hash",
"count": 1,
"definition": "container_fact_hash varchar(64) COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '领取时整柜订单与计划事实摘要'",
"handling": "历史行保留NULL,不伪造业务事实;新写入由应用校验"
}
]
}
+52
View File
@@ -0,0 +1,52 @@
import fs from 'node:fs';
import {spawnSync} from 'node:child_process';
const dir = new URL('./', import.meta.url);
const schema=process.argv.includes('--firstleg')?'baiyue_firstleg':'baiyue_lastleg';
const prefix=schema==='baiyue_firstleg'?'firstleg-':'';
function definitions(body) {
let depth=0,quote='',start=0;const parts=[];
for(let i=0;i<body.length;i++) {const c=body[i];
if(quote){if(c==='\\'){i++;continue;}if(c===quote){if(body[i+1]===quote)i++;else quote='';}continue;}
if(c==="'"||c==='"'||c==='`'){quote=c;continue;}
if(c==='(')depth++;else if(c===')')depth--;else if(c===','&&depth===0){parts.push(body.slice(start,i).trim());start=i+1;}
}
parts.push(body.slice(start).trim());return parts;
}
function mysql(sql) {
const r=spawnSync('D:/baiyue-runtime/mysql/server/bin/mysql.exe', ['--host=127.0.0.1','--user=root','--database='+schema,'--batch','--skip-column-names','--default-character-set=utf8mb4'], {input:sql,encoding:'utf8',env:process.env,maxBuffer:20*1024*1024});
if(r.status!==0) throw new Error(r.stderr); return r.stdout.trim();
}
const source=fs.readFileSync('deploy/sql/'+(prefix?'头程数据库统一增量-MySQL8.sql':'海外区域统一增量-MySQL8.sql'),'utf8');
let db='';const tables=[];
for(const m of source.matchAll(/USE (\w+);|CREATE TABLE\s+(?:IF NOT EXISTS\s+)?(\w+)\s*\(([\s\S]*?)\n\) ENGINE=[^;]+;/g)) {if(m[1])db=m[1];else if(db===schema)tables.push([m[0],m[2],m[3]]);}
if(tables.length<(prefix?100:170)) throw new Error('基线解析不完整');
const actual=mysql("SELECT table_name,column_name FROM information_schema.columns WHERE table_schema=DATABASE() ORDER BY table_name,ordinal_position;");
fs.writeFileSync(new URL(prefix+'columns-before.tsv',dir),actual);
const current=new Map();
for(const line of actual.split(/\r?\n/)) {const [t,c]=line.split('\t'); if(!current.has(t))current.set(t,new Set()); current.get(t).add(c);}
const plan=[], addedTables=[], addedColumns=[], unsafe=[], counts=new Map();
for(const m of tables) {
const [,table,body]=m;
if(!current.has(table)){plan.push(m[0]);addedTables.push(table);continue;}
for(const line of definitions(body)) {
const field=line.match(/^`?([a-z][a-z0-9_]*)`?\s+([\s\S]+)$/i);
if(!field || !/^(?:bigint|int|integer|tinyint|smallint|mediumint|varchar|char|text|longtext|mediumtext|datetime|timestamp|date|time|decimal|double|float|json|boolean|bool|binary|varbinary|blob|enum|bit)\b/i.test(field[2]) || current.get(table).has(field[1]))continue;
const definition=line.trim().replace(/,$/,'');
if(!counts.has(table))counts.set(table,Number(mysql('SELECT COUNT(*) FROM `'+table+'`;')));
const count=counts.get(table);
let appliedDefinition=definition;
if(count>0 && /NOT NULL/i.test(definition) && !/DEFAULT|AUTO_INCREMENT/i.test(definition)) {
unsafe.push({table,column:field[1],count,definition,handling:'历史行保留NULL,不伪造业务事实;新写入由应用校验'});
appliedDefinition=definition.replace(/NOT NULL/i,'NULL');
}
plan.push('ALTER TABLE `'+table+'` ADD COLUMN '+appliedDefinition+';');addedColumns.push(table+'.'+field[1]);
}
}
const report={baselineTables:tables.length,actualTables:current.size,addedTables,addedColumns,unsafe};
fs.writeFileSync(new URL(prefix+'plan.json',dir),JSON.stringify(report,null,2));
fs.writeFileSync(new URL(prefix+'incremental.sql',dir),'-- 本地服务结构补齐;仅创建缺失表、添加缺失字段,不删除现有数据。\nSET NAMES utf8mb4;\n'+plan.join('\n\n')+'\n');
console.log(JSON.stringify(report,null,2));
if(process.argv.includes('--apply')) {
mysql('SET SESSION lock_wait_timeout=15;\n'+plan.join('\n'));fs.appendFileSync(new URL(prefix+'applied.log',dir),`${new Date().toISOString()} ${plan.length} DDL applied\n`);
console.log('APPLIED '+plan.length);
}
@@ -0,0 +1,27 @@
$ErrorActionPreference='Stop'
$repo='D:\project\baiyue-firstleg'
. "$repo\scripts\local-env.ps1"
$env:LASTLEG_DB_PASSWORD=$env:AUTH_DB_PASSWORD
$env:LASTLEG_DB_USERNAME='root'
$env:LASTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_lastleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:FIRSTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_firstleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:WAREHOUSE_SERVICE_URL='http://127.0.0.1:9205'
$env:ORDER_SERVICE_URL='http://127.0.0.1:9204'
$env:FILE_SERVICE_URL='http://127.0.0.1:9206'
$env:DOMESTIC_WAREHOUSE_URL='http://127.0.0.1:9205'
$env:WAREHOUSE_OVERSEAS_SERVICE_URL='http://127.0.0.1:9305'
$env:FIRSTLEG_SERVICE_URL='http://127.0.0.1:9202'
$env:LASTLEG_SERVICE_URL='http://127.0.0.1:9303'
foreach($entry in @(@{Port=9202;Name='firstleg'})) {
$entry.Id=(Get-NetTCPConnection -LocalPort $entry.Port -State Listen | Select-Object -First 1).OwningProcess
$process=Get-CimInstance Win32_Process -Filter "ProcessId=$($entry.Id)"
if(!$process -or $process.CommandLine -notmatch "com\.baiyue\.$($entry.Name)\.") {throw '原服务进程身份不匹配'}
$cp=[regex]::Match($process.CommandLine,'(?:-classpath|-cp)\s+(?:"([^"]+)"|(\S+))')
$classpath=if($cp.Groups[1].Success){$cp.Groups[1].Value}else{$cp.Groups[2].Value}
$main=[regex]::Match($process.CommandLine,'com\.baiyue\.[\w.]+Application').Value
if(!$classpath -or !$main){throw '无法保留原服务启动类路径'}
Stop-Process -Id $entry.Id
$new=Start-Process -FilePath $process.ExecutablePath -ArgumentList "-Dfile.encoding=UTF-8 -Xmx1024m -cp `"$classpath`" $main" -WorkingDirectory $repo -WindowStyle Hidden -PassThru -RedirectStandardOutput "$PSScriptRoot\$($entry.Name)-tabs-runtime.log" -RedirectStandardError "$PSScriptRoot\$($entry.Name)-tabs-runtime.err.log"
"$($entry.Name) PID=$($new.Id)"
}
@@ -0,0 +1,27 @@
$ErrorActionPreference='Stop'
$repo='D:\project\baiyue-firstleg'
. "$repo\scripts\local-env.ps1"
$env:LASTLEG_DB_PASSWORD=$env:AUTH_DB_PASSWORD
$env:LASTLEG_DB_USERNAME='root'
$env:LASTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_lastleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:FIRSTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_firstleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:WAREHOUSE_SERVICE_URL='http://127.0.0.1:9205'
$env:ORDER_SERVICE_URL='http://127.0.0.1:9204'
$env:FILE_SERVICE_URL='http://127.0.0.1:9206'
$env:DOMESTIC_WAREHOUSE_URL='http://127.0.0.1:9205'
$env:WAREHOUSE_OVERSEAS_SERVICE_URL='http://127.0.0.1:9305'
$env:FIRSTLEG_SERVICE_URL='http://127.0.0.1:9202'
$env:LASTLEG_SERVICE_URL='http://127.0.0.1:9303'
foreach($entry in @(@{Port=9303;Name='lastleg'})) {
$entry.Id=(Get-NetTCPConnection -LocalPort $entry.Port -State Listen | Select-Object -First 1).OwningProcess
$process=Get-CimInstance Win32_Process -Filter "ProcessId=$($entry.Id)"
if(!$process -or $process.CommandLine -notmatch "com\.baiyue\.$($entry.Name)\.") {throw '原服务进程身份不匹配'}
$cp=[regex]::Match($process.CommandLine,'(?:-classpath|-cp)\s+(?:"([^"]+)"|(\S+))')
$classpath=if($cp.Groups[1].Success){$cp.Groups[1].Value}else{$cp.Groups[2].Value}
$main=[regex]::Match($process.CommandLine,'com\.baiyue\.[\w.]+Application').Value
if(!$classpath -or !$main){throw '无法保留原服务启动类路径'}
Stop-Process -Id $entry.Id
$new=Start-Process -FilePath $process.ExecutablePath -ArgumentList "-Dfile.encoding=UTF-8 -Xmx1024m -cp `"$classpath`" $main" -WorkingDirectory $repo -WindowStyle Hidden -PassThru -RedirectStandardOutput "$PSScriptRoot\$($entry.Name)-tabs-runtime.log" -RedirectStandardError "$PSScriptRoot\$($entry.Name)-tabs-runtime.err.log"
"$($entry.Name) PID=$($new.Id)"
}
@@ -0,0 +1,27 @@
$ErrorActionPreference='Stop'
$repo='D:\project\baiyue-firstleg'
. "$repo\scripts\local-env.ps1"
$env:LASTLEG_DB_PASSWORD=$env:AUTH_DB_PASSWORD
$env:LASTLEG_DB_USERNAME='root'
$env:LASTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_lastleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:FIRSTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_firstleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:WAREHOUSE_SERVICE_URL='http://127.0.0.1:9205'
$env:ORDER_SERVICE_URL='http://127.0.0.1:9204'
$env:FILE_SERVICE_URL='http://127.0.0.1:9206'
$env:DOMESTIC_WAREHOUSE_URL='http://127.0.0.1:9205'
$env:WAREHOUSE_OVERSEAS_SERVICE_URL='http://127.0.0.1:9305'
$env:FIRSTLEG_SERVICE_URL='http://127.0.0.1:9202'
$env:LASTLEG_SERVICE_URL='http://127.0.0.1:9303'
foreach($entry in @(@{Port=9204;Name='order'})) {
$entry.Id=(Get-NetTCPConnection -LocalPort $entry.Port -State Listen | Select-Object -First 1).OwningProcess
$process=Get-CimInstance Win32_Process -Filter "ProcessId=$($entry.Id)"
if(!$process -or $process.CommandLine -notmatch "com\.baiyue\.$($entry.Name)\.") {throw '原服务进程身份不匹配'}
$cp=[regex]::Match($process.CommandLine,'(?:-classpath|-cp)\s+(?:"([^"]+)"|(\S+))')
$classpath=if($cp.Groups[1].Success){$cp.Groups[1].Value}else{$cp.Groups[2].Value}
$main=[regex]::Match($process.CommandLine,'com\.baiyue\.[\w.]+Application').Value
if(!$classpath -or !$main){throw '无法保留原服务启动类路径'}
Stop-Process -Id $entry.Id
$new=Start-Process -FilePath $process.ExecutablePath -ArgumentList "-Dfile.encoding=UTF-8 -Xmx1024m -cp `"$classpath`" $main" -WorkingDirectory $repo -WindowStyle Hidden -PassThru -RedirectStandardOutput "$PSScriptRoot\$($entry.Name)-tabs-runtime.log" -RedirectStandardError "$PSScriptRoot\$($entry.Name)-tabs-runtime.err.log"
"$($entry.Name) PID=$($new.Id)"
}
@@ -0,0 +1,27 @@
$ErrorActionPreference='Stop'
$repo='D:\project\baiyue-firstleg'
. "$repo\scripts\local-env.ps1"
$env:LASTLEG_DB_PASSWORD=$env:AUTH_DB_PASSWORD
$env:LASTLEG_DB_USERNAME='root'
$env:LASTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_lastleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:FIRSTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_firstleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:WAREHOUSE_SERVICE_URL='http://127.0.0.1:9205'
$env:ORDER_SERVICE_URL='http://127.0.0.1:9204'
$env:FILE_SERVICE_URL='http://127.0.0.1:9206'
$env:DOMESTIC_WAREHOUSE_URL='http://127.0.0.1:9205'
$env:WAREHOUSE_OVERSEAS_SERVICE_URL='http://127.0.0.1:9305'
$env:FIRSTLEG_SERVICE_URL='http://127.0.0.1:9202'
$env:LASTLEG_SERVICE_URL='http://127.0.0.1:9303'
foreach($entry in @(@{Port=9202;Name='firstleg'},@{Port=9303;Name='lastleg'},@{Port=9204;Name='order'})) {
$entry.Id=(Get-NetTCPConnection -LocalPort $entry.Port -State Listen | Select-Object -First 1).OwningProcess
$process=Get-CimInstance Win32_Process -Filter "ProcessId=$($entry.Id)"
if(!$process -or $process.CommandLine -notmatch "com\.baiyue\.$($entry.Name)\.") {throw '原服务进程身份不匹配'}
$cp=[regex]::Match($process.CommandLine,'(?:-classpath|-cp)\s+(?:"([^"]+)"|(\S+))')
$classpath=if($cp.Groups[1].Success){$cp.Groups[1].Value}else{$cp.Groups[2].Value}
$main=[regex]::Match($process.CommandLine,'com\.baiyue\.[\w.]+Application').Value
if(!$classpath -or !$main){throw '无法保留原服务启动类路径'}
Stop-Process -Id $entry.Id
$new=Start-Process -FilePath $process.ExecutablePath -ArgumentList "-Dfile.encoding=UTF-8 -Xmx1024m -cp `"$classpath`" $main" -WorkingDirectory $repo -WindowStyle Hidden -PassThru -RedirectStandardOutput "$PSScriptRoot\$($entry.Name)-tabs-runtime.log" -RedirectStandardError "$PSScriptRoot\$($entry.Name)-tabs-runtime.err.log"
"$($entry.Name) PID=$($new.Id)"
}
@@ -0,0 +1,28 @@
$ErrorActionPreference='Stop'
$repo='D:\project\baiyue-firstleg'
. "$repo\scripts\local-env.ps1"
$env:LASTLEG_DB_PASSWORD=$env:AUTH_DB_PASSWORD
$env:LASTLEG_DB_USERNAME='root'
$env:LASTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_lastleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:FIRSTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_firstleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:WAREHOUSE_SERVICE_URL='http://127.0.0.1:9205'
$env:ORDER_SERVICE_URL='http://127.0.0.1:9204'
$env:FILE_SERVICE_URL='http://127.0.0.1:9206'
$env:DOMESTIC_WAREHOUSE_URL='http://127.0.0.1:9205'
$env:WAREHOUSE_OVERSEAS_SERVICE_URL='http://127.0.0.1:9305'
$env:FIRSTLEG_SERVICE_URL='http://127.0.0.1:9202'
$env:LASTLEG_SERVICE_URL='http://127.0.0.1:9303'
foreach($entry in @(@{Port=9205;Name='warehouse'})) {
$entry.Id=(Get-NetTCPConnection -LocalPort $entry.Port -State Listen | Select-Object -First 1).OwningProcess
$process=Get-CimInstance Win32_Process -Filter "ProcessId=$($entry.Id)"
if(!$process -or $process.CommandLine -notmatch "com\.baiyue\.$($entry.Name)\.") {throw '原服务进程身份不匹配'}
$cp=[regex]::Match($process.CommandLine,'(?:-classpath|-cp)\s+(?:"([^"]+)"|(\S+))')
$classpath=if($cp.Groups[1].Success){$cp.Groups[1].Value}else{$cp.Groups[2].Value}
$main=[regex]::Match($process.CommandLine,'com\.baiyue\.[\w.]+Application').Value
if(!$classpath -or !$main){throw '无法保留原服务启动类路径'}
Stop-Process -Id $entry.Id
$new=Start-Process -FilePath $process.ExecutablePath -ArgumentList "-Dfile.encoding=UTF-8 -Xmx1024m -cp `"$classpath`" $main" -WorkingDirectory $repo -WindowStyle Hidden -PassThru -RedirectStandardOutput "$PSScriptRoot\$($entry.Name)-tabs-runtime.log" -RedirectStandardError "$PSScriptRoot\$($entry.Name)-tabs-runtime.err.log"
"$($entry.Name) PID=$($new.Id)"
}
+25
View File
@@ -0,0 +1,25 @@
$ErrorActionPreference='Stop'
$repo='D:\project\baiyue-firstleg'
. "$repo\scripts\local-env.ps1"
$env:LASTLEG_DB_PASSWORD=$env:AUTH_DB_PASSWORD
$env:LASTLEG_DB_USERNAME='root'
$env:LASTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_lastleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:FIRSTLEG_DB_URL='jdbc:mysql://127.0.0.1:3306/baiyue_firstleg?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true'
$env:WAREHOUSE_SERVICE_URL='http://127.0.0.1:9205'
$env:ORDER_SERVICE_URL='http://127.0.0.1:9204'
$env:FILE_SERVICE_URL='http://127.0.0.1:9206'
$env:DOMESTIC_WAREHOUSE_URL='http://127.0.0.1:9205'
$env:WAREHOUSE_OVERSEAS_SERVICE_URL='http://127.0.0.1:9305'
$env:FIRSTLEG_SERVICE_URL='http://127.0.0.1:9202'
$env:LASTLEG_SERVICE_URL='http://127.0.0.1:9303'
foreach($entry in @(@{Id=73832;Name='firstleg'},@{Id=63968;Name='lastleg'})) {
$process=Get-CimInstance Win32_Process -Filter "ProcessId=$($entry.Id)"
if(!$process -or $process.CommandLine -notmatch "com\.baiyue\.$($entry.Name)\.") {throw '原服务进程身份不匹配'}
$cp=[regex]::Match($process.CommandLine,'(?:-classpath|-cp)\s+(?:"([^"]+)"|(\S+))')
$classpath=if($cp.Groups[1].Success){$cp.Groups[1].Value}else{$cp.Groups[2].Value}
$main=[regex]::Match($process.CommandLine,'com\.baiyue\.[\w.]+Application').Value
if(!$classpath -or !$main){throw '无法保留原服务启动类路径'}
Stop-Process -Id $entry.Id
$new=Start-Process -FilePath $process.ExecutablePath -ArgumentList "-Dfile.encoding=UTF-8 -Xmx1024m -cp `"$classpath`" $main" -WorkingDirectory $repo -WindowStyle Hidden -PassThru -RedirectStandardOutput "$PSScriptRoot\$($entry.Name)-runtime.log" -RedirectStandardError "$PSScriptRoot\$($entry.Name)-runtime.err.log"
"$($entry.Name) PID=$($new.Id)"
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,20 @@
[
{
"db": "baiyue_firstleg",
"baselineTables": 131,
"missingColumns": [],
"missingIndexes": [],
"appliedIndexes": [],
"blockedIndexes": []
},
{
"db": "baiyue_lastleg",
"baselineTables": 218,
"missingColumns": [],
"missingIndexes": [
"ll_inbound_plan.uk_ll_inbound_plan_source_order"
],
"appliedIndexes": [],
"blockedIndexes": []
}
]
+12
View File
@@ -0,0 +1,12 @@
import fs from 'node:fs';
const dir=new URL('./',import.meta.url);
function parse(file){let db='';const result=new Map();for(const m of fs.readFileSync(new URL(file,dir),'utf8').matchAll(/USE `(\w+)`;|CREATE TABLE `(\w+)` \(([\s\S]*?)\n\) ENGINE=[^;]+;/g)){if(m[1])db=m[1];else result.set(db+'.'+m[2],{db,name:m[2],sql:m[0],defs:m[3].split(/\r?\n/).map(s=>s.trim().replace(/,$/,''))});}return result;}
const before=parse('schema-before.sql'),after=parse('schema-after.sql'),report={},ddl=['-- 本次本机结构修复的实际增量,仅用于审阅与原始快照对照。已执行,禁止在当前库重复执行。','SET NAMES utf8mb4;'];
for(const [key,t] of after){const r=report[t.db]??={createdTables:[],addedColumns:[],addedIndexes:[]};const old=before.get(key);ddl.push('USE `'+t.db+'`;');
if(!old){r.createdTables.push(t.name);ddl.push(t.sql);continue;}
const oldCols=new Set(old.defs.map(d=>d.match(/^`(\w+)`/)?.[1]).filter(Boolean));
const oldKeys=new Set(old.defs.map(d=>d.match(/^(?:UNIQUE )?KEY `(\w+)`/)?.[1]).filter(Boolean));
for(const d of t.defs){const c=d.match(/^`(\w+)`/),i=d.match(/^(?:UNIQUE )?KEY `(\w+)`/);if(c&&!oldCols.has(c[1])){r.addedColumns.push(t.name+'.'+c[1]);ddl.push('ALTER TABLE `'+t.name+'` ADD COLUMN '+d+';');}else if(i&&!oldKeys.has(i[1])){r.addedIndexes.push(t.name+'.'+i[1]);ddl.push('ALTER TABLE `'+t.name+'` ADD '+d+';');}}
}
fs.writeFileSync(new URL('actual-changes.json',dir),JSON.stringify(report,null,2));fs.writeFileSync(new URL('actual-incremental-review.sql',dir),ddl.join('\n\n'));
for(const [db,r] of Object.entries(report))console.log(db,{tables:r.createdTables.length,columns:r.addedColumns.length,indexes:r.addedIndexes.length});
@@ -0,0 +1,116 @@
[
{
"status": "PENDING_REVIEW",
"count": 127,
"total": 127,
"passed": true
},
{
"status": "WAIT_MEASURE",
"count": 195,
"total": 195,
"passed": true
},
{
"status": "WAIT_WEIGHT_CONFIRM",
"count": 125,
"total": 125,
"passed": true
},
{
"status": "WEIGHT_CONFIRMED",
"count": 1,
"total": 1,
"passed": true
},
{
"status": "WAIT_CUSTOMS_DOCS",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "WAIT_PALLETIZE",
"count": 6,
"total": 6,
"passed": true
},
{
"status": "WAIT_SPLIT",
"count": 126,
"total": 126,
"passed": true
},
{
"status": "LOADING",
"count": 9,
"total": 9,
"passed": true
},
{
"status": "LOADED",
"count": 73,
"total": 73,
"passed": true
},
{
"status": "EXPORT_CUSTOMS",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "SAILING_CLEARANCE",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "WAIT_UNLOAD",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "WAIT_DISPATCH",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "OUTBOUND_DOCUMENT",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "DELIVERING",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "SIGNED",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "DELIVERED",
"count": 0,
"total": 0,
"passed": true
},
{
"status": "COMPLETED",
"count": 2,
"total": 2,
"passed": true
},
{
"status": "MEASUREMENT_REVIEW",
"count": 120,
"total": 120,
"passed": true
}
]
+537
View File
@@ -0,0 +1,537 @@
[
{
"path": "/api/auth/login",
"http": 200,
"code": "200",
"requestId": "5a80dd52-e63b-4750-9176-2d6d97a5e3c8, dddd7757-a5d2-4185-839b-04b34ab2837c",
"passed": true
},
{
"path": "/api/platform/v1/orders/status-counts",
"http": 200,
"code": "200",
"requestId": "1da4d48a-e0bb-41a3-ae43-1ddf12d5a14b, 741bf672-5db1-4914-81d0-d0a46745f67c",
"passed": true,
"counts": {
"PENDING_REVIEW": 127,
"WAIT_MEASURE": 195,
"WAIT_PALLETIZE": 6,
"WAIT_SPLIT": 127,
"LOADING": 8,
"LOADED": 74,
"DELIVERED": 0,
"COMPLETED": 2,
"WAIT_WEIGHT_CONFIRM": 124,
"WEIGHT_CONFIRMED": 1,
"WAIT_CUSTOMS_DOCS": 0,
"EXPORT_CUSTOMS": 55,
"SAILING_CLEARANCE": 0,
"WAIT_UNLOAD": 1,
"WAIT_DISPATCH": 1,
"OUTBOUND_DOCUMENT": 0,
"DELIVERING": 0,
"SIGNED": 0,
"MEASUREMENT_REVIEW": 120
}
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=PENDING_REVIEW",
"http": 200,
"code": "200",
"requestId": "3bbf7448-f7e1-40a3-bea6-8e7007bb5c23, 10fd5748-ea6f-413f-9d96-f67cc930b664",
"passed": true,
"total": "127",
"records": [
{
"orderId": "2112105953787518978",
"tenantId": "2112105501490544641",
"inboundId": "2112105957231161346",
"mainStatus": "PENDING_REVIEW"
},
{
"orderId": "2112105886309556225",
"tenantId": "2112105195373461506",
"inboundId": "2112105890017439745",
"mainStatus": "PENDING_REVIEW"
},
{
"orderId": "2112105822484832258",
"tenantId": "2112105195373461506",
"inboundId": "2112105825983000577",
"mainStatus": "PENDING_REVIEW"
},
{
"orderId": "2112105768302813186",
"tenantId": "2112105195373461506",
"inboundId": "2112105772081999873",
"mainStatus": "PENDING_REVIEW"
},
{
"orderId": "2112105682319581185",
"tenantId": "2112105501490544641",
"inboundId": "2112105687122178049",
"mainStatus": "PENDING_REVIEW"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_MEASURE",
"http": 200,
"code": "200",
"requestId": "71a6b016-4d23-448d-aa30-ed7c954e29ee, 60c5e10b-faf1-4e61-b16f-35306513a7f1",
"passed": true,
"total": "195",
"records": [
{
"orderId": "2112102981498183681",
"tenantId": "2112102958765047809",
"inboundId": "2112103003577118721",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2098325342631428097",
"tenantId": "2098324852501774338",
"inboundId": "2098325343935848449",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2098325190034259969",
"tenantId": "2098324852501774338",
"inboundId": "2098325191338680322",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2098325037621641217",
"tenantId": "2098324852501774338",
"inboundId": "2098325038921867265",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2098324887905959938",
"tenantId": "2098324852501774338",
"inboundId": "2098324891550801921",
"mainStatus": "WAIT_MEASURE"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_WEIGHT_CONFIRM",
"http": 200,
"code": "200",
"requestId": "ac639d03-1d4f-4140-bd19-a50e15e211ab, 8d6dfa2b-85c5-4cd8-bb8a-7bd112d2fe0d",
"passed": true,
"total": "124",
"records": [
{
"orderId": "2085355345216114689",
"tenantId": "2085308606829346818",
"inboundId": "2085355347941904385",
"mainStatus": null
},
{
"orderId": "2085355345975283713",
"tenantId": "2085308606829346818",
"inboundId": "2085355347992236034",
"mainStatus": null
},
{
"orderId": "2085355346734452738",
"tenantId": "2085308606829346818",
"inboundId": "2085355360826806273",
"mainStatus": null
},
{
"orderId": "2085355347493621762",
"tenantId": "2085308606829346818",
"inboundId": "2085355360881332226",
"mainStatus": null
},
{
"orderId": "2085355348282150913",
"tenantId": "2085308606829346818",
"inboundId": "2085355360931663873",
"mainStatus": null
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WEIGHT_CONFIRMED",
"http": 200,
"code": "200",
"requestId": "c47772c4-8188-47d5-9a8f-6e9aaabb2d7e, 52eabd98-7666-47da-b8e0-3447cdace665",
"passed": true,
"total": "1",
"records": [
{
"orderId": "2085341741574098946",
"tenantId": "2085308606829346818",
"inboundId": "2085341749429522434",
"mainStatus": null
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_CUSTOMS_DOCS",
"http": 200,
"code": "200",
"requestId": "febd1b16-fdea-4c4b-8cb8-69aecb5e1ff6, 82627b67-04a6-47b7-b168-e653d4eeb5e3",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_PALLETIZE",
"http": 200,
"code": "200",
"requestId": "8f84977d-97f1-4acf-b9e5-0e062a901490, 03707bbf-cb42-4b34-ba5f-a924f9bae410",
"passed": true,
"total": "6",
"records": [
{
"orderId": "2112105882580819970",
"tenantId": "2112105195373461506",
"inboundId": "2112105899853082626",
"mainStatus": "WAIT_PALLETIZE"
},
{
"orderId": "2112105818881925122",
"tenantId": "2112105195373461506",
"inboundId": "2112105836158382082",
"mainStatus": "WAIT_PALLETIZE"
},
{
"orderId": "2112105764741849089",
"tenantId": "2112105195373461506",
"inboundId": "2112105781263331330",
"mainStatus": "WAIT_PALLETIZE"
},
{
"orderId": "2112104925457424385",
"tenantId": "2112104631512203266",
"inboundId": "2112104942167650305",
"mainStatus": "WAIT_PALLETIZE"
},
{
"orderId": "2112104871636115457",
"tenantId": "2112104551203864578",
"inboundId": "2112104887486509058",
"mainStatus": "WAIT_PALLETIZE"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_SPLIT",
"http": 200,
"code": "200",
"requestId": "6fed641c-6076-41ca-b4e4-9567d1a843f5, 7199357b-7616-43c9-922f-74e2fa900477",
"passed": true,
"total": "127",
"records": [
{
"orderId": "2112374338811326466",
"tenantId": "2092814835845664769",
"inboundId": "2112376564246077441",
"mainStatus": "WAIT_SPLIT"
},
{
"orderId": "2112105949454802945",
"tenantId": "2112105501490544641",
"inboundId": "2112105974222286850",
"mainStatus": "WAIT_SPLIT"
},
{
"orderId": "2112105677974282242",
"tenantId": "2112105501490544641",
"inboundId": "2112105696567750658",
"mainStatus": "WAIT_SPLIT"
},
{
"orderId": "2112105550538743809",
"tenantId": "2112105501490544641",
"inboundId": "2112105615210835970",
"mainStatus": "WAIT_SPLIT"
},
{
"orderId": "2112105269298077697",
"tenantId": "2112105195373461506",
"inboundId": "2112105371026845697",
"mainStatus": "WAIT_SPLIT"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=LOADING",
"http": 200,
"code": "200",
"requestId": "acabdb6d-f822-46e4-92ae-30bc8efa7537, 8d45744a-682e-41a9-b738-9ade63926b28",
"passed": true,
"total": "8",
"records": [
{
"orderId": "2092816910277038081",
"tenantId": "2092816814294667266",
"inboundId": "2092816913754202115",
"mainStatus": "LOADING"
},
{
"orderId": "2092816871253233665",
"tenantId": "2092816814294667266",
"inboundId": "2092816875699281923",
"mainStatus": "LOADING"
},
{
"orderId": "2092816836365012994",
"tenantId": "2092816814294667266",
"inboundId": "2092816850256633858",
"mainStatus": "LOADING"
},
{
"orderId": "2091000814000001101",
"tenantId": "10001",
"inboundId": "2091000814000001301",
"mainStatus": "LOADING"
},
{
"orderId": "2091000814000000101",
"tenantId": "10001",
"inboundId": "2091000814000000301",
"mainStatus": "LOADING"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=LOADED",
"http": 200,
"code": "200",
"requestId": "0e6536aa-a82a-4c1b-a41c-7d7520511eeb, 03629346-096b-465c-956f-c9326328dcee",
"passed": true,
"total": "74",
"records": [
{
"orderId": "2093269574496440322",
"tenantId": "2093269089353961474",
"inboundId": "2093269587792433154",
"mainStatus": "LOADED"
},
{
"orderId": "2093269527184691202",
"tenantId": "2093269089353961474",
"inboundId": "2093269537020383234",
"mainStatus": "LOADED"
},
{
"orderId": "2093269460814024706",
"tenantId": "2093269089353961474",
"inboundId": "2093269473657032707",
"mainStatus": "LOADED"
},
{
"orderId": "2093269413967843329",
"tenantId": "2093269089353961474",
"inboundId": "2093269422700433411",
"mainStatus": "LOADED"
},
{
"orderId": "2093269346426966017",
"tenantId": "2093269089353961474",
"inboundId": "2093269359261585410",
"mainStatus": "LOADED"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=EXPORT_CUSTOMS",
"http": 200,
"code": "200",
"requestId": "b0568387-1d75-4d6e-8755-8fb49623a224, ba4bf212-2ea9-4909-b816-f1650265211a",
"passed": true,
"total": "55",
"records": [
{
"orderId": "2086081433932726274",
"tenantId": "10001",
"inboundId": "2086081437650956290",
"mainStatus": null
},
{
"orderId": "2086085225151528961",
"tenantId": "10001",
"inboundId": "2086085239259049985",
"mainStatus": null
},
{
"orderId": "2086085487601713154",
"tenantId": "10001",
"inboundId": "2086085491298971650",
"mainStatus": null
},
{
"orderId": "2086086464165707778",
"tenantId": "10001",
"inboundId": "2086086473193926658",
"mainStatus": null
},
{
"orderId": "2086088193535967234",
"tenantId": "10001",
"inboundId": "2086088197887537154",
"mainStatus": null
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=SAILING_CLEARANCE",
"http": 200,
"code": "200",
"requestId": "6de0f6f1-db74-43bd-a2df-1356dd2621dc, 836088e2-6974-4d24-86b5-3381f988cee4",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_UNLOAD",
"http": 200,
"code": "200",
"requestId": "4134d8d3-dd4d-4fd6-8950-83e3697d3f74, aae63083-913c-4453-82d3-7f8c7c97ef3f",
"passed": true,
"total": "1",
"records": [
{
"orderId": "2092814878690398210",
"tenantId": "2092814835845664769",
"inboundId": "2092814880129130499",
"mainStatus": "LOADED"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_DISPATCH",
"http": 200,
"code": "200",
"requestId": "cbb986f8-a8db-4057-a4ce-f81973b9f167, bf7e93c6-dfce-435f-a1fa-ee8a5801defd",
"passed": true,
"total": "1",
"records": [
{
"orderId": "2092814878690398210",
"tenantId": "2092814835845664769",
"inboundId": "2092814880129130499",
"mainStatus": "LOADED"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=OUTBOUND_DOCUMENT",
"http": 200,
"code": "200",
"requestId": "95e78822-1d56-4699-b90b-87322f972067, db5f9b65-6f7b-4cf6-a875-1c90e45d8f79",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=DELIVERING",
"http": 200,
"code": "200",
"requestId": "a98b495a-db94-471e-bc59-a3aeba7d2997, f409423a-5e9f-4f46-b2ec-203f987aa39a",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=SIGNED",
"http": 200,
"code": "200",
"requestId": "06260f7b-84cd-49f4-a03c-fa699a4e1a86, 3c3879e7-869d-4e9b-a725-868a466f8fb2",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=DELIVERED",
"http": 200,
"code": "200",
"requestId": "c6451658-5d84-4fa6-b2e5-2fee098c50c1, 05eb6078-71c4-4e98-b205-c643d69647b9",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=COMPLETED",
"http": 200,
"code": "200",
"requestId": "d46153fb-bfdd-4493-b789-a3a5261eed6d, 2b71ece4-b561-47f6-8978-68f71c9f62b3",
"passed": true,
"total": "2",
"records": [
{
"orderId": "2084515377635758081",
"tenantId": "2084513933705150465",
"inboundId": "2085623586303365121",
"mainStatus": "COMPLETED"
},
{
"orderId": "2084210113483173890",
"tenantId": "10001",
"inboundId": "2085623585678413826",
"mainStatus": "COMPLETED"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=MEASUREMENT_REVIEW",
"http": 200,
"code": "200",
"requestId": "16fe4770-d066-42f0-b9a0-3fb9e5ab7403, b51983ce-cf48-42b3-b003-0156ca953e44",
"passed": true,
"total": "120",
"records": [
{
"orderId": "2085355294326624258",
"tenantId": "2085308606829346818",
"inboundId": "2085355307252961281",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2085355295115153410",
"tenantId": "2085308606829346818",
"inboundId": "2085355307303292930",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2085355295895293953",
"tenantId": "2085308606829346818",
"inboundId": "2085355307357818882",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2085355296650268673",
"tenantId": "2085308606829346818",
"inboundId": "2085355307408150530",
"mainStatus": "WAIT_MEASURE"
},
{
"orderId": "2085355297438797826",
"tenantId": "2085308606829346818",
"inboundId": "2085355307462676481",
"mainStatus": "WAIT_MEASURE"
}
]
},
{
"path": "9202/actuator/health",
"http": 200,
"body": {
"status": "UP"
},
"passed": true
},
{
"path": "9303/actuator/health",
"http": 200,
"body": {
"status": "UP"
},
"passed": true
}
]
+17
View File
@@ -0,0 +1,17 @@
import fs from 'node:fs';
const base=process.env.ADMIN_TEST_GATEWAY;
if(!base||!['127.0.0.1','localhost'].includes(new URL(base).hostname))throw new Error('仅允许本机');
let token='';const checks=[];
async function call(path,body) {
const r=await fetch(base+path,{method:body?'POST':'GET',headers:{...(token?{Authorization:'Bearer '+token}:{}),...(body?{'Content-Type':'application/json'}:{})},body:body?JSON.stringify(body):undefined,signal:AbortSignal.timeout(45000)});
const value=await r.json().catch(()=>null);
checks.push({path,http:r.status,code:value?.code,message:String(value?.code)==='200'?undefined:value?.message,requestId:r.headers.get('x-request-id'),passed:r.status===200&&String(value?.code)==='200',total:value?.data?.total,counts:value?.data?.counts,records:value?.data?.records?.map(x=>({orderId:x.orderId,tenantId:x.tenantId,inboundId:x.inboundId,mainStatus:x.mainStatus}))});
fs.writeFileSync(new URL('tab-smoke.json',import.meta.url),JSON.stringify(checks,null,2));
return value;
}
const login=await call('/api/auth/login',{loginId:process.env.ADMIN_TEST_USERNAME,password:process.env.ADMIN_TEST_PASSWORD});
if(!login?.data?.accessToken)throw new Error('本地登录失败');token=login.data.accessToken;
for(const path of ['/api/platform/v1/orders/status-counts',...['PENDING_REVIEW','WAIT_MEASURE','WAIT_WEIGHT_CONFIRM','WEIGHT_CONFIRMED','WAIT_CUSTOMS_DOCS','WAIT_PALLETIZE','WAIT_SPLIT','LOADING','LOADED','EXPORT_CUSTOMS','SAILING_CLEARANCE','WAIT_UNLOAD','WAIT_DISPATCH','OUTBOUND_DOCUMENT','DELIVERING','SIGNED','DELIVERED','COMPLETED','MEASUREMENT_REVIEW'].map(s=>'/api/platform/v1/orders?page=1&size=5&mainStatus='+s)])await call(path);
for(const port of [9202,9303]){const r=await fetch(`http://127.0.0.1:${port}/actuator/health`);checks.push({path:`${port}/actuator/health`,http:r.status,body:await r.json(),passed:r.ok});}
fs.writeFileSync(new URL('tab-smoke.json',import.meta.url),JSON.stringify(checks,null,2));console.log(JSON.stringify(checks,null,2));
@@ -0,0 +1,67 @@
{
"at": "2026-10-20T03:20:01.182Z",
"checks": 23,
"failed": [],
"mismatches": [],
"tail": [
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=SAILING_CLEARANCE",
"http": 200,
"code": "200",
"requestId": "6de0f6f1-db74-43bd-a2df-1356dd2621dc, 836088e2-6974-4d24-86b5-3381f988cee4",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_UNLOAD",
"http": 200,
"code": "200",
"requestId": "4134d8d3-dd4d-4fd6-8950-83e3697d3f74, aae63083-913c-4453-82d3-7f8c7c97ef3f",
"passed": true,
"total": "1",
"records": [
{
"orderId": "2092814878690398210",
"tenantId": "2092814835845664769",
"inboundId": "2092814880129130499",
"mainStatus": "LOADED"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=WAIT_DISPATCH",
"http": 200,
"code": "200",
"requestId": "cbb986f8-a8db-4057-a4ce-f81973b9f167, bf7e93c6-dfce-435f-a1fa-ee8a5801defd",
"passed": true,
"total": "1",
"records": [
{
"orderId": "2092814878690398210",
"tenantId": "2092814835845664769",
"inboundId": "2092814880129130499",
"mainStatus": "LOADED"
}
]
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=DELIVERING",
"http": 200,
"code": "200",
"requestId": "a98b495a-db94-471e-bc59-a3aeba7d2997, f409423a-5e9f-4f46-b2ec-203f987aa39a",
"passed": true,
"total": "0",
"records": []
},
{
"path": "/api/platform/v1/orders?page=1&size=5&mainStatus=SIGNED",
"http": 200,
"code": "200",
"requestId": "06260f7b-84cd-49f4-a03c-fa699a4e1a86, 3c3879e7-869d-4e9b-a725-868a466f8fb2",
"passed": true,
"total": "0",
"records": []
}
]
}
@@ -0,0 +1,189 @@
[
{
"path": "/api/platform/v1/iam/users/domestic-pda-operators?warehouseId=193000000000200001",
"code": "200",
"message": "success",
"data": [
{
"userId": "1790048228520288513",
"displayName": "张三"
},
{
"userId": "1790048228520288516",
"displayName": "李四"
}
],
"requestId": null,
"traceId": null,
"timestamp": "2026-10-20T02:33:57.852782300Z"
},
{
"path": "/api/platform/v1/first-leg/pda-loading/tasks/2102273311474982914?warehouseId=193000000000200001",
"code": "200",
"message": "success",
"data": {
"id": "2102273311474982914",
"loadingPlanId": "2092814929479311362",
"containerBookingId": "2092814929307344898",
"inboundId": "2092814880129130499",
"inboundVersion": 6,
"loadingVersion": 6,
"cabinetNo": "CAB-260827-0019",
"currentContainerNo": "CSQU3054383",
"sourceType": "SIMULATION",
"recordStatus": "ACTIVE",
"mergedIntoContainerBookingId": null,
"taskStatus": "LOADING",
"workflowStatus": "IN_PROGRESS",
"version": 0,
"assignment": {
"assigneeId": "1790048228520288513",
"assigneeName": "pda_zhangsan",
"assignedBy": "1790048228520288513",
"assignedByName": "pda_zhangsan",
"assignmentType": "CLAIMED",
"version": 0
},
"review": null,
"completionCommand": null,
"items": [
{
"id": "2102273311542091778",
"loadingPlanItemId": "2092814929680637954",
"tenantId": "2092814835845664769",
"inboundId": "2092814880129130499",
"inboundDetailId": "2092814878690398211",
"unitType": "PACKAGE",
"palletId": null,
"palletNo": null,
"indivisible": false,
"orderNo": "FL2092814878690398210",
"inboundCode": "NYEXX2608270051",
"cargoName": "SMALL 测试产品",
"boxCodes": [
"NYEXX2608270051#4-1"
],
"inventoryResources": [
{
"blockId": "2092814880129130499",
"slotNo": 1,
"reservationId": "2092814900999888899",
"weightResultId": "2092814900605722626",
"palletSequence": 1,
"palletId": "2092814900211359746",
"locationId": "193000000000200202",
"locationCode": "A0",
"sharedOverflow": true,
"slotStatus": "BOUND",
"availablePackageCount": 4
}
],
"plannedPackageCount": 1,
"pickedPackageCount": 0,
"itemStatus": "PENDING",
"version": 0
}
]
},
"requestId": null,
"traceId": null,
"timestamp": "2026-10-20T02:33:57.981150700Z"
},
{
"path": "/api/platform/v1/containers/2092814929307344898/overview",
"code": "200",
"message": "success",
"data": {
"container": {
"id": "2092814929307344898",
"cabinetNo": "CAB-260827-0019",
"containerNo": "CSQU3054383",
"status": "LOADING",
"warehouseId": "193000000000200001",
"warehouseName": "义乌仓",
"voyageNo": "P3V-32153799-AA35DF75",
"vesselName": "P3VESSEL-32153799-AA35DF75",
"billOfLadingNo": "P3BL-32153799-AA35DF75",
"shippingCompanyId": "2092808875341127681",
"shippingCompanyName": "MATSON 开发联调船司",
"departurePortCode": "CNSZX",
"departurePortName": "深圳",
"destinationPortCode": "USLAX",
"destinationPortName": "洛杉矶",
"estimatedSailingAt": "2026-09-01T08:00:00",
"actualSailingAt": null,
"estimatedPortArrivalAt": "2026-09-20T08:00:00",
"actualPortArrivalAt": null,
"estimatedWarehouseArrivalAt": null,
"actualWarehouseArrivalAt": null,
"unloadingCompletedAt": null,
"unloadingPhotoUploadedAt": null,
"estimatedEmptyReportedAt": null,
"actualEmptyReportedAt": null,
"emptyReportSourceVersion": null,
"pickupCode": null,
"pickupCodeUpdatedBy": null,
"pickupCodeUpdatedByName": null,
"pickupCodeUpdatedAt": null,
"version": 2
},
"loadingPlanId": "2092814929479311362",
"pda": {
"taskId": "2102273311474982914",
"loadingPlanId": "2092814929479311362",
"containerBookingId": "2092814929307344898",
"taskStatus": "LOADING",
"workflowStatus": "IN_PROGRESS",
"taskVersion": 0,
"itemCount": 1,
"completedItemCount": 0,
"unresolvedItemCount": 1,
"photoCounts": [],
"photos": [],
"exceptionReasons": []
},
"documents": [],
"exception": {
"active": false,
"reason": null,
"markedBy": null,
"markedByName": null,
"markedAt": null
},
"exceptionHistory": [],
"timeline": [
{
"eventType": "TRANSPORT_UPDATE",
"detail": "按业务测试要求绑定已通过 ISO 6346 校验的集装箱号,暂不推送 PDA",
"operatorId": "9000000001",
"operatorName": "platform_custom_admin",
"occurredAt": "2026-09-22T11:32:55.69"
},
{
"eventType": "PDA_CLAIM",
"detail": "claim-1790048228520288513-2102273311474982914-2092814929479311362-2092814929307344898",
"operatorId": "1790048228520288513",
"operatorName": "pda_zhangsan",
"occurredAt": "2026-09-22T14:27:48.707"
}
]
},
"requestId": null,
"traceId": null,
"timestamp": "2026-10-20T02:33:58.064086600Z"
},
{
"path": "/api/platform/v1/container-shipping-nodes/2092814929307344898",
"code": "200",
"message": "success",
"data": {
"containerBookingId": "2092814929307344898",
"currentNode": null,
"currentNodeAt": null,
"nodes": []
},
"requestId": null,
"traceId": null,
"timestamp": "2026-10-20T02:33:58.128845700Z"
}
]
@@ -0,0 +1,16 @@
import fs from 'node:fs';
const base=process.env.ADMIN_TEST_GATEWAY;
if(!base || !['127.0.0.1','localhost'].includes(new URL(base).hostname))throw Error('仅允许本机');
let token='';
const login=await fetch(base+'/api/auth/login',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({loginId:process.env.ADMIN_TEST_USERNAME,password:process.env.ADMIN_TEST_PASSWORD})}).then(r=>r.json());
if(String(login.code)!=='200'||!login.data?.accessToken)throw Error('登录失败');
token=login.data.accessToken;
const paths=[
'/api/platform/v1/iam/users/domestic-pda-operators?warehouseId=193000000000200001',
'/api/platform/v1/first-leg/pda-loading/tasks/2102273311474982914?warehouseId=193000000000200001',
'/api/platform/v1/containers/2092814929307344898/overview',
'/api/platform/v1/container-shipping-nodes/2092814929307344898',
];
const out=[];
for(const path of paths){const r=await fetch(base+path,{headers:{Authorization:'Bearer '+token}}); const v=await r.json(); out.push({path,...v});console.log(path,v.code,String(v.message||''),v.data?Object.keys(v.data):'');}
fs.writeFileSync(new URL('tail-flow-inspect.json',import.meta.url),JSON.stringify(out,null,2));
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,2 @@
id warehouse_code internal_code version
193000000000000244 XLX1 NULL 0
1 id warehouse_code internal_code version
2 193000000000000244 XLX1 NULL 0
+84
View File
@@ -0,0 +1,84 @@
import fs from 'node:fs';
const base=process.env.ADMIN_TEST_GATEWAY;
if(!base||!['127.0.0.1','localhost'].includes(new URL(base).hostname))throw Error('仅允许本机');
const marker='LOCAL-TAIL-20261020';
const file=new URL('tail-flow-state.json',import.meta.url);
const state=fs.existsSync(file)?JSON.parse(fs.readFileSync(file,'utf8')):{marker,environment:'LOCAL',photoEvidence:'SYNTHETIC_TEST_PNG',checks:[],taskId:'2102273311474982914',containerId:'2092814929307344898',inboundId:'2092814880129130499',orderId:'2092814878690398210',warehouseId:'193000000000200001'};
const save=()=>fs.writeFileSync(file,JSON.stringify(state,null,2));
async function api(token,method,path,body,key){
const form=body instanceof FormData;
const r=await fetch(base+path,{method,headers:{...(token?{Authorization:'Bearer '+token}:{}),...(!form&&body!==undefined?{'Content-Type':'application/json'}:{}),...(key?{'Idempotency-Key':key}:{})},body:body===undefined?undefined:form?body:JSON.stringify(body),signal:AbortSignal.timeout(60000)});
const v=await r.json();
if(!path.includes('/auth/')){state.checks.push({method,path,http:r.status,code:v.code,message:String(v.code)==='200'?undefined:v.message});save();console.log(method,path,v.code,String(v.code)==='200'?'':v.message);}
if(!r.ok||String(v.code)!=='200')throw Error(`${method} ${path}: ${v.code} ${v.message}`);
return v.data;
}
const admin=(await api('','POST','/api/auth/login',{loginId:process.env.ADMIN_TEST_USERNAME,password:process.env.ADMIN_TEST_PASSWORD})).accessToken;
const root='/api/platform/v1/first-leg/pda-loading/tasks/'+state.taskId;
const task=()=>api(admin,'GET',root+'?warehouseId='+state.warehouseId);
const action=process.argv[2]||'inspect';
try {
if(action==='gate'){
for(const suffix of ['?containerBookingId='+state.containerId,'/'+state.containerId+'/gate']){
console.log(JSON.stringify(await api(admin,'GET','/api/platform/v1/first-leg/outbound-dispatches'+suffix)));
}
}
if(action==='verify'){
const doc=await api(admin,'GET','/api/platform/v1/containers/'+state.containerId+'/clearance');
const rows={};
for(const status of ['SAILING_CLEARANCE','WAIT_UNLOAD','WAIT_DISPATCH']){
const page=await api(admin,'GET','/api/platform/v1/orders?page=1&size=200&mainStatus='+status);
rows[status]={total:page.total,matching:page.records.filter(r=>r.inboundId===state.inboundId)};
}
if(rows.SAILING_CLEARANCE.matching.length||rows.WAIT_UNLOAD.matching.length!==1||rows.WAIT_DISPATCH.matching.length!==1)throw Error('测试来源页签流转不符合预期');
const r=await fetch(base+'/api/platform/v1/containers/'+state.containerId+'/clearance/document/'+doc.fileId+'/download',{headers:{Authorization:'Bearer '+admin},signal:AbortSignal.timeout(30000)});
const downloaded=await r.text();
if(!r.ok||!downloaded.includes(marker))throw Error('测试清关附件下载不一致');
state.verification={at:new Date().toISOString(),document:doc,rows,download:{http:r.status,containsLocalTestMarker:true}};save();
console.log(JSON.stringify({document:doc,rows:Object.fromEntries(Object.entries(rows).map(([s,p])=>[s,{total:p.total,matching:p.matching.map(r=>r.inboundId)}])),downloadHttp:r.status}));
}
if(action==='prepare'){
if(!state.pdaUserId && state.checks.some(c=>c.method==='POST'&&c.path==='/api/platform/v1/iam/users'&&String(c.code)==='200')){ const a=await api('','POST','/api/auth/login',{loginId:state.pdaUsername,password:process.env.LOCAL_TRANSFER_PDA_PASSWORD}); state.pdaUserId=JSON.parse(Buffer.from(a.accessToken.split('.')[1],'base64url')).sub;save(); }
if(!state.pdaUserId){
const roles=await api(admin,'GET','/api/platform/v1/iam/roles?page=1&size=200');
const role=(roles.records||roles).find(r=>r.roleCode==='CN_FIRSTLEG_PDA_OPERATOR');
if(!role)throw Error('缺少国内PDA角色');
state.pdaUsername='local_tail_pda_20261020';save();
await api(admin,'POST','/api/platform/v1/iam/users',{username:state.pdaUsername,displayName:'本地尾程流转验证PDA',phone:'18'+String(Date.now()).slice(-9),tenantId:'0',roleIds:[role.id],domesticWarehouseId:state.warehouseId,password:process.env.LOCAL_TRANSFER_PDA_PASSWORD,status:'ACTIVE'});
const users=await api(admin,'GET','/api/platform/v1/iam/users?page=1&size=20&keyword='+state.pdaUsername);
const user=users.records.find(r=>r.username===state.pdaUsername);
if(!user)throw Error('PDA创建后未查到');state.pdaUserId=user.userId;save();
}
const pda=(await api('','POST','/api/auth/login',{loginId:state.pdaUsername,password:process.env.LOCAL_TRANSFER_PDA_PASSWORD})).accessToken;
let current=await task();
if(current.assignment?.assigneeId!==state.pdaUserId)current=await api(admin,'POST',root+'/assign',{assigneeId:state.pdaUserId,assigneeName:'本地尾程流转验证PDA',expectedAssignmentVersion:current.assignment?.version||0,operationId:marker+'-assign'});
if(!state.before){state.before=await api(admin,'GET','/api/platform/v1/orders/status-counts');save();}
for(const item of current.items){if(item.itemStatus!=='PICKED')await api(pda,'POST',root+'/items/'+item.id+'/pick',{warehouseId:state.warehouseId,pickedPackageCount:item.plannedPackageCount,version:item.version,operationId:marker+'-pick-'+item.id});}
const evidence=await api(pda,'GET',root+'/evidence?warehouseId='+state.warehouseId);
for(const type of ['PHOTO_STEP_1','PHOTO_STEP_2','PHOTO_STEP_3','PHOTO_STEP_4','SEAL']){
if(evidence.evidences?.some(e=>e.evidenceType===type&&e.status==='ACTIVE'))continue;
if(state.evidence?.includes(type))continue;
const q=new URLSearchParams({warehouseId:state.warehouseId,expectedVersion:'0',evidenceType:type,remark:marker+' 合成测试图片;仅本地流转验收'});
if(type==='SEAL')q.set('sealNo','LOCALTEST20261020');
const bytes=Uint8Array.from([137,80,78,71,13,10,26,10,0,0,0,13,73,72,68,82,0,0,0,1,0,0,0,1,8,6,0,0,0,31,21,196,137,0,0,0,13,73,68,65,84,8,215,99,248,207,192,240,31,0,5,0,1,255,137,153,61,29,0,0,0,0,73,69,78,68,174,66,96,130]);
const body=new FormData();body.append('file',new Blob([bytes],{type:'image/png'}),marker+'-'+type+'.png');
await api(pda,'POST',root+'/evidence?'+q,body,marker+'-'+type);(state.evidence??=[]).push(type);save();
}
current=await task();
if(current.taskStatus==='LOADING'||current.taskStatus==='COMPLETION_FAILED')state.completion=await api(pda,'POST',root+'/complete',{expectedTaskVersion:state.completion?.completionCommand?.expectedTaskVersion??current.version,operationId:marker+'-complete',remark:marker+' 本地测试装柜交接验证'});
save();
}
if(action==='inspect'||action==='prepare') {state.task=await task();state.counts=await api(admin,'GET','/api/platform/v1/orders/status-counts');save();console.log(JSON.stringify({taskStatus:state.task.taskStatus,completion:state.task.completionCommand,counts:state.counts}));}
if(action==='depart'){
if((await task()).taskStatus!=='COMPLETED')throw Error('必须先装柜完成');
state.nodeTime??=new Date(Date.now()+8*3600000).toISOString().slice(0,19);save();
state.departure=await api(admin,'POST','/api/platform/v1/container-shipping-nodes/'+state.containerId,{standardNode:'DEPARTED_ORIGIN_PORT',observedAt:state.nodeTime,actualAt:state.nodeTime,locationName:'本地手动开船流转验收',reason:marker+' 用户授权本地手动节点验证'},marker+'-depart');
state.afterDeparture=await api(admin,'GET','/api/platform/v1/orders/status-counts');save();console.log(JSON.stringify(state.afterDeparture));
}
if(action==='clearance'){
state.clearanceBefore=await api(admin,'GET','/api/platform/v1/containers/'+state.containerId+'/clearance');save();
const form=new FormData();form.append('file',new Blob([marker+' LOCAL TEST ONLY 清关资料上传流转测试\n'],{type:'text/plain'}),marker+'-clearance.txt');
state.clearance=await api(admin,'POST','/api/platform/v1/containers/'+state.containerId+'/clearance/document/upload?expectedVersion='+(state.clearanceBefore?.version||0)+'&operationReason='+encodeURIComponent('本地流转测试资料'),form,marker+'-clearance');
state.afterClearance=await api(admin,'GET','/api/platform/v1/orders/status-counts');save();console.log(JSON.stringify(state.afterClearance));
}
}catch(e){state.lastError=e.message;save();console.error(e.message);process.exitCode=1;}
@@ -0,0 +1,26 @@
import fs from 'node:fs';
import {spawnSync} from 'node:child_process';
const dir=new URL('./',import.meta.url), results=[];
function sql(db,query){const r=spawnSync('D:/baiyue-runtime/mysql/server/bin/mysql.exe',['--host=127.0.0.1','--user=root','--database='+db,'-N','-B','--default-character-set=utf8mb4'],{input:query,encoding:'utf8',env:process.env,maxBuffer:20e6});if(r.status)throw new Error(r.stderr);return r.stdout.trim();}
function parts(s){let q='',d=0,start=0;const out=[];for(let i=0;i<s.length;i++){const c=s[i];if(q){if(c==='\\'){i++;continue;}if(c===q){if(s[i+1]===q)i++;else q='';}continue;}if("'\"`".includes(c)){q=c;continue;}if(c==='(')d++;else if(c===')')d--;else if(c===','&&!d){out.push(s.slice(start,i).trim());start=i+1;}}out.push(s.slice(start).trim());return out;}
for(const [db,file] of [['baiyue_firstleg','头程数据库统一增量-MySQL8.sql'],['baiyue_lastleg','海外区域统一增量-MySQL8.sql']]){
let active='';const tables=[];
for(const m of fs.readFileSync('deploy/sql/'+file,'utf8').matchAll(/USE (\w+);|CREATE TABLE\s+(?:IF NOT EXISTS\s+)?(\w+)\s*\(([\s\S]*?)\n\) ENGINE=[^;]+;/g)){if(m[1])active=m[1];else if(active===db)tables.push({name:m[2],defs:parts(m[3])});}
const columns=new Set(sql(db,'SELECT CONCAT(table_name,".",column_name) FROM information_schema.columns WHERE table_schema=DATABASE();').split(/\r?\n/));
const indexes=new Set(sql(db,'SELECT DISTINCT CONCAT(table_name,".",index_name) FROM information_schema.statistics WHERE table_schema=DATABASE();').split(/\r?\n/));
const report={db,baselineTables:tables.length,missingColumns:[],missingIndexes:[],appliedIndexes:[],blockedIndexes:[]};
for(const t of tables)for(const d of t.defs){
const col=d.match(/^`?(\w+)`?\s+(?:bigint|int|tinyint|smallint|mediumint|varchar|char|text|longtext|mediumtext|datetime|timestamp|date|time|decimal|double|float|json|boolean|binary|varbinary|blob|enum|bit)\b/i);
if(col&&!columns.has(t.name+'.'+col[1]))report.missingColumns.push(t.name+'.'+col[1]);
const key=d.match(/^(UNIQUE\s+)?KEY\s+`?(\w+)`?\s*\(([\s\S]*)\)$/i);
if(!key||indexes.has(t.name+'.'+key[2]))continue;
report.missingIndexes.push(t.name+'.'+key[2]);
if(process.argv.includes('--apply')){
try {sql(db,'SET SESSION lock_wait_timeout=15; ALTER TABLE `'+t.name+'` ADD '+d+';');report.appliedIndexes.push(t.name+'.'+key[2]);}
catch(e){report.blockedIndexes.push({index:t.name+'.'+key[2],reason:e.message});}
}
}
results.push(report);
}
fs.writeFileSync(new URL(process.argv.includes('--apply')?'index-repair.json':'schema-verification.json',dir),JSON.stringify(results,null,2));
console.log(JSON.stringify(results,null,2));
@@ -0,0 +1,4 @@
id tenant_id reservation_no idempotency_key source_service business_id inbound_code warehouse_id pallet_id pallet_code location_id location_code shared_overflow reservation_status expires_at confirmed_at released_at release_reason created_by created_at updated_at version active_reservation
2092814900999888899 0 LR2092814900999888899 measure-2092814880129130499-2092814899242573825-5-65052e11-585a-45c4-a89a-da1d54780e20:2092814900605722626 firstleg-service 2092814880129130499 NYEXX2608270051 193000000000200001 2092814900211359746 TP-080 193000000000200202 A0 1 CONFIRMED 2026-08-27 11:52:09.663 2026-08-27 11:22:09.716 NULL NULL 1000001 2026-08-27 11:22:09.686 2026-08-27 11:22:09.716 1 NULL
id tenant_id occupancy_no reservation_id source_service business_id inbound_code warehouse_id pallet_id pallet_code location_id location_code shared_overflow allocated_volume_cbm allocated_package_count occupancy_status occupied_at released_at release_reason created_by created_at updated_at version active_location_occupancy
2092814901134106625 0 LO2092814901134106625 2092814900999888899 firstleg-service 2092814880129130499 NYEXX2608270051 193000000000200001 2092814900211359746 TP-080 193000000000200202 A0 1 0.748000 4 OCCUPIED 2026-08-27 11:22:09.716 NULL NULL 1000001 2026-08-27 11:22:09.716 2026-08-27 11:22:09.716 0 NULL
1 id tenant_id reservation_no idempotency_key source_service business_id inbound_code warehouse_id pallet_id pallet_code location_id location_code shared_overflow reservation_status expires_at confirmed_at released_at release_reason created_by created_at updated_at version active_reservation
2 2092814900999888899 0 LR2092814900999888899 measure-2092814880129130499-2092814899242573825-5-65052e11-585a-45c4-a89a-da1d54780e20:2092814900605722626 firstleg-service 2092814880129130499 NYEXX2608270051 193000000000200001 2092814900211359746 TP-080 193000000000200202 A0 1 CONFIRMED 2026-08-27 11:52:09.663 2026-08-27 11:22:09.716 NULL NULL 1000001 2026-08-27 11:22:09.686 2026-08-27 11:22:09.716 1 NULL
3 id tenant_id occupancy_no reservation_id source_service business_id inbound_code warehouse_id pallet_id pallet_code location_id location_code shared_overflow allocated_volume_cbm allocated_package_count occupancy_status occupied_at released_at release_reason created_by created_at updated_at version active_location_occupancy
4 2092814901134106625 0 LO2092814901134106625 2092814900999888899 firstleg-service 2092814880129130499 NYEXX2608270051 193000000000200001 2092814900211359746 TP-080 193000000000200202 A0 1 0.748000 4 OCCUPIED 2026-08-27 11:22:09.716 NULL NULL 1000001 2026-08-27 11:22:09.716 2026-08-27 11:22:09.716 0 NULL
@@ -0,0 +1,52 @@
CREATE TABLE IF NOT EXISTS wh_location_block (
id BIGINT UNSIGNED NOT NULL COMMENT '整票库位块ID',
tenant_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '平台公共仓储资源域,固定为0',
warehouse_id BIGINT UNSIGNED NOT NULL COMMENT '仓库ID',
source_service VARCHAR(40) NOT NULL COMMENT '来源服务',
business_id BIGINT UNSIGNED NOT NULL COMMENT '当前归属入库单业务ID',
inbound_code VARCHAR(40) NOT NULL COMMENT '当前归属入仓码',
slot_count INT UNSIGNED NOT NULL COMMENT '整票独占槽位数',
idempotency_key VARCHAR(128) NOT NULL COMMENT '预占幂等键',
block_status VARCHAR(20) NOT NULL COMMENT 'RESERVED、OCCUPIED或RELEASED',
expires_at DATETIME(3) NOT NULL COMMENT '预占过期时间',
last_operation_key VARCHAR(128) NULL COMMENT '最近确认、转移或释放幂等键',
created_by BIGINT UNSIGNED NOT NULL COMMENT '创建人或系统主体ID',
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 '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
active_business_block TINYINT GENERATED ALWAYS AS
(CASE WHEN block_status IN ('RESERVED','OCCUPIED') THEN 1 ELSE NULL END) STORED
COMMENT '同一来源入库单仅允许一个活动整票块',
PRIMARY KEY (id),
UNIQUE KEY uk_location_block_idempotency (tenant_id, source_service, idempotency_key),
UNIQUE KEY uk_location_block_active_business (tenant_id, source_service, business_id, active_business_block),
KEY idx_location_block_business (tenant_id, source_service, business_id, block_status),
CONSTRAINT fk_location_block_warehouse FOREIGN KEY (warehouse_id) REFERENCES wh_warehouse (id),
CONSTRAINT ck_location_block_slot_count CHECK (slot_count BETWEEN 1 AND 200)
) ENGINE=InnoDB COMMENT='一票入仓码原子持有的稳定库位块';
CREATE TABLE IF NOT EXISTS wh_location_block_slot (
id BIGINT UNSIGNED NOT NULL COMMENT '槽位预占ID,对外作为reservationId',
tenant_id BIGINT UNSIGNED NOT NULL DEFAULT 0 COMMENT '平台公共仓储资源域,固定为0',
block_id BIGINT UNSIGNED NOT NULL COMMENT '整票库位块ID',
slot_no INT UNSIGNED NOT NULL COMMENT '块内稳定槽位序号,从1开始',
location_id BIGINT UNSIGNED NOT NULL COMMENT '库位ID',
location_code VARCHAR(50) NOT NULL COMMENT '库位编码快照',
shared_overflow TINYINT(1) NOT NULL DEFAULT 0 COMMENT '是否落入同仓共享A0',
resource_status VARCHAR(20) NOT NULL COMMENT 'RESERVED、OCCUPIED或RELEASED',
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 '更新时间',
version INT NOT NULL DEFAULT 0 COMMENT '乐观锁版本号',
active_normal_slot TINYINT GENERATED ALWAYS AS
(CASE WHEN resource_status IN ('RESERVED','OCCUPIED') AND shared_overflow = 0 THEN 1 ELSE NULL END) STORED
COMMENT '普通库位活动块槽唯一标记;A0返回NULL',
PRIMARY KEY (id),
UNIQUE KEY uk_location_block_slot_no (tenant_id, block_id, slot_no),
UNIQUE KEY uk_location_block_active_normal (tenant_id, location_id, active_normal_slot),
KEY idx_location_block_slot_block (tenant_id, block_id, resource_status),
CONSTRAINT fk_location_block_slot_block FOREIGN KEY (block_id) REFERENCES wh_location_block (id),
CONSTRAINT fk_location_block_slot_location FOREIGN KEY (location_id) REFERENCES wh_location (id)
) ENGINE=InnoDB COMMENT='整票库位块槽位;空槽也由当前入仓码独占';
-- 头程入库单属于其他数据库,不建立跨库外键。
@@ -0,0 +1,23 @@
-- 仅本机验收票:依据实际已确认预占/占用恢复缺失的块表示,不生成业务完成事实。
-- 旧预占、占用原始记录保留,恢复前快照见 warehouse-block-resource-before.tsv。
START TRANSACTION;
INSERT INTO wh_location_block
(id,tenant_id,warehouse_id,source_service,business_id,inbound_code,slot_count,
idempotency_key,block_status,expires_at,last_operation_key,created_by,created_at,version)
SELECT r.business_id,0,r.warehouse_id,r.source_service,r.business_id,r.inbound_code,1,
CONCAT('LOCAL-TAIL-20261020-RECOVER-',r.id),'OCCUPIED',r.expires_at,
'LOCAL-TAIL-20261020-RECOVER-CONFIRMED',r.created_by,r.created_at,0
FROM wh_location_reservation r
JOIN wh_location_occupancy o ON o.reservation_id=r.id AND o.business_id=r.business_id
WHERE r.id=2092814900999888899 AND r.business_id=2092814880129130499
AND r.tenant_id=0 AND o.tenant_id=0 AND r.reservation_status='CONFIRMED'
AND o.occupancy_status='OCCUPIED' AND o.allocated_package_count=4
AND NOT EXISTS (SELECT 1 FROM wh_location_block b WHERE b.id=r.business_id);
INSERT INTO wh_location_block_slot
(id,tenant_id,block_id,slot_no,location_id,location_code,shared_overflow,resource_status,created_at,version)
SELECT r.id,0,b.id,1,r.location_id,r.location_code,r.shared_overflow,'OCCUPIED',r.created_at,0
FROM wh_location_reservation r JOIN wh_location_block b ON b.id=r.business_id
WHERE r.id=2092814900999888899 AND b.id=2092814880129130499
AND b.idempotency_key=CONCAT('LOCAL-TAIL-20261020-RECOVER-',r.id)
AND NOT EXISTS (SELECT 1 FROM wh_location_block_slot s WHERE s.id=r.id);
COMMIT;
@@ -0,0 +1,78 @@
[
{
"method": "POST",
"path": "/api/auth/login",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "GET",
"path": "/api/platform/v1/iam/tenants/2085308606829346818",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "GET",
"path": "/api/platform/v1/orders?tenantId=2085308606829346818&mainStatus=WAIT_WEIGHT_CONFIRM&page=1&size=5",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "POST",
"path": "/api/platform/v1/iam/tenants/2085308606829346818/impersonation",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "POST",
"path": "/api/auth/impersonations/exchange",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "GET",
"path": "/api/merchant/v1/first-leg/orders/2085341741574098946/chargeable-weights",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "POST",
"path": "/api/merchant/v1/first-leg/chargeable-weights/2085341749429522434/confirm",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "POST",
"path": "/api/merchant/v1/first-leg/chargeable-weights/2085341749429522434/confirm",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "GET",
"path": "/api/platform/v1/orders?tenantId=2085308606829346818&mainStatus=WEIGHT_CONFIRMED&inboundCode=RK-2085341741574098946&page=1&size=5",
"http": 200,
"code": "200",
"passed": true
},
{
"method": "GET",
"path": "/api/platform/v1/orders?tenantId=2085308606829346818&mainStatus=WAIT_WEIGHT_CONFIRM&inboundCode=RK-2085341741574098946&page=1&size=5",
"http": 200,
"code": "200",
"passed": true
},
{
"label": "同一测试订单确认后进入已确认、离开待确认;同幂等命令重放成功",
"passed": true,
"orderId": "2085341741574098946",
"inboundId": "2085341749429522434"
}
]
@@ -0,0 +1,32 @@
import fs from 'node:fs';
import {randomUUID} from 'node:crypto';
const base=process.env.ADMIN_TEST_GATEWAY;
if(!base||!['localhost','127.0.0.1'].includes(new URL(base).hostname))throw new Error('仅允许本机');
const checks=[];let admin='',merchant='';
async function api(token,method,path,body,headers={}){
const r=await fetch(base+path,{method,headers:{...(token?{Authorization:'Bearer '+token}:{}),...(body?{'Content-Type':'application/json'}:{}),...headers},body:body?JSON.stringify(body):undefined,signal:AbortSignal.timeout(45000)});
const v=await r.json();checks.push({method,path,http:r.status,code:v.code,message:String(v.code)==='200'?undefined:v.message,passed:r.status===200&&String(v.code)==='200'});
fs.writeFileSync(new URL('weight-flow.json',import.meta.url),JSON.stringify(checks,null,2));
if(!checks.at(-1).passed)throw new Error(`${path}: ${r.status}/${v.code} ${v.message}`);return v.data;
}
admin=(await api('','POST','/api/auth/login',{loginId:process.env.ADMIN_TEST_USERNAME,password:process.env.ADMIN_TEST_PASSWORD})).accessToken;
const customer=await api(admin,'GET','/api/platform/v1/iam/tenants/2085308606829346818');
if(!JSON.stringify(customer).includes('测试'))throw new Error('目标并非既有测试客户,停止业务写入');
const before=await api(admin,'GET','/api/platform/v1/orders?tenantId=2085308606829346818&mainStatus=WAIT_WEIGHT_CONFIRM&page=1&size=5');
const target=before.records?.find(x=>x.inboundId);
if(!target)throw new Error('测试客户没有可确认来源');
const ticket=await api(admin,'POST','/api/platform/v1/iam/tenants/2085308606829346818/impersonation',{reason:'本地新增订单页签验收:独立确认测试客户计费重并核对队列流转'});
merchant=(await api('','POST','/api/auth/impersonations/exchange',{code:ticket.code})).accessToken;
const weights=await api(merchant,'GET',`/api/merchant/v1/first-leg/orders/${target.orderId}/chargeable-weights`);
const weight=weights.find(x=>String(x.inboundId)===String(target.inboundId)&&!x.confirmed);
if(!weight)throw new Error('测试来源没有当前待确认计费重');
const key=randomUUID();
const result=await api(merchant,'POST',`/api/merchant/v1/first-leg/chargeable-weights/${weight.inboundId}/confirm`,{expectedFingerprint:weight.fingerprint},{'Idempotency-Key':key});
if(!result.confirmed)throw new Error('未读回已确认事实');
await api(merchant,'POST',`/api/merchant/v1/first-leg/chargeable-weights/${weight.inboundId}/confirm`,{expectedFingerprint:weight.fingerprint},{'Idempotency-Key':key});
const confirmed=await api(admin,'GET',`/api/platform/v1/orders?tenantId=2085308606829346818&mainStatus=WEIGHT_CONFIRMED&inboundCode=${encodeURIComponent(target.inboundCode)}&page=1&size=5`);
const pending=await api(admin,'GET',`/api/platform/v1/orders?tenantId=2085308606829346818&mainStatus=WAIT_WEIGHT_CONFIRM&inboundCode=${encodeURIComponent(target.inboundCode)}&page=1&size=5`);
if(!confirmed.records.some(x=>String(x.orderId)===String(target.orderId))||pending.records.some(x=>String(x.orderId)===String(target.orderId)))throw new Error('确认后页签流转不一致');
checks.push({label:'同一测试订单确认后进入已确认、离开待确认;同幂等命令重放成功',passed:true,orderId:target.orderId,inboundId:weight.inboundId});
fs.writeFileSync(new URL('weight-flow.json',import.meta.url),JSON.stringify(checks,null,2));console.log(JSON.stringify(checks,null,2));
@@ -0,0 +1,127 @@
# 新增订单页签本地验收
2026-10-19,目标仅为本机 Gateway/MySQL/Nacos。此前已执行的结构补齐见同目录《验收记录.md》。本轮没有通过直接写业务表生成任何物流事实,没有远程部署。
## 本轮修复
复现发现,运行中的 Order 仍为旧版代码:新增 mainStatus 参数返回“统一订单主状态不合法”,status-counts 未生效。当前代码已支持这些状态,因此重新编译并重启 Order、Firstleg、Lastleg,并为本地跨服务调用配置 localhost 地址。
编译通过。当前后台服务为 Order PID 54860(9204)、Firstleg PID 33804(9202)、Lastleg PID 48016(9303)。进程由本轮启动;以后使用 IDE 启动前先核对端口占用,避免双启动。
本轮没有发现需要额外补齐的页签 SQL 表或字段;此前新建的 fl_chargeable_weight_confirmation、ll_delivery_facts_changed 等结构已被实际查询使用。
## 真实 HTTP 读取
通过既有本地平台账号登录统一 Gateway,19 个状态列表、status-counts 均 HTTP 200 / code 200。19 个状态列表 total 均与汇总对应数量一致,包括所有零数据状态。原有页签继续可读取。
| 页签 | 本轮最后核对数量 |
|---|---:|
| 待审核 | 127 |
| 待测量数据 | 195 |
| 测量审核 | 120 |
| 待客户确认计费重 | 125 |
| 已确认数据 | 1 |
| 待上传资料 | 0 |
| 一件代发打托 | 6 |
| 待分柜 | 126 |
| 装柜中 | 9 |
| 装柜完成 | 73 |
| 出口报关 | 0 |
| 已开船/待清关 | 0 |
| 待拆柜 | 0 |
| 待排车 | 0 |
| 出库单 | 0 |
| 派送 | 0 |
| 签收 | 0 |
| 派送完成 | 0 |
| 已完成 | 2 |
证据:tab-smoke.json、tab-count-consistency.json。数量是检查时刻的本地事实,不是固定产品配置。此次未完成全部浏览器页面的人工视觉验收。
## 真实本地业务流转
通过正式 IAM 代登录与 Auth 交换接口取得既有 ACTIVE 测试企业会话;仅确认一条该测试企业既有待确认计费重,没有改费用金额或物流主状态。
测试订单 2085341741574098946、入仓单 2085341749429522434:
1. 通过客户 API 读取当前审核通过的计费重及 fingerprint。
2. 使用当前 fingerprint 与独立幂等键提交确认。
3. 读回 confirmed=true;同一命令重放仍成功。
4. 平台按同入仓码查询:进入 WEIGHT_CONFIRMED,退出 WAIT_WEIGHT_CONFIRM。
5. 全量数量从待确认 126 / 已确认 0,变为待确认 125 / 已确认 1。
证据:weight-flow.json。测试确认历史予以保留。其他客户未被修改。
## 定向回归
Order / Firstleg 共 96 项通过;尾程独立定向编译与两项测试通过,共 98 项。覆盖当前来源的确认、重复命令、旧版本拒绝、重测失效、分柜父子来源、资料客户归属、清关上传、报关、卸柜事实、建出库单、取消回显、实际出库、派送及客户隔离。
尾程为临时 POM 限定 workflow 测试编译及独立测试输出目录,未视作尾程完整测试套件通过。临时 POM 已删除,正常构建配置没有修改。证据:tab-regression.log、lastleg-tab-regression.log。
Mapper 扫描合同通过:10 个持久化模块、396 个 Mapper。
截至 21:08 运行日志未发现 ERROR、BadSqlGrammarException、SQLSyntaxErrorException 或预约同步失败。两业务服务健康检查均为 UP。
## 后半程现场数据边界
本地 fl_carrier_schedule_node_fact 当前为 0 行,fl_customs_container 当前无 DECLARING 记录,因此待排车等后半程页签没有符合前置事实的订单。清关资料已有记录,不能单凭资料存在假设已实际开船。历史尾程来源主要为旧 CN 等标识,不能直接改成当前 FIRSTLEG 或伪造离港记录来证明流转。
后半程已通过隔离库真实 Mapper 和领域定向回归;尚未使用新生成的一票业务单,在本机通过完整装柜交接、实际离港录入、卸柜、出库和签收命令完成整链路真实 HTTP 验收。因此不能将本报告称为全部真实业务流验收通过。
此前保留的历史重复来源唯一索引冲突、历史必填事实为空及其他页面权限问题仍见《验收记录.md》,本轮未扩大账号授权。
## 2026-10-19 页签数量接口修复补验
纠正此前验证缺口:旧的统计接口验收请求额外带了 page/size,未覆盖浏览器实际不带分页的调用。此次修复前,以不带参数的 `/api/platform/v1/orders/status-counts` 成功复现 A0422(page 的 null 无法绑定 long),见 tab-smoke-before.log。旧验收结论不能证明该请求正常。
修复:统计入口使用独立的无分页筛选 DTO,转换为共用查询条件;保留筛选校验、平台权限及客户范围,忽略页签和分页,不改业务数量口径。前端已有“名称(数量)”显示,包括零数量,全部不显示数量,本轮无需改动布局。
验证:Order 定向 69 项、Admin 数量 API/页面定向 27 项全部通过;新增 MVC 用例覆盖不传分页、false 筛选、日期、客户范围、忽略额外分页/状态和非法税务类型。证据:status-count-binding-test.log、status-count-frontend-test.log。
本地仅重启 Order,PID 15788。实际经过 Gateway 的无分页统计请求成功(业务码200),19个状态列表均成功,逐项统计数量与各列表总数一致,见 tab-smoke.json、tab-count-consistency.json。当前待客户确认125、已确认数据1、测量数据审核120,无符合业务事实的状态返回0。Firstleg/Lastleg健康检查正常;Order本次启动日志未发现ERROR或SQL语法错误。
本轮未取得刷新后人工页面截图,未宣称完整视觉验收或后半程真实全链路验收通过。
## 2026-10-19 报关与开船链路口径补充
用户明确:待上传资料为报关资料;出口报关汇总本票资料已上传且装柜完成的订单。实际开船(目前人工节点,后续拉取节点)后进入已开船/待清关,头程上传清关资料后进入待拆柜,持续到实际卸柜完成。
已调整 WorkflowFactMapper 与 WorkflowTabService:出口报关不再仅匹配 DECLARING,也不要求整柜全部客户资料齐全或点击开始报关;按当前独立来源、本客户、本柜的有效报关资料与真实装柜证据汇总。买单票沿用既有无需客户退税资料的业务规则。实际开船后移出报关前序页签,按清关资料事实分类;预计日期不能替代实际离港。资料已上传但尚未实际开船时,不提前进入待拆柜。现有报关资料上传入口按完成装柜后的柜次关联,本轮未扩大到装柜前上传。原报关四态和实际报关命令保持原有规则。
手动及外部船节点均由 CarrierScheduleQueryService.addNode 保存到 fl_carrier_schedule_node_fact,统一按 DEPARTED_ORIGIN_PORT 且 actual_at 非空判断;不增加另一套人工开船标志。
自动回归:Order 69项、Firstleg 28项,共97项通过(customs-tab-flow-test.log)。真实 Mapper + H2 隔离库验证资料上传即进入、删除后回显、其他客户及其他柜资料不能覆盖、装柜未完成或无实拣数量不能进入、报关状态等待/就绪/申报/完成均不替代资料事实,以及买单资料豁免;领域测试覆盖开船、清关上传、实际卸柜退出及独立分柜来源。隔离库测试未写本机业务事实。
本机生效补验:仅重启 Firstleg(PID45432),启动成功,本次日志未见ERROR或SQL语法异常。通过Gateway重新读取无分页数量及19个状态列表,全部成功且数量逐项一致(customs-tab-live.log、customs-tab-consistency.json)。出口报关从0变为12,待上传报关资料0。
只读核对说明:当前满足独立实装关联的来源为BUY_DECLARATION 12条、历史tax_mode空值2条,无TAX_REFUND来源;因此12条是沿用买单免客户退税资料规则,并不表示伪造了12次资料上传。历史空税务模式没有自行补成买单。实际离港节点0条,后半程无数据符合进入条件。本轮没有为填充列表修改业务资料、装柜或船节点事实;真实本机完整开船到签收链路仍未验收。
## 2026-10-20 本地尾程节点与清关资料流转补验
当前显示口径:派送改为“派送中”,签收改为“签收完成”,签收完成仍显示括号数量;移除“派送完成”“已完成”页签,历史状态及接口保留。
修复实际阻塞:
- 当前部分装柜模型为来源单承接实装、REMAINDER 子单承接余量。统一页签不再把这种来源单当作纯父汇总排除;真正由 LOADED 子票承接的旧父汇总仍不重复计票。
- 尾程来源按客户、来源入仓单精确字符串匹配,避免 MySQL 连接默认排序规则冲突和大整数隐式比较;record 参数使用 MyBatis 可读取的 record 访问器。
- 目的港清关资料读取、上传、下载及完成入口接受有效货柜已确认离仓或已有 DEPARTED_ORIGIN_PORT 实际节点;预计节点不放行。保留国内出仓、国外工作台和 DO 原有门禁,未创建虚假的国内出仓确认。
- 本地补齐 Warehouse 的 wh_location_block / wh_location_block_slot;仅对本轮既有测试票按真实历史预占和占用恢复缺失块表示,保留原预占与占用。部分拣货由正式结算接口转移至余量票。
- 本地手动节点表 query_id 改为允许空,唯一键使用 container_booking_id/event_key,按当前正式基线支持无拉取任务的手动节点。
- 本地执行 IAM 正式 container-workspace-permissions.sql 补齐清关入口权限,并更新默认角色相关账号权限版本;旧登录建议重新登录。
测试来源:NYEXX2608270051(入仓单 2092814880129130499),柜 CSQU3054383;本轮正式 PDA 装柜完成后尾程新单 2112376565948878849 创建成功,装柜事件与手动开船事件均已处理。来源票实装1箱、独立余量票 NYEXX2608270051-1 为3箱,余量未被错误带入开船页签。
经本机 Gateway 的正式业务命令实测:
1. 装柜完成并保存手动实际开船节点后,已开船/待清关=1、待拆柜=0、待排车=1。
2. 上传 LOCAL-TAIL-20261020-clearance.txt 后,已开船/待清关=0、待拆柜=1、待排车=1;未点击“清关完成”,读回 completedAt 为空,证明按上传事实流转。
3. 待拆柜和待排车列表均精确返回本票来源;待清关列表不再返回。清关附件通过正式下载接口校验内容,HTTP200。
4. 无分页统计、19个状态列表、Firstleg/Lastleg 两个健康检查共23项均成功,各列表 total(字符串)与统计数值规范化后逐项一致,未用失败伪造零值。当前派送中和签收完成均为0,本轮没有真实发车或全签样本。
证据:tail-flow-state.json、tail-final-consistency.json、tab-smoke.json、tail-final-smoke.log。头程30项定向测试通过(tail-clearance-access-test.log);此前来源分柜/取消回显/派送/全签分类等12项通过(tail-flow-source-test.log)。Admin 405文件/3375测试及构建类型检查通过(tail-tabs-frontend-test.log、tail-tabs-frontend-build.log)。Gateway入口5项与Mapper扫描397个均通过。
边界:PDA照片是明确命名的合成测试图片,清关文件为本机测试文本;不能作为现场装柜或真实报关证据。本轮没有实际卸柜、出库发车和全签命令,后续环节仍以隔离库领域/Mapper测试覆盖;不能宣称真实物流全链路验收完成。浏览器临时页打开后处于登录页,未获得登录后截图,因此不宣称人工视觉验收通过。尾程常规测试编译仍被其他在途模块旧签名阻断,单独回归结果另记,不等于全量通过。
尾程补验:tail-workflow-isolated-test.log 最终 BUILD SUCCESS,完整生产源码编译及2项 workflow 隔离测试通过(含相邻长整型ID精确隔离、出库取消、实际派送/卸柜事实、内部令牌);读出键直接由JDBC按long映射,避免 H2 SIGNED 被解释为32位整数。临时模块/聚合POM已删除,正常构建配置未修改。
最终生效复核:Firstleg PID56348、Lastleg PID17412。尾程最终修复重启后,重新通过23项HTTP/健康检查且19项数量与列表total一致;清关文件下载及精确来源页签验证再次通过。两个本次启动日志未发现ERROR、BadSqlGrammarException或SQLSyntaxErrorException。头程没有新增代码变更,因此复用已通过的30项及此前12项回归,不重复占用其他任务的共享构建槽。
@@ -0,0 +1,34 @@
# 本地头程与尾程结构修复
时间:2026-10-19;目标:本机 MySQL 127.0.0.1:3306。
## 实际改动
| 数据库 | 新建表 | 已有表新增字段 | 已有表新增索引 |
|---|---:|---:|---:|
| baiyue_firstleg | 14 | 6 | 18 |
| baiyue_lastleg | 53 | 97 | 18 |
包含报错表 `ll_delivery_facts_changed`,头程计费重确认、报关/清关和船期表,以及尾程排车、派送事实、采购和自营统计等缺失结构。
对照当前统一初始化 SQL 的建表定义复查:头程 131 张基线表、尾程 218 张基线表均已存在,基线字段无缺失。保留本地额外表;未执行整库初始化、删除、业务数据回填或远程部署。
执行前后的结构快照为 `schema-before.sql`、`schema-after.sql`。`actual-changes.json` 是实际结构差异;`actual-incremental-review.sql` 是实际增量审阅记录,已执行,不能在当前库重复执行。DDL 隐式提交,前快照仅用于审阅和恢复设计,不应直接覆盖现有库。
## 运行验证
重启时沿用原 Java 可执行文件、应用主类和类路径,并加载本地 Nacos、Redis、数据库与服务地址配置。原 IDE 启动的两服务进程已停止,新进程在后台运行:头程 PID 48892(9202)、尾程 PID 64060(9303)。后续需要 IDE 调试时,先停止对应后台进程,避免端口冲突。
两服务均成功输出 Started;健康检查均为 HTTP 200、status UP。从约 20:36 启动至 20:40 的观察窗口内,未发现 ERROR、BadSqlGrammarException、SQLSyntaxErrorException 或预约同步失败;尾程曾出现一次同步耗时告警,complete=true、failed=false。
通过本地统一 Gateway,既有本地验收账号登录成功。尾程订单、整车排车、排车草稿、头程入库单、指定有效客户的履约任务列表五个只读业务接口均返回 HTTP 200 / code 200。未创建、修改或删除业务单据。
这次验证为结构、服务运行和 HTTP 读取验证,未完成所有页面的人工视觉验收,也未重新执行全量业务流。
## 保留事项
1. 已有尾程历史单据的 16 个新必填业务字段无法从结构本身推导真实值,按可空字段补齐,历史行保留 NULL,未伪造来源快照、清单摘要或实收数量。后续推进这些历史单据前需核对真实资料;这部分并非完整 NOT NULL 约束对齐。
2. `ll_inbound_plan.uk_ll_inbound_plan_source_order` 唯一索引因历史重复来源建索引失败(Duplicate entry)。原记录完整保留;其他缺失索引已建立。对应错误与复查见 `index-repair.json`、`schema-verification.json`。
3. 当前本地验收账号读取预约工作台汇总、船期渠道、船期模板返回 A0403 / Access denied。这三项是权限阻断,未改动账号授权,不能记作页面验收通过。详细结果见 `http-smoke.json`。
服务日志:`firstleg-runtime.log`、`lastleg-runtime.log`;两个标准错误日志均为空。