fix(fleet): compare pooled cargo identifiers without collation conflicts

This commit is contained in:
2026-10-21 14:16:17 +08:00
parent be79b90a4a
commit 0af977bdef
2 changed files with 27 additions and 6 deletions
@@ -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="""
@@ -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");