From 0af977bdefc1333186ead1234ea5aa824ebf83d9 Mon Sep 17 00:00:00 2001 From: ouyangxq <775153912@qq.com> Date: Wed, 21 Oct 2026 14:16:17 +0800 Subject: [PATCH] fix(fleet): compare pooled cargo identifiers without collation conflicts --- .../mapper/OwnedBusinessQueryMapper.java | 14 ++++++++------ .../OwnedBusinessScopePersistenceTest.java | 19 +++++++++++++++++++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/lastleg-service/src/main/java/com/baiyue/lastleg/fleet/ownedbusiness/mapper/OwnedBusinessQueryMapper.java b/lastleg-service/src/main/java/com/baiyue/lastleg/fleet/ownedbusiness/mapper/OwnedBusinessQueryMapper.java index ac511bf51..941053742 100644 --- a/lastleg-service/src/main/java/com/baiyue/lastleg/fleet/ownedbusiness/mapper/OwnedBusinessQueryMapper.java +++ b/lastleg-service/src/main/java/com/baiyue/lastleg/fleet/ownedbusiness/mapper/OwnedBusinessQueryMapper.java @@ -7,18 +7,20 @@ import java.util.List; /** 在原排车事实之上做自有运营分页,不复制或推进履约模型。 */ @Mapper public interface OwnedBusinessQueryMapper { - /** 拼车登记须已实收并绑定本车,且原实收来源仍在本车计划托盘组成内;多票只判存在。 */ + /** 拼车须实收且来源仍在本车;标识按完整字节精确比较,512字节覆盖128字符utf8mb4,避免列排序规则冲突或截断。 */ String POOLED_CARGO=""" EXISTS (SELECT 1 FROM ll_fleet_external_booking b - JOIN ll_warehouse_transfer_order incoming ON incoming.customer_id=b.customer_id AND incoming.transfer_no=b.incoming_no - WHERE b.trip_id=d.trip_id AND b.dispatch_no=d.dispatch_no AND b.offer_id IS NOT NULL + JOIN ll_warehouse_transfer_order incoming ON CAST(incoming.customer_id AS BINARY(512))=CAST(b.customer_id AS BINARY(512)) + AND CAST(incoming.transfer_no AS BINARY(512))=CAST(b.incoming_no AS BINARY(512)) + WHERE b.trip_id=d.trip_id AND CAST(b.dispatch_no AS BINARY(512))=CAST(d.dispatch_no AS BINARY(512)) AND b.offer_id IS NOT NULL AND b.status='BOUND' AND b.receipt_json IS NOT NULL AND EXISTS (SELECT 1 FROM ll_dispatch_item cargo JOIN ll_inbound_plan_pallet_allocation allocation ON allocation.pallet_id=cargo.plan_pallet_id - AND allocation.plan_id=cargo.plan_id AND allocation.customer_id=cargo.customer_id + AND allocation.plan_id=cargo.plan_id AND CAST(allocation.customer_id AS BINARY(512))=CAST(cargo.customer_id AS BINARY(512)) JOIN ll_inbound_plan_line line ON line.id=allocation.line_id AND line.plan_id=cargo.plan_id - WHERE cargo.dispatch_order_id=d.id AND cargo.customer_id=b.customer_id - AND line.customer_id=b.customer_id AND line.inbound_code=incoming.inbound_code + WHERE cargo.dispatch_order_id=d.id AND CAST(cargo.customer_id AS BINARY(512))=CAST(b.customer_id AS BINARY(512)) + AND CAST(line.customer_id AS BINARY(512))=CAST(b.customer_id AS BINARY(512)) + AND CAST(line.inbound_code AS BINARY(512))=CAST(incoming.inbound_code AS BINARY(512)) AND cargo.warehouse_pallet_id IS NOT NULL AND cargo.package_count>0)) """; String SOURCE=""" diff --git a/lastleg-service/src/test/java/com/baiyue/lastleg/fleet/ownedbusiness/OwnedBusinessScopePersistenceTest.java b/lastleg-service/src/test/java/com/baiyue/lastleg/fleet/ownedbusiness/OwnedBusinessScopePersistenceTest.java index d54ff5f29..5f3f64359 100644 --- a/lastleg-service/src/test/java/com/baiyue/lastleg/fleet/ownedbusiness/OwnedBusinessScopePersistenceTest.java +++ b/lastleg-service/src/test/java/com/baiyue/lastleg/fleet/ownedbusiness/OwnedBusinessScopePersistenceTest.java @@ -157,6 +157,25 @@ class OwnedBusinessScopePersistenceTest { assertEquals(2,outsourced.list(actor(),query).total()); assertThrows(BizException.class,()->outsourced.detail(actor(),"DS-OUT-2")); } + /** 同前缀编号末位必须参与来源匹配,128字符的多字节入仓码不能被二进制宽度截断。 */ + @Test void completeIdentifiersDeterminePoolScopeWithoutPrefixTruncation() { + String transfer="T".repeat(63)+"A",dispatch="D".repeat(63)+"A",inbound="仓".repeat(127)+"甲"; + baseline.jdbc.update("UPDATE ll_warehouse_transfer_order SET transfer_no=?,inbound_code=? WHERE transfer_no='INCOMING-2'",transfer,inbound); + baseline.jdbc.update("UPDATE ll_inbound_plan_line SET inbound_code=? WHERE plan_id=2000",inbound); + baseline.jdbc.update("UPDATE ll_dispatch_order SET dispatch_no=? WHERE id=2",dispatch); + baseline.jdbc.update("UPDATE ll_fleet_external_booking SET dispatch_no=?,incoming_no=? WHERE id=2",dispatch,transfer); + assertNotNull(outsourced.detail(actor(),dispatch)); + baseline.jdbc.update("UPDATE ll_fleet_external_booking SET incoming_no=? WHERE id=2","T".repeat(63)+"B"); + assertNotNull(queries.detail(OwnedBusinessFixtures.actor(),dispatch)); + baseline.jdbc.update("UPDATE ll_fleet_external_booking SET incoming_no=?,dispatch_no=? WHERE id=2",transfer,"D".repeat(63)+"B"); + assertNotNull(queries.detail(OwnedBusinessFixtures.actor(),dispatch)); + baseline.jdbc.update("UPDATE ll_fleet_external_booking SET dispatch_no=? WHERE id=2",dispatch); + baseline.jdbc.update("UPDATE ll_inbound_plan_line SET inbound_code=? WHERE plan_id=2000","仓".repeat(127)+"乙"); + assertNotNull(queries.detail(OwnedBusinessFixtures.actor(),dispatch)); + baseline.jdbc.update("UPDATE ll_inbound_plan_line SET inbound_code=? WHERE plan_id=2000",inbound); + assertNotNull(outsourced.detail(actor(),dispatch)); + assertEquals(3,outsourced.list(actor(),new OwnedBusinessModels.Query(1,1,null,null,null,null,null)).summary().dispatchCount()); + } /** 外配档案和临时车辆分别保持真实ID/空ID及原承运商,GET不建记录。 */ @Test void masterAndExternalReadOriginalSnapshotWithoutBackfill() { var master=outsourced.detail(actor(),"DS-OUT-2");var external=outsourced.detail(actor(),"DS-OUT-3");