Integrate verified owned dispatch operations and keep unfinished numbering out of TEST
This commit is contained in:
+2
-1
@@ -261,7 +261,8 @@ public interface DispatchCandidateMapper {
|
||||
"<if test='customerId != null and customerId != \"\"'>AND a.customer_id=#{customerId} </if>" +
|
||||
"<if test='relabelNo != null and relabelNo != \"\"'>AND a.relabel_no=#{relabelNo} </if>" +
|
||||
"<if test='orderNo != null and orderNo != \"\"'>AND (a.relabel_no LIKE CONCAT('%',#{orderNo},'%') OR ri.source_inbound_code LIKE CONCAT('%',#{orderNo},'%') OR ri.source_inbound_order_no LIKE CONCAT('%',#{orderNo},'%')) </if>" +
|
||||
"AND pos.hold_packages > 0 " +
|
||||
// 未绑定实托的位置不是可选运输来源;完整申请中的缺失组成仍由提供者返回阻断原因。
|
||||
"AND pos.hold_packages > 0 AND pos.pallet_id > 0 " +
|
||||
"AND NOT EXISTS (SELECT 1 FROM ll_dispatch_item di JOIN ll_dispatch_order existing_dispatch " +
|
||||
"ON existing_dispatch.id=di.dispatch_order_id " +
|
||||
"WHERE di.customer_id=a.customer_id AND di.source_stage='RELABEL' AND di.order_refs=a.relabel_no " +
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
package com.baiyue.lastleg.dispatch.repository;
|
||||
|
||||
import com.baiyue.common.core.api.ResultCode;
|
||||
import com.baiyue.common.core.exception.BizException;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.stereotype.Repository;
|
||||
import org.springframework.transaction.annotation.Propagation;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import java.time.LocalDate;
|
||||
|
||||
/** 整车单号独立日流水;独立短事务归还序列锁后才进入车辆、司机及货物锁。 */
|
||||
@Repository
|
||||
public class DispatchNumberSequence {
|
||||
private final JdbcTemplate jdbc;
|
||||
|
||||
/** 流水与排车主单使用相同服务数据库。 */
|
||||
public DispatchNumberSequence(JdbcTemplate jdbc) { this.jdbc = jdbc; }
|
||||
|
||||
/** 唯一日期行原子递增,连接内取回本次值;失败不复用已分配的业务号。 */
|
||||
@Transactional(propagation = Propagation.REQUIRES_NEW)
|
||||
public long next(LocalDate date) {
|
||||
jdbc.update("INSERT INTO ll_dispatch_daily_sequence(business_date,last_sequence) VALUES(?,LAST_INSERT_ID(1)) "
|
||||
+ "ON DUPLICATE KEY UPDATE last_sequence=LAST_INSERT_ID(last_sequence+1)", date);
|
||||
Long value = jdbc.queryForObject("SELECT LAST_INSERT_ID()", Long.class);
|
||||
if (value == null || value < 1) throw new IllegalStateException("排车日流水分配失败");
|
||||
if (value > 9999) throw new BizException(ResultCode.CONFLICT, "当日排车单四位流水号已用满");
|
||||
return value;
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -32,7 +32,6 @@ import static com.baiyue.lastleg.dispatch.port.DispatchContracts.*;
|
||||
/** 真整车创建、加货与查询;客户只属于明细,不属于整车头。 */
|
||||
@Service
|
||||
public class DispatchAggregateService implements DispatchExecutionPort,DispatchAppointmentAmendmentPort {
|
||||
@jakarta.annotation.Resource private DispatchNumberGenerator numbers;
|
||||
@jakarta.annotation.Resource private DispatchAppointmentAllocations appointments;
|
||||
@jakarta.annotation.Resource private DispatchPhysicalClaimService physicalClaims;
|
||||
@jakarta.annotation.Resource private DispatchItemSourceService relabelSources;
|
||||
@@ -270,7 +269,7 @@ public class DispatchAggregateService implements DispatchExecutionPort,DispatchA
|
||||
var replay = commands.replay(actor,null,identity);
|
||||
if (replay.isPresent()) return replay.get();
|
||||
long id=IdWorker.getId();
|
||||
String number=numbers.next();
|
||||
String number="DS-"+UUID.randomUUID().toString().replace("-","").toUpperCase(Locale.ROOT);
|
||||
var shell=fleet.createDispatchShell(actor.operatorId(),new FleetExecutionModels.DispatchShellRequest(id,number,
|
||||
Long.parseLong(request.warehouseId()),request.idempotencyKey(),identity.commandHash(),request.plannedDepartureAt(),
|
||||
fleetVehicle(request.vehicle()),fleetDriver(request.driver()),request.remark()));
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
package com.baiyue.lastleg.dispatch.service;
|
||||
|
||||
import com.baiyue.lastleg.dispatch.repository.DispatchNumberSequence;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
import java.time.Clock;
|
||||
import java.time.LocalDate;
|
||||
import java.time.ZoneId;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
|
||||
/** 平台排车单号:PC、北京时间日期与每日独立四位流水。 */
|
||||
@Component
|
||||
public class DispatchNumberGenerator {
|
||||
private static final ZoneId BUSINESS_ZONE = ZoneId.of("Asia/Shanghai");
|
||||
private final DispatchNumberSequence sequences;
|
||||
private final Clock clock;
|
||||
|
||||
/** 正式运行按统一业务时区取当天日期。 */
|
||||
@Autowired
|
||||
public DispatchNumberGenerator(DispatchNumberSequence sequences) { this(sequences, Clock.systemUTC()); }
|
||||
|
||||
/** 固定时钟用于核实跨午夜归零边界。 */
|
||||
DispatchNumberGenerator(DispatchNumberSequence sequences, Clock clock) { this.sequences = sequences; this.clock = clock; }
|
||||
|
||||
/** 已有命令重放由上层账本恢复原号,本方法只用于首次建单。 */
|
||||
public String next() {
|
||||
LocalDate date = LocalDate.now(clock.withZone(BUSINESS_ZONE));
|
||||
long value = sequences.next(date);
|
||||
if (value < 1 || value > 9999) throw new IllegalStateException("排车日流水不在四位范围内");
|
||||
return "PC" + date.format(DateTimeFormatter.BASIC_ISO_DATE) + String.format(Locale.ROOT, "%04d", value);
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -90,7 +90,9 @@ public class DispatchService {
|
||||
if(facts==null)throw new ResponseStatusException(HttpStatus.CONFLICT,"实托完整来源快照缺失");
|
||||
reasons.addAll(facts.blockReasons());
|
||||
if(!facts.complete() && facts.blockReasons().isEmpty())reasons.add("实托实际绑定组成未核齐");
|
||||
facts.positions().stream().map(RelabelDispatchSourcePort.Position::warehousePalletId).filter(Objects::nonNull).forEach(pallets::add);
|
||||
// 缺失的实托身份保留在事实与阻断原因中,不能拿零值扩组或传给严格的实托查询入口。
|
||||
facts.positions().stream().map(RelabelDispatchSourcePort.Position::warehousePalletId)
|
||||
.filter(id->id!=null && id>0).forEach(pallets::add);
|
||||
for(var app:facts.applications())applications.put(app.relabelNo(),app.customerId());
|
||||
var codes=rows.values().stream().map(DispatchPalletCandidate::palletNo).filter(Objects::nonNull).distinct().toList();
|
||||
for(var app:wholeSources.nativeApplications(seed.overseasWarehouseId(),codes))applications.put(app.relabelNo(),app.customerId());
|
||||
|
||||
+2
@@ -68,7 +68,9 @@ public class RelabelDispatchSourceRepository {
|
||||
if (position == null) position = mapper.position(item.getSourceInventoryPositionId());
|
||||
if (position == null) continue;
|
||||
positions.put(position.getId(), position);
|
||||
// 无效身份只作为本申请缺失组成保留,不能把其他未绑定位置误连为同一实托。
|
||||
if (warehouseId.equals(position.getOverseasWarehouseId()) && position.getPalletId() != null
|
||||
&& position.getPalletId() > 0
|
||||
&& !visitedPallets.contains(position.getPalletId())) pending.add(position.getPalletId());
|
||||
}
|
||||
}
|
||||
|
||||
+3
-2
@@ -149,8 +149,9 @@ public class RelabelDispatchSourceService implements RelabelDispatchSourcePort {
|
||||
long notified = number(item.getNotifiedPackageCount());
|
||||
if (!Objects.equals(item.getCustomerId(), app.getCustomerId()) || position == null
|
||||
|| !Objects.equals(position.getCustomerId(), app.getCustomerId())
|
||||
|| !Objects.equals(warehouseId, position.getOverseasWarehouseId()) || position.getPalletId() == null) {
|
||||
reasons.add(app.getRelabelNo() + ":明细当前位置缺失或客户、仓库归属不一致");
|
||||
|| !Objects.equals(warehouseId, position.getOverseasWarehouseId()) || position.getPalletId() == null
|
||||
|| position.getPalletId() <= 0) {
|
||||
reasons.add(app.getRelabelNo() + ":明细当前位置缺失、实托身份无效或客户、仓库归属不一致");
|
||||
bound = false;
|
||||
}
|
||||
if (item.getReturnCartonId() != null || "RETURN_BULK_SKU_LABEL".equals(item.getOperationType())) {
|
||||
|
||||
@@ -41,12 +41,6 @@ CREATE TABLE IF NOT EXISTS ll_order_no_daily_sequence (
|
||||
PRIMARY KEY(business_date)
|
||||
) ENGINE=InnoDB COMMENT='尾程单号按日原子流水';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_dispatch_daily_sequence (
|
||||
business_date DATE NOT NULL COMMENT '排车编号业务日期(Asia/Shanghai)',
|
||||
last_sequence INT NOT NULL COMMENT '当日已分配排车流水号,范围0001至9999',
|
||||
PRIMARY KEY(business_date)
|
||||
) ENGINE=InnoDB COMMENT='排车单号每日独立原子流水';
|
||||
|
||||
CREATE TABLE IF NOT EXISTS ll_order (
|
||||
id BIGINT NOT NULL COMMENT '雪花 ID',
|
||||
order_no VARCHAR(32) NOT NULL COMMENT '尾程单号',
|
||||
@@ -4560,7 +4554,6 @@ CREATE TABLE IF NOT EXISTS ll_fleet_pickup_history (
|
||||
KEY idx_pickup_history_trip(trip_no,id)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='取货不可变操作历史';
|
||||
|
||||
-- 自有业务仅保存原排车的归属证据和附加运营信息,不复制履约主单。
|
||||
CREATE TABLE IF NOT EXISTS ll_fleet_owned_business_ownership (
|
||||
dispatch_id BIGINT NOT NULL COMMENT '原排车内部主键',
|
||||
resource_mode VARCHAR(16) NOT NULL COMMENT '原排车资源模式MASTER或EXTERNAL',
|
||||
|
||||
@@ -237,15 +237,6 @@ paths:
|
||||
-
|
||||
"$ref": "#/components/schemas/Photo"
|
||||
nullable: true
|
||||
parameters:
|
||||
-
|
||||
name: "idempotencyKey"
|
||||
in: "query"
|
||||
required: true
|
||||
schema:
|
||||
type: "string"
|
||||
minLength: 8
|
||||
maxLength: 128
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
@@ -254,7 +245,13 @@ paths:
|
||||
type: "object"
|
||||
required:
|
||||
- "file"
|
||||
- "idempotencyKey"
|
||||
properties:
|
||||
idempotencyKey:
|
||||
type: "string"
|
||||
minLength: 8
|
||||
maxLength: 128
|
||||
description: "原上传请求键,以multipart表单字段提交,绑定使用独立请求键。"
|
||||
file:
|
||||
type: "string"
|
||||
format: "binary"
|
||||
|
||||
Reference in New Issue
Block a user