feat: prepare warehouse 01 floor 1 inbound pilot
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package com.ruoyi.algorithm.pilot;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "fortucky.inbound-pilot")
|
||||
public class Layer1InboundPilotProperties {
|
||||
private boolean enabled;
|
||||
private String warehouseId = "01";
|
||||
private int floor = 1;
|
||||
private long planningTimeoutMillis = 1500L;
|
||||
private int snapshotMaxAgeSeconds = 60;
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public String getWarehouseId() {
|
||||
return warehouseId;
|
||||
}
|
||||
|
||||
public void setWarehouseId(String warehouseId) {
|
||||
this.warehouseId = warehouseId == null ? "" : warehouseId.trim();
|
||||
}
|
||||
|
||||
public int getFloor() {
|
||||
return floor;
|
||||
}
|
||||
|
||||
public void setFloor(int floor) {
|
||||
this.floor = floor;
|
||||
}
|
||||
|
||||
public long getPlanningTimeoutMillis() {
|
||||
return planningTimeoutMillis;
|
||||
}
|
||||
|
||||
public void setPlanningTimeoutMillis(long planningTimeoutMillis) {
|
||||
this.planningTimeoutMillis = planningTimeoutMillis;
|
||||
}
|
||||
|
||||
public int getSnapshotMaxAgeSeconds() {
|
||||
return snapshotMaxAgeSeconds;
|
||||
}
|
||||
|
||||
public void setSnapshotMaxAgeSeconds(int snapshotMaxAgeSeconds) {
|
||||
this.snapshotMaxAgeSeconds = snapshotMaxAgeSeconds;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package com.ruoyi.algorithm.pilot;
|
||||
|
||||
public record Layer1InboundPilotResult(Status status, String finalSpaceId, String fallbackReason) {
|
||||
public enum Status {
|
||||
NOT_ELIGIBLE,
|
||||
COMMITTED,
|
||||
FALLBACK,
|
||||
INDETERMINATE
|
||||
}
|
||||
|
||||
public static Layer1InboundPilotResult notEligible() {
|
||||
return new Layer1InboundPilotResult(Status.NOT_ELIGIBLE, null, null);
|
||||
}
|
||||
|
||||
public static Layer1InboundPilotResult committed(String finalSpaceId) {
|
||||
return new Layer1InboundPilotResult(Status.COMMITTED, finalSpaceId, null);
|
||||
}
|
||||
|
||||
public static Layer1InboundPilotResult fallback(String reason) {
|
||||
return new Layer1InboundPilotResult(Status.FALLBACK, null, reason);
|
||||
}
|
||||
|
||||
public static Layer1InboundPilotResult indeterminate(String reason) {
|
||||
return new Layer1InboundPilotResult(Status.INDETERMINATE, null, reason);
|
||||
}
|
||||
|
||||
public boolean committed() {
|
||||
return status == Status.COMMITTED;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
package com.ruoyi.algorithm.pilot;
|
||||
|
||||
import com.ruoyi.algorithm.shadow.InboundShadowObservation;
|
||||
import com.ruoyi.algorithm.shadow.PublishedShadowSnapshot;
|
||||
import com.ruoyi.algorithm.shadow.ShadowPlanningEngine;
|
||||
import com.ruoyi.algorithm.shadow.ShadowSnapshotDescriptor;
|
||||
import com.ruoyi.algorithm.shadow.mapper.ShadowInputMapper;
|
||||
import com.ruoyi.api.domain.RequestEnter;
|
||||
import com.ruoyi.job.mydojob.domain.MydoJob;
|
||||
import com.ruoyi.job.mydojob.mapper.MydoJobMapper;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
import java.time.Instant;
|
||||
import java.util.HashMap;
|
||||
import java.util.Objects;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
@Component
|
||||
public class Layer1InboundPilotService implements AutoCloseable {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Layer1InboundPilotService.class);
|
||||
private static final String PUBLISHED = "PUBLISHED";
|
||||
private static final String PILOT_WAREHOUSE_ID = "01";
|
||||
private static final int PILOT_FLOOR = 1;
|
||||
private static final int REASON_LIMIT = 3900;
|
||||
|
||||
private final Layer1InboundPilotProperties properties;
|
||||
private final ShadowInputMapper shadowInputMapper;
|
||||
private final ShadowPlanningEngine planningEngine;
|
||||
private final MydoJobMapper jobMapper;
|
||||
private final Clock clock;
|
||||
private final ExecutorService planningExecutor;
|
||||
|
||||
@Autowired
|
||||
public Layer1InboundPilotService(Layer1InboundPilotProperties properties,
|
||||
ShadowInputMapper shadowInputMapper, ShadowPlanningEngine planningEngine,
|
||||
MydoJobMapper jobMapper) {
|
||||
this(properties, shadowInputMapper, planningEngine, jobMapper, Clock.systemUTC(), newPlanningExecutor());
|
||||
}
|
||||
|
||||
Layer1InboundPilotService(Layer1InboundPilotProperties properties,
|
||||
ShadowInputMapper shadowInputMapper, ShadowPlanningEngine planningEngine,
|
||||
MydoJobMapper jobMapper, Clock clock, ExecutorService planningExecutor) {
|
||||
this.properties = Objects.requireNonNull(properties, "properties");
|
||||
this.shadowInputMapper = Objects.requireNonNull(shadowInputMapper, "shadowInputMapper");
|
||||
this.planningEngine = Objects.requireNonNull(planningEngine, "planningEngine");
|
||||
this.jobMapper = Objects.requireNonNull(jobMapper, "jobMapper");
|
||||
this.clock = Objects.requireNonNull(clock, "clock");
|
||||
this.planningExecutor = Objects.requireNonNull(planningExecutor, "planningExecutor");
|
||||
}
|
||||
|
||||
public Layer1InboundPilotResult attempt(RequestEnter request, MydoJob job) {
|
||||
if (!eligible(request, job)) {
|
||||
return Layer1InboundPilotResult.notEligible();
|
||||
}
|
||||
|
||||
long startedNanos = System.nanoTime();
|
||||
long generation = 0L;
|
||||
String proposedSpace = null;
|
||||
Layer1InboundPilotResult result;
|
||||
try {
|
||||
Proposal proposal = planWithTimeout(request, job);
|
||||
generation = proposal.generation();
|
||||
proposedSpace = proposal.proposedSpaceId();
|
||||
if (proposal.fallbackReason() != null) {
|
||||
result = Layer1InboundPilotResult.fallback(proposal.fallbackReason());
|
||||
} else {
|
||||
result = mutate(request, job, proposal);
|
||||
}
|
||||
} catch (InterruptedException interrupted) {
|
||||
Thread.currentThread().interrupt();
|
||||
result = Layer1InboundPilotResult.fallback("PLAN_INTERRUPTED");
|
||||
} catch (TimeoutException timeout) {
|
||||
result = Layer1InboundPilotResult.fallback("PLAN_TIMEOUT");
|
||||
} catch (RejectedExecutionException busy) {
|
||||
result = Layer1InboundPilotResult.fallback("PLAN_BUSY");
|
||||
} catch (ExecutionException planningFailure) {
|
||||
result = Layer1InboundPilotResult.fallback("PLAN_ERROR_" + simpleName(planningFailure.getCause()));
|
||||
} catch (RuntimeException | Error unexpected) {
|
||||
result = Layer1InboundPilotResult.fallback("PILOT_ERROR_" + simpleName(unexpected));
|
||||
}
|
||||
|
||||
audit(request, job, generation, proposedSpace, result, elapsedMillis(startedNanos));
|
||||
return result;
|
||||
}
|
||||
|
||||
private Proposal planWithTimeout(RequestEnter request, MydoJob job)
|
||||
throws InterruptedException, ExecutionException, TimeoutException {
|
||||
long timeout = properties.getPlanningTimeoutMillis();
|
||||
if (timeout < 1L || properties.getSnapshotMaxAgeSeconds() < 5
|
||||
|| properties.getSnapshotMaxAgeSeconds() > 300) {
|
||||
return Proposal.fallback("INVALID_PILOT_CONFIGURATION");
|
||||
}
|
||||
Future<Proposal> future = planningExecutor.submit(() -> plan(request, job));
|
||||
try {
|
||||
return future.get(timeout, TimeUnit.MILLISECONDS);
|
||||
} catch (TimeoutException timeoutException) {
|
||||
future.cancel(true);
|
||||
throw timeoutException;
|
||||
}
|
||||
}
|
||||
|
||||
private Proposal plan(RequestEnter request, MydoJob job) {
|
||||
String warehouseId = PILOT_WAREHOUSE_ID;
|
||||
ShadowSnapshotDescriptor descriptor = shadowInputMapper.selectPublishedSnapshot(warehouseId);
|
||||
String invalid = invalidSnapshot(descriptor, warehouseId);
|
||||
if (invalid != null) {
|
||||
return Proposal.fallback(invalid);
|
||||
}
|
||||
PublishedShadowSnapshot snapshot = new PublishedShadowSnapshot(
|
||||
descriptor.getSnapshotGeneration(), descriptor.getWarehouseId(),
|
||||
descriptor.getSynchronizedAt(), descriptor.getSourceSignature());
|
||||
InboundShadowObservation observation = planningEngine.planInbound(snapshot,
|
||||
request.getTaskNo(), job.getTrayCode(), PILOT_FLOOR);
|
||||
if (!observation.observed() || isBlank(observation.proposedSpaceId())
|
||||
|| !("READY".equals(observation.resultCode())
|
||||
|| "READY_CONSERVATIVE".equals(observation.resultCode()))) {
|
||||
return Proposal.fallback(observation.resultCode() == null
|
||||
? "PLAN_NOT_READY" : "PLAN_" + observation.resultCode());
|
||||
}
|
||||
return new Proposal(observation.snapshotGeneration(), observation.proposedSpaceId(),
|
||||
observation.reason(), null);
|
||||
}
|
||||
|
||||
private String invalidSnapshot(ShadowSnapshotDescriptor descriptor, String warehouseId) {
|
||||
if (descriptor == null || !PUBLISHED.equals(descriptor.getSnapshotStatus())
|
||||
|| descriptor.getSnapshotGeneration() <= 0L
|
||||
|| descriptor.getSynchronizedAt() == null || isBlank(descriptor.getSourceSignature())) {
|
||||
return "SNAPSHOT_NOT_READY";
|
||||
}
|
||||
if (!warehouseEquivalent(descriptor.getWarehouseId(), warehouseId)) {
|
||||
return "SNAPSHOT_WAREHOUSE_MISMATCH";
|
||||
}
|
||||
Duration age = Duration.between(descriptor.getSynchronizedAt(), clock.instant());
|
||||
if (age.isNegative()) {
|
||||
return "SNAPSHOT_TIME_INVALID";
|
||||
}
|
||||
if (age.compareTo(Duration.ofSeconds(properties.getSnapshotMaxAgeSeconds())) > 0) {
|
||||
return "SNAPSHOT_STALE";
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Layer1InboundPilotResult mutate(RequestEnter request, MydoJob job, Proposal proposal) {
|
||||
HashMap<String, Object> arguments = new HashMap<>();
|
||||
arguments.put("v_task_no", request.getTaskNo());
|
||||
arguments.put("v_tray_code", job.getTrayCode());
|
||||
arguments.put("v_code", request.getDeviceCode());
|
||||
arguments.put("v_space_id", proposal.proposedSpaceId());
|
||||
arguments.put("v_warehouse_id", PILOT_WAREHOUSE_ID);
|
||||
arguments.put("v_floor", PILOT_FLOOR);
|
||||
arguments.put("v_snapshot_generation", proposal.generation());
|
||||
arguments.put("v_snapshot_max_age_seconds", properties.getSnapshotMaxAgeSeconds());
|
||||
try {
|
||||
jobMapper.allocateLayer1InboundPilot(arguments);
|
||||
int code = intValue(arguments.get("v_result"), -1);
|
||||
String finalSpace = stringValue(arguments.get("v_final_space_id"));
|
||||
if ((code == 10 || code == 11 || code == 12) && !isBlank(finalSpace)) {
|
||||
return Layer1InboundPilotResult.committed(finalSpace);
|
||||
}
|
||||
return Layer1InboundPilotResult.fallback("MUTATION_" + code + "_"
|
||||
+ abbreviate(stringValue(arguments.get("v_resultmsg")), 160));
|
||||
} catch (RuntimeException | Error mutationFailure) {
|
||||
return resolveMutationFailure(request.getTaskNo(), mutationFailure);
|
||||
}
|
||||
}
|
||||
|
||||
private Layer1InboundPilotResult resolveMutationFailure(String taskNo, Throwable mutationFailure) {
|
||||
try {
|
||||
MydoJob current = jobMapper.selectInJobByTaskNo(taskNo);
|
||||
if (current != null && !isBlank(current.getCargoSpaceId())) {
|
||||
return Layer1InboundPilotResult.committed(current.getCargoSpaceId());
|
||||
}
|
||||
return Layer1InboundPilotResult.fallback("MUTATION_ROLLED_BACK_" + simpleName(mutationFailure));
|
||||
} catch (RuntimeException | Error stateReadFailure) {
|
||||
LOG.error("layer1_inbound_pilot_indeterminate task={} mutationError={} stateReadError={}",
|
||||
taskNo, simpleName(mutationFailure), simpleName(stateReadFailure));
|
||||
return Layer1InboundPilotResult.indeterminate("MUTATION_STATE_UNKNOWN");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean eligible(RequestEnter request, MydoJob job) {
|
||||
return properties.isEnabled() && request != null && job != null
|
||||
&& properties.getFloor() == PILOT_FLOOR
|
||||
&& warehouseEquivalent(properties.getWarehouseId(), PILOT_WAREHOUSE_ID)
|
||||
&& Integer.toString(PILOT_FLOOR).equals(trim(request.getFloor()))
|
||||
&& warehouseEquivalent(job.getWarehouseId(), PILOT_WAREHOUSE_ID)
|
||||
&& !isBlank(request.getTaskNo()) && !isBlank(job.getTrayCode())
|
||||
&& job.getCargoSpaceId() == null;
|
||||
}
|
||||
|
||||
private void audit(RequestEnter request, MydoJob job, long generation, String proposedSpace,
|
||||
Layer1InboundPilotResult result, long elapsedMillis) {
|
||||
String reason = "task=" + safe(request.getTaskNo())
|
||||
+ "; tray=" + safe(job.getTrayCode())
|
||||
+ "; proposedSpace=" + safe(proposedSpace)
|
||||
+ "; finalSpace=" + safe(result.finalSpaceId())
|
||||
+ "; elapsedMs=" + elapsedMillis
|
||||
+ "; outcome=" + result.status()
|
||||
+ "; fallbackReason=" + safe(result.fallbackReason());
|
||||
try {
|
||||
shadowInputMapper.insertPilotAudit(UUID.randomUUID().toString(), PILOT_WAREHOUSE_ID,
|
||||
generation, result.status().name(), abbreviate(reason, REASON_LIMIT));
|
||||
} catch (RuntimeException | Error auditFailure) {
|
||||
LOG.warn("layer1_inbound_pilot_audit_failed task={} error={}",
|
||||
request.getTaskNo(), simpleName(auditFailure));
|
||||
}
|
||||
}
|
||||
|
||||
@PreDestroy
|
||||
@Override
|
||||
public void close() {
|
||||
planningExecutor.shutdownNow();
|
||||
}
|
||||
|
||||
private static ExecutorService newPlanningExecutor() {
|
||||
return new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS,
|
||||
new ArrayBlockingQueue<>(1), runnable -> {
|
||||
Thread thread = new Thread(runnable, "layer1-inbound-pilot-planner");
|
||||
thread.setDaemon(true);
|
||||
return thread;
|
||||
}, new ThreadPoolExecutor.AbortPolicy());
|
||||
}
|
||||
|
||||
private static boolean warehouseEquivalent(String left, String right) {
|
||||
String normalizedLeft = normalizeWarehouse(left);
|
||||
String normalizedRight = normalizeWarehouse(right);
|
||||
return normalizedLeft != null && normalizedLeft.equals(normalizedRight);
|
||||
}
|
||||
|
||||
private static String normalizeWarehouse(String value) {
|
||||
String trimmed = trim(value);
|
||||
if (trimmed == null || trimmed.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (trimmed.chars().allMatch(Character::isDigit)) {
|
||||
String normalized = trimmed.replaceFirst("^0+(?!$)", "");
|
||||
return normalized.isEmpty() ? "0" : normalized;
|
||||
}
|
||||
return trimmed;
|
||||
}
|
||||
|
||||
private static int intValue(Object value, int fallback) {
|
||||
if (value instanceof Number number) {
|
||||
return number.intValue();
|
||||
}
|
||||
try {
|
||||
return Integer.parseInt(Objects.toString(value, ""));
|
||||
} catch (NumberFormatException ignored) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
private static String stringValue(Object value) {
|
||||
return value == null ? null : value.toString();
|
||||
}
|
||||
|
||||
private static String simpleName(Throwable failure) {
|
||||
return failure == null ? "UNKNOWN" : failure.getClass().getSimpleName();
|
||||
}
|
||||
|
||||
private static long elapsedMillis(long startedNanos) {
|
||||
return TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startedNanos);
|
||||
}
|
||||
|
||||
private static String safe(String value) {
|
||||
return value == null ? "" : abbreviate(value.replace(';', '_'), 255);
|
||||
}
|
||||
|
||||
private static String abbreviate(String value, int limit) {
|
||||
if (value == null || value.length() <= limit) {
|
||||
return value;
|
||||
}
|
||||
return value.substring(0, limit);
|
||||
}
|
||||
|
||||
private static String trim(String value) {
|
||||
return value == null ? null : value.trim();
|
||||
}
|
||||
|
||||
private static boolean isBlank(String value) {
|
||||
return value == null || value.isBlank();
|
||||
}
|
||||
|
||||
private record Proposal(long generation, String proposedSpaceId, String reason, String fallbackReason) {
|
||||
private static Proposal fallback(String reason) {
|
||||
return new Proposal(0L, null, null, reason);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,16 @@ public class ShadowPlanningEngine {
|
||||
public InboundShadowObservation planInbound(PublishedShadowSnapshot snapshot,
|
||||
String taskNo, String trayNo) {
|
||||
return planWithStableSnapshot(snapshot,
|
||||
() -> planInboundInsideTransaction(snapshot, taskNo, trayNo));
|
||||
() -> planInboundInsideTransaction(snapshot, taskNo, trayNo, null));
|
||||
}
|
||||
|
||||
public InboundShadowObservation planInbound(PublishedShadowSnapshot snapshot,
|
||||
String taskNo, String trayNo, Integer targetFloor) {
|
||||
if (targetFloor == null || targetFloor <= 0) {
|
||||
throw new IllegalArgumentException("targetFloor must be positive");
|
||||
}
|
||||
return planWithStableSnapshot(snapshot,
|
||||
() -> planInboundInsideTransaction(snapshot, taskNo, trayNo, targetFloor));
|
||||
}
|
||||
|
||||
public OutboundShadowObservation planProjectOutbound(PublishedShadowSnapshot snapshot,
|
||||
@@ -245,7 +254,7 @@ public class ShadowPlanningEngine {
|
||||
}
|
||||
|
||||
private InboundShadowObservation planInboundInsideTransaction(PublishedShadowSnapshot snapshot,
|
||||
String taskNo, String trayNo) {
|
||||
String taskNo, String trayNo, Integer targetFloor) {
|
||||
String warehouseId = snapshot.warehouseId();
|
||||
ShadowInboundReference reference = inputMapper.selectInboundInput(
|
||||
warehouseId, snapshot.generation(), taskNo, trayNo);
|
||||
@@ -294,7 +303,7 @@ public class ShadowPlanningEngine {
|
||||
InboundRequest request = new InboundRequest(reference.getRequestId(), reference.getTrayNo(),
|
||||
reference.getProjectNo(), multipleProducts ? null : reference.getProductId(),
|
||||
multipleProducts ? null : reference.getLotNo(),
|
||||
null, null, null, Set.of(), null, Set.copyOf(eligibleSpaces));
|
||||
null, null, targetFloor, Set.of(), null, Set.copyOf(eligibleSpaces));
|
||||
InboundPlanningResult result = schedulingFacade.planInboundFromPublishedSnapshot(warehouseId, request);
|
||||
InboundPlan plan = result.plan();
|
||||
if (plan.assignment().isPresent()) {
|
||||
|
||||
@@ -50,6 +50,12 @@ public interface ShadowInputMapper {
|
||||
@Param("resultCode") String resultCode,
|
||||
@Param("reason") String reason);
|
||||
|
||||
int insertPilotAudit(@Param("decisionId") String decisionId,
|
||||
@Param("warehouseId") String warehouseId,
|
||||
@Param("inputVersion") long inputVersion,
|
||||
@Param("resultCode") String resultCode,
|
||||
@Param("reason") String reason);
|
||||
|
||||
void upsertRuntimeMetric(@Param("warehouseId") String warehouseId,
|
||||
@Param("metricName") String metricName,
|
||||
@Param("bucketUpperMicros") long bucketUpperMicros,
|
||||
|
||||
@@ -8,6 +8,8 @@ import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.ruoyi.algorithm.shadow.InboundShadowCompletion;
|
||||
import com.ruoyi.algorithm.shadow.ShadowObservationGateway;
|
||||
import com.ruoyi.algorithm.pilot.Layer1InboundPilotResult;
|
||||
import com.ruoyi.algorithm.pilot.Layer1InboundPilotService;
|
||||
import com.ruoyi.api.domain.*;
|
||||
import com.ruoyi.api.service.IToErpService;
|
||||
import com.ruoyi.api.service.IToWmsService;
|
||||
@@ -94,6 +96,8 @@ public class ToWmsServiceImpl implements IToWmsService {
|
||||
private MydoJobMapper mydoJobMapper;
|
||||
@Autowired
|
||||
private ShadowObservationGateway shadowObservationGateway;
|
||||
@Autowired
|
||||
private Layer1InboundPilotService layer1InboundPilotService;
|
||||
|
||||
|
||||
@Override
|
||||
@@ -411,6 +415,22 @@ public class ToWmsServiceImpl implements IToWmsService {
|
||||
if(inJob.getCargoSpaceId() != null && !"".equals(inJob.getCargoSpaceId())){
|
||||
return AjaxResult.success(inJob);
|
||||
}else{
|
||||
Layer1InboundPilotResult pilotResult;
|
||||
try {
|
||||
pilotResult = layer1InboundPilotService.attempt(requestEnter, inJob);
|
||||
} catch (RuntimeException | Error pilotFailure) {
|
||||
pilotResult = Layer1InboundPilotResult.fallback("PILOT_BOUNDARY_FAILURE");
|
||||
}
|
||||
if (pilotResult.committed()) {
|
||||
MydoJob pilotJob = mydoJobMapper.selectInJobByTaskNo(taskNo);
|
||||
if (pilotJob == null) {
|
||||
return AjaxResult.error("一层入库试点已提交但任务重读失败,请重新扫码确认任务货位");
|
||||
}
|
||||
return AjaxResult.success(pilotJob);
|
||||
}
|
||||
if (pilotResult.status() == Layer1InboundPilotResult.Status.INDETERMINATE) {
|
||||
return AjaxResult.error("一层入库试点写入状态待确认,请重新扫码确认任务货位");
|
||||
}
|
||||
//分配货位
|
||||
HashMap<String, Object> map = new HashMap<>();
|
||||
|
||||
|
||||
@@ -88,6 +88,8 @@ public interface MydoJobMapper
|
||||
|
||||
void allotInJobSpace(HashMap<String, Object> map);
|
||||
|
||||
void allocateLayer1InboundPilot(HashMap<String, Object> map);
|
||||
|
||||
void ykCompleted(HashMap<String, Object> map);
|
||||
|
||||
void updateLed(HashMap<String, Object> map);
|
||||
|
||||
@@ -197,3 +197,9 @@ fortucky:
|
||||
warehouse-id: ${FORTUCKY_ALGORITHM_WAREHOUSE_ID:01}
|
||||
database-writes-enabled: ${FORTUCKY_ALGORITHM_DATABASE_WRITES_ENABLED:true}
|
||||
legacy-fallback-on-technical-error: ${FORTUCKY_ALGORITHM_LEGACY_FALLBACK_ON_TECHNICAL_ERROR:false}
|
||||
inbound-pilot:
|
||||
enabled: ${FORTUCKY_INBOUND_PILOT_ENABLED:false}
|
||||
warehouse-id: ${FORTUCKY_INBOUND_PILOT_WAREHOUSE_ID:01}
|
||||
floor: ${FORTUCKY_INBOUND_PILOT_FLOOR:1}
|
||||
planning-timeout-millis: ${FORTUCKY_INBOUND_PILOT_PLANNING_TIMEOUT_MILLIS:1500}
|
||||
snapshot-max-age-seconds: ${FORTUCKY_INBOUND_PILOT_SNAPSHOT_MAX_AGE_SECONDS:60}
|
||||
|
||||
@@ -232,6 +232,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
and convert(varchar(64), state.source_signature, 2) = #{sourceSignature}
|
||||
</insert>
|
||||
|
||||
<insert id="insertPilotAudit">
|
||||
insert into alg.decision_log (
|
||||
decision_id, warehouse_id, decision_type, input_version, result_code, reason)
|
||||
values (try_convert(uniqueidentifier, #{decisionId}), #{warehouseId}, 'INBOUND_PILOT',
|
||||
convert(binary(8), #{inputVersion}), #{resultCode}, #{reason})
|
||||
</insert>
|
||||
|
||||
<update id="upsertRuntimeMetric">
|
||||
merge alg.shadow_runtime_metric with (holdlock) as target
|
||||
using (select #{warehouseId} as warehouse_id,
|
||||
|
||||
@@ -308,6 +308,22 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
)}
|
||||
</select>
|
||||
|
||||
<select id="allocateLayer1InboundPilot" parameterType="java.util.Map" statementType="CALLABLE" timeout="3">
|
||||
{call proc_allot_layer1_inbound_pilot(
|
||||
#{v_task_no,jdbcType=VARCHAR,mode=IN},
|
||||
#{v_tray_code,jdbcType=VARCHAR,mode=IN},
|
||||
#{v_code,jdbcType=VARCHAR,mode=IN},
|
||||
#{v_space_id,jdbcType=VARCHAR,mode=IN},
|
||||
#{v_warehouse_id,jdbcType=VARCHAR,mode=IN},
|
||||
#{v_floor,jdbcType=INTEGER,mode=IN},
|
||||
#{v_snapshot_generation,jdbcType=BIGINT,mode=IN},
|
||||
#{v_snapshot_max_age_seconds,jdbcType=INTEGER,mode=IN},
|
||||
#{v_result,mode=OUT,jdbcType=INTEGER},
|
||||
#{v_resultmsg,mode=OUT,jdbcType=VARCHAR},
|
||||
#{v_final_space_id,mode=OUT,jdbcType=VARCHAR}
|
||||
)}
|
||||
</select>
|
||||
|
||||
<select id="updateLed" parameterType="java.util.Map" statementType="CALLABLE">
|
||||
{call proc_update_led(
|
||||
#{v_code,jdbcType=VARCHAR,mode=IN},
|
||||
|
||||
Reference in New Issue
Block a user